mirror of
https://github.com/ruby/ruby.git
synced 2026-01-27 04:24:23 +00:00
Whenever we run into an inline cache miss when we try to set
an ivar, we may need to take the global lock, just to be able to
lookup inside `shape->edges`.
To solve that, when we're in multi-ractor mode, we can treat
the `shape->edges` as immutable. When we need to add a new
edge, we first copy the table, and then replace it with
CAS.
This increases memory allocations, however we expect that
creating new transitions becomes increasingly rare over time.
```ruby
class A
def initialize(bool)
@a = 1
if bool
@b = 2
else
@c = 3
end
end
def test
@d = 4
end
end
def bench(iterations)
i = iterations
while i > 0
A.new(true).test
A.new(false).test
i -= 1
end
end
if ARGV.first == "ractor"
ractors = 8.times.map do
Ractor.new do
bench(20_000_000 / 8)
end
end
ractors.each(&:take)
else
bench(20_000_000)
end
```
The above benchmark takes 27 seconds in Ractor mode on Ruby 3.4,
and only 1.7s with this branch.
Co-Authored-By: Étienne Barrié <etienne.barrie@gmail.com>
50 lines
2.1 KiB
C
50 lines
2.1 KiB
C
#ifndef RUBY_ID_TABLE_H
|
|
#define RUBY_ID_TABLE_H 1
|
|
#include "ruby/internal/config.h"
|
|
#include <stddef.h>
|
|
#include "ruby/ruby.h"
|
|
|
|
struct rb_id_table;
|
|
|
|
/* compatible with ST_* */
|
|
enum rb_id_table_iterator_result {
|
|
ID_TABLE_CONTINUE = ST_CONTINUE,
|
|
ID_TABLE_STOP = ST_STOP,
|
|
ID_TABLE_DELETE = ST_DELETE,
|
|
ID_TABLE_REPLACE = ST_REPLACE,
|
|
ID_TABLE_ITERATOR_RESULT_END
|
|
};
|
|
|
|
struct rb_id_table *rb_id_table_create(size_t size);
|
|
struct rb_id_table *rb_id_table_init(struct rb_id_table *tbl, size_t capa);
|
|
|
|
void rb_id_table_free(struct rb_id_table *tbl);
|
|
void rb_id_table_free_items(struct rb_id_table *tbl);
|
|
void rb_id_table_clear(struct rb_id_table *tbl);
|
|
|
|
size_t rb_id_table_memsize(const struct rb_id_table *tbl);
|
|
|
|
int rb_id_table_insert(struct rb_id_table *tbl, ID id, VALUE val);
|
|
int rb_id_table_lookup(struct rb_id_table *tbl, ID id, VALUE *valp);
|
|
int rb_id_table_delete(struct rb_id_table *tbl, ID id);
|
|
|
|
typedef enum rb_id_table_iterator_result rb_id_table_update_value_callback_func_t(VALUE *val, void *data, int existing);
|
|
typedef enum rb_id_table_iterator_result rb_id_table_foreach_func_t(ID id, VALUE val, void *data);
|
|
typedef enum rb_id_table_iterator_result rb_id_table_foreach_values_func_t(VALUE val, void *data);
|
|
void rb_id_table_foreach(struct rb_id_table *tbl, rb_id_table_foreach_func_t *func, void *data);
|
|
void rb_id_table_foreach_values(struct rb_id_table *tbl, rb_id_table_foreach_values_func_t *func, void *data);
|
|
void rb_id_table_foreach_values_with_replace(struct rb_id_table *tbl, rb_id_table_foreach_values_func_t *func, rb_id_table_update_value_callback_func_t *replace, void *data);
|
|
|
|
VALUE rb_managed_id_table_new(size_t capa);
|
|
VALUE rb_managed_id_table_dup(VALUE table);
|
|
int rb_managed_id_table_insert(VALUE table, ID id, VALUE val);
|
|
int rb_managed_id_table_lookup(VALUE table, ID id, VALUE *valp);
|
|
size_t rb_managed_id_table_size(VALUE table);
|
|
void rb_managed_id_table_foreach(VALUE table, rb_id_table_foreach_func_t *func, void *data);
|
|
|
|
RUBY_SYMBOL_EXPORT_BEGIN
|
|
size_t rb_id_table_size(const struct rb_id_table *tbl);
|
|
RUBY_SYMBOL_EXPORT_END
|
|
|
|
#endif /* RUBY_ID_TABLE_H */
|