From cea6834fef54da59fc1692d1db0221b93793238f Mon Sep 17 00:00:00 2001
From: Jacky Zhao <j.zhao2k19@gmail.com>
Date: Wed, 09 Aug 2023 07:26:33 +0000
Subject: [PATCH] profiling, better concurrency heuristics

---
 .gitignore                         |    1 +
 content/advanced/making plugins.md |    2 +-
 package.json                       |    3 ++-
 quartz/processors/parse.ts         |    9 +++++----
 4 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/.gitignore b/.gitignore
index 5177d66..fd96fec 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,7 @@
 .gitignore
 node_modules
 public
+prof
 tsconfig.tsbuildinfo
 .obsidian
 .quartz-cache
diff --git a/content/advanced/making plugins.md b/content/advanced/making plugins.md
index a73069e..d2db67e 100644
--- a/content/advanced/making plugins.md
+++ b/content/advanced/making plugins.md
@@ -2,7 +2,7 @@
 title: Making your own plugins
 ---
 
-This part of the documentation will assume you have some basic coding knowledge and will include code snippets that describe the interface of what Quartz plugins should look like.
+This part of the documentation will assume you have some basic coding knowledge in TypeScript and will include code snippets that describe the interface of what Quartz plugins should look like.
 
 ![[quartz-transform-pipeline.png]]
 
diff --git a/package.json b/package.json
index 0d5e7a0..29b46f2 100644
--- a/package.json
+++ b/package.json
@@ -14,7 +14,8 @@
   "scripts": {
     "check": "tsc --noEmit && npx prettier . --check",
     "format": "npx prettier . --write",
-    "test": "tsx ./quartz/path.test.ts"
+    "test": "tsx ./quartz/path.test.ts",
+    "profile": "0x -D prof ./quartz/bootstrap-cli.mjs build --concurrency=1"
   },
   "keywords": [
     "site generator",
diff --git a/quartz/processors/parse.ts b/quartz/processors/parse.ts
index 69df69b..299d59a 100644
--- a/quartz/processors/parse.ts
+++ b/quartz/processors/parse.ts
@@ -9,7 +9,6 @@
 import { read } from "to-vfile"
 import { FilePath, QUARTZ, slugifyFilePath } from "../path"
 import path from "path"
-import os from "os"
 import workerpool, { Promise as WorkerPromise } from "workerpool"
 import { QuartzLogger } from "../log"
 import { trace } from "../trace"
@@ -82,6 +81,7 @@
     const res: ProcessedContent[] = []
     for (const fp of fps) {
       try {
+        const perf = new PerfTimer()
         const file = await read(fp)
 
         // strip leading and trailing whitespace
@@ -101,7 +101,7 @@
         res.push([newAst, file])
 
         if (argv.verbose) {
-          console.log(`[process] ${fp} -> ${file.data.slug}`)
+          console.log(`[process] ${fp} -> ${file.data.slug} (${perf.timeSince()})`)
         }
       } catch (err) {
         trace(`\nFailed to process \`${fp}\``, err as Error)
@@ -112,14 +112,15 @@
   }
 }
 
+const clamp = (num: number, min: number, max: number) => Math.min(Math.max(Math.round(num), min), max);
 export async function parseMarkdown(ctx: BuildCtx, fps: FilePath[]): Promise<ProcessedContent[]> {
   const { argv } = ctx
   const perf = new PerfTimer()
   const log = new QuartzLogger(argv.verbose)
 
+  // rough heuristics: 128 gives enough time for v8 to JIT and optimize parsing code paths
   const CHUNK_SIZE = 128
-  let concurrency =
-    ctx.argv.concurrency ?? (fps.length < CHUNK_SIZE ? 1 : os.availableParallelism())
+  const concurrency = ctx.argv.concurrency ?? clamp(fps.length / CHUNK_SIZE, 1, 4)
 
   let res: ProcessedContent[] = []
   log.start(`Parsing input files using ${concurrency} threads`)

--
Gitblit v1.10.0