From cd01108e1b50243709f69a97fbe0a8a139718a3d Mon Sep 17 00:00:00 2001 From: Jason Bedard Date: Tue, 9 Jun 2026 14:57:54 -0700 Subject: [PATCH 1/2] perf: skip comment assignment when the file has no comments assignComments calls order() which walks the entire tree appending every expression to the preorder/postorder lists used only to attach comments. When the file has no comments this work (and its allocation) is wasted, so return early. --- build/lex.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/build/lex.go b/build/lex.go index f56fe2f01..d257d684b 100644 --- a/build/lex.go +++ b/build/lex.go @@ -881,6 +881,12 @@ func (in *input) order(v Expr) { // assignComments attaches comments to nearby syntax. func (in *input) assignComments() { + // If the file has no comments there is nothing to assign, then we can skip + // the expensive .order() when the file has no comments. + if len(in.lineComments) == 0 && len(in.suffixComments) == 0 { + return + } + // Generate preorder and postorder lists. in.order(in.file) in.assignSuffixComments() From b260fd596b37d0e7271c6eadc892becdd8c71268 Mon Sep 17 00:00:00 2001 From: Jason Bedard Date: Tue, 9 Jun 2026 17:03:35 -0700 Subject: [PATCH 2/2] perf: only build the comment-ordering list that is actually used order() builds both the preorder and postorder lists, but the preorder list is only consumed when attaching line comments and the postorder list only when attaching suffix comments. Build each list only when a comment of that kind is present, so a file with only one kind of comment no longer allocates the unused list. --- build/lex.go | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/build/lex.go b/build/lex.go index d257d684b..0fba2e35a 100644 --- a/build/lex.go +++ b/build/lex.go @@ -738,7 +738,7 @@ var keywordToken = map[string]int{ // order walks the expression adding it and its subexpressions to the // preorder and postorder lists. func (in *input) order(v Expr) { - if v != nil { + if len(in.lineComments) > 0 && v != nil { in.pre = append(in.pre, v) } switch v := v.(type) { @@ -874,23 +874,29 @@ func (in *input) order(v Expr) { in.order(s) } } - if v != nil { + if len(in.suffixComments) > 0 && v != nil { in.post = append(in.post, v) } } // assignComments attaches comments to nearby syntax. func (in *input) assignComments() { - // If the file has no comments there is nothing to assign, then we can skip - // the expensive .order() when the file has no comments. - if len(in.lineComments) == 0 && len(in.suffixComments) == 0 { + // Line comments are attached using the preorder list, suffix comments using + // the postorder list (order() builds only the list(s) for the comment kinds + // present). If the file has neither kind, skip the whole-tree walk entirely. + hasLine := len(in.lineComments) > 0 + hasSuffix := len(in.suffixComments) > 0 + if !hasLine && !hasSuffix { return } - // Generate preorder and postorder lists. in.order(in.file) - in.assignSuffixComments() - in.assignLineComments() + if hasSuffix { + in.assignSuffixComments() + } + if hasLine { + in.assignLineComments() + } } func (in *input) assignSuffixComments() {