Live data from Hacker News

Handles Are the Better Pointers (2018)

floooh.github.com

41–50 of 113 posts

Re: Handles Are the Better Pointers (2018)

#41
post #39

Earlier quoted context omitted.

You are essentially passing an database index key to the getter-function. The only issue I see is that your system has a database integrated into it.

That's probably not a bad way to think about it - in an application that large, dealing with lots of data, needing high performance, it is effectively an application-specific database.

On the other hand, think about the improved cache footprint from using 2-byte object handles rather than full-size 8-byte pointers. If the "user code" keeps a lot of those handles in sequential structs, that is a huge win.

Re: Handles Are the Better Pointers (2018)

#42
post #7

There should be a minor law in the spirit of Greenspun’s tenth rule: Every sufficiently performance-sensitive system eventually grows some version of a slab allocator[1]. There’s really no substitute for packing fixed-sized objects together in N big array chunks. If you can operate in a particular context (or entirely) with N=1, you can substitute handles for pointers. For any reasonable # of objects, those handles c…

Everything I read these days seems to trend towards columnar stores...

I write a mixture of R, Python, C and C++, in that order of prevalence, and mostly for data intensive tasks. After nearly two decades of unlearning loops and implementing instead with FP idioms, vectorization, and matrix multiplies to take advantage of R's strengths, I often have trouble recreating R's performance when I first reimplement in C or C++.

I think it would be beneficial to start with functional programming in more CS programs, they are a much better fit for modern CPU architectures in many ways.

Re: Handles Are the Better Pointers (2018)

#43

MacOS 1.0 in 1984 used handles in order to allow the heap to be coalesced more easily (although locked handles and regular pointers often created islands). Given the first Mac had 128K RAM and no MMU, it was highly necessary at the time.

Of course you mean System 1, not MacOS 1.0. Handles were used all the way through System 7, last released in 1997. Perhaps by then it was more about the legacy than the need. Don't know the physical limits, but a Quadra 950 could support 256MB RAM and more through VM (ramdisk), and of course these later gen machines did have MMUs.

In ye olden days, addressing was probably physical, so being non-multi-tasking ensured the safety of using handles, ie if used properly. IOW the system process was free to clean up the heap and manipulate your pointers b/c your app would only yield at specific points where you aren't holding onto a dereferenced handle.

Re: Handles Are the Better Pointers (2018)

#44
Does this assume that the handle consumers have to somehow 'release' the handle in addition to 'deleting' it? As was explained with an example of delayed release of some deleted but still GPU queued element.

I'm not sure if the suggested generation counter approach is the optimal way to deal with the delayed release. Also, when it comes down to own memory managers, benchmarking is a must. Added complexities may eventually eat up the initial savings.

Re: Handles Are the Better Pointers (2018)

#45
Also helps with arrays that you might wish to realloc. I've sometimes hit the (obvious, in hindsight) bug that you realloc an array and all pointers to members that are held elsewhere suddenly become invalid.

Re: Handles Are the Better Pointers (2018)

#47
post #7

There should be a minor law in the spirit of Greenspun’s tenth rule: Every sufficiently performance-sensitive system eventually grows some version of a slab allocator[1]. There’s really no substitute for packing fixed-sized objects together in N big array chunks. If you can operate in a particular context (or entirely) with N=1, you can substitute handles for pointers. For any reasonable # of objects, those handles c…

Everything I read these days seems to trend towards columnar stores... I write a mixture of R, Python, C and C++, in that order of prevalence, and mostly for data intensive tasks. After nearly two decades of unlearning loops and implementing instead with FP idioms, vectorization, and matrix multiplies to take advantage of R's strengths, I often have trouble recreating R's performance when I first reimplement in C or…

In my Perfect Programming Language That Doesn't Have To Deal With The Problems Of Actually Existing, serialization of data structures into memory is explicitly defined in the language, just as one would define a JSON or Protobuf serialization. One could define a "Point3{x,y,z}", and hypothetically define one array of them in the conventional manner, define another array as a columnar serialization, and potentially even define a compressed data structure right there in memory if that was advantageous.

It opens a wide array of exciting problems and possibilities, if you start thinking of that as something a language should let you twiddle with rather than hard coding it. It seems like a lot of high performance stuff is moving in a direction where this would be advantageous.

(For example, if you compress an array, you lose random access. The language would have to carefully build up capabilities from scratch so it can have a concept of "arrays" that can't be randomly accessed, can only be written in some very particular manner that may even require a "flush" concept, etc. My gut says it ought to be possible, since, after all, we can do it manually, but it would be a very careful operation to disentangle casual assumptions about what data structures can do based on the definition of what data they contain vs. how they are represented in memory, and what capabilities you get from that.)

Re: Handles Are the Better Pointers (2018)

#48

MacOS 1.0 in 1984 used handles in order to allow the heap to be coalesced more easily (although locked handles and regular pointers often created islands). Given the first Mac had 128K RAM and no MMU, it was highly necessary at the time.

Of course you mean System 1, not MacOS 1.0. Handles were used all the way through System 7, last released in 1997. Perhaps by then it was more about the legacy than the need. Don't know the physical limits, but a Quadra 950 could support 256MB RAM and more through VM (ramdisk), and of course these later gen machines did have MMUs. In ye olden days, addressing was probably physical, so being non-multi-tasking ensured…

> the system process was free to clean up the heap and manipulate your pointers b/c your app would only yield at specific points where you aren't holding onto a dereferenced handle.

True, but it was also your job as a developer to not be holding onto those pointers when the memory manager ran.

Re: Handles Are the Better Pointers (2018)

#49
Somehow, my first specialty as a developer was perf analysis, and so all through the Java Golden Era I read every press release about the JVM and subscribed to the ACM SIGPLAN, which had at least one paper on GC in virtually every proceeding that was published, and some occasional cool stuff on interpreter construction. I believe the 4rd technical book I read was The Java Virtual Machine. After Stevens, Comer (3 volumes), and the Java Programming Language.

The original GC had handles. With Hotspot (JDK 1.2, IIRC?) those were gone, and by Java ~8 they were back again, but embedded in the object header, where the pointer indirection presumably hurts less.

In an alternate universe, Sun would have shrunk the memory size for Strings earlier and kept the overhead per object, in which case I suspect the GC stall around 1-2GB would never have happened. But I don't think they had admitted to themselves how Stringly Typed production Java code was, and how UTF-16 wasn't going to last forever.

Re: Handles Are the Better Pointers (2018)

#50

Does this assume that the handle consumers have to somehow 'release' the handle in addition to 'deleting' it? As was explained with an example of delayed release of some deleted but still GPU queued element. I'm not sure if the suggested generation counter approach is the optimal way to deal with the delayed release. Also, when it comes down to own memory managers, benchmarking is a must. Added complexities may event…

The "generation counter" suggested in the article has nothing to do with delayed release, as far as I understand. It is used as a strategy to avoid returning colliding handles close in the time domain, reducing the chances for a collision of the "unique bit pattern", which would allow non-detectable dangling access conditions.
Post reply on HN