Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/apache-kafka/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Ruby C API中高效地合并两个哈希?_C_Ruby_Ruby C Extension - Fatal编程技术网

如何在Ruby C API中高效地合并两个哈希?

如何在Ruby C API中高效地合并两个哈希?,c,ruby,ruby-c-extension,C,Ruby,Ruby C Extension,我正在为Ruby编写一个C扩展,它确实需要合并两个哈希,但是Ruby 1.8.6中的rb_hash_merge()函数是静态的。我已尝试使用: rb_funcall(hash1, rb_intern("merge"), 1, hash2); 但这太慢了,性能在这个应用程序中非常关键 有人知道如何在考虑效率和速度的情况下执行此合并吗 (注意,我尝试过简单地查看rb_hash_merge()的源代码并复制它,但它被其他静态函数所困扰,这些静态函数本身也被更多的静态函数所困扰,因此几乎不可能解开…我

我正在为Ruby编写一个C扩展,它确实需要合并两个哈希,但是Ruby 1.8.6中的rb_hash_merge()函数是静态的。我已尝试使用:

rb_funcall(hash1, rb_intern("merge"), 1, hash2);

但这太慢了,性能在这个应用程序中非常关键

有人知道如何在考虑效率和速度的情况下执行此合并吗


(注意,我尝试过简单地查看rb_hash_merge()的源代码并复制它,但它被其他静态函数所困扰,这些静态函数本身也被更多的静态函数所困扰,因此几乎不可能解开…我需要另一种方法)

好的,看起来可能无法在已发布的API中进行优化

测试代码:

#extconf.rb
require 'mkmf'
dir_config("hello")
create_makefile("hello")


// hello.c
#include "ruby.h"

static VALUE rb_mHello;
static VALUE rb_cMyCalc;

static void calc_mark(void *f) { }
static void calc_free(void *f) { }
static VALUE calc_alloc(VALUE klass) { return Data_Wrap_Struct(klass, calc_mark, calc_free, NULL); }

static VALUE calc_init(VALUE obj) { return Qnil; }

static VALUE calc_merge(VALUE obj, VALUE h1, VALUE h2) {
  return rb_funcall(h1, rb_intern("merge"), 1, h2);
}

static VALUE
calc_merge2(VALUE obj, VALUE h1, VALUE h2)
{
  VALUE h3 = rb_hash_new();
  VALUE keys;
  VALUE akey;
  keys = rb_funcall(h1, rb_intern("keys"), 0);
  while (akey = rb_each(keys)) {
    rb_hash_aset(h3, akey, rb_hash_aref(h1, akey));
  }
  keys = rb_funcall(h2, rb_intern("keys"), 0);
  while (akey = rb_each(keys)) {
    rb_hash_aset(h3, akey, rb_hash_aref(h2, akey));
  }
  return h3;
}

static VALUE
calc_merge3(VALUE obj, VALUE h1, VALUE h2)
{
  VALUE keys;
  VALUE akey;
  keys = rb_funcall(h1, rb_intern("keys"), 0);
  while (akey = rb_each(keys)) {
    rb_hash_aset(h2, akey, rb_hash_aref(h1, akey));
  }
  return h2;
}

void
Init_hello()
{
  rb_mHello = rb_define_module("Hello");
  rb_cMyCalc = rb_define_class_under(rb_mHello, "Calculator", rb_cObject);
  rb_define_alloc_func(rb_cMyCalc, calc_alloc);
  rb_define_method(rb_cMyCalc, "initialize", calc_init, 0);
  rb_define_method(rb_cMyCalc, "merge", calc_merge, 2);
  rb_define_method(rb_cMyCalc, "merge2", calc_merge, 2);
  rb_define_method(rb_cMyCalc, "merge3", calc_merge, 2);
}


# test.rb
require "hello"

h1 = Hash.new()
h2 = Hash.new()

1.upto(100000) { |x| h1[x] = x+1; }
1.upto(100000) { |x| h2["#{x}-12"] = x+1; }

c = Hello::Calculator.new()

puts c.merge(h1, h2).keys.length if ARGV[0] == "1"
puts c.merge2(h1, h2).keys.length if ARGV[0] == "2"
puts c.merge3(h1, h2).keys.length if ARGV[0] == "3"
现在测试结果如下:

$ time ruby test.rb

real    0m1.021s
user    0m0.940s
sys     0m0.080s
$ time ruby test.rb 1
200000

real    0m1.224s
user    0m1.148s
sys     0m0.076s
$ time ruby test.rb 2
200000

real    0m1.219s
user    0m1.132s
sys     0m0.084s
$ time ruby test.rb 3
200000

real    0m1.220s
user    0m1.128s
sys     0m0.092s
因此,在0.2s的操作中,我们可能会在最大~0.004s时剃掉

考虑到除了设置值之外可能没有那么多,因此可能没有太多空间进行进一步优化。也许你可以尝试破解ruby源代码本身——但到那时,你不再真正开发“扩展”,而是改变语言,所以它可能无法工作

如果在C部分中需要多次连接哈希,那么使用内部数据结构并在最后一次将其导出到Ruby哈希中可能是优化的唯一方法


p、 从

中借用的代码的初始框架“性能在此应用程序中非常关键。”==不是Ruby,IMHO。你提到的似乎是唯一没有构建脆弱代码的方法。我不介意代码是否脆弱,只要它能在ruby 1.8.6和ruby 1.9.1上工作(即使在预处理器defs的帮助下),我做了一些测试,看起来使用标准API你不会得到太多。。。为了便于格式化,我将在答案中发布代码。哇!谢谢你对形势的透彻分析!:)所以,是的,根据你的结果,看起来我必须找到另一种解决方法……:)干杯不客气:-)如果您有时间进行实验,并且这与您的情况相关,那么您可以使用表检查Lua中类似代码的性能,并在此处发布比较结果。我认为使用Lua的数据结构的解决方案应该快一点。