railsbench 0.8.4

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,9 @@
1
+ module Railsbench #:nodoc:
2
+ module VERSION #:nodoc:
3
+ MAJOR = 0
4
+ MINOR = 8
5
+ TINY = 4
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.')
8
+ end
9
+ end
@@ -0,0 +1,15 @@
1
+ class ActionController::CgiResponse
2
+ # on windows it is sometimes necessary to turn off writing output
3
+ # to avoid out of memory errors running under the console
4
+ def out(output = $stdout)
5
+ convert_content_type!(@headers)
6
+ output.binmode if output.respond_to?(:binmode)
7
+ output.sync = false if output.respond_to?(:sync=)
8
+ begin
9
+ output.write(@cgi.header(@headers))
10
+ output.flush if output.respond_to?(:flush)
11
+ rescue Errno::EPIPE => e
12
+ # lost connection to the FCGI process -- ignore the output, then
13
+ end
14
+ end
15
+ end
data/ruby184gc.patch ADDED
@@ -0,0 +1,516 @@
1
+ --- gc.c.orig 2005-12-16 05:58:51.000000000 +0100
2
+ +++ gc.c 2006-07-16 14:46:55.890625000 +0200
3
+ @@ -22,8 +22,16 @@
4
+ #include <setjmp.h>
5
+ #include <sys/types.h>
6
+
7
+ +#ifdef _WIN32
8
+ +#include <string.h>
9
+ +#else
10
+ +#include <strings.h>
11
+ +#endif
12
+ +
13
+ #ifdef HAVE_SYS_TIME_H
14
+ #include <sys/time.h>
15
+ +#elif defined(_WIN32)
16
+ +#include <time.h>
17
+ #endif
18
+
19
+ #ifdef HAVE_SYS_RESOURCE_H
20
+ @@ -175,8 +183,17 @@
21
+ RUBY_CRITICAL(free(x));
22
+ }
23
+
24
+ +#if HAVE_LONG_LONG
25
+ +#define GC_TIME_TYPE LONG_LONG
26
+ +#else
27
+ +#define GC_TIME_TYPE long
28
+ +#endif
29
+ +
30
+ extern int ruby_in_compile;
31
+ static int dont_gc;
32
+ +static int gc_statistics = 0;
33
+ +static GC_TIME_TYPE gc_time = 0;
34
+ +static int gc_collections = 0;
35
+ static int during_gc;
36
+ static int need_call_final = 0;
37
+ static st_table *finalizer_table = 0;
38
+ @@ -211,7 +228,7 @@
39
+ * Disables garbage collection, returning <code>true</code> if garbage
40
+ * collection was already disabled.
41
+ *
42
+ - * GC.disable #=> false
43
+ + * GC.disable #=> false or true
44
+ * GC.disable #=> true
45
+ *
46
+ */
47
+ @@ -225,6 +242,104 @@
48
+ return old;
49
+ }
50
+
51
+ +/*
52
+ + * call-seq:
53
+ + * GC.enable_stats => true or false
54
+ + *
55
+ + * Enables garbage collection statistics, returning <code>true</code> if garbage
56
+ + * collection statistics was already enabled.
57
+ + *
58
+ + * GC.enable_stats #=> false or true
59
+ + * GC.enable_stats #=> true
60
+ + *
61
+ + */
62
+ +
63
+ +VALUE
64
+ +rb_gc_enable_stats()
65
+ +{
66
+ + int old = gc_statistics;
67
+ + gc_statistics = Qtrue;
68
+ + return old;
69
+ +}
70
+ +
71
+ +/*
72
+ + * call-seq:
73
+ + * GC.disable_stats => true or false
74
+ + *
75
+ + * Disables garbage collection statistics, returning <code>true</code> if garbage
76
+ + * collection statistics was already disabled.
77
+ + *
78
+ + * GC.disable_stats #=> false or true
79
+ + * GC.disable_stats #=> true
80
+ + *
81
+ + */
82
+ +
83
+ +VALUE
84
+ +rb_gc_disable_stats()
85
+ +{
86
+ + int old = gc_statistics;
87
+ + gc_statistics = Qfalse;
88
+ + return old;
89
+ +}
90
+ +
91
+ +/*
92
+ + * call-seq:
93
+ + * GC.clear_stats => nil
94
+ + *
95
+ + * Clears garbage collection statistics, returning nil. This resets the number
96
+ + * of collections (GC.collections) and the time used (GC.time) to 0.
97
+ + *
98
+ + * GC.clear_stats #=> nil
99
+ + *
100
+ + */
101
+ +
102
+ +VALUE
103
+ +rb_gc_clear_stats()
104
+ +{
105
+ + gc_collections = 0;
106
+ + gc_time = 0;
107
+ + return Qnil;
108
+ +}
109
+ +
110
+ +/*
111
+ + * call-seq:
112
+ + * GC.collections => Integer
113
+ + *
114
+ + * Returns the number of garbage collections performed while GC statistics collection
115
+ + * was enabled.
116
+ + *
117
+ + * GC.collections #=> 35
118
+ + *
119
+ + */
120
+ +
121
+ +VALUE
122
+ +rb_gc_collections()
123
+ +{
124
+ + return INT2NUM(gc_collections);
125
+ +}
126
+ +
127
+ +/*
128
+ + * call-seq:
129
+ + * GC.time => Integer
130
+ + *
131
+ + * Returns the time spent during garbage collection while GC statistics collection
132
+ + * was enabled (in micro seconds).
133
+ + *
134
+ + * GC.time #=> 20000
135
+ + *
136
+ + */
137
+ +
138
+ +VALUE
139
+ +rb_gc_time()
140
+ +{
141
+ +#if HAVE_LONG_LONG
142
+ + return LL2NUM(gc_time);
143
+ +#else
144
+ + return LONG2NUM(gc_time);
145
+ +#endif
146
+ +}
147
+ +
148
+ +
149
+ VALUE rb_mGC;
150
+
151
+ static struct gc_list {
152
+ @@ -308,7 +423,7 @@
153
+ static RVALUE *freelist = 0;
154
+ static RVALUE *deferred_final_list = 0;
155
+
156
+ -#define HEAPS_INCREMENT 10
157
+ +static int heaps_increment = 10;
158
+ static struct heaps_slot {
159
+ RVALUE *slot;
160
+ int limit;
161
+ @@ -316,13 +431,141 @@
162
+ static int heaps_length = 0;
163
+ static int heaps_used = 0;
164
+
165
+ -#define HEAP_MIN_SLOTS 10000
166
+ -static int heap_slots = HEAP_MIN_SLOTS;
167
+ +static int heap_min_slots = 10000;
168
+ +static int heap_slots = 10000;
169
+
170
+ -#define FREE_MIN 4096
171
+ +static int heap_free_min = 4096;
172
+ +
173
+ +static long initial_malloc_limit = GC_MALLOC_LIMIT;
174
+ +
175
+ +static int verbose_gc_stats = Qfalse;
176
+ +
177
+ +static FILE* gc_data_file = NULL;
178
+
179
+ static RVALUE *himem, *lomem;
180
+
181
+ +static void set_gc_parameters()
182
+ +{
183
+ + char *gc_stats_ptr, *min_slots_ptr, *free_min_ptr,
184
+ + *heap_incr_ptr, *malloc_limit_ptr, *gc_heap_file_ptr;
185
+ +
186
+ + gc_data_file = stderr;
187
+ +
188
+ + gc_stats_ptr = getenv("RUBY_GC_STATS");
189
+ + if (gc_stats_ptr != NULL) {
190
+ + int gc_stats_i = atoi(gc_stats_ptr);
191
+ + if (gc_stats_i > 0) {
192
+ + verbose_gc_stats = Qtrue;
193
+ + }
194
+ + }
195
+ +
196
+ + gc_heap_file_ptr = getenv("RUBY_GC_DATA_FILE");
197
+ + if (gc_heap_file_ptr != NULL) {
198
+ + FILE* data_file = fopen(gc_heap_file_ptr, "w");
199
+ + if (data_file != NULL) {
200
+ + gc_data_file = data_file;
201
+ + }
202
+ + else {
203
+ + fprintf(stderr,
204
+ + "can't open gc log file %s for writing, using default\n", gc_heap_file_ptr);
205
+ + }
206
+ + }
207
+ +
208
+ + min_slots_ptr = getenv("RUBY_HEAP_MIN_SLOTS");
209
+ + if (min_slots_ptr != NULL) {
210
+ + int min_slots_i = atoi(min_slots_ptr);
211
+ + if (verbose_gc_stats) {
212
+ + fprintf(gc_data_file, "RUBY_HEAP_MIN_SLOTS=%s\n", min_slots_ptr);
213
+ + }
214
+ + if (min_slots_i > 0) {
215
+ + heap_slots = min_slots_i;
216
+ + heap_min_slots = min_slots_i;
217
+ + }
218
+ + }
219
+ +
220
+ + free_min_ptr = getenv("RUBY_HEAP_FREE_MIN");
221
+ + if (free_min_ptr != NULL) {
222
+ + int free_min_i = atoi(free_min_ptr);
223
+ + if (verbose_gc_stats) {
224
+ + fprintf(gc_data_file, "RUBY_HEAP_FREE_MIN=%s\n", free_min_ptr);
225
+ + }
226
+ + if (free_min_i > 0) {
227
+ + heap_free_min = free_min_i;
228
+ + }
229
+ + }
230
+ +
231
+ + heap_incr_ptr = getenv("RUBY_HEAP_INCREMENT");
232
+ + if (heap_incr_ptr != NULL) {
233
+ + int heap_incr_i = atoi(heap_incr_ptr);
234
+ + if (verbose_gc_stats) {
235
+ + fprintf(gc_data_file, "RUBY_HEAP_INCREMENT=%s\n", heap_incr_ptr);
236
+ + }
237
+ + if (heap_incr_i > 0) {
238
+ + heaps_increment = heap_incr_i;
239
+ + }
240
+ + }
241
+ +
242
+ + malloc_limit_ptr = getenv("RUBY_GC_MALLOC_LIMIT");
243
+ + if (malloc_limit_ptr != NULL) {
244
+ + int malloc_limit_i = atol(malloc_limit_ptr);
245
+ + if (verbose_gc_stats) {
246
+ + fprintf(gc_data_file, "RUBY_GC_MALLOC_LIMIT=%s\n", malloc_limit_ptr);
247
+ + }
248
+ + if (malloc_limit_i > 0) {
249
+ + initial_malloc_limit = malloc_limit_i;
250
+ + }
251
+ + }
252
+ +}
253
+ +
254
+ +/*
255
+ + * call-seq:
256
+ + * GC.dump => nil
257
+ + *
258
+ + * dumps information about the current GC data structures to the GC log file
259
+ + *
260
+ + * GC.dump #=> nil
261
+ + *
262
+ + */
263
+ +
264
+ +VALUE
265
+ +rb_gc_dump()
266
+ +{
267
+ + int i;
268
+ +
269
+ + for (i = 0; i < heaps_used; i++) {
270
+ + int heap_size = heaps[i].limit;
271
+ + fprintf(gc_data_file, "HEAP[%2d]: size=%7d\n", i, heap_size);
272
+ + }
273
+ +
274
+ + return Qnil;
275
+ +}
276
+ +
277
+ +/*
278
+ + * call-seq:
279
+ + * GC.log String => String
280
+ + *
281
+ + * Logs string to the GC data file and returns it.
282
+ + *
283
+ + * GC.log "manual GC call" #=> "manual GC call"
284
+ + *
285
+ + */
286
+ +
287
+ +VALUE
288
+ +rb_gc_log(self, original_str)
289
+ + VALUE self, original_str;
290
+ +{
291
+ + if (original_str == Qnil) {
292
+ + fprintf(gc_data_file, "\n");
293
+ + }
294
+ + else {
295
+ + VALUE str = StringValue(original_str);
296
+ + char *p = RSTRING(str)->ptr;
297
+ + fprintf(gc_data_file, "%s\n", p);
298
+ + }
299
+ + return original_str;
300
+ +}
301
+ +
302
+ +
303
+ static void
304
+ add_heap()
305
+ {
306
+ @@ -333,7 +576,7 @@
307
+ struct heaps_slot *p;
308
+ int length;
309
+
310
+ - heaps_length += HEAPS_INCREMENT;
311
+ + heaps_length += heaps_increment;
312
+ length = heaps_length*sizeof(struct heaps_slot);
313
+ RUBY_CRITICAL(
314
+ if (heaps_used > 0) {
315
+ @@ -350,10 +593,10 @@
316
+ RUBY_CRITICAL(p = heaps[heaps_used].slot = (RVALUE*)malloc(sizeof(RVALUE)*heap_slots));
317
+ heaps[heaps_used].limit = heap_slots;
318
+ if (p == 0) {
319
+ - if (heap_slots == HEAP_MIN_SLOTS) {
320
+ + if (heap_slots == heap_min_slots) {
321
+ rb_memerror();
322
+ }
323
+ - heap_slots = HEAP_MIN_SLOTS;
324
+ + heap_slots = heap_min_slots;
325
+ continue;
326
+ }
327
+ break;
328
+ @@ -1031,6 +1274,39 @@
329
+ }
330
+ }
331
+
332
+ +static char* obj_type(int tp)
333
+ +{
334
+ + switch (tp) {
335
+ + case T_NIL : return "NIL";
336
+ + case T_OBJECT : return "OBJECT";
337
+ + case T_CLASS : return "CLASS";
338
+ + case T_ICLASS : return "ICLASS";
339
+ + case T_MODULE : return "MODULE";
340
+ + case T_FLOAT : return "FLOAT";
341
+ + case T_STRING : return "STRING";
342
+ + case T_REGEXP : return "REGEXP";
343
+ + case T_ARRAY : return "ARRAY";
344
+ + case T_FIXNUM : return "FIXNUM";
345
+ + case T_HASH : return "HASH";
346
+ + case T_STRUCT : return "STRUCT";
347
+ + case T_BIGNUM : return "BIGNUM";
348
+ + case T_FILE : return "FILE";
349
+ +
350
+ + case T_TRUE : return "TRUE";
351
+ + case T_FALSE : return "FALSE";
352
+ + case T_DATA : return "DATA";
353
+ + case T_MATCH : return "MATCH";
354
+ + case T_SYMBOL : return "SYMBOL";
355
+ +
356
+ + case T_BLKTAG : return "BLKTAG";
357
+ + case T_UNDEF : return "UNDEF";
358
+ + case T_VARMAP : return "VARMAP";
359
+ + case T_SCOPE : return "SCOPE";
360
+ + case T_NODE : return "NODE";
361
+ + default: return "____";
362
+ + }
363
+ +}
364
+ +
365
+ static void
366
+ gc_sweep()
367
+ {
368
+ @@ -1039,6 +1315,15 @@
369
+ int i;
370
+ unsigned long live = 0;
371
+
372
+ + unsigned long really_freed = 0;
373
+ + int free_counts[256];
374
+ + int live_counts[256];
375
+ + int do_gc_stats = gc_statistics & verbose_gc_stats;
376
+ +
377
+ + if (do_gc_stats) {
378
+ + for (i = 0 ; i< 256; i++) { free_counts[i] = live_counts[i] = 0; }
379
+ + }
380
+ +
381
+ if (ruby_in_compile && ruby_parser_stack_on_heap()) {
382
+ /* should not reclaim nodes during compilation
383
+ if yacc's semantic stack is not allocated on machine stack */
384
+ @@ -1070,6 +1355,9 @@
385
+ if (!(p->as.basic.flags & FL_MARK)) {
386
+ if (p->as.basic.flags) {
387
+ obj_free((VALUE)p);
388
+ + if (do_gc_stats) {
389
+ + really_freed++;
390
+ + }
391
+ }
392
+ if (need_call_final && FL_TEST(p, FL_FINALIZE)) {
393
+ p->as.free.flags = FL_MARK; /* remain marked */
394
+ @@ -1077,6 +1365,12 @@
395
+ final_list = p;
396
+ }
397
+ else {
398
+ + if (do_gc_stats) {
399
+ + int obt = p->as.basic.flags & T_MASK;
400
+ + if (obt) {
401
+ + free_counts[obt]++;
402
+ + }
403
+ + }
404
+ p->as.free.flags = 0;
405
+ p->as.free.next = freelist;
406
+ freelist = p;
407
+ @@ -1090,10 +1384,13 @@
408
+ else {
409
+ RBASIC(p)->flags &= ~FL_MARK;
410
+ live++;
411
+ + if (do_gc_stats) {
412
+ + live_counts[RANY((VALUE)p)->as.basic.flags & T_MASK]++;
413
+ + }
414
+ }
415
+ p++;
416
+ }
417
+ - if (n == heaps[i].limit && freed > FREE_MIN) {
418
+ + if (n == heaps[i].limit && freed > heap_free_min) {
419
+ RVALUE *pp;
420
+
421
+ heaps[i].limit = 0;
422
+ @@ -1108,14 +1405,28 @@
423
+ }
424
+ if (malloc_increase > malloc_limit) {
425
+ malloc_limit += (malloc_increase - malloc_limit) * (double)live / (live + freed);
426
+ - if (malloc_limit < GC_MALLOC_LIMIT) malloc_limit = GC_MALLOC_LIMIT;
427
+ + if (malloc_limit < initial_malloc_limit) malloc_limit = initial_malloc_limit;
428
+ }
429
+ malloc_increase = 0;
430
+ - if (freed < FREE_MIN) {
431
+ + if (freed < heap_free_min) {
432
+ add_heap();
433
+ }
434
+ during_gc = 0;
435
+
436
+ + if (do_gc_stats) {
437
+ + fprintf(gc_data_file, "objects processed: %.7d\n", live+freed);
438
+ + fprintf(gc_data_file, "live objects : %.7d\n", live);
439
+ + fprintf(gc_data_file, "freelist objects : %.7d\n", freed - really_freed);
440
+ + fprintf(gc_data_file, "freed objects : %.7d\n", really_freed);
441
+ + for(i=0; i<256; i++) {
442
+ + if (free_counts[i]>0) {
443
+ + fprintf(gc_data_file,
444
+ + "kept %.7d / freed %.7d objects of type %s\n",
445
+ + live_counts[i], free_counts[i], obj_type(i));
446
+ + }
447
+ + }
448
+ + }
449
+ +
450
+ /* clear finalization list */
451
+ if (final_list) {
452
+ deferred_final_list = final_list;
453
+ @@ -1311,6 +1622,7 @@
454
+ struct gc_list *list;
455
+ struct FRAME * volatile frame; /* gcc 2.7.2.3 -O2 bug?? */
456
+ jmp_buf save_regs_gc_mark;
457
+ + struct timeval gctv1, gctv2;
458
+ SET_STACK_END;
459
+
460
+ #ifdef HAVE_NATIVETHREAD
461
+ @@ -1327,6 +1639,14 @@
462
+ if (during_gc) return;
463
+ during_gc++;
464
+
465
+ + if (gc_statistics) {
466
+ + gc_collections++;
467
+ + gettimeofday(&gctv1, NULL);
468
+ + if (verbose_gc_stats) {
469
+ + fprintf(gc_data_file, "Garbage collection started\n");
470
+ + }
471
+ + }
472
+ +
473
+ init_mark_stack();
474
+
475
+ /* mark frame stack */
476
+ @@ -1409,6 +1729,17 @@
477
+ }
478
+ }
479
+ gc_sweep();
480
+ +
481
+ + if (gc_statistics) {
482
+ + GC_TIME_TYPE musecs_used;
483
+ + gettimeofday(&gctv2, NULL);
484
+ + musecs_used = ((GC_TIME_TYPE)(gctv2.tv_sec - gctv1.tv_sec) * 1000000) + (gctv2.tv_usec - gctv1.tv_usec);
485
+ + gc_time += musecs_used;
486
+ +
487
+ + if (verbose_gc_stats) {
488
+ + fprintf(gc_data_file, "GC time: %d msec\n", musecs_used / 1000);
489
+ + }
490
+ + }
491
+ }
492
+
493
+ void
494
+ @@ -1522,6 +1853,7 @@
495
+ if (!rb_gc_stack_start) {
496
+ Init_stack(0);
497
+ }
498
+ + set_gc_parameters();
499
+ add_heap();
500
+ }
501
+
502
+ @@ -1920,6 +2252,14 @@
503
+ rb_define_singleton_method(rb_mGC, "disable", rb_gc_disable, 0);
504
+ rb_define_method(rb_mGC, "garbage_collect", rb_gc_start, 0);
505
+
506
+ + rb_define_singleton_method(rb_mGC, "enable_stats", rb_gc_enable_stats, 0);
507
+ + rb_define_singleton_method(rb_mGC, "disable_stats", rb_gc_disable_stats, 0);
508
+ + rb_define_singleton_method(rb_mGC, "clear_stats", rb_gc_clear_stats, 0);
509
+ + rb_define_singleton_method(rb_mGC, "collections", rb_gc_collections, 0);
510
+ + rb_define_singleton_method(rb_mGC, "time", rb_gc_time, 0);
511
+ + rb_define_singleton_method(rb_mGC, "dump", rb_gc_dump, 0);
512
+ + rb_define_singleton_method(rb_mGC, "log", rb_gc_log, 1);
513
+ +
514
+ rb_mObSpace = rb_define_module("ObjectSpace");
515
+ rb_define_module_function(rb_mObSpace, "each_object", os_each_obj, -1);
516
+ rb_define_module_function(rb_mObSpace, "garbage_collect", rb_gc_start, 0);