Libraries developed by Linder Hard- und Software and licensed to the public under LGPL v2.1 Version 2.1: .
  • PureBasic 100%
Find a file
René Linder f19c0a6e64 lhs_arena: Bytes-Map-API optional ohne Case-Folding (Binaer-Keys)
Die *Bytes-Map-API (MapGetBytes/MapSetBytes/MapDeleteBytes) hat den Key
IMMER per _HashAndLowerUtf8 case-gefaltet (ASCII 'A'..'Z' -> 'a'..'z',
RFC-7230-Header-Namen). Fuer BINAERE Keys (z.B. 8-Byte QUIC-Stream-IDs)
ist das falsch: Keys die sich nur im Case-Bit unterscheiden kollidieren —
0x44 ('D', Stream 68) faltet auf 0x64 ('d', Stream 100) und liefert beim
Lookup einen Falsch-Treffer auf den fremden (ggf. schon reclaimten) Eintrag.

Fix: neuer Parameter fold.b = #True (Default = bisheriges Verhalten,
quell-/ABI-kompatibel, kein Header-Pfad-Caller muss angefasst werden).
fold=#False nutzt _HashBytesRaw (reiner FNV-1a, KEIN In-Place-Lowercase)
fuer Hash UND Vergleich → binaer-exakte Keys.

Wurzel des H3-Stalls (NETLIB-122 Bug #2): H3_Stream nutzt die Bytes-API mit
8-Byte-Stream-ID-Keys → Stall sobald eine Uppercase-Letter-Stream-ID und ihr
Lowercase-Pendant beide auftreten (~Req 25-32/Conn).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 01:35:20 +02:00
DATA LHSLIB-7: RFC-8259 Strictness-Followup (5 Codex-Findings) 2026-05-17 12:43:00 +02:00
GC_MEM GC_MEM: dlist-Struktur TTL-agnostisch (BUG1) + StartTicker-Race (Review-Runde 4) 2026-06-03 15:13:01 +02:00
GUI lhs_uuid + lhs_dialog: Rebase als saubere Module 2026-05-16 01:22:23 +02:00
SYS lhs_arena: Bytes-Map-API optional ohne Case-Folding (Binaer-Keys) 2026-06-05 01:35:20 +02:00
.gitignore Initial commit 2019-05-20 13:16:18 +02:00
LICENSE Initial commit 2019-05-20 13:16:18 +02:00
README.md Move tests/ to separate lhs_lib_full wrapper repo 2026-05-14 14:28:07 +02:00

lhs_lib

Includes entwickelt und erweitert aus bestehenden Sourcen um PureBasic-Funktionalitäten zu erweitern.

Module

SYS/

Modul Beschreibung C-Backend
lhs_log.pbi / lhs_log_ext.pbi Logging-Modul (single- bzw. multi-threaded Logger) nein
lhs_sys_debug_wrapper.pbi Debug-Wrapper für PB-Default-Debug, lhs_log, lhs_log_ext nein
lhs_uuid.pbi UUID-Generator (v1, v3, v4, v5) nein
lhs_arena.pbi Arena-Allocator mit case-insensitive HashMap und FlatList — Hot-Path-Performance für Result-Sets, HTTP-Header-Maps, Per-Request-Pools ja
lhs_atomic.pbi Lock-free Atomics über GCC builtins (CAS, AtomicLoad/Store, Increment/Decrement, Add, Memory-Barriers) ja
lhs_lockfree_queue.pbi MPMC-bounded Queue (Dmitry-Vyukov-Algorithmus), benötigt lhs_atomic ja

GUI/

Modul Beschreibung
lhs_dialog.pbi Erweiterte Dialog-Bausteine

Tests / Benchmarks

Liegen im separaten Wrapper-Repo lhs_lib_full (lhs_lib selbst eingebunden als Git-Submodule). Enthält:

  • lhs_arena_bench.pb — Performance-Benchmark gegen PB-Native Map/List mit Realworld-Szenarien (HTTP Lifecycle, Mixed Workload, Concurrent, PPQL Result-Sets, Search-Index, Cookie-Parser, Header-Match)
  • lhs_arena_memprof.pb — Memory-Footprint-Profiler (Peak-RSS, Page-Faults)
  • build_csv.sh — Vergleichstabellen-Generator
  • Bench-Outputs für verschiedene Hardware (Ryzen, Xeon X5650, …)

Build-Hinweise

Module mit C-Backend-Pflicht (lhs_arena, lhs_atomic, lhs_lockfree_queue) müssen mit dem PureBasic-C-Backend gebaut werden:

pbcompilerc dein_programm.pb --thread --optimizer --executable dein_programm

Das C-Backend ist auf Linux, macOS, Windows und ARM verfügbar. Der ASM-Backend wird für diese Module nicht unterstützt (GCC-builtin-Atomics und Inline-C-Hotpaths sind C-spezifisch).

Programming recommendations in this collection

Debugging

Es empfiehlt sich, SYS/lhs_sys_debug_wrapper.pbi zu verwenden statt direkt Debug:

Initial:

  Global LoggerUUID.s = ""
  Global Log_Level_Info = 0
  Global Log_Level_Debug = 0
  Global Log_Level_Error = 2

Im Code:

  ldl::Logging("Something on Info Log", LoggerUUID, Log_Level_Info)

Arena (HTTP/PPQL Hot-Path)

Pro Request/Query eine Arena, am Ende Reset (Speicher bleibt für nächsten Cycle wiederverwendbar) oder Destroy:

XIncludeFile "lhs_lib/SYS/lhs_arena.pbi"

Define *arena.lhs_arena::Arena = lhs_arena::Create(65536)

; HashMap mit case-insensitive Key-Vergleich (ideal für HTTP-Header)
Define *headers.lhs_arena::HashMap = lhs_arena::MapCreate(*arena, 32)
lhs_arena::MapSet(*headers, "Content-Type", "text/html")
v.s = lhs_arena::MapGet(*headers, "content-type")    ; → "text/html"

; Zero-UTF-Boundary für Bytes direkt aus Socket-Buffer (HTTP-Parser-Pfad)
lhs_arena::MapSetBytes(*headers, *key_ptr, key_len, *val_ptr, val_len)
*vp = lhs_arena::MapGetBytes(*headers, *key_ptr, key_len, @vlen)

lhs_arena::Reset(*arena)     ; Alles zurück, Chunks behalten
lhs_arena::Destroy(*arena)   ; Alles freigeben

Benchmark-Auszug (Ryzen AI 9 HX 370, 24 Cores) gegen PB-Native bei 100 000 Map-Einträgen:

Test PB-Native Arena Speedup
Map-Lifecycle (Insert + Lookup + Cleanup) 269 ms 27.6 ms 9.7×
Concurrent (1000 Threads × 5k ops, 90% read) 4.62 s 102 ms 45×
PPQL Result-Set 50k Rows × 10 Cols 9.89 s 69 ms 143×
HTTP Header-Match (500 known, Bytes-API) 1.4 µs/op 43 ns/op 32×

Details, X5650-Vergleich und Memory-Footprint: siehe tests/.

Lock-Free Queue (MPMC)

XIncludeFile "lhs_lib/SYS/lhs_atomic.pbi"
XIncludeFile "lhs_lib/SYS/lhs_lockfree_queue.pbi"

Define *q = lhs_lockfree_queue::Create(1024)   ; Power-of-2 capacity

; Producer (mehrere Threads ok)
lhs_lockfree_queue::Push(*q, *work_item)

; Consumer (mehrere Threads ok)
*item = lhs_lockfree_queue::Pop(*q)
If *item
  ; arbeiten ...
EndIf

lhs_lockfree_queue::Free(*q)

Autoren

René Linder [Ground0]

Lizenz

Sofern in den Sourcen nicht anders erwähnt gilt:

SPDX-License-Identifier: LGPL-2.1-or-later OR Commercial