rails/rails — pull request #4182 by bogdan (2011-12-25 15:09:03+00:00)
Title: AS::Callbacks: improve __define_runner perfomance for non-keyed callbacks.

`__define_runner` is used internally in `set_callback`, `define_callbacks` and `reset_callbacks`

Here is my benchmark for `set_callback` method as it get called more often then any other:

https://gist.github.com/1519380

```
Rehearsal ----------------------------------------------------
New set_callback 0.590000 0.020000 0.610000 ( 0.612187)
Old set_callback 0.840000 0.050000 0.890000 ( 0.890388)
------------------------------------------- total: 1.500000sec

user system total real
New set_callback 0.600000 0.030000 0.630000 ( 0.626086)
Old set_callback 0.810000 0.060000 0.870000 ( 0.875475)
```

About **28% performance improvement**

Second benchmark in the gist above ensures that we didn't lose performance when calling `run_callbacks`:

```
Rehearsal -----------------------------------------------------
New run_callbacks 0.020000 0.000000 0.020000 ( 0.020010)
Old run_callbacks 0.020000 0.000000 0.020000 ( 0.020006)
-------------------------------------------- total: 0.040000sec

user system total real
New run_callbacks 0.020000 0.000000 0.020000 ( 0.019823)
Old run_callbacks 0.020000 0.010000 0.030000 ( 0.019993)
```

### How?

Keyed callbacks have very nice lazy compilation via cache method.
This patch makes non-keyed callbacks to use the same cache method.

So now instead of recompiling the callback chain on each call - we just flush the cache:

``` diff
- body = send("_#{symbol}_callbacks").compile
- runner_method = "_run_#{symbol}_callbacks"
+ name = __callback_runner_name(nil, symbol)
+ undef_method(name) if method_defined?(name)
```