Skip to content

Commit

Permalink
Unslab downloaded blocks (#541)
Browse files Browse the repository at this point in the history
* Unslab downloaded blocks

* Unslab in cacheOnResolve, and only if small

* resolved.byteLength instead of resolved.length

* Add test for big block case
  • Loading branch information
HDegroote authored Jul 24, 2024
1 parent 8f0626e commit a437ed2
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 6 deletions.
8 changes: 7 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const z32 = require('z32')
const id = require('hypercore-id-encoding')
const safetyCatch = require('safety-catch')
const { createTracer } = require('hypertrace')
const unslab = require('unslab')

const Replicator = require('./lib/replicator')
const Core = require('./lib/core')
Expand Down Expand Up @@ -911,7 +912,12 @@ module.exports = class Hypercore extends EventEmitter {
}

async _cacheOnResolve (index, req, fork) {
const block = await req
const resolved = await req

// Unslab only when it takes up less then half the slab
const block = resolved !== null && 2 * resolved.byteLength < resolved.buffer.byteLength
? unslab(resolved)
: resolved

if (this.cache && fork === this.core.tree.fork) {
this.cache.set(index, Promise.resolve(block))
Expand Down
10 changes: 5 additions & 5 deletions test/cache.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,15 +76,15 @@ test('cache on replicate', async function (t) {
replicate(a, b, t)

// These will issue a replicator request
const p = b.get(0)
const q = b.get(0)
const p = await b.get(0)
const q = await b.get(0)

t.is(await p, await q, 'blocks are identical')
t.is(p, q, 'blocks are identical')

// This should use the cache
const r = b.get(0)
const r = await b.get(0)

t.is(await p, await r, 'blocks are identical')
t.is(p, r, 'blocks are identical')
})

test('session cache with different encodings', async function (t) {
Expand Down
39 changes: 39 additions & 0 deletions test/replicate.js
Original file line number Diff line number Diff line change
Expand Up @@ -955,6 +955,45 @@ test('download available blocks on non-sparse update', async function (t) {
t.is(b.contiguousLength, b.length)
})

test('downloaded blocks are unslabbed if small', async function (t) {
const a = await create()

await a.append(Buffer.alloc(1))

const b = await create(a.key)

replicate(a, b, t)

t.is(b.contiguousLength, 0, 'sanity check: we want to receive the downloaded buffer (not from fs)')
const block = await b.get(0)

t.is(block.buffer.byteLength, 1, 'unslabbed block')
})

test('downloaded blocks are not unslabbed if bigger than half of slab size', async function (t) {
const a = await create()

await a.append(Buffer.alloc(5000))
t.is(
Buffer.poolSize < 5000 * 2,
true,
'Sanity check (adapt test if fails)'
)

const b = await create(a.key)

replicate(a, b, t)

t.is(b.contiguousLength, 0, 'sanity check: we want to receive the downloaded buffer (not from fs)')
const block = await b.get(0)

t.is(
block.buffer.byteLength !== block.byteLength,
true,
'No unslab if big block' // slab includes the protomux frame
)
})

test('sparse replication without gossiping', async function (t) {
t.plan(4)

Expand Down

0 comments on commit a437ed2

Please sign in to comment.