GregM
10/26/2026, 2:34 PMRocky
10/26/2026, 2:35 PMfslib) and underlying cloud SDKs (like ADLS Gen2) is not fully accounted for in the internal /mem_tracker.
Is this memory supposed to be outside trackers?
Yes, in current and many older versions, memory allocated within the fslib layer—specifically by BufferInputStream and the Azure/ADLS SDK wrappers—is often untracked.
* Why: These allocations happen deep in the filesystem library or third-party SDKs that are not always instrumented with StarRocks' MemTracker hooks.
* Total vs. Breakdown: This explains why your process total (jemalloc stats.allocated) is ~130 GiB while the sum of child trackers is only ~5 GiB. The remaining ~125 GiB is "untracked" heap memory.
Is there a bound or a known leak?
The fact that 5.6 GiB out of the latest 7 GiB of live allocations belongs to fslib::BufferInputStream strongly suggests a leak or an unbounded growth of stream buffers.
1. Buffer Management: StarCacheInputStream uses buffers to read data from remote storage (ADLS2) to populate the local Data Cache or to serve queries directly when there is a cache miss. If these streams are not closed promptly (e.g., due to a query being canceled or a bug in the stream lifecycle), the buffers remain in jemalloc.
2. Direct I/O Impact: Enabling datacache_direct_io_enable allows the Data Cache (Block Cache) to bypass the kernel page cache for disk I/O. However, it does not affect application-level heap buffers. Even with direct I/O on, the BufferInputStream will still allocate heap memory via jemalloc for its internal buffering.
3. Known Issues:
* In earlier v3.x versions, there were issues where starlet (the underlying cloud-native library) metadata and certain read streams could grow significantly.
* Fixes in versions like v3.1.9 and v3.2.4 addressed high memory usage in CN nodes where fslib meta-memory was not being reclaimed properly.
* If you are on a version earlier than v3.3.0, you may be hitting a known issue with stream handle leaks or metadata overhead.
Recommended Actions
1. Check StarRocks Version: If you are below v3.2.4 or v3.3.0, consider upgrading to the latest maintenance release in your branch (e.g., v3.2.x or v3.3.x).
2. Investigate Starlet Metadata: Check the size of the cache metadata directory on disk: ${storage_root_path}/starlet_cache/star_cache/meta. If this is massive, it indicates a metadata leak.
3. Tune Relevant Configs:
* `starlet_filesystem_instance_cache_capacity`: Controls the number of cached filesystem instances.
* `lake_compaction_stream_buffer_size_bytes`: (Default 1MB) Controls buffers during compaction. If many compactions run in parallel, this adds up.
4. Monitor Stream Closure: Check your BE logs (<http://be.INFO|be.INFO> and be.WARNING) for errors related to "failed to close stream" or "ADLS2 error". Leaking streams are often preceded by remote I/O timeouts or networking errors that prevent standard cleanup paths from executing.
If the untracked memory continues to grow linearly despite no active queries, it is a confirmed leak in the fslib stream handling layer. You should report this to the community with the specific jemalloc trace you've captured.
References
• using_starrocks/caching/block_cache.md
• data_source/data_cache_observe.md
• knowledge/trouble_shooting/fe_memory_problems.mdGregM
10/26/2026, 2:37 PMRocky
10/26/2026, 2:38 PMfslib) and the underlying ADLS2 filesystem wrapper.
1. Is this memory supposed to be outside trackers?
Yes, in the current architecture, memory allocated by fslib::BufferInputStream and the Azure SDK (ADLS2) is often not instrumented with StarRocks' MemTracker.
* Tracked vs. Untracked: The MemTracker tree usually covers query execution, memtables, and metadata. However, the buffers used by fslib to pull data from object storage into the Data Cache (StarCache) or to serve query misses are often allocated directly via jemalloc without a tracker hook.
* StarCache Role: Your trace shows StarCacheInputStream::read_one_block triggering these allocations. This happens when the Data Cache is fetching a block from ADLS to either fill the local cache or satisfy a read.
2. Is there a bound or a known leak?
Given that nearly 125 GiB is untracked on a 192 GiB node, this is either a leak or a configuration that allows in-flight buffers to grow indefinitely.
* `datacache_max_flying_memory_mb`: This is the primary parameter introduced to bound exactly what you are seeing—the memory used for "flying" (in-flight) cache operations. In v4.1.1, if this is not configured or set too high, the system may allow an unbounded number of BufferInputStream objects to coexist during high I/O or background cache prefetching.
_ _Action:* Check your BE/CN config. If it's unset, try setting it to a reasonable value (e.g., 10240 for 10 GiB) to see if it caps the growth.
* The "Stream Leak" Hypothesis: Your jemalloc profile shows 5.6 GiB of the newest 7 GiB is BufferInputStream. If this memory remains "live" even after query activity stops, it is a confirmed leak.
* Direct I/O Impact: Turning datacache_direct_io_enable = on correctly evicts the kernel page cache (which you saw drop to <1 GiB), but it places a higher burden on StarRocks to manage its own user-space buffers. In some v4.1 edge cases, if a stream is interrupted (e.g., query timeout or network jitter with ADLS), the BufferInputStream may fail to close, leaking the jemalloc-allocated buffer.
* Large Tablet Impact: v4.1 introduces support for 100 GB tablets. Larger tablets can lead to larger contiguous read streams. If the buffer size or the number of concurrent streams isn't strictly capped, the memory footprint scales quickly.
3. Recommended Diagnostics & Tuning
1. Restrict Flying Memory: Set datacache_max_flying_memory_mb in your cn.conf (e.g., 2048 or 4096) and restart. If memory still climbs to 130 GiB, the limit is being bypassed, which suggests a lower-level leak in the ADLS2 wrapper.
2. Verify Stream Closure: Check your <http://be.INFO|be.INFO> logs for strings like failed to close or ADLS2 error. If you see frequent remote I/O errors, it’s likely that the cleanup path for BufferInputStream is being skipped.
3. Check Starlet Metadata: Check the size of ${storage_root_path}/starlet_cache/star_cache/meta. While your trace points to data streams, massive metadata can also contribute to untracked overhead.
4. Version Specifics: Since v4.1.1 is a very recent release featuring significant changes to the shared-data architecture (like adaptive distribution), this may be a regression in how ADLS streams are lifecycle-managed. I recommend reporting this jemalloc trace to the StarRocks community Slack or GitHub, as 125 GiB of untracked stream buffers is abnormal for a 192 GiB node.
Key Configs to Check:
* datacache_max_flying_memory_mb (Limit for in-flight cache I/O)
* lake_read_stream_buffer_size_bytes (Size of each stream buffer)
* starlet_filesystem_instance_cache_capacity (Number of FS handles)
ReferencesRocky
10/26/2026, 2:38 PMGregM
10/26/2026, 5:11 PMRocky
10/26/2026, 5:11 PMfslib (filesystem library) and the underlying cloud SDKs (like ADLS2) is often untracked.
* The Gap: StarRocks' internal /mem_tracker (and the child trackers you see) primarily instruments query execution, memtables, and metadata. However, the buffers used by fslib::BufferInputStream and the Azure C++ SDK are allocated directly via jemalloc without being wrapped in StarRocks' tracking hooks.
* The Evidence: Your observation (Process ~130 GiB vs. Trackers ~5 GiB) is the classic symptom of large-scale allocations in these lower-level libraries.
2. Is there a bound, or a known leak?
There is supposed to be a bound, but your profile suggests either it's being bypassed or a leak is occurring in the ADLS2 stream lifecycle.
* datacache_max_flying_memory_mb: This is the primary parameter intended to cap the memory used by in-flight ("flying") I/O operations in the Data Cache. If this is unset or set too high, the system may allow an unlimited number of BufferInputStream buffers to be active simultaneously.
* Recommendation: Check your current value for datacache_max_flying_memory_mb. If it is at the default (often very high or unbounded), try setting it to a conservative value (e.g., 8192 or 16384 for 8-16 GiB) to see if it forces the process to stay within cgroup limits.
* The Leak Trace: Your trace fslib::BufferInputStream -> ADLS2ReadOnlyFile -> ... -> StarCacheInputStream::read accounts for the vast majority of your memory growth. If this memory remains "Live" even when the cluster is idle, it is a confirmed leak.
* Direct I/O Correlation: Turning datacache_direct_io_enable = on correctly bypassed the kernel page cache (dropping it to <1 GiB), but it shifted the buffering responsibility entirely to these user-space BufferInputStream objects. In v4.1.1, there may be a regression where ADLS2 streams are not being destroyed/closed properly upon query completion or failure, especially when Direct I/O is involved.
3. Connection to Issue #81608
Since you have already opened GitHub Issue #81608, the community maintainers will likely focus on the StarCacheReadOnlyFile::get_persist_stream path. This path indicates that while reading from the local Data Cache, the system is opening a stream to the "persist" (remote) source, likely for a cache miss or background prefetch, and failing to release the buffer.
Immediate Workarounds
1. Set datacache_max_flying_memory_mb: Explicitly cap this to a small fraction of your RAM (e.g., 5-10% of 192 GiB).
2. Monitor ADLS Errors: Check <http://be.INFO|be.INFO> for failed to close stream or Timeout errors. Leaks in the Azure SDK often occur when a stream enters an error state and the StarRocks cleanup logic is bypassed.
3. Restart Frequency: Given the 125 GiB discrepancy, if the flying memory limit doesn't help, this is a linear leak that will require a process restart until the fix in #81608 is merged.
I recommend attaching the full text of your jemalloc trace to that GitHub issue, as it provides the exact smoking gun for the fslib developers.
References
• using_starrocks/caching/block_cache.md
• data_source/data_cache.md
• data_source/data_cache_troubleshooting.md
• data_source/datalake_faq.md
• administration/management/BE_configuration.mdGregM
10/26/2026, 5:20 PMBE_ID |NAME |VALUE |
------+------------------------------------------+-------+
803329|datacache_max_flying_memory_mb |2 |
803329|starlet_filesystem_instance_cache_capacity|10000 |
803329|starlet_fs_stream_buffer_size_bytes |1048576|
759187|datacache_max_flying_memory_mb |2 |
759187|starlet_filesystem_instance_cache_capacity|10000 |
759187|starlet_fs_stream_buffer_size_bytes |1048576|
801554|datacache_max_flying_memory_mb |2 |
801554|starlet_filesystem_instance_cache_capacity|10000 |
801554|starlet_fs_stream_buffer_size_bytes |1048576|Rocky
10/26/2026, 5:21 PMfslib::BufferInputStream objects being opened via the ADLS2 filesystem during Data Cache operations (StarCacheInputStream::read).
1. Is this memory supposed to be outside trackers?
Yes, technically. In the current architecture (including v4.1.1), memory allocated by the fslib library and underlying cloud SDKs (ADLS2/S3) is not instrumented with the StarRocks MemTracker hooks.
* These are considered "external" library allocations.
* Because fslib::BufferInputStream uses standard operator new (which you see in your trace), it bypasses the internal tracking system used for query execution and metadata.
2. Is there a bound, or a known leak?
There is a bound, but your data proves it is being bypassed or leaked:
* The Bound: datacache_max_flying_memory_mb is specifically designed to limit the memory used by in-flight ("flying") I/O buffers. You have it set to 2 MiB, yet you have ~125 GiB of these buffers. This confirms that either:
1. The StarCacheReadOnlyFile::get_persist_stream path is not accounted for in the "flying memory" bucket (a bug).
2. There is a reference count leak, where BufferInputStream objects are created for every read miss but never destroyed/closed, effectively making the "limit" irrelevant as the memory is "leaked" rather than "in-flight."
* The Leak: With starlet_fs_stream_buffer_size_bytes = 1048576 (1 MiB), your ~125 GiB of usage implies there are roughly 125,000 active/leaked stream buffers. Even with your starlet_filesystem_instance_cache_capacity at 10,000, it cannot account for this scale of growth.
* Direct I/O Correlation: By turning datacache_direct_io_enable = on, you have successfully eliminated the kernel file cache overhead (which you saw at 2 GiB). However, this forces StarRocks to rely entirely on its own user-space buffering. In v4.1.x, there appears to be a regression where the lifecycle of persist_stream (the remote ADLS connection) is not being managed correctly when accessed via the Data Cache.
3. Analysis of your Trace
The trace StarCacheInputStream::read -> read_one_block -> get_persist_stream -> ADLS2FileSystem::open -> fslib::BufferInputStream is the critical path.
* In Shared-data mode, if a block is missing from the local Data Cache, get_persist_stream is called to fetch it from ADLS.
* In v4.1.1, it seems every such call may be creating a new stream instance that is never returned to a pool or closed, especially if the query that triggered it is finished or canceled.
Recommendations
Since you have already opened GitHub Issue #81608, you have provided the developers with exactly what they need. To mitigate this in the meantime:
1. Reduce starlet_filesystem_instance_cache_capacity: Try lowering this from 10000 to 1000. While it shouldn't cause 125 GiB of usage, it may reduce the number of cached file handles that are potentially pinning these streams.
2. Verify ADLS Errors: Check <http://be.INFO|be.INFO> for ADLS2 related errors or failed to close. Often, a network timeout causes the stream cleanup logic to be skipped.
3. Check for Version Fixes: There are known fixes in the v4.1.x maintenance branch (like v4.1.4+) addressing memory leaks in the ADLS2 connector and starlet metadata. Since you are on v4.1.1, an upgrade to the latest patch in the v4.1 series is highly recommended.
4. Workaround (Temporary): Disable datacache_adaptor_enable or the cache prefetcher if you suspect aggressive prefetching is triggering the surge in persist_stream calls.Rocky
10/26/2026, 5:21 PMdatacache_max_flying_memory_mb = 2 setting makes it a high-priority fix for the maintainers of that GitHub issue.GregM
10/26/2026, 5:24 PMRocky
10/26/2026, 5:24 PMBufferInputStream and ADLS2 streams are consuming nearly the entire heap—there are several relevant fixes and optimizations in the v4.1.x maintenance line (up to v4.1.6 and beyond).
Since your jemalloc trace identifies fslib::BufferInputStream as the primary consumer (accounting for ~125 GiB), these specific PRs and version updates address related lifecycle and memory management bugs in the storage layer:
1. Azure / Starlet Client Lifecycle Fixes
Several issues were identified where filesystem clients or stream handles were not correctly released or were causing contention in Starlet (the storage orchestration layer):
* PR #71459 & #70586: Addresses Azure filesystem client cache issues in Starlet. These fixes ensure that connections and stream buffers to Azure (ADLS2) are lifecycle-managed more strictly, preventing "zombie" streams from pinning memory.
* PR #78448 (v4.1.6): Makes Starlet object-store upload/read thresholds configurable at runtime and improves the cleanup of transient buffers.
2. Jemalloc Fragmentation & Large Buffer Reuse
The fact that you see ~125 GiB of untracked memory is often exacerbated by jemalloc fragmentation when large I/O buffers are frequently allocated and freed.
* PR #78396 (v4.1.6): Enables jemalloc's dedicated oversize arena by default. This change is specifically designed for scenarios like yours—where large buffers (like your 1 MiB stream buffers) are used. It prevents these allocations from landing in per-CPU arenas, which significantly improves memory reuse and reduces the "bloat" where jemalloc holds onto memory that it can't return to the OS.
3. bRPC and Metadata Leaks
* PR #75973 (v4.1.x): Fixes a bRPC stub cache timer leak that caused memory to grow slowly over time. While smaller than your current issue, it contributes to overall process instability.
* PR #76870: Improves reclamation of tablet metadata.
Summary of Recommendations
While your specific issue *#81608* is a more recent report (likely targeting a regression in the Data Cache's get_persist_stream logic), the following steps are standard for v4.1.1 users facing this profile:
1. Upgrade to v4.1.6+: This version includes the jemalloc oversize arena optimization and the Azure client cache fixes mentioned above.
2. Explicitly Tune Starlet: In your `cn.conf`/`be.conf`, ensure starlet_filesystem_instance_cache_capacity is not set excessively high (your 10,000 is quite large; try 1,000 to force more frequent handle recycling).
3. Check lake_enable_protobuf_file_checksum: Introduced in v4.1.4, this helps prevent corruption in shared-data metadata which can sometimes cause infinite retry loops (and thus memory surges) in the storage layer.
Reference:
• StarRocks v4.1 Release Notes
• BE Configuration Parameters
References
• release_notes/release-3.4.md
• release_notes/release-4.0.md
• release_notes/release-3.2.mdGregM
10/26/2026, 5:37 PMFail to publish partition 6099309 error Fail to publish version for tablets:[[6099313, 6099310, 6099315, 6099311, 6099314, 6099312]], error msg: sstables are not ordered, last_max_rss_rowid=781684047871 : max_rss_rowid=781684047870, host: kube-starrocks-cn-0.kube-starrocks-cn-search.kube-starrocks.svc.cluster.local
as documented here https://starrocks.slack.com/archives/C02FACZSNJV/p1791296654694139Rocky
10/26/2026, 5:37 PMPublish task for that partition.
2. Why it didn't fail in v4.1.1
In v4.1.1, the check was likely less strict or absent. You were able to load data, but you were effectively "running on thin ice"—the underlying metadata was potentially inconsistent, but the system didn't stop you. The fact that last_max_rss_rowid=781684047871 is greater than the current max_rss_rowid=781684047870 in your error message is a definitive proof of this existing inconsistency.
3. How to resolve this
Since your main goal is to solve the memory leak in v4.1.1 without breaking your cluster on v4.1.6, here is the recommended path:
* For the "SSTables are not ordered" error:
1. Check for the fix in later patches: This specific "misordering" issue was a high-priority fix. Check the release notes for v4.1.7 or v4.1.8 to see if the validation logic was adjusted to handle legacy inconsistencies more gracefully.
2. Repair the Table: If a specific partition is stuck, the safest way to "clean" the metadata is to TRUNCATE or DROP/RECREATE that specific partition. Since this is a Primary Key table, re-loading the data will regenerate the index correctly and resolve the order issue.
3. Disable the check (Use with Caution): There are internal BE configurations that can sometimes bypass these checks, but I do not recommend this as it risks silent data corruption.
4. Summary Recommendation
You are caught between two issues: a massive memory leak in v4.1.1 (confirmed by your jemalloc trace in #81608) and a strict metadata check in v4.1.6.
1. Do not stay on v4.1.1. The memory leak is severe, and you likely have the "misordered SSTable" bug silently occurring in the background.
2. Move to v4.1.7+ or v4.1.8+ (if available). These versions include the fix for the memory leak (via jemalloc improvements and Azure client fixes) and may have better handling for the metadata transition.
3. If the "sstables are not ordered" error persists after upgrading to a later patch, it confirms your data is already inconsistent. You should re-load the affected partitions to ensure data integrity.
I recommend posting the "sstables are not ordered" error directly into your GitHub issue #81608 as well, as the maintainers can confirm if the fix for that error is also backported to the same version that fixes your memory leak.
References
• administration/management/BE_configuration.md
• using_starrocks/sorted_aggregate.md