<p><code>NSZone</code> is a type representing a memory allocation. <code>NSObject</code> implements the <code>allocWithZone:</code> method to allocate memory in a specific zone, or the default zone if none is provided; <code>alloc</code> is equivalent to <code>allocWithZone:nil</code>.</p>
<p><code>NSZone</code> was originally created to allow custom allocation and deallocation:</p>
<blockquote>
<p>If you are mass-allocating hundreds of cheap objects, you may find the cost of actually allocating space for them becomes significant. Because the standard zone is used all the time, it can become very patchy; deleted objects can leave awkward gaps throughout memory. The allocator for the standard NSZone knows this, and it tries to fill these gaps in preference to grabbing more memory off the system, but this can be costly in time if the zone has grown quite large.</p>
<p>If you want to mass-allocate objects, then, you can create your own zone and tell it not to bother with finding gaps to put new objects in. The allocator can now jump to the end of its allotted memory each time and quickly assign memory to your new objects, saving a lot of effort.</p>
<p>Rumor has it that NSZone could save you deallocation time in the Good Old Days, too, with a method that simply chucks away all the allotted memory without bothering to call deallocators.</p>
</blockquote>
<p>(<a href="https://stackoverflow.com/a/6097110/6253337">source</a>)</p>
<p>However, in modern programs, the zone is <em>always</em> <code>nil</code>. From <a href="https://developer.apple.com/library/archive/releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html#//apple_ref/doc/uid/TP40011226-CH1-SW14" rel="noreferrer">the archived Objective-C documentation</a>:</p>
<blockquote>
<ul>
<li>You cannot use memory zones.<br />
There is no need to use <code>NSZone</code> any more—they are ignored by the modern Objective-C runtime anyway.</li>
</ul>
</blockquote>
<p>Custom allocators have been used in other languages as well, such as by the C++ STL. Given the potential benefits to custom allocation, why was <code>NSZone</code> deprecated? And why do (most) modern languages provide no equivalent?</p>

<implementation><memory-management><objective-c><history>
Why did Objective-C remove `NSZone`?
CC BY-SA 4.0
2024-04-27T14:38:38.860Z
I haven't able to find any announcements in official documentation about the deprecation.  This answer provides a little more context on why NSZone was deprecated, similar to the answers below: https://stackoverflow.com/a/7935382
remcycles
CC BY-SA 4.0
2024-04-27T14:39:12.623Z
This post doesn't answer why NSZone was removed, but it does show how to implement custom allocators on your own:
https://www.mikeash.com/pyblog/friday-qa-2010-12-17-custom-object-allocators-in-objective-c.html

The main idea is to set the class id in the pre-allocated memory you want to use for the object.  Of course, there are other details to worry about, so read the whole post and it's comments if you want to go there.
remcycles
<p>Something else which should be mentioned is that <a href="https://stackoverflow.com/questions/5737887/specifics-of-objective-c-runtime-performance-penalties?noredirect=1&amp;lq=1">Objective-C objects and methods suffer from overhead</a>, because objects are reference counted and <a href="https://www.mikeash.com/pyblog/friday-qa-2009-03-20-objective-c-messaging.html" rel="noreferrer">methods are dynamic (every call is a lookup)</a> among other things. This overhead is such a big problem it was one of the reasons Swift was developed, and <a href="https://www.apple.com/swift/" rel="noreferrer">Apple themselves claim Swift is up to 2.6x faster</a>, in part because its methods are static.</p>
<p>So, if you <em>really</em> need your app to be performant, you're better off not using Objective-C objects at all, instead resorting to C structs or <strong>Objective-C++</strong> classes (in the olden days when <code>NSZone</code> was deprecated, or Swift structs/classes now).</p>
<p>In C/C++ using your own allocator is easy. In C you just replace <code>malloc</code> and <code>free</code> with your custom allocator's equivalent, like <code>MyMalloc</code>/<code>MyFree</code> in <a href="https://sites.cs.ucsb.edu/%7Erich/class/cs170/labs/lab1.malloc/index.html" rel="noreferrer">this lab assignment</a> and <code>context_alloc</code> in <a href="https://github.com/tsoding/arena" rel="noreferrer">tscoding/arena</a>. In C++ you allocate storage via above, then use <a href="https://en.cppreference.com/w/cpp/language/new#Placement_new" rel="noreferrer">placement new</a> to construct a class instance (run its constructor) within this storage (and <a href="https://en.cppreference.com/w/cpp/memory/new/operator_delete" rel="noreferrer">operator <code>delete</code></a> to run the destructor before freeing).</p>
<p>What about Swift? Honestly I'm not sure, since <a href="https://forums.swift.org/t/are-custom-allocators-possible-in-swift/10797" rel="noreferrer">custom allocators</a> are <a href="https://forums.swift.org/t/custom-allocators/58615" rel="noreferrer">currently not possible</a> unless you want to use unsafe bitcasts. In this case you probably also resort to C/C++ code, since although Swift methods are static, Swift classes and even structs are still reference-counted and thus have extra overhead.</p>
<hr />
<p>In the extreme case, instead of calling <code>[[MyObjectiveCClass alloc] init]</code>, you could cast arbitrary preallocated bytes to your class and then call <code>init</code> on that; or in Swift, you could initialize preallocated bytes if necessary and then <a href="https://developer.apple.com/documentation/swift/unsafebitcast(_:to:)" rel="noreferrer"><code>unsafeBitCast(_:to:)</code></a> them to your instance's type. However I'm not sure how this interacts with ARC and other features of the Objective-C/Swift runtime, and I doubt it's defined or stable (could break in future versions of the OS). More likely, if you have very performant code and still need to use Objective-C or Swift objects, you can allocate them all in advance and just avoid allocating in your code's hot path.</p>

CC BY-SA 4.0
2023-07-26T06:17:47.207Z
2023-07-26T06:17:47.207Z
tarzh
CC BY-SA 4.0
2023-07-26T12:04:35.623Z
Custom Swift allocations are absolutely possible without unsafe bitcasts if you restrict yourself to structs instead of classes — you can use the method `bindMemory` to convert an untyped pointer to a typed pointer.
Bbrk24
CC BY-SA 4.0
2024-04-26T13:54:48.747Z
Before you call `init` or other methods on pre-allocated bytes you have to set the class id pointer, as described here:
https://www.mikeash.com/pyblog/friday-qa-2010-12-17-custom-object-allocators-in-objective-c.html
remcycles
<p>Someone thought it was a good idea, maybe it even was a good idea 30 years ago, and now it isn't anymore. That happens.</p>
<p>In modern Objective-C, you just allocate memory, and it is either allocated until it is released, or the allocation failed. In old Objective-C, the developer could create heap zones and allocate memory within a heap zone. I think it was possible to destroy a complete heap zone and then all allocations within that heap zone would be gone, which to me today with modern experience seems a very, very bad idea.</p>
<p>One idea was that allocating memory in zones could provide better performance. Since then, memory allocation performance has been improved through other means. For example, by using a very simple allocator (&quot;simple&quot; in the sense that often very little work needs to be done to allocate or deallocate memory) that doesn't use any memory near the allocated memory for bookkeeping, allocations that are aware of threads, so that the allocator knows &quot;this was allocated in thread X and was never seen by anyone other than thread X, so it can be deallocated without any communication with other threads&quot;, and many other things.</p>
<p>Zones were an attempt at optimisation at the expense of the developer, who either didn't care and didn't get any optimisation, or who cared and spend lots of time and code on performance instead of functionality. It is a much better strategy to leave this kind of optimisation to one library developer who knows everything about memory allocation, so that a million developers don't need to care about it.</p>

CC BY-SA 4.0
2023-07-25T15:39:36.093Z
2023-07-25T15:39:36.093Z
gnasher729
CC BY-SA 4.0
2023-07-26T01:51:24.463Z
Also, you can get a new zone from the OS by starting a new process, but for that to be viable, we needed cheap context switches and IPC first.
Simon Richter
# Why did Objective-C remove `NSZone`?
Posted by: username_0 on 2023-07-13
`NSZone` is a type representing a memory allocation. `NSObject` implements the `allocWithZone:` method to allocate memory in a specific zone, or the default zone if none is provided; `alloc` is equivalent to `allocWithZone:nil`.

`NSZone` was originally created to allow custom allocation and deallocation:

> If you are mass-allocating hundreds of cheap objects, you may find the cost of actually allocating space for them becomes significant. Because the standard zone is used all the time, it can become very patchy; deleted objects can leave awkward gaps throughout memory. The allocator for the standard NSZone knows this, and it tries to fill these gaps in preference to grabbing more memory off the system, but this can be costly in time if the zone has grown quite large.
>
> If you want to mass-allocate objects, then, you can create your own zone and tell it not to bother with finding gaps to put new objects in. The allocator can now jump to the end of its allotted memory each time and quickly assign memory to your new objects, saving a lot of effort.
>
> Rumor has it that NSZone could save you deallocation time in the Good Old Days, too, with a method that simply chucks away all the allotted memory without bothering to call deallocators.

([source](https://stackoverflow.com/a/6097110/6253337))

However, in modern programs, the zone is *always* `nil`. From [the archived Objective-C documentation](https://developer.apple.com/library/archive/releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html#//apple_ref/doc/uid/TP40011226-CH1-SW14):

> * You cannot use memory zones.  
>   There is no need to use `NSZone` any more—they are ignored by the modern Objective-C runtime anyway.

Custom allocators have been used in other languages as well, such as by the C++ STL. Given the potential benefits to custom allocation, why was `NSZone` deprecated? And why do (most) modern languages provide no equivalent?
**Tags:** implementation memory-management objective-c history
> **Comments:**
> **username_1**: I haven't able to find any announcements in official documentation about the deprecation.  This answer provides a little more context on why NSZone was deprecated, similar to the answers below: https://stackoverflow.com/a/7935382  
> **username_1**: This post doesn't answer why NSZone was removed, but it does show how to implement custom allocators on your own:
https://www.mikeash.com/pyblog/friday-qa-2010-12-17-custom-object-allocators-in-objective-c.html

The main idea is to set the class id in the pre-allocated memory you want to use for the object.  Of course, there are other details to worry about, so read the whole post and it's comments if you want to go there.  
---
## 2 answers
### Answer by username_2 on 2023-07-26. Score: 6
Something else which should be mentioned is that [Objective-C objects and methods suffer from overhead](https://stackoverflow.com/questions/5737887/specifics-of-objective-c-runtime-performance-penalties?noredirect=1&lq=1), because objects are reference counted and [methods are dynamic (every call is a lookup)](https://www.mikeash.com/pyblog/friday-qa-2009-03-20-objective-c-messaging.html) among other things. This overhead is such a big problem it was one of the reasons Swift was developed, and [Apple themselves claim Swift is up to 2.6x faster](https://www.apple.com/swift/), in part because its methods are static.

So, if you *really* need your app to be performant, you're better off not using Objective-C objects at all, instead resorting to C structs or **Objective-C++** classes (in the olden days when `NSZone` was deprecated, or Swift structs/classes now).

In C/C++ using your own allocator is easy. In C you just replace `malloc` and `free` with your custom allocator's equivalent, like `MyMalloc`/`MyFree` in [this lab assignment](https://sites.cs.ucsb.edu/%7Erich/class/cs170/labs/lab1.malloc/index.html) and `context_alloc` in [tscoding/arena](https://github.com/tsoding/arena). In C++ you allocate storage via above, then use [placement new](https://en.cppreference.com/w/cpp/language/new#Placement_new) to construct a class instance (run its constructor) within this storage (and [operator `delete`](https://en.cppreference.com/w/cpp/memory/new/operator_delete) to run the destructor before freeing).

What about Swift? Honestly I'm not sure, since [custom allocators](https://forums.swift.org/t/are-custom-allocators-possible-in-swift/10797) are [currently not possible](https://forums.swift.org/t/custom-allocators/58615) unless you want to use unsafe bitcasts. In this case you probably also resort to C/C++ code, since although Swift methods are static, Swift classes and even structs are still reference-counted and thus have extra overhead.

---

In the extreme case, instead of calling `[[MyObjectiveCClass alloc] init]`, you could cast arbitrary preallocated bytes to your class and then call `init` on that; or in Swift, you could initialize preallocated bytes if necessary and then [`unsafeBitCast(_:to:)`](https://developer.apple.com/documentation/swift/unsafebitcast(_:to:)) them to your instance's type. However I'm not sure how this interacts with ARC and other features of the Objective-C/Swift runtime, and I doubt it's defined or stable (could break in future versions of the OS). More likely, if you have very performant code and still need to use Objective-C or Swift objects, you can allocate them all in advance and just avoid allocating in your code's hot path.
> **Comments:**
> **username_0** (2023-07-26): Custom Swift allocations are absolutely possible without unsafe bitcasts if you restrict yourself to structs instead of classes — you can use the method `bindMemory` to convert an untyped pointer to a typed pointer.  
> **username_1** (2024-04-26): Before you call `init` or other methods on pre-allocated bytes you have to set the class id pointer, as described here:
https://www.mikeash.com/pyblog/friday-qa-2010-12-17-custom-object-allocators-in-objective-c.html  
---
### Answer by username_3 on 2023-07-25. Score: 6
Someone thought it was a good idea, maybe it even was a good idea 30 years ago, and now it isn't anymore. That happens.

In modern Objective-C, you just allocate memory, and it is either allocated until it is released, or the allocation failed. In old Objective-C, the developer could create heap zones and allocate memory within a heap zone. I think it was possible to destroy a complete heap zone and then all allocations within that heap zone would be gone, which to me today with modern experience seems a very, very bad idea.

One idea was that allocating memory in zones could provide better performance. Since then, memory allocation performance has been improved through other means. For example, by using a very simple allocator ("simple" in the sense that often very little work needs to be done to allocate or deallocate memory) that doesn't use any memory near the allocated memory for bookkeeping, allocations that are aware of threads, so that the allocator knows "this was allocated in thread X and was never seen by anyone other than thread X, so it can be deallocated without any communication with other threads", and many other things.

Zones were an attempt at optimisation at the expense of the developer, who either didn't care and didn't get any optimisation, or who cared and spend lots of time and code on performance instead of functionality. It is a much better strategy to leave this kind of optimisation to one library developer who knows everything about memory allocation, so that a million developers don't need to care about it.
> **Comments:**
> **username_4** (2023-07-26): Also, you can get a new zone from the OS by starting a new process, but for that to be viable, we needed cheap context switches and IPC first.  
---
