Skip to content

Instantly share code, notes, and snippets.

@ILoGM
Created February 14, 2013 02:11
Show Gist options
  • Save ILoGM/4950127 to your computer and use it in GitHub Desktop.
Save ILoGM/4950127 to your computer and use it in GitHub Desktop.
Пример программного снятия GVL. Оригинал статьи http://www.spacevatican.org/2012/7/5/whos-afraid-of-the-big-bad-lock/
static void *rb_rdiscount_to_html_no_gvl(void * param_block){
rb_discount_to_html_param_block *block = (rb_discount_to_html_param_block*)param_block;
block->doc = mkd_string(block->input, block->input_length, block->flags);
if(mkd_compile(block->doc, block->flags)){
block->szres = mkd_document(block->doc, &block->res);
}
return NULL;
}
/*wrapper function. only exists because we need to pass a function pointer to rb_ensure*/
static VALUE rb_discount_to_html_no_gvl_wrapper(VALUE arg){
rb_thread_blocking_region(rb_rdiscount_to_html_no_gvl, arg, NULL, NULL);
return Qnil;
}
/*called after rb_discount_no_gvl_wrapper. cleanups up markdown resources and sticks the result in block->result)*/
static VALUE rb_discount_to_html_no_gvl_cleanup(VALUE arg){
rb_discount_param_block *block = (rb_discount_to_html_param_block*)arg;
if(block->szres !=EOF){
block->result = rb_str_buf_new(block->szres+1);
rb_str_cat(block->result, block->res, block->szres);
rb_str_cat(block->result, "\n", 1);
}
else{
block->result = rb_str_buf_new(1);
}
mkd_cleanup(block->doc);
return Qnil;
}
static VALUE rb_rdiscount_to_html(int argc, VALUE *argv, VALUE self)
{
/* boring setup*/;
rb_ensure(rb_discount_to_html_no_gvl_wrapper, &block, rb_discount_to_html_no_gvl_cleanup, &block);
/*encoding massaging omitted*/
return block.result;
}
user system total real
1 thread 6.420000 0.010000 6.430000 ( 6.426911)
2 thread 6.430000 0.010000 6.440000 ( 6.439822)
4 thread 6.380000 0.020000 6.400000 ( 6.395870)
user system total real
1 thread 6.250000 0.060000 6.310000 ( 6.315216)
2 thread 6.730000 0.110000 6.840000 ( 3.463594)
4 thread 7.520000 0.350000 7.870000 ( 2.146914)
rb_thread_blocking_region(do_some_work, argument, unblocker, unblocker_argument);
static void *rb_rdiscount_to_html_no_gvl(void * param_block){
rb_discount_to_html_param_block *block = (rb_discount_to_html_param_block*)param_block;
block->doc = mkd_string(block->input, block->input_length, block->flags);
if(mkd_compile(block->doc, block->flags)){
block->szres = mkd_document(block->doc, &block->res);
}
}
static VALUE
rb_rdiscount_to_html(int argc, VALUE *argv, VALUE self)
{
/* boring setup stuff */
rb_thread_blocking_region(rb_rdiscount_to_html_no_gvl, (void*)&block, NULL, NULL);
if(block.szres !=EOF){
rb_str_cat(buf, block.res, block.szres);
rb_str_cat(buf, "\n", 1);
}
mkd_cleanup(block.doc);
/* boring cleanup */
return buf;
}
static VALUE rb_rdiscount_to_html(int argc, VALUE *argv, VALUE self) {
/*boring setup stuff */
MMIOT *doc = mkd_string(RSTRING_PTR(text), RSTRING_LEN(text), flags);
if ( mkd_compile(doc, flags) ) {
szres = mkd_document(doc, &res);
if ( szres != EOF ) {
rb_str_cat(buf, res, szres);
rb_str_cat(buf, "\n", 1);
}
}
mkd_cleanup(doc);
/*boring cleanup */
return buf;
}
require 'thread'
require 'benchmark'
require 'rdiscount'
include Benchmark
$content = []
Dir.glob('/Users/fred/markdown/*.markdown').each {|path| $content.push File.read path}
def parse_with_threads(count)
q = Queue.new
$content.each {|data| q.push data}
count.times {q.push nil}
threads = (1..count).collect do
Thread.new do
while s = q.pop
RDiscount.new(s).to_html
end
end
end
threads.each {|th| th.join}
end
bmbm(5) do |x|
x.report("1 thread") { 40.times {parse_with_threads 1}}
x.report("2 thread") { 40.times {parse_with_threads 2}}
x.report("4 thread") { 40.times {parse_with_threads 4}}
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment