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

Compact MJIT methods to single so file #1921

Closed
wants to merge 6 commits into from

Conversation

@k0kubun
Copy link
Member

commented Jul 28, 2018

This is for https://bugs.ruby-lang.org/issues/14490.

Changes

In some conditions, this patch compacts all .o files to one .so file and load all methods from it again to improve memory locality of generated code. As this is an experimental version, MJIT attempts the compaction and reload only when one of following conditions are met:

  • All queued methods are already compiled
  • The number of compiled methods is the same as --jit-max-cache (default: 1000)

Benchmark

In this benchmark, I'll compare following four conditions:

  • trunk: r64082
  • trunk JIT: r64082 w/ --jit
  • single-so JIT: This PR w/ --jit
  • objfcn JIT: This branch w/ --jit, which is shinh's objfcn rebased from this PR
$ uname -a 
Linux bionic 4.15.0-29-generic #31-Ubuntu SMP Tue Jul 17 15:39:52 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

Micro benchmark

Using this script https://gist.github.com/k0kubun/10e6d3387c9ab1b134622b2c9d76ef51, calls some amount of different methods that just return nil. The following tables are its average duration seconds of 3 measurements.

Smaller is better.

1 method (seconds)

trunk trunk JIT single-so JIT objfcn JIT
Time 5.576067774333296 5.915551971666446 5.833641665666619 5.845915191666639
Ratio 1.00x 1.06x 1.05x 1.05x

50 methods (seconds)

trunk trunk JIT single-so JIT objfcn JIT
Time 3.1661167996666677 6.125825928333342 4.135432743666665 3.750358728333348
Ratio 1.00x 1.93x 1.31x 1.18x

1500 methods (seconds)

trunk trunk JIT single-so JIT objfcn JIT
Time 5.971650823666664 19.579182102999994 10.511108153999961 10.854653588999932
Ratio 1.00x 3.28x 1.76x 1.82x

Discourse

Using the same benchmark strategy as https://bugs.ruby-lang.org/issues/14490 with this branch forked from discourse v1.8.11 to support running trunk.

  1. Run ruby script/bench.rb to warm up profiling database
  2. Run RUBYOPT='--jit-verbose=1 --jit-max-cache=10000' RAILS_ENV=profile bin/puma -e production
  3. WAIT 5-15 or so minutes for all jitting to stop so we have no cross talk
  4. Run ab -n 100 http://localhost:9292/
  5. Wait for all new jitting to finish
  6. Run ab -n 100 http://localhost:9292/

Response time (ms)

Here is the response time milliseconds for each percentile. Skipping 99%ile because it's the same as 100%ile in 100 calls.

trunk trunk JIT single-so JIT objfcn JIT
50% 38 45 41 43
66% 39 50 44 44
75% 47 51 46 45
80% 49 52 47 47
90% 50 63 50 52
95% 60 79 52 55
98% 91 114 91 91
100% 97 133 96 99

Ratio (smaller is better)

Here is the response time increase ratio against no-JIT trunk's one. Bold results are ones faster than no-JIT trunk.

trunk trunk JIT single-so JIT objfcn JIT
50% 1.00x 1.18x 1.08x 1.13x
66% 1.00x 1.28x 1.13x 1.13x
75% 1.00x 1.09x 0.98x 0.96x
80% 1.00x 1.06x 0.96x 0.96x
90% 1.00x 1.26x 1.00x 1.04x
95% 1.00x 1.32x 0.87x 0.92x
98% 1.00x 1.25x 1.00x 1.00x
100% 1.00x 1.37x 0.99x 1.02x

@matzbot matzbot closed this in 443f4d5 Jul 28, 2018

@k0kubun k0kubun deleted the k0kubun:single-so branch Jul 29, 2018

@k0kubun k0kubun restored the k0kubun:single-so branch Jul 29, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
1 participant
You can’t perform that action at this time.