Skip to content

Instantly share code, notes, and snippets.

@funny-falcon
Created March 5, 2011 11:11
Show Gist options
  • Star 31 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save funny-falcon/856296 to your computer and use it in GitHub Desktop.
Save funny-falcon/856296 to your computer and use it in GitHub Desktop.
GC tunning simple patch ruby 1.9.2 p180
diff --git a/gc.c b/gc.c
--- a/gc.c
+++ b/gc.c
@@ -77,6 +77,41 @@ void *alloca ();
#ifndef GC_MALLOC_LIMIT
#define GC_MALLOC_LIMIT 8000000
#endif
+#define HEAP_MIN_SLOTS 10000
+#define FREE_MIN 4096
+
+static unsigned int initial_malloc_limit = GC_MALLOC_LIMIT;
+static unsigned int initial_heap_min_slots = HEAP_MIN_SLOTS;
+static unsigned int initial_free_min = FREE_MIN;
+
+static void set_gc_parameters()
+{
+ char *malloc_limit_ptr, *heap_min_slots_ptr, *free_min_ptr;
+
+ malloc_limit_ptr = getenv("RUBY_GC_MALLOC_LIMIT");
+ if ( malloc_limit_ptr != NULL ) {
+ int malloc_limit_i = atoi(malloc_limit_ptr);
+ if ( malloc_limit_i > 0 ) {
+ initial_malloc_limit = malloc_limit_i;
+ }
+ }
+
+ heap_min_slots_ptr = getenv("RUBY_HEAP_MIN_SLOTS");
+ if ( heap_min_slots_ptr != NULL ) {
+ int heap_min_slots_i = atoi(heap_min_slots_ptr);
+ if ( heap_min_slots_i > 0 ) {
+ initial_heap_min_slots = heap_min_slots_i;
+ }
+ }
+
+ free_min_ptr = getenv("RUBY_FREE_MIN");
+ if ( free_min_ptr != NULL ) {
+ int free_min_i = atoi(free_min_ptr);
+ if ( free_min_i > 0 ) {
+ initial_free_min = free_min_i;
+ }
+ }
+}
#define nomem_error GET_VM()->special_exceptions[ruby_error_nomemory]
@@ -283,9 +318,6 @@ struct heaps_slot {
int finalize_flag;
};
-#define HEAP_MIN_SLOTS 10000
-#define FREE_MIN 4096
-
struct gc_list {
VALUE *varptr;
struct gc_list *next;
@@ -341,7 +373,7 @@ typedef struct rb_objspace {
static int ruby_initial_gc_stress = 0;
int *ruby_initial_gc_stress_ptr = &ruby_initial_gc_stress;
#else
-static rb_objspace_t rb_objspace = {{GC_MALLOC_LIMIT}, {HEAP_MIN_SLOTS}};
+static rb_objspace_t rb_objspace = {{initial_malloc_limit}, {initial_heap_min_slots}};
int *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress;
#endif
#define malloc_limit objspace->malloc_params.limit
@@ -375,7 +407,7 @@ rb_objspace_alloc(void)
{
rb_objspace_t *objspace = malloc(sizeof(rb_objspace_t));
memset(objspace, 0, sizeof(*objspace));
- malloc_limit = GC_MALLOC_LIMIT;
+ malloc_limit = initial_malloc_limit;
ruby_gc_stress = ruby_initial_gc_stress;
return objspace;
@@ -958,7 +990,7 @@ init_heap(rb_objspace_t *objspace)
{
size_t add, i;
- add = HEAP_MIN_SLOTS / HEAP_OBJ_LIMIT;
+ add = initial_heap_min_slots / HEAP_OBJ_LIMIT;
if (!add) {
add = 1;
@@ -1862,9 +1894,9 @@ gc_sweep(rb_objspace_t *objspace)
do_heap_free = (size_t)((heaps_used * HEAP_OBJ_LIMIT) * 0.65);
free_min = (size_t)((heaps_used * HEAP_OBJ_LIMIT) * 0.2);
- if (free_min < FREE_MIN) {
+ if (free_min < initial_free_min) {
do_heap_free = heaps_used * HEAP_OBJ_LIMIT;
- free_min = FREE_MIN;
+ free_min = initial_free_min;
}
freelist = 0;
@@ -1926,7 +1958,7 @@ gc_sweep(rb_objspace_t *objspace)
GC_PROF_SET_MALLOC_INFO;
if (malloc_increase > malloc_limit) {
malloc_limit += (size_t)((malloc_increase - malloc_limit) * (double)live / (live + freed));
- if (malloc_limit < GC_MALLOC_LIMIT) malloc_limit = GC_MALLOC_LIMIT;
+ if (malloc_limit < initial_malloc_limit) malloc_limit = initial_malloc_limit;
}
malloc_increase = 0;
if (freed < free_min) {
@@ -2298,6 +2330,7 @@ Init_stack(volatile VALUE *addr)
void
Init_heap(void)
{
+ set_gc_parameters();
init_heap(&rb_objspace);
}
@funny-falcon
Copy link
Author

Tiny patch for confugure ruby GC parameters for ruby-1.9.2 (p136 and p180 ok).
It is small part from https://github.com/skaes/railsbench/blob/master/ruby186gc.patch .
It supports only RUBY_GC_MALLOC_LIMIT, RUBY_HEAP_MIN, RUBY_FREE_MIN

With RUBY_GC_MALLOC_LIMIT=40000000 RUBY_HEAP_MIN_SLOTS=1000000 RUBY_FREE_MIN=65536
performance gain is about 17% (simple sinatra application + sequel + haml)

To apply patch on rvm installation on linux:

cd /home/user/.rvm/src/ruby-1.9.2-p1xx
wget https://gist.github.com/raw/856296/patch-1.9.2-gc.patch
patch -p 1 < patch-1.9.2-gc.patch
make && make install

@funny-falcon
Copy link
Author

Это маленький кусочек патча от railsbecnh (применённый в REE),
позволяющего настроить параметры GC через переменные окружения.

Патч сделан относительно ruby 1.9.2 (p136 p180).

Поддерживаются только RUBY_GC_MALLOC_LIMIT, RUBY_HEAP_MIN_SLOTS и RUBY_FREE_MIN .

На простой странице sinatra + sequel + haml с переменными окружения
RUBY_GC_MALLOC_LIMIT=40000000
RUBY_HEAP_MIN_SLOTS=1000000
RUBY_FREE_MIN=65536
прирост производительности на разных машинах колеблется от 17% до 30% .

(не забудьте, что как и в случае с REE, расход памяти от этих настроек
увеличивается)

@asaaki
Copy link

asaaki commented Mar 6, 2011

Will this patch be included in a next patch release of ruby? Would be nice not to think about manual patches while updating when next release comes.

@funny-falcon
Copy link
Author

Will this patch be included in a next patch release of ruby?

Many would be glad if. But railsbench patches exists a long time (since 1.8.5), and ruby team did not accept them even in such stripped form :(

@funny-falcon
Copy link
Author

There an issue about getters and setters method on GC module in ruby issue tracker: http://redmine.ruby-lang.org/issues/1047
It includes patch which provides GC.malloc_limit= and GC.heap_slots= http://redmine.ruby-lang.org/attachments/873/1047.patch

@funny-falcon
Copy link
Author

I add patch to the gist for methods GC.malloc_limit=, GC.heap_min_slots= and GC.free_min=.
Attention: patch is showed in the gist as first but should be applied after patch-1.9.2-gc.patch !

@asaaki
Copy link

asaaki commented Mar 6, 2011

If I think right, then I don't need your second patch as long as I'm not familiar with the GC.stuff because these methods only additionals.

Is there a good "tutorial" about GC in Ruby? Do you have tips and tricks for manual optimization of Ruby's GC/memory stuff?

@asaaki
Copy link

asaaki commented Mar 6, 2011

And: Maybe you should create a new gist with both patches bundled to one. So nobody has to think about right order ;o)

(If you do that, please link the new gist here. Thanks!)

@jhuckabee
Copy link

Glad to see Matz has merged this into trunk ruby/ruby@eb807d4

@asirad
Copy link

asirad commented May 18, 2011

I used this patch for 1.9.2-p180 and I did not get what I expected to have. Rails benchmarks doesn't show proper values. I used also trunk version of ruby and still nothing. Is it possible to receive some tips how to compile ruby 1.9.2 to have benchmarks in rails. I used 1.8.7 Enterprise Edition and results are ok. Thanks for any help.

@funny-falcon
Copy link
Author

I did not get what I expected to have

What did you expect? What did you get? How did you setup environment variables?

Well, this patch do not improve 1.9.2 as Enterprise Edition improve 1.8.7. This patch allows 1.9.2 to be not slower than REE for typical web application.
1.9.2 is faster than 1.8.7, but its garbage collector worser than REE's one.
With this patch (and properly set variables) simple web pages runs with 1.9.2 as fast as with REE, so that I can go with 1.9.2.

What is your experience?

@asirad
Copy link

asirad commented May 19, 2011

Now I understand what this patch do.

I want to run performance tests for Rails and to have all information e.g. created objects, memory, how many times gc runs, I need GC patch. With patch for 1.8.7 I have this information. With this patch I only receive value for time.
Now I don't have access to my notes but I will write my environment settings.
Regarding my experience I've never look so close of ruby language and ruby implementation. I know what is GC and what this do.

Is it possible to receive from you some notes/comments about what is missing to receive benchmark results for Rails application?
If you want to look for ruby benchmarks please follow this link: http://guides.rubyonrails.org/performance_testing.html

Best Regards

@funny-falcon
Copy link
Author

This patch is not implement statistics.
I took as a basis that patch from railsbench repository.
You could analyse railsbench patch and create patch against 1.9.2 .
I did it only for GC parameters cause I were not interested in deep benchmark statistic. "Siege" is enough for me.

@skaes
Copy link

skaes commented Jul 21, 2011

@asirad maybe you want to try out my full GC patches available here: https://github.com/skaes/rvm-patchsets

@funny-falcon
Copy link
Author

@skaes cool patch set :)

@aaronjensen
Copy link

will this work on p290?

@skaes
Copy link

skaes commented Sep 20, 2011

will what work on p290? My patchsets work https://github.com/skaes/rvm-patchsets

@aaronjensen
Copy link

ah, didn't realize your patchset included this functionality. awesome, i'll check it out, thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment