From ccbaa1a4b447c67f997a63494a82c8e2b905dccd Mon Sep 17 00:00:00 2001 From: Maxime Devos Date: Sun, 5 Sep 2021 16:28:33 +0200 Subject: [PATCH v2 9/9] base32: Reduce GC pressure in make-bytevector->base32-string. The following code has been used to compare performance: ;; first 20 bytes of sha256 of #vu8(#xde #xad #xbe #xef) (define bv #vu8(95 120 195 50 116 228 63 169 222 86 89 38 92 29 145 126 37 192 55 34)) ,profile (let loop ((n 0)) (when (< n #e1e6) ((@ (guix base32) bytevector->nix-base32-string) bv) (loop (+ n 1)))) Before this change, the output was: [...] Sample count: 1140 Total time: 27.465560018 seconds (10.659331433 seconds in GC) After this change, the output was: [...] Sample count: 957 Total time: 20.478847143 seconds (6.139721189 seconds in GC) * guix/base32.scm (make-bytevector->base32-string): Eliminate 'reverse', use mutation instead. --- guix/base32.scm | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/guix/base32.scm b/guix/base32.scm index 49f191ba26..e76bf35ecc 100644 --- a/guix/base32.scm +++ b/guix/base32.scm @@ -141,12 +141,18 @@ the previous application or INIT." (define (make-bytevector->base32-string quintet-fold base32-chars) (lambda (bv) "Return a base32 encoding of BV using BASE32-CHARS as the alphabet." - (let ((chars (quintet-fold (lambda (q r) - (cons (vector-ref base32-chars q) - r)) - '() - bv))) - (list->string (reverse chars))))) + ;; Mutation can be avoided with 'reverse'. However, that would + ;; make this procedure about 30% slower due to the extra GC pressure. + (let* ((start (cons #f #f)) + (end (quintet-fold (lambda (q r) + (define pair + (cons (vector-ref base32-chars q) #f)) + (set-cdr! r pair) + pair) + start + bv))) + (set-cdr! end '()) + (list->string (cdr start))))) (define %nix-base32-chars ;; See `libutil/hash.cc'. -- 2.33.0