perf(parse-rule): O(n) join-lines; hash set for config dir-cycle dedup
ober
f82940aa59e97d65b2ee7d9c1861f6e33b454164
--- a/lib/semgrep/rule/parse-rule.sls +++ b/lib/semgrep/rule/parse-rule.sls @@ -150,12 +150,14 @@ (cond [(null? lines) ""] [else - (let loop ([remaining (cdr lines)] [acc (car lines)]) - (if (null? remaining) - acc - (loop - (cdr remaining) - (string-append acc "\n" (car remaining)))))])) + (let ([out (open-output-string)]) + (display (car lines) out) + (let loop ([remaining (cdr lines)]) + (unless (null? remaining) + (display #\newline out) + (display (car remaining) out) + (loop (cdr remaining)))) + (get-output-string out))])) (def (line-indent line) (let ([len (string-length line)]) (let loop ([i 0]) @@ -429,14 +431,12 @@ (let ([key (cons (secure-entry-device info) (secure-entry-inode info))]) - (let loop ([xs seen]) - (and (not (null? xs)) - (or (equal? key (car xs)) (loop (cdr xs))))))) + (hash-key? seen key))) (def (config-files-recursive handle) (let ([entry-count 0] [file-count 0] [path-char-count 0] - [seen '()]) + [seen (make-hash-table)]) (let walk ([relative-dir ""] [depth 0] [acc '()]) (when (> depth max-config-walk-depth) (error 'parse-config-file @@ -452,12 +452,12 @@ (error 'parse-config-file "config directory contains a cycle" relative-dir)) - (set! seen + (hash-put! + seen (cons - (cons - (secure-entry-device directory-info) - (secure-entry-inode directory-info)) - seen)) + (secure-entry-device directory-info) + (secure-entry-inode directory-info)) + #t) (let loop ([entries (secure-directory-list handle relative-dir --- a/src/semgrep/rule/parse-rule.ss +++ b/src/semgrep/rule/parse-rule.ss @@ -150,11 +150,14 @@ (cond [(null? lines) ""] [else - (let loop ([remaining (cdr lines)] [acc (car lines)]) - (if (null? remaining) - acc - (loop (cdr remaining) - (string-append acc "\n" (car remaining)))))])) + (let ([out (open-output-string)]) + (display (car lines) out) + (let loop ([remaining (cdr lines)]) + (unless (null? remaining) + (display #\newline out) + (display (car remaining) out) + (loop (cdr remaining)))) + (get-output-string out))])) (def (line-indent line) (let ([len (string-length line)]) @@ -438,16 +441,13 @@ (def (config-identity-seen? info seen) (let ([key (cons (secure-entry-device info) (secure-entry-inode info))]) - (let loop ([xs seen]) - (and (not (null? xs)) - (or (equal? key (car xs)) - (loop (cdr xs))))))) + (hash-key? seen key))) (def (config-files-recursive handle) (let ([entry-count 0] [file-count 0] [path-char-count 0] - [seen '()]) + [seen (make-hash-table)]) (let walk ([relative-dir ""] [depth 0] [acc '()]) (when (> depth max-config-walk-depth) (error 'parse-config-file "config directory exceeds depth limit")) @@ -457,10 +457,10 @@ (when (config-identity-seen? directory-info seen) (error 'parse-config-file "config directory contains a cycle" relative-dir)) - (set! seen - (cons (cons (secure-entry-device directory-info) - (secure-entry-inode directory-info)) - seen)) + (hash-put! seen + (cons (secure-entry-device directory-info) + (secure-entry-inode directory-info)) + #t) (let loop ([entries (secure-directory-list handle relative-dir 10000 (* 1024 1024))] [current-acc acc])