Skip to content

Commit cdb9d74

Browse files
committed
Add concurrent set probe stats to GC.stat
1 parent 3d35bad commit cdb9d74

7 files changed

Lines changed: 125 additions & 1 deletion

File tree

concurrent_set.c

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
#define CONCURRENT_SET_KEY_MASK (~CONCURRENT_SET_CONTINUATION_BIT)
1010

1111
/*#define CONCURRENT_SET_DEBUG 0*/
12-
#define CONCURRENT_SET_DEBUG 1
12+
#define CONCURRENT_SET_DEBUG 0
1313

1414
enum concurrent_set_special_values {
1515
CONCURRENT_SET_EMPTY = 0,
@@ -35,6 +35,14 @@ struct concurrent_set {
3535
const struct rb_concurrent_set_funcs *funcs;
3636
struct concurrent_set_entry *entries;
3737
int key_type;
38+
#if CONCURRENT_SET_DEBUG
39+
rb_atomic_t find_count;
40+
rb_atomic_t find_probe_total;
41+
rb_atomic_t find_probe_max;
42+
rb_atomic_t insert_count;
43+
rb_atomic_t insert_probe_total;
44+
rb_atomic_t insert_probe_max;
45+
#endif
3846
};
3947

4048
static bool
@@ -143,6 +151,42 @@ rb_concurrent_set_capacity(VALUE set_obj)
143151
return set->capacity;
144152
}
145153

154+
void
155+
rb_concurrent_set_probe_stats(VALUE set_obj,
156+
rb_atomic_t *find_count, rb_atomic_t *find_probe_total, rb_atomic_t *find_probe_max,
157+
rb_atomic_t *insert_count, rb_atomic_t *insert_probe_total, rb_atomic_t *insert_probe_max)
158+
{
159+
#if CONCURRENT_SET_DEBUG
160+
struct concurrent_set *set = RTYPEDDATA_GET_DATA(set_obj);
161+
*find_count = RUBY_ATOMIC_LOAD(set->find_count);
162+
*find_probe_total = RUBY_ATOMIC_LOAD(set->find_probe_total);
163+
*find_probe_max = RUBY_ATOMIC_LOAD(set->find_probe_max);
164+
*insert_count = RUBY_ATOMIC_LOAD(set->insert_count);
165+
*insert_probe_total = RUBY_ATOMIC_LOAD(set->insert_probe_total);
166+
*insert_probe_max = RUBY_ATOMIC_LOAD(set->insert_probe_max);
167+
#else
168+
*find_count = 0;
169+
*find_probe_total = 0;
170+
*find_probe_max = 0;
171+
*insert_count = 0;
172+
*insert_probe_total = 0;
173+
*insert_probe_max = 0;
174+
#endif
175+
}
176+
177+
#if CONCURRENT_SET_DEBUG
178+
static void
179+
concurrent_set_atomic_max(rb_atomic_t *target, rb_atomic_t val)
180+
{
181+
rb_atomic_t cur = RUBY_ATOMIC_LOAD(*target);
182+
while (val > cur) {
183+
rb_atomic_t prev = rbimpl_atomic_cas(target, cur, val, RBIMPL_ATOMIC_RELAXED, RBIMPL_ATOMIC_RELAXED);
184+
if (prev == cur) break;
185+
cur = prev;
186+
}
187+
}
188+
#endif
189+
146190
struct concurrent_set_probe {
147191
int idx;
148192
int d;
@@ -354,6 +398,11 @@ rb_concurrent_set_find(VALUE *set_obj_ptr, VALUE key)
354398
VALUE curr_hash = rbimpl_atomic_value_load(&entry->hash, RBIMPL_ATOMIC_ACQUIRE) & CONCURRENT_SET_HASH_MASK;
355399

356400
if (curr_hash == 0) {
401+
#if CONCURRENT_SET_DEBUG
402+
rbimpl_atomic_fetch_add(&set->find_count, 1, RBIMPL_ATOMIC_RELAXED);
403+
rbimpl_atomic_fetch_add(&set->find_probe_total, probe.d, RBIMPL_ATOMIC_RELAXED);
404+
concurrent_set_atomic_max(&set->find_probe_max, probe.d);
405+
#endif
357406
return 0;
358407
}
359408

@@ -363,6 +412,11 @@ rb_concurrent_set_find(VALUE *set_obj_ptr, VALUE key)
363412

364413
if (curr_hash != hash) {
365414
if (!continuation) {
415+
#if CONCURRENT_SET_DEBUG
416+
rbimpl_atomic_fetch_add(&set->find_count, 1, RBIMPL_ATOMIC_RELAXED);
417+
rbimpl_atomic_fetch_add(&set->find_probe_total, probe.d, RBIMPL_ATOMIC_RELAXED);
418+
concurrent_set_atomic_max(&set->find_probe_max, probe.d);
419+
#endif
366420
return 0;
367421
}
368422
idx = concurrent_set_probe_next(&probe);
@@ -389,11 +443,21 @@ rb_concurrent_set_find(VALUE *set_obj_ptr, VALUE key)
389443

390444
if (set->funcs->cmp(key, curr_key)) {
391445
// We've found a match.
446+
#if CONCURRENT_SET_DEBUG
447+
rbimpl_atomic_fetch_add(&set->find_count, 1, RBIMPL_ATOMIC_RELAXED);
448+
rbimpl_atomic_fetch_add(&set->find_probe_total, probe.d, RBIMPL_ATOMIC_RELAXED);
449+
concurrent_set_atomic_max(&set->find_probe_max, probe.d);
450+
#endif
392451
RB_GC_GUARD(set_obj);
393452
return curr_key;
394453
}
395454

396455
if (!continuation) {
456+
#if CONCURRENT_SET_DEBUG
457+
rbimpl_atomic_fetch_add(&set->find_count, 1, RBIMPL_ATOMIC_RELAXED);
458+
rbimpl_atomic_fetch_add(&set->find_probe_total, probe.d, RBIMPL_ATOMIC_RELAXED);
459+
concurrent_set_atomic_max(&set->find_probe_max, probe.d);
460+
#endif
397461
return 0;
398462
}
399463

@@ -488,6 +552,11 @@ rb_concurrent_set_find_or_insert(VALUE *set_obj_ptr, VALUE key, void *data)
488552

489553
VALUE prev_raw_key = rbimpl_atomic_value_cas(&entry->key, raw_key, key | (continuation ? CONCURRENT_SET_CONTINUATION_BIT : 0), RBIMPL_ATOMIC_RELEASE, RBIMPL_ATOMIC_ACQUIRE);
490554
if (prev_raw_key == raw_key) {
555+
#if CONCURRENT_SET_DEBUG
556+
rbimpl_atomic_fetch_add(&set->insert_count, 1, RBIMPL_ATOMIC_RELAXED);
557+
rbimpl_atomic_fetch_add(&set->insert_probe_total, probe.d, RBIMPL_ATOMIC_RELAXED);
558+
concurrent_set_atomic_max(&set->insert_probe_max, probe.d);
559+
#endif
491560
RB_GC_GUARD(set_obj);
492561
return key;
493562
}
@@ -525,6 +594,11 @@ rb_concurrent_set_find_or_insert(VALUE *set_obj_ptr, VALUE key, void *data)
525594

526595
if (set->funcs->cmp(key, curr_key)) {
527596
// We've found a live match.
597+
#if CONCURRENT_SET_DEBUG
598+
rbimpl_atomic_fetch_add(&set->insert_count, 1, RBIMPL_ATOMIC_RELAXED);
599+
rbimpl_atomic_fetch_add(&set->insert_probe_total, probe.d, RBIMPL_ATOMIC_RELAXED);
600+
concurrent_set_atomic_max(&set->insert_probe_max, probe.d);
601+
#endif
528602
RB_GC_GUARD(set_obj);
529603

530604
// We created key using set->funcs->create, but we didn't end

gc.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4741,6 +4741,39 @@ gc_stat_concurrent_set(VALUE hash_or_sym)
47414741
CS_SET(fstring_table_capacity, rb_fstring_table_capacity());
47424742
CS_SET(symbol_table_size, rb_symbol_table_size());
47434743
CS_SET(symbol_table_capacity, rb_symbol_table_capacity());
4744+
4745+
#define CS_SET_F(name, val) \
4746+
if (key == ID2SYM(rb_intern_const(#name))) \
4747+
return DBL2NUM(val); \
4748+
else if (hash != Qnil) \
4749+
rb_hash_aset(hash, ID2SYM(rb_intern_const(#name)), DBL2NUM(val));
4750+
4751+
{
4752+
rb_atomic_t fc, fpt, fpm, ic, ipt, ipm;
4753+
4754+
rb_concurrent_set_probe_stats(rb_fstring_table_obj(), &fc, &fpt, &fpm, &ic, &ipt, &ipm);
4755+
CS_SET(fstring_table_find_count, fc);
4756+
CS_SET(fstring_table_find_probe_total, fpt);
4757+
CS_SET_F(fstring_table_find_probe_avg, fc > 0 ? (double)fpt / fc : 0.0);
4758+
CS_SET(fstring_table_find_probe_max, fpm);
4759+
CS_SET(fstring_table_insert_count, ic);
4760+
CS_SET(fstring_table_insert_probe_total, ipt);
4761+
CS_SET_F(fstring_table_insert_probe_avg, ic > 0 ? (double)ipt / ic : 0.0);
4762+
CS_SET(fstring_table_insert_probe_max, ipm);
4763+
4764+
rb_concurrent_set_probe_stats(rb_symbol_table_obj(), &fc, &fpt, &fpm, &ic, &ipt, &ipm);
4765+
CS_SET(symbol_table_find_count, fc);
4766+
CS_SET(symbol_table_find_probe_total, fpt);
4767+
CS_SET_F(symbol_table_find_probe_avg, fc > 0 ? (double)fpt / fc : 0.0);
4768+
CS_SET(symbol_table_find_probe_max, fpm);
4769+
CS_SET(symbol_table_insert_count, ic);
4770+
CS_SET(symbol_table_insert_probe_total, ipt);
4771+
CS_SET_F(symbol_table_insert_probe_avg, ic > 0 ? (double)ipt / ic : 0.0);
4772+
CS_SET(symbol_table_insert_probe_max, ipm);
4773+
}
4774+
4775+
#undef CS_SET_F
4776+
47444777
#undef CS_SET
47454778

47464779
return Qundef;

internal/concurrent_set.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,8 @@ VALUE rb_concurrent_set_find(VALUE *set_obj_ptr, VALUE key);
1818
VALUE rb_concurrent_set_find_or_insert(VALUE *set_obj_ptr, VALUE key, void *data);
1919
VALUE rb_concurrent_set_delete_by_identity(VALUE *set_obj_ptr, VALUE key);
2020
void rb_concurrent_set_foreach_with_replace(VALUE set_obj, int (*callback)(VALUE *key, void *data), void *data);
21+
void rb_concurrent_set_probe_stats(VALUE set_obj,
22+
rb_atomic_t *find_count, rb_atomic_t *find_probe_total, rb_atomic_t *find_probe_max,
23+
rb_atomic_t *insert_count, rb_atomic_t *insert_probe_total, rb_atomic_t *insert_probe_max);
2124

2225
#endif

internal/string.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ void rb_gc_free_fstring(VALUE obj);
123123
bool rb_obj_is_fstring_table(VALUE obj);
124124
size_t rb_fstring_table_size(void);
125125
size_t rb_fstring_table_capacity(void);
126+
VALUE rb_fstring_table_obj(void);
126127
void Init_fstring_table();
127128
VALUE rb_obj_as_string_result(VALUE str, VALUE obj);
128129
VALUE rb_str_opt_plus(VALUE x, VALUE y);

internal/symbol.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ ID rb_make_temporary_id(size_t n);
3333
bool rb_obj_is_symbol_table(VALUE obj);
3434
size_t rb_symbol_table_size(void);
3535
size_t rb_symbol_table_capacity(void);
36+
VALUE rb_symbol_table_obj(void);
3637
void rb_sym_global_symbol_table_foreach_weak_reference(int (*callback)(VALUE *key, void *data), void *data);
3738
void rb_gc_free_dsymbol(VALUE);
3839
int rb_static_id_valid_p(ID id);

string.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -602,6 +602,12 @@ rb_fstring_table_capacity(void)
602602
return rb_concurrent_set_capacity(fstring_table_obj);
603603
}
604604

605+
VALUE
606+
rb_fstring_table_obj(void)
607+
{
608+
return fstring_table_obj;
609+
}
610+
605611
void
606612
rb_gc_free_fstring(VALUE obj)
607613
{

symbol.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -933,6 +933,12 @@ rb_symbol_table_capacity(void)
933933
return rb_concurrent_set_capacity(ruby_global_symbols.sym_set);
934934
}
935935

936+
VALUE
937+
rb_symbol_table_obj(void)
938+
{
939+
return ruby_global_symbols.sym_set;
940+
}
941+
936942
struct global_symbol_table_foreach_weak_reference_data {
937943
int (*callback)(VALUE *key, void *data);
938944
void *data;

0 commit comments

Comments
 (0)