# Optimize empty hash space

**URL:** <https://www.ruby-forum.com/t/optimize-empty-hash-space/113277>\
**Category:** Development\
**Created:** [August 29, 2007, 2:12pm UTC](https://www.ruby-forum.com/t/optimize-empty-hash-space/113277 "2007-08-29T14:12:21Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![Tanaka\_A](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/c67d28/32.png) [@Tanaka\_A](https://www.ruby-forum.com/u/Tanaka_A)\
**Post date:** [August 29, 2007, 2:12pm UTC](https://www.ruby-forum.com/t/optimize-empty-hash-space/113277/1 "2007-08-29T14:12:21Z")

</div>

e$B6u$Ne(B Hash e$B$Oe(B st  
e$B$r3NJ]$7$J$$$h$&$K$9$k$N$O$I$&$G$7$g$&$+!#e(B

REXML e$B$@$H!“e(BXML e$B$NB0@-$KJ]B8$Ke(B Hash  
e$B$r;H$&$N$G$9$,!”$3$N\>l9ge(B  
e$B6u$Ne(B Hash e$B$,$+$J$j;H$o$l$^$9!#e(B

e$B$=$&$$$&$H$-$Ke(B struct st\_table e$B$He(B bins  
e$B$,3NJ]$5$l$k$N$O$b$Ce(B  
e$B$?$$$J$$$N$G!"I,MW$K$J$k$^$GCY1d$9$k$N$O$I$&$G$7$g$&$+!#e(B

e$B$J$\*!“e(BRHASH(h)-\>tbl e$B$r;H$C$F$$$k%3!\<%I$Oe(B RHASH\_TBL(h)  
e$B$KCV49e(B  
e$B$9$kI,MW$,$”$j$^$9!#$=$&$7$J$$\>l9g!"e(B(0 e$B$r;H$C$F$7$^$C$Fe(B SEGV  
e$B$K$J$k$N$rKI$0$?$ae(B) e$B%3%s%Q%$%k%(%i!\<$K$J$j$^$9!#e(B

e$B$?$@!“e(BRHASH\_TBL e$B$OFbIt$Ge(B st\_table  
e$B$r3NJ]$9$k$N$G!”%a%b%j$r@ae(B  
e$BLs$9$k$?$a$K$Oe(B RHASH\_SIZE(h) e$B$J$I$r;H$C$FJ,4t$9$kI,MW$,$"$je(B  
e$B$^$9$,!#e(B

# Index: include/ruby/intern.h

# — include/ruby/intern.h (e$B%j%S%8%g%se(B 13307) +++ include/ruby/intern.h (e$B:n6H%3%T!\<e(B) @@ -326,6 +326,7 @@ VALUE rb\_hash\_aset(VALUE, VALUE, VALUE); VALUE rb\_hash\_delete\_if(VALUE); VALUE rb\_hash\_delete(VALUE,VALUE); +struct st\_table _rb\_hash\_tbl(VALUE); int rb\_path\_check(const char_); int rb\_env\_path\_tainted(void); /\* io.c \*/ Index: include/ruby/ruby.h

— include/ruby/ruby.h (e$B%j%S%8%g%se(B 13307)  
+++ include/ruby/ruby.h (e$B:n6H%3%T!\<e(B)  
@@ -478,10 +478,15 @@

struct RHash {  
struct RBasic basic;

- struct st\_table \*tbl;

- struct st\_table \*ntbl;  
int iter\_lev;  
VALUE ifnone;  
};  
+#define RHASH\_TBL(h) rb\_hash\_tbl(h)  
+#define RHASH\_ITER\_LEV(h) RHASH(h)-\>iter\_lev  
+#define RHASH\_IFNONE(h) RHASH(h)-\>ifnone  
+#define RHASH\_SIZE(h) (RHASH(h)-\>ntbl ? RHASH(h)-\>ntbl-\>num\_entries :

1. 

+#define RHASH\_EMPTY\_P(h) (RHASH\_SIZE(h) == 0)

# struct RFile { struct RBasic basic; Index: array.c

— array.c (e$B%j%S%8%g%se(B 13307)  
+++ array.c (e$B:n6H%3%T!\<e(B)  
@@ -2525,7 +2525,7 @@  
ary3 = rb\_ary\_new();

```
 for (i=0; i<RARRAY_LEN(ary1); i++) {

```

- if (st\_lookup(RHASH(hash)-\>tbl, RARRAY\_PTR(ary1)[i], 0)) continue;

- if (st\_lookup(RHASH\_TBL(hash), RARRAY\_PTR(ary1)[i], 0)) continue;  
rb\_ary\_push(ary3, rb\_ary\_elt(ary1, i));  
}  
return ary3;  
@@ -2553,9 +2553,12 @@  
RARRAY\_LEN(ary1) : RARRAY\_LEN(ary2));  
hash = ary\_make\_hash(ary2, 0);

- if (RHASH\_EMPTY\_P(hash))

- 

```
   return ary3;

```

- for (i=0; i\<RARRAY\_LEN(ary1); i++) {  
v = vv = rb\_ary\_elt(ary1, i);

- if (st\_delete(RHASH(hash)-\>tbl, (st\_data\_t\*)&vv, 0)) {

- if (st\_delete(RHASH\_TBL(hash), (st\_data\_t\*)&vv, 0)) {  
rb\_ary\_push(ary3, v);  
}  
}  
@@ -2587,13 +2590,13 @@

- if (st\_delete(RHASH(hash)-\>tbl, (st\_data\_t\*)&vv, 0)) {

- if (st\_delete(RHASH\_TBL(hash), (st\_data\_t\*)&vv, 0)) {  
rb\_ary\_push(ary3, v);  
}  
}  
for (i=0; i\<RARRAY\_LEN(ary2); i++) {  
v = vv = rb\_ary\_elt(ary2, i);

- if (st\_delete(RHASH(hash)-\>tbl, (st\_data\_t\*)&vv, 0)) {

- if (st\_delete(RHASH\_TBL(hash), (st\_data\_t\*)&vv, 0)) {  
rb\_ary\_push(ary3, v);  
}  
}  
@@ -2623,12 +2626,12 @@  
ary\_iter\_check(ary);  
hash = ary\_make\_hash(ary, 0);

- if (RARRAY\_LEN(ary) == RHASH(hash)-\>tbl-\>num\_entries) {

- if (RARRAY\_LEN(ary) == RHASH\_SIZE(hash)) {  
return Qnil;  
}  
for (i=j=0; i\<RARRAY\_LEN(ary); i++) {  
v = vv = rb\_ary\_elt(ary, i);

- if (st\_delete(RHASH(hash)-\>tbl, (st\_data\_t\*)&vv, 0)) {

- if (st\_delete(RHASH\_TBL(hash), (st\_data\_t\*)&vv, 0)) {  
rb\_ary\_store(ary, j++, v);  
}  
}  
Index: insns.def  
===================================================================  
— insns.def (e$B%j%S%8%g%se(B 13307)  
+++ insns.def (e$B:n6H%3%T!\<e(B)  
@@ -1312,7 +1312,7 @@  
}  
else {  
VALUE val;

- if (st\_lookup(RHASH(hash)-\>tbl, key, &val)) {

- if (st\_lookup(RHASH\_TBL(hash), key, &val)) {  
JUMP(FIX2INT(val));  
}  
else {  
@@ -1958,7 +1958,7 @@  
val = LONG2NUM(RARRAY\_LEN(recv));  
}  
else if (HEAP\_CLASS\_OF(recv) == rb\_cHash) {

- 

```
 val = INT2FIX(RHASH(recv)->tbl->num_entries);

```

- 

```
 val = INT2FIX(RHASH_TBL(recv)->num_entries);

```

}  
else {  
goto INSN\_LABEL(normal\_dispatch);  
Index: gc.c  
===================================================================  
— gc.c (e$B%j%S%8%g%se(B 13307)  
+++ gc.c (e$B:n6H%3%T!\<e(B)  
@@ -1032,7 +1032,7 @@  
break;

```
 case T_HASH:

```

- mark\_hash(obj-\>as.hash.tbl, lev);

- mark\_hash(obj-\>as.hash.ntbl, lev);  
ptr = obj-\>as.hash.ifnone;  
goto again;

@@ -1267,8 +1267,8 @@  
rb\_ary\_free(obj);  
break;  
case T\_HASH:

- if (RANY(obj)-\>as.hash.tbl) {
- 

```
 st_free_table(RANY(obj)->as.hash.tbl);

```

- if (RANY(obj)-\>as.hash.ntbl) {
- 

```
 st_free_table(RANY(obj)->as.hash.ntbl);

```

}  
break;  
case T\_REGEXP:  
Index: ext/json/ext/generator/generator.c  
===================================================================  
— ext/json/ext/generator/generator.c (e$B%j%S%8%g%se(B 13307)  
+++ ext/json/ext/generator/generator.c (e$B:n6H%3%T!\<e(B)  
@@ -86,7 +86,7 @@  
}

inline static VALUE mHash\_json\_transfrom(VALUE self, VALUE Vstate,  
VALUE Vdepth) {

- long depth, len = RHASH(self)-\>tbl-\>num\_entries;

- long depth, len = RHASH\_SIZE(self);  
VALUE result;  
GET\_STATE(Vstate);

@@ -140,7 +140,7 @@  
rb\_scan\_args(argc, argv, “02”, &Vstate, &Vdepth);  
depth = NIL\_P(Vdepth) ? 0 : FIX2LONG(Vdepth);  
if (NIL\_P(Vstate)) {

- 

```
   long len = RHASH(self)->tbl->num_entries;

```

- 

```
   long len = RHASH_SIZE(self);
   result = rb_str_buf_new(len);
   rb_str_buf_cat2(result, "{");
   rb_hash_foreach(self, hash_to_json_i, result);

```

@@ -480,7 +480,7 @@  
state-\>object\_nl = tmp;  
}  
tmp = ID2SYM(i\_check\_circular);

- if (st\_lookup(RHASH(opts)-\>tbl, tmp, 0)) {

- if (st\_lookup(RHASH\_TBL(opts), tmp, 0)) {  
tmp = rb\_hash\_aref(opts, ID2SYM(i\_check\_circular));  
state-\>check\_circular = RTEST(tmp);  
} else {  
@@ -488,7 +488,7 @@  
}  
tmp = ID2SYM(i\_max\_nesting);  
state-\>max\_nesting = 19;

- if (st\_lookup(RHASH(opts)-\>tbl, tmp, 0)) {

- if (st\_lookup(RHASH\_TBL(opts), tmp, 0)) {  
VALUE max\_nesting = rb\_hash\_aref(opts, tmp);  
if (RTEST(max\_nesting)) {  
Check\_Type(max\_nesting, T\_FIXNUM);  
Index: ext/json/ext/parser/parser.c  
===================================================================  
— ext/json/ext/parser/parser.c (e$B%j%S%8%g%se(B 13307)  
+++ ext/json/ext/parser/parser.c (e$B:n6H%3%T!\<e(B)  
@@ -1470,7 +1470,7 @@  
rb\_raise(rb\_eArgError, “opts needs to be like a hash”);  
} else {  
VALUE tmp = ID2SYM(i\_max\_nesting);

- 

```
       if (st_lookup(RHASH(opts)->tbl, tmp, 0)) {

```

- 

```
       if (st_lookup(RHASH_TBL(opts), tmp, 0)) {
           VALUE max_nesting = rb_hash_aref(opts, tmp);
           if (RTEST(max_nesting)) {
               Check_Type(max_nesting, T_FIXNUM);

```

@@ -1480,7 +1480,7 @@  
}  
}  
tmp = ID2SYM(i\_allow\_nan);

- 

```
       if (st_lookup(RHASH(opts)->tbl, tmp, 0)) {

```

- 

```
       if (st_lookup(RHASH_TBL(opts), tmp, 0)) {
           VALUE allow_nan = rb_hash_aref(opts, tmp);
           if (RTEST(allow_nan)) json->allow_nan = 1;
       }

```

# Index: ext/syck/rubyext.c

— ext/syck/rubyext.c (e$B%j%S%8%g%se(B 13307)  
+++ ext/syck/rubyext.c (e$B:n6H%3%T!\<e(B)  
@@ -621,7 +621,7 @@  
if ( bonus-\>taint) OBJ\_TAINT( obj );  
if ( bonus-\>proc != 0 ) rb\_funcall(bonus-\>proc, s\_call, 1, obj);

- rb\_hash\_aset(bonus-\>data,  
INT2FIX(RHASH(bonus-\>data)-\>tbl-\>num\_entries), obj);

- rb\_hash\_aset(bonus-\>data, INT2FIX(RHASH\_SIZE(bonus-\>data)), obj);  
return obj;  
}

# Index: ext/iconv/iconv.c

— ext/iconv/iconv.c (e$B%j%S%8%g%se(B 13307)  
+++ ext/iconv/iconv.c (e$B:n6H%3%T!\<e(B)  
@@ -138,10 +138,10 @@  
{  
VALUE val = \*code;

- if (RHASH(charset\_map)-\>tbl &&  
RHASH(charset\_map)-\>tbl-\>num\_entries) {

- if (RHASH\_SIZE(charset\_map)) {  
VALUE key = rb\_funcall2(val, rb\_intern(“downcase”), 0, 0);  
StringValuePtr(key);

- if (st\_lookup(RHASH(charset\_map)-\>tbl, key, &val)) {

- if (st\_lookup(RHASH\_TBL(charset\_map), key, &val)) {  
\*code = val;  
}  
}  
Index: hash.c  
===================================================================  
— hash.c (e$B%j%S%8%g%se(B 13307)  
+++ hash.c (e$B:n6H%3%T!\<e(B)  
@@ -147,10 +147,10 @@  
int status;  
st\_table \*tbl;

- tbl = RHASH(arg-\>hash)-\>tbl;

- tbl = RHASH(arg-\>hash)-\>ntbl;  
if (key == Qundef) return ST\_CONTINUE;  
status = (\*arg-\>func)(key, value, arg-\>arg);

- if (RHASH(arg-\>hash)-\>tbl != tbl) {

- if (RHASH(arg-\>hash)-\>ntbl != tbl) {  
rb\_raise(rb\_eRuntimeError, “rehash occurred during iteration”);  
}  
switch (status) {  
@@ -172,7 +172,7 @@

- 

```
 st_cleanup_safe(RHASH(hash)->tbl, Qundef);

```

- 

```
 st_cleanup_safe(RHASH(hash)->ntbl, Qundef);
 FL_UNSET(hash, HASH_DELETED);

```

}  
}  
@@ -182,7 +182,7 @@  
static VALUE  
hash\_foreach\_call(struct hash\_foreach\_arg \*arg)  
{

- if (st\_foreach(RHASH(arg-\>hash)-\>tbl, hash\_foreach\_iter,  
(st\_data\_t)arg)) {

- if (st\_foreach(RHASH(arg-\>hash)-\>ntbl, hash\_foreach\_iter,  
(st\_data\_t)arg)) {  
rb\_raise(rb\_eRuntimeError, “hash modified during iteration”);  
}  
return Qnil;  
@@ -193,6 +193,8 @@  
{  
struct hash\_foreach\_arg arg;

- if (!RHASH(hash)-\>ntbl)

- 

```
   return;

```

RHASH(hash)-\>iter\_lev++;  
arg.hash = hash;  
arg.func = (rb\_foreach\_func \*)func;  
@@ -216,7 +218,7 @@  
{  
VALUE hash = hash\_alloc0(klass);

- RHASH(hash)-\>tbl = st\_init\_table(&objhash);

- RHASH(hash)-\>ntbl = 0;

static void  
-rb\_hash\_modify(VALUE hash)  
+rb\_hash\_modify\_check(VALUE hash)  
{

- if (!RHASH(hash)-\>tbl) rb\_raise(rb\_eTypeError, “uninitialized  
Hash”);  
if (OBJ\_FROZEN(hash)) rb\_error\_frozen(“hash”);  
if (!OBJ\_TAINTED(hash) && rb\_safe\_level() \>= 4)  
rb\_raise(rb\_eSecurityError, “Insecure: can’t modify hash”);  
}

+struct st\_table \*  
+rb\_hash\_tbl(VALUE hash)  
+{

- if (!RHASH(hash)-\>ntbl) {
- 

```
   RHASH(hash)->ntbl = st_init_table(&objhash);

```

- }
- return RHASH(hash)-\>ntbl;  
+}
- 

+static void  
+rb\_hash\_modify(VALUE hash)  
+{

- rb\_hash\_modify\_check(hash);
- rb\_hash\_tbl(hash);  
+}
- 

/\*

- call-seq:
- 

```
Hash.new => hash

```

@@ -313,7 +330,9 @@

```
 if (argc == 1 && TYPE(argv[0]) == T_HASH) {

```

hash = hash\_alloc0(klass);

- RHASH(hash)-\>tbl = st\_copy(RHASH(argv[0])-\>tbl);

- 

```
   if (RHASH(argv[0])->ntbl) {

```

- 

```
       RHASH(hash)->ntbl = st_copy(RHASH(argv[0])->ntbl);

```

- 

```
   }

```

return hash;  
}  
@@ -388,11 +407,13 @@  
if (RHASH(hash)-\>iter\_lev \> 0) {  
rb\_raise(rb\_eRuntimeError, “rehash during iteration”);  
}

- rb\_hash\_modify(hash);
- tbl = st\_init\_table\_with\_size(RHASH(hash)-\>tbl-\>type,  
RHASH(hash)-\>tbl-\>num\_entries);

- rb\_hash\_modify\_check(hash);
- if (!RHASH(hash)-\>ntbl)
- 

```
   return hash;

```

- tbl = st\_init\_table\_with\_size(RHASH(hash)-\>ntbl-\>type,  
RHASH(hash)-\>ntbl-\>num\_entries);  
rb\_hash\_foreach(hash, rb\_hash\_rehash\_i, (st\_data\_t)tbl);

- st\_free\_table(RHASH(hash)-\>tbl);
- RHASH(hash)-\>tbl = tbl;

- st\_free\_table(RHASH(hash)-\>ntbl);

- RHASH(hash)-\>ntbl = tbl;

- if (!st\_lookup(RHASH(hash)-\>tbl, key, &val)) {

- if (!RHASH(hash)-\>ntbl || !st\_lookup(RHASH(hash)-\>ntbl, key, &val))  
{  
return rb\_funcall(hash, id\_default, 1, key);  
}  
return val;  
@@ -427,7 +448,7 @@  
{  
VALUE val;

- if (!st\_lookup(RHASH(hash)-\>tbl, key, &val)) {

- if (!RHASH(hash)-\>ntbl || !st\_lookup(RHASH(hash)-\>ntbl, key, &val))  
{  
return Qnil; /\* without Hash#default \*/  
}  
return val;  
@@ -475,7 +496,7 @@  
if (block\_given && argc == 2) {  
rb\_warn(“block supersedes default value argument”);  
}

- if (!st\_lookup(RHASH(hash)-\>tbl, key, &val)) {

- if (!RHASH(hash)-\>ntbl || !st\_lookup(RHASH(hash)-\>ntbl, key, &val))  
{  
if (block\_given) return rb\_yield(key);  
if (argc == 1) {  
rb\_raise(rb\_eKeyError, “key not found”);  
@@ -620,13 +641,15 @@  
{  
st\_data\_t ktmp = (st\_data\_t)key, val;

- if (!RHASH(hash)-\>ntbl)

- 

```
   return Qundef;

```

if (RHASH(hash)-\>iter\_lev \> 0) {

- if (st\_delete\_safe(RHASH(hash)-\>tbl, &ktmp, &val, Qundef)) {

- if (st\_delete\_safe(RHASH(hash)-\>ntbl, &ktmp, &val, Qundef)) {  
FL\_SET(hash, HASH\_DELETED);  
return (VALUE)val;  
}  
}

- else if (st\_delete(RHASH(hash)-\>tbl, &ktmp, &val))

- else if (st\_delete(RHASH(hash)-\>ntbl, &ktmp, &val))  
return (VALUE)val;  
return Qundef;  
}  
@@ -765,9 +788,12 @@  
VALUE  
rb\_hash\_reject\_bang(VALUE hash)  
{

- int n = RHASH(hash)-\>tbl-\>num\_entries;

- int n;
- if (!RHASH(hash)-\>ntbl)
- 

```
   return Qnil;

```

- n = RHASH(hash)-\>ntbl-\>num\_entries;  
rb\_hash\_delete\_if(hash);

- if (n == RHASH(hash)-\>tbl-\>num\_entries) return Qnil;

- if (n == RHASH(hash)-\>ntbl-\>num\_entries) return Qnil;  
return hash;  
}

@@ -861,12 +887,14 @@  
static VALUE  
rb\_hash\_clear(VALUE hash)  
{

- rb\_hash\_modify(hash);
- if (RHASH(hash)-\>tbl-\>num\_entries \> 0) {

- rb\_hash\_modify\_check(hash);
- if (!RHASH(hash)-\>ntbl)
- 

```
   return hash;

```

- if (RHASH(hash)-\>ntbl-\>num\_entries \> 0) {  
if (RHASH(hash)-\>iter\_lev \> 0)  
rb\_hash\_foreach(hash, clear\_i, 0);  
else

- 

```
 st_clear(RHASH(hash)->tbl);

```

- 

```
 st_clear(RHASH(hash)->ntbl);

```

}

return hash;  
@@ -894,11 +922,11 @@  
rb\_hash\_aset(VALUE hash, VALUE key, VALUE val)  
{  
rb\_hash\_modify(hash);

- if (TYPE(key) != T\_STRING || st\_lookup(RHASH(hash)-\>tbl, key, 0)) {
- st\_insert(RHASH(hash)-\>tbl, key, val);

- if (TYPE(key) != T\_STRING || st\_lookup(RHASH(hash)-\>ntbl, key, 0))  
{
- st\_insert(RHASH(hash)-\>ntbl, key, val);  
}  
else {

- st\_add\_direct(RHASH(hash)-\>tbl, rb\_str\_new4(key), val);

- st\_add\_direct(RHASH(hash)-\>ntbl, rb\_str\_new4(key), val);  
}  
return val;  
}  
@@ -959,7 +987,9 @@  
static VALUE  
rb\_hash\_size(VALUE hash)  
{

- return INT2FIX(RHASH(hash)-\>tbl-\>num\_entries);

- if (!RHASH(hash)-\>ntbl)
- 

```
   return INT2FIX(0);

```

- return INT2FIX(RHASH(hash)-\>ntbl-\>num\_entries);  
}

@@ -976,7 +1006,7 @@  
static VALUE  
rb\_hash\_empty\_p(VALUE hash)  
{

- if (RHASH(hash)-\>tbl-\>num\_entries == 0)

- if (!RHASH(hash)-\>ntbl || RHASH(hash)-\>ntbl-\>num\_entries == 0)  
return Qtrue;  
return Qfalse;  
}  
@@ -1190,7 +1220,7 @@  
static VALUE  
rb\_hash\_inspect(VALUE hash)  
{

- if (RHASH(hash)-\>tbl == 0 || RHASH(hash)-\>tbl-\>num\_entries == 0)

- if (!RHASH(hash)-\>ntbl || RHASH(hash)-\>ntbl-\>num\_entries == 0)  
return rb\_str\_new2("{}");  
return rb\_exec\_recursive(inspect\_hash, hash, 0);  
}  
@@ -1288,7 +1318,9 @@  
static VALUE  
rb\_hash\_has\_key(VALUE hash, VALUE key)  
{

- if (st\_lookup(RHASH(hash)-\>tbl, key, 0)) {

- if (!RHASH(hash)-\>ntbl)
- 

```
   return Qfalse;

```

- if (st\_lookup(RHASH(hash)-\>ntbl, key, 0)) {  
return Qtrue;  
}  
return Qfalse;  
@@ -1380,15 +1412,17 @@  
}  
return rb\_equal(hash2, hash1);  
}

- if (RHASH(hash1)-\>tbl-\>num\_entries !=  
RHASH(hash2)-\>tbl-\>num\_entries)

- if (RHASH\_SIZE(hash1) != RHASH\_SIZE(hash2))  
return Qfalse;
- if (!RHASH(hash1)-\>ntbl || !RHASH(hash2)-\>ntbl)
- 

```
   return Qtrue;

```

#if 0  
if (!(rb\_equal(RHASH(hash1)-\>ifnone, RHASH(hash2)-\>ifnone) &&  
FL\_TEST(hash1, HASH\_PROC\_DEFAULT) == FL\_TEST(hash2,  
HASH\_PROC\_DEFAULT)))  
return Qfalse;  
#endif

- data.tbl = RHASH(hash2)-\>tbl;

- data.tbl = RHASH(hash2)-\>ntbl;  
data.result = Qtrue;  
rb\_hash\_foreach(hash1, eql ? eql\_i : equal\_i, (st\_data\_t)&data);

@@ -1451,7 +1485,9 @@  
if (recur) {  
return LONG2FIX(0);  
}

- hval = RHASH(hash)-\>tbl-\>num\_entries;

- if (!RHASH(hash)-\>ntbl)
- 

```
   return LONG2FIX(0);

```

- hval = RHASH(hash)-\>ntbl-\>num\_entries;  
rb\_hash\_foreach(hash, hash\_i, (st\_data\_t)&hval);  
return INT2FIX(hval);  
}  
@@ -1695,7 +1731,7 @@  
rb\_hash\_compare\_by\_id(VALUE hash)  
{  
rb\_hash\_modify(hash);

- RHASH(hash)-\>tbl-\>type = &identhash;

- RHASH(hash)-\>ntbl-\>type = &identhash;  
rb\_hash\_rehash(hash);  
return hash;  
}  
@@ -1712,7 +1748,9 @@  
static VALUE  
rb\_hash\_compare\_by\_id\_p(VALUE hash)  
{

- if (RHASH(hash)-\>tbl-\>type == &identhash) {

- if (!RHASH(hash)-\>ntbl)
- 

```
   return Qfalse;

```

- if (RHASH(hash)-\>ntbl-\>type == &identhash) {  
return Qtrue;  
}  
return Qfalse;  
Index: marshal.c  
===================================================================  
— marshal.c (e$B%j%S%8%g%se(B 13307)  
+++ marshal.c (e$B:n6H%3%T!\<e(B)  
@@ -578,7 +578,7 @@  
else {  
w\_byte(TYPE\_HASH\_DEF, arg);  
}

- 

```
 w_long(RHASH(obj)->tbl->num_entries, arg);

```

- 

```
 w_long(RHASH_SIZE(obj), arg);
 rb_hash_foreach(obj, hash_each, (st_data_t)&c_arg);
 if (!NIL_P(RHASH(obj)->ifnone)) {

```

w\_object(RHASH(obj)-\>ifnone, arg, limit);  
@@ -899,7 +899,7 @@  
static VALUE  
r\_entry(VALUE v, struct load\_arg \*arg)  
{

- rb\_hash\_aset(arg-\>data,  
INT2FIX(RHASH(arg-\>data)-\>tbl-\>num\_entries), v);

- rb\_hash\_aset(arg-\>data, INT2FIX(RHASH\_SIZE(arg-\>data)), v);  
if (arg-\>taint) OBJ\_TAINT(v);  
if (arg-\>proc) {  
v = rb\_funcall(arg-\>proc, rb\_intern(“call”), 1, v);

---

<div class="post-metadata">

**Author:** ![Tanaka\_A](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/c67d28/32.png) [@Tanaka\_A](https://www.ruby-forum.com/u/Tanaka_A)\
**Post date:** [August 29, 2007, 8:03pm UTC](https://www.ruby-forum.com/t/optimize-empty-hash-space/113277/2 "2007-08-29T20:03:31Z")

</div>

e$B$^$D$b$He(B e$B$f$-$R$m$G$9e(B

In message “Re: [ruby-dev:31678] optimize empty hash space”  
on Wed, 29 Aug 2007 21:11:04 +0900, Tanaka A. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
writes:

|e$B6u$Ne(B Hash e$B$Oe(B st e$B$r3NJ]$7$J$$$h$&$K$9$k$N$O$I$&$G$7$g$&$+!#e(B  
|  
|REXML e$B$@$H!“e(BXML e$B$NB0@-$KJ]B8$Ke(B Hash e$B$r;H$&$N$G$9$,!”$3$N\>l9ge(B  
|e$B6u$Ne(B Hash e$B$,$+$J$j;H$o$l$^$9!#e(B  
|  
|e$B$=$&$$$&$H$-$Ke(B struct st\_table e$B$He(B bins e$B$,3NJ]$5$l$k$N$O$b$Ce(B  
|e$B$?$$$J$$$N$G!"I,MW$K$J$k$^$GCY1d$9$k$N$O$I$&$G$7$g$&$+!#e(B

e$B;n$7$F$_$^$7$g$&!#%3%_%C%H$7$F$/$@$5$$!#e(B
