Skip to content

v3.5.6

Choose a tag to compare

@nataell95 nataell95 released this 08 Sep 15:23
· 8 commits to main since this release
Immutable release. Only release title and notes can be modified.

v3.5.6 — removes the allocator settings that are the likely cause of the CPU slowdown reported under WSL2 (#34)

No API or model changes. Supersedes v3.5.5.

What was wrong

Since 3.5.3 (GPU server) and 3.5.5 (CPU server), startup forced a 1 MB mmap threshold and a 4 MB trim threshold on glibc. Every multi-megabyte tensor an inference allocates then became an mmap/munmap pair with fresh page faults. Measured on a 24-core Linux host, that is six times the page faults and twice the kernel time of 3.5.0 for the same document; wall time on that host does not move. The report in #34 is a 2-page document taking 30 s instead of 5 s under Docker Desktop on WSL2 with every core busy. A large munmap rate inside a VM, where each unmap is a TLB shootdown across all vCPUs, would fit that picture, and neither of the two 3.5.5 flags (TURBO_OCR_DISABLE_HOST_IMAGE_POOL, TURBO_OCR_DISABLE_MALLOC_REAPER) touches these settings, which matches the reporter's observation that they changed nothing. How much a VM amplifies that was tested in an 8-vCPU KVM guest on the same host: v3.5.5 there costs twice the page faults and kernel time of 3.5.0 but only 3% of wall time, so the 6× reported under Hyper-V on a Ryzen was not reproduced on KVM on an Intel host. The thresholds are removed because they are measured, pure overhead on every platform; whether they alone explain the reporter's number is for the reporter's machine to show.

What changed

  • The two thresholds are gone. The arena cap stays, sized to the CPUs the process may run on (its affinity mask, so a pinned container sizes it to its share; at least 8) instead of a flat 8, and it yields to an operator's own MALLOC_ARENA_MAX or GLIBC_TUNABLES setting. The cap bounds the resident floor without a single system call. Memory stays bounded by the mechanisms that actually do it: page-sized image buffers come from the host image pool and never touch malloc, and the idle-memory reaper returns freed pages of every arena to the OS every 5 s. The startup line reports the cap ("arena_max").

Measured

The three candidate configurations were compared under identical conditions: v3.5.5 (thresholds + cap 8), no tuning at all, and the cap alone (shipped).

v3.5.0 v3.5.5 no tuning cap only (v3.5.6)
CPU server, 2 × 300-dpi pages, medium + slanext, 8 pinned cores: minor page faults / kernel time (wall time 9.6–9.7 s in every column) 16.4–17.0k / 0.2 s 102–109k / 0.4 s 19–27k / 0.2 s
GPU server, glibc, 20 rounds of 1100 base64 requests: idle RSS first → last, trend of the last third 2666 → 2717 MB, +4.9 MB/round 2698 → 2851 MB, +1.7 MB/round 2696 → 2761 MB, +0.3 MB/round (44 MB above the v3.5.5 end point, but no longer rising)
CPU image amd64, 6 bursts of 120 base64 requests: idle RSS after the last burst (bursts 2 → 6) 6297 MB 6946 MB 6412–6416 MB (6396 → 6412; rerun 6378 → 6416)
KVM guest, 8 vCPUs, same 2 pages: wall / page faults / kernel time 9.8 s / 461k / 0.5 s 10.1 s / 882k / 1.1 s 9.8 s / 490k / 0.6 s
CPU image arm64, 6 bursts: idle memory after the last burst 5.17 GiB 5.85 GiB, climbing 5.30 GiB, flat

A fixed cap of 8 instead of the CPU count (measured, not shipped): 100 MB lower floor on the CPU server (6.33 GB) but the GPU server rises 9.6 MB per round over 20 rounds (2674 → 2856 MB), so the cap scales with the CPUs the process may use, which is at least 8.

jemalloc preloaded instead (measured, not shipped): 80–82k page faults for the same two pages and a 6.98 GB CPU floor, so no advantage over the cap on glibc. Absolute fault counts differ between runs by a few times depending on page-cache state; the ordering of the columns was the same in every run.

GPU throughput and FUNSD accuracy are identical with and without the change (A/B on the same box, run while the GPU was shared with other jobs, so both arms were equally slowed: 265–268 img/s both, F1 85.40% both; the candidate image alone on a free GPU: 432–437 img/s, F1 85.30–85.40% across TensorRT engine builds). Unit tests 380, response shapes of every endpoint identical to v3.5.2, PDF results byte-identical. The images built from this tree were verified before tagging: GPU (FUNSD 85.30–85.40%, 432–437 img/s, parity, batch), CPU amd64 and CPU arm64 (parity, batch, PDF pages identical, flat bursts).

Images

  • GPU (TensorRT, x86_64): ghcr.io/aiptimizer/turboocr:v3.5.6 (also :latest)
  • CPU (ONNX Runtime, amd64+arm64): ghcr.io/aiptimizer/turboocr-cpu:v3.5.6 (also :latest, and ghcr.io/aiptimizer/turboocr:v3.5.6-cpu)