The values of `@@map` are `Symbol`s and `@value` should be an
`Integer` since unpacked as unsigned long, so this comparison should
be false always. Probably comparison with `Symbol` was intended.
The allocated parser string is never freed, which causes a memory leak.
The following code leaks memory:
Ripper.sexp_raw(DATA.read)
__END__
<<~EOF
a
#{1}
a
EOF
There are some codepages like cp708 for which no ruby encoding exists:
$ ruby -e "Encoding.find('cp708')"
Traceback (most recent call last):
1: from -e:1:in `<main>'
-e:1:in `find': unknown encoding name - cp708 (ArgumentError)
win32/registry uses ENCODING to transcode error messages and expand environment
variables from UTF-16LE, so using UTF-8 seems like the best choice and is better
than a hard failure.
This should resolve [Bug #13831]
This change is reduce Ruby C API dependency for Universal Parser.
Reuse dedent_string functions in rb_ruby_ripper_dedent_string functions and remove dependencies on rb_str_modify and rb_str_set_len from the parser.
(https://github.com/ruby/strscan/pull/106)
It supports non-head match cases such as StringScanner#scan_until.
If we use a String as a pattern, we can improve match performance.
Here is a result of the including benchmark.
## CRuby
It shows String as a pattern is 1.18x faster than Regexp as a pattern.
```
$ benchmark-driver benchmark/check_until.yaml
Warming up --------------------------------------
regexp 9.403M i/s - 9.548M times in 1.015459s (106.35ns/i)
regexp_var 9.162M i/s - 9.248M times in 1.009479s (109.15ns/i)
string 8.966M i/s - 9.274M times in 1.034343s (111.54ns/i)
string_var 11.051M i/s - 11.190M times in 1.012538s (90.49ns/i)
Calculating -------------------------------------
regexp 10.319M i/s - 28.209M times in 2.733707s (96.91ns/i)
regexp_var 10.032M i/s - 27.485M times in 2.739807s (99.68ns/i)
string 9.681M i/s - 26.897M times in 2.778397s (103.30ns/i)
string_var 12.162M i/s - 33.154M times in 2.726046s (82.22ns/i)
Comparison:
string_var: 12161920.6 i/s
regexp: 10318949.7 i/s - 1.18x slower
regexp_var: 10031617.6 i/s - 1.21x slower
string: 9680843.7 i/s - 1.26x slower
```
## JRuby
It shows String as a pattern is 2.11x faster than Regexp as a pattern.
```
$ benchmark-driver benchmark/check_until.yaml
Warming up --------------------------------------
regexp 7.591M i/s - 7.544M times in 0.993780s (131.74ns/i)
regexp_var 6.143M i/s - 6.125M times in 0.997038s (162.77ns/i)
string 14.135M i/s - 14.079M times in 0.996067s (70.75ns/i)
string_var 14.079M i/s - 14.057M times in 0.998420s (71.03ns/i)
Calculating -------------------------------------
regexp 9.409M i/s - 22.773M times in 2.420268s (106.28ns/i)
regexp_var 10.116M i/s - 18.430M times in 1.821820s (98.85ns/i)
string 21.389M i/s - 42.404M times in 1.982519s (46.75ns/i)
string_var 20.897M i/s - 42.237M times in 2.021187s (47.85ns/i)
Comparison:
string: 21389191.1 i/s
string_var: 20897327.5 i/s - 1.02x slower
regexp_var: 10116464.7 i/s - 2.11x slower
regexp: 9409222.3 i/s - 2.27x slower
```
See:
be7815ec02/core/src/main/java/org/jruby/util/StringSupport.java (L1706-L1736)
---------
f9d96c446a
Co-authored-by: Sutou Kouhei <kou@clear-code.com>
A string similar to "0x____" should be treated as a string.
Currently it is processed as an Integer.
This alters the regex specified by http://yaml.org/type/int.html
to ensure at least one numerical symbol is present in the string
before converting to Integer.
81479b203e
delete_prefix with a string is easier to read than a regular expression
also it should be faster. It is available since ruby 2.5 and the gem requires
ruby 2.7.
0070f43f19
[Feature #20590]
For better of for worse, fork(2) remain the primary provider of
parallelism in Ruby programs. Even though it's frowned uppon in
many circles, and a lot of literature will simply state that only
async-signal safe APIs are safe to use after `fork()`, in practice
most APIs work well as long as you are careful about not forking
while another thread is holding a pthread mutex.
One of the APIs that is known cause fork safety issues is `getaddrinfo`.
If you fork while another thread is inside `getaddrinfo`, a mutex
may be left locked in the child, with no way to unlock it.
I think we could reduce the impact of these problem by preventing
in for the most notorious and common cases, by locking around
`fork(2)` and known unsafe APIs with a read-write lock.
getlogin is only called if USER environment variable is not set,
but if getlogin returns NULL in that case, then do not call
getpwnam, and assume /bin/sh as shell.
Mentioned in comment to bug 20586.
This test is checking what happens if you try and define a class in a C
extension where that constant is already not a class. It was doing this
by overriding ::Date and then trying to require 'date. The issue with
this is that if we ever add 'date' as a dependency for the test runner,
this test will break because the test runner files get implicitly
required in an `assert_separately` block.
Better use an explicit class for this purpose which can't be accidentally
required elsewhere.
RUBY_TYPED_DEFAULT_FREE will only free the rand_loop_t, but it will cause
the buf to be leaked. This commit fixes the memory leak by implementing
a free function for the rand_loop_t type.
When an exception is raised, it can leak memory in `head`. There are two
places that can leak memory:
1. `Check_Type(tuple, T_ARRAY)` can leak memory if `tuple` is not an
array.
2. `StringValue(name)` and `StringValue(value)` if they are not strings
and the call to `to_str` does not return a string.
This commit fixes these memory leaks by wrapping the code around a
rb_ensure so that the memory is freed in all cases.
The following code demonstrates the memory leak:
emitter = Psych::Emitter.new(StringIO.new)
nil_to_string_tags = [[nil, "tag:TALOS"]] + ([1] * 1000)
expected_array_tags = [1] * 1000
10.times do
1_000.times do
# Raises `no implicit conversion of nil into String`
emitter.start_document([], nil_to_string_tags, 0)
rescue TypeError
end
1_000.times do
# Raises `wrong argument type Integer (expected Array)`
emitter.start_document([], expected_array_tags, 0)
rescue TypeError
end
puts `ps -o rss= -p #{$$}`
end
Before:
47248
79728
111968
144224
176480
208896
241104
273280
305472
337664
After:
14832
15088
15344
15344
15360
15632
15632
15632
15648
15648
053af73818
These files were to build libffi from the bundled source, but are no
longer used since we stopped bundling the libffi sources in commit
e4f5296f06.
The gemspec file is unchanged because fiddle gem itself still supports
ruby 2.5.
[Feature #20646]Improve Socket.tcp
This is a proposed improvement to `Socket.tcp`, which has implemented Happy Eyeballs version 2 (RFC8305) in PR9374.
1. Background
I implemented Happy Eyeballs version 2 (HEv2) for Socket.tcp in PR9374, but several issues have been identified:
- `IO.select` waits for name resolution or connection establishment in v46w, but it does not consider the case where both events occur simultaneously when it returns a value.
- In this case, Socket.tcp can only capture one event and needs to execute an unnecessary loop to capture the other one, calling `IO.select` one extra time.
- `IO.select` waits for both IPv6/IPv4 name resolution (in start), but when it returns a value, it doesn't consider the case where name resolution for both address families is complete.
- In this case, `Socket.tcp` can only obtain the addresses of one address family and needs to execute an unnecessary loop obtain the other addresses, calling `IO.select` one extra time.
- The consideration for `connect_timeout` was insufficient. After initiating one or more connections, it raises a 'user specified timeout' after the `connect_timeout` period even if there were addresses that have been resolved and have not yet tried to connect.
- It does not retry with another address in case of a connection failure.
- It executes unnecessary state transitions even when an IP address is passed as the `host` argument.
- The regex for IP addresses did not correctly specify the start and end.
2. Proposal & Outcome
To overcome the aforementioned issues, this PR introduces the following changes:
- Previously, each loop iteration represented a single state transition. This has been changed to execute all processes that meet the execution conditions within a single loop iteration.
- This prevents unnecessary repeated loops and calling `IO.select`
- Introduced logic to determine the timeout value set for `IO.select`. During the Resolution Delay and Connection Attempt Delay, the user-specified timeout is ignored. Otherwise, the timeout value is set to the larger of `resolv_timeout` and `connect_timeout`.
- This ensures that the `connect_timeout` is only detected after attempting to connect to all resolved addresses.
- Retry with another address in case of a connection failure.
- This prevents unnecessary repeated loops upon connection failure.
- Call `tcp_without_fast_fallback` when an IP address is passed as the host argument.
- This prevents unnecessary state transitions when an IP address is passed.
- Fixed regex for IP addresses.
Additionally, the code has been reduced by over 100 lines, and redundancy has been minimized, which is expected to improve readability.
3. Performance
No significant performance changes were observed in the happy case before and after the improvement.
However, improvements in state transition deficiencies are expected to enhance performance in edge cases.
```ruby
require 'socket'
require 'benchmark'
Benchmark.bmbm do |x|
x.report('fast_fallback: true') do
30.times { Socket.tcp("www.ruby-lang.org", 80) }
end
x.report('fast_fallback: false') do # Ruby3.3時点と同じ
30.times { Socket.tcp("www.ruby-lang.org", 80, fast_fallback: false) }
end
end
```
Before:
```
~/s/build ❯❯❯ ../install/bin/ruby ../ruby/test.rb
user system total real
fast_fallback: true 0.021315 0.040723 0.062038 ( 0.504866)
fast_fallback: false 0.007553 0.026248 0.033801 ( 0.533211)
```
After:
```
~/s/build ❯❯❯ ../install/bin/ruby ../ruby/test.rb
user system total real
fast_fallback: true 0.023081 0.040525 0.063606 ( 0.406219)
fast_fallback: false 0.007302 0.025515 0.032817 ( 0.418680)
```
OpenSSL::ASN1 is being rewritten in Ruby. To make it easier, let's
remove dependency to the instance variables and the internal-use
function ossl_asn1_get_asn1type() outside OpenSSL::ASN1.
This also fixes the insufficient validation of the passed value with
its tagging.
35a157462e
This confused me for a few minutes -- the testcase for
https://bugs.ruby-lang.org/issues/14834 was mistyped in the file name,
as well as once in the source.
E.g. in some cases it was
`one-four-three-eight-four` instead of
`one-four-eight-three-four`.
This commit splits gc.c into two files:
- gc.c now only contains code not specific to Ruby GC. This includes
code to mark objects (which the GC implementation may choose not to
use) and wrappers for internal APIs that the implementation may need
to use (e.g. locking the VM).
- gc_impl.c now contains the implementation of Ruby's GC. This includes
marking, sweeping, compaction, and statistics. Most importantly,
gc_impl.c only uses public APIs in Ruby and a limited set of functions
exposed in gc.c. This allows us to build gc_impl.c independently of
Ruby and plug Ruby's GC into itself.