Skip to content

Commit 9ac4696

Browse files
committed
perf: determine js_run_devserver isDirectory in rule
1 parent adec779 commit 9ac4696

File tree

2 files changed

+36
-47
lines changed

2 files changed

+36
-47
lines changed

js/private/js_run_devserver.bzl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ def _file_to_entry_json(f):
3535
if len(path_segments) <= package_name_segment or "@0.0.0" not in path_segments[package_name_segment]:
3636
return None
3737

38-
return json.encode(f.short_path)
38+
return json.encode([f.short_path, 1 if f.is_directory else 0])
3939

4040
def _js_run_devserver_impl(ctx):
4141
config_file = ctx.actions.declare_file("{}_config.json".format(ctx.label.name))

js/private/js_run_devserver.mjs

Lines changed: 35 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -176,20 +176,18 @@ async function syncSymlink(src, dst, sandbox, exists) {
176176
return 1
177177
}
178178

179-
async function syncDirectory(src, dst, sandbox, writePerm) {
179+
async function syncDirectory(file, src, sandbox, writePerm) {
180180
if (process.env.JS_BINARY__LOG_DEBUG) {
181-
console.error(
182-
`Syncing directory ${src.slice(RUNFILES_ROOT.length + 1)}...`
183-
)
181+
console.error(`Syncing directory ${file}...`)
184182
}
185183
const contents = await fs.promises.readdir(src)
186184
return (
187185
await Promise.all(
188186
contents.map(
189187
async (entry) =>
190188
await syncRecursive(
191-
path.join(src, entry),
192-
path.join(dst, entry),
189+
path.join(file, entry),
190+
undefined,
193191
sandbox,
194192
writePerm
195193
)
@@ -201,9 +199,9 @@ async function syncDirectory(src, dst, sandbox, writePerm) {
201199
async function syncFile(src, dst, exists, lstat, writePerm) {
202200
if (process.env.JS_BINARY__LOG_DEBUG) {
203201
console.error(
204-
`Syncing file ${src.slice(
205-
RUNFILES_ROOT.length + 1
206-
)} (${friendlyFileSize(lstat.size)})`
202+
`Syncing file ${src.slice(RUNFILES_ROOT.length + 1)}${
203+
lstat ? ' (' + friendlyFileSize(lstat.size) + ')' : ''
204+
})`
207205
)
208206
}
209207
if (exists) {
@@ -237,7 +235,10 @@ async function syncFile(src, dst, exists, lstat, writePerm) {
237235
// synced it is only re-copied if the file's last modified time has changed since the last time that
238236
// file was copied. Symlinks are not copied but instead a symlink is created under the destination
239237
// pointing to the source symlink.
240-
async function syncRecursive(src, dst, sandbox, writePerm) {
238+
async function syncRecursive(file, _, sandbox, writePerm) {
239+
const src = path.join(RUNFILES_ROOT, file)
240+
const dst = path.join(sandbox, file)
241+
241242
try {
242243
const lstat = await withRetry(
243244
() => fs.promises.lstat(src),
@@ -260,7 +261,7 @@ async function syncRecursive(src, dst, sandbox, writePerm) {
260261
if (lstat.isSymbolicLink()) {
261262
return syncSymlink(src, dst, sandbox, exists)
262263
} else if (lstat.isDirectory()) {
263-
return syncDirectory(src, dst, sandbox, writePerm)
264+
return syncDirectory(file, src, sandbox, writePerm)
264265
} else {
265266
const lastChecksum = syncedChecksum.get(src)
266267
const checksum = await generateChecksum(src)
@@ -293,8 +294,11 @@ async function deleteFiles(previousFiles, updatedFiles, sandbox) {
293294
const deletions = []
294295

295296
// Remove files that were previously synced but are no longer in the updated list of files to sync
296-
const updatedFilesSet = new Set(updatedFiles)
297-
for (const f of previousFiles) {
297+
const updatedFilesSet = new Set()
298+
for (const [f] of updatedFiles) {
299+
updatedFilesSet.add(f)
300+
}
301+
for (const [f] of previousFiles) {
298302
if (updatedFilesSet.has(f)) {
299303
continue
300304
}
@@ -353,18 +357,19 @@ async function syncFiles(files, sandbox, writePerm, doSync) {
353357
const packageStore1pDeps = []
354358
const otherNodeModulesFiles = []
355359
const otherFiles = []
356-
for (const file of files) {
360+
for (const fileInfo of files) {
361+
const file = fileInfo[0]
357362
if (isNodeModulePath(file)) {
358363
// Node module file
359364
if (is1pPackageStoreDep(file)) {
360365
// 1p package store dep
361-
packageStore1pDeps.push(file)
366+
packageStore1pDeps.push(fileInfo)
362367
} else {
363368
// Other node_modules file
364-
otherNodeModulesFiles.push(file)
369+
otherNodeModulesFiles.push(fileInfo)
365370
}
366371
} else {
367-
otherFiles.push(file)
372+
otherFiles.push(fileInfo)
368373
}
369374
}
370375

@@ -378,10 +383,8 @@ async function syncFiles(files, sandbox, writePerm, doSync) {
378383

379384
let totalSynced = (
380385
await Promise.all(
381-
otherFiles.map(async (file) => {
382-
const src = path.join(RUNFILES_ROOT, file)
383-
const dst = path.join(sandbox, file)
384-
return await doSync(src, dst, sandbox, writePerm)
386+
otherFiles.map(async ([file, isDirectory]) => {
387+
return await doSync(file, isDirectory, sandbox, writePerm)
385388
})
386389
)
387390
).reduce((s, t) => s + t, 0)
@@ -396,10 +399,8 @@ async function syncFiles(files, sandbox, writePerm, doSync) {
396399

397400
totalSynced += (
398401
await Promise.all(
399-
packageStore1pDeps.map(async (file) => {
400-
const src = path.join(RUNFILES_ROOT, file)
401-
const dst = path.join(sandbox, file)
402-
return await doSync(src, dst, sandbox, writePerm)
402+
packageStore1pDeps.map(async ([file, isDirectory]) => {
403+
return await doSync(file, isDirectory, sandbox, writePerm)
403404
})
404405
)
405406
).reduce((s, t) => s + t, 0)
@@ -413,10 +414,8 @@ async function syncFiles(files, sandbox, writePerm, doSync) {
413414

414415
totalSynced += (
415416
await Promise.all(
416-
otherNodeModulesFiles.map(async (file) => {
417-
const src = path.join(RUNFILES_ROOT, file)
418-
const dst = path.join(sandbox, file)
419-
return await doSync(src, dst, sandbox, writePerm)
417+
otherNodeModulesFiles.map(async ([file, isDirectory]) => {
418+
return await doSync(file, isDirectory, sandbox, writePerm)
420419
})
421420
)
422421
).reduce((s, t) => s + t, 0)
@@ -658,7 +657,7 @@ async function watchProtocolCycle(config, entriesPath, sandbox, cycle) {
658657
const newFiles = await fs.promises.readFile(entriesPath).then(JSON.parse)
659658

660659
// Only sync files changed in the current cycle.
661-
const filesToSync = newFiles.filter((f) =>
660+
const filesToSync = newFiles.filter(([f]) =>
662661
cycle.sources.hasOwnProperty(`${process.env.JS_BINARY__WORKSPACE}/${f}`)
663662
)
664663

@@ -679,7 +678,10 @@ async function watchProtocolCycle(config, entriesPath, sandbox, cycle) {
679678
config.previous_entries = newFiles
680679
}
681680

682-
async function cycleSyncRecurse(cycle, src, dst, sandbox, writePerm) {
681+
async function cycleSyncRecurse(cycle, file, isDirectory, sandbox, writePerm) {
682+
const src = path.join(RUNFILES_ROOT, file)
683+
const dst = path.join(sandbox, file)
684+
683685
// Assume it exists if it has been synced before.
684686
const exists = syncedTime.has(src)
685687

@@ -700,23 +702,10 @@ async function cycleSyncRecurse(cycle, src, dst, sandbox, writePerm) {
700702
return syncSymlink(src, dst, sandbox, exists)
701703
}
702704

703-
let isDirectory = false
704-
let lstat = null
705-
if (isNodeModulePath(src)) {
706-
// A node_modules path which is not a symlink is always a directory
707-
isDirectory = true
708-
} else {
709-
// Otherwise a fs.lstat is needed to determine if it is a directory
710-
// TODO: move to protocol capability that expands directories
711-
lstat = await fs.promises.lstat(src)
712-
713-
isDirectory = lstat.isDirectory()
714-
}
715-
716705
if (isDirectory) {
717-
return syncDirectory(src, dst, sandbox, writePerm)
706+
return syncDirectory(file, src, sandbox, writePerm)
718707
} else {
719-
return syncFile(src, dst, exists, lstat, writePerm)
708+
return syncFile(src, dst, exists, null, writePerm)
720709
}
721710
}
722711

0 commit comments

Comments
 (0)