Skip to content
This repository was archived by the owner on Jul 3, 2019. It is now read-only.

Commit 79a8891

Browse files
committed
fix(perf): use bulk file reads for index reads
1 parent 1af0141 commit 79a8891

File tree

1 file changed

+54
-52
lines changed

1 file changed

+54
-52
lines changed

lib/entry-index.js

Lines changed: 54 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,13 @@ const crypto = require('crypto')
66
const fixOwner = require('./util/fix-owner')
77
const fs = require('graceful-fs')
88
const path = require('path')
9-
const pipe = require('mississippi').pipe
109
const Promise = require('bluebird')
11-
const split = require('split')
1210
const through = require('mississippi').through
1311

1412
const indexV = require('../package.json')['cache-version'].index
1513

1614
const appendFileAsync = Promise.promisify(fs.appendFile)
15+
const readFileAsync = Promise.promisify(fs.readFile)
1716

1817
module.exports.insert = insert
1918
function insert (cache, key, digest, opts) {
@@ -50,32 +49,20 @@ function insert (cache, key, digest, opts) {
5049
module.exports.find = find
5150
function find (cache, key) {
5251
const bucket = bucketPath(cache, key)
53-
const stream = fs.createReadStream(bucket)
54-
let ret
55-
return Promise.fromNode(cb => {
56-
pipe(stream, split('\n', null, {trailing: true}).on('data', function (l) {
57-
const pieces = l.split('\t')
58-
if (!pieces[1] || pieces[1].length !== parseInt(pieces[0], 10)) {
59-
// Length is no good! Corruption ahoy!
60-
return
61-
}
62-
let obj
63-
try {
64-
obj = JSON.parse(pieces[1])
65-
} catch (e) {
66-
// Entry is corrupted!
67-
return
68-
}
69-
if (obj && (obj.key === key)) {
70-
ret = formatEntry(cache, obj)
71-
}
72-
}), function (err) {
73-
if (err && err.code === 'ENOENT') {
74-
cb(null, null)
52+
return bucketEntries(cache, bucket).then(entries => {
53+
return entries.reduce((latest, next) => {
54+
if (next && next.key === key) {
55+
return formatEntry(cache, next)
7556
} else {
76-
cb(err, ret)
57+
return latest
7758
}
78-
})
59+
}, null)
60+
}).catch(err => {
61+
if (err.code === 'ENOENT') {
62+
return null
63+
} else {
64+
throw err
65+
}
7966
})
8067
}
8168

@@ -102,38 +89,27 @@ function lsStream (cache) {
10289
return cb(err)
10390
} else {
10491
asyncMap(files, function (f, cb) {
105-
fs.readFile(path.join(indexDir, bucket, f), 'utf8', function (err, data) {
106-
if (err) { return cb(err) }
107-
const entries = {}
108-
data.split('\n').slice(1).forEach(function (entry) {
109-
const pieces = entry.split('\t')
110-
if (pieces[1].length !== parseInt(pieces[0], 10)) {
111-
// Length is no good! Corruption ahoy!
112-
return
113-
}
114-
let parsed
115-
try {
116-
parsed = JSON.parse(pieces[1])
117-
} catch (e) {
118-
}
119-
// NOTE - it's possible for an entry to be
120-
// incomplete/corrupt. So we just skip it.
121-
// See comment on `insert()` for deets.
122-
if (parsed) {
123-
entries[parsed.key] = formatEntry(cache, parsed)
124-
}
125-
})
92+
const bpath = path.join(indexDir, bucket, f)
93+
bucketEntries(cache, bpath).then(_entries => {
94+
const entries = _entries.reduce((acc, entry) => {
95+
acc[entry.key] = entry
96+
return acc
97+
}, {})
12698
Object.keys(entries).forEach(function (k) {
127-
stream.write(entries[k])
99+
stream.write(formatEntry(cache, entries[k]))
128100
})
129101
cb()
102+
}, err => {
103+
if (err.code === 'ENOENT') {
104+
cb()
105+
} else {
106+
cb(err)
107+
}
130108
})
131-
}, function (err) {
132-
cb(err)
133-
})
109+
}, cb)
134110
}
135111
})
136-
}, err => {
112+
}, function (err) {
137113
if (err) { stream.emit('error') }
138114
stream.end()
139115
})
@@ -163,6 +139,32 @@ function notFoundError (cache, key) {
163139
return err
164140
}
165141

142+
function bucketEntries (cache, bucket, filter) {
143+
return readFileAsync(
144+
bucket, 'utf8'
145+
).then(data => {
146+
let entries = []
147+
data.split('\n').forEach(entry => {
148+
const pieces = entry.split('\t')
149+
if (!pieces[1] || pieces[1].length !== parseInt(pieces[0], 10)) {
150+
// Length is no good! Corruption ahoy!
151+
return
152+
}
153+
let obj
154+
try {
155+
obj = JSON.parse(pieces[1])
156+
} catch (e) {
157+
// Entry is corrupted!
158+
return
159+
}
160+
if (obj) {
161+
entries.push(obj)
162+
}
163+
})
164+
return entries
165+
})
166+
}
167+
166168
function bucketDir (cache) {
167169
return path.join(cache, `index-v${indexV}`)
168170
}

0 commit comments

Comments
 (0)