pmq20 / ruby-packer

Packing your Ruby application into a single executable.
MIT License
1.56k stars 99 forks source link

[Feature request] Allow packing bundler in standalone mode #137

Open d4rky-pl opened 3 years ago

d4rky-pl commented 3 years ago

Bundler allows creating a standalone install that puts all gems in bundle directory and creates a bundle/bundler/setup.rb that loads all the gems and adds them to the $LOAD_PATH. This allows us to run a script without rubygems enabled.

I built a specifically modified version of our internal CLI tool that uses this behaviour but unfortunately other than overriding RUBYOPT on run time to include --disable=gems I was unable to disable RubyGems inside packed Ruby.

Here's the benchmark. The ht-bundle-standalone version runs require call with both RubyGems and the standalone bundle, hence why it's twice as slow:

➜  benchmark hyperfine -w 2 ./ht-regular ./ht-bundle-standalone ./ht-bundle-standalone-rubyopt
Benchmark #1: ./ht-regular
  Time (mean ± σ):     208.8 ms ±   5.4 ms    [User: 190.8 ms, System: 14.0 ms]
  Range (min … max):   201.7 ms … 223.0 ms    14 runs

Benchmark #2: ./ht-bundle-standalone
  Time (mean ± σ):     379.6 ms ±   6.8 ms    [User: 356.6 ms, System: 18.0 ms]
  Range (min … max):   372.9 ms … 394.0 ms    10 runs

Benchmark #3: ./ht-bundle-standalone-rubyopt
  Time (mean ± σ):     183.2 ms ±   3.9 ms    [User: 167.1 ms, System: 12.9 ms]
  Range (min … max):   177.4 ms … 191.7 ms    15 runs

Summary
  './ht-bundle-standalone-rubyopt' ran
    1.14 ± 0.04 times faster than './ht-regular'
    2.07 ± 0.06 times faster than './ht-bundle-standalone'

As you can see, there's a consistent 15% gain in boot time of the tool. It would be great if ruby-packer supported this out of the box or allowed passing ruby flags other than via RUBYOPT env var.

casper commented 6 months ago

Did you get this to work with --standalone and native C extensions somehow, or any idea how to make it work?

It works great with RUBYOPT and pure Ruby gems, but as soon as you have a native extension among the bundled gems, then you cannot load that gem (fails with "incompatible library version" when loading the .so file).

Is there any way around that problem?