Google TechTalks
Hardware-assisted garbage collection read barriers successfully eliminate pause times across massive enterprise heaps, whereas hardware transactional memory fails to deliver real-world performance gains because application throughput is bottlenecked by data dependencies and I/O rather than lock contention.
AI-assisted summary of Java on a 1000 Cores - Tales of Hardware / Software CoDesign — original source. Check the original for full context.
Source published:
Key ideas
- Azul Systems developed custom Vega RISC processors scaling up to 864 cache-coherent cores in a flat Uniform Memory Access (UMA) topology, explicitly rejecting NUMA due to the lack of spatial data locality in enterprise Java workloads. (0:00)
- Hardware-assisted garbage collection read-barriers and custom user-mode trap vectors enabled concurrent, pauseless collection across heaps up to 600 GB with allocation rates of 35 GB/s, capping pause times to 10–15 milliseconds. (44:54)
- Hardware transactional memory (HTM) for automatic lock elision yielded negligible real-world performance gains because enterprise bottlenecks were overwhelmingly dominated by I/O, databases, and serialization on shared counters. (10:21)
- A specialized Cache Line Zero (CLZ) instruction eliminated read misses when allocating memory into uninitialized addresses, cutting memory bus bandwidth consumption by a measurable 30%. (12:00)
Detailed notes
## Background This talk was delivered by Dr. Cliff Click of Azul Systems, presented at a Google Tech Talk on August 12, 2009, and published by Google TechTalks on YouTube on September 8, 2009. The presentation focuses on the hardware and software co-design principles behind Azul's custom multicore systems, detailing how tailored silicon and runtime integration solved massive garbage collection pause times and scalability bottlenecks for enterprise Java applications.
## TL;DR Dr. Cliff Click outlines the design philosophy and technical evolution of Azul Systems' custom Vega processor architectures, which scaled up to 864 coherent RISC cores to execute massive enterprise Java workloads. He details key architectural innovations, including hardware-assisted read barriers, fast user-mode traps, cache-line zeroing, and a flat Uniform Memory Access (UMA) topology, which collectively enabled pauseless garbage collection across heaps spanning hundreds of gigabytes. The talk candidly covers early hardware bring-up disasters—such as severe silicon defects, third-party IP failures, and exploding power supplies—and contrasts these realities with industry experiments in hardware transactional memory. Click concludes by examining the practical performance tradeoffs between custom silicon and commodity x86 architectures, explaining why targeted runtime features in silicon consistently trump brute-force hardware complexity.
## Atmosphere & style The presentation carries the gritty, irreverent vibe of a seasoned systems veteran recounting war stories straight from the engineering trenches. Dr. Click speaks with rapid-fire enthusiasm, blending deep technical rigor with sharp, self-deprecating humor as he mocks broken silicon, third-party IP blunders, and vendor hesitation. Watching the talk feels like sitting in on an unfiltered, master-level postmortem where immense pride in genuine engineering triumphs stands shoulder-to-shoulder with candid admissions of what failed.
## Bulletin - [00:00](https://www.youtube.com/watch?v=5uljtqyBLxI&t=0s) Azul Systems developed custom Vega RISC processors scaling up to 864 cache-coherent cores in a flat Uniform Memory Access (UMA) topology, explicitly rejecting NUMA due to the lack of spatial data locality in enterprise Java workloads. - [44:54](https://www.youtube.com/watch?v=5uljtqyBLxI&t=2694s) Hardware-assisted garbage collection read-barriers and custom user-mode trap vectors enabled concurrent, pauseless collection across heaps up to 600 GB with allocation rates of 35 GB/s, capping pause times to 10–15 milliseconds. - [10:21](https://www.youtube.com/watch?v=5uljtqyBLxI&t=621s) Hardware transactional memory (HTM) for automatic lock elision yielded negligible real-world performance gains because enterprise bottlenecks were overwhelmingly dominated by I/O, databases, and serialization on shared counters. - [12:00](https://www.youtube.com/watch?v=5uljtqyBLxI&t=720s) A specialized Cache Line Zero (CLZ) instruction eliminated read misses when allocating memory into uninitialized addresses, cutting memory bus bandwidth consumption by a measurable 30%.
## Key takeaways - [00:00](https://www.youtube.com/watch?v=5uljtqyBLxI&t=0s) Enterprise Java business logic lacks predictable spatial locality, making NUMA architectures counterproductive and justifying a flat Uniform Memory Access (UMA) interconnect with memory hashed across controllers. - [06:01](https://www.youtube.com/watch?v=5uljtqyBLxI&t=361s) Uncontended synchronization speed is paramount, as over 99% of locks in real-world Java applications experience no contention. - [10:21](https://www.youtube.com/watch?v=5uljtqyBLxI&t=621s) Hardware Transactional Memory (HTM) confined to L1 caches failed to provide significant application-level scaling because true data dependencies and non-CPU bottlenecks routinely serialize execution. - [19:52](https://www.youtube.com/watch?v=5uljtqyBLxI&t=1192s) Direct hardware bytecode execution was rejected in favor of a clean 3-address RISC microarchitecture optimized specifically as a target for JIT compilers. - [12:00](https://www.youtube.com/watch?v=5uljtqyBLxI&t=720s) The Cache Line Zero (CLZ) instruction eliminates read requests over the memory bus during object allocation, reducing total memory bus bandwidth consumption by 30%. - [14:21](https://www.youtube.com/watch?v=5uljtqyBLxI&t=861s) Optimistic runtime escape detection outperforms static escape analysis on massive enterprise codebases, achieving 60% to 70% stack allocation versus 20% to 30% statically. - [18:01](https://www.youtube.com/watch?v=5uljtqyBLxI&t=1081s) Embedding object metadata directly into the unused upper bits of 64-bit pointers enables speculative subclass checks and method dispatches without dereferencing object headers. - [19:52](https://www.youtube.com/watch?v=5uljtqyBLxI&t=1192s) Azul applied a core co-design philosophy: implement fast detection mechanisms in silicon while delegating complex recovery and fixup logic to software. - [24:11](https://www.youtube.com/watch?v=5uljtqyBLxI&t=1451s) A stateless custom operating system eliminated swap space and legacy drivers while providing bulk virtual-to-physical memory remapping and instant core de-configuration on hardware faults. - [34:17](https://www.youtube.com/watch?v=5uljtqyBLxI&t=2057s) First silicon from TSMC suffered critical defects from faulty licensed third-party IP, requiring limp-home mode, voltage adjustments, and an emergency metal-mask respin utilizing spare substrate transistors. - [56:42](https://www.youtube.com/watch?v=5uljtqyBLxI&t=3402s) Hardware-assisted user-mode read-barrier traps eliminate operating system intervention, patching stale pointers in 40 to 50 CPU cycles and self-healing memory to prevent repeated traps. - [47:08](https://www.youtube.com/watch?v=5uljtqyBLxI&t=2828s) The Pauseless Garbage Collector runs entirely without manual tuning flags, treating sub-par performance or pausing issues as internal collector bugs rather than customer configuration errors. - [01:00:32](https://www.youtube.com/watch?v=5uljtqyBLxI&t=3632s) Safepointing thousands of threads within milliseconds is achieved via hardware-broadcast status bits that force backward branches and poll points into fast user-mode traps. - [01:02:47](https://www.youtube.com/watch?v=5uljtqyBLxI&t=3767s) Azul processors provide symmetric 1-clock uncontended volatile reads and writes, contrasting with x86 where volatile writes require expensive multi-hundred-cycle memory fences.
## Detailed walkthrough ### [00:00](https://www.youtube.com/watch?v=5uljtqyBLxI&t=0s) Introduction and the Azul Systems Architecture
At Google TechTalks, Dr. Cliff Click—Chief JVM Architect at Azul Systems and previously the lead architect on Sun Microsystems' HotSpot server compiler—is introduced to speak about building custom hardware and software for massive concurrency. Presenting slides originally prepared for an ECOOP keynote, Click outlines Azul's approach: designing proprietary chips manufactured by TSMC (Taiwan Semiconductor Manufacturing Company) and assembling coherent systems specifically targeted at running business Java applications.
Azul's architecture fits 54 custom cores per die and connects up to 16 dies into a single cache-coherent system, yielding an 864-core machine. Rather than using Non-Uniform Memory Access (NUMA)—the standard industry choice for high-core-count computers—Azul built a flat, Uniform Memory Access (UMA) architecture. Click explains that business Java performs highly irregular computations where data layout cannot be planned in advance to guarantee cache locality. Instead of having memory that is sometimes fast and sometimes slow depending on physical proximity, Azul chose a design where all memory accesses run at a uniform, predictable speed backed by supercomputer-class interconnect bandwidth (placing them on the top-20 supercomputer bandwidth rankings).
```mermaid flowchart TD accTitle: Azul Systems Die Cache and Memory Hierarchy accDescr: Diagram illustrating 54 cores grouped into clusters of 9 sharing L2 caches, connected to coherent uniform memory.
subgraph Die["Azul Processor Die (54 Cores Total)"] subgraph Cluster1["Core Cluster 1"] C1["9 x RISC Cores<br>(16KB L1 I-Cache + 16KB L1 D-Cache per core)"] L2_1["Shared 2MB L2 Cache"] C1 --> L2_1 end subgraph Cluster6["Core Clusters 2 through 6"] C6["45 x RISC Cores<br>(in 5 clusters of 9 cores)"] L2_6["5 x Shared 2MB L2 Caches<br>(10MB Total)"] C6 --> L2_6 end end
subgraph SystemMem["Uniform Memory Subsystem"] MC["Coherent Interconnect<br>(Up to 16 Dies / 864 Cores)"] DRAM["Commodity 64-bit DRAM<br>(Uniform Memory Access)"] L2_1 --> MC L2_6 --> MC MC --> DRAM end ```
The individual processing cores are simple, classic 3-address RISC engines without replicated execution units or complex branch prediction, operating at lower clock frequencies than standard x86 processors to conserve die area and power. Caches are structured hierarchically: - Each core carries its own 16 KB L1 instruction cache and 16 KB L1 data cache. - Every group of 9 cores shares a 2 MB L2 cache (amounting to 6 L2 caches, or 12 MB total L2 cache per 54-core die). - Individual cores can keep multiple cache-missing loads in flight, while each L2 sustains several concurrent prefetches. - Across a fully loaded 864-core box, well over 2,000 outstanding memory references can remain in flight concurrently without saturating memory bus bandwidth.
---
[03:24](https://www.youtube.com/watch?v=5uljtqyBLxI&t=204s) Business Drivers: The Death of COBOL and the Multicore Era
Click contextualizes Azul's founding around the turn of the century, driven largely by enterprise transitions following the Y2K scare. Enterprise organizations realized their legacy COBOL systems were unmaintainable and aging out, prompting widespread migrations to Java for mission-critical core systems. This created tens of millions of lines of enterprise Java code structured around application servers, Enterprise JavaBeans (EJB), WebLogic, WebSphere, and JBoss. The concurrency model of these workloads was characterized by transaction- and task-level parallelism implemented using thread pools and worklists.
Concurrently, chip designers ran straight into the thermal "power wall." Increasing clock frequencies drove power consumption and heat dissipation to unsustainable levels. Click highlights that as clock scaling stalled—settling around 2.5 GHz for server parts and up to 3.5 GHz for consumer gaming chips—increasing performance required packing more cores onto a die rather than bloating single-thread caches. While this industry trend made a multi-threaded, multicore machine the natural solution for enterprise transactions, Azul faced a demanding commercial hurdle.
> “You must have like a really, really good reason to buy custom hardware for the obvious X86 solution. And, you know, a merely 5x price performance kind of gain is not really good enough to make people jump ship there.”
To justify custom silicon against commodity x86 hardware, Azul had to engineer features directly targeting the core pain points of managed runtimes: - **64-bit Heaps:** Enterprise business applications were already exhausting 32-bit address spaces, so Azul bypassed 32-bit entirely to natively support massive 64-bit heaps. - **Hardware-Assisted Garbage Collection:** Building on ideas dating back 20 years to Symbolics Lisp machines, Azul incorporated dedicated read- and write-barriers directly into the CPU instruction set. - **Commodity DRAM Alignment:** Although software architects requested an extra hardware tag bit per memory word to identify object references, hardware engineers rejected the proposal: “Must have commodity DRAMs, must be 64-bit DRAMs. Cannot have the 5th—65th bit there.”
---
[06:01](https://www.youtube.com/watch?v=5uljtqyBLxI&t=361s) Memory Models, Cache-Speed CAS, and Lock Elision via HTM
Azul also focused on concurrency synchronization. In theory, hardware transactional memory (HTM) was championed in academic circles as an alternative to complex locking schemes, which developers struggled to write correctly without scattering defensive `synchronized` statements throughout codebases. Because businesses will not rewrite massive enterprise applications for speculative language primitives without industry momentum, Azul adapted HTM specifically to perform transparent Java lock elision.
Beyond transactions, Click points out that 99% of locks encountered in real workloads are completely uncontended, making uncontended synchronization latency paramount: - **L1 Cache-Hit Compare-and-Swap (CAS):** On commodity CPUs, an atomic CAS is paired with an expensive bus locking protocol or memory fence that incurs heavy pipeline penalties. Azul designed their memory model so that an uncontended CAS hits directly in the L1 data cache and completes in a single clock cycle. - **Fence-Free CAS Operations:** In standard HotSpot on third-party CPUs, CAS instructions enforce strict memory ordering, often in the wrong location relative to Java monitor enter semantics, forcing the JVM to emit a second separate fence. Azul decoupled ordering from atomicity, providing a fence-free CAS that executes in one pipeline clock. This instruction accelerates lock-free data structures, concurrent collectors, and high-frequency performance counters. - **Explicit Memory Fences:** The architecture adopts a memory model significantly weaker than x86 or SPARC TSO (Total Store Order), allowing aggressive instruction reordering while relying on explicit compiler-emitted fences to conform strictly to the Java Memory Model specification.
```mermaid flowchart TD accTitle: HTM Speculative Execution and Software Fallback Flow accDescr: Flowchart showing how HTM executes speculative operations in L1, commits silently, or aborts to software fallback.
Start["Enter Critical Section"] --> Spec["Execute SPECULATE Opcode<br>(Set L1 spec-read / spec-write bits)"] Spec --> Exec["Run Speculative Critical Section<br>(L2 Cache remains completely unaware)"]
Exec --> Conflict{"L1 Line Eviction<br>or Core Conflict?"}
Conflict -- "No Conflict" --> Commit["Execute COMMIT Opcode<br>(Clear spec bits, make writes permanent)"]
Conflict -- "Conflict / Eviction" --> Abort["Execute ABORT Opcode"] Abort --> Flush["Invalidate Speculative L1 Cache Lines<br>(All pending writes discarded)"] Flush --> Fallback["Software Recovery Handler<br>(Retry transaction or acquire heavyweight OS lock)"] ```
Azul integrated HTM support from day one via three dedicated instructions: `speculate`, `commit`, and `abort`. The hardware engineering team placed strict architectural constraints on where HTM could touch the design:
> “The L2 is a—what Intel calls the LLC, the Last Level Cache. It’s the point of coherency between the hundreds of hundreds CPUs in the system. That is already one of the most complicated parts in the system. There’s no freaking way you’re going to go in there and add some new weird-ass thing that no one knows if it’s going to help or not.”
Consequently, HTM is implemented strictly inside the L1 cache using speculative read and write tracking tag bits, leaving the shared L2 coherency fabric completely unaware of ongoing transactions: - When a core runs the `speculate` instruction, subsequent cache line reads and writes mark speculative tag bits in the L1. - If a tagged line is invalidated, evicted due to capacity, or contested by another core, the transaction immediately aborts. - On abort, all speculatively written lines in L1 are thrown out, and the core jumps to a software recovery routine. - The software handler can retry the speculative section or fall back to acquiring a heavyweight lock.
Although the hardware reliably executes speculative transactions lasting thousands of instructions, Click concludes with a candid realization: in real-world deployments, lock elision failed to yield significant speedups on legacy "dusty-deck" enterprise code.
[10:21](https://www.youtube.com/watch?v=5uljtqyBLxI&t=621s) The Limits of Transactional Memory and the Reality of GC Pauses
Cliff Click explains that while hardware transactional memory sounds appealing in theory, in large concurrent programs it rarely delivers the breakthrough of allowing more threads to run in parallel. The fundamental roadblock is the presence of true data dependencies. More often than not, these dependencies are caused by trivial code artifacts: an unread global performance counter that gets incremented inside an otherwise isolated transaction instantly forces serialization. Because no transactional memory system—hardware or software—can magically bypass a true data dependency, developers are ultimately forced to go into the codebase and manually refactor it. Cliff points out the irony of that requirement: once a team is already willing to alter their source code to make it transactional-memory friendly, they might as well invest that effort into standard fine-grained locking instead. Cliff notes that he already open-sourced practical concurrency alternatives in his `high-scale-lib` library.
Furthermore, transactional memory fails to address the actual operational bottleneck of massively parallel enterprise architectures. On high core-count machines, application scaling is bounded by garbage collection rather than locking. As workloads scale and heap sizes grow, stop-the-world GC pause times become intolerable, leaving teams with no choice but to chop their applications into clusters of smaller JVM instances rather than scaling vertically on big iron. Cliff contrasts Azul’s transactional hardware support with contemporary efforts like Sun Microsystems’ Rock processor. While Azul's implementation was far more robust than Rock—Azul did not abort transactions for nested locks, function calls, or TLB misses—Cliff remains pragmatic about its overall impact on enterprise workloads. As Cliff puts it:
> “It's not going to save the world.”
- Incremented shared counters represent true data dependencies that break transaction commit pipelines across concurrent threads. - Sun’s Rock processor notoriously aborted hardware transactions on standard operations such as TLB misses, nested locks, and basic function calls. - GC pause times, rather than lock contention, represent the primary driver forcing enterprise Java architectures into clustered deployments.
---
[12:00](https://www.youtube.com/watch?v=5uljtqyBLxI&t=720s) Tackling the Memory Bandwidth Bottleneck: Cache-Line Zeroing and Loose Ordering
Looking back to the 2000–2002 architectural design phase, the Azul team faced a glaring hardware constraint: memory bandwidth saturation. If a chip packs dozens of cores (such as 54 cores), each core generates its own distinct working set, suffers its own L1 cache misses, and competes for the bus. To keep the memory pipeline from collapsing under standard Java memory patterns, Azul introduced dedicated hardware features. In standard bump-pointer garbage collectors, the thread continuously allocates into brand-new addresses that have not been referenced by that core since the prior collection cycle. Normally, writing to a new object triggers a cache read miss to bring the uninitialized line from main memory into L1, only for the CPU to immediately overwrite the entire line with zeros before filling it with object payload data.
To eliminate that wasted read traffic, Azul implemented the `CLZ` (Cache Line Zero) instruction. `CLZ` performs just-in-time zeroing directly inside the L1 cache without issuing a read transaction to main memory, securing cache coherence without pulling unneeded bytes over the memory bus. Because the generational hypothesis holds true and most young objects die quickly in cache, this single architectural optimization delivered an immediate, massive payoff. Alongside a very loose memory model that allows the hardware wide latitude to reorder memory operations to mask latency, `CLZ` provided substantial bandwidth relief. As Cliff emphasizes:
> “It turns out that that, in practice, very measurable, very real 30% reduction in bandwidth.”
```mermaid flowchart TD accTitle: Standard Allocation vs CLZ Hardware Allocation accDescr: Flow comparison showing how traditional allocation wastes memory bus reads while CLZ allocates directly in cache.
subgraph Standard["Standard Bump Pointer Allocation"] A["Thread allocates at new address"] --> B["Cache miss: Read line from RAM"] B --> C["Write zeros over fetched data"] C --> D["Write object fields"] end
subgraph AzulCLZ["Azul Hardware CLZ Allocation"] E["Thread allocates at new address"] --> F["CLZ instruction zeros line directly in L1"] F --> G["No read traffic sent across memory bus"] G --> H["Write object fields into hot cache"] end ```
- Bump-pointer allocation causes a continuous stream of cache misses for newly claimed heap space. - The `CLZ` instruction allocates and zeros cache lines in L1 without reading stale data from main memory. - Eliminating unneeded memory reads during object allocation reduced memory bus bandwidth consumption by roughly 30%. - A relaxed, loose memory model grants the hardware pipeline deep opportunities to reorder operations and cover bandwidth latencies.
---
[14:21](https://www.youtube.com/watch?v=5uljtqyBLxI&t=861s) Escape Detection vs. Escape Analysis
When asked to clarify the distinction between escape detection and compiler escape analysis, Cliff details the vast operational gap between static compile-time proofs and runtime optimistic execution. Traditional escape analysis relies on conservative static compiler passes. If the compiler can mathematically prove that an allocated object never escapes its local lexical scope or analysis boundary, it can allocate that object directly on the thread stack, turning allocation and deallocation into near-zero-cost stack pointer adjustments. While this works well on small benchmarks, it breaks down on enterprise-grade business logic. Enterprise applications are far too large and complex for whole-program static proofs; the analysis rapidly becomes conservative, encounters unknown pointer paths, and yields virtually zero stack allocation for big applications.
Azul bypassed this limitation by replacing static compile-time escape analysis with optimistic runtime escape detection. Under escape detection, the runtime speculatively allocates objects on the stack under the assumption that they will have stack lifetimes, requiring no expensive pre-analysis. The CPU hardware and runtime monitor subsequent pointer stores: if code attempts to store an object reference outside the thread's local stack purvey, the hardware detects the escaping pointer and triggers a post-facto fix-up to move the object onto the global heap. Because the overwhelming majority of short-lived objects never escape, this optimistic gambit succeeds at an extraordinary rate compared to standard static approaches. As Cliff explains:
> “In turns out in practice, for these big up servers, we can get between 60%, 70% of all objects stack allocated, whereas the good escape analysis are, like, well under 20 or 30%.”
- Static escape analysis degrades severely on large, multi-million-line codebases, yielding low single-digit percentage gains. - Runtime escape detection requires zero ahead-of-time static proofs, optimistically betting that objects do not escape. - Hardware checks during pointer writes intercept escaping references and fix them up dynamically. - Stack-allocated objects eliminate both memory reads and memory writes to main RAM by recycling hot cache lines.
---
[16:08](https://www.youtube.com/watch?v=5uljtqyBLxI&t=968s) Memory Striping and Abandoning NUMA in Business Logic
Cliff shifts to Azul’s chip-level memory subsystem, framing the processor strictly as a high-throughput machine rather than an uber-fast single-threaded core. Instead of betting on massive caches and deep single-core speculative execution, Azul deployed large numbers of lightweight cores, each spewing independent cache misses that the memory subsystem satisfies concurrently. Each chip integrates four distinct memory controllers. To prevent any single controller from becoming a pipeline bottleneck, physical memory accesses are fine-grained striped across all controllers and chips using a semi-random hash. Successive memory accesses light up every controller in turn, distributing the electrical and bandwidth load evenly across the entire machine.
This architecture arose from a fundamental realization regarding enterprise Java applications: unlike scientific computing, business logic applications exhibit zero sane spatial memory locality. It is impossible to isolate a specific heap chunk and assign it locally to a single core. With memory accesses uniformly scattered across the machine, any traditional Non-Uniform Memory Access (NUMA) scheme breaks down. In a multi-socket system, fifteen out of every sixteen memory references inevitably target remote controllers on other chips. Attempting to accelerate the rare 1/16th local case yields negligible system-level performance while dramatically increasing hardware and software complexity. Azul consequently abandoned NUMA entirely, intentionally routing local memory transactions off-chip and back on to guarantee that local and remote memory operations carry the exact same latency and cost. As Cliff points out:
> “Since there's no sane layout, if it's just random, then 15/16ths of your memory is on the other memory controllers on the other chip, right, so remote.”
- Each Azul processor integrates four independent on-die memory controllers. - Memory addresses are hashed and striped across all chips to eliminate hot-spotting on any individual bus or controller. - Enterprise Java features no meaningful data locality, rendering NUMA optimizations ineffective. - Azul opted for a flat Uniform Memory Access (UMA) latency profile where local memory loops off-chip, matching remote latency costs evenly across the board. - On-chip caches are prioritized strictly for stack frames and newly allocated young-generation objects.
---
[18:01](https://www.youtube.com/watch?v=5uljtqyBLxI&t=1081s) Pointer Metadata, Safepointing at Scale, and Hardware/Software Co-Design
To squeeze out further efficiencies, Azul engineered short cache lines, which mitigated bandwidth waste and eliminated concurrency-destroying false-sharing bugs. They also repurposed standard 64-bit pointers. Because modern architectures utilize only the lower 40 to 42 address bits—already capable of addressing multiple terabytes of RAM—the upper 20 bits of a pointer are typically filled with redundant sign-extended zeros or ones. Azul leveraged these unused upper bits to embed runtime metadata directly into object references. The CPU hardware strips these metadata bits before driving physical address buses. By keeping metadata in the pointer itself, the JVM accelerates virtual method dispatch by performing predicted subclass checks directly on the reference without having to dereference the object's memory header.
Azul also implemented a dedicated cooperative self-suspension mechanism designed to safepoint thousands of actively executing threads. Unlike standard server workloads where the majority of threads idle on blocking I/O, Azul systems had to halt thousands of runnable CPU-bound threads in mere milliseconds to initiate garbage collection cycles, and then restart them simultaneously without thread-scheduling stalls. Cliff concludes with a humorous look at the daily friction of hardware and software co-design. Whenever he approached the hardware engineering team asking for a specialized single instruction to execute a complex sequence, the hardware engineers would push back with rigorous trade-offs. As Cliff recounts:
> “And I go to the hardware guys and say, ‘Can you give me instruction to do this?’ He said, ‘Sure. I'll give you one. Here are my three clocks and here are three, one-clock instructions that do X. And now tell me why it really has to be faster than three clocks?’”
- Short cache line sizes minimize false sharing between concurrent threads and preserve memory bus bandwidth. - Unused upper bits of 64-bit pointers store object metadata, stripped by the hardware prior to bus transactions. - In-pointer metadata accelerates virtual calls by validating predicted subclass tests without memory dereferences. - Hardware-assisted cooperative self-suspension brings thousands of running threads into GC safepoints within milliseconds. - Hardware architects constantly challenged JVM requests for custom instructions, demanding proofs where a dedicated instruction genuinely outperformed a few standard single-cycle RISC operations.
[19:52](https://www.youtube.com/watch?v=5uljtqyBLxI&t=1192s) Hardware/Software Co-Design: What Belongs in Silicon vs. Software
During the co-design of the chip, Cliff Click frequently had to rein in hardware engineers who proposed complex features. Whenever they offered optimizations that shaved a few clock cycles off infrequent operations, Click would counter that three clocks every few thousand instructions was completely acceptable. In return, the hardware team would propose seemingly attractive Java-centric features like direct bytecode execution in silicon—reminiscent of Sun's picoJava or ARM's Jazelle. Click vehemently pushed back against these ideas:
> “Oh, my God, don't do that. It's been tried before. It's disastrous. What about JIT? Give me a nice JIT target. Nice RISC. I'll make you a pretty code for it and it'll run really fast. Don't try and screw around with executing bytecodes directly because after I JIT, you won't care for it and, in any case, you can't handle all the bytecodes, so you'll have to bail out the software over anyhow.”
The same dynamic played out with virtual method dispatch. When hardware engineers offered complex branch target buffers to accelerate dynamic calls, Click analyzed instruction traces and showed that jump-register instructions were almost nonexistent in their compiled output. The JIT compiler relied heavily on polymorphic inline caches instead of indirect jumps, rendering specialized hardware prediction redundant. Click urged them to stick to standard, well-tuned branch prediction and focus on baseline execution speed instead, noting:
> “Basic stuff is more important to get right. I'd rather have a 5% bumping clock rate over any one of these other things.”
The guiding rule of Azul’s hardware/software co-design became clear: **simple detection belongs in hardware, while complex recovery and fixup belong in software.**
```mermaid flowchart LR accTitle: Hardware Detection vs Software Fixup Division accDescr: Diagram showing how Azul splits responsibilities between simple hardware detection mechanisms and complex software recovery logic.
subgraph HW["Hardware Layer (Detection)"] H1["Cache Line Eviction (HTM)"] H2["GC Read / Write Barriers"] H3["Type Sub-Checking Checks"] end
subgraph SW["Software Layer (Fixup & Logic)"] S1["Abort, Retry & Fallback Logic"] S2["Object Relocation & Remapping"] S3["Inline Cache Updates & Deopt"] end
H1 -->|"signal eviction"| S1 H2 -->|"trap / mark bit trigger"| S2 H3 -->|"mismatch detect"| S3 ```
- **Hardware Transactional Memory (HTM):** Software transactional memory (STM) implementations incur an order-of-magnitude 10x penalty trying to track memory conflicts. Hardware already tracks cache-line invalidations via coherency protocols, making conflict detection virtually free. - **No hardware register rollback:** Academic HTM models depend on complex out-of-order execution engines with register renaming to roll back speculative state. Azul’s cores remain simple in-order RISC; when an HTM transaction aborts, rollback and retry are orchestrated entirely by the software runtime. - **Cache line zeroing:** Zeroing allocations outside the standard memory coherency domain avoids stalling incoming zeroing pipelines on lock acquisitions, preventing CPU stalls and maintaining high allocation bandwidth. - **Garbage collection read barriers:** Academic literature typically cites a 10% to 20% throughput penalty for software read barriers. Implementing lightweight detection directly in the load/store hardware dropped the barrier overhead to near zero, enabling concurrent GC algorithms that scale to massive heap sizes.
---
[24:11](https://www.youtube.com/watch?v=5uljtqyBLxI&t=1451s) The Appliance Strategy and Custom OS Architecture
Enterprise customers and conservative financial institutions were unwilling to buy an unproven server architecture running an unfamiliar operating system if it required major operational disruption. Azul solved this adoption hurdle by packaging the system as a drop-in network appliance. Existing enterprise applications running on legacy Sun SPARC or HP-UX servers could simply point their local client to the Azul appliance's JDK over the network, achieving massive speedups without touching core enterprise infrastructure:
> “And, literally, it's 10 minutes from install to sort of a max score JBB on any old machine in your entire data center.”
By treating the appliance as an execution engine, Azul bypassed typical operating system headaches. The OS contained no legacy driver baggage, no user-facing DLL or patch management issues, and ran completely stateless without disk swap space. Standard commodity kernels like Linux could not handle the machine's concurrency profile, prompting Azul to design a custom scheduler capable of managing hundreds of CPU cores and thousands of runnable threads simultaneously.
- **Quality-of-service guarantees:** The OS enforces strict hard performance floors, allowing administrators to partition and guarantee specific CPU and memory quotas to mission-critical JVM processes while permitting lower-priority batch jobs to opportunistically consume idle resources. - **Custom memory management:** The OS provides rapid, bulk virtual-to-physical memory remapping and bulk TLB shootdowns designed expressly for high-speed concurrent garbage collection. - **Virtual memory with type safety:** When questioned why an appliance running type-safe Java requires hardware TLBs and page protection, Click's blunt answer was simply: “Well, you get bugs.” - **Hardware fault isolation:** The operating system continuously monitors hardware reliability, using chipkill and parity data to dynamically de-configure failed memory chips, individual dead caches, or faulty CPU cores without crashing the entire system.
---
[26:54](https://www.youtube.com/watch?v=5uljtqyBLxI&t=1614s) Why Design a Custom CPU and How to Exploit Massive Core Counts
Azul ended up designing their own CPU because no commercial 64-bit multi-core designs were available that met their architectural requirements. Adapting an existing x86 core layout would have required gutting and redesigning the load-store unit and L1 caches to accommodate hardware transactional memory, metadata stripping for GC barriers, ECC protection across L1 caches, and register file parity. Because each core featured 32 architectural registers backed by 64 physical registers across 54 cores per chip (thousands of register cells vulnerable to soft errors), register integrity was essential:
> “And by that time, you are now redesigning about half your CPU anyhow.”
Rather than struggling with proprietary IP modifications, Azul built their own RISC processor, ported GCC and the toolchain, and brought up the HotSpot JVM on the architecture in short order.
Having hundreds of cores completely altered software tradeoffs: when spare cores are ubiquitous, background tasks become virtually free. Azul leveraged this architectural scale in two primary areas:
- **Aggressive JIT compilation:** During application startup, the runtime spins up pools of 30 to 50 background compiler threads. The JIT generates megabytes of optimized native code per second, compiling the entire multi-gigabyte application footprint in flight within minutes. - **Cache-isolated concurrent GC:** Full-heap garbage collection touches huge volumes of memory and exhibits poor spatial locality, which would typically thrash processor caches. Rather than competing with application threads (mutators) on shared L2 caches, Azul isolates GC worker threads onto distinct L2 processor clusters. Because the GC threads only need to finish before the next collection cycle begins, their low L2 cache hit rate is immaterial, leaving the application mutators' caches entirely unpolluted.
[29:55](https://www.youtube.com/watch?v=5uljtqyBLxI&t=1795s) Toolchain, Simulation, and the Multi-CPU Simulator Rule
Azul explored a variety of low-latency hardware and software tricks, including background profiling, pre-zeroing memory pages, and having the CPU hot-spin on I/O so that only single-digit clock cycles elapsed between data landing in memory and processing beginning. Once the architectural concepts were solidified, the team faced the daunting task of turning those ideas into a taped-out design for TSMC. Cliff Click recalls that the dot-com bust worked in their favor for hiring: with widespread layoffs across Silicon Valley, Azul assembled an elite roster of hardware engineers, operating system specialists, and VM developers. They immediately started porting GCC and Sun's HotSpot JVM to their custom ISA while developing an in-house software simulator.
Running on high-end x86 machines, their simulator achieved roughly 20 MHz of simulated Vega chip operations—fast enough to boot the operating system and execute massive, complex Java enterprise applications under simulation. The team built an extensive suite of analysis tools around it, including trace generators, cache-miss and layout visualizers, and an aggressive data-race detector that rooted out latent race conditions within HotSpot as well as user applications. A major technical takeaway emerged regarding simulator architecture: if a multi-core system simulator is executed on a single-core host, it hides real-world concurrency phenomena.
Cliff Click emphasized this hard-won realization: > “Your simulators have to be run on a true multi-CPU machine or you will not get realistic [timing] that will happen in real life.”
When Azul transitioned their simulator runs from single-socket to dual-processor x86 hosts, an entirely new class of simulation data races surfaced that had never triggered under single-threaded execution.
- Toolchain efforts ran in parallel with hardware design, porting both GCC and HotSpot to the custom Vega RISC architecture. - Simulator speed reached ~20 MHz equivalent Vega execution speed on top of fast x86 host hardware. - Host multiprocessor parallelism was required to expose real race conditions in the simulated multi-threaded guest.
---
[31:43](https://www.youtube.com/watch?v=5uljtqyBLxI&t=1903s) Vega 1 Core Architecture and L2 Cache Over-Subscription
The first physical processor, Vega 1, integrated 24 64-bit RISC cores arranged as three clusters of eight cores, with each cluster sharing a 1 MB L2 cache. Individual cores featured a 16 KB instruction cache and a 16 KB data cache (both 4-way set-associative) along with short cache lines and dedicated tag bits to support Hardware Transactional Memory. However, the shared L2 cache was also only 4-way set-associative. This created an extreme structural over-subscription: eight independent processors, each carrying separate 4-way instruction and 4-way data streams, converged onto a shared 4-way L2 cache. If four CPUs happened to map into the exact same L2 set, any access from a fifth core would evict an active line, triggering thrashing and severe false sharing across all eight CPUs.
Azul was acutely aware of this risk, but manufacturing realities dictated the compromise. Vega 1 was already pushing the absolute boundaries of silicon die area and yield—it was the largest physical die TSMC had ever fabricated up to that point. The system architecture supported coherent interconnect fabric across up to 16 physical chips. Memory latencies were structured such that missing the local L2 incurred roughly the same cost regardless of whether the fetch resolved in a peer chip's L2 or in main DRAM.
On the core level, Click got the clean JIT compilation target he had requested. The pipeline was an in-order, classic 3-address 64-bit RISC engine with a single-entry store buffer/latch and hit-under-miss caching. It incorporated hardware metadata masking, an integrated per-core floating-point unit without vector register baggage or legacy status flags, a background register stack engine to spill and fill registers on deep call frames, and dedicated hardware assists for array bounds checks, virtual method dispatch, and Garbage Collection barriers.
```mermaid flowchart TD accTitle: Vega 1 Memory Hierarchy and Cluster Architecture accDescr: Architecture of Vega 1 showing 8-core clusters sharing a 4-way L2 cache backed by the 16-chip coherent interconnect.
subgraph Cluster["Cluster (1 of 3 per Vega 1 Chip)"] subgraph Cores["8 RISC Cores"] C1["Core 0\n16KB I / 16KB D (4-way)"] C2["Core 1\n16KB I / 16KB D (4-way)"] CDots["... Cores 2-6..."] C8["Core 7\n16KB I / 16KB D (4-way)"] end L2["Shared 1MB L2 Cache\n(4-way Associative - Over-subscribed)"] Cores -->|"Read / Write Contention"| L2 end
subgraph Fabric["Coherent Interconnect & Memory"] CoherentBus["16-Chip Interconnect Fabric"] RemoteL2["Remote Chip L2 / Main Memory\n(Latency ~ Local L2 Miss)"] L2 -->|"L2 Miss"| CoherentBus CoherentBus --> RemoteL2 end ```
- Each Vega 1 die packed 24 cores organized into three clusters of 8 cores. - L1 cache per core: 16 KB I-cache (4-way) and 16 KB D-cache (4-way) with HTM metadata state tags. - Cluster cache: 1 MB L2 (4-way) shared among 8 cores, heavily over-subscribed and prone to eviction thrashing under aligned workloads. - Core pipeline: In-order 64-bit 3-address RISC, single-entry store latch, zero legacy flags/modes, background spill/fill register engine. - Memory fabric: Coherent scaling up to 16 chips, where an off-core L2 miss cost was comparable to remote cache or memory access.
---
[34:17](https://www.youtube.com/watch?v=5uljtqyBLxI&t=2057s) First Silicon Back from TSMC: "Mostly Dead" and Cooking Chips
In 2004, the first batch of manufactured Vega 1 silicon arrived from TSMC. A courier boarded a flight in Taiwan carrying the physical parts in a box, landing at Azul's headquarters 24 hours later. The engineering team immediately began probing the chips, only to discover severe manufacturing and design defects across the die. The L2 caches were almost entirely non-functional. The chip could only boot if operated in a degraded fallback mode Azul dubbed "limp home mode"—borrowing automotive terminology for driving an exploded transmission stuck in first gear. Engineers disabled three of the four L2 ways entirely, leaving a fragile 1-way 256 KB L2 alive while relying on continuous Error-Correcting Code (ECC) scrubbing to survive.
The CPU register files suffered an even more bizarre electrical defect: bit lines were capacitive coupling, causing writes to even-numbered registers to bleed unpredictably into the adjacent odd-numbered registers. If an instruction executed `ADD Rx, Ry -> Rz`, and `Rz` was an even register, its payload would corrupt register `Rz+1`. The JIT compiler team had to immediately generate code targeting only register subsets. Worse, the instruction decoder erroneously decoded branch target offset bits through the register address ports simultaneously with branch opcodes, toggling register file address lines on branches and corrupting arbitrary state unless branches targeted specific aligned addresses with predetermined zero bits.
To make the surviving silicon operational at all, Azul was forced to drop the clock speed down to one-third of the target frequency and jack the operating voltage up to five times normal ratings. The extreme over-voltage induced severe electromigration: metal atoms within the silicon lattice physically migrated across traces under high current density. The test chips literally cooked themselves to death within about thirty days. Test benches featured howling industrial fans clamped directly to glowing heatsinks. Despite the chaos, the operating system team leveraged the failing hardware as the ultimate baptism by fire, verifying their hardware-error handling, dynamic CPU de-configuration, and ECC recovery subroutines on genuinely damaged silicon.
Cliff Click summarized the scene when the first packaged parts arrived: > “We get our first silicon back from TSMC at 2004, right? It's not quite dead. It's dead, gentleman. Not quite.”
- First silicon arrived via personal air courier from TSMC Taiwan in 2004 and exhibited critical electrical faults. - "Limp home mode" cut the 1 MB 4-way L2 cache down to a 1-way 256 KB cache running under constant ECC correction. - Even-numbered register writes bled into odd-numbered registers, forcing compiler mitigations. - Instruction decoder bugs treated branch offsets as register decodes, requiring software branches to enforce specific zeroed bit masks. - Running at 1/3 clock frequency and 5x operating voltage triggered rapid electromigration that destroyed test dies within a single month.
---
[37:17](https://www.youtube.com/watch?v=5uljtqyBLxI&t=2237s) Third-Party IP Failure, Metal-Mask Fixes, and Cache Collisions
Azul investigated the root causes with TSMC and discovered that the failures originated inside licensed third-party silicon IP cores sourced from the DSP sector. The IP vendor had certified their designs on paper to run at Azul’s targeted high frequencies, but in reality, that vendor had never actually taped out or shipped functional silicon running beyond one-half to one-third of that rated speed. Because the circuits had never been manufactured or validated at those limits, they collapsed in real silicon.
Rather than incurring the multi-month delay and immense expense of a complete silicon redesign, Azul’s hardware engineers utilized an emergency metal-mask spin. The team had deliberately manufactured excess wafers that were paused three-quarters of the way through the fabrication pipeline, awaiting final metal routing layers. The original die layout was intentionally peppered with uncommitted "spare" transistors sprinkled across the substrate. By revising only the topmost metal masks, hardware designers routed around broken IP blocks, hooking into previously idle transistors to patch logic paths and fix clocking issues without a full silicon respin.
The resulting second silicon revision proved exceptionally clean. The operating system booted successfully within two weeks of receiving the new silicon. A C "Hello World" binary was running 24 hours later, and `java -version` executed cleanly just four days after that, validated by thousands of hours of prior simulator verification.
Even with functional silicon, stabilizing the machine at scale took another full year. The architecture featured more concurrent cores and aggressive out-of-order execution than any software platform had previously targeted, revealing endless timing bugs. Additionally, the 4-way over-subscribed L2 cache suffered severe performance penalties due to memory alignment: thread call stacks were all aligned to 1 MB boundaries by default. When multiple application threads reached similar execution depths, their stack frames mapped precisely onto the same L2 cache lines, causing the eight cores in a cluster to aggressively evict one another's active frames. Azul resolved the thrashing entirely in software by introducing randomized stack pointer offsets, randomized JIT code cache offsets, and OS-level memory page coloring.
Cliff Click described the sheer relief and speed of getting the second silicon revision running after the metal respin: > “Two weeks from getting this silicon to getting the OS to boot, a day later to get 'hello world' out of C program. Four days later, the 'java -version' works, right?”
- The hardware failures were traced to third-party DSP silicon IP rated for frequencies at which it had never physically been manufactured or tested. - A metal-mask spin salvaged partially fabricated wafers by rewiring logic through unused spare transistors left across the die layout. - Software bring-up on the revised silicon took only two weeks to boot the OS, one additional day for C binaries, and four days to achieve a working `java -version`. - Massive L2 thrashing across the 8-core clusters was resolved in software using randomized thread stack offsets, randomized code cache layout, and operating system page coloring.
[40:03](https://www.youtube.com/watch?v=5uljtqyBLxI&t=2403s) What Worked, What Didn't: Silicon, Power Supplies, and Cache Mysteries
Reflecting on the hardware architecture, Cliff Click notes that sharing a single 4-way L2 cache among eight 4-way L1 caches ultimately yielded an entirely tolerable miss rate, although achieving that required substantial tuning. The virtualization layer designed for drop-in plug-and-play operation with existing JVMs also leaked abstractions initially, forcing engineers to patch several layers before performance stabilized. Once the second metal spin came back from the fab, the chip itself performed solidly: memory bandwidth was plentiful, and raw compute density blew commodity hardware out of the water. “Certainly compared to like an X86, we have way more MIPS per chip, MIPS per watt than X86, like five X more.”
```mermaid flowchart TD accTitle: System Challenges in Hardware and OS Bring-up accDescr: Diagram showing how hardware quirks, platform failures, and OS scaling issues impacted the overall system stability.
subgraph HW["Silicon & Board Bring-up"] A["Low-Frequency DRAM Bugs masked by ECC"] --> B["Motherboard Redesigns for DRAM Timing"] C["In-Order RISC Limits Frequency"] --> D["Lower Single-Thread Speed"] end
subgraph Vendor["Platform Components"] E["2,500W Power Supplies"] --> F["Instant Lab Blowouts Under Full Load"] end
subgraph OS["OS & Runtime Scaling"] G["Scheduling 800+ Cores"] --> H["Scheduler Bottlenecks"] I["Virtualizing I/O Stacks"] --> J["High I/O Latency & Jitter"] end ```
Yet severe hurdles cropped up across the rest of the platform. Single-thread CPU performance remained stubbornly slower than hoped—a direct consequence of using simple in-order cores at low clock frequencies without an army of hardware engineers to design aggressive out-of-order execution pipelines. In the lab, hardware teams fought low-frequency DRAM bugs that had been silently masked for months because the ECC continuously corrected single-bit flips instead of surfacing the underlying fault. The motherboard had to undergo multiple redesigns to fix DRAM bus timing issues. Even commodity hardware components failed unexpectedly: high-capacity 2,500-watt power supplies purchased from major vendors repeatedly blew up when subjected to an actual full-load draw in the lab. Operating system software had equal trouble managing scale: scheduling tasks across 800-plus cores and virtualizing complex I/O stacks proved far from a simple drop-in engineering exercise.
- **MIPS per watt advantage:** Approximately 5× greater MIPS per chip and per watt compared to contemporaneous x86 platforms. - **Power supply failures:** Commercial 2,500-watt power supplies repeatedly died immediately upon drawing maximum rated power in the lab. - **Silicon revisions:** The processor silicon reached stable, functional operation on its second metal spin.
---
[42:52](https://www.youtube.com/watch?v=5uljtqyBLxI&t=2572s) Garbage Collection Growing Pains and Engineering Priorities
Integrating upstream Sun code into Azul's modified JVM presented continuous software maintenance friction. Because Sun's standard HotSpot VM never used read-barriers, every new Sun code drop introduced un-barriered memory reads that Azul engineers had to hunt down manually; missing even one caused elusive, ultra-low-frequency memory corruption bugs that took ages to diagnose. Furthermore, the initial version of Azul's GC was purely single-generation, running a complete collection cycle every five seconds. While pauses were held to around 100 milliseconds across hundreds of gigabytes, executing a full-heap cycle every few seconds exposed latent defects in Sun's codebase that normally ran only during infrequent daily full GCs: “We found lots of bugs in the full GC cycle behavior that were related to the fact that they only happen on the full GC cycle because we're doing it so much more often.”
Engineering priorities became a battlefield between stability and experimental features. Debates flared over whether to spend developer hours stabilizing basic code generation and helping field engineers or chasing advanced capabilities like hardware transactional memory (HTM), stack allocation via escape analysis, larger thread pools for faster warm-up, and tiered compilation. Customer support routinely pulled senior engineers into sales escalation calls: enterprise clients had multi-threaded code riddled with undetected data races that had run stably on x86 purely by chance, but running on a massively parallel box caused the same applications to crash every ten minutes.
- **Initial GC pause target:** 100-millisecond pauses across hundreds of gigabytes, executing every 5 seconds. - **Sun code drop friction:** Missing read-barriers in newly imported HotSpot code caused rare, difficult-to-trace garbage collection anomalies. - **Customer concurrency bugs:** Code that crashed once a day on x86 crashed every 10 minutes on Azul hardware due to massive thread concurrency exposing dormant race conditions.
---
[44:54](https://www.youtube.com/watch?v=5uljtqyBLxI&t=2694s) Hardware Transactional Memory and Stack Allocation Trade-Offs
Both hardware transactional memory (HTM) and hardware-assisted stack allocation were sidelined for extended stretches due to software complexity and engineering time constraints. Early HTM implementations suffered from severe livelock: a core would repeatedly attempt to transact through a contended lock, fail, abort, and retry indefinitely without forward progress. The runtime eventually had to implement fallback paths that detected livelock, trapped to an OS-level lock to force execution forward, and only re-enabled speculative HTM transactions once the system reached steady state. Although HTM has been enabled by default for years, Click admits it is rarely a silver bullet: “It rarely helps customers for—like I said, it's mostly in another talk—it never hurts. And occasionally, you get big wins. You get a 2X speed up or something but the usual case is there's nothing.” Applications usually hit bottleneck limits in the network, the database, or genuine data dependencies long before lock contention dominates.
```mermaid flowchart LR accTitle: Hardware Transactional Memory Fallback State Machine accDescr: Flowchart tracing an HTM transaction from speculative attempt to livelock fallback and eventual steady-state recovery.
A["Attempt HTM Lock Transaction"] --> B{"Transaction Succeeded?"} B -- Yes --> C["Commit Speculative State"] B -- No --> D["Detect Livelock / Repeated Aborts"] D --> E["Trap & Acquire Heavy OS Lock"] E --> F["Make Forward Progress"] F --> G["Wait for Steady-State System Conditions"] G --> A ```
Stack allocation met a similar fate. While aggressive escape analysis could eliminate a huge percentage of heap allocations in ideal cases, edge cases behaved pathologically. Because Azul's continuous concurrent garbage collector advanced so rapidly, the team had little reason to spend scarce engineering time chasing escape analysis bugs. In production, the garbage collector routinely manages heaps of 300 to 500 gigabytes with allocation rates reaching 35 gigabytes per second while holding maximum pause times to 10–15 milliseconds—far outpacing any concurrent x86 collector.
- **HTM shipping status:** Enabled by default in production for over three years prior to the talk. - **Performance impact of HTM:** Occasional 2× speedups, but typically neutral due to non-locking bottlenecks like I/O and databases. - **Production GC metrics:** Sustained 300–500 GB heap sizes with 35 GB/s allocation rates and 10–15 ms maximum pause times.
---
[47:08](https://www.youtube.com/watch?v=5uljtqyBLxI&t=2828s) The Zero-Flag Collector and Always-On Production Profiling
Deploying the Azul JVM at customer sites followed a surprisingly simple playbook: technicians stripped away all legacy HotSpot GC tuning flags, doubled the default heap size, and relaunched. In response to an audience member asking whether the gains came merely from doubling memory or from the fundamentally different collector, Click clarified that HotSpot tuning flags have no meaning on Azul's engine: “And, in fact, we have no tuning flags at all on the GC. If it doesn't perform well, then it's a bug for us and we go fix it on whatever your app is, whatever shape GC cycle thing it's doing.” Doubling the heap removes arbitrary memory restrictions that forced customers to write awkward workarounds or configure undersized internal caches to escape punishing x86 GC pauses. With pauses no longer scaling with heap size, expanding memory instantly unclogged application performance.
The talk highlights an internal diagnostic profiling tool that became an accidental commercial hit. Originally an in-house utility with an unglamorous internal name, customer operations teams demanded access the moment they saw it run. The tool connects through a standard web browser directly into the internals of any production JVM—even instances that have run continuously for months—with virtually zero performance overhead. Rather than attempting to reproduce elusive production hiccups in staging environments, engineers can inspect live thread stacks, watch real-time GC cycles, surf live heap memory, inspect lock contention traces, and analyze call-site profiling. When throughput mysteriously plummets after days of stable production execution, operators no longer need a synthetic reproduction; they simply connect the browser and inspect the runtime state live.
- **Zero-tuning GC philosophy:** No customer-facing GC tuning switches; suboptimal GC performance is classified and patched as an internal Azul bug. - **Production diagnostic visibility:** Live web browser access to inspect thread call stacks, monitor real-time GC behavior, browse active heap graphs, and detect hot locks on live enterprise systems.
[49:51](https://www.youtube.com/watch?v=5uljtqyBLxI&t=2991s) System Uptime and the Always-On TPM Web Profiler
Cliff Click highlights the rock-solid stability of Azul's hardware in production, noting that several customer deployments maintain uptimes exceeding a year. Within Azul, the engineering boxes used for day-to-day development rarely experience crashes unless physical infrastructure fails: “The standard engineering box that they do daily work on at Azul now goes down when we have power failures and that's it.” He jokes that the last catastrophic outage happened when Google accidentally severed the chilled water supply line feeding their data center.
Turning to monitoring, Click showcases the Thread Priority Manager (TPM) or live JVM inspector, which he ranks as the platform’s second-best feature behind pause-free garbage collection. It allows developers to view internal JVM operational metrics through any standard web browser without imposing measurable overhead. Responding to audience questions about whether it continuously streams data, Click clarifies that it operates on a pull model: refreshing the web page pulls an instantaneous snapshot of live stack traces across running threads, their execution durations, and internal network telemetry like open sockets, I/O rates, and data endpoints.
- Systems regularly achieve over a year of uninterrupted uptime. - Engineering systems only go down due to external events (such as power outages or severed data center water lines). - The web-based inspection tool provides zero-overhead, always-on diagnostic snapshots across threads, stacks, and socket-level network traffic.
---
[51:20](https://www.youtube.com/watch?v=5uljtqyBLxI&t=3080s) Silicon Generations: Vega 2, Vega 3, and Beyond
Click details the evolution of Azul's proprietary multi-core chips across several iterations:
```mermaid flowchart TD accTitle: Azul Systems Vega Chip Evolution accDescr: Progression from Vega 2 yield harvesting to Vega 3 full core activation and architectural improvements.
subgraph V2["Vega 2 (48 Active Cores)"] direction TB V2_Clusters["6 clusters of 9 cores = 54 physical cores"] V2_Yield["1 core per cluster reserved for yield defects"] V2_Mask["Defective cores disabled with ion beam"] V2_Clusters --> V2_Yield --> V2_Mask end
subgraph V3["Vega 3 (54 Active Cores)"] direction TB V3_Yield["Fab yield maturity eliminates core masking"] V3_Features["All 9 cores per cluster enabled (54 total)"] V3_Upgrades["Bigger cache, faster bus & clock, generational GC, improved HTM"] V3_Yield --> V3_Features --> V3_Upgrades end
V2 -->|"Fabrication improvements"| V3 ```
Vega 2 packed 48 active cores alongside an upgraded clock rate, a higher-throughput memory bus, and an overhauled read-barrier supporting generational garbage collection. Under the hood, the die contained 54 cores organized into six 9-core clusters. The extra core per cluster served as a yield buffer against fab flaws: if one core had defects, an ion beam masked it out to deliver 48 operational cores. By the time Vega 3 arrived in 2008, manufacturing yields were sufficiently mature to eliminate core harvesting entirely, enabling all 54 cores across the die alongside larger caches, higher clock rates, richer hardware profiling, and refined Hardware Transactional Memory (HTM). Click mentions that a fourth-generation processor is currently under active development.
Because Azul compiles directly from Java bytecode rather than shipping legacy machine-code binaries, the engineering team had the freedom to drop unused instructions and reorganize opcode bit layouts across chip generations to simplify hardware decoding.
---
[52:31](https://www.youtube.com/watch?v=5uljtqyBLxI&t=3151s) Hardware/Software Co-Design Lessons: Bandwidth, GC, and HTM
Click turns to the strategic advantages of vertically integrated systems engineering: “If you own the whole stack, hardware and up, you can do progress even with some of the real awful hardware bugs, right?” Rather than waiting on multi-year silicon respins, the software team regularly patched hardware quirks at the compiler or OS level and permanently moved on.
When memory bus bandwidth forecasts threatened to bottleneck performance, the software team implemented a custom zero-overhead compression technique (CLZ) that cut required memory bandwidth by one-third, turning what hardware engineers considered a marginal architectural design into an optimal sweet spot.
On runtime behavior, Click reflects on several core design decisions: - **Garbage Collection:** Click asserts that GC is effectively solved across everyday commercial scales up to hundreds of gigabytes, even if it does not qualify as microscopic hard real-time execution. - **Hardware Transactional Memory (HTM):** Azul implemented simple HTM mechanisms to attempt automatic lock elision, but Click admits the real-world results were disappointing: “We can do lock elision with some very simple hardware transactional memory and it doesn't really help. It's very sad.” While HTM shows niche promise for multi-word compare-and-swap (N-CAS) primitives in specialized non-blocking data structures, it failed to deliver magic-bullet speedups for general-purpose application workloads. - **Massive Simple Core Counts:** Click confesses surprise at how successfully high volumes of simple, in-order RISC cores handle enterprise business logic, outperforming x86 machines on large parallel workloads despite having slower single-thread speeds.
---
[54:16](https://www.youtube.com/watch?v=5uljtqyBLxI&t=3256s) Why Major Chipmakers Hesitated: Intel and Sun
During the Q&A, an audience member asks why established chip vendors like Intel never integrated specialized read barriers and memory hooks directly into their CPUs. Click reveals that Azul engaged in extensive, frustrating discussions with Intel: “We have talked a lot within Intel and it's like moving the Titanic, you know. It doesn't matter how hard you push, it's just like a millimeters at a time.”
Click argues that adding hardware read-barrier traps would have allowed Intel or Sun Microsystems to dominate the enterprise server runtime market outright:
> “For Intel not to do a read barrier is like an obvious crying shame and a waste of, like, huge market potential for them to suddenly own the whole Java server market, right? For Sun not to have done it should have been a criminal offense on their—their stockholders should have sent their, you know, exec staff to jail for being, like—you know, after we did it and said, 'Oh, look what we can do,' that they didn't immediately announce that we're doing it on our next chip was just like criminal.”
When audience member Jerry points out that these primitives benefit every modern managed language, Click agrees that hardware support for managed runtimes is a universal win across any garbage-collected platform. Another attendee asks about binary compatibility and ECC memory; Click clarifies that Azul bypasses traditional OS/ISA binary constraints by adopting Java bytecode as its stable binary contract, freeing the underlying RISC microarchitecture to evolve without backward compatibility debt.
---
[56:42](https://www.youtube.com/watch?v=5uljtqyBLxI&t=3402s) Fast User-Mode Traps and Self-Healing Pointers
An audience member asks how the Azul processor eliminates the massive overhead typically caused by trap handling in hardware-assisted read barriers. Click explains that the cores utilize custom user-mode traps that bypass the operating system kernel:
```mermaid flowchart LR accTitle: Azul Fast User-Mode Read-Barrier Trap Handling accDescr: Fast user-mode trap flow showing low overhead entry, pointer patching in registers and memory, and fast return.
A["Read Barrier Detects Stale Bit"] --> B["4-Clock User-Mode Vector<br/>(No Kernel Transition)"] B --> C["Patch Register & Update Memory (40–50 Cycles)"] C --> D["Self-Healing Complete:<br/>Subsequent Loads Never Trap"] ```
1. **User-Mode Trap Vectors:** The processor traps directly into a pre-registered user-space function address in about four clock cycles without kernel intervention or context-switch overhead. 2. **Self-Healing Updates:** The handler updates both the CPU register holding the reference and the original memory location where the outdated pointer resided. 3. **Trap Storms Dissipate:** At the onset of a GC phase switch (when reference bit polarities flip), application mutator threads hit a brief burst of traps across their initial working set. Each trap costs roughly 40 to 50 clock cycles. Within a few hundred traps, mutators patch their active references, while background GC threads sweep ahead through heap memory to update remaining pointers. As a result, trap rates drop to near zero, making the overall overhead imperceptible even to high-precision hardware performance counters.
---
[58:45](https://www.youtube.com/watch?v=5uljtqyBLxI&t=3525s) Mitigating Stop-the-World Pauses: Ragged Barriers and Self-Preemption
An attendee asks how the runtime manages thread coordination and pauses across hundreds of active CPU cores during garbage collection passes. Click explains that full stop-the-world events occur only a few times per minute, while the vast majority of phase transitions rely on "ragged barriers":
```mermaid flowchart TD accTitle: Ragged Barrier vs. Cooperative Safepoints accDescr: Comparison of independent ragged barrier execution versus cooperative thread suspension during global safe points.
subgraph Ragged["Ragged Phase Transition (Non-Blocking)"] R1["Mutator hits phase boundary"] R2["Mutator checks own hot stack"] R3["Mutator signals completion & resumes work"] R1 --> R2 --> R3 end
subgraph Safepoint["Global Safepoint (Full Coordination)"] S1["Announce safepoint across all cores"] S2["Blocked / I/O threads park at safepoint automatically"] S3["Running threads self-preempt cooperatively"] S4["GC threads shoot down lagging uncooperative threads"] S1 --> S2 --> S3 --> S4 end ```
- **Ragged Barriers:** Cores reach GC phase boundaries independently. Each core pauses briefly to crawl and inspect its own stack—which is already hot inside its local L1/L2 caches—broadcasts an atomic completion signal, and immediately continues application processing. No global stall occurs, and the GC phase completes once the last core checks in. - **Cooperative Self-Preemption:** For the rare operations requiring a complete halt, threads anticipating blocking operations (such as I/O or sleep) automatically park at safe points beforehand. This reduces the number of threads requiring coordination from thousands down to just the active hardware execution contexts running on the CPU cores. The runtime broadcasts a safe point request, mutators cooperatively yield at compiler-inserted check sites, and GC threads intervene to preempt any lagging threads that fail to yield in time.
[01:00:32](https://www.youtube.com/watch?v=5uljtqyBLxI&t=3632s) Hardware-Assisted Safepoints and Stopping Threads
Cliff Click explains how the system rapidly halts threads at safe points using an infected, cooperative stopping mechanism. He compares the process to a cascading epidemic:
> “That, you know, Night of the Living Dead kind of race, where each guy that checks in now goes and helps the next guy check in kind of thing.”
Because of this log-tree propagation effect, bringing running threads to a standstill takes only microseconds when running tens of threads, and just a handful of milliseconds when coordinating hundreds of threads.
This rapid halting relies directly on hardware-level support. Each Azul processor core contains an internal status bit. When the JVM decides a safe point is required, it calls into the operating system to broadcast a request across every processor:
```mermaid flowchart TD accTitle: Safepoint Trigger and Trap Sequence accDescr: Sequence diagram showing how the OS and core hardware trigger safepoint traps on backward branches.
subgraph OS_Action["1. OS Broadcast"] A["JVM requests Safepoint"] --> B["OS sets trap bit on all cores"] end
subgraph Core_Action["2. Core Execution"] B --> C{"Core bit active & safe point instruction?"} C -->|Backward branch / safe point| D["Fast user-mode trap"] C -->|Normal execution| E["Continue execution"] end
subgraph Cascade["3. Check-in Cascade"] D --> F["Thread registers at safe point"] F --> G["Helps halt remaining threads"] end ```
The OS replicates the message across all cores to light up their safe-point bits in microseconds. Once set, whenever a core hits an instruction designated for safe-point polling—such as backward branch targets inside loops—the hardware executes a fast user-mode trap instead of executing the instruction normally. Because testing this state requires executing only a single instruction, threads rapidly trap and check in.
[01:01:54](https://www.youtube.com/watch?v=5uljtqyBLxI&t=3714s) Software vs. Hardware Stack Allocation and Escape Analysis
When asked whether Azul implemented hardware support for escape analysis and stack allocation, Click clarifies that it was never deployed to production. The Pauseless Garbage Collector performed so exceptionally well that engineering never felt the pressure to implement the hardware-assisted stack allocation mechanisms they had conceived.
Click notes that he has not seen industry or academic literature attempting runtime escape detection entirely in software, even though he has proposed the concept to multiple researchers. Azul had originally designed an aggressive escape-detection mechanism in hardware simply because they had full control over their silicon design. However, Click emphasizes that a software-based approach using just a handful of instructions could reasonably identify around 50% of non-escaping allocations, which would deliver massive performance gains for large heaps without dedicated silicon changes.
[01:02:47](https://www.youtube.com/watch?v=5uljtqyBLxI&t=3767s) Volatile Reads vs. Writes and the x86 Cost Model
An audience member asks how a Java programmer should balance algorithmic trade-offs between volatile reads and volatile writes when underlying CPU architectures treat them differently. Click half-jokingly advises developers to “throw up his hands,” before delivering a clear guideline:
> “You have to code the x86 platform and what's the cost model with volatile read versus a volatile on an x86 and everyone else has to live with whatever you do, okay?”
```mermaid flowchart TD accTitle: Architectural Cost Comparison of Volatile Operations accDescr: Comparison between volatile read and write latencies on x86 versus Azul hardware.
subgraph X86["x86 Architecture"] R1["Volatile Read"] --> CostR1["Equivalent to plain read (~1 clock)"] W1["Volatile Write"] --> Fence1["Requires memory fence"] Fence1 --> Miss1["Cache miss: ~300 clocks x 4 issues (~1000 lost ops)"] end
subgraph Azul["Azul System"] R2["Volatile Read"] --> CostR2["1 clock (uncontended)"] W2["Volatile Write"] --> Fence2["1 clock write + 1 clock fence (uncontended)"] end ```
On x86 processors, a volatile read behaves almost identically to a standard memory load. A volatile write, however, requires an expensive memory fence. That fence forces a pipeline drain and a cache coherency stall, translating to roughly 300 clock cycles at a 4-wide instruction issue rate—costing the CPU roughly 1,000 instruction slots that simply fail to execute. Therefore, programmers targeting x86 must almost always prefer algorithms that favor frequent volatile reads over volatile writes.
On Azul's custom hardware, the trade-off is virtually nonexistent: - Uncontended volatile reads and writes take a single clock cycle. - A memory fence adds only a single additional cycle when there is no active contention between threads. - If an algorithm experiences high contention, it will not scale across hundreds of cores anyway.
Click adds that while concurrency expert Doug Lea is typically satisfied when algorithms scale efficiently up to 64 cores, Click constantly pushes him to make concurrent structures scale to hundreds of cores. Click has authored data structures that scale completely across all 864 cores, but because general programmers will not write algorithms at that level of concurrency, software must continue to favor volatile reads.
[01:05:22](https://www.youtube.com/watch?v=5uljtqyBLxI&t=3922s) Customer Education and Multicore Scaling Tools
Addressing how Azul interfaces with enterprise customers, Click describes the typical customer engagement cycle:
> “The usual story, the way it kind of goes is the first time you get into a customer's site, it's always an oh-my-God-save-my-bacon kind of thing.”
Customers generally bring in Azul when their absolute best engineers are completely stuck on scalability bottlenecks. Azul exposes the application's runtime behavior using the Real-Time Performance Monitor (RTPM): - RTPM provides immediate, fine-grained visibility into core stalls, lock contention, and cache pressure that engineers have lacked for years. - Customer teams quickly pinpoint bottlenecks in their own code and resolve them independently. - Click occasionally delivers focused lectures on concurrent software design patterns, but customer engineers usually take ownership of optimization once they understand the tooling.
Over time, that expertise permeates customer organizations, lifting the software engineering community's overall understanding of multicore scalability. Click draws a comparison to Google, noting that while Google relies on distributed memory architectures rather than massive shared memory, they face the exact same ongoing need to train incoming engineers on scalable design patterns.
[01:07:03](https://www.youtube.com/watch?v=5uljtqyBLxI&t=4023s) Academic Licenses and Language Support Boundaries
Asked why Azul does not broadly offer its platform to academic institutions to run arbitrary C or C++ workloads, Click explains that Azul lacks the engineering support capacity to debug arbitrary native toolchains for universities:
> “If you're on Java, we'll honor the contract on maintenance and guarantees and the works. If you're running with anything else, well then, that's just your problem.”
Despite those strict product boundaries, Azul collaborates with academia: - Several institutions have secured government research grants to acquire Azul hardware. - Azul provides academic licenses allowing remote access directly onto Azul appliances. - Doug Lea and various graduate students routinely log in remotely to execute massive, highly parallel, experimental algorithms compiled into standard Java bytecode.
[01:07:59](https://www.youtube.com/watch?v=5uljtqyBLxI&t=4079s) Hardware Architecture: Register Windows and Pre-Zeroed Store Buffers
Click details the CPU register organization and memory subsystem design of the Vega processors: - **Register Architecture**: The CPU employs variable-sized hardware register windows split into two distinct stacks: a dedicated register stack and a standard C-style execution stack, making function calls extremely cheap. - **Window Size**: The Vega 3 processor settled on 64 windowed registers. Instruction traces revealed that the hardware spill-and-fill engine accounted for well under 1% of total processor clock cycles, rendering further microarchitectural optimization of the spill engine unnecessary. - **Store Buffers**: While contemporary commodity chips rely on deep store buffers to prevent processor stalls during allocation bursts, Vega 3 operates efficiently with a store buffer depth of only two entries.
Click explains why Vega requires such small store buffers compared to x86 and SPARC: - Standard architectures like SPARC and x86 require large write buffers because new object allocations trigger immediate bursts of zeroing stores against memory lines that are not present in L1 cache, causing immediate misses. - SPARC added giant write buffers specifically to absorb these rapid zeroing bursts without stalling execution pipelines. - In contrast, Azul processors pre-zero cache lines directly within the L1 data cache just in time for allocation. Because newly allocated memory arrives already zeroed and hot in the L1 cache, the JVM avoids issuing explicit zeroing writes altogether, drastically lowering total store traffic and eliminating store-buffer stalls.
[01:10:05](https://www.youtube.com/watch?v=5uljtqyBLxI&t=4205s) Garbage Collection Mechanics and Heap Headroom
An audience member asks about the specifics of Azul's collector algorithm and whether it uses a copying collector. Click confirms that the engine is a concurrent, compacting, copying collector that relocates and compacts the entire heap every single GC cycle, citing the comprehensive details published in the VEE 2005 paper co-authored with Paul Lucchesi and others.
Addressing questions regarding memory overhead and heap wastage: - The system easily dedicates spare CPU cores to continuous garbage collection tasks without impacting application throughput. - Traditional stop-the-world collectors force administrators to run heaps dangerously close to OutOfMemory limits to minimize garbage collection pause lengths. - Because Azul eliminates pause times entirely, deployments deliberately provision heaps with generous buffer headroom ("slop"), relieving allocation pressure and giving the concurrent collector plenty of runway to run without risking an out-of-memory crisis.
[01:11:28](https://www.youtube.com/watch?v=5uljtqyBLxI&t=4288s) Garbage Collection Headroom and Wrap-Up
Wrapping up an answer regarding garbage collector headroom and heap margins, Cliff Click explains the trade-off between heap headroom and processor utilization. When running with tight margins, the collector simply has to work much harder to keep up: “the GC cycle is faster and faster, it burns CPU.” He notes that the system is fully capable of operating under these constrained conditions, stating, “But it will comfortably run at, you know, 10%, 20% over live heap.” However, running with only a 10% to 20% cushion beyond the live data set comes with an operational penalty: “You'll just be burning a lot of CPU to do it.”
Click cautions that while the runtime will not fall over or crash when pushed into such tight bounds, dedicating that much processing power solely to recycling memory is inefficient: “This is--it's not necessarily where you want to set yourself.” With that final insight on GC sizing and headroom trade-offs, the attendee thanks Click, and Click closes out the presentation by thanking the audience.
- **Headroom vs. CPU Overhead:** Operating at 10% to 20% above live heap size is technically sustainable for the Azul collector, but it drives up collection frequency and consumes significant CPU cycles that would otherwise be available for application throughput. - **Session Conclusion:** The talk concludes with audience appreciation and Click’s closing thanks.
## Notable quotes > [03:24](https://www.youtube.com/watch?v=5uljtqyBLxI&t=204s) You must have like a really, really good reason to buy custom hardware for the obvious X86 solution. And, you know, a merely 5x price performance kind of gain is not really good enough to make people jump ship there. — Cliff Click
> [52:31](https://www.youtube.com/watch?v=5uljtqyBLxI&t=3151s) If you own the whole stack, hardware and up, you can do progress even with some of the real awful hardware bugs, right? — Cliff Click
## Mentioned ARM Jazelle, Azul Systems, Cliff Click, Doug Lea, ECOOP, GCC, Google, Google TechTalks, HP-UX, HotSpot, Intel, JBoss, Pauseless Garbage Collector, Paul Lucchesi, Real-Time Performance Monitor (RTPM), Rock processor, SPARC, Sun Microsystems, Symbolics, TSMC, Thread Priority Manager (TPM), VEE 2005, Vega, Vega 1, Vega 2, Vega 3, WebLogic, WebSphere, high-scale-lib, picoJava, x86
## Video description Google Tech Talk August 12, 2009
ABSTRACT
Presented by Cliff Click, Azul Systems.
Azul Systems designs and builds systems for running business logic applications written in Java. Unlike scientific computing, business logic code tends to be very large and complex (greater than 1MLOC is common), display very irregular data access patterns, and make heavy use of threads and locks. The common unit of parallelism is the transaction or thread-level task. Business logic programs tend to have high allocation rates which scale up with the amount of work accomplished, and they are sensitive to Garbage Collection max-pause-times. Typical JVM implementations for heaps greater than 4 Gigabytes have unacceptable pause times and this forces many applications to run clustered.
Our systems support heaps up to 600 Gigabytes and allocation rates up to 35 Gig/s with pause times in the dozen-millisecond range. We have large core counts (up to 864) for running parallel tasks; our memory is Uniform Memory Access (as opposed to the more common NUMA), cache-coherent, and has supercomputer-level bandwidth. The cores are our own design; simple 3-address RISCs with read- & write-barriers to support GC, hardware transactional memory, zero-cost high-rez profiling, and some more modest Java-specific tweaks.
This talk is about the business environment which drove the design of the hardware (e.g. why put in HTM support? why our own CPU design and not e.g. MIPS or X86?), some early company history with designing our own chips (1st silicon back from the fab had problems like the bits in the odd-numbered registers bleeding into the even-numbered registers), and finally some wisdom and observations from a tightly integrated hardware/software co-design effort.
[Source](https://www.youtube.com/watch?v=5uljtqyBLxI)