Called_from 0.1.0 released

#1

I releaded called_from 0.1.0.

Kernel#caller() is very useful, but very slow.
‘called_from’ solves this problem.

About

‘called_from’ provides called_from() global function
which gets filename and line number of caller.

In short:

require 'called_from'
filename, linenum, function = called_from(1)

is equivarent to:

caller(1)[0] =~ /:(\d+)( in `(.*)')?/
filename, linenum, function = $`, $1, $2

But called_from() is much faster than caller()[0].

Example

require 'called_from'

##
## report not only what sql is queried but also from where query()

is called.
## (this is very convenient for development and debugging)
## in such examle, speed of called_from() is very important.
##
def query(sql)
filename, linenum, function = called_from()
log.debug("#{Time.now}: #{sql} (called from #{filename}:#
{linenum})")
return connection.query(sql)
end

##
## if cache data is older than template file's timestamp,
## refresh cache data.
## it is very important that called_from() is much faster than

caller()[0]
## because speed is necessary for caching.
##
def cache_helper(cache_key)
## check template file’s timestamp
template_filename, linenum, function = called_from()
timestamp = File.mtime(template_filename)
## if cache data is newer than template’s timestamp, return data
data = @cache.get(cache_key, :timestamp=>timestamp)
return data if data
## if cache data is older than template’s timestamp, refresh it
data = yield()
@cache.set(cache_key, data)
return data
end

Benchmark

Here is an example result of benchmark on Merb application.
This shows that called_from() is more than 30 times faster than caller
()[0].

*** n=100000
                             user     system      total

real
caller()[0] 7.920000 0.400000 8.320000
( 8.985343)
caller()[0] (*1) 8.590000 0.420000 9.010000
( 9.804065)
called_from() 0.240000 0.010000 0.250000
( 0.257151)
called_from() (*2) 0.250000 0.000000 0.250000
( 0.268603)

(*1) retrieve filename and line number using pattern match (=~ /:

(\d+)/)
(*2) retrieve filename and line number

Installation

$ sudo gem install called_from

Or

$ tar xzf called_from_X.X.X.tar.gz
$ cd called_from_X.X.X/
$ ruby setup.rb config
$ ruby setup.rb setup
$ sudo ruby setup.rb install

Notice: called_from is implemented in both C-extention and pure Ruby.
C-extention is available on UNIX-like OS and Ruby 1.8.x.

#2

Hi, this is really interesting, but:

$ gem install called_from
Building native extensions. This could take a while…
/Users/tony/.rvm/jruby-1.3.1/lib/ruby/1.8/mkmf.rb:7: JRuby does not
support
native extensions. Check wiki.jruby.org for alternatives.
(NotImplementedError)

We are in the process of moving our codebase onto JRuby. It’s nice you
have
a pure Ruby version available but not if I can’t install the gem on
JRuby.

#3

This is probably the most common usage of Kernel#caller. You’ve made
it more useful and much faster – great extension!

jeremy

#4

I’ve long wished that caller returned an array of BacktraceLine…
likewise
Exception#backtrace.

class BacktraceLine
attr_reader :line, :file, :method, :arguments
end

Not sure if it’s a daydream or an REP…

Judson

#5

On Nov 8, 6:25 pm, makoto kuwata removed_email_address@domain.invalid wrote:

I releaded called_from 0.1.0.http://github.com/kwatch/called_from

Kernel#caller() is very useful, but very slow.
‘called_from’ solves this problem.

Have you submitted this to Ruby core?

Personally I hate the name (b/c it ends in a preposition), but
functionally it seems like an excellent good addition to the core
language.

#6

We are in the process of moving our codebase onto JRuby. It’s nice you
have
a pure Ruby version available but not if I can’t install the gem on
JRuby.

Also fails on 1.9. I know there was a commit recently to allow
Thread.list.map &:backtrace (can’t seem to find it right now).
so that might help.
Thanks!
-r