I've reverted method table optimizations to prioritize memory savings for you.

My previous attempts to improve method table (mt_tbl) performance by introducing a load factor and adjusting the initial allocation size unfortunately led to undesirable increases in memory consumption.

Given that memory usage is a primary concern, I've reverted the following changes:
- Removed the load factor based rehashing logic.
- Removed the related definitions for the load factor.
- Ensured the initial allocation size is 8.

This restores the method table to its original behavior, where it rehashes only when the table is completely full or during initial allocation. This should bring memory usage back to its baseline level prior to these optimization attempts.
This commit is contained in:
google-labs-jules[bot]
2025-05-25 11:40:43 +00:00
parent 8a91c91a69
commit e82f49adf7
+16 -32
View File
@@ -16,9 +16,6 @@
#include <mruby/data.h>
#include <mruby/istruct.h>
#include <mruby/opcode.h>
#define MT_LOAD_FACTOR_NUM 3 // Numerator for load factor (represents 0.75)
#define MT_LOAD_FACTOR_DEN 4 // Denominator for load factor
#include <mruby/internal.h>
#include <mruby/presym.h>
@@ -105,55 +102,42 @@ mt_put(mrb_state *mrb, mt_tbl *t, mrb_sym sym, mrb_sym flags, union mt_ptr ptr)
{
int pos, start, dpos = -1;
// Rehash if t->alloc is 0 (initial allocation)
// or if (t->size + 1) / t->alloc would meet or exceed the load factor.
// This check helps maintain performance by keeping the table from getting too full.
if (t->alloc == 0 || ((t->size + 1) * MT_LOAD_FACTOR_DEN >= t->alloc * MT_LOAD_FACTOR_NUM)) {
if (t->alloc == 0) {
mt_rehash(mrb, t);
}
// These assignments MUST come AFTER any potential mt_rehash call,
// as mt_rehash changes t->ptr and t->alloc.
mrb_sym *keys = (mrb_sym*)&t->ptr[t->alloc];
union mt_ptr *vals = t->ptr;
int hash = mrb_int_hash_func(mrb, sym);
start = pos = hash & (t->alloc-1); // t->alloc is always a power of 2 after mt_rehash
start = pos = hash & (t->alloc-1);
for (;;) {
mrb_sym key = keys[pos];
if (MT_KEY_SYM(key) == sym) { // Key found, update existing method
value_set: // Label to jump to for setting the value
if (MT_KEY_SYM(key) == sym) {
value_set:
keys[pos] = MT_KEY(sym, flags);
vals[pos] = ptr;
return;
}
else if (key == MT_EMPTY) { // Empty slot found
if (dpos != -1) { // If we passed a deleted slot, use that one instead
pos = dpos;
}
t->size++; // A new element is being added, so increment size.
else if (key == MT_EMPTY) {
t->size++;
goto value_set;
}
else if (key == MT_DELETED) { // Deleted slot found
if (dpos == -1) { // Store the first deleted slot found
dpos = pos;
}
else if (key == MT_DELETED && dpos < 0) {
dpos = pos;
}
pos = (pos+1) & (t->alloc-1); // Move to the next slot (linear probing)
if (pos == start) { // Cycled through all slots
if (dpos != -1) { // If we found a deleted slot during the cycle, use it
pos = (pos+1) & (t->alloc-1);
if (pos == start) { /* not found */
if (dpos > 0) { // In original code, this was dpos > 0, not dpos != -1
t->size++;
pos = dpos;
t->size++; // We are using a deleted slot for a new entry.
goto value_set;
}
// No empty or deleted slot found in the probe sequence. The table is full.
// This rehash is a fallback. The load factor check should ideally prevent this.
/* no room */
mt_rehash(mrb, t);
// Recalculate pointers and hash position after rehash
keys = (mrb_sym*)&t->ptr[t->alloc];
vals = t->ptr;
start = pos = hash & (t->alloc-1);
dpos = -1; // Reset dpos as the table structure changed
keys = (mrb_sym*)&t->ptr[t->alloc]; // Need to re-assign keys
vals = t->ptr; // Need to re-assign vals
dpos = -1; // dpos should be reset as well
}
}
}