You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -489,6 +489,8 @@ Precomputed percentile values can not. Percentiles are unique to each dataset (t
489
489
490
490
== Automatically generated metrics
491
491
492
+
=== HTTP server
493
+
492
494
The Micrometer extension automatically times HTTP server requests. Following Prometheus naming conventions for
493
495
timers, look for `http_server_requests_seconds_count`, `http_server_requests_seconds_sum`, and
494
496
`http_server_requests_seconds_max`. Dimensional labels have been added for the requested uri, the HTTP method
@@ -523,6 +525,155 @@ For example, setting
523
525
By default, the metrics are exported using the Prometheus format `application/openmetrics-text`,
524
526
you can revert to the former format by specifying the `Accept` request header to `text/plain` (`curl -H "Accept: text/plain" localhost:8080/q/metrics/`).
525
527
528
+
=== Netty memory management metrics
529
+
530
+
https://netty.io/[Netty] memory management metrics are important because Quarkus is built on top of https://vertx.io/[Eclipse Vert.x], which is a framework built on top of Netty to create reactive applications in Java. Even if you use imperative style programing in Quarkus, under the surface it is conveniently handled by Vert.x in a reactive way.
531
+
532
+
In short, Netty provides an _efficient_ memory management system for asynchronous applications.
533
+
It offers different types of memory allocation strategies, including **heap** (stored in the JVM heap) and direct memory (allocated outside the JVM memory), along with a **buffer pooling mechanism** to optimize allocations and reduce garbage collection (GC) overhead.
534
+
535
+
==== Memory Categories in Netty
536
+
Netty uses two primary memory categories:
537
+
538
+
1. **Heap Memory**
539
+
- Allocated from the JVM heap (`byte[]`).
540
+
- Managed by the garbage collector.
541
+
- Slower for I/O operations because it requires copying data to/from direct memory before sending over a socket.
542
+
543
+
2. **Direct Memory**
544
+
- Allocated outside the JVM heap using `ByteBuffer.allocateDirect()`.
545
+
- Not managed by the garbage collector, reducing GC pressure.
546
+
- Faster for I/O operations as it avoids unnecessary copying.
547
+
548
+
[NOTE]
549
+
====
550
+
Using a very high value for -XX:MaxRAMPercentage (allocating most of the available RAM to the Java heap) is not recommended for Quarkus applications, as it’s important to leave room for Netty's native memory allocations.
551
+
552
+
These Netty metrics help evaluate how much room is needed.
553
+
====
554
+
555
+
==== Pooling Mechanism
556
+
Netty uses **PooledByteBufAllocator** to reduce memory allocation overhead and fragmentation. It is based on a **jemalloc-style arena system** (see https://github.com/jemalloc/jemalloc[jemalloc/jemalloc]), which includes:
557
+
558
+
- **Arenas**: Large memory blocks that manage allocations.
559
+
- **Chunks**: Memory segments within arenas (typically 16MB in size).
560
+
- **Pages**: Fixed-size portions of a chunk (usually 8KB).
561
+
- **Subpages**: Smaller allocations within a page for tiny objects.
562
+
- **Thread-local Caches**: Per-thread cache for frequently used small buffers, reducing contention.
563
+
564
+
==== Metrics for Netty Memory Management
565
+
The Micrometer metrics report key metrics from Netty's allocator, helping monitor memory usage, pinned memory, pooling efficiency, and cache behavior.
===== **2. Pooled Allocator - Pinned Memory Metrics**
581
+
Pinned memory refers to buffers that cannot be recycled due to active references, preventing reuse by the allocator. A _high_ number may indicate some kind of leak (as reference are not released).
Arenas (large size of memory) manage memory allocations efficiently by grouping chunks of memory. So this metric is the number of arenas allocated for a given allocator.
595
+
596
+
|===
597
+
| Metric Name | Description | Type | Tags
598
+
599
+
| `allocator.pooled.arenas`
600
+
|Number of arenas handling memory allocation
601
+
|Gauge
602
+
| `memory_type=[heap, direct]`
603
+
604
+
|===
605
+
606
+
===== **4. Cache Size Metrics**
607
+
Netty caches small buffers within a given thread to avoid frequent memory allocations and improve performance. If the same thread needs memory, it will first check in its own cache. This is particularly efficient due to the event loop threading model (low number of threads). Note that the tiny caches are now merged into the small ones.
608
+
609
+
|===
610
+
| Metric Name | Description | Type | Tags
611
+
612
+
| `allocator.pooled.cache.size`
613
+
|Size of the buffer cache
614
+
|Gauge
615
+
| `cache_type=[small, normal]`
616
+
617
+
|===
618
+
619
+
===== **5. Thread-Local Cache Metrics**
620
+
These metrics indicate the number of active thread-local caches used for memory pooling. It complements the cache size metrics (cache being the size, and this being the number of cache)
621
+
622
+
|===
623
+
| Metric Name | Description | Type | Tags
624
+
625
+
| `allocator.pooled.threadlocal.caches`
626
+
|Number of thread-local caches for buffers
627
+
|Gauge
628
+
| None
629
+
630
+
|===
631
+
632
+
===== **6. Chunk Size Metrics**
633
+
Chunks are the primary unit of memory allocation in Netty's arenas.
634
+
635
+
|===
636
+
| Metric Name | Description | Type | Tags
637
+
638
+
| `allocator.pooled.chunk.size`
639
+
|Size of a memory chunk in pooled allocator
640
+
|Gauge
641
+
| None
642
+
643
+
|===
644
+
645
+
[[quarkus-extensions-using-micrometer]]
646
+
=== List of Quarkus core extensions automatically instrumented with Micrometer
0 commit comments