summaryrefslogtreecommitdiffstats
path: root/library/cpp
Commit message (Collapse)AuthorAgeFilesLines
* optimize TPagedVectortobo2026-07-041-8/+11
| | | | | | - erase() method erases element from pages first, then pushes back a new one - make size() a bit faster commit_hash:2dd667908f10f03c976c53002e1a9c51cb3be8f6
* Add TAnyObject::Holds<T> and rename IsCurrentlyStored to HoldsTypebabenko2026-07-033-7/+41
| | | | commit_hash:5f0c248f2c24b501b04777fb0300693b0e942c89
* Correctly fork orbits with multiple active shuttles in LWTrace libTaras Pashkin2026-07-033-2/+8
| | | | | | | | | | | | | Original fix merged to the nbs repo a while ago: https://github.com/ydb-platform/nbs/pull/4479 Can you bring to the upstream? --- Pull Request resolved: https://github.com/ytsaurus/ytsaurus/pull/1771 Co-authored-by: Alexander Smirnov <[email protected]> commit_hash:5bf628be8a9c7b591f290ed05754e206b23efc34
* apply style fixes to TPagedVectortobo2026-07-032-62/+72
| | | | | No behaviuor changes, just style fixes commit_hash:0d251b393424c70c7c26c563b08d2746c756c7ad
* Optimize TLogger::WithTag/WithRawTagpechatnov2026-07-036-14/+61
| | | | | Make TLogger::WithTag use a compile-time format string commit_hash:0a119b8eb278bceb411b7d071bbefe0b41e6233d
* optimize TPagedVector + fixed copy assignment and copy constructortobo2026-07-022-23/+154
| | | | | | | | | refactor and fix paged vector: - use more effective THolder instead of TSimpleSharedPtr - fixed copy constructor and copy assignment (was shallow copy instead of deep copy) - no more private inheritance from TVector - add tests for copy and move constructors, copy and move assignments commit_hash:a32c0247dd4cc5f8e29a9046c43627f4ede29044
* Intermediate changesrobot-piglet2026-07-011-0/+2
| | | | commit_hash:f46c06c29696f6cfd01e306372ca9b430bd6b9e3
* Reliable on-demand construction of TThreadLockTracker instancebabenko2026-07-011-3/+8
| | | | commit_hash:39506fb1534ae2d5c5dfe509c9d95a7f74c2aa18
* Fix L-N day-of-month crossing a month boundarybez-tch2026-06-302-1/+90
| | | | | | | | | | | | | | | | | | | | | **Проблема** TCronExpression::CronNext/CronPrev бросал `library/cpp/cron_expression/cron_expression.cpp: Requested date does not exist` для валидного выражения вроде `59 59 23 * *` (UTC) в определённые даты (например, когда now = 30 июня → следующее срабатывание должно быть 30 июля 23:59:59). **Причина** В DoNextPrev шаг по дню месяца определяет, изменилась ли дата, сравнивая только номер дня (value == updateValue). Однако FindDay может перевести календарь через границу месяца/года, попав при этом на тот же номер дня (30 июня → 30 июля, в обоих случаях день 30, потому что `` — это фиксированное смещение от конца месяца). Цикл тогда считает, что ничего не изменилось, пропускает continue, который пере-резолвит секунды/минуты/часы, и оставляет поля времени, которые FindDay уже сбросил в 00:00:00. Финальная проверка консистентности отклоняет 00:00:00 относительно second=\{59\} и бросает исключение. Это было замаскировано, потому что существующие тесты используют \* для полей времени, где 00:00:00 — валидное совпадение. **Фикс** Сохраняем месяц/год до вызова FindDay и требуем, чтобы они остались неизменными (в дополнение к номеру дня), прежде чем считать день окончательным; иначе — перезапускаем цикл. Затрагивает оба направления. commit_hash:62055eed169ba210e81c89aab860301f3e445f46
* Intermediate changesrobot-piglet2026-06-304-3/+11
| | | | commit_hash:a5ad51e30c00aeacf1073d685849e929e3113e9a
* Allow custom socket streams in library/cpp/http/serverkulikov2026-06-285-56/+179
| | | | | | | | | | Prepare to use external coroutine/fiber/etc pool with non-blocking read/writes instead of plain blocking system threads. We already can replace system thread pool with something else, allow to inject different streams around connection socket: - move common part of http connection (http streams and output buffer) directly into it; - replace connection Impl with socket streams provider; - add TClientRequest::CreateHttpConnection factory; - check that we are able to override socket streams in unittest. commit_hash:afe39ce57ee1d10673f4c36a12e01b467d9f77b0
* YT-22593: Add AsciiStringToLower/AsciiStringToUpperbabenko2026-06-282-1/+30
| | | | commit_hash:106e53bffa668818abf8e4003d694e1eb0a0316f
* Use dot librarydon-dron2026-06-2810-2/+604
| | | | commit_hash:46268aab3c7952cc83f661c4c1d1e3c858f20a2d
* Address-salted ref-counted signaturebabenko2026-06-274-0/+118
| | | | | Self-validating signature word at the head of every `TRefCounter` (`YT_ENABLE_REF_COUNTED_SIGNATURE`, on by default in debug) so a coredump walker can distinguish a live ref-counted object from freed-but-unreclaimed memory and locate the counter without virtual-base casts. Consumed by gdb_plugin (separate PR). commit_hash:6696d8c26a8298be6543b1e3456de617d06417e9
* Revert commit rXXXXXX, Add zstd codec on hamsteruranix2026-06-252-3/+0
| | | | commit_hash:8ba59395f9d9a69e5d6ebc82ab5ed0765f142f39
* New version of the tld SKIP_CHECK SKIP_REVIEWrobot-ratatosk2026-06-251-1/+1
| | | | commit_hash:1f26f20bb31b7321a5f24277d10d6bcd814ea442
* YT-28458: Add rseq-backed hot sensorsbabenko2026-06-243-9/+26
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Rename `percpu.{cpp,h}` to `per_cpu.{cpp,h}` and update all includers. Add an rseq-backed implementation of the hot per-CPU counter, time counter and gauge (`rseq_sensor_impl.{h,cpp}`): each update commits to the calling CPU's shard lock-free via an rseq critical section (`library/cpp/yt/rseq` `AddPerCpu`/`StorePerCpu`) — no atomic and no lock on the fast path. The shard array is sized to `NRseq::GetCpuCount()` and folded into the sensor allocation (`NewWithExtraSpace`); reads aggregate with `LoadPerCpu`. The gauge keeps last-writer-wins semantics. Linux-only. The existing `TPerCpu{Counter,TimeCounter,Gauge}` stay (`per_cpu_sensor_impl.{h,cpp}`) as the atomic sharded fallback. The two are interchangeable and chosen per sensor at construction in `TSolomonRegistry`, so the hot Increment/Update path carries no dispatch: * The rseq fast path is **off by default**; opt in via `singletons/solomon_registry/enable_rseq`. Even when on, a hot sensor uses it only in a process where the kernel rseq area sits at a fixed thread-pointer offset (tcmalloc/glibc-owned), per the rseq library's runtime safety probe (`NRseq::IsPerCpuFastPathSafe`). Everything else — notably a `dlopen`'d YQL UDF whose `__rseq_abi` lands in dynamically allocated TLS — uses the atomic sharded sensors. * `TSolomonRegistry` is a reconfigurable singleton (`solomon_registry`) with an `enable_rseq` knob (default false), settable in static config and updatable via dynamic config. Off Linux the rseq sensors do not exist and the registry uses the atomic sharded sensors for hot requests. The per-CPU summary is unchanged (TTscp + spinlock). Unit tests cover the atomic sensors, the rseq sensors (Linux-only), and the simple sensors. The controller-agent memory-watchdog integration tests are made resilient to the (core-count-dependent) per-sensor footprint. Benchmark (hot per-CPU path, 64-core host), atomic sharded vs rseq: | Benchmark | atomic | rseq | speedup | | --- | --- | --- | --- | | BM_PerCpuCounter, threads:1 | 30.7 ns | 3.6 ns | ~8.5x | | BM_PerCpuCounter, threads:16 | 30.9 ns | 4.4 ns | ~7x | | BM_PerCpuGauge, threads:1 | 32.8 ns | 12.4 ns | ~2.6x | | BM_PerCpuGauge, threads:16 | 32.7 ns | 12.5 ns | ~2.5x | commit_hash:8c633d31f03b2cc862ed2217ae08342bf42adc52
* Add ExactRefCountedCast and TRef::Containsbabenko2026-06-247-0/+199
| | | | | | | | | Some handy helpers. `ExactRefCountedCast<T>(p)`: exact-type downcast for `New<T>()`-allocated objects. `New<T>(`) builds a final `TRefCountedWrapper<T>`, so this casts to the wrapper and upcasts back to `T*`; being final, the `dynamic_cast` lowers to a single `type_info` compare (~2ns vs ~20ns for the is-a path). `TRef::Contains(other)`: true iff other's range lies within this range. commit_hash:138e8719b8ecbd953437b81380e54f736db029ef
* Add zstd codec on hamstermaxpogrebnyak2026-06-242-0/+3
| | | | | Добавлена поддержка HTTP-сжатия zstd в apphost http_adapter и включен эксперимент для WEB@hamster. Для этого зарегистрирован кодек zstd в общей HTTP-библиотеке, добавлен отдельный hamster-конфиг с приоритетом zstd. commit_hash:b959243e6a6508f93bd9920c2cc445fa012c8247
* Add std::string-backed stream adapters to library/cpp/yt/stringbabenko2026-06-235-0/+319
| | | | commit_hash:54a07f0d411d0ece7af812a9fdf91509f25ee5cb
* Fix weak ptr for TTrueAtomicSharedPtragri2026-06-231-38/+66
| | | | | | | fix weak ptr add swap test reinterpret\_cast, precise memory\_order commit_hash:a1b73fa28d9314d4cd21a473f421cfedcaf19330
* YT-28458: Make per-CPU rseq fast path dlopen-safebabenko2026-06-234-8/+118
| | | | | | | | | | | | | | | | | | | | | | | | | Hardens `library/cpp/yt/rseq` for the case where it is linked into a dlopen'd, position-independent module (e.g. a YQL UDF `.so`). Extracted from the profiling work that enables the rseq fast path by default. **TLS model.** The weak `__rseq_abi` gets `global-dynamic` linkage under `__PIC__/__PIE__` (`initial-exec` otherwise), mirroring `contrib/libs/tcmalloc`. `initial-exec` needs a slot in the static TLS block reserved at startup, which the loader cannot grant a module dlopen'd later — the module would fail to load with "cannot allocate memory in static TLS block". This only changes the cold `&__rseq_abi` accesses; the hot path still reads `*(thread_pointer + CpuIdFieldOffset)`. **Runtime safety probe `IsPerCpuFastPathSafe()`.** The cached thread-pointer offset is valid only when `__rseq_abi` sits at a fixed offset from the thread pointer — a glibc-owned area or the static TLS block (incl. tcmalloc), the common case. When our `__rseq_abi` instead lands in a dlopen'd module's *dynamically allocated* TLS, the offset is valid only on the thread that computed it; on other threads the hot path's first store (`area->rseq_cs`) would corrupt unrelated memory. The probe spawns one thread and checks — by pointer comparison, never dereferencing the suspect offset — that the offset names that thread's rseq area; if not, callers use the atomic fallback. Decided once and cached (one thread spawn at first use).= commit_hash:633f58f500d9d097800da81f526c56283445ffc7
* YT-22593: migrate assorted library/cpp/yt string APIs to std::stringbabenko2026-06-224-24/+24
| | | | commit_hash:bfab0d0115b50949f66878004cf718b988575734
* YT-28504: Support heterogeneous lookup in cachesbabenko2026-06-192-2/+4
| | | | commit_hash:acb3e84437f5bdb125d7c1807847eb5edecbb11f
* [monlib] Fix use-after-free in TMonService2 destructorkgershov2026-06-191-0/+1
| | | | | | | | | | TMonService2 binds `this` into the HTTP handler stored in TMtHttpServer. Stop() was only called from TImpl::~TImpl() — after TMonService2 members (IndexMonPage, AuthProvider_) had already been destroyed. A concurrent request could call ServeRequest() and crash on IndexMonPage->Output(). Fix: call Stop() in ~TMonService2() before member destruction. commit_hash:f5b6aff5d9f85ae76d121a036bfd30094377c5ca
* Add lock-free per-CPU primitives to library/cpp/yt/rseqbabenko2026-06-197-3/+781
| | | | | | | | | | | | | | | | | Introduce AddPerCpu and StorePerCpu over an rseq-sharded per-CPU array. On the x86-64 Linux fast path the update is committed by a hand-rolled rseq critical section (non-atomic, migration-safe): addq for the 8-byte accumulate, movq / movdqu for the 8- or 16-byte store. The kernel restarts the sequence on preemption or migration, and only one thread runs on a CPU at a time, so no atomic or lock is needed. Off the fast path (other arches, no kernel rseq) the operation falls back to an atomic on the slot indexed by sched_getcpu(). A naturally-aligned 8-byte store is single-copy atomic on x86-64, so it is never observed torn; the 16-byte store may be, which is acceptable for a last-writer-wins gauge. commit_hash:6250f6e9e35cf3895ebafe0b534ec12cca50b03b
* New version of the tld SKIP_CHECK SKIP_REVIEWrobot-ratatosk2026-06-191-1/+1
| | | | commit_hash:700366443410f399c1582f64da0f5efac01b725d
* Serialize TGrpcTimer on completion queue threadandybg2026-06-185-8/+249
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | ## 1. В чём была проблема У сессии gRPC-клиента (`TClientSession`) несколько таймеров на базе **`TGrpcTimer`** используют один и тот же механизм: внутри лежит **`grpc::Alarm`**, привязанный к **одному** `CompletionQueue`, события с которого обрабатывает **отдельный поток** poller (в логах и стеках — `ua_grpc_cq`). **Публичные методы** `TGrpcTimer::Set` и `Cancel` вызывались **и с этого потока** (после срабатывания alarm, из колбэков завершения gRPC-операций, из `Poll` и т.д.), **и с других потоков** — например, при старте сессии из потока пула (`DoStart` → первый `MakeGrpcCallTimer->Set`). В результате **один и тот же** `grpc::Alarm` и связанные с ним поля таймера менялись **конкурентно без синхронизации**. ThreadSanitizer фиксировал **data race** внутри реализации alarm в gRPC; с точки зрения контракта это **недопустимое параллельное использование** обёртки над alarm. Типичный конфликт: на потоке приложения выполняется **`Set`** (первый запуск таймера переподключения), параллельно на **`ua_grpc_cq`** обрабатывается завершение вызова и снова вызывается **`Set`** для отложенного переподключения — оба попадают в **`Alarm::Set`** для одного объекта. --- ## 2. Изменение архитектуры (как починили) Инвариант: **любое изменение состояния `TGrpcTimer`, которое трогает `grpc::Alarm` и служебные поля таймера, выполняется только на потоке, который крутит `CompletionQueue::Next` для этого клиента** (тот же поток, что обрабатывает срабатывания alarm). Для этого: - Введены внутренние **`ApplySet` / `ApplyCancel`** — в них перенесена прежняя логика работы с alarm; вызывать их разрешено **только** в контексте poller. - Публичные **`Set` / `Cancel`**: если вызов уже идёт **из** poller (определяется **thread-local** флагом на время обработки события из CQ), сразу вызываются **`Apply*`**; иначе работа **ставится в ту же** `CompletionQueue` через **искусственное завершение** (`grpc_cq_begin_op` / `grpc_cq_end_op`), а колбэк на стороне poller выполняет **`Apply*`**. - Чтобы отложенная операция не обращалась к уже уничтоженной сессии, перед постановкой в очередь делается **`TryRef`** на **`TAsyncJoiner`** сессии; после выполнения **`Apply*`** — **`UnRef`**. Если сессия уже уходит в закрытие и joiner недоступен, отложенный **`Set`/`Cancel`** тихо отбрасывается. С точки зрения **`client_impl`**, вызовы **`MakeGrpcCallTimer->Set`**, **`ForceCloseTimer->Set`**, **`PollTimer->Set`**, **`->Cancel`** **не менялись** — меняется только реализация внутри **`TGrpcTimer`** и конструктор (передаётся ссылка на **`AsyncJoiner`** сессии). --- ## 3. Новая архитектура: sequence diagram и пример {% cut "Таблица потоков, примеры A/B и диаграммы Mermaid" %} Ниже — **два типичных сценария** для одного таймера, например **`MakeGrpcCallTimer`** (переподключение после завершения gRPC-вызова). ### Где именно теперь «живёт» работа с таймером | Действие | Поток | | :--- | :--- | | Публичный **`Set` / `Cancel`** с **стороны приложения** (не poller) | Постановка задачи в **CQ**; реальное **`Apply*`** — на **`ua_grpc_cq`**. | | Публичный **`Set` / `Cancel`** уже **внутри** обработчика события CQ (вложенный вызов) | Сразу **`Apply*`** на том же потоке (**без** повторной постановки). | | Срабатывание **`grpc::Alarm`** | Доставка в poller → **`TGrpcTimer::OnIOCompleted`** → при необходимости снова **`Alarm.Set`** / вызов пользовательского колбэка — **всё на `ua_grpc_cq`**. | ### Пример A: первый `Set` при старте сессии (поток приложения) Сессия стартует в **`DoStart`** на **рабочем** потоке; **`MakeGrpcCallTimer->Set(Now())`** не трогает alarm напрямую — **ставит** в CQ задачу «выполнить **`ApplySet`**»; poller **выполняет** её и выставляет alarm. ```mermaid sequenceDiagram participant App as AppThread participant Timer as TGrpcTimer participant CQ as CompletionQueue participant Poller as ua_grpc_cq App->>Timer: Set(now) Timer->>Timer: not poller thread Timer->>Timer: TryRef(AsyncJoiner) Timer->>CQ: enqueue synthetic op CQ-->>Poller: Next delivers op Poller->>Timer: deferred callback Timer->>Timer: ApplySet(now) Timer->>Timer: Alarm.Set + schedule Timer->>Timer: UnRef(AsyncJoiner) ``` ### Пример B: перепланирование после завершения вызова (уже на poller) **`OnGrpcCallFinished`** вызывается с **CQ** после обработки тега gRPC; **`MakeGrpcCallTimer->Set(reconnectTime)`** попадает в **fast path** и сразу вызывает **`ApplySet`** на **`ua_grpc_cq`** — без очереди. ```mermaid sequenceDiagram participant Poller as ua_grpc_cq participant Session as TClientSession participant Timer as TGrpcTimer Poller->>Session: OnGrpcCallFinished Session->>Timer: Set(reconnectTime) Timer->>Timer: poller thread (TLS) Timer->>Timer: ApplySet(reconnectTime) ``` ### Срабатывание alarm (напоминание) Когда срабатывает **внутренний** alarm gRPC, poller получает тег **`TGrpcTimer`**, вызывает **`OnIOCompleted`**: там снова возможны **`Alarm.Set`** (перенос по **`NextTriggerTime`**) или переход к **пользовательскому** колбэку (**`MakeGrpcCall`**, **`Poll`**, **`BeginClose`** и т.д.) — **всё на том же потоке `ua_grpc_cq`**. {% endcut %} --- {% cut "Технические детали (файлы, API gRPC, TSAN, lifetime)" %} ### Файлы в Arcadia | Файл | Роль | | :--- | :--- | | `library/cpp/unified_agent_client/grpc_io.h`, `grpc_io.cpp` | `TGrpcTimer`, `TPostedCompletion` / `TPostedBridge`, `PostIIOCallbackToCompletionQueue`, `TlsInUaGrpcCompletionQueuePoller` в цикле poller. | | `library/cpp/unified_agent_client/client_impl.cpp` | Создание трёх `TGrpcTimer` с передачей `AsyncJoiner` сессии. | ### Низкоуровневая постановка в CQ Паттерн тот же, что у **`TGrpcNotification::Trigger`**: **`grpc_core::ApplicationCallbackExecCtx`**, **`grpc_core::ExecCtx`**, **`grpc_cq_begin_op`**, **`grpc_cq_end_op`**. Тег **`CompletionQueueTag`** — отдельный объект; в **`FinalizeResult`** в poller передаётся **`IIOCallback`** (мост), который выполняет отложенную лямбду и освобождает себя после **`OnIOCompleted`**. ### TSAN () В отчёте TSAN конкурирующие записи шли в **`grpc::internal::AlarmImpl::Set`** из потока **`ua_grpc_cq`** (цепочка **`OnGrpcCallFinished` → `MakeGrpcCallTimer->Set`**) и из потока приложения (**`DoStart` → `MakeGrpcCallTimer->Set(Now())`**). После фикса оба пути сериализуют **`ApplySet`** на poller. ### Поведение при закрытии сессии Если **`TryRef(AsyncJoiner)`** не удался, отложенный **`Set`/`Cancel`** не ставится — сессия уже в фазе **`Join`**. Уже стоящие в CQ задачи удерживают ref до выполнения **`Apply*`** и **`UnRef`**. ### Заглушка счётчика для `MakeIOCallback` Для отложенной лямбды используется **`TNoOpRefStub`**: **`Ref`/`UnRef`** пустые; удержание сессии обеспечивается парой **`TryRef`/`UnRef`** на **`TAsyncJoiner`**, а не счётчиком **`TIOCallback`**. {% endcut %} commit_hash:ba05e9c98e41bcf748270a48a818cc7d233a161b
* Add TTscp::GetApproximatebabenko2026-06-185-27/+52
| | | | | | | | | | | | | | | | | | | | | TTscp::GetApproximate takes the processor id from the rseq fast path (GetCurrentCpuId) and the instant from a non-serializing rdtsc, instead of the single serializing rdtscp of TTscp::Get. TPerCpuGauge::Update switches to it: the per-shard timestamp only orders writes across shards to pick the freshest value, so the lower precision is fine. Update is virtual and now YT_PREVENT_TLS_CACHING -- the fiber-TLS boundary the inlined rseq read needs. #### Benchmark sas2-2769 (glibc 2.31 + tcmalloc, rseq fast path), median of 5: | primitive | time | |---|---| | TTscp::Get() (rdtscp) | 14.1 ns | | TTscp::GetApproximate() (rseq + rdtsc) | 10.6 ns (-25%) | commit_hash:b277b6551accd6d0b879f8ffb168bcbe8d9fbb74
* Speed up working with timezonesshamteev2026-06-161-1/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Optimize timezone-aware query functions (timestamp_floor\_\*\_tz, format_timestamp_tz) Problem: queries using timezone functions on a non-Moscow/non-UTC zone (e.g. Europe/Bucharest) ran 10-20x slower than their non-timezone equivalents. For Moscow/UTC a lookup table handles the conversion; for any other zone the code falls back to live cctz calls. Cause, confirmed by flamegraph and code: 1. NDatetime::ToCivilTime performed two independent timezone lookups per call. cctz::convert(tp, tz) is defined as tz.lookup(tp).cs, and the function then called tz.lookup(tp) again for the offset/is_dst fields. Both pieces of data are already present in a single absolute_lookup result. 2. TimestampFloorDayTZInternal (and Month/Quarter/Year variants) located the start of the period via a binary search that called ToCivilTime on every iteration — \~18 iterations for the day case. Combined with (1) that is \~38 cctz lookups per call, and timestamp_floor_day_tz appears twice per row in a typical WHERE clause. * Changelog entry Type: fix 1. ToCivilTime now does a single tz.lookup(tp) and reuses both cs and the offset/is_dst fields. Behavior is identical; affects all callers. 2. TimestampFloor\{Day,Month,Quarter,Year\}TZ compute the period start directly (subtract the civil time-of-day, or build the first second of the period and convert it back), then verify the result. The binary search is kept as a fallback for the rare days that do not start at midnight (DST transitions at 00:00, historical offset shifts), so results are unchanged. commit_hash:295ee82832ab2a4a35920067e7c063d6992bb083
* New version of the tld SKIP_CHECK SKIP_REVIEWrobot-ratatosk2026-06-161-1/+1
| | | | commit_hash:12a46325d5cf858c816e573782759a1cf0580070
* Fix some typos in library/cpp/getopt/smallponasenko-rs2026-06-152-9/+9
| | | | commit_hash:35d60580ca855d25f47b96ec20edccdae29d3bf5
* Make library/cpp/yt/rseq a Linux-only dependency of library/cpp/yt/systembabenko2026-06-154-16/+20
| | | | | Make library/cpp/yt/rseq a Linux-only dependency of library/cpp/yt/system commit_hash:7d6f5e738658447529440425b55b2891f6664d81
* Add YT_DEFINE_SENTINEL_OPTIONAL macrobabenko2026-06-152-3/+17
| | | | | | | | | | | | | | | | | | | Add a macro for defining `TSentinelOptional` type aliases when the value type is not structural (e.g. has protected members) and therefore cannot use `TValueSentinel<V>`. The macro collapses the boilerplate sentinel struct plus `using` declaration into a single line: ```cpp // before struct TInstantSentinel { static constexpr auto Sentinel = TInstant::Zero(); }; using TSentinelOptionalInstant = TSentinelOptional<TInstant, TInstantSentinel>; // after YT_DEFINE_SENTINEL_OPTIONAL(TSentinelOptionalInstant, TInstant, TInstant::Zero()); ``` Also convert the existing call sites in `service_detail.cpp` and `inferrum/block_cache.cpp`. commit_hash:5dcdeb8db215736b0ce5a5b71f30aead91c7b8e8
* YT-18571: Move TTscp to library/cpp/yt/systembabenko2026-06-153-0/+97
| | | | commit_hash:33721d8fd9919cec2c217db529145c881baf144b
* Fix rseq fast path on glibc < 2.35: read the shared __rseq_abi areababenko2026-06-141-28/+43
| | | | | | | | | | | | | | | | | | | | | | | The own-area approach did not deliver the fast path on glibc 2.31 (YT's current runtime). There tcmalloc registers the conventional `__rseq_abi` area for every thread; our attempt to register a separate area was rejected by the kernel with EINVAL (a thread may have only one rseq area), so `cpu_id` stayed -1 and every `GetCurrentCpuId()` fell back to `sched_getcpu()` (~17-20 ns, slower than the rdtscp it replaced). Read the shared `__rseq_abi` symbol instead -- the area tcmalloc, librseq and pre-2.35 glibc all register. Our definition is weak, so it coalesces with theirs when present (the common case -- tcmalloc owns it) and stands alone otherwise (e.g. musl), with us registering it. We register with the conventional signature `0x53053053` and size 32, so re-registering an already-registered area returns EBUSY (treated as success) rather than EINVAL -- coexisting cleanly with tcmalloc. glibc >= 2.35 still takes the `__rseq_offset` path unchanged. Measured on sas2-2769 (glibc 2.31 + tcmalloc): `GetCurrentCpuId()` 20.0 ns -> 0.60 ns, verified via strace that our registration now returns EBUSY against tcmalloc's `__rseq_abi` (was EINVAL against a separate area). commit_hash:509809deeb5f7c671817fcd9ebcc8499eabf096e
* Fold TEnumTraits GetMinValue/GetMaxValue to compile timebabenko2026-06-141-6/+12
| | | | | | | | | | | | | | | | | GetMinValue()/GetMaxValue() are constexpr, but when called from a runtime context for a large-domain enum, clang does not fold the min/max_element and emits a runtime scan over the whole domain on every call. This is hot on the master replay path: TEnumIndexedArray::operator[] bounds-checks against these (e.g. TCypressManager::FindHandler), and TCompositeAutomaton::RememberReign hits GetCurrentReign() = GetMaxValue() over the ~3300-entry EMasterReign domain per mutation. Bind the result to a constexpr local to force compile-time evaluation. Verified by disasm on a 240-value sample enum: getmin() goes from a ~44-instruction runtime scan to a single 'mov $const'. No behavior change. Part of YT-28453 (master replay-speed optimizations). commit_hash:7cdb969e00ba219415d80c5c8c984aa8bbde99d2
* Add library/cpp/yt/rseq: NYT::GetCurrentCpuId() via Linux rseqbabenko2026-06-1412-0/+455
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Self-contained current-CPU-id reader backed by Linux **rseq** (restartable sequences), with **no third-party dependency** (no librseq): * The rseq ABI is hand-defined; the calling thread is registered lazily via the rseq syscall. * Fast path is a single inlined, **branch-free** thread-local read. The offset always points at a readable `cpu_id` -- the glibc-owned area when glibc registers rseq (>= 2.35, via the weak `__rseq_offset`/`__rseq_size`), otherwise our own area -- so an unregistered thread reads `-1` and routes to the slow path. * Falls back to `sched_getcpu()` (Linux) or `0` (darwin/windows). Works on glibc **and musl** alike (librseq does not build on musl). Fiber-TLS contract: the inlined read must be reached only via a non-inlinable, fiber-switch-free frame (a virtual call or `YT_PREVENT_TLS_CACHING`). #### Benchmark -- cost of one cpu-id read | source | time / call | |---|---| | `GetCurrentCpuId()` (rseq) | **0.34 ns** | | `sched_getcpu()` (vDSO) | 3.5 ns | | `rdtscp` (what `TTscp::Get()` does) | 23 ns | This is an alternative to the librseq-based review/13886037 -- same speed, but no contrib dependency and it also covers musl. The unit test pins to each allowed CPU and asserts the reported id matches. 🤖 Generated with [Claude Code](https://claude.com/claude-code) commit_hash:09d282c2f48755836b1cd68cedbffc3c6a662eed
* Include port.h from logger.hbabenko2026-06-131-0/+2
| | | | | | | | | | YT_LOG_TRACE is gated on YT_ENABLE_TRACE_LOGGING, defined in library/cpp/yt/misc/port.h. logger.h relies on that macro but does not include port.h, so in a TU that does not pull in port.h before logger.h, YT_LOG_TRACE silently compiles to a no-op regardless of the configured log level. Make logger.h self-contained by including the header that defines the macro it depends on. commit_hash:c53f26a7dff9d3f9c5a9d9aab8ea7fa31d11ec49
* New version of the tld SKIP_CHECK SKIP_REVIEWrobot-ratatosk2026-06-131-1/+1
| | | | commit_hash:b892a307cba4ad3c500398eaaf34669ba3f76b00
* Speed up NYT::Formatbabenko2026-06-134-71/+44
| | | | | | | | | | | | | | | | | | | | | | | | | | | Profile-driven optimizations of the `Format` hot path, benchmarked against a representative master debug log (structured `"Key: %v"` messages dominated by GUIDs, strings, integers, bools and durations). Median improvements of ~15-20% across the workload, measured on a dedicated host. Changes: - `string_builder`: use `resize_uninitialized` in `DoReserve` to avoid zero-filling the buffer on every `Format` call. - `format`: replace the per-argument `memchr` (`spec.Contains('n')`) with an inline scan, force-inline `RunFormatterAt`, and add a `FormatString` fast path for the common plain `%v` / empty spec. - `guid`: rewrite `WriteGuidToBuffer` using a `clz`-derived digit count and a back-to-front fill instead of the per-magnitude branch cascade (cut from ~26% to ~12% of a GUID-heavy line). Validated against an `%x` reference over 2M random GUIDs plus edge cases. Also adds `library/cpp/yt/string/benchmark` to track `Format` performance. ### Benchmarks Median ns/op (lower is better), pinned core on a dedicated Xeon E5-2650 v2, 9x1s repetitions. See `library/cpp/yt/string/benchmark`. | Benchmark | What it formats | Before | After | Speedup | | --- | --- | ---: | ---: | ---: | | `ManyMixedArgs` | ~18 args: GUIDs, strings, duration, ints | 1030 | 833 | -19% | | `StringAndTwoGuids` | literal prefix + two GUIDs | 233 | 185 | -21% | | `IntAndGuid` | one int + one GUID | 205 | 179 | -13% | | `ManyInts` | six integers | 389 | 340 | -13% | | `Guid` | a single GUID | 156 | 131 | -16% | | `String` | a single string | 139 | 104 | -25% | | `Int` | a single integer | 142 | 120 | -15% | | `NoArgs` | a literal with no arguments | 88.8 | 85.7 | -3% | commit_hash:ce9957a06c3ff28b2889aa65fbbddf4ca444f9fe
* Add TSharedMutableRef::AllocateViaMmapbabenko2026-06-125-1/+220
| | | | commit_hash:1666d5c27b2dfe54460efdc686d98ad955b0c4f1
* Intermediate changesrobot-piglet2026-06-121-104/+104
| | | | commit_hash:41bdf36203cd75db0aa209d4867da7ca434cef78
* Fix gzip detection in libmagicivan-kligunov2026-06-101-1/+1
| | | | | add gzip alias commit_hash:4543da4a84ec380ede1e06385ff85a7fa8d6bcec
* make constant public MD5_HEX_DIGEST_LENGTHuzhas2026-06-103-2/+4
| | | | commit_hash:4a07699e482566e3338ad4a92dcef209f57c2742
* New version of the tld SKIP_CHECK SKIP_REVIEWrobot-ratatosk2026-06-101-1/+1
| | | | commit_hash:de3a49d188850e6ff1eee30d3f25ff5726a9f415
* Improve TGenericLocalValue, allow mixed thread-fiber-etc valueskulikov2026-06-082-25/+86
| | | | | | | | | | Make generic local values more safe and usable: - instead of factory, register fiber/coroutine-aware "GLS (general local storage) contexts"; - put up to 4 (normally no more than 2 -- threads and one coroutine implementation) different "tls" variables into one generic, choose correct one from current execution context; - suitable version of variable will be constructed on demand (no dependency from first usage); - improve unit test too. commit_hash:8586846a6a775bd66dffcdf58263f78042be2480
* switch JSON→proto parsing to NProtobufJson::Json2Protoibratchik2026-06-083-5/+132
| | | | | Replace google::protobuf::util::JsonStringToMessage with NProtobufJson::Json2Proto in incut_search request parsing and helpers/proto.h::ConvertFromString. commit_hash:ccd17f46188ef0fd0253e146d9df2e6a8e7ba1b0
* New version of the tld SKIP_CHECK SKIP_REVIEWrobot-ratatosk2026-06-071-1/+1
| | | | commit_hash:91a2de31f763fca2eb5b8595deb369458d889731
* Stroka -> TString, Wtroka -> TUtf16String..akhropov2026-06-072-8/+8
| | | | commit_hash:0f92ee40eb5e4a80c59a5cbdcac895ff7acd22e9