hitimes 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Copyright (c) 2008 Jeremy Hinegardner
3
+ * All rights reserved. See LICENSE and/or COPYING for details.
4
+ *
5
+ * vim: shiftwidth=4
6
+ */
7
+
8
+ #ifndef __HITIMES_INTERVAL_H__
9
+ #define __HITIMES_INTERVAL_H__
10
+
11
+ #include <ruby.h>
12
+
13
+ #define NANOSECONDS_PER_SECOND 1e9
14
+
15
+ #ifdef USE_INSTANT_CLOCK_GETTIME
16
+ # define HITIMES_U64INT unsigned long long int
17
+ # define HITIMES_INSTANT_CONVERSION_FACTOR 1e9
18
+ #elif USE_INSTANT_OSX
19
+ # define HITIMES_U64INT unsigned long long int
20
+ # define HITIMES_INSTANT_CONVERSION_FACTOR 1e9
21
+ #elif USE_INSTANT_WINDOWS
22
+ # define HITIMES_U64INT unsigned __int64
23
+ # define HITIMES_INSTANT_CONVERSION_FACTOR hitimes_instant_conversion_factor()
24
+ #else
25
+ # error "Unable to build hitimes, no Instance backend available"
26
+ #endif
27
+
28
+
29
+ /* an alias for a 64bit unsigned integer. The various sytem dependenent
30
+ * files must define hitimes_u64int_t
31
+ */
32
+ typedef HITIMES_U64INT hitimes_instant_t;
33
+
34
+ typedef struct hitimes_interval {
35
+ hitimes_instant_t start_instant;
36
+ hitimes_instant_t stop_instant;
37
+ VALUE duration;
38
+ } hitimes_interval_t;
39
+
40
+ /* all the backends must define this method */
41
+ hitimes_instant_t hitimes_get_current_instant( );
42
+ double hitimes_instant_conversion_factor( );
43
+
44
+ /* init methods */
45
+ void Init_hitimes_stats();
46
+ void Init_hitimes_interval();
47
+
48
+
49
+ /* Module and Classes -- defined at the top level */
50
+ extern VALUE mH; /* module Hitimes */
51
+ extern VALUE eH_Error; /* class Hitimes::Error */
52
+ extern VALUE cH_Interval; /* class Hitimes::Interval */
53
+
54
+
55
+ /**
56
+ * Methods for Interval
57
+ */
58
+
59
+ VALUE hitimes_interval_free(hitimes_interval_t* i) ;
60
+ VALUE hitimes_interval_alloc(VALUE klass);
61
+ VALUE hitimes_interval_now( VALUE self );
62
+ VALUE hitimes_interval_measure( VALUE self );
63
+ VALUE hitimes_interval_split( VALUE self );
64
+ VALUE hitimes_interval_start( VALUE self );
65
+ VALUE hitimes_interval_stop( VALUE self );
66
+ VALUE hitimes_interval_started( VALUE self );
67
+ VALUE hitimes_interval_stopped( VALUE self );
68
+ VALUE hitimes_interval_running( VALUE self );
69
+ VALUE hitimes_interval_start_instant( VALUE self );
70
+ VALUE hitimes_interval_stop_instant( VALUE self );
71
+ VALUE hitimes_interval_duration ( VALUE self );
72
+
73
+ #endif
@@ -0,0 +1,217 @@
1
+ /**
2
+ * Copyright (c) 2008 Jeremy Hinegardner
3
+ * All rights reserved. See LICENSE and/or COPYING for details.
4
+ *
5
+ * vim: shiftwidth=4
6
+ */
7
+
8
+ #include "hitimes_stats.h"
9
+
10
+ /* classes defined here */
11
+ VALUE cH_Stats; /* Hitimes::Stats */
12
+
13
+ /**
14
+ * Allocator and Deallocator for Stats classes
15
+ */
16
+
17
+ VALUE hitimes_stats_free(hitimes_stats_t* s)
18
+ {
19
+ xfree( s );
20
+ return Qnil;
21
+ }
22
+
23
+ VALUE hitimes_stats_alloc(VALUE klass)
24
+ {
25
+ VALUE obj;
26
+ hitimes_stats_t* s = xmalloc( sizeof( hitimes_stats_t ) );
27
+
28
+ s->min = 0.0;
29
+ s->max = 0.0;
30
+ s->count = 0;
31
+ s->sum = 0.0;
32
+ s->sumsq = 0.0;
33
+
34
+ obj = Data_Wrap_Struct(klass, NULL, hitimes_stats_free, s);
35
+
36
+ return obj;
37
+ }
38
+
39
+
40
+ /**
41
+ * call-seq:
42
+ * stat.update( val ) -> nil
43
+ *
44
+ * Update the running stats with the new value.
45
+ */
46
+ VALUE hitimes_stats_update( VALUE self, VALUE v )
47
+ {
48
+ double new_v = NUM2DBL( v );
49
+ hitimes_stats_t *stats;
50
+
51
+ Data_Get_Struct( self, hitimes_stats_t, stats );
52
+
53
+ if ( 0 == stats->count ) {
54
+ stats->min = new_v;
55
+ stats->max = new_v;
56
+ } else {
57
+ stats->min = ( new_v < stats->min) ? ( new_v ) : ( stats->min );
58
+ stats->max = ( new_v > stats->max) ? ( new_v ) : ( stats->max );
59
+ }
60
+
61
+ stats->count += 1;
62
+ stats->sum += new_v;
63
+ stats->sumsq += ( new_v * new_v );
64
+
65
+ return Qnil;
66
+ }
67
+
68
+ /**
69
+ * call-seq:
70
+ * stat.mean -> Float
71
+ *
72
+ * Return the arithmetic mean of the values put into the Stats object. If no
73
+ * values have passed through the stats object then 0.0 is returned;
74
+ */
75
+ VALUE hitimes_stats_mean( VALUE self )
76
+ {
77
+ hitimes_stats_t *stats;
78
+ double mean = 0.0;
79
+
80
+ Data_Get_Struct( self, hitimes_stats_t, stats );
81
+
82
+ if ( stats->count > 0 ) {
83
+ mean = stats->sum / stats->count ;
84
+ }
85
+
86
+ return rb_float_new( mean );
87
+ }
88
+
89
+ /**
90
+ * call-seq:
91
+ * stat.max -> Float
92
+ *
93
+ * Return the maximum value that has passed through the Stats object
94
+ */
95
+ VALUE hitimes_stats_max( VALUE self )
96
+ {
97
+ hitimes_stats_t *stats;
98
+
99
+ Data_Get_Struct( self, hitimes_stats_t, stats );
100
+
101
+ return rb_float_new( stats->max );
102
+ }
103
+
104
+
105
+
106
+ /**
107
+ * call-seq:
108
+ * stat.min -> Float
109
+ *
110
+ * Return the minimum value that has passed through the Stats object
111
+ */
112
+ VALUE hitimes_stats_min( VALUE self )
113
+ {
114
+ hitimes_stats_t *stats;
115
+
116
+ Data_Get_Struct( self, hitimes_stats_t, stats );
117
+
118
+ return rb_float_new( stats->min );
119
+ }
120
+
121
+
122
+ /**
123
+ * call-seq:
124
+ * stat.count -> Integer
125
+ *
126
+ * Return the number of values that have passed through the Stats object.
127
+ */
128
+ VALUE hitimes_stats_count( VALUE self )
129
+ {
130
+ hitimes_stats_t *stats;
131
+
132
+ Data_Get_Struct( self, hitimes_stats_t, stats );
133
+
134
+ return LONG2NUM( stats->count );
135
+ }
136
+
137
+
138
+ /**
139
+ * call-seq:
140
+ * stat.sum -> Float
141
+ *
142
+ * Return the sum of all the values that have passed through the Stats object.
143
+ */
144
+ VALUE hitimes_stats_sum( VALUE self )
145
+ {
146
+ hitimes_stats_t *stats;
147
+
148
+ Data_Get_Struct( self, hitimes_stats_t, stats );
149
+
150
+ return rb_float_new( stats->sum );
151
+ }
152
+
153
+
154
+ /**
155
+ * call-seq:
156
+ * stat.stddev -> Float
157
+ *
158
+ * Return the standard deviation of all the values that have passed through the
159
+ * Stats object. The standard deviation has no meaning unless the count is > 1,
160
+ * therefore if the current _stat.count_ is < 1 then 0.0 will be returned;
161
+ */
162
+ VALUE hitimes_stats_stddev ( VALUE self )
163
+ {
164
+ hitimes_stats_t *stats;
165
+ double stddev = 0.0;
166
+
167
+ Data_Get_Struct( self, hitimes_stats_t, stats );
168
+ if ( stats->count > 1 ) {
169
+ stddev = sqrt( ( stats->sumsq - ( stats->sum * stats->sum / stats->count ) ) / ( stats->count - 1 ) );
170
+ }
171
+
172
+ return rb_float_new( stddev );
173
+ }
174
+
175
+
176
+ /**
177
+ * Document-class: Hitimes::Stats
178
+ *
179
+ * The Stats class encapulsates capturing and reporting statistics. It is
180
+ * modeled after the RFuzz::Sampler class, but implemented in C. For general use
181
+ * you allocate a new Stats object, and then update it with new values. The
182
+ * Stats object will keep track of the _min_, _max_, _count_ and _sum_ and when
183
+ * you want you may also retrieve the _mean_ and _stddev_.
184
+ *
185
+ * this contrived example shows getting a list of all the files in a directory
186
+ * and running stats on file sizes.
187
+ *
188
+ * s = Hitimes::Stats.new
189
+ * dir = ARGV.shift || Dir.pwd
190
+ * Dir.entries( dir ).each do |entry|
191
+ * fs = File.stat( entry )
192
+ * if fs.file? then
193
+ * s.update( fs.size )
194
+ * end
195
+ * end
196
+ *
197
+ * %w[ count min max mean sum stddev ].each do |m|
198
+ * puts "#{m.rjust(6)} : #{s.send( m ) }"
199
+ * end
200
+ */
201
+ void Init_hitimes_stats()
202
+ {
203
+
204
+ mH = rb_define_module("Hitimes");
205
+
206
+ cH_Stats = rb_define_class_under( mH, "Stats", rb_cObject ); /* in hitimes_stats.c */
207
+ rb_define_alloc_func( cH_Stats, hitimes_stats_alloc );
208
+
209
+ rb_define_method( cH_Stats, "update", hitimes_stats_update, 1 ); /* in hitimes_stats.c */
210
+ rb_define_method( cH_Stats, "mean", hitimes_stats_mean, 0 ); /* in hitimes_stats.c */
211
+ rb_define_method( cH_Stats, "max", hitimes_stats_max, 0 ); /* in hitimes_stats.c */
212
+ rb_define_method( cH_Stats, "min", hitimes_stats_min, 0 ); /* in hitimes_stats.c */
213
+ rb_define_method( cH_Stats, "count", hitimes_stats_count, 0 ); /* in hitimes_stats.c */
214
+ rb_define_method( cH_Stats, "sum", hitimes_stats_sum, 0 ); /* in hitimes_stats.c */
215
+ rb_define_method( cH_Stats, "stddev", hitimes_stats_stddev, 0 ); /* in hitimes_stats.c */
216
+ }
217
+
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Copyright (c) 2008 Jeremy Hinegardner
3
+ * All rights reserved. See LICENSE and/or COPYING for details.
4
+ *
5
+ * vim: shiftwidth=4
6
+ */
7
+
8
+ #ifndef __HITIMES_STATS_H__
9
+ #define __HITIMES_STATS_H__
10
+
11
+ #include <ruby.h>
12
+ #include <math.h>
13
+
14
+ /* classes and modules defined elswhere */
15
+ extern VALUE mH; /* Hitimes */
16
+ extern VALUE eH_Error; /* Hitimes::Error */
17
+ extern VALUE cH_Stats; /* Hitimes::Stats */
18
+
19
+
20
+ typedef struct hitimes_stats {
21
+ double min;
22
+ double max;
23
+ double sum;
24
+ double sumsq;
25
+ long count;
26
+ } hitimes_stats_t;
27
+
28
+ #endif
29
+
30
+
@@ -0,0 +1,20 @@
1
+ require 'rubygems'
2
+ require 'mkrf'
3
+ require 'rbconfig'
4
+
5
+ Mkrf::Generator.new('hitimes_ext') do |g|
6
+ g.logger.level = Logger::WARN
7
+
8
+ if Config::CONFIG['host_os'] =~ /darwin/ then
9
+ g.add_define "USE_INSTANT_OSX=1"
10
+ g.additional_code = "LIBS.concat(' -framework CoreServices')"
11
+ elsif Config::CONFIG['host_os'] =~ /win32/ then
12
+ g.add_define "USE_INSTANT_WINDOWS=1"
13
+ else
14
+ g.include_library("rt")
15
+ if g.has_function?( 'clock_gettime' ) then
16
+ g.add_define "USE_INSTANT_CLOCK_GETTIME=1"
17
+ end
18
+ end
19
+
20
+ end
@@ -0,0 +1,49 @@
1
+ require 'rubygems'
2
+ require 'hitimes/version'
3
+ require 'tasks/config'
4
+
5
+ Hitimes::GEM_SPEC = Gem::Specification.new do |spec|
6
+ proj = Configuration.for('project')
7
+ spec.name = proj.name
8
+ spec.version = Hitimes::VERSION
9
+
10
+ spec.author = proj.author
11
+ spec.email = proj.email
12
+ spec.homepage = proj.homepage
13
+ spec.summary = proj.summary
14
+ spec.description = proj.description
15
+ spec.platform = Gem::Platform::RUBY
16
+
17
+
18
+ pkg = Configuration.for('packaging')
19
+ spec.files = pkg.files.all
20
+ spec.executables = pkg.files.bin.collect { |b| File.basename(b) }
21
+
22
+ # add dependencies here
23
+ spec.add_dependency("rake", ">= 0.8.1")
24
+ spec.add_dependency("configuration", ">= 0.0.5")
25
+ spec.add_dependency("mkrf", ">= 0.2.3")
26
+
27
+ if ext_conf = Configuration.for_if_exist?("extension") then
28
+ spec.extensions << ext_conf.configs
29
+ spec.require_paths << 'ext'
30
+ spec.extensions.flatten!
31
+ end
32
+
33
+ if rdoc = Configuration.for_if_exist?('rdoc') then
34
+ spec.has_rdoc = true
35
+ spec.extra_rdoc_files = pkg.files.rdoc
36
+ spec.rdoc_options = rdoc.options + [ "--main" , rdoc.main_page ]
37
+ else
38
+ spec.has_rdoc = false
39
+ end
40
+
41
+ if test = Configuration.for_if_exist?('testing') then
42
+ spec.test_files = test.files
43
+ end
44
+
45
+ if rf = Configuration.for_if_exist?('rubyforge') then
46
+ spec.rubyforge_project = rf.project
47
+ end
48
+
49
+ end
@@ -0,0 +1,21 @@
1
+ #--
2
+ # Copyright (c) 2008 Jeremy Hinegardner
3
+ # All rights reserved. See LICENSE and/or COPYING for details.
4
+ #++
5
+
6
+ #
7
+ # The top level module containing the contents of the hitimes library
8
+ #
9
+ # use the library with:
10
+ #
11
+ # require 'hitimes'
12
+ #
13
+ module Hitimes
14
+ #
15
+ # Base class of all errors in Hitimes
16
+ #
17
+ class Error < ::StandardError; end
18
+ end
19
+ require 'hitimes/paths'
20
+ require 'hitimes/version'
21
+ require 'hitimes/timer'
@@ -0,0 +1,54 @@
1
+ #--
2
+ # Copyright (c) 2008 Jeremy Hinegardner
3
+ # All rights reserved. See LICENSE and/or COPYING for details.
4
+ #++
5
+ #
6
+ module Hitimes
7
+ #
8
+ # Access to various paths inside the project programatically
9
+ #
10
+ module Paths
11
+ #
12
+ # :call-seq:
13
+ # Hitimes::Paths.root_dir -> String
14
+ #
15
+ # Returns The full expanded path of the parent directory of +lib+
16
+ # going up the path from the current file. A trailing File::SEPARATOR
17
+ # is guaranteed.
18
+ #
19
+ def self.root_dir
20
+ unless @root_dir
21
+ path_parts = ::File.expand_path(__FILE__).split(::File::SEPARATOR)
22
+ lib_index = path_parts.rindex("lib")
23
+ @root_dir = path_parts[0...lib_index].join(::File::SEPARATOR) + ::File::SEPARATOR
24
+ end
25
+ return @root_dir
26
+ end
27
+
28
+ #
29
+ # :call-seq:
30
+ # Hitimes::Paths.lib_path( *args ) -> String
31
+ #
32
+ # Returns The full expanded path of the +lib+ directory below
33
+ # _root_dir_. All parameters passed in are joined onto the
34
+ # result. A trailing File::SEPARATOR is guaranteed if
35
+ # _args_ are *not* present.
36
+ #
37
+ def self.lib_path(*args)
38
+ self.sub_path("lib", *args)
39
+ end
40
+
41
+ #
42
+ # :call-seq:
43
+ # Hitimes::Paths.sub_path( sub, *args ) -> String
44
+ #
45
+ # Returns the full expanded path of the +sub+ directory below _root_dir. All
46
+ # _arg_ parameters passed in are joined onto the result. A trailing
47
+ # File::SEPARATOR is guaranteed if _args_ are *not* present.
48
+ #
49
+ def self.sub_path(sub,*args)
50
+ sp = ::File.join(root_dir, sub) + File::SEPARATOR
51
+ sp = ::File.join(sp, *args) if args
52
+ end
53
+ end
54
+ end