1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
|
/* Copyright (C) 2005-2013 Shugo Maeda <shugo@ruby-lang.org> and Charlie Savage <cfis@savagexi.com>
Please see the LICENSE file for copyright and distribution information */
#include "ruby_prof.h"
static VALUE cMeasureCpuTime;
/* The _WIN32 check is needed for msys (and maybe cygwin?) */
#if defined(_WIN32)
static unsigned long long get_cpu_time()
{
LARGE_INTEGER time;
QueryPerformanceCounter(&time);
return time.QuadPart;
}
static unsigned long long get_cpu_frequency()
{
static unsigned long long cpu_frequency;
if(!cpu_frequency) {
LARGE_INTEGER cpu_frequency_struct;
QueryPerformanceFrequency(&cpu_frequency_struct);
cpu_frequency = cpu_frequency_struct.QuadPart;
}
return cpu_frequency;
}
static double measure_cpu_time()
{
return ((double)get_cpu_time()) / get_cpu_frequency();
}
#else
#include <sys/resource.h>
#include <stdint.h>
#include <time.h>
static unsigned long long get_cpu_time()
{
#if defined(__i386__) || defined(__x86_64__)
uint32_t a, d;
__asm__ volatile("rdtsc" : "=a" (a), "=d" (d));
return ((uint64_t)d << 32) + a;
#elif defined(__powerpc__) || defined(__ppc__)
unsigned long long x, y;
__asm__ __volatile__ ("\n\
1: mftbu %1\n\
mftb %L0\n\
mftbu %0\n\
cmpw %0,%1\n\
bne- 1b"
: "=r" (x), "=r" (y));
return x;
#endif
}
static unsigned long long get_cpu_frequency()
{
static unsigned long long cpu_frequency;
if(!cpu_frequency) {
unsigned long long x, y;
struct timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = 500000000;
x = get_cpu_time();
nanosleep(&ts, NULL);
y = get_cpu_time();
cpu_frequency = (y - x) * 2;
}
return cpu_frequency;
}
static double measure_cpu_time()
{
struct rusage rusage;
getrusage(RUSAGE_SELF, &rusage);
double seconds = 0;
seconds += rusage.ru_utime.tv_sec;
seconds += rusage.ru_stime.tv_sec;
seconds += rusage.ru_utime.tv_usec / 1000000.0;
seconds += rusage.ru_stime.tv_usec / 1000000.0;
return seconds;
}
#endif
prof_measurer_t* prof_measurer_cpu_time()
{
prof_measurer_t* measure = ALLOC(prof_measurer_t);
measure->measure = measure_cpu_time;
return measure;
}
/* call-seq:
measure -> float
Returns the cpu time.*/
static VALUE
prof_measure_cpu_time(VALUE self)
{
return rb_float_new(measure_cpu_time());
}
/* call-seq:
cpu_frequency -> int
Returns the cpu's frequency. This value is needed when
RubyProf::measure_mode is set to CPU_TIME. */
static VALUE
prof_get_cpu_frequency(VALUE self)
{
return ULL2NUM(get_cpu_frequency());
}
void rp_init_measure_cpu_time()
{
rb_define_const(mProf, "CPU_TIME", INT2NUM(MEASURE_CPU_TIME));
rb_define_const(mProf, "CPU_TIME_ENABLED", Qtrue);
cMeasureCpuTime = rb_define_class_under(mMeasure, "CpuTime", rb_cObject);
rb_define_singleton_method(cMeasureCpuTime, "measure", prof_measure_cpu_time, 0);
rb_define_singleton_method(cMeasureCpuTime, "frequency", prof_get_cpu_frequency, 0);
}
|