Friday, February 12, 2016

Concurrent Memory Deallocation in the Objective-C Runtime

Mike Ash (comments):

For our own apps we can test and tune the caches to avoid this, but the Objective-C runtime doesn’t have this option. Because the method cache is so critical to performance, and because each entry is relatively small, the runtime doesn’t impose any size limit on the caches, and expands them as necessary to cache all messages that have been sent.

Note that the caches do sometimes get flushed; any time something happens that might cause the cached data to become stale, such as loading new code into the process or modifying a class’s method lists, the appropriate caches are destroyed and allowed to refill.


Note that there is no need to block execution of objc_msgSend for this to work properly. Once the cache free code is sure that nothing is in objc_msgSend at any particular moment after it has replaced the cache pointer, it can go ahead and free the old one. Another thread might call out to objc_msgSend while the old cache pointer is being deallocated, but this new call can’t possibly see the old pointer anymore, so it’s safe.


The purpose of the hypothetical global counter is to track when any thread is within a particular region of code. Threads already have something that tracks what code they’re currently running: the program counter. This is the CPU register which tracks the memory address of the current instruction. Instead of a global counter, we could check each thread’s program counter to see if it’s within objc_msgSend. If all threads are outside, then it’s safe to free the old caches. […] Then objc_msgSend doesn’t have to do anything special at all. It can access the caches directly without worrying about flagging that access.

1 Comment RSS · Twitter

Fairly old article (6 months). I commented on it, thinking it was something fresh :)
Well thanks anyway, I missed it the first time.

Leave a Comment