summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-09-18 00:36:37 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-09-18 00:36:37 +0000
commit4cd2a4d74aa8f4ecb742208b0d083ff2417d8858 (patch)
treee59a7f79c7c57ea290233b2e6d47078dfeb9393b
parent11548f925390fc72d04be5276bc1fe77f99ddd02 (diff)
downloadruby-4cd2a4d74aa8f4ecb742208b0d083ff2417d8858.tar.gz
vm_method.c: configurable global method cache size
* vm_method.c (Init_Method): make global method cache size configurable by environment variable "RUBY_GLOBAL_METHOD_CACHE_SIZE" [Fix GH-719] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@47621 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog6
-rw-r--r--inits.c1
-rw-r--r--vm_method.c38
3 files changed, 42 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index 0557a5a896..26db3bcd87 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Thu Sep 18 09:36:37 2014 Scott Francis <scott.francis@shopify.com>
+
+ * vm_method.c (Init_Method): make global method cache size
+ configurable by environment variable
+ "RUBY_GLOBAL_METHOD_CACHE_SIZE" [Fix GH-719]
+
Thu Sep 18 07:03:36 2014 Eric Wong <e@80x24.org>
* test/-ext-/string/test_modify_expand.rb: increase limit
diff --git a/inits.c b/inits.c
index da8cfb1ed9..458eb64b1e 100644
--- a/inits.c
+++ b/inits.c
@@ -17,6 +17,7 @@
void
rb_call_inits(void)
{
+ CALL(Method);
CALL(RandomSeed);
CALL(sym);
CALL(var_tables);
diff --git a/vm_method.c b/vm_method.c
index 17211a5634..ffcf5be339 100644
--- a/vm_method.c
+++ b/vm_method.c
@@ -15,8 +15,8 @@
#define GLOBAL_METHOD_CACHE_MASK (GLOBAL_METHOD_CACHE_SIZE-1)
#endif
-#define GLOBAL_METHOD_CACHE_KEY(c,m) ((((c)>>3)^(m))&GLOBAL_METHOD_CACHE_MASK)
-#define GLOBAL_METHOD_CACHE(c,m) (global_method_cache + GLOBAL_METHOD_CACHE_KEY(c,m))
+#define GLOBAL_METHOD_CACHE_KEY(c,m) ((((c)>>3)^(m))&(global_method_cache.mask))
+#define GLOBAL_METHOD_CACHE(c,m) (global_method_cache.entries + GLOBAL_METHOD_CACHE_KEY(c,m))
#else
#define GLOBAL_METHOD_CACHE(c,m) (rb_bug("global method cache disabled improperly"), NULL)
#endif
@@ -47,7 +47,14 @@ struct cache_entry {
};
#if OPT_GLOBAL_METHOD_CACHE
-static struct cache_entry global_method_cache[GLOBAL_METHOD_CACHE_SIZE];
+static struct {
+ unsigned int size;
+ unsigned int mask;
+ struct cache_entry *entries;
+} global_method_cache = {
+ GLOBAL_METHOD_CACHE_SIZE,
+ GLOBAL_METHOD_CACHE_MASK,
+};
#endif
#define ruby_running (GET_VM()->running)
@@ -1726,6 +1733,31 @@ obj_respond_to_missing(VALUE obj, VALUE mid, VALUE priv)
}
void
+Init_Method(void)
+{
+#if OPT_GLOBAL_METHOD_CACHE
+ char *ptr = getenv("RUBY_GLOBAL_METHOD_CACHE_SIZE");
+ int val;
+
+ if (ptr != NULL && (val = atoi(ptr)) > 0) {
+ if ((val & (val - 1)) == 0) { /* ensure val is a power of 2 */
+ global_method_cache.size = val;
+ global_method_cache.mask = val - 1;
+ }
+ else {
+ fprintf(stderr, "RUBY_GLOBAL_METHOD_CACHE_SIZE was set to %d but ignored because the value is not a power of 2.\n", val);
+ }
+ }
+
+ global_method_cache.entries = (struct cache_entry *)calloc(global_method_cache.size, sizeof(struct cache_entry));
+ if (global_method_cache.entries == NULL) {
+ fprintf(stderr, "[FATAL] failed to allocate memory\n");
+ exit(EXIT_FAILURE);
+ }
+#endif
+}
+
+void
Init_eval_method(void)
{
#undef rb_intern