aboutsummaryrefslogtreecommitdiff
path: root/src/zencore
diff options
context:
space:
mode:
authorDan Engelbrecht <[email protected]>2026-04-27 11:14:09 +0200
committerGitHub Enterprise <[email protected]>2026-04-27 11:14:09 +0200
commit753ab4e89b9a5952e50bc77d404198520b362a3a (patch)
tree39dbaad8389677981281b8c1585ac846251539f0 /src/zencore
parentfix crash when scavenging sequences or copying local chunks (#1013) (diff)
downloadarchived-zen-753ab4e89b9a5952e50bc77d404198520b362a3a.tar.xz
archived-zen-753ab4e89b9a5952e50bc77d404198520b362a3a.zip
hydration with pack (#1016)
- Feature: Hub hydration packs small files into raw CAS pack blobs to reduce request count for modules dominated by tiny metadata files - `--hub-hydration-enable-pack` (Lua: `hub.hydration.enablepack`, default true) - `--hub-hydration-pack-threshold-bytes` (Lua: `hub.hydration.packthresholdbytes`, default 256 KiB) - `--hub-hydration-max-pack-bytes` (Lua: `hub.hydration.maxpackbytes`, default 4 MiB) - Feature: Hub hydration and dehydration can be disabled per direction - `--hub-enable-hydration` (Lua: `hub.enablehydration`, default true) - `--hub-enable-dehydration` (Lua: `hub.enabledehydration`, default true) - Feature: Hub hydration accepts a configurable file exclude list via `HydrationOptions` `excludes` (array of wildcards). Built-in defaults skip transient runtime files (`.lock`, `.sentry-native/*`, `state_marker`, `*.bak`, `gc/reserve.gc`, `auth/*`) so they no longer participate in dehydrate scans. Override semantics: a present field replaces the default outright; explicit `[]` opts out of all defaults. - Improvement: Hub hydration completion logs now report per-request average and max latency, peak in-flight workers, queue wait, and hash-cache hit percentage; loose and pack-blob transfers are reported separately - Improvement: Hub hydration pre-creates unique parent directories before scheduling parallel writes - Improvement: S3 hydration retries transient HTTP failures (timeouts, 429 throttling, 5xx server errors, connection errors) up to 3 times via the HTTP client retry layer - Improvement: S3 hydration multipart chunk size is persisted in `state.cbo` per module so hydrate replays the partitioning used at dehydrate; default raised to 64 MiB (was 32 MiB) - Improvement: Hub hydration `Obliterate` retries backend delete once before falling back to local cleanup
Diffstat (limited to 'src/zencore')
-rw-r--r--src/zencore/include/zencore/string.h6
-rw-r--r--src/zencore/string.cpp62
2 files changed, 68 insertions, 0 deletions
diff --git a/src/zencore/include/zencore/string.h b/src/zencore/include/zencore/string.h
index a1c7a3914..7ca2afc69 100644
--- a/src/zencore/include/zencore/string.h
+++ b/src/zencore/include/zencore/string.h
@@ -742,6 +742,7 @@ size_t NiceBytesToBuffer(uint64_t Num, std::span<char> Buffer);
size_t NiceByteRateToBuffer(uint64_t Num, uint64_t ms, std::span<char> Buffer);
size_t NiceLatencyNsToBuffer(uint64_t NanoSeconds, std::span<char> Buffer);
size_t NiceTimeSpanMsToBuffer(uint64_t Milliseconds, std::span<char> Buffer);
+size_t NiceTimeSpanUsToBuffer(uint64_t Microseconds, std::span<char> Buffer);
struct NiceBase
{
@@ -803,6 +804,11 @@ struct NiceTimeSpanMs : public NiceBase
inline NiceTimeSpanMs(uint64_t Milliseconds) { NiceTimeSpanMsToBuffer(Milliseconds, m_Buffer); }
};
+struct NiceTimeSpanUs : public NiceBase
+{
+ inline NiceTimeSpanUs(uint64_t Microseconds) { NiceTimeSpanUsToBuffer(Microseconds, m_Buffer); }
+};
+
//////////////////////////////////////////////////////////////////////////
inline std::string
diff --git a/src/zencore/string.cpp b/src/zencore/string.cpp
index 34519b83b..4072aec56 100644
--- a/src/zencore/string.cpp
+++ b/src/zencore/string.cpp
@@ -482,6 +482,24 @@ NiceTimeSpanMsToBuffer(uint64_t Millis, std::span<char> Buffer)
}
}
+size_t
+NiceTimeSpanUsToBuffer(uint64_t Micros, std::span<char> Buffer)
+{
+ if (Micros < 1000)
+ {
+ return snprintf(Buffer.data(), Buffer.size(), "%" PRIu64 "us", Micros);
+ }
+ else if (Micros < 10000)
+ {
+ return snprintf(Buffer.data(), Buffer.size(), "%.2fms", Micros / 1000.0);
+ }
+ else if (Micros < 1000000)
+ {
+ return snprintf(Buffer.data(), Buffer.size(), "%.1fms", Micros / 1000.0);
+ }
+ return NiceTimeSpanMsToBuffer(Micros / 1000, Buffer);
+}
+
//////////////////////////////////////////////////////////////////////////
template<typename C>
@@ -850,6 +868,13 @@ TEST_CASE("niceNum")
NiceNumGeneral(100000000000000, Buffer, kNicenumTime);
CHECK(StringEquals(Buffer, "100000s"));
+
+ // floor() instead of round(): 999.5us must NOT render as "1000us".
+ NiceNumGeneral(999500, Buffer, kNicenumTime);
+ CHECK(StringEquals(Buffer, "999us"));
+
+ NiceNumGeneral(999999, Buffer, kNicenumTime);
+ CHECK(StringEquals(Buffer, "999us"));
}
SUBCASE("bytes")
@@ -917,6 +942,43 @@ TEST_CASE("niceNum")
NiceTimeSpanMsToBuffer(360000000, Buffer);
CHECK(StringEquals(Buffer, "100h00m"));
}
+
+ SUBCASE("timespan_us")
+ {
+ NiceTimeSpanUsToBuffer(0, Buffer);
+ CHECK(StringEquals(Buffer, "0us"));
+
+ NiceTimeSpanUsToBuffer(1, Buffer);
+ CHECK(StringEquals(Buffer, "1us"));
+
+ NiceTimeSpanUsToBuffer(999, Buffer);
+ CHECK(StringEquals(Buffer, "999us"));
+
+ NiceTimeSpanUsToBuffer(1000, Buffer);
+ CHECK(StringEquals(Buffer, "1.00ms"));
+
+ NiceTimeSpanUsToBuffer(1500, Buffer);
+ CHECK(StringEquals(Buffer, "1.50ms"));
+
+ NiceTimeSpanUsToBuffer(9999, Buffer);
+ CHECK(StringEquals(Buffer, "10.00ms")); // %.2f rounds 9.999 -> 10.00
+
+ NiceTimeSpanUsToBuffer(10000, Buffer);
+ CHECK(StringEquals(Buffer, "10.0ms"));
+
+ NiceTimeSpanUsToBuffer(999500, Buffer);
+ CHECK(StringEquals(Buffer, "999.5ms"));
+
+ NiceTimeSpanUsToBuffer(999999, Buffer);
+ CHECK(StringEquals(Buffer, "1000.0ms")); // boundary just below 1s
+
+ // >=1s delegates to NiceTimeSpanMs.
+ NiceTimeSpanUsToBuffer(1000000, Buffer);
+ CHECK(StringEquals(Buffer, "1.00s"));
+
+ NiceTimeSpanUsToBuffer(60000000, Buffer);
+ CHECK(StringEquals(Buffer, "1m00s"));
+ }
}
TEST_CASE("StringBuilder")