summaryrefslogtreecommitdiff
path: root/thread.c
AgeCommit message (Collapse)Author
2018-07-08mjit: get rid of memory leak in pause+resume loopnormal
pthread_atfork is not idempotent and repeatedly calling it causes it to register the same hook repeatedly; leading to unbound memory growth. Ruby already has a (confusing-named) internal API for to call in the forked child process: rb_thread_atfork Call the MJIT child_after_fork hook inside that to prevent unbound growth with the following loop: loop do RubyVM::MJIT.pause RubyVM::MJIT.resume end git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63884 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-07-06thread.c (ruby_ppoll): improve timespec to msec conversionnormal
Round up non-zero <1ms timeouts to 1ms and use INT_MAX instead of infinite (-1) for extremely large timeouts. All of our ppoll/select callers are able to handle spurious wakeups, anyways. This avoids excessive CPU usage and busy waits with short timeouts to rb_wait_for_single_fd. CPU usage with the following script is significantly reduced for systems with "#undef HAVE_PPOLL": require 'io/wait' r, w = IO.pipe Thread.new { loop { r.wait_readable(0.000001) } }.join(5) exit!(0) Low-resolution in poll(2) still sucks, though... Note: I don't see the value in making a similar change to time_timeval of a <1us sleep is attempted because of GVL release and syscall latency. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63867 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-07-06thread.c: our fake ppoll implementation is staticnormal
Rename it to "ruby_ppoll" so it looks more obvious in debuggers. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63866 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-07-05unrevert r63852 but keep SIGCHLD path disabled for win32normal
Reading win32/win32.c waitpid implementation, maybe waitpid(-1, ...) on that platform will never conflict with mjit use of waitpid. In any case, I've added WAITPID_USE_SIGCHLD macro to vm_core.h so it can be easy for Linux/BSD users to test (hopefully!) win32-compatible code. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63855 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-07-04Revert r63758 and related commitsnaruse
The change is unstable on Windows. Please re-commit it when it correctly supports Windows. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63852 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-06-27hijack SIGCHLD handler for internal usenormal
Use a global SIGCHLD handler to guard all callers of rb_waitpid. To work safely with multi-threaded programs, we introduce a VM-wide waitpid_lock to be acquired BEFORE fork/vfork spawns the process. This is to be combined with the new ruby_waitpid_locked function used by mjit.c in a non-Ruby thread. Ruby-level SIGCHLD handlers registered with Signal.trap(:CHLD) continues to work as before and there should be no regressions in any existing use cases. Splitting the wait queues for PID > 0 and groups (PID <= 0) ensures we favor PID > 0 callers. The disabling of SIGCHLD in rb_f_system is longer necessary, as we use deferred signal handling and no longer make ANY blocking waitpid syscalls in other threads which could "beat" the waitpid call made by rb_f_system. We prevent SIGCHLD from firing in normal Ruby Threads and only enable it in the timer-thread, to prevent spurious wakeups from in test/-ext-/gvl/test_last_thread.rb with MJIT enabled. I've tried to guard as much of the code for RUBY_SIGCHLD==0 using C "if" statements rather than CPP "#if" so to reduce the likelyhood of portability problems as the compiler will see more code. We also work to suppress false-positives from Process.wait(-1, Process::WNOHANG) to quiets warnings from spec/ruby/core/process/wait2_spec.rb with MJIT enabled. Lastly, we must implement rb_grantpt for ext/pty. We need a MJIT-compatible way of supporting grantpt(3) which may spawn the `pt_chown' binary and call waitpid(2) on it. [ruby-core:87605] [Ruby trunk Bug#14867] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63758 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-06-22thread.c (sleep_timespec): avoid needless update w/o spuriuos checknormal
No point in wasting cycles updating the timespec when not checking on spurious wakeups. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63719 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-06-16thread.c (timeout_prepare): common functionnormal
I can't seem to reproduce the maybe-uninitialized warning on gcc 7 or 8 on Debian sid (7.3.0-16 / 8-20180425-1 r259628), so the guard from r62305 is dropped. * thread.c (timeout_prepare): hoist out from do_select (do_select): ditto (rb_wait_for_single_fd): use timeout_prepare git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63672 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-06-13thread.c: use flags for sleep_* functionsnormal
Same thing as https://bugs.ruby-lang.org/issues/14798 My easily-confused mind gets function call ordering confused easily: sleep_forever(..., TRUE, FALSE); sleep_forever(..., FALSE, TRUE); git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63647 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-05-18thread.c (rb_wait_for_single_fd): do not leak EINTR on timeoutnormal
We must not leak EINTR to users in case a signal hits a ppoll/select caller right when (or just before) the timeout expires. In other words, the timeout should take precedence over the -1 result from ppoll or select. We also try one more time in case of EINTR with a zero timeout, since technically the syscall finished before timing out if it returns EINTR. Regression appeared in r62457 ("thread.c (update_timespec): use timespec_update_expire", commit e6bf0128add103730d8c96727f3ed4dab95088e4) and is not in any stable release of Ruby. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63462 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-05-16thread: reduce GET_THREAD callsnormal
This allows native_sleep to use less stack (80 -> 64 bytes on x86-64) for GVL_UNLOCK_BEGIN/END. For future APIs, we will pass `ec` or `th` around anyways, so the BLOCKING_REGION change should be beneficial in the future. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63448 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-05-15thread.c: enable ppoll for FreeBSD 11.0 and laternormal
FreeBSD 11.0+ supports ppoll, so we may use it after accounting for portability differences in how it treats POLLOUT vs POLLHUP events as mutually exclusive (as documented in the FreeBSD poll(2) manpage). For waiting on high-numbered single FDs, this should put FreeBSD on equal footing with Linux and should allow cheaper FD readiness checking with sleepy GC in the future. * thread.c (USE_POLL, POLLERR_SET): define for FreeBSD 11.0+ (rb_wait_for_single_fd): return all requested events on POLLERR_SET io.c (USE_POLL): define for FreeBSD 11.0+ git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63427 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-05-01use list_head_init instead of open-coding itnormal
While we cannot use LIST_HEAD since r63312, we can at least use list_head_init to make our code more readable. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63314 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-05-01LIST_HEAD as a local variable is a C99ism.shyouhei
Address of a variable whose storage duration is `auto` is _not_ a compile time constant, according to ISO 9899 section 6.4. LIST_HEAD takes such thing. You can't use it to declare local variables. Interestingly, address of a static variable _is_ a compile time constant. So a declaration like `static LIST_HEAD..` is completely legal even in C90. In C99 and newer, this is not a constraint violation. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63312 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-04-30thread.c (vm_living_thread_num): constify vm argnormal
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63307 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-04-21io.c: do not use rb_notify_fd_close close on recycled FDnormal
It is unsafe to release GVL and call rb_notify_fd_close after close(2) on any given FD. FDs (file descriptor) may be recycled in other threads immediately after close() to point to a different file description. Note the distinction between "file description" and "file descriptor". th-1 | th-2 -------------------------------+--------------------------------------- io_close_fptr | rb_notify_fd_close(fd) | fptr_finalize_flush | close(fd) | rb_thread_schedule | | fd reused (via pipe/open/socket/etc) rb_notify_fd_close(fd) | | sees "stream closed" exception | for DIFFERENT file description * thread.c (rb_thread_io_blocking_region): adjust comment for list_del * thread.c (rb_notify_fd_close): give busy list to caller * thread.c (rb_thread_fd_close): loop on busy list * io.c (io_close_fptr): do not call rb_thread_fd_close on invalid FD * io.c (io_reopen): use rb_thread_fd_close Fixes: r57422 ("io.c: close before wait") git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63216 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-04-20thread_sync: redo r62934 to use fork_gennormal
Instead of maintaining linked-lists to store all rb_queue/rb_szqueue/rb_condvar structs; store only a fork_gen serial number to simplify management of these items. This reduces initialization costs and avoids the up-front cost of resetting all Queue/SizedQueue/ConditionVariable objects at fork while saving 8 bytes per-structure on 64-bit. There are no savings on 32-bit. * thread.c (rb_thread_atfork_internal): remove rb_thread_sync_reset_all call * thread_sync.c (rb_thread_sync_reset_all): remove * thread_sync.c (queue_live): remove * thread_sync.c (queue_free): remove * thread_sync.c (struct rb_queue): s/live/fork_gen/ * thread_sync.c (queue_data_type): use default free * thread_sync.c (queue_alloc): remove list_add * thread_sync.c (queue_fork_check): new function * thread_sync.c (queue_ptr): call queue_fork_check * thread_sync.c (szqueue_free): remove * thread_sync.c (szqueue_data_type): use default free * thread_sync.c (szqueue_alloc): remove list_add * thread_sync.c (szqueue_ptr): check fork_gen via queue_fork_check * thread_sync.c (struct rb_condvar): s/live/fork_gen/ * thread_sync.c (condvar_free): remove * thread_sync.c (cv_data_type): use default free * thread_sync.c (condvar_ptr): check fork_gen * thread_sync.c (condvar_alloc): remove list_add [ruby-core:86316] [Bug #14634] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63215 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-04-20simplify altstack and enable reuse with thread cachenormal
Instead of allocating and registering the altstack in different places, do it together to reduce code and improve readability. When thread cache is enabled, storing altstack in rb_thread_t is wasteful and we may reuse altstack in the same pthread. This also lets us clearly allow use of xmalloc to allow GC to recover from ENOMEM. [ruby-core:85621] [Feature #14487] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63213 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-04-20variable.c: fix thread + fork errors in autoloadnormal
This is fairly non-intrusive bugfix to prevent children from trying to reach into thread stacks of the parent. I will probably reuse this idea and redo r62934, too (same bug). * vm_core.h (typedef struct rb_vm_struct): add fork_gen counter * thread.c (rb_thread_atfork_internal): increment fork_gen * variable.c (struct autoload_data_i): store fork_gen * variable.c (check_autoload_data): remove (replaced with get_...) * variable.c (get_autoload_data): check fork_gen when retrieving * variable.c (check_autoload_required): use get_autoload_data * variable.c (rb_autoloading_value): ditto * variable.c (rb_autoload_p): ditto * variable.c (current_autoload_data): ditto * variable.c (autoload_reset): reset fork_gen, adjust indent * variable.c (rb_autoload_load): set fork_gen when setting state * test/ruby/test_autoload.rb (test_autoload_fork): new test [ruby-core:86410] [Bug #14634] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63210 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-04-04refactoring r63073.ko1
* cont.c (root_fiber_alloc): call `ConvertThreadToFiber()` here. `rb_fiber_t` for root_fiber is allocated before running Threads. Fiber objects wrapping this rb_fiber_t for root_fiber are created when root Fiber object is required explicitly (for example, Fiber switching and so on). We can put calling `ConvertThreadToFiber()`. In other words, we can pending `ConvertThreadToFiber()` until Fiber objects are created. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63090 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-04-03Fix Fiber with Thread issue on Windows [Bug #14642]ko1
* cont.c (rb_threadptr_root_fiber_setup): divide into two functions: * rb_threadptr_root_fiber_setup_by_parent(): called by the parent thread. * rb_threadptr_root_fiber_setup_by_child(): called by the created thread. `rb_threadptr_root_fiber_setup()` is called by the parent thread and set fib->fib_handle by ConvertThreadToFiber() on the parent thread on Windows enveironment. This means that root_fib->fib_handle of child thread is initialized with parent thread's Fiber handle. Furthermore, second call of `ConvertThreadToFiber()` for the same thread fails. This patch solves this weird situateion. However, maybe we can make more clean code. * thread.c (thread_start_func_2): call `rb_threadptr_root_fiber_setup_by_child()` at thread initialize routine. * vm.c (th_init): call `rb_threadptr_root_fiber_setup_by_parent()`. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63073 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-03-27thread_sync.c: avoid reaching across stacks of dead threadsnormal
rb_ensure is insufficient cleanup for fork and we must reinitialize all waitqueues in the child process. Unfortunately this increases the footprint of ConditionVariable, Queue and SizedQueue by 8 bytes on 32-bit (16 bytes on 64-bit). [ruby-core:86316] [Bug #14634] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62934 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-03-06thread.c: deadlock in backtracenobu
* thread.c (unblock_function_set): check interrupts just once during raising exceptions, as they are deferred since r16651. [ruby-core:85939] [Bug #14577] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62673 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-03-05thread.c: reset waitq of keeping mutexes in childnormal
We must not maintain references to threads in the parent process in any mutexes held by the child process. * thread_sync.c (rb_mutex_cleanup_keeping_mutexes): new function * thread.c (rb_thread_atfork): cleanup keeping mutexes [ruby-core:85940] [Bug #14578] Fixes: r58604 (commit 3586c9e0876e784767a1c1adba9ebc2499fa0ec2) ("reduce rb_mutex_t size from 160 to 80 bytes on 64-bit") git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62668 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-02-23[DOC] missing docs at toplevelnobu
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62544 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-02-18thread.c: remove redundant USE_SIGALTSTACK #definenormal
thread.c already includes vm_core.h where USE_SIGALTSTACK is defined, #include it explicitly (eval_intern.h already includes it) git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62473 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-02-18thread.c (thread_join_m): handle negative timeouts correctlynormal
Users may subtract and round into negative values when using Thread#join, so clamp the timeout to zero to avoid infinite/long timeouts. Note: other methods such as Kernel#sleep and IO.select will raise on negative values, but Thread#join is an outlier *shrug* This restores Ruby 2.5 (and earlier) behavior. Fixes: r62182 (commit c915390b9530c31b4665aacf27c1adfc114f768e) ("thread.c: avoid FP for Thread#join") git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62462 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-02-18thread.c (double2timespec): adjust to use NULL for infinitynormal
Using: strace ruby -e 'Thread.new { sleep }.join(Float::INFINITY)' Will show a difference in futex() syscall args (not that I'd ever advocate Float::INFINITY as a Thread#join arg :P) git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62461 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-02-18thread.c: stop updating timespec when timeout is unspecifiednormal
No need to waste cycles updating timespecs if there's no expiry. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62458 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-02-18thread.c (update_timespec): use timespec_update_expirenormal
Rename "end" as a appropriate for readability. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62457 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-02-18thread.c: introduce timespec_cmp for timespec comparisonsnormal
This hopefully improves readability when comparing timespecs. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62456 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-02-18thread.c (timespec_update_expire): improve namingnormal
Naming the constant timespec as "end" should make it more apparent is is an absolute time. Update callers, too. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62455 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-02-08thread.c: suppress a warningnobu
* thread.c (do_select): initialize timespec variable to suppress a false positive maybe-uninitialized warning by gcc 7 and 8. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62305 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-02-07thread.c: int32_t instead of suseconds_tnobu
* thread.c (timeval_for): cast to int32_t instead of suseconds_t, which is not defined non-POSIX platforms. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62276 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-02-07fix up r62272nobu
* thread.c (timeval_for): tv_usec is suseconds_t which may be smaller than long. * thread_pthread.c (native_cond_timeout): ret is now used in CLOCK_MONOTONIC case only. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62275 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-02-07thread.c: favor timespec internallynormal
This results in fewer conversion on common modern systems with support for clock_gettime, pthread_cond_timedwait and ppoll. gettimeofday is declared obsolete by POSIX.1-2008, so it is yet another reason to move away from it. This also appears to result in the reduction of compatibility code required for dealing with inconsistent implementations of "struct timeval".tv_sec In the future, this will also result in fewer conversions for kqueue and pselect if we elect to use them. [ruby-core:85416] [Feature #14452] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62272 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-02-04mjit_compile.c: merge initial JIT compilerk0kubun
which has been developed by Takashi Kokubun <takashikkbn@gmail> as YARV-MJIT. Many of its bugs are fixed by wanabe <s.wanabe@gmail.com>. This JIT compiler is designed to be a safe migration path to introduce JIT compiler to MRI. So this commit does not include any bytecode changes or dynamic instruction modifications, which are done in original MJIT. This commit even strips off some aggressive optimizations from YARV-MJIT, and thus it's slower than YARV-MJIT too. But it's still fairly faster than Ruby 2.5 in some benchmarks (attached below). Note that this JIT compiler passes `make test`, `make test-all`, `make test-spec` without JIT, and even with JIT. Not only it's perfectly safe with JIT disabled because it does not replace VM instructions unlike MJIT, but also with JIT enabled it stably runs Ruby applications including Rails applications. I'm expecting this version as just "initial" JIT compiler. I have many optimization ideas which are skipped for initial merging, and you may easily replace this JIT compiler with a faster one by just replacing mjit_compile.c. `mjit_compile` interface is designed for the purpose. common.mk: update dependencies for mjit_compile.c. internal.h: declare `rb_vm_insn_addr2insn` for MJIT. vm.c: exclude some definitions if `-DMJIT_HEADER` is provided to compiler. This avoids to include some functions which take a long time to compile, e.g. vm_exec_core. Some of the purpose is achieved in transform_mjit_header.rb (see `IGNORED_FUNCTIONS`) but others are manually resolved for now. Load mjit_helper.h for MJIT header. mjit_helper.h: New. This is a file used only by JIT-ed code. I'll refactor `mjit_call_cfunc` later. vm_eval.c: add some #ifdef switches to skip compiling some functions like Init_vm_eval. win32/mkexports.rb: export thread/ec functions, which are used by MJIT. include/ruby/defines.h: add MJIT_FUNC_EXPORTED macro alis to clarify that a function is exported only for MJIT. array.c: export a function used by MJIT. bignum.c: ditto. class.c: ditto. compile.c: ditto. error.c: ditto. gc.c: ditto. hash.c: ditto. iseq.c: ditto. numeric.c: ditto. object.c: ditto. proc.c: ditto. re.c: ditto. st.c: ditto. string.c: ditto. thread.c: ditto. variable.c: ditto. vm_backtrace.c: ditto. vm_insnhelper.c: ditto. vm_method.c: ditto. I would like to improve maintainability of function exports, but I believe this way is acceptable as initial merging if we clarify the new exports are for MJIT (so that we can use them as TODO list to fix) and add unit tests to detect unresolved symbols. I'll add unit tests of JIT compilations in succeeding commits. Author: Takashi Kokubun <takashikkbn@gmail.com> Contributor: wanabe <s.wanabe@gmail.com> Part of [Feature #14235] --- * Known issues * Code generated by gcc is faster than clang. The benchmark may be worse in macOS. Following benchmark result is provided by gcc w/ Linux. * Performance is decreased when Google Chrome is running * JIT can work on MinGW, but it doesn't improve performance at least in short running benchmark. * Currently it doesn't perform well with Rails. We'll try to fix this before release. --- * Benchmark reslts Benchmarked with: Intel 4.0GHz i7-4790K with 16GB memory under x86-64 Ubuntu 8 Cores - 2.0.0-p0: Ruby 2.0.0-p0 - r62186: Ruby trunk (early 2.6.0), before MJIT changes - JIT off: On this commit, but without `--jit` option - JIT on: On this commit, and with `--jit` option ** Optcarrot fps Benchmark: https://github.com/mame/optcarrot | |2.0.0-p0 |r62186 |JIT off |JIT on | |:--------|:--------|:--------|:--------|:--------| |fps |37.32 |51.46 |51.31 |58.88 | |vs 2.0.0 |1.00x |1.38x |1.37x |1.58x | ** MJIT benchmarks Benchmark: https://github.com/benchmark-driver/mjit-benchmarks (Original: https://github.com/vnmakarov/ruby/tree/rtl_mjit_branch/MJIT-benchmarks) | |2.0.0-p0 |r62186 |JIT off |JIT on | |:----------|:--------|:--------|:--------|:--------| |aread |1.00 |1.09 |1.07 |2.19 | |aref |1.00 |1.13 |1.11 |2.22 | |aset |1.00 |1.50 |1.45 |2.64 | |awrite |1.00 |1.17 |1.13 |2.20 | |call |1.00 |1.29 |1.26 |2.02 | |const2 |1.00 |1.10 |1.10 |2.19 | |const |1.00 |1.11 |1.10 |2.19 | |fannk |1.00 |1.04 |1.02 |1.00 | |fib |1.00 |1.32 |1.31 |1.84 | |ivread |1.00 |1.13 |1.12 |2.43 | |ivwrite |1.00 |1.23 |1.21 |2.40 | |mandelbrot |1.00 |1.13 |1.16 |1.28 | |meteor |1.00 |2.97 |2.92 |3.17 | |nbody |1.00 |1.17 |1.15 |1.49 | |nest-ntimes|1.00 |1.22 |1.20 |1.39 | |nest-while |1.00 |1.10 |1.10 |1.37 | |norm |1.00 |1.18 |1.16 |1.24 | |nsvb |1.00 |1.16 |1.16 |1.17 | |red-black |1.00 |1.02 |0.99 |1.12 | |sieve |1.00 |1.30 |1.28 |1.62 | |trees |1.00 |1.14 |1.13 |1.19 | |while |1.00 |1.12 |1.11 |2.41 | ** Discourse's script/bench.rb Benchmark: https://github.com/discourse/discourse/blob/v1.8.7/script/bench.rb NOTE: Rails performance was somehow a little degraded with JIT for now. We should fix this. (At least I know opt_aref is performing badly in JIT and I have an idea to fix it. Please wait for the fix.) *** JIT off Your Results: (note for timings- percentile is first, duration is second in millisecs) categories_admin: 50: 17 75: 18 90: 22 99: 29 home_admin: 50: 21 75: 21 90: 27 99: 40 topic_admin: 50: 17 75: 18 90: 22 99: 32 categories: 50: 35 75: 41 90: 43 99: 77 home: 50: 39 75: 46 90: 49 99: 95 topic: 50: 46 75: 52 90: 56 99: 101 *** JIT on Your Results: (note for timings- percentile is first, duration is second in millisecs) categories_admin: 50: 19 75: 21 90: 25 99: 33 home_admin: 50: 24 75: 26 90: 30 99: 35 topic_admin: 50: 19 75: 20 90: 25 99: 30 categories: 50: 40 75: 44 90: 48 99: 76 home: 50: 42 75: 48 90: 51 99: 89 topic: 50: 49 75: 55 90: 58 99: 99 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62197 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-02-04mjit.c: merge MJIT infrastructurek0kubun
that allows to JIT-compile Ruby methods by generating C code and using C compiler. See the first comment of mjit.c to know what this file does. mjit.c is authored by Vladimir Makarov <vmakarov@redhat.com>. After he invented great method JIT infrastructure for MRI as MJIT, Lars Kanis <lars@greiz-reinsdorf.de> sent the patch to support MinGW in MJIT. In addition to merging it, I ported pthread to Windows native threads. Now this MJIT infrastructure can be compiled on Visual Studio. This commit simplifies mjit.c to decrease code at initial merge. For example, this commit does not provide multiple JIT threads support. We can resurrect them later if we really want them, but I wanted to minimize diff to make it easier to review this patch. `/tmp/_mjitXXX` file is renamed to `/tmp/_ruby_mjitXXX` because non-Ruby developers may not know the name "mjit" and the file name should make sure it's from Ruby and not from some harmful programs. TODO: it may be better to store this to some temporary directory which Ruby is already using by Tempfile, if it's not bad for performance. mjit.h: New. It has `mjit_exec` interface similar to `vm_exec`, which is for triggering MJIT. This drops interface for AOT compared to the original MJIT. Makefile.in: define macros to let MJIT know the path of MJIT header. Probably we can refactor this to reduce the number of macros (TODO). win32/Makefile.sub: ditto. common.mk: compile mjit.o and mjit_compile.o. Unlike original MJIT, this commit separates MJIT infrastructure and JIT compiler code as independent object files. As initial patch is NOT going to have ultra-fast JIT compiler, it's likely to replace JIT compiler, e.g. original MJIT's compiler or some future JIT impelementations which are not public now. inits.c: define MJIT module. This is added because `MJIT.enabled?` was necessary for testing. test/lib/zombie_hunter.rb: skip if `MJIT.enabled?`. Obviously this wouldn't work with current code when JIT is enabled. test/ruby/test_io.rb: skip this too. This would make no sense with MJIT. ruby.c: define MJIT CLI options. As major difference from original MJIT, "-j:l"/"--jit:llvm" are renamed to "--jit-cc" because I want to support not only gcc/clang but also cl.exe (Visual Studio) in the future. But it takes only "--jit-cc=gcc", "--jit-cc=clang" for now. And only long "--jit" options are allowed since some Ruby committers preferred it at Ruby developers Meeting on January, and some of options are renamed. This file also triggers to initialize MJIT thread and variables. eval.c: finalize MJIT worker thread and variables. test/ruby/test_rubyoptions.rb: fix number of CLI options for --jit. thread_pthread.c: change for pthread abstraction in MJIT. Prefix rb_ for functions which are used by other files. thread_win32.c: ditto, for Windows. Those pthread porting is one of major works that YARV-MJIT created, which is my fork of MJIT, in Feature 14235. thread.c: follow rb_ prefix changes vm.c: trigger MJIT call on VM invocation. Also trigger `mjit_mark` to avoid SEGV by race between JIT and GC of ISeq. The improvement was provided by wanabe <s.wanabe@gmail.com>. In JIT compiler I created and am going to add in my next commit, I found that having `mjit_exec` after `vm_loop_start:` is harmful because the JIT-ed function doesn't proceed other ISeqs on RESTORE_REGS of leave insn. Executing non-FINISH frame is unexpected for my JIT compiler and `exception_handler` triggers executions of such ISeqs. So `mjit_exec` here should be executed only when it directly comes from `vm_exec` call. `RubyVM::MJIT` module and `.enabled?` method is added so that we can skip some tests which don't expect JIT threads or compiler file descriptors. vm_insnhelper.h: trigger MJIT on method calls during VM execution. vm_core.h: add fields required for mjit.c. `bp` must be `cfp[6]` because rb_control_frame_struct is likely to be casted to another struct. The last position is the safest place to add the new field. vm_insnhelper.c: save initial value of cfp->ep as cfp->bp. This is an optimization which are done in both MJIT and YARV-MJIT. So this change is added in this commit. Calculating bp from ep is a little heavy work, so bp is kind of cache for it. iseq.c: notify ISeq GC to MJIT. We should know which iseq in MJIT queue is GCed to avoid SEGV. TODO: unload some GCed units in some safe way. gc.c: add hooks so that MJIT can wait GC, and vice versa. Simultaneous JIT and GC executions may cause SEGV and so we should synchronize them. cont.c: save continuation information in MJIT worker. As MJIT shouldn't unload JIT-ed code which is being used, MJIT wants to know full list of saved execution contexts for continuation and detect ISeqs in use. mjit_compile.c: added empty JIT compiler so that you can reuse this commit to build your own JIT compiler. This commit tries to compile ISeqs but all of them are considered as not supported in this commit. So you can't use JIT compiler in this commit yet while we added --jit option now. Patch author: Vladimir Makarov <vmakarov@redhat.com>. Contributors: Takashi Kokubun <takashikkbn@gmail.com>. wanabe <s.wanabe@gmail.com>. Lars Kanis <lars@greiz-reinsdorf.de>. Part of Feature 12589 and 14235. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62189 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-02-04thread.c: timespec_for is used only if poll() is usednobu
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62186 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-02-03thread.c (thread_join_m): avoid NUM2TIMET for Bignumnormal
Bignums exceed the range of time_t (or long). git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62184 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-02-03thread.c: avoid FP in C-API time calculationsnormal
FP arithmetic can lose precision in some cases leading to premature wakeup and wasting CPU cycles. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62183 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-02-03thread.c: avoid FP for Thread#joinnormal
FP arithmetic can lose precision in some cases leading to premature wakeup and wasting CPU cycles. Convert to use timeval_* functions for now. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62182 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-02-03thread.c: extract timeval_sub from timeval_update_expirenormal
It can be useful on its own. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62181 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-02-03thread.c (rb_thread_terminate_all): eliminate double2timeval callnormal
No point for a fixed 1s value, and I plan on eliminating double timeouts from internal API. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62179 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-01-30ia64: update ia64-specific code to use execution contexthsbt
This change follows commit 837fd5e494731d7d44786f29e7d6e8c27029806f in '#ifdef __ia64' branches. Noticed as a build failure by John Paul Adrian Glaubitz: ``` cont.c:502:50: error: 'rb_thread_t {aka struct rb_thread_struct}' has no member named 'machine' size = cont->machine.register_stack_size = th->machine.register_stack_end - th->machine.register_stack_start; ^~ ``` The change is trivial: update 'th->machine' usage to 'th->ec->machine'. Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org> git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62106 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-01-27vm_core: use "int" for living_thread_numnormal
We treat this as "int" through the vm_living_thread_num API anyways, and "pid_t" is still 32-bits with glibc on 64-bit platforms. I expect it'll be a long time before anybody needs more than 2 billion native threads. For now, let's save one cacheline on x86-64 (as reported by pahole(1)): before: size: 1288, cachelines: 21, members: 45 after: size: 1280, cachelines: 20, members: 45 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62075 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-01-18rb_threadptr_to_kill marked as NORETURNshyouhei
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@61925 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-01-17Fix typos.hsbt
* node.c: strucutre -> structure * random.c: acquried -> acquired * thread.c: accross -> across git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@61889 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-01-12thread.c (thread_cleanup_func): document small leaknormal
It's minor, I haven't analyzed how fixable it is, but we should at least note it, here. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@61779 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-01-09thread.c: threadptr_pending_interrupt_active_p is staticnormal
It's not used elsewhere. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@61749 b2dd03c8-39d4-4d8f-98ff-823fe69b080e