Permalink
Browse files

Remove performance counters

Not very useful, and a big headache for linking.
  • Loading branch information...
1 parent 6cab829 commit d530a3dd77ddab680b42e9ca1e6cf60390f5db7a @kerneis kerneis committed Nov 4, 2011
Showing with 9 additions and 377 deletions.
  1. +3 −10 Makefile.in
  2. +0 −34 configure.in
  3. +0 −6 myocamlbuild.ml
  4. +0 −255 ocamlutil/perfcount.c.in
  5. +4 −53 ocamlutil/stats.ml
  6. +1 −18 ocamlutil/stats.mli
  7. +1 −1 src/main.ml
View
13 Makefile.in
@@ -34,9 +34,6 @@ config.status: configure
configure: configure.in aclocal.m4
autoconf
-ocamlutil/perfcount.c: config.status ocamlutil/perfcount.c.in
- ./$<
-
@DEFAULT_COMPILER@=1
@@ -108,7 +105,7 @@ CILLY_LIBRARY_MODULES = pretty inthash errormsg alpha trace stats util clist \
# otherwise every program that links against that library will get
# main's argument checking and whatnot ...
CILLY_MODULES = $(CILLY_LIBRARY_MODULES) main
-CILLY_CMODULES = perfcount
+CILLY_CMODULES =
CILLY_LIBS = unix str nums
SOURCEDIRS += src src/frontc src/ext src/ext/pta ocamlutil @EXTRASRCDIRS@
@@ -283,7 +280,7 @@ endif
OCAML_CIL_LIB_MODULES := $(CILLY_LIBRARY_MODULES)
-OCAML_CIL_LIB_CMODULES := perfcount
+OCAML_CIL_LIB_CMODULES :=
# list of modules to use for building a library; remove 'main'
# and add 'libmaincil'
@@ -296,9 +293,6 @@ $(OBJDIR)/cil.$(CMXA): $(OCAML_CIL_LIB_CMODULES:%=$(OBJDIR)/lib%.a) \
$(OCAML_CIL_LIB_CMODULES:%=-cclib -l%) \
$(OCAML_CIL_LIB_MODULES:%=$(OBJDIR)/%.$(CMO))
-$(OBJDIR)/libperfcount.a: %: %($(OBJDIR)/perfcount.$(CMC))
- ranlib $@
-
# sm: for Simon: build a library of CIL functions which can
# be called from C code; this is like the target above, except
# it is callable from C instead of from Ocaml
@@ -438,7 +432,7 @@ DISTRIB_OCAMLUTIL = pretty.ml pretty.mli errormsg.ml errormsg.mli \
longarray.ml longarray.mli \
growArray.ml growArray.mli \
bitmap.ml bitmap.mli \
- perfcount.c.in Makefile.ocaml \
+ Makefile.ocaml \
_tags
@@ -537,7 +531,6 @@ checkdistrib:
distclean: clean
rm -f src/frontc/cparser.output
rm -f src/formatparse.output
- rm -f ocamlutil/perfcount.c
rm -f bin/cilly.bat
rm -f bin/patcher.bat
rm -f bin/CilConfig.pm
View
34 configure.in
@@ -291,38 +291,6 @@ EOF
fi
fi
-#
-# Now setup the performance counters
-#
-# At runtime, we'll try to get the cycle speed from /proc/cpuinfo
-# or FreeBSD sysctl. This means binaries can be moved to different computers.
-# CYCLES_PER_USEC is only a backup in case these aren't available.
-# (See the subversion history for the old code that read /proc/cpuinfo here.)
-AC_MSG_CHECKING(if performance counters are usable)
-# Create a C file from src/perfcount.c.in
-rm -f ./cycles.exe
-if gcc -DCONFIGURATION_ONLY \
- -x c ocamlutil/perfcount.c.in -lm -o ./cycles.exe >/dev/null 2>&1; then
-
- if CYCLES_PER_USEC=`./cycles.exe 2>&1` ;then
- AC_MSG_RESULT([ok ($CYCLES_PER_USEC cycles per us)])
- else
- # Print what we got
- AC_MSG_RESULT([no ($CYCLES_PER_USEC)])
- CYCLES_PER_USEC=0
- fi
-else
- CYCLES_PER_USEC=0
- AC_MSG_RESULT([no (cannot compile perfcount.c)])
-fi
-rm -f ./cycles.exe
-
-if test "$CYCLES_PER_USEC" != "0" ;then
- HAS_PERFCOUNT=1
-else
- HAS_PERFCOUNT=0
-fi
-
# additional tools we might check for:
# - gnu make
@@ -581,7 +549,6 @@ AC_SUBST(CIL_VERSION_MINOR)
AC_SUBST(CIL_VERSION_REV)
AC_SUBST(CIL_VERSION)
AC_SUBST(CYCLES_PER_USEC)
-AC_SUBST(HAS_PERFCOUNT)
AC_SUBST(HAVE_BUILTIN_VA_LIST)
AC_SUBST(THREAD_IS_KEYWORD)
AC_SUBST(UNDERSCORE_NAME)
@@ -601,7 +568,6 @@ CIL_CONFIG_EXE_FILES(bin/patcher.bat)
CIL_CONFIG_FILES(bin/CilConfig.pm)
CIL_CONFIG_FILES(doc/index.html)
CIL_CONFIG_FILES(doc/header.html)
-CIL_CONFIG_FILES(ocamlutil/perfcount.c)
CIL_CONFIG_FILES(test/llvm/Makefile)
CIL_CONFIG_FILES(src/machdep-ml.c)
View
6 myocamlbuild.ml
@@ -11,12 +11,6 @@ dispatch begin
(* the main CIL library *)
ocaml_lib "src/cil";
- (* performance counter external functions *)
- let perfcount = "ocamlutil/perfcount.o" in
- flag ["use_perfcount"] (S [P perfcount]);
- dep ["use_perfcount"] [perfcount];
- flag ["optimize"] (S [A "-ccopt"; A "-O3"]);
-
(* residual reliance on make to build some OCaml source files *)
let make target =
let basename = Pathname.basename target in
View
255 ocamlutil/perfcount.c.in
@@ -1,255 +0,0 @@
-// -*- Mode: c -*-
-//
-/*
- * A module that allows the reading of performance counters on Pentium.
- *
- * This file contains both code that uses the performance counters to
- * compute the number of cycles per second (to be used during ./configure)
- * and also code to read the performance counters from Ocaml.
- *
- * Author: George Necula (necula@cs.berkeley.edu)
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#if defined(__GNUC__)
- #define longlong long long
- // RDTSC puts the result in EAX and EDX. We tell gcc to use those registers
- // for "low" and "high"
- #if defined(__i386__) || defined(__x86_64__)
- #define GETCOUNTER(low,high) \
- __asm__ volatile ("rdtsc" : "=a" (low), "=d" (high));
- #else
- #define GETCOUNTER(low,high) \
- printf ("Reading of performance counters is supported only on Intel x86\n"); \
- exit(1);
- #endif
-#else
- // Microsoft Visual Studio
- #define longlong __int64
- #define inline __inline
- #define GETCOUNTER(low,high) __asm { \
- __asm rdtsc \
- __asm mov low, eax \
- __asm mov high, edx };
-#endif
-
-/* Store here the first value read from the performance counter */
-unsigned static longlong first_value;
-
-
-/* This is the function that actually reads the performance counter. */
-inline unsigned longlong read_ppc(void) {
- unsigned long pclow, pchigh;
- unsigned longlong lowhigh;
-
- GETCOUNTER(pclow, pchigh);
-
- // printf ("Read low=0x%08lx high=0x%08lx\n", low, high);
-
- // Put the 64-bit value together
- lowhigh = ((unsigned longlong)pclow) | ((unsigned longlong)pchigh << 32);
-
- if(first_value == 0) {
- first_value = lowhigh;
- }
- return lowhigh - first_value;
-}
-
-
-/* sm: I want a version that is as fast as possible, dropping
- * bits that aren't very important to achieve it. *
- *
- * This version drops the low 20 bits and the high 14 bits so the
- * result is 30 bits (always a positive Ocaml int); this yields
- * megacycles, which for GHz machines will be something like
- * milliseconds. */
-static unsigned long sample_ppc_20(void)
-{
- unsigned long pclow, pchigh;
-
- GETCOUNTER(pclow, pchigh);
-
- return ((pclow >> 20) | (pchigh << 12)) & 0x3FFFFFFF;
-}
-
-/* This version drops the low 10 bits, yielding something like
- * microseconds. */
-inline static unsigned long sample_ppc_10()
-{
- unsigned long pclow, pchigh;
-
- GETCOUNTER(pclow,pchigh);
-
- return ((pclow >> 10) | (pchigh << 22)) & 0x3FFFFFFF;
-}
-
-
-
-#ifndef CONFIGURATION_ONLY
-/*** This is the OCAML stub for the read_ppc ***/
-#include <caml/mlvalues.h>
-#include <caml/alloc.h>
-#include <caml/memory.h>
-
-// At configuration time, we estimated the cycles per microsecond as
-// @CYCLES_PER_USEC@. But if we can get the cycle counts directly from the OS,
-// do that instead, since it's more reliable and it lets us move programs
-// to different machines without recompiling.
-double cycles_per_usec = @CYCLES_PER_USEC@;
-
-#if defined(__FreeBSD__)
-#define CAN_GET_SPEED_FROM_OS
-
- // Get the CPU speed from the sysctl machdep.tsc_freq
- // This only works on FreeBSD
-
- #include <sys/types.h>
- #include <sys/param.h>
- #include <sys/sysctl.h>
-
- double getSpeedFromOS() {
- unsigned long tscfreq;
- size_t tflen = sizeof(tscfreq);
-
- if (sysctlbyname("machdep.tsc_freq", (void *) &tscfreq,
- &tflen, NULL, 0) < 0) {
- perror("sysctl failed");
- return @CYCLES_PER_USEC@;
- }
- return (double)tscfreq / 1000000; // We care about cycles per microsecond
- }
-#elif defined(__CYGWIN__) || defined(__linux__)
-#define CAN_GET_SPEED_FROM_OS
-
- // Get the CPU speed from /proc/cpuinfo
-
- #define CPUINFO_KEY "cpu MHz"
- #include <errno.h>
-
- double getSpeedFromOS(){
- char buffer[100];
- FILE* cpuinfo = fopen("/proc/cpuinfo", "r");
- if (!cpuinfo) {
- printf("Error: could not open /proc/cpuinfo: %s", strerror(errno));
- exit(1);
- }
- while(fgets(buffer, 100, cpuinfo)) {
- if (0 == strncasecmp(buffer, CPUINFO_KEY, sizeof(CPUINFO_KEY)-1)) {
- char* speed = buffer + sizeof(CPUINFO_KEY)-1;
- double result;
- while (*speed == ' ' || *speed == '\t' || *speed == ':') {
- speed++;
- }
- result = atof(speed);
- if (result != 0.0) {
- return result;
- }
- }
- }
- // Reading /proc/cpuinfo failed to find "cpu MHz"
- return @CYCLES_PER_USEC@;
- }
-#endif
-
-
-/* Returns false if hardware counters are not availible. */
-value has_performance_counters() {
-
- // HAS_PERFCOUNT is set by the configuration code at the end of
- // this file, during ./configure
- if ((@HAS_PERFCOUNT@) && (cycles_per_usec > 0.0)) {
- return Val_true;
- } else {
- return Val_false;
- }
-}
-
-/* The Ocaml system can use this function to set cycles_per_usec.
- Returns false if hardware counters are not availible. */
-value reset_performance_counters() {
-
-#ifdef CAN_GET_SPEED_FROM_OS
- cycles_per_usec = getSpeedFromOS();
-#endif
-
- return has_performance_counters();
-}
-
-value read_pentium_perfcount()
-{
- double counter = (double)read_ppc() / (1000000.0 * cycles_per_usec);
- return copy_double(counter);
-}
-
-/* sm: interface to above from Ocaml */
-value sample_pentium_perfcount_20()
-{
- return Val_long(sample_ppc_20());
-}
-
-value sample_pentium_perfcount_10()
-{
- return Val_long(sample_ppc_10());
-}
-
-#endif
-
-
-/* Now we have a function that tries to compute the number of cycles per
- * second (to be used during ./configure) */
-#ifdef CONFIGURATION_ONLY
-#include <sys/times.h>
-#include <unistd.h>
-#include <math.h>
-
-int main() {
- struct tms t;
- clock_t start, finish, diff;
- unsigned longlong start_pc, finish_pc, diff_pc;
- long clk_per_sec = sysconf(_SC_CLK_TCK);
- double cycles_per_usec;
-
- if(clk_per_sec <= 0) {
- printf("Cannot find clk_per_sec (got %ld)\n", clk_per_sec);
- exit(1);
- }
-
- times(&t); start = t.tms_utime;
- start_pc = read_ppc();
- // Do something for a while
- {
- int i;
- double a = 5.678;
- for(i=0;i<10000000;i++) {
- a = (i & 1) ? (a * a) : (sqrt(a));
- }
- }
- times(&t); finish = t.tms_utime;
- finish_pc = read_ppc();
- diff = finish - start;
- diff_pc = finish_pc - start_pc;
- if(diff == 0) {
- printf("Cannot use Unix.times\n");
- exit(1);
- }
- if(diff_pc == 0) {
- printf("Invalid result from the peformance counters\n");
- exit(1);
- }
- diff_pc /= 1000000; // We care about cycles per microsecond
-// printf("diff = %ld, diff_pc = %ld, clk = %ld\n",
-// (long)diff,
-// (long)diff_pc, (long)clk_per_sec);
-
- cycles_per_usec = (((double)diff_pc / (double)diff)
- * (double)clk_per_sec);
-
- /* Whatever value we print here will be used as the CYCLES_PER_USEC
- * below */
- printf("%.3lf\n", cycles_per_usec);
- exit(0);
-}
-#endif //defined CONFIGURATION_ONLY
-
View
57 ocamlutil/stats.ml
@@ -1,33 +1,8 @@
-(* The following functions are implemented in perfcount.c *)
-
-(* Returns true if we have the performance counters *)
-external has_performance_counters: unit -> bool = "has_performance_counters"
-
-(* Initializes the CPU speed and returns true if we have
- the performance counters *)
-external reset_performance_counters: unit -> bool = "reset_performance_counters"
-
-(* Returns number of seconds since the first read *)
-external read_pentium_perfcount : unit -> float = "read_pentium_perfcount"
-
-(* Returns current cycle counter, divided by 1^20, and truncated to 30 bits *)
-external sample_pentium_perfcount_20 : unit -> int = "sample_pentium_perfcount_20"
-
-(* Returns current cycle counter, divided by 1^10, and truncated to 30 bits *)
-external sample_pentium_perfcount_10 : unit -> int = "sample_pentium_perfcount_10"
-
-
(** Whether to use the performance counters (on Pentium only) *)
type timerModeEnum =
| Disabled (** Do not collect timing information *)
| SoftwareTimer (** Use OCaml's [Unix.time] for timing information *)
- | HardwareTimer (** Use the Pentium's cycle counter to time code *)
- | HardwareIfAvail (** Use the hardware cycle counter if availible;
- otherwise use SoftwareTimer *)
-(* The performance counters are disabled by default.
- This will always be one of Disabled | SoftwareTimer | HardwareTimer.
- HardwareIfAvail is handled in reset. *)
let timerMode = ref Disabled
(* Flag for counting number of calls *)
@@ -54,35 +29,16 @@ let current : t list ref = ref [top]
exception NoPerfCount
let reset (mode: timerModeEnum) : unit =
top.sub <- [];
- match mode with
- Disabled
- | SoftwareTimer -> timerMode := mode
- | HardwareTimer ->
- if not (reset_performance_counters ()) then begin
- timerMode := SoftwareTimer;
- raise NoPerfCount
- end;
- timerMode := mode
- | HardwareIfAvail ->
- if (reset_performance_counters ()) then
- timerMode := HardwareTimer
- else
- timerMode := SoftwareTimer
+ timerMode := mode
let print chn msg =
(* Total up *)
top.time <- List.fold_left (fun sum f -> sum +. f.time) 0.0 top.sub;
let rec prTree ind node =
- begin
- if !timerMode = HardwareTimer then
- (Printf.fprintf chn "%s%-25s %8.5f s"
- (String.make ind ' ') node.name node.time)
- else
(Printf.fprintf chn "%s%-25s %6.3f s"
- (String.make ind ' ') node.name node.time)
- end;
+ (String.make ind ' ') node.name node.time);
begin
if node.ncalls <= 0 then
output_string chn "\n"
@@ -95,9 +51,7 @@ let print chn msg =
in
Printf.fprintf chn "%s" msg;
List.iter (prTree 0) [ top ];
- Printf.fprintf chn "Timing used %s\n"
- (if !timerMode = HardwareTimer then "Pentium performance counters"
- else "Unix.time");
+ Printf.fprintf chn "Timing used\n";
let gc = Gc.quick_stat () in
let printM (w: float) : string =
let coeff = float_of_int (Sys.word_size / 8) in
@@ -121,10 +75,7 @@ let print chn msg =
(* Get the current time, in seconds *)
let get_current_time () : float =
- if !timerMode = HardwareTimer then
- read_pentium_perfcount ()
- else
- (Unix.times ()).Unix.tms_utime
+ (Unix.times ()).Unix.tms_utime
let repeattime limit str f arg =
(* Find the right stat *)
View
19 ocamlutil/stats.mli
@@ -32,36 +32,19 @@
(** Utilities for maintaining timing statistics *)
-(** Whether to use the performance counters (on Pentium only) *)
type timerModeEnum =
| Disabled (** Do not collect timing information *)
| SoftwareTimer (** Use OCaml's [Unix.time] for timing information *)
- | HardwareTimer (** Use the Pentium's cycle counter to time code *)
- | HardwareIfAvail (** Use the hardware cycle counter if availible;
- otherwise use SoftwareTimer *)
(** Resets all the timings and specifies the method to use for future timings.
- * Call this before doing any timing.
-
- * You will get an exception if you pass HardwareTimer to reset and the
- * hardware counters are not available *)
+ * Call this before doing any timing. *)
val reset: timerModeEnum -> unit
-exception NoPerfCount
(** Flag to indicate whether or not to count the number of calls of
to {!Stats.repeattime} or {!Stats.time} for each label.
(default: false) *)
val countCalls: bool ref
-(** Check if we have performance counters *)
-val has_performance_counters: unit -> bool
-
-(** Sample the current cycle count, in megacycles. *)
-val sample_pentium_perfcount_20: unit -> int
-
-(** Sample the current cycle count, in kilocycles. *)
-val sample_pentium_perfcount_10: unit -> int
-
(** Time a function and associate the time with the given string. If some
timing information is already associated with that string, then accumulate
the times. If this function is invoked within another timed function then
View
2 src/main.ml
@@ -211,7 +211,7 @@ let theMain () =
begin
(* this point in the code is the program entry point *)
- Stats.reset Stats.HardwareIfAvail;
+ Stats.reset Stats.SoftwareTimer;
(* parse the command-line arguments *)
Arg.parse (Arg.align argDescr) Ciloptions.recordFile usageMsg;

0 comments on commit d530a3d

Please sign in to comment.