Skip to content

Commit 1dc41fa

Browse files
authored
Merge pull request #11986 from quarto-dev/perf/md5-async
Perf: prefer `async` md5 calls
2 parents e0cb9ea + cb9bb5d commit 1dc41fa

File tree

14 files changed

+67
-51
lines changed

14 files changed

+67
-51
lines changed

package/src/common/cyclic-dependencies.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { runCmd } from "../util/cmd.ts";
1111
import { Configuration, readConfiguration } from "./config.ts";
1212
import { error, info } from "../../../src/deno_ral/log.ts";
1313
import { progressBar } from "../../../src/core/console.ts";
14-
import { md5Hash } from "../../../src/core/hash.ts";
14+
import { md5HashSync } from "../../../src/core/hash.ts";
1515

1616
export function cycleDependenciesCommand() {
1717
return new Command()
@@ -186,7 +186,7 @@ function findCyclicDependencies(
186186
// creates a hash for a set of paths (a cycle)
187187
const hash = (paths: string[]) => {
188188
const string = paths.join(" ");
189-
return md5Hash(string);
189+
return md5HashSync(string);
190190
};
191191

192192
// The current import stack

src/command/render/freeze.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import { cloneDeep } from "../../core/lodash.ts";
2424

2525
import { inputFilesDir } from "../../core/render.ts";
2626
import { TempContext } from "../../core/temp.ts";
27-
import { md5Hash } from "../../core/hash.ts";
27+
import { md5HashSync } from "../../core/hash.ts";
2828
import {
2929
normalizePath,
3030
removeIfEmptyDir,
@@ -310,7 +310,7 @@ export function removeFreezeResults(filesDir: string) {
310310
function freezeInputHash(input: string) {
311311
// Calculate the hash on a content with LF line ending to avoid
312312
// different hash on different OS (#3599)
313-
return md5Hash(format(Deno.readTextFileSync(input), LF));
313+
return md5HashSync(format(Deno.readTextFileSync(input), LF));
314314
}
315315

316316
// don't use _files suffix in freezer

src/command/use/commands/binder/binder-utils.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* Copyright (C) 2021-2022 Posit Software, PBC
55
*/
66

7-
import { md5Hash } from "../../../../core/hash.ts";
7+
import { md5HashAsync } from "../../../../core/hash.ts";
88
import { projectScratchPath } from "../../../../project/project-scratch.ts";
99

1010
import { info, warning } from "../../../../deno_ral/log.ts";
@@ -36,11 +36,11 @@ export const safeFileWriter = (projectDir: string, prompt = true) => {
3636
info(`[✓] ${projRelativePath}`);
3737
};
3838

39-
const hash = md5Hash(contents);
39+
const hash = await md5HashAsync(contents);
4040
if (existsSync(absPath)) {
4141
const lastHash = fileIndex[projRelativePath];
4242
const currentContents = Deno.readTextFileSync(absPath);
43-
const currentHash = md5Hash(currentContents);
43+
const currentHash = await md5HashAsync(currentContents);
4444

4545
let writeFile = true;
4646
if (!lastHash || lastHash !== currentHash) {

src/core/devconfig.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { error, info } from "../deno_ral/log.ts";
88
import { join } from "../deno_ral/path.ts";
99
import { ensureDirSync, existsSync } from "../deno_ral/fs.ts";
1010

11-
import { md5Hash } from "./hash.ts";
11+
import { md5HashSync } from "./hash.ts";
1212

1313
import { quartoConfig } from "./quarto.ts";
1414
import { normalizePath } from "./path.ts";
@@ -47,13 +47,13 @@ export function createDevConfig(
4747
dartsass,
4848
esbuild,
4949
typst,
50-
script: md5Hash(Deno.readTextFileSync(scriptPath)),
51-
importMap: md5Hash(
50+
script: md5HashSync(Deno.readTextFileSync(scriptPath)),
51+
importMap: md5HashSync(
5252
Deno.readTextFileSync(
5353
join(srcDir, "import_map.json"),
5454
),
5555
),
56-
bundleImportMap: md5Hash(
56+
bundleImportMap: md5HashSync(
5757
Deno.readTextFileSync(
5858
join(srcDir, "resources/vendor/import_map.json"),
5959
),

src/core/hash.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,15 @@
77
import { crypto } from "crypto/crypto";
88
import blueimpMd5 from "blueimpMd5";
99

10-
export function md5Hash(content: string) {
10+
export function md5HashSync(content: string) {
1111
return blueimpMd5(content);
1212
}
1313

14+
export async function md5HashAsync(content: string) {
15+
const buffer = new TextEncoder().encode(content);
16+
return md5HashBytes(buffer);
17+
}
18+
1419
export async function md5HashBytes(content: Uint8Array) {
1520
const buffer = await crypto.subtle.digest(
1621
"MD5",

src/core/pdfjs.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*/
66

77
import { basename, join } from "../deno_ral/path.ts";
8-
import { md5Hash } from "./hash.ts";
8+
import { md5HashAsync } from "./hash.ts";
99
import { viewerIFrameURL } from "./http-devserver.ts";
1010
import { FileResponse } from "./http-types.ts";
1111
import { contentType } from "./mime.ts";
@@ -100,7 +100,7 @@ export function pdfJsFileHandler(
100100
// (preserve user viewer prefs across reloads)
101101
} else if (file === previewPath("build", "pdf.worker.js")) {
102102
const filePathHash = "quarto-preview-pdf-" +
103-
md5Hash(pdfFile());
103+
await md5HashAsync(pdfFile());
104104
const workerJs = Deno.readTextFileSync(file).replace(
105105
/(key: "fingerprint",\s+get: function get\(\) {\s+)(var hash;)/,
106106
`$1return "${filePathHash}"; $2`,

src/core/sass/cache.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*/
88

99
import { InternalError } from "../lib/error.ts";
10-
import { md5Hash } from "../hash.ts";
10+
import { md5HashAsync } from "../hash.ts";
1111
import { join } from "../../deno_ral/path.ts";
1212
import { ensureDirSync, existsSync } from "../../deno_ral/fs.ts";
1313
import { TempContext } from "../temp.ts";
@@ -105,8 +105,8 @@ class SassCache {
105105
cacheIdentifier: string,
106106
compilationThunk: (outputFilePath: string) => Promise<void>,
107107
): Promise<string> {
108-
const identifierHash = md5Hash(cacheIdentifier);
109-
const inputHash = md5Hash(input);
108+
const identifierHash = await md5HashAsync(cacheIdentifier);
109+
const inputHash = await md5HashAsync(input);
110110
return this.setFromHash(
111111
identifierHash,
112112
inputHash,
@@ -121,8 +121,8 @@ class SassCache {
121121
compilationThunk: (outputFilePath: string) => Promise<void>,
122122
): Promise<string> {
123123
log.debug(`SassCache.getOrSet(...)`);
124-
const identifierHash = md5Hash(cacheIdentifier);
125-
const inputHash = md5Hash(input);
124+
const identifierHash = await md5HashAsync(cacheIdentifier);
125+
const inputHash = await md5HashAsync(input);
126126
const existing = await this.getFromHash(identifierHash, inputHash);
127127
if (existing !== null) {
128128
log.debug(` cache hit`);

src/execute/jupyter/jupyter-kernel.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { sleep } from "../../core/async.ts";
1212
import { quartoDataDir, quartoRuntimeDir } from "../../core/appdirs.ts";
1313
import { execProcess } from "../../core/process.ts";
1414
import { ProcessResult } from "../../core/process-types.ts";
15-
import { md5Hash } from "../../core/hash.ts";
15+
import { md5HashSync } from "../../core/hash.ts";
1616
import { resourcePath } from "../../core/resources.ts";
1717
import { pythonExec } from "../../core/jupyter/exec.ts";
1818
import {
@@ -327,7 +327,7 @@ function kernelTransportFile(target: string) {
327327
throw e;
328328
}
329329
const targetFile = normalizePath(target);
330-
const hash = md5Hash(targetFile).slice(0, 20);
330+
const hash = md5HashSync(targetFile).slice(0, 20);
331331
return join(transportsDir, hash);
332332
}
333333

src/project/project-context.ts

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {
1313
SEP,
1414
} from "../deno_ral/path.ts";
1515

16-
import { existsSync, walkSync } from "../deno_ral/fs.ts";
16+
import { existsSync, walk, walkSync } from "../deno_ral/fs.ts";
1717
import * as ld from "../core/lodash.ts";
1818

1919
import { ProjectType } from "./types/types.ts";
@@ -99,6 +99,7 @@ import { computeProjectEnvironment } from "./project-environment.ts";
9999
import { ProjectEnvironment } from "./project-environment-types.ts";
100100
import { NotebookContext } from "../render/notebook/notebook-types.ts";
101101
import { MappedString } from "../core/mapped-text.ts";
102+
import { makeTimedFunctionAsync } from "../core/performance/function-times.ts";
102103
import { createProjectCache } from "../core/cache/cache.ts";
103104
import { createTempContext, globalTempContext } from "../core/temp.ts";
104105

@@ -750,7 +751,12 @@ function projectHiddenIgnoreGlob(dir: string) {
750751
.concat(["**/README.?([Rrq])md"]); // README
751752
}
752753

753-
export async function projectInputFiles(
754+
export const projectInputFiles = makeTimedFunctionAsync(
755+
"projectInputFiles",
756+
projectInputFilesInternal,
757+
);
758+
759+
async function projectInputFilesInternal(
754760
project: ProjectContext,
755761
metadata?: ProjectConfig,
756762
): Promise<{ files: string[]; engines: string[] }> {
@@ -802,10 +808,9 @@ export async function projectInputFiles(
802808
}];
803809
};
804810
const addDir = async (dir: string): Promise<FileInclusion[]> => {
805-
// ignore selected other globs
806-
const walkIterator = walkSync(
807-
dir,
808-
{
811+
const promises: Promise<FileInclusion[]>[] = [];
812+
for await (
813+
const walkEntry of walk(dir, {
809814
includeDirs: false,
810815
// this was done b/c some directories e.g. renv/packrat and potentially python
811816
// virtualenvs include symblinks to R or Python libraries that are in turn
@@ -816,16 +821,18 @@ export async function projectInputFiles(
816821
globToRegExp(join(dir, ignore) + SEP)
817822
),
818823
),
819-
},
820-
);
821-
return Promise.all(
822-
Array.from(walkIterator)
823-
.filter((walk) => {
824-
const pathRelative = pathWithForwardSlashes(relative(dir, walk.path));
825-
return !projectIgnores.some((regex) => regex.test(pathRelative));
826-
})
827-
.map(async (walk) => addFile(walk.path)),
828-
).then((fileInclusions) => fileInclusions.flat());
824+
})
825+
) {
826+
const pathRelative = pathWithForwardSlashes(
827+
relative(dir, walkEntry.path),
828+
);
829+
if (projectIgnores.some((regex) => regex.test(pathRelative))) {
830+
continue;
831+
}
832+
promises.push(addFile(walkEntry.path));
833+
}
834+
const inclusions = await Promise.all(promises);
835+
return inclusions.flat();
829836
};
830837
const addEntry = async (entry: string) => {
831838
if (Deno.statSync(entry).isDirectory) {

src/project/serve/render.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { isAbsolute, join } from "../../deno_ral/path.ts";
22

33
import { RenderResult, RenderResultFile } from "../../command/render/types.ts";
4-
import { md5Hash } from "../../core/hash.ts";
4+
import { md5HashSync } from "../../core/hash.ts";
55
import { HttpDevServerRenderMonitor } from "../../core/http-devserver.ts";
66
import { isJupyterNotebook } from "../../core/jupyter/jupyter.ts";
77
import { logError } from "../../core/log.ts";
@@ -118,8 +118,8 @@ export class ServeRenderManager {
118118
String(Deno.statSync(inputFile).mtime) +
119119
resourceHash;
120120
} else {
121-
return md5Hash(Deno.readTextFileSync(file)) +
122-
md5Hash(Deno.readTextFileSync(inputFile)) +
121+
return md5HashSync(Deno.readTextFileSync(file)) +
122+
md5HashSync(Deno.readTextFileSync(inputFile)) +
123123
resourceHash;
124124
}
125125
}

0 commit comments

Comments
 (0)