Skip to content

Commit 4a9f0b0

Browse files
committed
perf: dual-child read + traversal tweaks
1 parent ff83ea4 commit 4a9f0b0

File tree

2 files changed

+67
-11
lines changed

2 files changed

+67
-11
lines changed

reader.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,67 @@ func readNodeBySize(buffer []byte, offset, bit, recordSize uint) (uint, error) {
515515
}
516516
}
517517

518+
// readNodePairBySize reads both left (bit=0) and right (bit=1) child pointers
519+
// for a node at the given base offset according to the record size. This reduces
520+
// duplicate bound checks and byte fetches when both children are needed.
521+
func readNodePairBySize(buffer []byte, baseOffset, recordSize uint) (left, right uint, err error) {
522+
bufferLen := uint(len(buffer))
523+
switch recordSize {
524+
case 24:
525+
// Each child is 3 bytes; total 6 bytes starting at baseOffset
526+
if baseOffset > bufferLen-6 {
527+
return 0, 0, mmdberrors.NewInvalidDatabaseError(
528+
"bounds check failed: insufficient buffer for 24-bit node pair read",
529+
)
530+
}
531+
o := baseOffset
532+
left = (uint(buffer[o]) << 16) | (uint(buffer[o+1]) << 8) | uint(buffer[o+2])
533+
o += 3
534+
right = (uint(buffer[o]) << 16) | (uint(buffer[o+1]) << 8) | uint(buffer[o+2])
535+
return left, right, nil
536+
case 28:
537+
// Left uses high nibble of shared byte, right uses low nibble.
538+
// Layout: [A B C S][D E F] where S provides 4 shared bits for each child
539+
if baseOffset > bufferLen-7 {
540+
return 0, 0, mmdberrors.NewInvalidDatabaseError(
541+
"bounds check failed: insufficient buffer for 28-bit node pair read",
542+
)
543+
}
544+
// Left child (bit=0): uses high nibble of shared byte
545+
shared := uint(buffer[baseOffset+3])
546+
left = ((shared & 0xF0) << 20) |
547+
(uint(buffer[baseOffset]) << 16) |
548+
(uint(buffer[baseOffset+1]) << 8) |
549+
uint(buffer[baseOffset+2])
550+
// Right child (bit=1): uses low nibble of shared byte, next 3 bytes
551+
right = ((shared & 0x0F) << 24) |
552+
(uint(buffer[baseOffset+4]) << 16) |
553+
(uint(buffer[baseOffset+5]) << 8) |
554+
uint(buffer[baseOffset+6])
555+
return left, right, nil
556+
case 32:
557+
// Each child is 4 bytes; total 8 bytes
558+
if baseOffset > bufferLen-8 {
559+
return 0, 0, mmdberrors.NewInvalidDatabaseError(
560+
"bounds check failed: insufficient buffer for 32-bit node pair read",
561+
)
562+
}
563+
o := baseOffset
564+
left = (uint(buffer[o]) << 24) |
565+
(uint(buffer[o+1]) << 16) |
566+
(uint(buffer[o+2]) << 8) |
567+
uint(buffer[o+3])
568+
o += 4
569+
right = (uint(buffer[o]) << 24) |
570+
(uint(buffer[o+1]) << 16) |
571+
(uint(buffer[o+2]) << 8) |
572+
uint(buffer[o+3])
573+
return left, right, nil
574+
default:
575+
return 0, 0, mmdberrors.NewInvalidDatabaseError("unsupported record size")
576+
}
577+
}
578+
518579
func (r *Reader) traverseTree(ip netip.Addr, node uint, stopBit int) (uint, int, error) {
519580
switch r.Metadata.RecordSize {
520581
case 24:

traverse.go

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -223,8 +223,12 @@ func (r *Reader) NetworksWithin(prefix netip.Prefix, options ...NetworksOption)
223223
}
224224
ipRight[node.bit>>3] |= 1 << (7 - (node.bit % 8))
225225

226-
offset := node.pointer * r.nodeOffsetMult
227-
rightPointer, err := readNodeBySize(r.buffer, offset, 1, r.Metadata.RecordSize)
226+
baseOffset := node.pointer * r.nodeOffsetMult
227+
leftPointer, rightPointer, err := readNodePairBySize(
228+
r.buffer,
229+
baseOffset,
230+
r.Metadata.RecordSize,
231+
)
228232
if err != nil {
229233
yield(Result{
230234
ip: mappedIP(node.ip),
@@ -241,15 +245,6 @@ func (r *Reader) NetworksWithin(prefix netip.Prefix, options ...NetworksOption)
241245
bit: node.bit,
242246
})
243247

244-
leftPointer, err := readNodeBySize(r.buffer, offset, 0, r.Metadata.RecordSize)
245-
if err != nil {
246-
yield(Result{
247-
ip: mappedIP(node.ip),
248-
prefixLen: uint8(node.bit),
249-
err: err,
250-
})
251-
return
252-
}
253248
node.pointer = leftPointer
254249
}
255250
}

0 commit comments

Comments
 (0)