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
@@ -491,6 +491,8 @@ Precomputed percentile values can not. Percentiles are unique to each dataset (t
491
491
492
492
== Automatically generated metrics
493
493
494
+
=== HTTP server
495
+
494
496
The Micrometer extension automatically times HTTP server requests. Following Prometheus naming conventions for
495
497
timers, look for `http_server_requests_seconds_count`, `http_server_requests_seconds_sum`, and
496
498
`http_server_requests_seconds_max`. Dimensional labels have been added for the requested uri, the HTTP method
@@ -525,6 +527,155 @@ For example, setting
525
527
By default, the metrics are exported using the Prometheus format `application/openmetrics-text`,
526
528
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/`).
527
529
530
+
=== Netty memory management metrics
531
+
532
+
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.
533
+
534
+
In short, Netty provides an _efficient_ memory management system for asynchronous applications.
535
+
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.
536
+
537
+
==== Memory Categories in Netty
538
+
Netty uses two primary memory categories:
539
+
540
+
1. **Heap Memory**
541
+
- Allocated from the JVM heap (`byte[]`).
542
+
- Managed by the garbage collector.
543
+
- Slower for I/O operations because it requires copying data to/from direct memory before sending over a socket.
544
+
545
+
2. **Direct Memory**
546
+
- Allocated outside the JVM heap using `ByteBuffer.allocateDirect()`.
547
+
- Not managed by the garbage collector, reducing GC pressure.
548
+
- Faster for I/O operations as it avoids unnecessary copying.
549
+
550
+
[NOTE]
551
+
====
552
+
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.
553
+
554
+
These Netty metrics help evaluate how much room is needed.
555
+
====
556
+
557
+
==== Pooling Mechanism
558
+
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:
559
+
560
+
- **Arenas**: Large memory blocks that manage allocations.
561
+
- **Chunks**: Memory segments within arenas (typically 16MB in size).
562
+
- **Pages**: Fixed-size portions of a chunk (usually 8KB).
563
+
- **Subpages**: Smaller allocations within a page for tiny objects.
564
+
- **Thread-local Caches**: Per-thread cache for frequently used small buffers, reducing contention.
565
+
566
+
==== Metrics for Netty Memory Management
567
+
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**
583
+
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.
597
+
598
+
|===
599
+
| Metric Name | Description | Type | Tags
600
+
601
+
| `allocator.pooled.arenas`
602
+
|Number of arenas handling memory allocation
603
+
|Gauge
604
+
| `memory_type=[heap, direct]`
605
+
606
+
|===
607
+
608
+
===== **4. Cache Size Metrics**
609
+
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.
610
+
611
+
|===
612
+
| Metric Name | Description | Type | Tags
613
+
614
+
| `allocator.pooled.cache.size`
615
+
|Size of the buffer cache
616
+
|Gauge
617
+
| `cache_type=[small, normal]`
618
+
619
+
|===
620
+
621
+
===== **5. Thread-Local Cache Metrics**
622
+
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)
623
+
624
+
|===
625
+
| Metric Name | Description | Type | Tags
626
+
627
+
| `allocator.pooled.threadlocal.caches`
628
+
|Number of thread-local caches for buffers
629
+
|Gauge
630
+
| None
631
+
632
+
|===
633
+
634
+
===== **6. Chunk Size Metrics**
635
+
Chunks are the primary unit of memory allocation in Netty's arenas.
636
+
637
+
|===
638
+
| Metric Name | Description | Type | Tags
639
+
640
+
| `allocator.pooled.chunk.size`
641
+
|Size of a memory chunk in pooled allocator
642
+
|Gauge
643
+
| None
644
+
645
+
|===
646
+
647
+
[[quarkus-extensions-using-micrometer]]
648
+
=== List of Quarkus core extensions automatically instrumented with Micrometer
0 commit comments