serialization: Micro-optimize string literal output in 'write-file-tree'.
This reduces allocations and bit twiddling in the loop. * guix/serialization.scm (write-literal-strings): New macro. (write-file-tree): Use it in lieu of 'write-string' calls where applicable.master
parent
9ce78f27a0
commit
f293705d7e
|
@ -199,6 +199,37 @@ substitute invalid byte sequences with question marks. This is a
|
||||||
(define write-store-path-list write-string-list)
|
(define write-store-path-list write-string-list)
|
||||||
(define read-store-path-list read-string-list)
|
(define read-store-path-list read-string-list)
|
||||||
|
|
||||||
|
(define-syntax write-literal-strings
|
||||||
|
(lambda (s)
|
||||||
|
"Write the given literal strings to PORT in an optimized fashion, without
|
||||||
|
any run-time allocations or computations."
|
||||||
|
(define (padding len)
|
||||||
|
(let ((m (modulo len 8)))
|
||||||
|
(if (zero? m)
|
||||||
|
0
|
||||||
|
(- 8 m))))
|
||||||
|
|
||||||
|
(syntax-case s ()
|
||||||
|
((_ port strings ...)
|
||||||
|
(let* ((bytes (map string->utf8 (syntax->datum #'(strings ...))))
|
||||||
|
(len (fold (lambda (bv size)
|
||||||
|
(+ size 8 (bytevector-length bv)
|
||||||
|
(padding (bytevector-length bv))))
|
||||||
|
0
|
||||||
|
bytes))
|
||||||
|
(bv (make-bytevector len))
|
||||||
|
(zeros (make-bytevector 8 0)))
|
||||||
|
(fold (lambda (str offset)
|
||||||
|
(let ((len (bytevector-length str)))
|
||||||
|
(bytevector-u32-set! bv offset len (endianness little))
|
||||||
|
(bytevector-copy! str 0 bv (+ 8 offset) len)
|
||||||
|
(bytevector-copy! zeros 0 bv (+ 8 offset len)
|
||||||
|
(padding len))
|
||||||
|
(+ offset 8 len (padding len))))
|
||||||
|
0
|
||||||
|
bytes)
|
||||||
|
#`(put-bytevector port #,bv))))))
|
||||||
|
|
||||||
|
|
||||||
(define-condition-type &nar-read-error &nar-error
|
(define-condition-type &nar-read-error &nar-error
|
||||||
nar-read-error?
|
nar-read-error?
|
||||||
|
@ -332,14 +363,12 @@ which case you can use 'identity'."
|
||||||
(define-values (type size)
|
(define-values (type size)
|
||||||
(file-type+size f))
|
(file-type+size f))
|
||||||
|
|
||||||
(write-string "(" p)
|
(write-literal-strings p "(")
|
||||||
(case type
|
(case type
|
||||||
((regular executable)
|
((regular executable)
|
||||||
(write-string "type" p)
|
(write-literal-strings p "type" "regular")
|
||||||
(write-string "regular" p)
|
|
||||||
(when (eq? 'executable type)
|
(when (eq? 'executable type)
|
||||||
(write-string "executable" p)
|
(write-literal-strings p "executable" ""))
|
||||||
(write-string "" p))
|
|
||||||
(let ((input (file-port f)))
|
(let ((input (file-port f)))
|
||||||
(dynamic-wind
|
(dynamic-wind
|
||||||
(const #t)
|
(const #t)
|
||||||
|
@ -348,28 +377,23 @@ which case you can use 'identity'."
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(close-port input)))))
|
(close-port input)))))
|
||||||
((directory)
|
((directory)
|
||||||
(write-string "type" p)
|
(write-literal-strings p "type" "directory")
|
||||||
(write-string "directory" p)
|
|
||||||
(let ((entries (postprocess-entries (directory-entries f))))
|
(let ((entries (postprocess-entries (directory-entries f))))
|
||||||
(for-each (lambda (e)
|
(for-each (lambda (e)
|
||||||
(let* ((f (string-append f "/" e)))
|
(let* ((f (string-append f "/" e)))
|
||||||
(write-string "entry" p)
|
(write-literal-strings p "entry" "(" "name")
|
||||||
(write-string "(" p)
|
|
||||||
(write-string "name" p)
|
|
||||||
(write-string e p)
|
(write-string e p)
|
||||||
(write-string "node" p)
|
(write-literal-strings p "node")
|
||||||
(dump f)
|
(dump f)
|
||||||
(write-string ")" p)))
|
(write-literal-strings p ")")))
|
||||||
entries)))
|
entries)))
|
||||||
((symlink)
|
((symlink)
|
||||||
(write-string "type" p)
|
(write-literal-strings p "type" "symlink" "target")
|
||||||
(write-string "symlink" p)
|
|
||||||
(write-string "target" p)
|
|
||||||
(write-string (symlink-target f) p))
|
(write-string (symlink-target f) p))
|
||||||
(else
|
(else
|
||||||
(raise (condition (&message (message "unsupported file type"))
|
(raise (condition (&message (message "unsupported file type"))
|
||||||
(&nar-error (file f) (port port))))))
|
(&nar-error (file f) (port port))))))
|
||||||
(write-string ")" p)))
|
(write-literal-strings p ")")))
|
||||||
|
|
||||||
(define port-conversion-strategy
|
(define port-conversion-strategy
|
||||||
(fluid->parameter %default-port-conversion-strategy))
|
(fluid->parameter %default-port-conversion-strategy))
|
||||||
|
|
Reference in New Issue