From d2464e525b55ef9fc1d03bbd1cd7860fb90800c3 Mon Sep 17 00:00:00 2001 From: Tienson Qin Date: Sun, 30 Aug 2026 14:47:12 +0800 Subject: [PATCH] [WARNING] Running as root is not recommended perf: reduce outline line metadata allocations --- lib/syntax/md_outline.ml | 39 +++++++++++++++++++++++++-------------- lib/syntax/property.ml | 22 +++++++++++++++++++++- 2 files changed, 46 insertions(+), 15 deletions(-) diff --git a/lib/syntax/md_outline.ml b/lib/syntax/md_outline.ml index abbdba08..2d1672e5 100644 --- a/lib/syntax/md_outline.ml +++ b/lib/syntax/md_outline.ml @@ -763,22 +763,33 @@ let rec parse_list_items config lines i min_indent = let parse config input = let raw_lines = String.split_on_char '\n' input in - let lines = Array.of_list (List.map rstrip_cr raw_lines) in + let lines = Array.of_list raw_lines in + (* [split_on_char] has already allocated every line. Reuse those strings + for the overwhelmingly common LF input rather than allocating an + intermediate mapped list; only replace CRLF lines in place. *) + Array.iteri + (fun i line -> + let stripped = rstrip_cr line in + if stripped != line then lines.(i) <- stripped) + lines; let n = Array.length lines in let line_starts = - let arr = Array.make (max n 1) 0 in - let pos = ref 0 in - for idx = 0 to n - 1 do - arr.(idx) <- !pos; - let nl = - if idx + 1 < n then - 1 - else - 0 - in - pos := !pos + String.length lines.(idx) + nl - done; - arr + if config.parse_outline_only then + [||] + else + let arr = Array.make (max n 1) 0 in + let pos = ref 0 in + for idx = 0 to n - 1 do + arr.(idx) <- !pos; + let nl = + if idx + 1 < n then + 1 + else + 0 + in + pos := !pos + String.length lines.(idx) + nl + done; + arr in let src_end_pos body_i = let rec find j = diff --git a/lib/syntax/property.ml b/lib/syntax/property.ml index 3c29b701..f9e4684b 100644 --- a/lib/syntax/property.ml +++ b/lib/syntax/property.ml @@ -18,11 +18,31 @@ open Conf let property_references config s = let config = { config with inline_skip_macro = true } in + (* Most Logseq properties are scalar values (ids, dates, booleans, and so + on). Running the complete inline grammar for all of them dominates an + outline parse even though only tags and links survive the filter below. + Every syntax accepted by that filter starts with one of these bytes, so + cheaply reject scalar values before constructing an Angstrom parser. *) + let may_have_reference = + let length = String.length s in + let rec loop i = + if i = length then + false + else + match s.[i] with + | '#' + | '[' + | '(' -> + true + | _ -> loop (i + 1) + in + loop 0 + in let end_quoted = match last_char s with | Some '"' -> true | _ -> false in - if s = "" || (s.[0] == '"' && end_quoted) then + if (not may_have_reference) || (s.[0] == '"' && end_quoted) then [] else match parse_string ~consume:All (Inline.parse config) s with