From: "Eregon (Benoit Daloze) via ruby-core" Date: 2024-04-17T18:54:03+00:00 Subject: [ruby-core:117574] [Ruby master Feature#20335] `Thread.each_caller_location` should accept the same arguments as `caller` and `caller_locations` Issue #20335 has been updated by Eregon (Benoit Daloze). @byroot It's both, but for TruffleRuby I'm pretty sure the first matters much more. These few allocations are no big deal on the JVM, so I would expect similar on JRuby. Walking the stack is also obviously slower with a deeper stack (e.g. Rails), while the object allocations are pretty obvious and simply the number of times the block yielded before the user `break`s/`return`s. I also don't see any valid use case for `Thread.each_caller_location` with a Range with negative begin or end, so that's why I think it's better to prevent it altogether instead of making it a performance trap (i.e. it's `O(stack depth)` instead of the expected `O(number of locations yielded)`). (the only way to make that fast would be to maintain a stack depth field in every frame, but that's overhead in time and memory for every call just for this feature, which seems clearly unreasonable). ---------------------------------------- Feature #20335: `Thread.each_caller_location` should accept the same arguments as `caller` and `caller_locations` https://bugs.ruby-lang.org/issues/20335#change-107974 * Author: byroot (Jean Boussier) * Status: Closed ---------------------------------------- `Thread.each_caller_location` was added to Ruby 3.2 as part of [Feature #16663] and is a very useful API for emitting warnings with a proper source location and similar use cases. However in many of the cases where I used it, or seen it used, it was needed to skip the first, or a couple frames: Examples: Sorbet: https://github.com/Shopify/sorbet/blob/b27a14c247ace7cabdf0f348bfb11fdf0b7e9ab4/gems/sorbet-runtime/lib/types/private/caller_utils.rb#L6-L18 ```ruby def self.find_caller skiped_first = false Thread.each_caller_location do |loc| unless skiped_first skiped_first = true next end next if loc.path&.start_with?("= 1 frames_to_skip -= 1 next end # snipp... ``` ### Proposal I think it would be very useful if `Thread.each_caller_location` accepted the same arguments as `caller` and `caller_locations`: ```ruby #each_caller_location(start = 1, length = nil) #each_caller_location(range) ``` @jeremyevans0 what do you think? -- https://bugs.ruby-lang.org/ ______________________________________________ ruby-core mailing list -- ruby-core@ml.ruby-lang.org To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/