Age | Commit message (Collapse) | Author |
|
Moving object_id dumping from ObjectSpace to the GC flags allows ObjectSpace
to not assume the FL_SEEN_OBJ_ID flag and instead move it to the responsibility
of the GC.
Notes:
Merged: https://github.com/ruby/ruby/pull/12915
|
|
This function replaces the internal rb_obj_gc_flags API. rb_gc_object_metadata
returns an array of name and value pairs, with the last element having
0 for the name.
Notes:
Merged: https://github.com/ruby/ruby/pull/12777
|
|
Outputs the object ID in the dump for objects that have it seen.
Notes:
Merged: https://github.com/ruby/ruby/pull/12657
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/12385
|
|
We observed crashes from rb_io_bufwrite() thread switching (through
rb_thread_check_ints()) in the middle of rb_execution_context_mark(). By
the time rb_execution_context_mark() gets a timeslice again, it read
garbage from a frame that was already popped in another thread, crashing
the process in SEGV. Other mark functions probably have their own ways
of breaking, but clearly, the usual IO code do too much for this
perilous pseudo GC context.
Use `FILE*` like before 5001cc47169614ea07d87651c95c2ee185e374e0
("Optimize ObjectSpace.dump_all"). Also, add type checking for
the private _dump methods.
Co-authored-by: Peter Zhu <[email protected]>
Notes:
Merged: https://github.com/ruby/ruby/pull/12285
|
|
[Bug #20892]
Until the introduction of that method, it was impossible for a
Module name not to be valid JSON, hence it wasn't going through
the slower escaping function.
This assumption no longer hold.
Notes:
Merged: https://github.com/ruby/ruby/pull/12067
|
|
[Feature #20205]
As a path toward enabling frozen string literals by default in the future,
this commit introduce "chilled strings". From a user perspective chilled
strings pretend to be frozen, but on the first attempt to mutate them,
they lose their frozen status and emit a warning rather than to raise a
`FrozenError`.
Implementation wise, `rb_compile_option_struct.frozen_string_literal` is
no longer a boolean but a tri-state of `enabled/disabled/unset`.
When code is compiled with frozen string literals neither explictly enabled
or disabled, string literals are compiled with a new `putchilledstring`
instruction. This instruction is identical to `putstring` except it marks
the String with the `STR_CHILLED (FL_USER3)` and `FL_FREEZE` flags.
Chilled strings have the `FL_FREEZE` flag as to minimize the need to check
for chilled strings across the codebase, and to improve compatibility with
C extensions.
Notes:
- `String#freeze`: clears the chilled flag.
- `String#-@`: acts as if the string was mutable.
- `String#+@`: acts as if the string was mutable.
- `String#clone`: copies the chilled flag.
Co-authored-by: Jean Boussier <[email protected]>
|
|
This frees FL_USER0 on both T_MODULE and T_CLASS.
Note: prior to this, FL_SINGLETON was never set on T_MODULE,
so checking for `FL_SINGLETON` without first checking that
`FL_TYPE` was `T_CLASS` was valid. That's no longer the case.
|
|
Not all `ID` have an associated string.
Fixes a SEGFAULT in ObjectSpace.dump_all spec.
|
|
This reverts commit 5f3fb4f4e397735783743fe52a7899b614bece20.
|
|
This records the called_id and klass from imemo_callcache objects in
heap dumps.
|
|
This reverts commit f6910a61122931e4193bcc0fad18d839c319b720.
We're seeing crashes in the test suite of Shopify's core monolith after
this change.
|
|
We don't need to create a shape to transition capacity as we can
transition the capacity when the capacity of the SHAPE_IVAR changes.
|
|
This commit makes every initial size pool shape a root shape and assigns
it a capacity of 0.
|
|
I don't think it's possible to create a CI with a mid which would need
escaping to be in a JSON string, but I think we might as well not rely
on that assumption.
|
|
super() uses 0 as mid for its callinfo, so we need to check for that to
avoid a segfault when using dump_all.
|
|
This commit dumps the `mid` of the imemo callinfo when calling
`ObjectSpace.dump_all`.
|
|
* Add deprecations for public struct rb_io members.
Notes:
Merged-By: ioquatix <[email protected]>
|
|
This reverts commit 18e55fc1e1ec20e8f3166e3059e76c885fc9f8f2.
fix [Bug #19704]
https://bugs.ruby-lang.org/issues/19704
This breaks compatibility for extension libraries. Such changes
need a discussion.
|
|
* Add rb_io_path and rb_io_open_descriptor.
* Use rb_io_open_descriptor to create PTY objects
* Rename FMODE_PREP -> FMODE_EXTERNAL and expose it
FMODE_PREP I believe refers to the concept of a "pre-prepared" file, but
FMODE_EXTERNAL is clearer about what the file descriptor represents and
aligns with language in the IO::Buffer module.
* Ensure that rb_io_open_descriptor closes the FD if it fails
If FMODE_EXTERNAL is not set, then it's guaranteed that Ruby will be
responsible for closing your file, eventually, if you pass it to
rb_io_open_descriptor, even if it raises an exception.
* Rename IS_EXTERNAL_FD -> RUBY_IO_EXTERNAL_P
* Expose `rb_io_closed_p`.
* Add `rb_io_mode` to get IO mode.
---------
Co-authored-by: KJ Tsanaktsidis <[email protected]>
Notes:
Merged-By: ioquatix <[email protected]>
|
|
[Feature #19425]
Notes:
Merged: https://github.com/ruby/ruby/pull/7273
|
|
This commit adds `"embedded":true` in ObjectSpace.dump for T_OBJECTs
that are embedded.
Notes:
Merged: https://github.com/ruby/ruby/pull/7068
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/6939
|
|
When an object becomes "too complex" (in other words it has too many
variations in the shape tree), we transition it to use a "too complex"
shape and use a hash for storing instance variables.
Without this patch, there were rare cases where shape tree growth could
"explode" and cause performance degradation on what would otherwise have
been cached fast paths.
This patch puts a limit on shape tree growth, and gracefully degrades in
the rare case where there could be a factorial growth in the shape tree.
For example:
```ruby
class NG; end
HUGE_NUMBER.times do
NG.new.instance_variable_set(:"@unique_ivar_#{_1}", 1)
end
```
We consider objects to be "too complex" when the object's class has more
than SHAPE_MAX_VARIATIONS (currently 8) leaf nodes in the shape tree and
the object introduces a new variation (a new leaf node) associated with
that class.
For example, new variations on instances of the following class would be
considered "too complex" because those instances create more than 8
leaves in the shape tree:
```ruby
class Foo; end
9.times { Foo.new.instance_variable_set(":@uniq_#{_1}", 1) }
```
However, the following class is *not* too complex because it only has
one leaf in the shape tree:
```ruby
class Foo
def initialize
@a = @b = @c = @d = @e = @f = @g = @h = @i = nil
end
end
9.times { Foo.new }
``
This case is rare, so we don't expect this change to impact performance
of most applications, but it needs to be handled.
Co-Authored-By: Aaron Patterson <[email protected]>
Notes:
Merged: https://github.com/ruby/ruby/pull/6931
|
|
Count how many "variations" each class creates. A "variation" is a a
unique ordering of instance variables on a particular class. This can
also be thought of as a branch in the shape tree.
For example, the following Foo class will have 2 variations:
```ruby
class Foo ; end
Foo.new.instance_variable_set(:@a, 1) # case 1: creates one variation
Foo.new.instance_variable_set(:@b, 1) # case 2: creates another variation
foo = Foo.new
foo.instance_variable_set(:@a, 1) # does not create a new variation
foo.instance_variable_set(:@b, 1) # does not create a new variation (a continuation of the variation in case 1)
```
We will use this number to limit the amount of shapes that a class can
create and fallback to using a hash iv lookup.
Co-Authored-By: Aaron Patterson <[email protected]>
Notes:
Merged: https://github.com/ruby/ruby/pull/6931
|
|
They don't actually have a class.
Notes:
Merged: https://github.com/ruby/ruby/pull/6925
|
|
|
|
We forgot about that one, it's quite useful to see which capacity
we started from.
Notes:
Merged: https://github.com/ruby/ruby/pull/6891
|
|
I see several arguments in doing so.
First they use a non trivial amount of memory, so for various memory
profiling/mapping tools it is relevant to have visibility of the space
occupied by shapes.
Then, some pathological code can create a tons of shape, so it is
valuable to have a way to have a way to observe shapes without having
to compile Ruby with `SHAPE_DEBUG=1`.
And additionally it's likely much faster to dump then this way than
to use `RubyVM::Shape`.
There are however a few open questions:
- Shapes can't respect the `since:` argument. Not sure what to do when
it is provided. Would probably make sense to not dump them.
- Maybe it would make more sense to have a separate `ObjectSpace.dump_shapes`?
- Maybe instead `dump_all` should take a `shapes: false` argument?
Additionally, `ObjectSpace.dump_shapes` is added for the use case of
debugging the evolution of the shape tree.
Notes:
Merged: https://github.com/ruby/ruby/pull/6868
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/6864
|
|
Since object shapes store the capacity of an object, we no longer
need the numiv field on RObjects. This gives us one extra slot which
we can use to give embedded objects one more instance variable (for a
total of 3 ivs). This commit removes the concept of numiv from RObject.
Notes:
Merged: https://github.com/ruby/ruby/pull/6699
|
|
The ELTS_SHARED flag is generic, so we should prefer to use the flags
specific of the type (STR_SHARED for strings and RARRAY_SHARED_FLAG
for arrays).
|
|
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/6166
|
|
Non-ASCII code may be negative on platforms plain char is signed.
Notes:
Merged: https://github.com/ruby/ruby/pull/6166
|
|
This reverts commit 79406e3600862bbb6dcdd7c5ef8de1978e6f916c.
Notes:
Merged: https://github.com/ruby/ruby/pull/6165
|
|
Sidekiq has a method named `❨╯°□°❩╯︵┻━┻`which corrupts
heap dumps.
Normally we could just dump is as is since it's valid UTF-8 and need
no escaping. But our code to escape control characters isn't UTF-8
aware so it's more complicated than it seems.
Ultimately since the overwhelming majority of method names are
pure ASCII, it's not a big loss to just skip it.
Notes:
Merged: https://github.com/ruby/ruby/pull/6161
|
|
[Misc #18891]
Notes:
Merged: https://github.com/ruby/ruby/pull/6094
|
|
|
|
I suspect that some shared pages are invalidated because
some static string don't have their coderange set eagerly.
So the first time they are scanned, the entire memory page is
invalidated.
Being able to see the coderange in `ObjectSpace` would help debug
this.
And in addition `dump` currently call `is_broken_string()` and `is_ascii_string()`
which both end up scanning the string and assigning coderange. I think it's
undesirable as `dump` should be read only.
Notes:
Merged: https://github.com/ruby/ruby/pull/6076
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/5609
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/5520
|
|
Example:
```
In file included from ../../../include/ruby/defines.h:72,
from ../../../include/ruby/ruby.h:23,
from ../../../gc.h:3,
from ../../../ext/objspace/objspace_dump.c:15:
../../../ext/objspace/objspace_dump.c: In function ‘dump_append_ld’:
../../../ext/objspace/objspace_dump.c:95:26: warning: comparison of integer expressions of different signedness: ‘long unsigned int’ and ‘int’ [-Wsign-compare]
95 | RUBY_ASSERT(required <= width);
| ^~
```
Notes:
Merged: https://github.com/ruby/ruby/pull/4417
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/4104
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/4078
|
|
ext/objspace iterates over the heap, but some slots in the heap are
poisoned, so we need to take care of that when running with ASAN
Notes:
Merged: https://github.com/ruby/ruby/pull/3592
|
|
[Feature #17045] ObjectSpace.dump_all should allocate as little as possible in the GC heap
Up until this commit ObjectSpace.dump_all allocates two Hash because of `rb_scan_args`.
It also can allocate a `File` because of `rb_io_get_write_io`.
These allocations are problematic because `dump_all` dumps the Ruby
heap, so it should try modify as little as possible what it is
observing.
Notes:
Merged: https://github.com/ruby/ruby/pull/3530
|
|
pointed out by Coverity Scan
|
|
The two main optimization are:
- buffer writes for improved performance
- avoid formatting functions when possible
```
| |compare-ruby|built-ruby|
|:------------------|-----------:|---------:|
|dump_all_string | 1.038| 195.925|
| | -| 188.77x|
|dump_all_file | 33.453| 139.645|
| | -| 4.17x|
|dump_all_dev_null | 44.030| 278.552|
| | -| 6.33x|
```
Notes:
Merged: https://github.com/ruby/ruby/pull/3420
|
|
This is useful to see what a block of code allocated, e.g.
```
GC.start
GC.disable
ObjectSpace.trace_object_allocations do
# run some code
end
gc_gen = GC.count
allocations = ObjectSpace.dump_all(output: :file, since: gc_gen)
GC.enable
GC.start
retentions = ObjectSpace.dump_all(output: :file, since: gc_gen)
```
Notes:
Merged: https://github.com/ruby/ruby/pull/3368
|