[前][次][番号順一覧][スレッド一覧]

ruby-changes:55070

From: k0kubun <ko1@a...>
Date: Sun, 17 Mar 2019 14:13:43 +0900 (JST)
Subject: [ruby-changes:55070] k0kubun:r67277 (trunk): Change defaults of --jit options

k0kubun	2019-03-17 14:13:38 +0900 (Sun, 17 Mar 2019)

  New Revision: 67277

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=67277

  Log:
    Change defaults of --jit options
    
    * --jit-min-calls: 5 -> 10000
    
    --jit-min-calls=5 obviously can compile non hotspot. This was not a
    problem for MJIT-benchmarks and Optcarrot because the former has very
    few hot optimiziable methods and the latter is likely to trigger
    compilation of hotspot by its intensive calls to optimizable hotspot
    methods and has a very short window to allow limited compilations.
    
    In real-world applications, it has more time to compile more methods and
    it pressures computer's limited resources like icache. We should avoid
    compiling too many methods. Also compiling many methods exhausts time
    budget for compilation in one ruby process lifetime and delays the "JIT
    compaction" of Ruby 2.6.
    
    JVM is known to use 1,500 for C1 (client) compiler and 10,000 for C2
    (server) compiler for -XX:CompileThreshold by default.
    https://docs.oracle.com/javase/8/embedded/develop-apps-platforms/codecache.htm
    
    When things are called X,000 times, requiring 10,000 can eliminate
    compilation of methods which are called only once in these X,000
    iterations and obviously not hotspot. And in fact things like
    unicorn-worker-killer restarts unicorn process every 4096 requests.
    So I felt 10,000 is good for such an environment.
    
    * --jit-max-cache: 1000 -> 100
    
    By the same reason stated above, we should not allow compiling many
    methods especially on MJIT which has a larger overhead due to poor code
    locality by dlopen and whose code is also likely to be bigger by just
    inlining many VM instructions with -O3 rather than directly generating
    low-level code.
    
    In JVM -XX:ReservedCodeCacheSize is 32M for reserved and 48M for maximum.
    --jit-max-cache=1,000 could be closer to it, but in this case MJIT's
    compilation is slow due to data synchronization between threads (to be
    improved in Ruby 2.7 though) and we do not want to delay the "JIT
    compaction" for a long time.
    
    So I chose a really conservative number for this, but by having method
    inlining in the future, wider range could be optimized even with this
    value.
    
    * Optcarrot
    
    --disable-gems, --benchmark Lan_Master.nes 12 attempts.
    No significant impact.
    
    | r67276             | r67276 --jit      | after --jit       |
    |:-------------------|:------------------|:------------------|
    | 50.44369263063978  | 72.87390680773056 | 73.47873485047297 |
    | 50.58788746124193  | 78.06820808947026 | 78.29723420171945 |
    | 50.77509250801378  | 80.29010348842613 | 78.94689404460769 |
    | 50.935361702064405 | 80.42796829926374 | 80.39539527351525 |
    | 51.27352672981195  | 81.98758158033202 | 81.6754198664817  |
    | 51.720715743242124 | 82.00118535811626 | 82.22960569251283 |
    | 51.89643169822524  | 82.2290091613556  | 82.5013636146388  |
    | 51.95895898113868  | 82.37318990939565 | 82.74002377794454 |
    | 52.10124886807968  | 82.48796686037502 | 83.23354941183932 |
    | 52.292280637519376 | 83.0265226541066  | 84.01552618012572 |
    | 52.51856237784144  | 83.8797360318052  | 84.8588319093393  |
    | 52.65076845986818  | 84.80037351256634 | 85.13577756273656 |
    
    * Railsbench
    
    `WARMUP=20000 BENCHMARK=1000 bin/bench` of https://github.com/k0kubun/railsbench.
    It gets closer to --disable=jit.
    
    |           | r67276 | r67276 | after  |
    |           |        | --jit  | --jit  |
    |:----------|:-------|:-------|:-------|
    | req/s     | 891.3  | 742.2  | 841.5  |
    |:----------|:-------|:-------|:-------|
    | 50%ile ms | 1.00   | 1.21   | 1.08   |
    | 66%ile ms | 1.02   | 1.24   | 1.09   |
    | 75%ile ms | 1.03   | 1.28   | 1.10   |
    | 80%ile ms | 1.03   | 1.30   | 1.11   |
    | 90%ile ms | 1.09   | 1.42   | 1.15   |
    | 95%ile ms | 1.32   | 1.65   | 1.27   |
    | 98%ile ms | 4.79   | 2.23   | 1.81   |
    | 99%ile ms | 5.68   | 7.52   | 6.64   |
    |100%ile ms | 6.52   | 9.69   | 8.59   |

  Modified files:
    trunk/mjit.c
    trunk/ruby.c
Index: mjit.c
===================================================================
--- mjit.c	(revision 67276)
+++ mjit.c	(revision 67277)
@@ -563,13 +563,12 @@ system_tmpdir(void) https://github.com/ruby/ruby/blob/trunk/mjit.c#L563
 # undef RETURN_ENV
 }
 
-/* Default permitted number of units with a JIT code kept in
-   memory.  */
-#define DEFAULT_CACHE_SIZE 1000
-/* A default threshold used to add iseq to JIT. */
-#define DEFAULT_MIN_CALLS_TO_ADD 5
-/* Minimum value for JIT cache size.  */
+// Minimum value for JIT cache size.
 #define MIN_CACHE_SIZE 10
+// Default permitted number of units with a JIT code kept in memory.
+#define DEFAULT_MAX_CACHE_SIZE 100
+// A default threshold used to add iseq to JIT.
+#define DEFAULT_MIN_CALLS_TO_ADD 10000
 
 /* Start MJIT worker. Return TRUE if worker is sucessfully started. */
 static bool
@@ -605,7 +604,7 @@ mjit_init(struct mjit_options *opts) https://github.com/ruby/ruby/blob/trunk/mjit.c#L604
     if (mjit_opts.min_calls == 0)
         mjit_opts.min_calls = DEFAULT_MIN_CALLS_TO_ADD;
     if (mjit_opts.max_cache_size <= 0)
-        mjit_opts.max_cache_size = DEFAULT_CACHE_SIZE;
+        mjit_opts.max_cache_size = DEFAULT_MAX_CACHE_SIZE;
     if (mjit_opts.max_cache_size < MIN_CACHE_SIZE)
         mjit_opts.max_cache_size = MIN_CACHE_SIZE;
 
Index: ruby.c
===================================================================
--- ruby.c	(revision 67276)
+++ ruby.c	(revision 67277)
@@ -287,8 +287,8 @@ usage(const char *name, int help) https://github.com/ruby/ruby/blob/trunk/ruby.c#L287
         M("--jit-wait",          "", "Wait until JIT compilation is finished everytime (for testing)"),
         M("--jit-save-temps",    "", "Save JIT temporary files in $TMP or /tmp (for testing)"),
         M("--jit-verbose=num",   "", "Print JIT logs of level num or less to stderr (default: 0)"),
-        M("--jit-max-cache=num", "", "Max number of methods to be JIT-ed in a cache (default: 1000)"),
-        M("--jit-min-calls=num", "", "Number of calls to trigger JIT (for testing, default: 5)"),
+        M("--jit-max-cache=num", "", "Max number of methods to be JIT-ed in a cache (default: 100)"),
+        M("--jit-min-calls=num", "", "Number of calls to trigger JIT (for testing, default: 10000)"),
     };
     int i;
     const int num = numberof(usage_msg) - (help ? 1 : 0);

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]