Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Running bundle install --jobs 4 --retry 3 intermittently throws [ruby] WARNING OutOfMemoryError #2127

Closed
MSP-Greg opened this issue Oct 21, 2020 · 10 comments
Assignees
Milestone

Comments

@MSP-Greg
Copy link

Using truffleruby-head with GitHub Actions, see:
https://github.com/MSP-Greg/puma/runs/1288146881?check_suite_focus=true#step:5:9

Maybe something with zlib? Some of the log:

TypeError: class or module required for rescue clause
  /home/runner/.rubies/truffleruby-head/lib/truffle/truffle/cext.rb:1503:in `rb_rescue2'
  exception.c:90:in `rb_rescue2'
  zlib.c:2409:in `gzfile_read_raw'
  zlib.c:2694:in `gzfile_read_more'
  zlib.c:2825:in `gzfile_read_all'
  zlib.c:3828:in `rb_gzreader_read'
  /home/runner/.rubies/truffleruby-head/lib/truffle/truffle/cext_ruby.rb:39:in `read'

Reminder - this is an intermittent error...

@eregon
Copy link
Member

eregon commented Oct 21, 2020

The rb_rescue2 TypeError is from

return rb_rescue2(gzfile_read_raw_partial, (VALUE)&ra,
gzfile_read_raw_rescue, (VALUE)&ra,
rb_eEOFError, rb_eNoMethodError, (VALUE)0);

and
VALUE rb_rescue2(VALUE (*b_proc)(ANYARGS), VALUE data1, VALUE (*r_proc)(ANYARGS), VALUE data2, ...) {
VALUE rescued = rb_ary_new();
int total = polyglot_get_arg_count();
int n = 4;
// Callers _should_ have terminated the var args with a VALUE sized 0, but
// some code uses a zero instead, and this can break. So we read the
// arguments using the polyglot api.
for (;n < total; n++) {
VALUE arg = polyglot_get_arg(n);
rb_ary_push(rescued, arg);
}
return cext_rb_rescue2(b_proc, data1, r_proc, data2, rb_tr_unwrap(rescued));
}

and
rescue *rescued => e

Probably we should filter out (VALUE) 0 which is the same as Qfalse from rescued.

@MSP-Greg
Copy link
Author

@eregon - I have no idea, just the messenger... Thanks.

@eregon
Copy link
Member

eregon commented Oct 21, 2020

Yeah I know, just making notes of what I found and how to help fix this :)

@eregon
Copy link
Member

eregon commented Nov 4, 2020

The actual rescue2 error is fixed in 953cc21, thanks for the report.
(the spec for it unfortunately checked for a TypeError going through, and we raised another TypeError due to the bug, which got unnoticed)

I'd like to close this issue, but feel free to reopen or comment if an OutOfMemoryError happens again, the rescue2 might not be the root cause of the OutOfMemoryError.

@eregon eregon closed this as completed Nov 4, 2020
@eregon eregon modified the milestones: 21.0.0, 20.3.0 Nov 4, 2020
@eregon eregon self-assigned this Nov 4, 2020
@MSP-Greg
Copy link
Author

MSP-Greg commented Nov 4, 2020

@eregon

Thanks. Oddly, I just saw the error in nio4r CI yesterday. I knew you'd get to it sometime. If I see it again, I'll reopen.

Question - would you suggest running CI with truffleruby-head as a normal job (not 'allow-failure')?

The question is somewhat clouded since 'allow-failure' doesn't really work in Actions...

@eregon eregon removed this from the 20.3.0 milestone Nov 9, 2020
@eregon
Copy link
Member

eregon commented Nov 9, 2020

I saw it in https://github.com/ruby/setup-ruby/runs/1373979628?check_suite_focus=true

/home/runner/.rubies/truffleruby-head/bin/bundle install --jobs 4
 [ruby] WARNING OutOfMemoryError
 NoMemoryError: failed to allocate memory
   <internal:core> core/string.rb:44:in `byteslice'
   /home/runner/.rubies/truffleruby-head/lib/truffle/stringio.rb:421:in `read'
   /home/runner/.rubies/truffleruby-head/lib/truffle/stringio.rb:533:in `sysread'
   /home/runner/.rubies/truffleruby-head/lib/truffle/truffle/cext.rb:847:in `rb_funcall'
   /home/runner/.rubies/truffleruby-head/lib/truffle/truffle/cext.rb:840:in `rb_funcallv'
   call.c:18:in `rb_funcallv'
   zlib.c:2380:in `gzfile_read_raw_partial'
   /home/runner/.rubies/truffleruby-head/lib/truffle/truffle/cext.rb:1484:in `rb_rescue2'
   exception.c:94:in `rb_rescue2'
   zlib.c:2409:in `gzfile_read_raw'
   zlib.c:2694:in `gzfile_read_more'
   zlib.c:2825:in `gzfile_read_all'
   zlib.c:3828:in `rb_gzreader_read'
   /home/runner/.rubies/truffleruby-head/lib/truffle/truffle/cext_ruby.rb:39:in `read'
   /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/compact_index_client/updater.rb:58:in `block in update'
   /home/runner/.rubies/truffleruby-head/lib/mri/tmpdir.rb:93:in `mktmpdir'
   /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/compact_index_client/updater.rb:31:in `update'
   /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/compact_index_client.rb:98:in `update'
   /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/compact_index_client.rb:85:in `update_and_parse_checksums!'
   /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/fetcher/compact_index.rb:75:in `available?'
   /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/fetcher/compact_index.rb:16:in `call'
   /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/fetcher/compact_index.rb:16:in `available?'
   /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/fetcher.rb:162:in `use_api'
   /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/source/rubygems.rb:388:in `block in api_fetchers'
   /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/source/rubygems.rb:388:in `select'
   /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/source/rubygems.rb:388:in `api_fetchers'
   /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/source/rubygems.rb:393:in `block in remote_specs'
   /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/index.rb:11:in `build'
   /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/source/rubygems.rb:392:in `remote_specs'
   /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/source/rubygems.rb:88:in `specs'
   /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/definition.rb:273:in `block (2 levels) in index'
   /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/definition.rb:271:in `each'
   /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/definition.rb:271:in `block in index'
   /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/index.rb:11:in `build'
   /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/definition.rb:268:in `index'
   /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/definition.rb:258:in `resolve'
   /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/definition.rb:170:in `specs'
   /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/definition.rb:158:in `resolve_remotely!'
   /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/installer.rb:303:in `resolve_if_needed'
   /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/installer.rb:84:in `block in run'
   /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/process_lock.rb:12:in `block in lock'
   <internal:core> core/io.rb:688:in `open'
   /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/process_lock.rb:9:in `lock'
   /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/installer.rb:73:in `run'
   /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/installer.rb:25:in `install'
   /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/cli/install.rb:66:in `run'
   /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/cli.rb:256:in `block in install'
   /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/settings.rb:124:in `temporary'
   /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/cli.rb:255:in `install'
   /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
   /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/vendor/thor/lib/thor/invocation.rb:127:in `invoke_command'
   /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/vendor/thor/lib/thor.rb:399:in `dispatch'
   /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/cli.rb:30:in `dispatch'
   /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/vendor/thor/lib/thor/base.rb:476:in `start'
   /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/cli.rb:24:in `start'
   /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/exe/bundle:46:in `block in <top (required)>'
   /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/friendly_errors.rb:123:in `with_friendly_errors'
   /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/exe/bundle:34:in `<top (required)>'
   <internal:core> core/kernel.rb:401:in `load'
   <internal:core> core/kernel.rb:401:in `load'
   /home/runner/.rubies/truffleruby-head/bin/bundle:23:in `<main>'

And also
https://github.com/ruby/setup-ruby/runs/1370892336?check_suite_focus=true

NoMemoryError: failed to allocate memory
  <internal:core> core/splitter.rb:42:in `split'
  <internal:core> core/string.rb:272:in `split'
  /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/compact_index_client/cache.rb:54:in `block in checksums'
  /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/compact_index_client/cache.rb:53:in `each'
  /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/compact_index_client/cache.rb:53:in `checksums'
  /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/compact_index_client.rb:86:in `update_and_parse_checksums!'
  /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/fetcher/compact_index.rb:75:in `available?'
  /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/fetcher/compact_index.rb:16:in `call'
  /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/fetcher/compact_index.rb:16:in `available?'
  /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/fetcher.rb:162:in `use_api'
  /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/source/rubygems.rb:388:in `block in api_fetchers'
  /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/source/rubygems.rb:388:in `select'
  /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/source/rubygems.rb:388:in `api_fetchers'
  /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/source/rubygems.rb:393:in `block in remote_specs'
  /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/index.rb:11:in `build'
  /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/source/rubygems.rb:392:in `remote_specs'
  /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/source/rubygems.rb:88:in `specs'
  /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/definition.rb:273:in `block (2 levels) in index'
  /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/definition.rb:271:in `each'
  /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/definition.rb:271:in `block in index'
  /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/index.rb:11:in `build'
  /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/definition.rb:268:in `index'
  /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/definition.rb:258:in `resolve'
  /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/definition.rb:170:in `specs'
  /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/definition.rb:158:in `resolve_remotely!'
  /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/installer.rb:303:in `resolve_if_needed'
  /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/installer.rb:84:in `block in run'
  /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/process_lock.rb:12:in `block in lock'
  <internal:core> core/io.rb:688:in `open'
  /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/process_lock.rb:9:in `lock'
  /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/installer.rb:73:in `run'
  /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/installer.rb:25:in `install'
  /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/cli/install.rb:66:in `run'
  /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/cli.rb:256:in `block in install'
  /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/settings.rb:124:in `temporary'
  /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/cli.rb:255:in `install'
  /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
  /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/vendor/thor/lib/thor/invocation.rb:127:in `invoke_command'
  /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/vendor/thor/lib/thor.rb:399:in `dispatch'
  /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/cli.rb:30:in `dispatch'
  /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/vendor/thor/lib/thor/base.rb:476:in `start'
  /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/cli.rb:24:in `start'
  /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/exe/bundle:46:in `block in <top (required)>'
  /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/friendly_errors.rb:123:in `with_friendly_errors'
  /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/exe/bundle:34:in `<top (required)>'
  <internal:core> core/kernel.rb:401:in `load'
  <internal:core> core/kernel.rb:401:in `load'
  /home/runner/.rubies/truffleruby-head/bin/bundle:23:in `<main>'

https://github.com/ruby/setup-ruby/runs/1379242481

  NoMemoryError: failed to allocate memory
    <internal:core> core/string.rb:44:in `byteslice'
    /home/runner/.rubies/truffleruby-head/lib/truffle/stringio.rb:421:in `read'
    /home/runner/.rubies/truffleruby-head/lib/truffle/stringio.rb:533:in `sysread'
    /home/runner/.rubies/truffleruby-head/lib/truffle/truffle/cext.rb:847:in `rb_funcall'
    /home/runner/.rubies/truffleruby-head/lib/truffle/truffle/cext.rb:840:in `rb_funcallv'
    call.c:18:in `rb_funcallv'
    zlib.c:2380:in `gzfile_read_raw_partial'
    /home/runner/.rubies/truffleruby-head/lib/truffle/truffle/cext.rb:1484:in `rb_rescue2'
    exception.c:94:in `rb_rescue2'
    zlib.c:2409:in `gzfile_read_raw'
    zlib.c:2694:in `gzfile_read_more'
    zlib.c:2825:in `gzfile_read_all'
    zlib.c:3828:in `rb_gzreader_read'
    /home/runner/.rubies/truffleruby-head/lib/truffle/truffle/cext_ruby.rb:39:in `read'
    /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/compact_index_client/updater.rb:58:in `block in update'
    /home/runner/.rubies/truffleruby-head/lib/mri/tmpdir.rb:93:in `mktmpdir'
    /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/compact_index_client/updater.rb:31:in `update'
    /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/compact_index_client.rb:98:in `update'
    /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/compact_index_client.rb:85:in `update_and_parse_checksums!'
    /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/fetcher/compact_index.rb:75:in `available?'
    /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/fetcher/compact_index.rb:16:in `call'
    /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/fetcher/compact_index.rb:16:in `available?'
    /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/fetcher.rb:162:in `use_api'
    /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/source/rubygems.rb:388:in `block in api_fetchers'
    /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/source/rubygems.rb:388:in `select'
    /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/source/rubygems.rb:388:in `api_fetchers'
    /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/source/rubygems.rb:393:in `block in remote_specs'
    /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/index.rb:11:in `build'
    /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/source/rubygems.rb:392:in `remote_specs'
    /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/source/rubygems.rb:88:in `specs'
    /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/definition.rb:273:in `block (2 levels) in index'
    /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/definition.rb:271:in `each'
    /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/definition.rb:271:in `block in index'
    /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/index.rb:11:in `build'
    /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/definition.rb:268:in `index'
    /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/definition.rb:258:in `resolve'
    /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/definition.rb:170:in `specs'
    /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/definition.rb:158:in `resolve_remotely!'
    /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/installer.rb:303:in `resolve_if_needed'
    /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/installer.rb:84:in `block in run'
    /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/process_lock.rb:12:in `block in lock'
    <internal:core> core/io.rb:688:in `open'
    /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/process_lock.rb:9:in `lock'
    /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/installer.rb:73:in `run'
    /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/installer.rb:25:in `install'
    /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/cli/install.rb:66:in `run'
    /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/cli.rb:256:in `block in install'
    /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/settings.rb:124:in `temporary'
    /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/cli.rb:255:in `install'
    /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
    /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/vendor/thor/lib/thor/invocation.rb:127:in `invoke_command'
    /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/vendor/thor/lib/thor.rb:399:in `dispatch'
    /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/cli.rb:30:in `dispatch'
    /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/vendor/thor/lib/thor/base.rb:476:in `start'
    /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/cli.rb:24:in `start'
    /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/exe/bundle:46:in `block in <top (required)>'
    /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/lib/bundler/friendly_errors.rb:123:in `with_friendly_errors'
    /home/runner/.rubies/truffleruby-head/lib/gems/gems/bundler-2.1.4/exe/bundle:34:in `<top (required)>'
    <internal:core> core/kernel.rb:401:in `load'
    <internal:core> core/kernel.rb:401:in `load'

https://github.com/ruby/setup-ruby/runs/1380279025?check_suite_focus=true

https://github.com/eregon/setup-ruby-test/runs/1399749440?check_suite_focus=true

https://github.com/eregon/setup-ruby-test/runs/1399903396?check_suite_focus=true

@eregon eregon reopened this Nov 9, 2020
@eregon eregon added the priority label Nov 9, 2020
@eregon
Copy link
Member

eregon commented Nov 14, 2020

It was quite tricky to reproduce, because this OOM actually happens when downloading the full index with all gem versions, and that gets cached under ~/.bundle/cache/compact_index.
But on GitHub Actions, that index is not cached since it's a fresh $HOME every time, if there is no Gemfile.lock, and so that case is downloading it once per workflow job.
That index is 5957796 bytes (5.7MB) compressed, 15513690 bytes (14.8MB) uncompressed, and it's read fully in the Ruby heap here:

content = response.body
if response["Content-Encoding"] == "gzip"
content = Zlib::GzipReader.new(StringIO.new(content)).read

So something in that seems particularly inefficient in memory footprint.

This reproduces it reliably:

# Gemfile
source 'https://rubygems.org'

gem "rake"
gem "path"
gem "json", "2.2.0"
# once is enough
bundle config --local path vendor/bundle

rm -rf Gemfile.lock vendor/bundle ~/.bundle
TRUFFLERUBYOPT="--vm.Xmx1g" DEBUG=true bundle install --jobs 4

With --vm.Xmx2g it seems to work fine
DEBUG=true is optional, it just enables debug messages from Bundler, showing what it downloads.

@eregon
Copy link
Member

eregon commented Nov 14, 2020

Simpler reproduction:

require 'net/http'

# https://index.rubygems.org/versions
Net::HTTP.start('index.rubygems.org', 443, use_ssl: true) do |http|
  headers = {"Accept-Encoding"=>"gzip"}
  request = Net::HTTP::Get.new "/versions", headers

  response = http.request request
  content = response.body
  p content.encoding
  p content.bytesize
  
  raise unless response["Content-Encoding"] == "gzip"
  content = Zlib::GzipReader.new(StringIO.new(content)).read
  p content.bytesize
end
$ ruby --vm.Xmx1g dl_versions.rb                
#<Encoding:ASCII-8BIT>
5957883
[ruby] WARNING OutOfMemoryError
gc.c:30:in `rb_tr_gc_guard': failed to allocate memory (NoMemoryError)
	from gc.c:30:in `rb_gc_force_recycle'
	from zlib.c:1099:in `zstream_run'
	from zlib.c:2697:in `gzfile_read_more'
	from zlib.c:2814:in `gzfile_read_all'
	from zlib.c:3813:in `rb_gzreader_read'
	from /home/eregon/.rubies/truffleruby-dev/lib/truffle/truffle/cext_ruby.rb:39:in `read'
	from dl_versions.rb:14:in `block in <main>'
	from /home/eregon/.rubies/truffleruby-dev/lib/mri/net/http.rb:933:in `start'
	from /home/eregon/.rubies/truffleruby-dev/lib/mri/net/http.rb:606:in `start'
	from dl_versions.rb:4:in `<main>'

@eregon
Copy link
Member

eregon commented Nov 19, 2020

@norswap found out that this results in computing many SubstringRope's of a large ConcatRope (of ConcatRopes)*.
We end up materializing all byte[] for each SubstringRope and so in the end duplicating each byte many times.
We're considering some ways to address that.

I've also found that Net::HTTP can decode gzip-encoded contents itself, and it does so in a streaming fashion which seems to consume much less memory than the naive approach of reading the whole String in memory, wrapping it in a StringIO and passing that to Zlib.
Actually, Net::HTTP does that automatically, but it's disabled by

headers["Accept-Encoding"] = "gzip"

That's trivial to change, just removing that line work so I'll merge that as a short-term workaround for this issue.

Repro:

require 'net/http'

# https://index.rubygems.org/versions
Net::HTTP.start('index.rubygems.org', 443, use_ssl: true) do |http|
  headers = {} # {"Accept-Encoding"=>"gzip"}
  request = Net::HTTP::Get.new "/versions", headers

  response = http.request request
  content = response.body
  p content.encoding
  p content.bytesize
end

graalvmbot pushed a commit that referenced this issue Nov 19, 2020
…index

* That is more memory efficient than reading the whole String in memory,
  wrapping in a StringIO and then using Zlib on it.
* See #2127 (comment)
eregon added a commit to eregon/rubygems that referenced this issue Nov 23, 2020
* Setting the Accept-Encoding header actually disables the automatic
  decompression as documented in Net::HTTP.
  https://github.com/ruby/ruby/blob/79a8ed07650dcbb36ec4b49a22596275e6c0fe23/lib/net/http/response.rb#L105-L107
  https://github.com/ruby/ruby/blob/c5eb24349a4535948514fe765c3ddb0628d81004/lib/net/http/request.rb#L11-L12
* This is also more memory efficient as Net::HTTP decompresses chunk
  by chunk instead of having the entire compressed String in memory
  and also wrapped in a StringIO which is particularly inefficient.
* See oracle/truffleruby#2127 (comment)
  for more details.
eregon added a commit to eregon/rubygems that referenced this issue Dec 4, 2020
* Setting the Accept-Encoding header actually disables the automatic
  decompression as documented in Net::HTTP.
  https://github.com/ruby/ruby/blob/79a8ed07650dcbb36ec4b49a22596275e6c0fe23/lib/net/http/response.rb#L105-L107
  https://github.com/ruby/ruby/blob/c5eb24349a4535948514fe765c3ddb0628d81004/lib/net/http/request.rb#L11-L12
* This is also more memory efficient as Net::HTTP decompresses chunk
  by chunk instead of having the entire compressed String in memory
  and also wrapped in a StringIO which is particularly inefficient.
* See oracle/truffleruby#2127 (comment)
  for more details.
rbotafogo pushed a commit to rbotafogo/truffleruby that referenced this issue Dec 8, 2020
…index

* That is more memory efficient than reading the whole String in memory,
  wrapping in a StringIO and then using Zlib on it.
* See oracle#2127 (comment)
deivid-rodriguez pushed a commit to eregon/rubygems that referenced this issue Jan 7, 2021
* Setting the Accept-Encoding header actually disables the automatic
  decompression as documented in Net::HTTP.
  https://github.com/ruby/ruby/blob/79a8ed07650dcbb36ec4b49a22596275e6c0fe23/lib/net/http/response.rb#L105-L107
  https://github.com/ruby/ruby/blob/c5eb24349a4535948514fe765c3ddb0628d81004/lib/net/http/request.rb#L11-L12
* This is also more memory efficient as Net::HTTP decompresses chunk
  by chunk instead of having the entire compressed String in memory
  and also wrapped in a StringIO which is particularly inefficient.
* See oracle/truffleruby#2127 (comment)
  for more details.
deivid-rodriguez pushed a commit to eregon/rubygems that referenced this issue Jan 7, 2021
* Setting the Accept-Encoding header actually disables the automatic
  decompression as documented in Net::HTTP.
  https://github.com/ruby/ruby/blob/79a8ed07650dcbb36ec4b49a22596275e6c0fe23/lib/net/http/response.rb#L105-L107
  https://github.com/ruby/ruby/blob/c5eb24349a4535948514fe765c3ddb0628d81004/lib/net/http/request.rb#L11-L12
* This is also more memory efficient as Net::HTTP decompresses chunk
  by chunk instead of having the entire compressed String in memory
  and also wrapped in a StringIO which is particularly inefficient.
* See oracle/truffleruby#2127 (comment)
  for more details.
@eregon
Copy link
Member

eregon commented Feb 28, 2021

This should be properly fixed now with ec62fae.

@eregon eregon closed this as completed Feb 28, 2021
@eregon eregon added this to the 21.1.0 milestone Feb 28, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants