Commits on Source 15

  • Josh Bleecher Snyder's avatar
    modernc.org/libc: extract TLS signal checking · 8f81eb5b
    Josh Bleecher Snyder authored
    TLS.Free delivers pending signals as a side effect of unwinding a C
    stack frame. Splitting the check out into its own method lets libc
    routines with no frame to unwind reach it directly, rather than
    allocating a frame just to get the signal delivered.
    8f81eb5b
  • Josh Bleecher Snyder's avatar
    modernc.org/libc: native Go implementations of hot musl routines · 7fcd6f30
    Josh Bleecher Snyder authored
    The transpiled musl mem* routines move at most four bytes per
    load/store, through a double pointer indirection. Go's copy, clear and
    bytes.Compare lower to the runtime's vectorized memmove and memclr and
    to bytes.Compare's SIMD scan. In the JSON-heavy speedtest1 workloads
    of github.com/josharian/benchmosql, where SQLite shuttles blob
    payloads around, that takes Xmemcpy from 41% of CPU to under 20%;
    Xmemcmp is 47-98% faster across the measured sizes.
    
    Only linux/amd64 and linux/arm64, the two arches the measurements
    cover. The other musl arches keep the transpiled routines; the
    non-musl ports have always had hand-written ones in libc.go.
    
    Xmemcmp returns -1/0/+1 rather than musl's difference of the first
    mismatched bytes. C99 specifies only the sign, and every caller in the
    transpiled musl code and in modernc.org/sqlite's generated code
    (including its vec and pcache variants) compares the result against
    zero.
    
    Xmemset's nonzero fill seeds 512 bytes with word stores and then
    doubles that prefix with copy. Transpiled musl's unrolled word stores
    are genuinely fast from 512B to 4KiB, and this is the only pure-Go
    shape measured that keeps up with them there; a plain byte loop and a
    doubling fill from a single byte both lose badly somewhere.
    
    Xfabs allocated a 16-byte C stack frame, with a deferred release, to
    clear one sign bit, and Xstrcspn built its byte set on the C stack.
    Both now work in Go locals and check for pending signals directly.
    7fcd6f30
  • Josh Bleecher Snyder's avatar
    modernc.org/libc: use bytes.IndexByte in the internal strlen · 97025c52
    Josh Bleecher Snyder authored
    This helper walked the string a byte at a time. It is the
    implementation behind Xstrlen on every port: the musl translation is
    generated with -hide strlen exactly so that the generated code reaches
    it too, both directly and through Xstrlen.
    
    Scanning with bytes.IndexByte instead, over chunks that stop at
    4096-byte boundaries so that the scan cannot fault, is 10-83% faster
    from 16 bytes up on linux/amd64, linux/arm64 and darwin/arm64
    (benchstat, n=10, strings at an odd offset). Strings shorter than 8
    bytes pay ~1.2ns of call overhead on amd64; a hybrid that prescans a
    word or two inline recovers only a fraction of that while giving back
    half the mid-size win, so it is not worth its complexity.
    
    strlen_test.go keeps the classic word-at-a-time scan as a benchmark
    baseline. strlen_guard_test.go checks the no-overread property against
    a PROT_NONE guard page.
    97025c52
  • Josh Bleecher Snyder's avatar
    modernc.org/libc: make TLS.Free's fast path inlinable · f59b4ae6
    Josh Bleecher Snyder authored
    Every ccgo-generated function brackets its body with TLS.Alloc and
    TLS.Free, so their call overhead is paid on every C function call.
    
    Free's common path is now a stack pointer decrement and a bool test,
    which inlines into every generated function; the signal delivery it
    guards stays behind a call. When a signal is pending it is still
    delivered at the same point.
    
    Alloc is split the same way but still does not inline: any useful fast
    path plus the call to the grow path exceeds the inlining budget, the
    call alone costing 57 of the 80 available. The fast path does at least
    stop loading the stack slot twice.
    
    It is possible to make Alloc mid-stack inline,
    but it is a very disruptive change with moderate perf impact.
    f59b4ae6
  • cznic's avatar
    Merge branch 'opt' into 'master' · 2f1d5e61
    cznic authored
    modernc.org/libc: optimize for performance
    
    See merge request !34
    2f1d5e61
  • cznic's avatar
    modernc.org/libc: extend the native musl routines to all linux targets · 886cba32
    cznic authored
    native_musl.go now serves every musl-derived target, not just
    linux/amd64 and linux/arm64. generator.go applies the ___musl_ rename
    unconditionally and the transpiled originals in the six remaining
    ccgo_linux_*.go files are renamed accordingly. On linux/arm musl's
    memcpy is assembly and was never transpiled; the hand-written memcpy
    in libc_musl_linux_arm.go takes the ___musl_memcpy role, while the
    generated arm code keeps calling its unchanged _memcpy helper.
    
    The 32-bit targets exposed three spots that leaned on 64-bit
    operations, expensive there:
    
    - Xmemset seeds with aligned native-word stores instead of unaligned
      PutUint64: parity on amd64, -39% to -77% vs the transpiled original
      on 386 from 32 bytes up, where the 64-bit seed had measured up to
      +140%. The doubling loop no longer computes i *= 2, which could
      overflow int on 32-bit.
    - Xstrcspn's byte set uses native words: -40% to -48% vs transpiled
      on 386 (previously up to +81%), and -10% to -25% on amd64 too.
    - strlen splits per arch (strlen.go, strlen_simd.go, strlen_nosimd.go):
      the chunked bytes.IndexByte scan stays where IndexByte has real
      assembly (amd64, arm64, ppc64le, s390x, riscv64, loong64); the rest
      use the classic word-at-a-time scan, because on 386 IndexByte is a
      byte loop and the chunked scan measured ~2x slower than even the
      plain byte loop it had replaced.
    
    Verified: go test -short and TestLibc natively on linux/amd64 and
    linux/386; the native_musl and strlen tests on arm, arm64, loong64,
    ppc64le, riscv64 and s390x under qemu-user; a 1.6M-case equivalence
    run against the ___musl_ originals on amd64, 386, arm and s390x;
    -race; build_all_targets.sh; and downstream modernc.org/sqlite
    -short, a 36k-test SQLite TCL subset via libsqlite3, libz and
    libquickjs.
    
    Co-Authored-By: default avatarClaude Fable 5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01B7y1NexgTgnEx8S6uFHoqw
    886cba32
  • cznic's avatar
    internal/autogen: blank all mod snapshots to force re-generation · d6af0e74
    cznic authored
    Let every builder regenerate its ccgo_linux_<goarch>.go after 886cba32
    extended the native musl routines to all linux targets; the autogen
    runs double-check that generator.go reproduces the renames committed
    there.
    
    Co-Authored-By: default avatarClaude Fable 5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01B7y1NexgTgnEx8S6uFHoqw
    d6af0e74
  • cznic's avatar
    modernc.org/libc: nuc64 auto generate · 4cad56e0
    cznic authored
    4cad56e0
  • cznic's avatar
    modernc.org/libc: pi64 auto generate · 7d25fda4
    cznic authored
    7d25fda4
  • cznic's avatar
    modernc.org/libc: ppc64le auto generate · df3fad55
    cznic authored
    df3fad55
  • cznic's avatar
    modernc.org/libc: pi32 auto generate · 5341b860
    cznic authored
    5341b860
  • cznic's avatar
    modernc.org/libc: e5-1650 auto generate · dd3f60f7
    cznic authored
    dd3f60f7
  • cznic's avatar
    modernc.org/libc: linux_loong64b auto generate · 2622cca6
    cznic authored
    2622cca6
  • cznic's avatar
    modernc.org/libc: riscv64 auto generate · 521ec848
    cznic authored
    521ec848
  • cznic's avatar
    modernc.org/libc: s390x auto generate · 74a29c4e
    cznic authored
    74a29c4e
Loading
Loading