~ chicken-core (chicken-5) 2853220c6b18ca4bb9afb3cace0b9d9c647102ea
commit 2853220c6b18ca4bb9afb3cace0b9d9c647102ea Author: megane <meganeka@gmail.com> AuthorDate: Wed Mar 20 15:15:25 2019 +0200 Commit: Peter Bex <peter@more-magic.net> CommitDate: Sun Mar 24 19:49:55 2019 +0100 Make imports faster Importing modules with many identifiers (e.g. wrappers for GL libraries) most of the time is spent merging the environments in merge-se. * modules.scm (merge-se): Use hash-tables to get O(n) instead of O(n^2) behaviour Signed-off-by: Kooda <kooda@upyum.com> Signed-off-by: Peter Bex <peter@more-magic.net> diff --git a/internal.scm b/internal.scm index 4594f23e..605a72ad 100644 --- a/internal.scm +++ b/internal.scm @@ -50,7 +50,7 @@ macro-subset fixup-macro-environment ;; Low-level hash table support - hash-table-ref hash-table-set! hash-table-update! + make-hash-table hash-table-ref hash-table-set! hash-table-update! hash-table-for-each hash-table-size ;; Modules that are made available to code by default @@ -174,6 +174,9 @@ (set! cache-h (##core#inline "C_u_i_string_hash" (##sys#slot s 1) rand)) (##core#inline "C_fixnum_modulo" cache-h n)))))) +(define (make-hash-table #!optional (size 301)) + (make-vector size '())) + (define (hash-table-ref ht key) (let loop ((bucket (##sys#slot ht (hash-symbol key (##core#inline "C_block_size" ht))))) (and (not (eq? '() bucket)) diff --git a/modules.scm b/modules.scm index e018de5f..debe15c5 100644 --- a/modules.scm +++ b/modules.scm @@ -294,15 +294,22 @@ (warn "indirect export of unknown binding" (car iexports)) (loop2 (cdr iexports))))))))))) -(define (merge-se . ses) ; later occurrences take precedence - (let bwd ((ses (remove null? ses))) - (cond ((null? ses) '()) - ((null? (cdr ses)) (car ses)) ; Do not re-cons the final list - (else (let fwd ((se (car ses)) - (rest (bwd (cdr ses)))) - (cond ((null? se) rest) - ((assq (caar se) rest) (fwd (cdr se) rest)) - (else (cons (car se) (fwd (cdr se) rest))))))))) +(define (merge-se . ses*) ; later occurrences take precedence to earlier ones + (let ((seen (make-hash-table)) (rses (reverse ses*))) + (let loop ((ses (cdr rses)) (last-se #f) (se2 (car rses))) + (cond ((null? ses) se2) + ((or (eq? last-se (car ses)) (null? (car ses))) + (loop (cdr ses) last-se se2)) + ((not last-se) + (unless (null? ses) + (for-each (lambda (e) (hash-table-set! seen (car e) #t)) se2)) + (loop ses se2 se2)) + (else (let lp ((se (car ses)) (se2 se2)) + (cond ((null? se) (loop (cdr ses) (car ses) se2)) + ((hash-table-ref seen (caar se)) + (lp (cdr se) se2)) + (else (hash-table-set! seen (caar se) #t) + (lp (cdr se) (cons (car se) se2)))))))))) (define (##sys#compiled-module-registration mod) (let ((dlist (module-defined-list mod))Trap