CDX internal node format fix: - Was: [child LE][recNo LE][key] (NTX-style) - Now: [key][recNo BE][child BE] (correct CDX format) - Fixes GoTop/Seek/Scan for large CDX files (50K+ records) CDX mmap: - syscall.Mmap on OpenIndex for zero-copy reads - idx.readAt() helper: mmap slice or file fallback - All ReadAt calls in Tag navigation replaced - Close: munmap CDX 50K benchmark (all counts correct): SEEK NAME 50K: 362ms (f=50000) SCAN 50K: 276ms (c=50000) SCOPE 35K: 238ms (c=35000) SEEK ID 50K: 320ms (f=50000) CDX is slower than NTX due to bit-packed leaf decompression per page. Cross-read test: 18/18 still PASS. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
67 lines
1.4 KiB
Plaintext
67 lines
1.4 KiB
Plaintext
// CDX Read Benchmark — opens Harbour-created CDX, tests seek/scan/scope
|
|
PROCEDURE Main()
|
|
LOCAL i, nStart, nEnd, nCount
|
|
|
|
// Open Harbour-created files
|
|
USE "cdx_bench" NEW
|
|
SET INDEX TO "cdx_bench.cdx"
|
|
|
|
? "TAGS=" + LTrim(Str(OrdCount()))
|
|
|
|
// SEEK 50K by NAME
|
|
SET ORDER TO 3
|
|
nStart := Seconds()
|
|
nCount := 0
|
|
FOR i := 1 TO 50000
|
|
SEEK PadR("Name_" + PadL(LTrim(Str(i)), 5, "0"), 20)
|
|
IF Found()
|
|
nCount++
|
|
ENDIF
|
|
NEXT
|
|
nEnd := Seconds()
|
|
? "SEEK_NAME=" + LTrim(Str(Int((nEnd-nStart)*1000))) + "ms f=" + LTrim(Str(nCount))
|
|
|
|
// SCAN 50K
|
|
SET ORDER TO 3
|
|
GO TOP
|
|
nStart := Seconds()
|
|
nCount := 0
|
|
DO WHILE !EOF()
|
|
nCount++
|
|
SKIP
|
|
ENDDO
|
|
nEnd := Seconds()
|
|
? "SCAN=" + LTrim(Str(Int((nEnd-nStart)*1000))) + "ms c=" + LTrim(Str(nCount))
|
|
|
|
// ORDSCOPE on CITY
|
|
SET ORDER TO 1
|
|
OrdScope(0, PadR("London", 15))
|
|
OrdScope(1, PadR("Seoul", 15))
|
|
nStart := Seconds()
|
|
GO TOP
|
|
nCount := 0
|
|
DO WHILE !EOF()
|
|
nCount++
|
|
SKIP
|
|
ENDDO
|
|
nEnd := Seconds()
|
|
? "SCOPE=" + LTrim(Str(Int((nEnd-nStart)*1000))) + "ms c=" + LTrim(Str(nCount))
|
|
OrdScope(0, NIL)
|
|
OrdScope(1, NIL)
|
|
|
|
// SEEK by ID
|
|
SET ORDER TO 2
|
|
nStart := Seconds()
|
|
nCount := 0
|
|
FOR i := 1 TO 50000
|
|
SEEK Str(i, 8)
|
|
IF Found()
|
|
nCount++
|
|
ENDIF
|
|
NEXT
|
|
nEnd := Seconds()
|
|
? "SEEK_ID=" + LTrim(Str(Int((nEnd-nStart)*1000))) + "ms f=" + LTrim(Str(nCount))
|
|
|
|
CLOSE ALL
|
|
RETURN
|