proven_c_lib-v0.3.0
A MINOR release: nothing public removed, one build profile added, and one profile's behaviour
changed on purpose. ./nob release now defines NDEBUG, so pool and map misuse checks are out
of release builds (pool teardown was quadratic with them), and the new ./nob hardened keeps them
in an optimised build (B-036). find_last makes the forward search's choices, and its quadratic
tail is gone (B-024). The freestanding runtime contract is stated and link-proven (B-034). ./nob cross reports every target and cannot skip the mandatory ones (B-035). Benchmarks share one row
format and back the published numbers (B-037, B-038). The build rebuilds exactly what a header
change touched, and ./nob clean removes the selected build root safely (B-036). English public
text is ASCII, and a gate keeps it that way.
Added
- One benchmark row format, and the benchmarks behind the published numbers (B-037, B-038).
tests/proven_bench.h: warmup, five samples on a monotonic clock, median, spread, raw samples,
checksum, compiler and profile on one line; every registered benchmark uses it. New
tests/test_bench_float_host.c(the float-vs-glibc comparison, now checked in, with accuracy
asserted in the same run) andtests/test_bench_job.c(idle CPU for 1-32 workers, idle / burst
/ saturated wake latency, throughput). Raw results and a claim-to-row map in
the maintainers' benchmark records, with the job system's latency budget.
Changed
- The build rebuilds exactly what a change touched (B-036). Objects and test executables are
built with compiler dependency files (-MMD); the cache key is the exact compile or link command
plus the contents of every file the dependency file names. Editinginclude/proven/job.hnow
recompilesjob.calone (1 of 36 objects; the tests relink because they link every object), and
editingmanual/examples/example.hrelinks the 92 examples that include it and nothing else -
before, any header edit rebuilt everything. A missing dependency file means a rebuild, never a
stale cache hit. The test cache hash is now taken from the exact link command (it used to be a
hand-kept copy that differed from it), and-ldlis linked only into the test that interposes
libc withdlsym(RTLD_NEXT, ...)instead of every POSIX test (B-035). The first build after
updating rebuilds everything once. ./nob cleanremoves the selected build root, safely (B-036). It honours-build-rootand
PROVEN_BUILD_ROOTinstead of always runningrm -rf build/rmdir /s /q buildthrough the
shell, deletes without following symlinks or junctions, refuses.,/, any..component
and unusual characters, and removes a root other than the defaultbuildonly when it carries
the.proven-build-rootmarker nob now writes into every build root it creates. Compatibility
note: a custom build root created by an oldernobhas no marker, socleanrefuses it once
with a hint; remove it by hand or build into it again first. As for building, a root with a
drive letter or backslashes (C:\...) is refused; on Windows use a relative root. The Windows
deletion path is compiled with mingw-w64 (x86-64, i686) but not yet run on Windows.- The job system's wake-latency budget states its condition (B-041). The Windows idle-wake p99
of ~8.9 ms was traced withb041-wake-probe.c: a bare OS semaphore shows the same tail
whenever CPUs are scarce (the 2-vCPU VM; Linux pinned to 2 CPUs), and neither shows it on a
quiet 16-CPU host. The job system adds ~1 us at the median. No library change; the budget in
the job budget in the maintainers' benchmark records now says it assumes free CPUs, andtest_bench_jobprints the
host's logical CPU count. ./nob releasedefinesNDEBUG; new./nob hardenedkeeps the checks (B-036).
Compatibility note: a release build no longer traps a pool double free or a foreign pointer, or
the map's key-overlap misuse - those checks are for debug and hardened builds. They made pool
teardown quadratic: 20,000 frees took 59.6 ms with the check, 0.05 ms without
(b036-pool-teardown-benchmark.c). Build withhardened(-O2 -DNDEBUG -DPROVEN_HARDENED=1) to keep them in an optimised build, and usealloc_check.hin tests.
Every build now logs its safety profile.- Published float speed claims follow the checked-in benchmark. Re-measured: parsing is
faster than glibc on short numbers, level at ~16 digits, ~1.1x slower at 17; shortest formatting
~3.6x faster than%.17g;%f/%efaster at every magnitude measured - the June claim that
they were 3-5x slower at extreme magnitudes did not reproduce. README (both), the float doc and
primitives-benchmark.mdupdated. - English public text is ASCII, and stays so (B-036). README.md, TEST.md, CHANGELOG.md, the
English manual and examples, and all C sources and build files were normalised (em dashes,
section signs, arrows and the like; 48 files), with the Markdown anchors of changed headings
updated.scripts/ascii_policy.py check, run byproject-check, fails on any new non-ASCII byte
in that scope; Hangul is exempt, and the Korean mirrors are out of scope. ./nob crossreports every target and cannot skip the ones a release needs (B-035). Each
target ends PASS, FAIL or SKIP with a reason, a failure no longer stops the other targets, and a
summary is printed. Skippingnative-gcc-hosted,native-clang-hosted,windows-x86_64-winapi
orwindows-i686-winapifails the run; before, a run that skipped nine of eleven targets
finished green.- The freestanding runtime contract is explicit and linked (B-034). A freestanding build needs
memcpy,memmove,memset,memcmpand the compiler support library, nothing else - stated
in the freestanding guide and proven by a new./nob crossstage that links every freestanding
object with a program supplying only those four (-nostdlib -nostartfiles -static -lgcc) for
Cortex-M4 and RISC-V.float_format.cno longer callsstrlen, which was the one dependency
outside that set. proven_u8str_view_find_lastmakes the forward search's choices (B-024). The same entropy
sample; an anchored backward scan over a new portableproven_sys_mem_rchron ordinary input;
backward Shift-Or (<= 64 bytes) or a new reverse Two-Way (> 64) on low-entropy input. Measured
withb024-find-last-benchmark.c: about 5x faster on ordinary text for 2-64 byte needles
(0.30 -> 0.055 ns/byte), and the long-needle quadratic tail is gone (a 256-byte needle on a dense
run: 1,994 -> 0.002 ns/byte). Long needles on ordinary text are slower (0.022 -> 0.055), the price
of a portable backward scan. Results unchanged: the oracle agrees on 120,000 cases.
Fixed
tests/test_regression_fs_perms_and_typesbuilds with clang. It passed_Atomic int
objects to the GCC__atomic_*_nbuiltins, which clang rejects; it now uses<stdatomic.h>
atomic_load_explicit/atomic_store_explicit. The full hosted suite passes under clang.