discuss-gnustep
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Custom Allocator and 64-bit pointers, ARC


From: David Chisnall
Subject: Re: Custom Allocator and 64-bit pointers, ARC
Date: Mon, 15 Oct 2018 17:57:13 +0100

On 15 Oct 2018, at 17:12, Tom Sheffler <tom.sheffler@gmail.com> wrote:
> 
> I have an application that models events as objects.  They are frequently 
> allocated and deallocated.  It occurred to me that this class might be a 
> canidate for a custom allocator that allocates objects from a simple pool.
> 
> I found this article (from 2010)
>  
> https://www.mikeash.com/pyblog/friday-qa-2010-12-17-custom-object-allocators-in-objective-c.html
> that describes my situation.
> 
>  - objects allocated and deallocated on same thread
>  - not subclassed
>  - direct subclass of NSObject
> 
> The gist of it is to override allocWithZone: to retrieve objects from a 
> 'cache' (it could be pre-allocated, in my application).  There is a line that 
> sets the ISA Pointer of the new object to the class.

It’s worth making sure you can turn this off.  90% of the time that I’ve 
benchmarked code that uses a custom allocator, it runs faster if you disable it 
because of fragmentation and / or interactions with threading.  Often this is 
code that *did* run faster with the custom allocator when it was written, but 
CPUs and memory allocators became a lot faster over the years.

> I looked through the source code to NSObject.m and libobjc2/runtime.c and it 
> looks like his idea doesn't violate any assumptions.
> 
> But I've been wondering a couple of things about this in the context of ARC 
> and a 64-bit implementation.
> 
>    + (id)allocWithZone: (NSZone *)zone
>    {
>        id obj = GetObjectFromCache();
>        if(obj)
>            *(Class *)obj = self;   // set the ISA pointer to the CLASS
>        else
>            obj = [super allocWithZone: zone];
>        return obj;
>    }

You might want to put something in +initialize to store self in a static and 
then check that self == {cached self}, falling back to the superclass 
implementation.  Note that now your code is about as complex as the fast path 
of a modern memory allocator, so it’s unclear that it would actually make 
things faster (unless you’re on GNU/Linux, because pretty much anything 
outperforms glibc’s default malloc implementation).

> 
> 
> 1.  Is the assignment of the ISA pointer (the first slot in the object) to 
> the CLASS
>    still valid in 2018?  With 64-bit pointers I think some bits are used for 
> refcounts
>    and other things.  Maybe this assignment isn't safe.
> 
>    This article
>        https://sectionfive.net/blog/2015/03/31/arc-in-depth-part-i/
> 
>    says that with "tagged pointers" you need to use a function 
> object_setClass().
> 
>    Is that the right thing for libobjc2 and GNUstep.    

Please use object_setClass().  This is portable and will work in the future 
(and will prevent clang from shouting at you).  Direct assignment does 
currently work, but we make no guarantees that it will continue to do so.

> 
> 2.  Will this work with ARC?  It seems like keeping reference counts of 
> references to instances
>    is independent of alloc/dealloc of objects, so it shouldn't matter.

Maintaining the cache is difficult in ARC, because ARC does not allow 
resurrection.  Your code will need to be compiled without ARC and to implement 
a dealloc that doesn’t call [super dealloc].  This means that you’ll lose out 
on the fast paths for deallocation.  You’ll also have some odd interactions 
with weak pointers.  I’d have to check the code to see exactly what the failure 
modes will be.  I think there’s now an attribute you can stick on a class to 
say that it doesn’t support weak pointers - you’ll probably want to do that.

Oh, and do profile your code!

David




reply via email to

[Prev in Thread] Current Thread [Next in Thread]