Re: File I/O Metrics
Mark Evenson <[email protected]> Sat, 5 Nov 2022 19:40:01 +0100
| Newsgroups | gmane.editors.j.devel |
|---|---|
| Message-ID | <[email protected]> |
> On Nov 1, 2022, at 02:33, Alan Ruttenberg <[email protected]> = wrote: >=20 > Here's an example of fast reading in ABCL. The implementation of = certain array types use java.nio buffers, which can be directly read = into via the java.nio functions. >=20 > (defun test-read (path) > (let* ((f (new 'RandomAccessFile (namestring (truename path)) "r")) > (channel (#"getChannel" f)) > (array (make-array (* 16 1024 1024) :element-type = '(unsigned-byte 8))) > (buffer (get-java-field array "elements" t))) > (time (loop for count =3D (#"read" channel buffer) > until (eql count -1) > sum count > do (#"position" buffer 0) > )))) >=20 > On my machine, for a 5G file, the SBCL code in an earlier post takes = 2.4 seconds. This code takes 1.4 sec. It's fastest if I use 2M buffers - = 1.1 seconds. SBCL is also marginally faster with smaller buffer sizes. >=20 > In the ABCL source code the files "SimpleArray_*.java" are the = implementations of the nio buffer backed array types. See = make_array.java where the specific type of underlying array is chosen. = There is a global switch for array allocation choosing either direct = allocation or nio-buffers, with the default being nio buffers. >=20 > (get-java-field 'java$buffers "active" t) > -> #<org.armedbear.lisp.Java$Buffers$AllocationPolicy NIO {432E958E}>=20= Hmmm. That isn=E2=80=99t quite the official interface that I = implemented for abcl-1.7. and am rather unsure if setting that really = works at the moment. I would need to look closer at the Java = implementation to be sure. =20 The =E2=80=9Cofficial=E2=80=9D way is to use the additional keywords to = CL:MAKE-ARRAY =46rom the fine manual =C2=A7 4.10 "Extension to CL:MAKE-ARRARY" With the NIO feature is present and indicated by the presence of :nio in CL:*FEATURES*, the implementation adds two keyword arguments to CL:MAKE-ARRAY :nio-buffer and :nio-direct. With the :nio-buffer keyword, the user is able to pass instances of of java.nio.ByteBuffer and its subclasses for the storage of vectors and arrays specialized on the byte-vector types satisfying (or (unsigned-byte 8) (unsigned-byte 16) (unsigned-byte 32)) As an example, the following would use the :nio-buffer as follows to create a 16 byte vector using the created byte-buffer for storage: (let* ((length 16) (byte-buffer (java:jstatic "allocate" "java.nio.ByteBuffer" = length))) (make-array length :element-type '(unsigned-byte 8) :nio-buffer = byte-buffer)) :nio-buffer NIO-BUFFER Initializes the contents of the new vector or array with the contents of NIO-BUFFER which needs to be a reference to a JAVA-OBJECT of class java.nio.ByteBuffer. \:nio-direct NIO-DIRECT-P NIO-DIRECT-P is not NIL, constructs a java.nio.Buffer as a ``direct'' buffer. The buffers returned by this method typically have somewhat higher allocation and deallocation costs than non-direct buffers. The contents of direct buffers may reside outside of the normal garbage-collected heap, and so their impact upon the memory footprint of an application might not be obvious. It is therefore recommended that direct buffers be allocated primarily for large, long-lived buffers that are subject to the underlying system's native I/O operations. In general it is best to allocate direct buffers only when they yield a measurable gain in program performance. > I haven't looked into the :element-type 'character case.=20 >=20 > Maybe someone who is familiar with the ABCL stream implementation is = interested in writing a fast path for read-sequence that uses the nio = calls? If so, shout. Otherwise I'll keep it on my = procrastinate-by-hacking-abcl list. I have some experiments with replacing i/o with asynchronous thread = pools, for which using specials isn=E2=80=99t going to work, hence it is = preferrable to use the CL:MAKE-ARRAY implementation. =20 After I finish stablizing with abcl-1.9.1 (any day now=E2=80=A6). we can = start look at optimizing for various read/write patterns. Other than = =E2=80=9Cmake it as fast as SBCL=E2=80=9D it would be helpful if = potential users could give me some usage patterns to optimize for. Oh, and with suitable elbow grease the ultimate plan is to add a flag to = mmap(2) files as well, which should speed up fasl loads immensely. =20 --=20 "A screaming comes across the sky. It has happened before but there is = nothing=20 to compare to it now."