D
Doug Lea
gee.cs.oswego.edu · Personal blog · on HN since 2010
Doug Lea, a computer science professor, shares Java concurrency work and writings, and the dlmalloc memory allocator.
What HN saysCommenters cite his malloc allocator as a classic reference, including its mspaces, and credit his early work for Java's concurrency utilities.
31HN people shared it
20linked it in comments
12stories submitted
265story points
7 months agolast shared
2010people per year2026
Most-shared posts
- 1A Memory Allocator (2000)11 people · 16 points · first shared 2012 · discussion on HN
- 2Using JDK 9 Memory Order Modes7 people · 201 points · first shared 2017 · 36 comments on HN
- 3A Java Fork/Join Framework2 people · 5 points · first shared 2012 · 1 comments on HN
- 4Oopsla14.pdf2 people · first shared 2020
- 5Design Patterns for Avionics Control Systems (1994)1 people · 24 points · first shared 2015 · 3 comments on HN
- 6Doug Lea on the credibility of the Java JCP1 people · 14 points · first shared 2010 · 1 comments on HN
- 7Design Patterns for Avionics Control Systems (1994)1 people · 3 points · first shared 2015 · 1 comments on HN
- 8When to use Java parallel streams1 people · 2 points · first shared 2014 · discussion on HN
- 9Malloc.c1 people · first shared 2016
- 10Misc1 people · first shared 2026
- 11Fj.pdf1 people · first shared 2017
- 12Test1 people · first shared 2020
- 13Intro1 people · first shared 2021
- 14Striped64.java1 people · first shared 2013
- 15Jsr166ydocs1 people · first shared 2010
What HN people wrote when they linked it
HexDecOctBin · 2026-03-28
The classic Doug Lee's memory allocator[1] has explicit heaps by the name of mspaces. OP, were you aware of that; and if yes, what does your solution do better or different than dlmalloc's mspaces?
[1] https://gee.cs.oswego.edu/pub/misc/?C=N;O=D
jillesvangurp · 2021-01-27
Worth noting Doug Lee's early work on adding concurrency to Java. That effort resulted in the java.util.concurrency package but work started in the late nineties and it was available as a separate library. And of course it included a Latch class; and the related CountDownLatch.
http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/i…
Before this stuff landed, Java's concurrency model was a lot less nice to deal with. Good high level abstractions are important. Nice to see the same kind of primitives are being added to C++.
nicioan · 2020-12-13
Reminded me of Doug Lea‘a classic reference on memory allocation http://gee.cs.oswego.edu/dl/html/malloc.html
npsimons · 2013-05-16
Another good read along these lines: http://gee.cs.oswego.edu/dl/html/malloc.html
sshine · 2024-07-04
Amazing survey.
Big fan of property testing.
A particularly big fan of Hedgehog.
I tried writing a Hedgehog-inspired library in Rust and realized how complex the underlying domain is.
For example, the RNG is "splittable" [1][2] which means you can take a deterministic seed and split it in two, e.g. for parallel generators to work independently but still deterministically. The effort that has gone into this feature level is a little numbing. I have an awe similar to that of the "fast inverse square root" hack when I see code like this:
-- | A predefined gamma value's needed for initializing the "root" instances of -- 'Seed'. That is, instances not produced by splitting an already existing -- instance. -- -- We choose: the odd integer closest to @2^64/φ@, where @φ = (1 + √5)/2@ is -- the golden ratio. -- goldenGamma :: Word64 goldenGamma = 0x9e3779b97f4a7c15 when realizing that those numbers don't come easily. [3]
[1]: https://hackage.haskell.org/package/hedgehog-1.4/docs/src/Hedgehog.Int…
[2]: https://gee.cs.oswego.edu/dl/papers/oopsla14.pdf
[3]: https://github.com/hedgehogqa/haskell-hedgehog/issues/191
Wonder why most property-testing libaries don't have features like this?
The libraries require training to use. And they're not that easy to write.
> the current state-of-the-art when it comes to property-based testing is stateful testing via a state machine model and reusing the same sequential state machine model…
johnbender · 2018-10-26
> well-defined atomic primitives
The example I gave is simple and relates to the example of the parent but there are more complex cases for which it is a matter of ongoing research to define a semantics that also admits compiler optimizations.
For example the "well-defined" semantics of (C|C++)11's atomics admits executions where values can materialize out of thin air [1].
The broader point I was hoping to make is that optimizations are great but are not free in a multi-threaded context with data-races (even benign ones). As a consequence the choice to just remove many of them is one that is supported by many people in the weak-memory community and even appears in newer memory models [2]. For example preventing read-write reorderings to prevent causal cycles.
[1] https://www.cl.cam.ac.uk/~pes20/cpp/notes42.html
[2] http://gee.cs.oswego.edu/dl/html/j9mm.html (ruling out po U rf cycles)
xxs · 2017-08-30
Not sure if late for the party... But there is no bug int the impl. BigDecimal.toString(). It's a JVM bug. It blatantly violates the spec of the original JMM (as of Java 1.5 and backported to 1.4)
Not only that but it lacks optimization/intrinsics for String. String.length() should never/ever yield a NPE. I'd expect a process crash than adding metadata for trapping read access faults.
---
Edit: final fields have become ubiquitous even for objects that are safely published [via volatile, synchronizeed, CAS, before thread.start()]. All wrapper classes Integer, Long, etc. have them. Final fields are very much advised to be used and they do help reliability and readability by making it easy to reason about object state (i.e. it doesn't change once seen).
On x86 field fields require a compiler barrier at best as the writes are not reordered. In other words they are extremely cheap. Stuff like AtomicReference.lazySet is next to free and a welcome way to build fast concurrency primitives.
There is Doug Lea's parer[0] for the improved jmm.
There are different versions of ARM architecture with different memory models, overall ARM is considered weak.
v7 has dmb[1] only, and to my knowledge it's not cheap. Skipping dmb requires rather deep analysis, so I wonder if that was the case experienced by the poster.
ARMv8 has store-release fence but I don't know how efficient would be spamming it.
0: http://gee.cs.oswego.edu/dl/html/j9mm.html
1:…
corysama · 2023-09-27
A very old trick for running Lua in your PlayStation 2 game (where the PS2 is a machine with 32MB of RAM and no memory paging) is to hook Lua’s realloc function into the venerable Doug Lea’s Malloc (https://gee.cs.oswego.edu/dl/html/malloc.html) set up to run in arena mode (ONLY_MSPACES? It’s been a decade or two…). That way Lua can fragment the arena all it wants without making a mess of the rest of the tiny address space.
electricshampo1 · 2021-07-06
"Java and JavaScript have avoided introducing weak (acquire/release) synchronizing atomics, which seem tailored for x86."
This is not true for Java; see
http://gee.cs.oswego.edu/dl/html/j9mm.html
https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/lang…
aidenn0 · 2019-11-18
Can someone point me to a glossary for the jargon "acquire, release, plain" access semantics?
[edit]
It does seem to be a general term, but given that TFA is about a Java program, see http://gee.cs.oswego.edu/dl/html/j9mm.html
bassman9000 · 2017-07-19
Neat
For the main tests, programs were run on a 30−CPU Sun
Enterprise 10000 running the Solaris Production 1.2 JVM (an
early version of the 1.2.2_05 release) on Solaris 7.
And slides: http://gee.cs.oswego.edu/dl/cpjslides/fj.pdf
neopallium · 2016-07-03
ptmalloc[0] is developed by Wolfram Gloger and is a modified version of Doug Lea's malloc (aka dlmalloc [1]).
0. http://www.malloc.de/en/
1. http://gee.cs.oswego.edu/pub/misc/malloc.c
majke · 2014-07-12
Implementator's perspective:
* http://gee.cs.oswego.edu/dl/jmm/cookbook.html
strlen · 2010-04-30
> "I just want to remind people that many recent Java success stories are getting lost in all the gloom and doom. Among them are Google Collections, Guice, the JVM languages you referred to earlier, and Android"
Bloch should also highlight java.util.concurrent, which was his and Doug Lea's own work, including upcoming Fork/Join framework (JSR166y): http://gee.cs.oswego.edu/dl/jsr166/dist/jsr166ydocs/
People often overlook this strength. There are quite beautifully designed APIs (built on fairly few primitives e.g., monitors and condition variables) around the difficult problem of shared state concurrency (yet the Fork/Join APIs are also used by the Actor implementation in Scala 2.8 and I believe other Actor implementations).
hayley-patton · 2021-12-27
> Compacting GC needs additional memory to have a room to allocate from, and that amount of memory is substantial unless you want to do more GC than any useful work.
Not in the case of a mark-compact collector, which works entirely in place, or a mark-region collector such as Immix [0], which only copies a small fraction of the heap.
> Also it is not free from fragmentation most of the time - the heap is defragmented only at the moment right after compaction.
An improvement would be to to perform more frequent "partial" collections, such as in the Train algorithm [1]. But some collectors (such as Immix again) avoid compaction until fragmentation is considered bad enough, which seems like a fair compromise.
> And there is internal fragmentation caused by object headers needed to store marking flags for GC - which can consume a huge amount of memory if your data is divided into tiny chunks.
The description of Doug Lea's allocator [2] suggests there are also "object headers" of a sort on allocated data in dlmalloc. You could probably steal mark bits from those headers, but it is commmon to use a separate marking bit/bytemap which is separate to space where objects are allocated, and thus has none of the fragmentation you describe.
[0] https://www.cs.utexas.edu/users/speedway/DaCapo/papers/immix-pldi-2008…
[1] https://beta.cs.au.dk/Papers/Train/train.html
[2] http://gee.cs.oswego.edu/dl/html/malloc.html
jonv · 2021-08-27
Excuse me if I have mis-read your sample program but it looks like you are allocating 16 bytes, then immediately freeing it, again and again in a loop. Since you're not allocating anything else, the allocate and free will happen almost immediately. Malloc() has a run time that can vary a lot depending on what has already been allocated & freed in the past, so this test is not meaningful.
Not only that, but the original doug lea's malloc has a bin specifically for 16 byte allocations: http://gee.cs.oswego.edu/dl/html/malloc.html (the smallest size), so you've specifically chosen a very fast example.
In order to properly test malloc() you have to pre-generate some pseudo random numbers for your allocation sizes, and allocate and free unpredictably. But it's more complicated than that, as in the very occasional case when malloc() has to ask the OS for more heap, that system call may not "finish" until your program first writes to that region of memory... (ie malloc() returns but hasn't finished!)
gosu · 2014-11-16
Probably the fact that it eagerly coalesces newly freed blocks where high performance allocators like tcmalloc and jemalloc use slabs of fixed-sized blocks which are never coalesced. Coalescing will load adjacent blocks into cache, and it probably implies doubly linked lists where slab allocators can get away with cache-friendlier single links or bitmaps etc. (Because you probably have to remove a block from the middle of a free list if you've just coalesced it with a newly freed block). It turns out cache footprint is key for speed and scalability in allocators, so that's a big problem.
I'm embarassed to link this twice in a row now, but at one point I played around with the perf of a couple allocators, including glibc's ptmalloc. I wound up answering exactly this question, at least for some simple use cases:
http://www.andrew.cmu.edu/user/apodolsk/418/finalreport.html.
Comments in ptmalloc sources say they basically stick to the algorithm described here: http://gee.cs.oswego.edu/dl/html/malloc.html.
arielweisberg · 2013-06-26
Counters aren't a good use case for transactional memory because the contention is over very specific sets of memory.
Transactional memory is useful for using a coarse lock to access a wide set of data most of which is not accessed concurrently. You are having the hardware doing the work of lock elision/splitting for you.
This saves you from having the unnecessary mutual exclusion of a regular coarse lock. Or alternatively it saves you from the unnatural acts necessary to get lock splitting or eliminate shared state.
For write mostly counters where performance is an issue you want to have a thread local counters or striped counters.
See http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/jsr166e/Stripe… for an example of how that is done. This counter demonstrates lock splitting as well as an attempt at mechanical sympathy by trying to pick the right stripe based on CAS failures.
throwaway4891a · 2016-11-15
See also:
- http://locklessinc.com/benchmarks_allocator.shtml ($, use as a minimum performance target)
- http://www.nedprod.com/programs/portable/nedmalloc/
- http://phk.freebsd.dk/pubs/malloc.pdf [PDF] (phkmalloc)
- https://github.com/gperftools/gperftools (tcmalloc)
- https://github.com/ivmai/bdwgc/blob/master/malloc.c
- https://github.com/jemalloc/jemalloc
- http://gee.cs.oswego.edu/dl/html/malloc.html (dlmalloc)
mratsim · 2020-10-15
I've been diving into parallel reproducible PRNG [1] in the end I choose to have a PRNG based on xoshiro and seeding process that could take loop iteration variables [2] for reproducibility:
- [1] https://github.com/mratsim/weave/issues/147
- [2] https://github.com/mratsim/trace-of-radiance/blob/99f7d85/trace_of_rad…
- Usage for parallel raytracing: https://github.com/mratsim/trace-of-radiance/blob/99f7d85/trace_of_rad…
Beyond the JAX paper, the Pedigree-based RNG from Leiserson was interesting as well:
- http://supertech.csail.mit.edu/papers/dprng.pdf
- https://pdfs.semanticscholar.org/a32c/3b7b8d5d3ebd594bea2d9c0935c1ac7f…
And Haskell's splittable RNG:
- http://www.hg.schaathun.net/research/Papers/hgs2015jfp.pdf
- http://publications.lib.chalmers.se/records/fulltext/183348/local_1833…
- http://gee.cs.oswego.edu/dl/papers/oopsla14.pdf