Improving the performance of callbacks

Whenever a callback is added to the ``CallbackChain``, all of the callbacks in the chain are scanned to check if there are duplicates. I've changed the behavior of the callback chain so that this full scan only happens when the callback is an object filter.

In all other cases (which is the majority of cases), the ``CallbackChain`` implementation checks a hash of callbacks to see if there is a duplicate. This reduces the number of previous callbacks checked to just one per callback to be added.

In addition, adding the hash means that ``matches`` and ``duplicates?`` can be called much less frequently because the hash does the matching automatically.

Here is a gist of the performance before and after this change: https://gist.github.com/wangjohn/5505347