hitimes 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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