{"id":13494,"date":"2016-02-12T11:36:02","date_gmt":"2016-02-12T16:36:02","guid":{"rendered":"http:\/\/mjtsai.com\/blog\/?p=13494"},"modified":"2016-02-12T11:36:02","modified_gmt":"2016-02-12T16:36:02","slug":"concurrent-memory-deallocation-in-the-objective-c-runtime","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2016\/02\/12\/concurrent-memory-deallocation-in-the-objective-c-runtime\/","title":{"rendered":"Concurrent Memory Deallocation in the Objective-C Runtime"},"content":{"rendered":"<p><a href=\"https:\/\/www.mikeash.com\/pyblog\/friday-qa-2015-05-29-concurrent-memory-deallocation-in-the-objective-c-runtime.html\">Mike Ash<\/a> (<a href=\"https:\/\/news.ycombinator.com\/item?id=9670666\">comments<\/a>):<\/p>\n<blockquote cite=\"https:\/\/www.mikeash.com\/pyblog\/friday-qa-2015-05-29-concurrent-memory-deallocation-in-the-objective-c-runtime.html\"><p>For our own apps we can test and tune the caches to avoid this, but the Objective-C runtime doesn&rsquo;t have this option. Because the method cache is so critical to performance, and because each entry is relatively small, the runtime doesn&rsquo;t impose any size limit on the caches, and expands them as necessary to cache all messages that have been sent.<\/p><p>Note that the caches <em>do<\/em> 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&rsquo;s method lists, the appropriate caches are destroyed and allowed to refill.<\/p><p>[&#8230;]<\/p><p>Note that there is no need to <em>block<\/em> execution of <code>objc_msgSend<\/code> for this to work properly. Once the cache free code is sure that nothing is in <code>objc_msgSend<\/code> 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 <code>objc_msgSend<\/code> while the old cache pointer is being deallocated, but this new call can&rsquo;t possibly see the old pointer anymore, so it&rsquo;s safe.<\/p><p>[&#8230;]<\/p><p>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&rsquo;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&rsquo;s program counter to see if it&rsquo;s within <code>objc_msgSend<\/code>. If all threads are outside, then it&rsquo;s safe to free the old caches. [&#8230;] Then <code>objc_msgSend<\/code> doesn&rsquo;t have to do anything special at all. It can access the caches directly without worrying about flagging that access.<\/p><\/blockquote>","protected":false},"excerpt":{"rendered":"<p>Mike Ash (comments): For our own apps we can test and tune the caches to avoid this, but the Objective-C runtime doesn&rsquo;t have this option. Because the method cache is so critical to performance, and because each entry is relatively small, the runtime doesn&rsquo;t impose any size limit on the caches, and expands them as [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"apple_news_api_created_at":"","apple_news_api_id":"","apple_news_api_modified_at":"","apple_news_api_revision":"","apple_news_api_share_url":"","apple_news_coverimage":0,"apple_news_coverimage_caption":"","apple_news_is_hidden":false,"apple_news_is_paid":false,"apple_news_is_preview":false,"apple_news_is_sponsored":false,"apple_news_maturity_rating":"","apple_news_metadata":"\"\"","apple_news_pullquote":"","apple_news_pullquote_position":"","apple_news_slug":"","apple_news_sections":"\"\"","apple_news_suppress_video_url":false,"apple_news_use_image_component":false,"footnotes":""},"categories":[4],"tags":[800,571,54,760,138,71],"class_list":["post-13494","post","type-post","status-publish","format-standard","hentry","category-programming-category","tag-concurrency","tag-memory-management","tag-objective-c","tag-objective-c-runtime","tag-optimization","tag-programming"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/13494","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/comments?post=13494"}],"version-history":[{"count":1,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/13494\/revisions"}],"predecessor-version":[{"id":13495,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/13494\/revisions\/13495"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=13494"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=13494"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=13494"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}