Project

General

Profile

Feature #16001

Provide an alias to Kernel#caller_locations(1,1) and Kernel#caller(1,1)

Added by piotrmurach (Piotr Murach) 5 months ago. Updated 3 months ago.

Status:
Open
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-core:93753]

Description

As it is common to use caller_locations(1,1) and caller(1,1), this proposes aliases to help get the previous backtrace frame and improve performance by avoiding getting full backtrace information - a common mistake.

The currently suggestions are:

  • immediate_caller
  • first_caller
  • caller_only

This feature request is based on a conversation with Charles Nutter who says:

This is such a common thing... maybe we need to add something like #caller_only or #caller1 that basically do caller(1,1).

History

Updated by Eregon (Benoit Daloze) 5 months ago

Maybe direct_caller?

Would it call caller_locations(1,1) or caller(1,1)? It can only be one of them.

Updated by piotrmurach (Piotr Murach) 5 months ago

Eregon (Benoit Daloze) wrote:

Maybe direct_caller?

Would it call caller_locations(1,1) or caller(1,1)? It can only be one of them.

That's a very good point. I'd probably lean towards modern API of caller_locations(1,1) if we only used a single alias. However, we could follow a pattern and name caller_locations(1,1) as direct_caller_location and caller(1,1) as direct_caller?

Updated by alanwu (Alan Wu) 5 months ago

Would this be an instance method on Kernel? If so, it seems like a very heavy handed way to shorten something that is already fairly short.
I don't see caller_locations(1,1) or caller(1,1) very frequently, though.

Updated by chrisseaton (Chris Seaton) 5 months ago

If so, it seems like a very heavy handed way to shorten something that is already fairly short

For some reason nobody seems to have commented here what I think is the original motivation for this new method - it's not an alias for brevity, it's a performance thing. Getting the full backtrace is extremely expensive and nobody has a good idea how to make it fully lazy. This new method allows the user to explicitly say that they only need some of the callers.

Updated by piotrmurach (Piotr Murach) 5 months ago

it's not an alias for brevity

Definitely not brevity but clarity certainly. The caller(1,1) seems cryptic as compared to direct_caller which is more expressive.

it's a performance thing. Getting the full backtrace is extremely expensive and nobody has a good idea how to make it fully lazy. This new method allows the user to explicitly say that they only need some of the callers.

That's a very important point. Limiting the full backtrace to the immediate caller will reduce unnecessary allocations.

#6

Updated by piotrmurach (Piotr Murach) 5 months ago

  • Description updated (diff)

Updated by shevegen (Robert A. Heiler) 5 months ago

For some reason nobody seems to have commented here what I think is the original motivation for this
new method - it's not an alias for brevity, it's a performance thing.

I think this may have been lost a bit in the discussion because typically aliases are used to use something
differentially, such as .map versus .collect. At first I also thought that there is something about an
exciting new feature :-) until I noticed that the primary use case may have been related to
speed/performance gains; which is nice (as matz has said: nobody minds if things become faster), but I
was almost hoping for something cool, new and extremely exciting! :D

To the name itself, from the suggestions, I like benoit's direct_caller the most (from the above),
for caller_locations(1,1) - but it may be best to have someone from the core team comment on the
proposal thus far in regards to the speed/performance improvement here.

Updated by Eregon (Benoit Daloze) 5 months ago

chrisseaton (Chris Seaton) wrote:

This new method allows the user to explicitly say that they only need some of the callers.

caller and caller_locations already allow that with the length argument, which is more flexible.
I don't think there would be a significant performance difference between caller_locations(1,1) and immediate_caller, is it?

piotrmurach (Piotr Murach) wrote:

That's a very important point. Limiting the full backtrace to the immediate caller will reduce unnecessary allocations.

Which allocations? Isn't caller_locations(1,1) exactly the same as immediate_caller?
Maybe the only difference is the first one returns an Array and the second just a Thread::Backtrace::Location?
That's probably not significant for performance.

Updated by chrisseaton (Chris Seaton) 5 months ago

Eregon (Benoit Daloze) the answer is in the former version of this issue - 'avoid common beginner mistakes getting full backtrace information' - it improves performance by being obvious when you look in the docs and helping people avoid getting the full backtrace when they only need a bit of it.

Updated by Eregon (Benoit Daloze) 5 months ago

Right, I'm thinking we should just improve the documentation of caller and caller_locations then,
to mention limit should be used when possible, otherwise the impact on performance can be very high.

Updated by piotrmurach (Piotr Murach) 5 months ago

Right, I'm thinking we should just improve the documentation of caller and caller_locations then,
to mention limit should be used when possible, otherwise the impact on performance can be very high.

This is quite a common thing to do and it's not only about performance, though the performance aspect is equally important. I often see code caller[0] used to refer to the immediate frame which means that the whole backtrace is retrieved and then discarded. On the syntax front, this can be likened to having Array#first or Array#last aliases. We could add documentation to explain what array[0] and array[-1] do respectively. However, having additional method calls on an array will help clarify intention. One reason that I use Ruby is its expressiveness and readability. I'm far from wanting to add aliases for the sake of it, they need to match the spirit of Ruby.

#12

Updated by piotrmurach (Piotr Murach) 5 months ago

  • Description updated (diff)

Updated by ko1 (Koichi Sasada) 5 months ago

  • maybe it should be an alias of caller_locations(1, 1).first.
  • do you know good name on it? caller_location(n=1), for example?
  • do people use it on performance important places? I assume it is debugging method. Other than debugging, I think it should be a bad idea because depending on (direct) caller disallows delegation, druby and other techniques.

Updated by matz (Yukihiro Matsumoto) 3 months ago

I prefer caller_location(n=1) or direct_caller. For former, it might be confusing with caller_locations. The latter is straightforward but it is restricted to the direct caller (n=1).

Matz.

Updated by Dan0042 (Daniel DeLorme) 3 months ago

piotrmurach (Piotr Murach) wrote:

This is quite a common thing to do and it's not only about performance, though the performance aspect is equally important. I often see code caller[0] used to refer to the immediate frame which means that the whole backtrace is retrieved and then discarded.

Maybe caller without any arguments should be deprecated? Force people to use e.g. caller(1..) if they really want the full expensive backtrace.

Updated by sawa (Tsuyoshi Sawada) 3 months ago

What about nth_caller(n=1), with some CSS flavor?

Also available in: Atom PDF