From: merch-redmine@... Date: 2020-07-17T23:09:20+00:00 Subject: [ruby-core:99209] [Ruby master Bug#17031] `Kernel#caller_locations(m, n)` should be optimized Issue #17031 has been updated by jeremyevans0 (Jeremy Evans). Reviewing the related code in vm_backtrace.c, you are correct. This occurs both for `caller` and `caller_locations`. The entire internal backtrace object is generated by `rb_ec_backtrace_object`, and then passed to a function that looks at specific parts of it to generate the strings or Thread::Backtrace::Location objects. To fix this would require changing the logic so that `rb_ec_backtrace_object` was passed the starting level and number of frames. ---------------------------------------- Bug #17031: `Kernel#caller_locations(m, n)` should be optimized https://bugs.ruby-lang.org/issues/17031#change-86589 * Author: marcandre (Marc-Andre Lafortune) * Status: Open * Priority: Normal * Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN ---------------------------------------- `Kernel#caller_locations(1, 1)` currently appears to needlessly allocate memory for the whole backtrace. It allocates ~20kB for a 800-deep stacktrace, vs 1.6 kB for a shallow backtrace. It is also much slower for long stacktraces: about 7x slower for a 800-deep backtrace than for a shallow one. Test used: ```ruby def do_something location = caller_locations(1, 1).first end def test(depth, trigger) do_something if depth == trigger test(depth - 1, trigger) unless depth == 0 end require 'benchmark/ips' Benchmark.ips do |x| x.report (:short_backtrace ) {test(800,800)} x.report (:long_backtrace ) {test(800, 0)} x.report (:no_caller_locations) {test(800, -1)} end require 'memory_profiler' MemoryProfiler.report { test(800,800) }.pretty_print(scale_bytes: true, detailed_report: false) MemoryProfiler.report { test(800, 0) }.pretty_print(scale_bytes: true, detailed_report: false) ``` Found when checking memory usage on RuboCop. -- https://bugs.ruby-lang.org/ Unsubscribe: