Skip to content

Commit 0f25886

Browse files
committed
Implement dsize function for fstring_table_type
The fstring table size used to be reported as part of the VM size, but since it was refactored to be lock-less it was no longer reported. Since it's now wrapped by a `T_DATA`, we can implement its `dsize` function and get a valuable insight into the size of the table. ``` {"address":"0x100ebff18", "type":"DATA", "shape_id":0, "slot_size":80, "struct":"VM/fstring_table", "memsize":131176, ... ```
1 parent 5248770 commit 0f25886

File tree

1 file changed

+36
-11
lines changed

1 file changed

+36
-11
lines changed

string.c

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -546,13 +546,20 @@ fstring_table_free(void *ptr)
546546
xfree(table->entries);
547547
}
548548

549+
static size_t
550+
fstring_table_size(const void *ptr)
551+
{
552+
const struct fstring_table_struct *table = ptr;
553+
return sizeof(struct fstring_table_struct) + sizeof(struct fstring_table_entry) * table->capacity;
554+
}
555+
549556
// We declare a type for the table so that we can lean on Ruby's GC for deferred reclamation
550557
static const rb_data_type_t fstring_table_type = {
551-
.wrap_struct_name = "fstring_table",
558+
.wrap_struct_name = "VM/fstring_table",
552559
.function = {
553560
.dmark = NULL,
554561
.dfree = fstring_table_free,
555-
.dsize = NULL,
562+
.dsize = fstring_table_size,
556563
},
557564
.flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE
558565
};
@@ -609,15 +616,19 @@ struct fstring_table_probe {
609616
int mask;
610617
};
611618

612-
static int fstring_table_probe_start(struct fstring_table_probe *probe, struct fstring_table_struct *table, VALUE hash_code) {
619+
static int
620+
fstring_table_probe_start(struct fstring_table_probe *probe, struct fstring_table_struct *table, VALUE hash_code)
621+
{
613622
RUBY_ASSERT((table->capacity & (table->capacity - 1)) == 0);
614623
probe->d = 0;
615624
probe->mask = table->capacity - 1;
616625
probe->idx = hash_code & probe->mask;
617626
return probe->idx;
618627
}
619628

620-
static int fstring_table_probe_next(struct fstring_table_probe *probe) {
629+
static int
630+
fstring_table_probe_next(struct fstring_table_probe *probe)
631+
{
621632
probe->d++;
622633
probe->idx = (probe->idx + probe->d) & probe->mask;
623634
return probe->idx;
@@ -626,7 +637,9 @@ static int fstring_table_probe_next(struct fstring_table_probe *probe) {
626637

627638
#define RUBY_ATOMIC_VALUE_LOAD(x) (VALUE)(RUBY_ATOMIC_PTR_LOAD(x))
628639

629-
static void fstring_insert_on_resize(struct fstring_table_struct *table, VALUE hash_code, VALUE value) {
640+
static void
641+
fstring_insert_on_resize(struct fstring_table_struct *table, VALUE hash_code, VALUE value)
642+
{
630643
struct fstring_table_probe probe;
631644
int idx = fstring_table_probe_start(&probe, table, hash_code);
632645

@@ -653,7 +666,9 @@ static void fstring_insert_on_resize(struct fstring_table_struct *table, VALUE h
653666
}
654667

655668
// Rebuilds the table
656-
static void fstring_try_resize(VALUE old_table_obj) {
669+
static void
670+
fstring_try_resize(VALUE old_table_obj)
671+
{
657672
RB_VM_LOCK_ENTER();
658673

659674
// Check if another thread has already resized
@@ -710,7 +725,9 @@ static void fstring_try_resize(VALUE old_table_obj) {
710725
RB_VM_LOCK_LEAVE();
711726
}
712727

713-
static VALUE fstring_find_or_insert(VALUE hash_code, VALUE value, struct fstr_update_arg *arg) {
728+
static VALUE
729+
fstring_find_or_insert(VALUE hash_code, VALUE value, struct fstr_update_arg *arg)
730+
{
714731
struct fstring_table_probe probe;
715732
bool inserting = false;
716733
int idx;
@@ -790,7 +807,9 @@ static VALUE fstring_find_or_insert(VALUE hash_code, VALUE value, struct fstr_up
790807

791808

792809
// Removes an fstring from the table. Compares by identity
793-
static void fstring_delete(VALUE hash_code, VALUE value) {
810+
static void
811+
fstring_delete(VALUE hash_code, VALUE value)
812+
{
794813
// Delete is never called concurrently, so atomic operations are unnecessary
795814
VALUE table_obj = RUBY_ATOMIC_VALUE_LOAD(fstring_table_obj);
796815
RUBY_ASSERT_ALWAYS(table_obj);
@@ -849,7 +868,9 @@ register_fstring(VALUE str, bool copy, bool force_precompute_hash)
849868
return result;
850869
}
851870

852-
void rb_fstring_foreach_with_replace(st_foreach_check_callback_func *func, st_update_callback_func *replace, st_data_t arg) {
871+
void
872+
rb_fstring_foreach_with_replace(st_foreach_check_callback_func *func, st_update_callback_func *replace, st_data_t arg)
873+
{
853874
// Assume locking and barrier (which there is no assert for)
854875
ASSERT_vm_locking();
855876

@@ -888,13 +909,17 @@ void rb_fstring_foreach_with_replace(st_foreach_check_callback_func *func, st_up
888909
}
889910
}
890911

891-
bool rb_obj_is_fstring_table(VALUE obj) {
912+
bool
913+
rb_obj_is_fstring_table(VALUE obj)
914+
{
892915
ASSERT_vm_locking();
893916

894917
return obj == fstring_table_obj;
895918
}
896919

897-
void rb_gc_free_fstring(VALUE obj) {
920+
void
921+
rb_gc_free_fstring(VALUE obj)
922+
{
898923
// Assume locking and barrier (which there is no assert for)
899924
ASSERT_vm_locking();
900925

0 commit comments

Comments
 (0)