[armedbear-cvs] r13329 - trunk/abcl/tools

mevenson at common-lisp.net mevenson at common-lisp.net
Wed Jun 15 06:26:33 UTC 2011


Author: mevenson
Date: Tue Jun 14 23:26:32 2011
New Revision: 13329

Log:
Fast SHA-{1,256,512} cryptographic hashes for files.

Includes the start of a benchmark that seems to show that using NIO
direcly without involving Lisp streams works a couple orders of
magnitude faster.  A definite point of optimization would be to have a
java.nio.ByteBuffer backed Stream that could be used as source and/or
a sync for fast io via FileChannel.

Added:
   trunk/abcl/tools/digest.lisp

Added: trunk/abcl/tools/digest.lisp
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ trunk/abcl/tools/digest.lisp	Tue Jun 14 23:26:32 2011	(r13329)
@@ -0,0 +1,68 @@
+(defvar *digest-types* 
+  '((:sha-1 . "SHA-1")
+    (:sha-256 . "SHA-256")
+    (:sha-512 . "SHA-512")))
+
+(defconstant +byte-buffer-rewind+ 
+  (jmethod "java.nio.ByteBuffer" "rewind"))
+(defconstant +byte-buffer-get+ 
+  (jmethod "java.nio.ByteBuffer" "get" "[B" "int" "int"))
+(defconstant +digest-update+ 
+  (jmethod "java.security.MessageDigest" "update" "[B" "int" "int"))
+
+;;;  needs ABCL svn > r13328 and is probably not faster than the NIO version
+
+(defun digest-file-1 (path &key (digest :sha-256))
+ (let* ((digest-type (cdr (assoc digest *digest-types*)))
+        (digest (jstatic "getInstance" "java.security.MessageDigest" digest-type))
+        (buffer (make-array 8192 :element-type '(unsigned-byte 8))))
+   (with-open-file (input path :element-type '(unsigned-byte 8))
+     (loop :for bytes = (read-sequence buffer input)
+        :while (plusp bytes)
+        :do 
+        (jcall-raw "update" digest 
+                   (jnew-array-from-array "byte" buffer) 0 bytes))
+     (jcall "digest" digest))))
+
+(defun digest-file (path &key (digest :sha-256))
+ (let* ((digest-type (cdr (assoc digest *digest-types*)))
+        (digest (jstatic "getInstance" "java.security.MessageDigest" digest-type))
+        (namestring (if (pathnamep path) (namestring path) path))
+        (file-input-stream (jnew "java.io.FileInputStream" namestring))
+        (channel (jcall "getChannel" file-input-stream))
+        (length 8192)
+        (buffer (jstatic "allocateDirect" "java.nio.ByteBuffer" length))
+        (array (jnew-array "byte" length)))
+   (do ((read (jcall "read" channel buffer)
+              (jcall "read" channel buffer)))
+       ((not (> read 0)))
+     (jcall +byte-buffer-rewind+ buffer)
+     (jcall +byte-buffer-get+ buffer array 0 read)
+     (jcall +byte-buffer-rewind+ buffer)
+     (jcall +digest-update+ digest array 0 read))
+   (jcall "digest" digest)))
+
+(defun ascii-digest (digest)
+  (format nil "~{~X~}"
+          (mapcar (lambda (b) (if (< b 0) (+ 256 b) b))
+                  (java::list-from-jarray digest))))
+
+(defun benchmark (directory)
+    (let (results start-1 end-1 start-2 end-2)
+      (dolist (entry (directory directory))
+        (setf start-1 (get-internal-run-time))
+        (digest-file-1 entry)
+        (setf end-1 (get-internal-run-time))
+        (setf start-2 (get-internal-run-time))
+        (digest-file entry)
+        (setf end-2 (get-internal-run-time))
+        (let ((result (list entry (- end-1 start-1) (- end-2 start-2))))
+          (format t "~&~A" result)
+          (push result results)))
+      results))
+    
+        
+
+
+    
+




More information about the armedbear-cvs mailing list