Skip to content

Commit 00e022a

Browse files
Make want batches smaller (#758)
* add simple test * wip * ranges work * fix bugs * fix tests * deopt instead of failing wants in bad cases * and we are done * format * Add unit tests for `LocalWants` & `RemoteWants` (#762) Includes the following: - `LocalWants`'s `.add()` - `LocalWants`'s `.remove()` - `LocalWants`'s `.destroy()` - `RemoteWants`'s `.add()` - `RemoteWants`'s `.remove()` - `RemoteWants`'s `.hasRange()` * Update lib/replicator.js Co-authored-by: Sean Zellmer <[email protected]> * Update lib/replicator.js Co-authored-by: Sean Zellmer <[email protected]> * Update lib/replicator.js Co-authored-by: Sean Zellmer <[email protected]> * Update lib/wants.js Co-authored-by: Sean Zellmer <[email protected]> * Update lib/wants.js Co-authored-by: Sean Zellmer <[email protected]> * lint * Update lib/replicator.js Co-authored-by: Sean Zellmer <[email protected]> * fix some issues * Update lib/replicator.js Co-authored-by: Sean Zellmer <[email protected]> --------- Co-authored-by: Sean Zellmer <[email protected]>
1 parent cb195fb commit 00e022a

File tree

9 files changed

+966
-114
lines changed

9 files changed

+966
-114
lines changed

lib/bitfield.js

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,26 @@ module.exports = class Bitfield {
420420
return this.findLast(false, position)
421421
}
422422

423+
hasUnset(start, length) {
424+
const end = start + length
425+
426+
let j = start & (BITS_PER_SEGMENT - 1)
427+
let i = (start - j) / BITS_PER_SEGMENT
428+
429+
while (i < this._segments.maxLength) {
430+
const s = this._segments.get(i)
431+
const index = s ? s.findFirst(false, j) : j
432+
if (index !== -1) return i * BITS_PER_SEGMENT + index < end
433+
434+
j = 0
435+
i++
436+
437+
if (i * BITS_PER_SEGMENT >= end) return false
438+
}
439+
440+
return true
441+
}
442+
423443
hasSet(start, length) {
424444
const end = start + length
425445

@@ -475,23 +495,23 @@ module.exports = class Bitfield {
475495
}
476496

477497
*want(start, length) {
478-
const j = start & (BITS_PER_SEGMENT - 1)
498+
let j = start & (BITS_PER_SEGMENT - 1)
479499
let i = (start - j) / BITS_PER_SEGMENT
480500

481501
while (length > 0) {
482502
const s = this._segments.get(i)
483503

484504
if (s) {
485-
// We always send at least 4 KiB worth of bitfield in a want, rounding
486-
// to the nearest 4 KiB.
487-
const end = ceilTo(clamp(length / 8, 4096, BYTES_PER_SEGMENT), 4096)
505+
let end = Math.min(j + length, BITS_PER_SEGMENT)
506+
if (end & 31) end += 32 - (end & 31)
488507

489508
yield {
490-
start: i * BITS_PER_SEGMENT,
491-
bitfield: s.bitfield.subarray(0, end / 4)
509+
start: i * BITS_PER_SEGMENT + j,
510+
bitfield: s.bitfield.subarray(j / 32, end / 32)
492511
}
493512
}
494513

514+
j = 0
495515
i++
496516
length -= BITS_PER_SEGMENT
497517
}
@@ -521,13 +541,3 @@ module.exports = class Bitfield {
521541
return new Bitfield(buffer)
522542
}
523543
}
524-
525-
function clamp(n, min, max) {
526-
return Math.min(Math.max(n, min), max)
527-
}
528-
529-
function ceilTo(n, multiple = 1) {
530-
const remainder = n % multiple
531-
if (remainder === 0) return n
532-
return n + multiple - remainder
533-
}

lib/messages.js

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -543,19 +543,32 @@ wire.noData = {
543543
}
544544
}
545545

546+
// TODO: we should move to having these have a handle like in data, easier since they
547+
// allocate state in practice
546548
wire.want = {
547549
preencode(state, m) {
548550
c.uint.preencode(state, m.start)
549551
c.uint.preencode(state, m.length)
552+
553+
const flags = m.any ? 1 : 0
554+
if (flags !== 0) c.uint.preencode(state, flags)
550555
},
551556
encode(state, m) {
552557
c.uint.encode(state, m.start)
553558
c.uint.encode(state, m.length)
559+
560+
const flags = m.any ? 1 : 0
561+
if (flags !== 0) c.uint.encode(state, flags)
554562
},
555563
decode(state) {
564+
const start = c.uint.decode(state)
565+
const length = c.uint.decode(state)
566+
const flags = state.start < state.end ? c.uint.decode(state) : 0
567+
556568
return {
557-
start: c.uint.decode(state),
558-
length: c.uint.decode(state)
569+
start,
570+
length,
571+
any: (flags & 1) !== 0
559572
}
560573
}
561574
}
@@ -564,15 +577,26 @@ wire.unwant = {
564577
preencode(state, m) {
565578
c.uint.preencode(state, m.start)
566579
c.uint.preencode(state, m.length)
580+
581+
const flags = m.any ? 1 : 0
582+
if (flags !== 0) c.uint.preencode(state, flags)
567583
},
568584
encode(state, m) {
569585
c.uint.encode(state, m.start)
570586
c.uint.encode(state, m.length)
587+
588+
const flags = m.any ? 1 : 0
589+
if (flags !== 0) c.uint.encode(state, flags)
571590
},
572591
decode(state, m) {
592+
const start = c.uint.decode(state)
593+
const length = c.uint.decode(state)
594+
const flags = state.start < state.end ? c.uint.decode(state) : 0
595+
573596
return {
574-
start: c.uint.decode(state),
575-
length: c.uint.decode(state)
597+
start,
598+
length,
599+
any: (flags & 1) !== 0
576600
}
577601
}
578602
}

lib/remote-bitfield.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ class RemoteBitfieldSegment {
147147

148148
module.exports = class RemoteBitfield {
149149
static BITS_PER_PAGE = BITS_PER_PAGE
150+
static BITS_PER_SEGMENT = BITS_PER_SEGMENT
150151

151152
constructor() {
152153
this._pages = new BigSparseArray()

0 commit comments

Comments
 (0)