diff --git a/benchmarks/java/FijiExportBench.java b/benchmarks/java/FijiExportBench.java new file mode 100644 index 0000000..75e12ba --- /dev/null +++ b/benchmarks/java/FijiExportBench.java @@ -0,0 +1,77 @@ +import ij.ImagePlus; +import ij.io.FileSaver; +import ij.process.ShortProcessor; +import java.io.File; +import java.io.RandomAccessFile; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.MappedByteBuffer; +import java.nio.channels.FileChannel; +import java.util.Random; + +/** + * What Fiji's host code pays to hand an open image to the worker, measured with the ImageJ that Fiji ships (ij 1.54p): + * tiff_disk FileSaver.saveAsTiff to a file (what LabConstrictor_Tools.groovy does today) + * tiff_shmfs the same into /dev/shm (CPU cost of the encoder, no disk) + * shm_appose Appose 0.12.0 SharedMemory + ShortBuffer.put(short[]) from the ImagePlus's pixel array (JNA) + * tiff_read ij.io.Opener.openImage of the file just written (a result coming back as TIFF) + * shm_to_short_array block -> new short[] (a result coming back through shared memory) + * shm_mmap JDK-only MappedByteBuffer over a file in /dev/shm + * Args: side count scratchDir. Image = side x side uint16 (side 16384 = 512 MiB). One short[] per plane, like ImageJ. + */ +public class FijiExportBench { + public static void main(String[] a) throws Exception { + int side = Integer.parseInt(a[0]); + int repeats = Integer.parseInt(a[1]); + File scratch = new File(a[2]); + short[] pixels = new short[side * side]; + Random r = new Random(1); + for (int i = 0; i < pixels.length; i += 7) pixels[i] = (short) r.nextInt(65536); + ImagePlus imp = new ImagePlus("bench", new ShortProcessor(side, side, pixels, null)); + long nbytes = (long) pixels.length * 2; + for (int k = 0; k < repeats; k++) { + StringBuilder out = new StringBuilder("{\"MiB\":" + nbytes / (1024 * 1024)); + File tif = new File(scratch, "fiji_bench.tif"); + long t = System.nanoTime(); + new FileSaver(imp).saveAsTiff(tif.getPath()); + out.append(",\"tiff_disk_s\":").append(sec(t)); + t = System.nanoTime(); + ImagePlus back = new ij.io.Opener().openImage(tif.getPath()); // what the Fiji host does with an image result + out.append(",\"tiff_read_s\":").append(sec(t)); + if (back == null || back.getWidth() != side) throw new IllegalStateException("read back failed"); + t = System.nanoTime(); + org.apposed.appose.SharedMemory rb = org.apposed.appose.SharedMemory.create((long) side * side * 2); + rb.buf(0, (long) side * side * 2).order(ByteOrder.nativeOrder()).asShortBuffer().put((short[]) pixels); // stand-in for the worker's block + double rbMake = (System.nanoTime() - t) / 1e9; + t = System.nanoTime(); + short[] copy = new short[side * side]; + rb.buf(0, (long) side * side * 2).order(ByteOrder.nativeOrder()).asShortBuffer().get(copy); // block -> ImageJ short[] + out.append(",\"shm_to_short_array_s\":").append(sec(t)); + rb.close(); + back.close(); + tif.delete(); + File tif2 = new File("/dev/shm/fiji_bench.tif"); + t = System.nanoTime(); + new FileSaver(imp).saveAsTiff(tif2.getPath()); + out.append(",\"tiff_shmfs_s\":").append(sec(t)); + tif2.delete(); + t = System.nanoTime(); + org.apposed.appose.SharedMemory shm = org.apposed.appose.SharedMemory.create(nbytes); + shm.buf(0, nbytes).order(ByteOrder.nativeOrder()).asShortBuffer().put((short[]) imp.getProcessor().getPixels()); + out.append(",\"shm_appose_s\":").append(sec(t)); + shm.close(); + File f = new File("/dev/shm/fiji_bench_map"); + t = System.nanoTime(); + RandomAccessFile raf = new RandomAccessFile(f, "rw"); + raf.setLength(nbytes); + MappedByteBuffer buf = raf.getChannel().map(FileChannel.MapMode.READ_WRITE, 0, nbytes); + buf.order(ByteOrder.nativeOrder()).asShortBuffer().put((short[]) imp.getProcessor().getPixels()); + out.append(",\"shm_mmap_s\":").append(sec(t)); + raf.close(); + f.delete(); + System.out.println(out.append("}")); + } + } + + static String sec(long t0) { return String.format("%.3f", (System.nanoTime() - t0) / 1e9); } +} diff --git a/benchmarks/java/ShmProof.java b/benchmarks/java/ShmProof.java new file mode 100644 index 0000000..aec728a --- /dev/null +++ b/benchmarks/java/ShmProof.java @@ -0,0 +1,65 @@ +import java.io.RandomAccessFile; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.MappedByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Random; + +/** + * Java side of the shared-memory proofs (see docs/PERF_SHARED_MEMORY.md, host Fiji / QuPath). + * + * mode "appose": the Appose 0.12.0 SharedMemory (JNA: shm_open + mmap on Linux/macOS, CreateFileMapping on Windows), the + * class Fiji already ships; compiled with --release 8. + * mode "mmap" : JDK only (Java 8+): FileChannel.map over a file in /dev/shm (RAM-backed on Linux). + * mode "ffm" : Java 21 Foreign Function and Memory API (preview in 21): shm_open + mmap without JNA. Compile with + * --enable-preview --release 21 and run with --enable-preview. + * + * Fills a short[] image (what ImageJ holds: one short[] per plane) into the block, prints one JSON line the Python side reads: + * {"mode","name","shape":[h,w],"dtype":"uint16","max":N,"fill_s":x}. The block stays alive until the Python side writes "done" to stdin. + */ +public class ShmProof { + static final int SIDE = Integer.getInteger("side", 4096); + + public static void main(String[] args) throws Exception { + String mode = args[0]; + int h = SIDE, w = SIDE; + short[] pixels = new short[h * w]; + Random r = new Random(1); + int max = 0; long sum = 0; + for (int i = 0; i < pixels.length; i++) { + int v = r.nextInt(65536); // above 255 and above 32767: exposes byte order and signedness mistakes + pixels[i] = (short) v; + max = Math.max(max, v); sum += v; + } + long nbytes = (long) pixels.length * 2; + String name; + long t0 = System.nanoTime(); + AutoCloseable owner; + if (mode.equals("appose")) { + org.apposed.appose.SharedMemory shm = org.apposed.appose.SharedMemory.create(nbytes); + ByteBuffer buf = shm.buf(0, nbytes).order(ByteOrder.nativeOrder()); + buf.asShortBuffer().put(pixels); + name = shm.name(); + owner = shm; + } else if (mode.equals("mmap")) { + name = "lc_java_proof_" + java.util.UUID.randomUUID().toString().substring(0, 8); + Path file = Paths.get("/dev/shm", name); + RandomAccessFile raf = new RandomAccessFile(file.toFile(), "rw"); + raf.setLength(nbytes); + MappedByteBuffer buf = raf.getChannel().map(FileChannel.MapMode.READ_WRITE, 0, nbytes); + buf.order(ByteOrder.nativeOrder()).asShortBuffer().put(pixels); + owner = () -> { raf.close(); Files.deleteIfExists(file); }; + } else { + throw new IllegalArgumentException(mode); + } + double fill = (System.nanoTime() - t0) / 1e9; + System.out.println("{\"mode\":\"" + mode + "\",\"name\":\"" + name + "\",\"shape\":[" + h + "," + w + + "],\"dtype\":\"uint16\",\"max\":" + max + ",\"sum\":" + sum + ",\"first\":" + (pixels[0] & 0xFFFF) + ",\"fill_s\":" + fill + "}"); + System.out.flush(); + System.in.read(); // the host keeps the block until the task is over + owner.close(); + } +} diff --git a/benchmarks/java/ShmProofFfm.java b/benchmarks/java/ShmProofFfm.java new file mode 100644 index 0000000..216a74f --- /dev/null +++ b/benchmarks/java/ShmProofFfm.java @@ -0,0 +1,48 @@ +import java.lang.foreign.*; +import java.lang.invoke.MethodHandle; +import java.nio.ByteOrder; +import java.util.Random; + +/** Java 21 FFM (preview in 21, final in 22): shm_open + ftruncate + mmap straight from libc, no JNA, no JNI. POSIX only. */ +public class ShmProofFfm { + public static void main(String[] args) throws Throwable { + int side = Integer.getInteger("side", 4096); + long nbytes = (long) side * side * 2; + Linker linker = Linker.nativeLinker(); + SymbolLookup libc = linker.defaultLookup(); + // shm_open is variadic (mode is optional): declare the variadic part explicitly + MethodHandle shmOpen = linker.downcallHandle(libc.find("shm_open").orElseThrow(), + FunctionDescriptor.of(ValueLayout.JAVA_INT, ValueLayout.ADDRESS, ValueLayout.JAVA_INT, ValueLayout.JAVA_INT), + Linker.Option.firstVariadicArg(2)); + MethodHandle ftruncate = linker.downcallHandle(libc.find("ftruncate").orElseThrow(), + FunctionDescriptor.of(ValueLayout.JAVA_INT, ValueLayout.JAVA_INT, ValueLayout.JAVA_LONG)); + MethodHandle mmap = linker.downcallHandle(libc.find("mmap").orElseThrow(), + FunctionDescriptor.of(ValueLayout.ADDRESS, ValueLayout.ADDRESS, ValueLayout.JAVA_LONG, ValueLayout.JAVA_INT, + ValueLayout.JAVA_INT, ValueLayout.JAVA_INT, ValueLayout.JAVA_LONG)); + MethodHandle shmUnlink = linker.downcallHandle(libc.find("shm_unlink").orElseThrow(), + FunctionDescriptor.of(ValueLayout.JAVA_INT, ValueLayout.ADDRESS)); + String name = "/lc_ffm_" + ProcessHandle.current().pid(); + try (Arena arena = Arena.ofConfined()) { + int fd = (int) shmOpen.invokeExact(arena.allocateUtf8String(name), 02 | 0100, 0600); // O_RDWR | O_CREAT + if (fd < 0) throw new IllegalStateException("shm_open failed"); + if ((int) ftruncate.invokeExact(fd, nbytes) != 0) throw new IllegalStateException("ftruncate failed"); + MemorySegment base = (MemorySegment) mmap.invokeExact(MemorySegment.NULL, nbytes, 3, 1, fd, 0L); // PROT_RW, MAP_SHARED + MemorySegment block = base.reinterpret(nbytes); + Random r = new Random(1); + int max = 0; long sum = 0; int first = -1; + long t0 = System.nanoTime(); + ValueLayout.OfShort le = ValueLayout.JAVA_SHORT.withOrder(ByteOrder.nativeOrder()); + for (long i = 0; i < (long) side * side; i++) { + int v = r.nextInt(65536); + max = Math.max(max, v); sum += v; if (first < 0) first = v; + block.setAtIndex(le, i, (short) v); + } + double fill = (System.nanoTime() - t0) / 1e9; + System.out.println("{\"mode\":\"ffm\",\"name\":\"" + name.substring(1) + "\",\"shape\":[" + side + "," + side + + "],\"dtype\":\"uint16\",\"max\":" + max + ",\"sum\":" + sum + ",\"first\":" + first + ",\"fill_s\":" + fill + "}"); + System.out.flush(); + System.in.read(); + int rc = (int) shmUnlink.invokeExact(arena.allocateUtf8String(name)); + } + } +} diff --git a/benchmarks/java_shm_proof.py b/benchmarks/java_shm_proof.py new file mode 100644 index 0000000..1abb8d7 --- /dev/null +++ b/benchmarks/java_shm_proof.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python3 +"""Run a Java process that creates a shared block with a short[] image, then let the REAL LabConstrictor worker read it. + + python benchmarks/java_shm_proof.py --mode appose --classpath DIR_WITH_COMPILED_CLASSES:jna.jar:jna-platform.jar + python benchmarks/java_shm_proof.py --mode mmap --classpath DIR + python benchmarks/java_shm_proof.py --mode ffm --classpath DIR (ShmProofFfm, Java 21 --enable-preview) + +Passes when the worker's `image_checksum` equals the sum and first pixel Java computed: the pixels, their byte order and their unsigned values +survived Java heap -> block -> worker copy. Exit code 0 = pass. +""" + +import argparse +import json +import subprocess +import sys +import tempfile +from pathlib import Path + +HERE = Path(__file__).resolve().parent +sys.path.insert(0, str(HERE.parent)) +from labconstrictor_tools.client import WorkerProcess + + +def main() -> int: + ap = argparse.ArgumentParser() + ap.add_argument("--mode", choices=["appose", "mmap", "ffm"], required=True) + ap.add_argument("--classpath", required=True) + ap.add_argument("--side", type=int, default=4096) + args = ap.parse_args() + cmd = ["java", "-Dside=%d" % args.side, "-Xmx3g"] + main_class = "ShmProof" + if args.mode == "ffm": + cmd += ["--enable-preview"] + main_class = "ShmProofFfm" + cmd += ["-cp", args.classpath, main_class] + ([args.mode] if args.mode != "ffm" else []) + java = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, text=True) + try: + line = java.stdout.readline() + info = json.loads(line) + descriptor = { + "appose_type": "ndarray", + "shm": {"name": info["name"]}, + "shape": info["shape"], + "dtype": info["dtype"], + } + with WorkerProcess(module="shm_bench_app", pythonpath=[str(HERE)]) as worker: + task = worker.task("image_checksum", {"image": descriptor, "_job_dir": tempfile.mkdtemp()}).wait( + 60 + ) + values = next(r["values"] for r in task.outputs["results"] if r["type"] == "values") + ok = ( + values["sum"] == info["sum"] + and values["first"] == info["first"] + and values["shape"] == info["shape"] + ) + print( + "%s: java sum %d first %d, worker sum %d first %d, java fill %.3f s -> %s" + % ( + info["mode"], + info["sum"], + info["first"], + values["sum"], + values["first"], + info["fill_s"], + "PASS" if ok else "FAIL", + ) + ) + return 0 if ok else 1 + finally: + java.stdin.write("done\n") + java.stdin.close() + java.wait(10) + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/benchmarks/results/sandbox_1024_invert_disk_then_oom.txt b/benchmarks/results/sandbox_1024_invert_disk_then_oom.txt new file mode 100644 index 0000000..eb7cdac --- /dev/null +++ b/benchmarks/results/sandbox_1024_invert_disk_then_oom.txt @@ -0,0 +1,6 @@ +== 1024 MiB ((23170, 23170), uint16) + invert disk run1 export 2.75 task 11.58 (load 5.74 tool 5.33 write 0.50 other 0.008) back 0.00 total 15.29 worker faults 2888 rss 2079 MiB psi 31ms scan 0 + invert disk run2 export 1.20 task 4.63 (load 1.41 tool 2.76 write 0.45 other 0.010) back 0.00 total 6.46 worker faults 2028 rss 2079 MiB psi 8ms scan 0 + invert disk run3 export 0.53 task 2.79 (load 0.39 tool 1.89 write 0.51 other 0.008) back 0.00 total 3.94 worker faults 2027 rss 2079 MiB psi 47ms scan 71 +/usr/lib/python3.11/multiprocessing/resource_tracker.py:254: UserWarning: resource_tracker: There appear to be 1 leaked shared_memory objects to clean up at shutdown + warnings.warn('resource_tracker: There appear to be %d ' diff --git a/benchmarks/results/sandbox_breakdown_512_asis.json b/benchmarks/results/sandbox_breakdown_512_asis.json new file mode 100644 index 0000000..eef864e --- /dev/null +++ b/benchmarks/results/sandbox_breakdown_512_asis.json @@ -0,0 +1,310 @@ +{ + "mb": 512, + "runs": [ + { + "attach": { + "wall_s": 0.00014087700037634932, + "user_s": 4.4999999999850715e-05, + "sys_s": 0.00010799999999999699, + "faults": 0 + }, + "copy": { + "wall_s": 2.91714850399876, + "user_s": 0.050715000000000066, + "sys_s": 2.6679890000000004, + "faults": 8960 + }, + "copy_warm": { + "wall_s": 0.06701599999905739, + "user_s": 0.06601799999999991, + "sys_s": 0.0, + "faults": 0 + }, + "tool": { + "wall_s": 2.7085988569997426, + "user_s": 0.07954499999999998, + "sys_s": 2.5578000000000003, + "faults": 768 + }, + "tiff_disk": { + "wall_s": 3.185967969000558, + "user_s": 0.0, + "sys_s": 2.957759000000001, + "faults": 0 + }, + "tiff_fsync": { + "wall_s": 0.5468352469997626, + "user_s": 0.0, + "sys_s": 0.013265999999999778, + "faults": 0 + }, + "tiff_tmpfs": { + "wall_s": 0.2971160500001133, + "user_s": 0.0, + "sys_s": 0.22569000000000017, + "faults": 0 + }, + "tiff_read": { + "wall_s": 2.961236008999549, + "user_s": 0.0, + "sys_s": 2.7825550000000003, + "faults": 771 + }, + "peak_rss_mib": 3109 + }, + { + "attach": { + "wall_s": 0.00014170199938234873, + "user_s": 1.9999999999686935e-05, + "sys_s": 0.00013400000000096668, + "faults": 0 + }, + "copy": { + "wall_s": 0.23661263699978008, + "user_s": 0.06802600000000014, + "sys_s": 0.14130800000000043, + "faults": 8960 + }, + "copy_warm": { + "wall_s": 0.06992763800008106, + "user_s": 0.06451999999999991, + "sys_s": 0.0, + "faults": 0 + }, + "tool": { + "wall_s": 0.266844191999553, + "user_s": 0.09464999999999968, + "sys_s": 0.1507959999999997, + "faults": 768 + }, + "tiff_disk": { + "wall_s": 0.21690112400028738, + "user_s": 0.0028920000000001167, + "sys_s": 0.1332810000000002, + "faults": 0 + }, + "tiff_fsync": { + "wall_s": 0.4388216179995652, + "user_s": 0.0004620000000001845, + "sys_s": 0.015696000000000154, + "faults": 0 + }, + "tiff_tmpfs": { + "wall_s": 0.2173496890009119, + "user_s": 0.0, + "sys_s": 0.20431199999999983, + "faults": 0 + }, + "tiff_read": { + "wall_s": 2.888957716000732, + "user_s": 0.0, + "sys_s": 2.673446, + "faults": 769 + }, + "peak_rss_mib": 3109 + }, + { + "attach": { + "wall_s": 0.0001400460005243076, + "user_s": 2.199999999996649e-05, + "sys_s": 0.0001299999999986312, + "faults": 0 + }, + "copy": { + "wall_s": 0.21593217400004505, + "user_s": 0.09304299999999976, + "sys_s": 0.1036999999999999, + "faults": 8960 + }, + "copy_warm": { + "wall_s": 0.10072628899979463, + "user_s": 0.0639829999999999, + "sys_s": 0.001426999999999623, + "faults": 0 + }, + "tool": { + "wall_s": 0.17394880800020474, + "user_s": 0.07175999999999982, + "sys_s": 0.08175700000000319, + "faults": 768 + }, + "tiff_disk": { + "wall_s": 1.521196202000283, + "user_s": 0.0024159999999997517, + "sys_s": 1.3836310000000012, + "faults": 2 + }, + "tiff_fsync": { + "wall_s": 0.4227487549997022, + "user_s": 0.00020200000000025753, + "sys_s": 0.013116000000000128, + "faults": 0 + }, + "tiff_tmpfs": { + "wall_s": 0.2160497269996995, + "user_s": 0.0, + "sys_s": 0.20123599999999797, + "faults": 0 + }, + "tiff_read": { + "wall_s": 2.2664202109990583, + "user_s": 0.0037959999999999106, + "sys_s": 2.2070449999999973, + "faults": 768 + }, + "peak_rss_mib": 3109 + }, + { + "attach": { + "wall_s": 0.00013627900079882238, + "user_s": 2.19999999995224e-05, + "sys_s": 0.0001259999999980721, + "faults": 0 + }, + "copy": { + "wall_s": 0.180951009000637, + "user_s": 0.058260999999999896, + "sys_s": 0.12136600000000186, + "faults": 8960 + }, + "copy_warm": { + "wall_s": 0.06311430800087692, + "user_s": 0.06044200000000011, + "sys_s": 0.00268000000000157, + "faults": 0 + }, + "tool": { + "wall_s": 0.8099346409999271, + "user_s": 0.06371900000000075, + "sys_s": 0.7433259999999997, + "faults": 768 + }, + "tiff_disk": { + "wall_s": 0.14990987700002734, + "user_s": 0.000204000000000093, + "sys_s": 0.13643000000000072, + "faults": 0 + }, + "tiff_fsync": { + "wall_s": 0.43152419599937275, + "user_s": 0.0, + "sys_s": 0.014797000000001503, + "faults": 0 + }, + "tiff_tmpfs": { + "wall_s": 0.20323713600009796, + "user_s": 0.0, + "sys_s": 0.19636300000000162, + "faults": 1 + }, + "tiff_read": { + "wall_s": 2.2069326889995864, + "user_s": 0.0, + "sys_s": 2.1835929999999983, + "faults": 768 + }, + "peak_rss_mib": 3109 + }, + { + "attach": { + "wall_s": 0.00013812399993184954, + "user_s": 2.3999999999801958e-05, + "sys_s": 0.00012699999999910005, + "faults": 0 + }, + "copy": { + "wall_s": 0.19472586900155875, + "user_s": 0.11167000000000016, + "sys_s": 0.07747800000000282, + "faults": 8960 + }, + "copy_warm": { + "wall_s": 0.06801667299987457, + "user_s": 0.06351699999999916, + "sys_s": 5.499999999969418e-05, + "faults": 0 + }, + "tool": { + "wall_s": 0.1747493860002578, + "user_s": 0.07578899999999944, + "sys_s": 0.09721100000000149, + "faults": 768 + }, + "tiff_disk": { + "wall_s": 0.24652882200098247, + "user_s": 0.0, + "sys_s": 0.14214799999999883, + "faults": 0 + }, + "tiff_fsync": { + "wall_s": 0.4369230040010734, + "user_s": 0.0, + "sys_s": 0.014312000000000324, + "faults": 0 + }, + "tiff_tmpfs": { + "wall_s": 0.23125115999937407, + "user_s": 0.0, + "sys_s": 0.20580400000000054, + "faults": 0 + }, + "tiff_read": { + "wall_s": 2.2150409200003196, + "user_s": 0.0, + "sys_s": 2.076131, + "faults": 769 + }, + "peak_rss_mib": 3109 + } + ], + "median": { + "attach": { + "wall_s": 0.0001400460005243076, + "user_s": 2.199999999996649e-05, + "sys_s": 0.00012699999999910005, + "faults": 0 + }, + "copy": { + "wall_s": 0.21593217400004505, + "user_s": 0.06802600000000014, + "sys_s": 0.12136600000000186, + "faults": 8960 + }, + "copy_warm": { + "wall_s": 0.06801667299987457, + "user_s": 0.0639829999999999, + "sys_s": 5.499999999969418e-05, + "faults": 0 + }, + "tool": { + "wall_s": 0.266844191999553, + "user_s": 0.07578899999999944, + "sys_s": 0.1507959999999997, + "faults": 768 + }, + "tiff_disk": { + "wall_s": 0.24652882200098247, + "user_s": 0.000204000000000093, + "sys_s": 0.14214799999999883, + "faults": 0 + }, + "tiff_fsync": { + "wall_s": 0.4369230040010734, + "user_s": 0.0, + "sys_s": 0.014312000000000324, + "faults": 0 + }, + "tiff_tmpfs": { + "wall_s": 0.2173496890009119, + "user_s": 0.0, + "sys_s": 0.20431199999999983, + "faults": 0 + }, + "tiff_read": { + "wall_s": 2.2664202109990583, + "user_s": 0.0, + "sys_s": 2.2070449999999973, + "faults": 769 + } + } +} \ No newline at end of file diff --git a/benchmarks/results/sandbox_breakdown_512_prewarm.json b/benchmarks/results/sandbox_breakdown_512_prewarm.json new file mode 100644 index 0000000..e310a4a --- /dev/null +++ b/benchmarks/results/sandbox_breakdown_512_prewarm.json @@ -0,0 +1,310 @@ +{ + "mb": 512, + "runs": [ + { + "attach": { + "wall_s": 0.00014723599997523706, + "user_s": 0.00011200000000011201, + "sys_s": 4.999999999999449e-05, + "faults": 0 + }, + "copy": { + "wall_s": 0.2216907940000965, + "user_s": 0.06187000000000009, + "sys_s": 0.15424399999999994, + "faults": 8960 + }, + "copy_warm": { + "wall_s": 0.07097081000028993, + "user_s": 0.064187, + "sys_s": 0.0, + "faults": 0 + }, + "tool": { + "wall_s": 0.13967800099999295, + "user_s": 0.07584900000000006, + "sys_s": 0.06315000000000004, + "faults": 769 + }, + "tiff_disk": { + "wall_s": 0.14297185999930662, + "user_s": 0.0, + "sys_s": 0.12540900000000033, + "faults": 0 + }, + "tiff_fsync": { + "wall_s": 0.42230047399971227, + "user_s": 0.0, + "sys_s": 0.02641699999999947, + "faults": 0 + }, + "tiff_tmpfs": { + "wall_s": 0.2195018930015067, + "user_s": 0.0, + "sys_s": 0.20281700000000047, + "faults": 0 + }, + "tiff_read": { + "wall_s": 0.1777987599998596, + "user_s": 0.000460000000000127, + "sys_s": 0.16094000000000008, + "faults": 771 + }, + "peak_rss_mib": 3109 + }, + { + "attach": { + "wall_s": 0.00013991199921292718, + "user_s": 3.999999999981796e-05, + "sys_s": 0.0001129999999998077, + "faults": 0 + }, + "copy": { + "wall_s": 0.18708537699967565, + "user_s": 0.06640399999999991, + "sys_s": 0.1145480000000001, + "faults": 8960 + }, + "copy_warm": { + "wall_s": 0.06678115000067919, + "user_s": 0.06521799999999978, + "sys_s": 0.0, + "faults": 0 + }, + "tool": { + "wall_s": 0.14889235299961, + "user_s": 0.07103799999999971, + "sys_s": 0.07224900000000023, + "faults": 768 + }, + "tiff_disk": { + "wall_s": 0.123875395000141, + "user_s": 0.0, + "sys_s": 0.12254700000000085, + "faults": 0 + }, + "tiff_fsync": { + "wall_s": 0.4178127070008486, + "user_s": 0.00031200000000009, + "sys_s": 0.013192999999999344, + "faults": 0 + }, + "tiff_tmpfs": { + "wall_s": 0.20176250899930892, + "user_s": 0.0, + "sys_s": 0.19738700000000087, + "faults": 0 + }, + "tiff_read": { + "wall_s": 0.1525951370003895, + "user_s": 0.00011200000000011201, + "sys_s": 0.1525029999999994, + "faults": 769 + }, + "peak_rss_mib": 3109 + }, + { + "attach": { + "wall_s": 0.000162472999363672, + "user_s": 4.2999999999793204e-05, + "sys_s": 0.00013500000000021828, + "faults": 0 + }, + "copy": { + "wall_s": 0.18529519100047764, + "user_s": 0.09493499999999999, + "sys_s": 0.08505199999999924, + "faults": 8960 + }, + "copy_warm": { + "wall_s": 0.07999492400085728, + "user_s": 0.06617099999999976, + "sys_s": 2.000000000279556e-06, + "faults": 0 + }, + "tool": { + "wall_s": 0.1581498380000994, + "user_s": 0.07954700000000026, + "sys_s": 0.0775409999999983, + "faults": 768 + }, + "tiff_disk": { + "wall_s": 0.13191628200002015, + "user_s": 0.0004679999999996909, + "sys_s": 0.12380500000000083, + "faults": 2 + }, + "tiff_fsync": { + "wall_s": 0.4421744539995416, + "user_s": 0.0006180000000002295, + "sys_s": 0.014184999999997672, + "faults": 0 + }, + "tiff_tmpfs": { + "wall_s": 0.2808901460011839, + "user_s": 0.0002849999999998687, + "sys_s": 0.23946300000000065, + "faults": 0 + }, + "tiff_read": { + "wall_s": 0.17320462499992573, + "user_s": 0.003473999999999755, + "sys_s": 0.16563400000000073, + "faults": 768 + }, + "peak_rss_mib": 3109 + }, + { + "attach": { + "wall_s": 0.0001818450000428129, + "user_s": 4.2000000000541604e-05, + "sys_s": 0.000158000000002545, + "faults": 0 + }, + "copy": { + "wall_s": 0.20269269999880635, + "user_s": 0.10080000000000044, + "sys_s": 0.09261700000000062, + "faults": 8960 + }, + "copy_warm": { + "wall_s": 0.06673322200003895, + "user_s": 0.06677300000000042, + "sys_s": 0.0, + "faults": 0 + }, + "tool": { + "wall_s": 0.1412367639986769, + "user_s": 0.056272000000000766, + "sys_s": 0.08498300000000114, + "faults": 768 + }, + "tiff_disk": { + "wall_s": 0.14601967499947932, + "user_s": 0.0, + "sys_s": 0.12925699999999907, + "faults": 0 + }, + "tiff_fsync": { + "wall_s": 0.4381002089994581, + "user_s": 0.0003709999999994551, + "sys_s": 0.02410199999999918, + "faults": 0 + }, + "tiff_tmpfs": { + "wall_s": 0.2161665340008767, + "user_s": 0.0, + "sys_s": 0.20273800000000008, + "faults": 0 + }, + "tiff_read": { + "wall_s": 0.19158362699999998, + "user_s": 0.0012259999999999494, + "sys_s": 0.1699850000000005, + "faults": 769 + }, + "peak_rss_mib": 3109 + }, + { + "attach": { + "wall_s": 0.0001902799995150417, + "user_s": 3.799999999998249e-05, + "sys_s": 0.00016800000000216642, + "faults": 0 + }, + "copy": { + "wall_s": 0.2284115530001145, + "user_s": 0.07991599999999988, + "sys_s": 0.11433200000000099, + "faults": 8960 + }, + "copy_warm": { + "wall_s": 0.06561814599990612, + "user_s": 0.06408699999999978, + "sys_s": 0.0012369999999997106, + "faults": 0 + }, + "tool": { + "wall_s": 0.27296080499945674, + "user_s": 0.11709600000000009, + "sys_s": 0.13274000000000186, + "faults": 768 + }, + "tiff_disk": { + "wall_s": 0.14021257599961245, + "user_s": 0.000484000000000151, + "sys_s": 0.13171000000000177, + "faults": 0 + }, + "tiff_fsync": { + "wall_s": 0.4623810230004892, + "user_s": 0.00044799999999955986, + "sys_s": 0.022368000000000166, + "faults": 0 + }, + "tiff_tmpfs": { + "wall_s": 0.2090801439990173, + "user_s": 0.0032719999999999416, + "sys_s": 0.19970099999999746, + "faults": 0 + }, + "tiff_read": { + "wall_s": 0.17821842699959234, + "user_s": 0.003547000000000189, + "sys_s": 0.168334999999999, + "faults": 769 + }, + "peak_rss_mib": 3109 + } + ], + "median": { + "attach": { + "wall_s": 0.000162472999363672, + "user_s": 4.2000000000541604e-05, + "sys_s": 0.00013500000000021828, + "faults": 0 + }, + "copy": { + "wall_s": 0.20269269999880635, + "user_s": 0.07991599999999988, + "sys_s": 0.11433200000000099, + "faults": 8960 + }, + "copy_warm": { + "wall_s": 0.06678115000067919, + "user_s": 0.06521799999999978, + "sys_s": 0.0, + "faults": 0 + }, + "tool": { + "wall_s": 0.14889235299961, + "user_s": 0.07584900000000006, + "sys_s": 0.0775409999999983, + "faults": 768 + }, + "tiff_disk": { + "wall_s": 0.14021257599961245, + "user_s": 0.0, + "sys_s": 0.12540900000000033, + "faults": 0 + }, + "tiff_fsync": { + "wall_s": 0.4381002089994581, + "user_s": 0.0003709999999994551, + "sys_s": 0.022368000000000166, + "faults": 0 + }, + "tiff_tmpfs": { + "wall_s": 0.2161665340008767, + "user_s": 0.0, + "sys_s": 0.20273800000000008, + "faults": 0 + }, + "tiff_read": { + "wall_s": 0.1777987599998596, + "user_s": 0.0012259999999999494, + "sys_s": 0.16563400000000073, + "faults": 769 + } + } +} \ No newline at end of file diff --git a/benchmarks/results/sandbox_cold_cache_512.json b/benchmarks/results/sandbox_cold_cache_512.json new file mode 100644 index 0000000..3a153dc --- /dev/null +++ b/benchmarks/results/sandbox_cold_cache_512.json @@ -0,0 +1,372 @@ +{ + "env": { + "python": "3.11.15", + "numpy": "2.4.6", + "tifffile": "2026.3.3", + "cpus": 4, + "scratch": "/home/user/tmp_shm/tmp/lc-shm-bench-c7o6twzs", + "out_scratch": "/home/user/tmp_shm/tmp/lc-shm-bench-c7o6twzs", + "cold": true, + "prewarm": 2 + }, + "runs": { + "512": { + "image_max": { + "disk": { + "rows": [ + { + "path": "disk", + "tool": "image_max", + "export_s": 0.1259620860000723, + "export_fsync_s": 0.4398597299996254, + "host_export_faults": 1, + "cache_dropped": true, + "task_wall_s": 0.3911331720000817, + "load_s": 0.3448, + "tool_s": 0.0412, + "write_s": 0.0001, + "transport_s": 0.00503317200008169, + "worker_faults": 1119, + "worker_maxrss_mib": 543, + "cleanup_s": 0.462937867000619, + "k_nr_written": 131336, + "k_pgpgout": 525352, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.980033125000773 + }, + { + "path": "disk", + "tool": "image_max", + "export_s": 0.12441098500039516, + "export_fsync_s": 0.42385963599917886, + "host_export_faults": 0, + "cache_dropped": true, + "task_wall_s": 0.39537296399976185, + "load_s": 0.3501, + "tool_s": 0.0405, + "write_s": 0.0001, + "transport_s": 0.004672963999761827, + "worker_faults": 259, + "worker_maxrss_mib": 543, + "cleanup_s": 0.4420924879996164, + "k_nr_written": 131165, + "k_pgpgout": 524656, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.9618764369997734 + }, + { + "path": "disk", + "tool": "image_max", + "export_s": 0.12492417900011787, + "export_fsync_s": 0.43195746800029156, + "host_export_faults": 0, + "cache_dropped": true, + "task_wall_s": 0.22900631099946622, + "load_s": 0.189, + "tool_s": 0.0351, + "write_s": 0.0001, + "transport_s": 0.004806310999466222, + "worker_faults": 257, + "worker_maxrss_mib": 543, + "cleanup_s": 0.23057509800037224, + "k_nr_written": 131122, + "k_pgpgout": 524488, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.5845055879999563 + } + ], + "summary": { + "cleanup_s": { + "median": 0.4420924879996164, + "min": 0.23057509800037224, + "max": 0.462937867000619 + }, + "export_fsync_s": { + "median": 0.43195746800029156, + "min": 0.42385963599917886, + "max": 0.4398597299996254 + }, + "export_s": { + "median": 0.12492417900011787, + "min": 0.12441098500039516, + "max": 0.1259620860000723 + }, + "host_export_faults": { + "median": 0, + "min": 0, + "max": 1 + }, + "k_allocstall_normal": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_nr_written": { + "median": 131165, + "min": 131122, + "max": 131336 + }, + "k_pgpgout": { + "median": 524656, + "min": 524488, + "max": 525352 + }, + "k_pgscan_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgscan_kswapd": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgsteal_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_psi_some_us": { + "median": 0, + "min": 0, + "max": 0 + }, + "load_s": { + "median": 0.3448, + "min": 0.189, + "max": 0.3501 + }, + "task_wall_s": { + "median": 0.3911331720000817, + "min": 0.22900631099946622, + "max": 0.39537296399976185 + }, + "tool_s": { + "median": 0.0405, + "min": 0.0351, + "max": 0.0412 + }, + "total_s": { + "median": 0.9618764369997734, + "min": 0.5845055879999563, + "max": 0.980033125000773 + }, + "transport_s": { + "median": 0.004806310999466222, + "min": 0.004672963999761827, + "max": 0.00503317200008169 + }, + "worker_faults": { + "median": 259, + "min": 257, + "max": 1119 + }, + "worker_maxrss_mib": { + "median": 543, + "min": 543, + "max": 543 + }, + "write_s": { + "median": 0.0001, + "min": 0.0001, + "max": 0.0001 + } + } + }, + "shm": { + "rows": [ + { + "path": "shm", + "tool": "image_max", + "shm_create_s": 0.0015036069999041501, + "shm_fill_s": 0.49549050299992814, + "export_s": 0.4969941099998323, + "host_export_faults": 131072, + "cache_dropped": true, + "task_wall_s": 0.29131116999997175, + "load_s": 0.2464, + "tool_s": 0.0406, + "write_s": 0.0001, + "transport_s": 0.004211169999971748, + "worker_faults": 8733, + "worker_maxrss_mib": 1059, + "cleanup_s": 0.12341439600004378, + "k_nr_written": 32, + "k_pgpgout": 128, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.9117196759998478 + }, + { + "path": "shm", + "tool": "image_max", + "shm_create_s": 0.0001614399998288718, + "shm_fill_s": 0.4306393429997115, + "export_s": 0.4308007829995404, + "host_export_faults": 131072, + "cache_dropped": true, + "task_wall_s": 0.27671123899926897, + "load_s": 0.2382, + "tool_s": 0.0341, + "write_s": 0.0001, + "transport_s": 0.004311238999268978, + "worker_faults": 8450, + "worker_maxrss_mib": 1059, + "cleanup_s": 0.07626294799956668, + "k_nr_written": 93, + "k_pgpgout": 372, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.783774969998376 + }, + { + "path": "shm", + "tool": "image_max", + "shm_create_s": 0.00014726399967912585, + "shm_fill_s": 0.5035837850000462, + "export_s": 0.5037310489997253, + "host_export_faults": 131072, + "cache_dropped": true, + "task_wall_s": 0.27886596899952565, + "load_s": 0.2341, + "tool_s": 0.0404, + "write_s": 0.0001, + "transport_s": 0.004265968999525647, + "worker_faults": 8450, + "worker_maxrss_mib": 1059, + "cleanup_s": 0.11414879499989183, + "k_nr_written": 83, + "k_pgpgout": 340, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.8967458129991428 + } + ], + "summary": { + "cleanup_s": { + "median": 0.11414879499989183, + "min": 0.07626294799956668, + "max": 0.12341439600004378 + }, + "export_s": { + "median": 0.4969941099998323, + "min": 0.4308007829995404, + "max": 0.5037310489997253 + }, + "host_export_faults": { + "median": 131072, + "min": 131072, + "max": 131072 + }, + "k_allocstall_normal": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_nr_written": { + "median": 83, + "min": 32, + "max": 93 + }, + "k_pgpgout": { + "median": 340, + "min": 128, + "max": 372 + }, + "k_pgscan_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgscan_kswapd": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgsteal_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_psi_some_us": { + "median": 0, + "min": 0, + "max": 0 + }, + "load_s": { + "median": 0.2382, + "min": 0.2341, + "max": 0.2464 + }, + "shm_create_s": { + "median": 0.0001614399998288718, + "min": 0.00014726399967912585, + "max": 0.0015036069999041501 + }, + "shm_fill_s": { + "median": 0.49549050299992814, + "min": 0.4306393429997115, + "max": 0.5035837850000462 + }, + "task_wall_s": { + "median": 0.27886596899952565, + "min": 0.27671123899926897, + "max": 0.29131116999997175 + }, + "tool_s": { + "median": 0.0404, + "min": 0.0341, + "max": 0.0406 + }, + "total_s": { + "median": 0.8967458129991428, + "min": 0.783774969998376, + "max": 0.9117196759998478 + }, + "transport_s": { + "median": 0.004265968999525647, + "min": 0.004211169999971748, + "max": 0.004311238999268978 + }, + "worker_faults": { + "median": 8450, + "min": 8450, + "max": 8733 + }, + "worker_maxrss_mib": { + "median": 1059, + "min": 1059, + "max": 1059 + }, + "write_s": { + "median": 0.0001, + "min": 0.0001, + "max": 0.0001 + } + } + } + } + } + } +} \ No newline at end of file diff --git a/benchmarks/results/sandbox_default_1024_image_max.json b/benchmarks/results/sandbox_default_1024_image_max.json new file mode 100644 index 0000000..c0e5b6a --- /dev/null +++ b/benchmarks/results/sandbox_default_1024_image_max.json @@ -0,0 +1,366 @@ +{ + "env": { + "python": "3.11.15", + "numpy": "2.4.6", + "tifffile": "2026.3.3", + "cpus": 4, + "scratch": "/home/user/tmp_shm/tmp/lc-shm-bench-aunwfg2k", + "out_scratch": "/home/user/tmp_shm/tmp/lc-shm-bench-aunwfg2k", + "cold": false, + "prewarm": 0 + }, + "runs": { + "1024": { + "image_max": { + "disk": { + "rows": [ + { + "path": "disk", + "tool": "image_max", + "export_s": 6.731915731999834, + "export_fsync_s": 0.7320060869997178, + "host_export_faults": 1, + "task_wall_s": 8.070568005000496, + "load_s": 7.9879, + "tool_s": 0.0775, + "write_s": 0.0001, + "transport_s": 0.005068005000495981, + "worker_faults": 1877, + "worker_maxrss_mib": 1055, + "cleanup_s": 0.5293831440003487, + "k_nr_written": 263994, + "k_pgpgout": 1055940, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 15.331866881000678 + }, + { + "path": "disk", + "tool": "image_max", + "export_s": 0.4128023250004844, + "export_fsync_s": 0.6766263189992969, + "host_export_faults": 0, + "task_wall_s": 0.4790630110001075, + "load_s": 0.3965, + "tool_s": 0.0779, + "write_s": 0.0001, + "transport_s": 0.004563011000107492, + "worker_faults": 1015, + "worker_maxrss_mib": 1055, + "cleanup_s": 0.8475175759995182, + "k_nr_written": 262381, + "k_pgpgout": 1049528, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 1.73938291200011 + }, + { + "path": "disk", + "tool": "image_max", + "export_s": 0.6044557210007042, + "export_fsync_s": 0.7429221270003836, + "host_export_faults": 0, + "task_wall_s": 1.991664500999832, + "load_s": 1.8974, + "tool_s": 0.0892, + "write_s": 0.0001, + "transport_s": 0.0049645009998319665, + "worker_faults": 1013, + "worker_maxrss_mib": 1055, + "cleanup_s": 0.9372501329999068, + "k_nr_written": 262660, + "k_pgpgout": 1050644, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 3.533370355000443 + } + ], + "summary": { + "cleanup_s": { + "median": 0.8475175759995182, + "min": 0.5293831440003487, + "max": 0.9372501329999068 + }, + "export_fsync_s": { + "median": 0.7320060869997178, + "min": 0.6766263189992969, + "max": 0.7429221270003836 + }, + "export_s": { + "median": 0.6044557210007042, + "min": 0.4128023250004844, + "max": 6.731915731999834 + }, + "host_export_faults": { + "median": 0, + "min": 0, + "max": 1 + }, + "k_allocstall_normal": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_nr_written": { + "median": 262660, + "min": 262381, + "max": 263994 + }, + "k_pgpgout": { + "median": 1050644, + "min": 1049528, + "max": 1055940 + }, + "k_pgscan_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgscan_kswapd": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgsteal_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_psi_some_us": { + "median": 0, + "min": 0, + "max": 0 + }, + "load_s": { + "median": 1.8974, + "min": 0.3965, + "max": 7.9879 + }, + "task_wall_s": { + "median": 1.991664500999832, + "min": 0.4790630110001075, + "max": 8.070568005000496 + }, + "tool_s": { + "median": 0.0779, + "min": 0.0775, + "max": 0.0892 + }, + "total_s": { + "median": 3.533370355000443, + "min": 1.73938291200011, + "max": 15.331866881000678 + }, + "transport_s": { + "median": 0.0049645009998319665, + "min": 0.004563011000107492, + "max": 0.005068005000495981 + }, + "worker_faults": { + "median": 1015, + "min": 1013, + "max": 1877 + }, + "worker_maxrss_mib": { + "median": 1055, + "min": 1055, + "max": 1055 + }, + "write_s": { + "median": 0.0001, + "min": 0.0001, + "max": 0.0001 + } + } + }, + "shm": { + "rows": [ + { + "path": "shm", + "tool": "image_max", + "shm_create_s": 0.0008246580000559334, + "shm_fill_s": 0.9490234960003363, + "export_s": 0.9498481540003922, + "host_export_faults": 262134, + "task_wall_s": 1.8855195240003013, + "load_s": 1.8062, + "tool_s": 0.0742, + "write_s": 0.0001, + "transport_s": 0.005019524000301287, + "worker_faults": 17689, + "worker_maxrss_mib": 2083, + "cleanup_s": 0.174273532999905, + "k_nr_written": 0, + "k_pgpgout": 0, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 3.0096412110005986 + }, + { + "path": "shm", + "tool": "image_max", + "shm_create_s": 0.00013807600043946877, + "shm_fill_s": 0.9305419550000806, + "export_s": 0.9306800310005201, + "host_export_faults": 262134, + "task_wall_s": 1.6150101310004175, + "load_s": 1.538, + "tool_s": 0.0723, + "write_s": 0.0001, + "transport_s": 0.004610131000417422, + "worker_faults": 17398, + "worker_maxrss_mib": 2083, + "cleanup_s": 0.1489186239996343, + "k_nr_written": 0, + "k_pgpgout": 0, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 2.694608786000572 + }, + { + "path": "shm", + "tool": "image_max", + "shm_create_s": 0.0003141899996990105, + "shm_fill_s": 0.9177656140000181, + "export_s": 0.9180798039997171, + "host_export_faults": 262134, + "task_wall_s": 1.8734643940006208, + "load_s": 1.7849, + "tool_s": 0.0834, + "write_s": 0.0001, + "transport_s": 0.005064394000620881, + "worker_faults": 17398, + "worker_maxrss_mib": 2083, + "cleanup_s": 0.23001271900011488, + "k_nr_written": 343, + "k_pgpgout": 1372, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 3.021556917000453 + } + ], + "summary": { + "cleanup_s": { + "median": 0.174273532999905, + "min": 0.1489186239996343, + "max": 0.23001271900011488 + }, + "export_s": { + "median": 0.9306800310005201, + "min": 0.9180798039997171, + "max": 0.9498481540003922 + }, + "host_export_faults": { + "median": 262134, + "min": 262134, + "max": 262134 + }, + "k_allocstall_normal": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_nr_written": { + "median": 0, + "min": 0, + "max": 343 + }, + "k_pgpgout": { + "median": 0, + "min": 0, + "max": 1372 + }, + "k_pgscan_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgscan_kswapd": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgsteal_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_psi_some_us": { + "median": 0, + "min": 0, + "max": 0 + }, + "load_s": { + "median": 1.7849, + "min": 1.538, + "max": 1.8062 + }, + "shm_create_s": { + "median": 0.0003141899996990105, + "min": 0.00013807600043946877, + "max": 0.0008246580000559334 + }, + "shm_fill_s": { + "median": 0.9305419550000806, + "min": 0.9177656140000181, + "max": 0.9490234960003363 + }, + "task_wall_s": { + "median": 1.8734643940006208, + "min": 1.6150101310004175, + "max": 1.8855195240003013 + }, + "tool_s": { + "median": 0.0742, + "min": 0.0723, + "max": 0.0834 + }, + "total_s": { + "median": 3.0096412110005986, + "min": 2.694608786000572, + "max": 3.021556917000453 + }, + "transport_s": { + "median": 0.005019524000301287, + "min": 0.004610131000417422, + "max": 0.005064394000620881 + }, + "worker_faults": { + "median": 17398, + "min": 17398, + "max": 17689 + }, + "worker_maxrss_mib": { + "median": 2083, + "min": 2083, + "max": 2083 + }, + "write_s": { + "median": 0.0001, + "min": 0.0001, + "max": 0.0001 + } + } + } + } + } + } +} \ No newline at end of file diff --git a/benchmarks/results/sandbox_default_1024_passthrough.json b/benchmarks/results/sandbox_default_1024_passthrough.json new file mode 100644 index 0000000..1530ad3 --- /dev/null +++ b/benchmarks/results/sandbox_default_1024_passthrough.json @@ -0,0 +1,366 @@ +{ + "env": { + "python": "3.11.15", + "numpy": "2.4.6", + "tifffile": "2026.3.3", + "cpus": 4, + "scratch": "/home/user/tmp_shm/tmp/lc-shm-bench-zzxqjyrx", + "out_scratch": "/dev/shm/lcbench_out/lc-shm-out-vtw2bo61", + "cold": false, + "prewarm": 0 + }, + "runs": { + "1024": { + "passthrough": { + "disk": { + "rows": [ + { + "path": "disk", + "tool": "passthrough", + "export_s": 5.746448795000106, + "export_fsync_s": 0.6569792410000446, + "host_export_faults": 1, + "task_wall_s": 6.3634891589999825, + "load_s": 5.8196, + "tool_s": 0.0, + "write_s": 0.5335, + "transport_s": 0.010389158999982162, + "worker_faults": 1877, + "worker_maxrss_mib": 1055, + "cleanup_s": 0.5942183730003308, + "k_nr_written": 263273, + "k_pgpgout": 1053100, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 12.704156327000419 + }, + { + "path": "disk", + "tool": "passthrough", + "export_s": 0.2684781629995996, + "export_fsync_s": 0.7224582509998072, + "host_export_faults": 0, + "task_wall_s": 0.840894961000231, + "load_s": 0.4571, + "tool_s": 0.0, + "write_s": 0.3786, + "transport_s": 0.00519496100023098, + "worker_faults": 1016, + "worker_maxrss_mib": 1055, + "cleanup_s": 0.6185906139999133, + "k_nr_written": 262293, + "k_pgpgout": 1049172, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 1.727963737999744 + }, + { + "path": "disk", + "tool": "passthrough", + "export_s": 0.26727675599977374, + "export_fsync_s": 0.5964060119995338, + "host_export_faults": 0, + "task_wall_s": 0.8506324529998892, + "load_s": 0.3638, + "tool_s": 0.0, + "write_s": 0.4813, + "transport_s": 0.0055324529998891925, + "worker_faults": 1014, + "worker_maxrss_mib": 1055, + "cleanup_s": 0.7827218780003022, + "k_nr_written": 262205, + "k_pgpgout": 1048828, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 1.9006310869999652 + } + ], + "summary": { + "cleanup_s": { + "median": 0.6185906139999133, + "min": 0.5942183730003308, + "max": 0.7827218780003022 + }, + "export_fsync_s": { + "median": 0.6569792410000446, + "min": 0.5964060119995338, + "max": 0.7224582509998072 + }, + "export_s": { + "median": 0.2684781629995996, + "min": 0.26727675599977374, + "max": 5.746448795000106 + }, + "host_export_faults": { + "median": 0, + "min": 0, + "max": 1 + }, + "k_allocstall_normal": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_nr_written": { + "median": 262293, + "min": 262205, + "max": 263273 + }, + "k_pgpgout": { + "median": 1049172, + "min": 1048828, + "max": 1053100 + }, + "k_pgscan_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgscan_kswapd": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgsteal_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_psi_some_us": { + "median": 0, + "min": 0, + "max": 0 + }, + "load_s": { + "median": 0.4571, + "min": 0.3638, + "max": 5.8196 + }, + "task_wall_s": { + "median": 0.8506324529998892, + "min": 0.840894961000231, + "max": 6.3634891589999825 + }, + "tool_s": { + "median": 0.0, + "min": 0.0, + "max": 0.0 + }, + "total_s": { + "median": 1.9006310869999652, + "min": 1.727963737999744, + "max": 12.704156327000419 + }, + "transport_s": { + "median": 0.0055324529998891925, + "min": 0.00519496100023098, + "max": 0.010389158999982162 + }, + "worker_faults": { + "median": 1016, + "min": 1014, + "max": 1877 + }, + "worker_maxrss_mib": { + "median": 1055, + "min": 1055, + "max": 1055 + }, + "write_s": { + "median": 0.4813, + "min": 0.3786, + "max": 0.5335 + } + } + }, + "shm": { + "rows": [ + { + "path": "shm", + "tool": "passthrough", + "shm_create_s": 0.0004861369998252485, + "shm_fill_s": 0.8541924159999326, + "export_s": 0.8546785529997578, + "host_export_faults": 262134, + "task_wall_s": 2.607750627999849, + "load_s": 0.4798, + "tool_s": 0.0, + "write_s": 2.1191, + "transport_s": 0.008850627999848815, + "worker_faults": 17695, + "worker_maxrss_mib": 2083, + "cleanup_s": 0.2999282310001945, + "k_nr_written": 2, + "k_pgpgout": 8, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 3.762357411999801 + }, + { + "path": "shm", + "tool": "passthrough", + "shm_create_s": 0.00011386799997126218, + "shm_fill_s": 0.895208521999848, + "export_s": 0.8953223899998193, + "host_export_faults": 262134, + "task_wall_s": 2.8866428230003294, + "load_s": 1.3514, + "tool_s": 0.0, + "write_s": 1.5303, + "transport_s": 0.004942823000329444, + "worker_faults": 17399, + "worker_maxrss_mib": 2083, + "cleanup_s": 0.353415001999565, + "k_nr_written": 344, + "k_pgpgout": 1376, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 4.135380214999714 + }, + { + "path": "shm", + "tool": "passthrough", + "shm_create_s": 0.00011823700060631381, + "shm_fill_s": 0.8854583420006747, + "export_s": 0.8855765790012811, + "host_export_faults": 262134, + "task_wall_s": 4.912052625000797, + "load_s": 1.0593, + "tool_s": 0.0, + "write_s": 3.8481, + "transport_s": 0.004652625000796995, + "worker_faults": 17398, + "worker_maxrss_mib": 2083, + "cleanup_s": 0.22274449599990476, + "k_nr_written": 6, + "k_pgpgout": 24, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 6.020373700001983 + } + ], + "summary": { + "cleanup_s": { + "median": 0.2999282310001945, + "min": 0.22274449599990476, + "max": 0.353415001999565 + }, + "export_s": { + "median": 0.8855765790012811, + "min": 0.8546785529997578, + "max": 0.8953223899998193 + }, + "host_export_faults": { + "median": 262134, + "min": 262134, + "max": 262134 + }, + "k_allocstall_normal": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_nr_written": { + "median": 6, + "min": 2, + "max": 344 + }, + "k_pgpgout": { + "median": 24, + "min": 8, + "max": 1376 + }, + "k_pgscan_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgscan_kswapd": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgsteal_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_psi_some_us": { + "median": 0, + "min": 0, + "max": 0 + }, + "load_s": { + "median": 1.0593, + "min": 0.4798, + "max": 1.3514 + }, + "shm_create_s": { + "median": 0.00011823700060631381, + "min": 0.00011386799997126218, + "max": 0.0004861369998252485 + }, + "shm_fill_s": { + "median": 0.8854583420006747, + "min": 0.8541924159999326, + "max": 0.895208521999848 + }, + "task_wall_s": { + "median": 2.8866428230003294, + "min": 2.607750627999849, + "max": 4.912052625000797 + }, + "tool_s": { + "median": 0.0, + "min": 0.0, + "max": 0.0 + }, + "total_s": { + "median": 4.135380214999714, + "min": 3.762357411999801, + "max": 6.020373700001983 + }, + "transport_s": { + "median": 0.004942823000329444, + "min": 0.004652625000796995, + "max": 0.008850627999848815 + }, + "worker_faults": { + "median": 17399, + "min": 17398, + "max": 17695 + }, + "worker_maxrss_mib": { + "median": 2083, + "min": 2083, + "max": 2083 + }, + "write_s": { + "median": 2.1191, + "min": 1.5303, + "max": 3.8481 + } + } + } + } + } + } +} \ No newline at end of file diff --git a/benchmarks/results/sandbox_default_128_512.json b/benchmarks/results/sandbox_default_128_512.json new file mode 100644 index 0000000..f23701c --- /dev/null +++ b/benchmarks/results/sandbox_default_128_512.json @@ -0,0 +1,2314 @@ +{ + "env": { + "python": "3.11.15", + "numpy": "2.4.6", + "tifffile": "2026.3.3", + "cpus": 4, + "scratch": "/home/user/tmp_shm/tmp/lc-shm-bench-fhrcfz20", + "out_scratch": "/home/user/tmp_shm/tmp/lc-shm-bench-fhrcfz20", + "cold": false, + "prewarm": 0 + }, + "runs": { + "128": { + "image_max": { + "disk": { + "rows": [ + { + "path": "disk", + "tool": "image_max", + "export_s": 0.6102052249998451, + "export_fsync_s": 0.11215446300047915, + "host_export_faults": 2, + "task_wall_s": 0.6833688699998675, + "load_s": 0.6703, + "tool_s": 0.0102, + "write_s": 0.0001, + "transport_s": 0.002768869999867449, + "worker_faults": 927, + "worker_maxrss_mib": 159, + "cleanup_s": 0.06432725299964659, + "k_nr_written": 32769, + "k_pgpgout": 131156, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 1.3579013479993591 + }, + { + "path": "disk", + "tool": "image_max", + "export_s": 0.03810682000039378, + "export_fsync_s": 0.10494965599991701, + "host_export_faults": 0, + "task_wall_s": 0.07769100699988485, + "load_s": 0.0662, + "tool_s": 0.0092, + "write_s": 0.0001, + "transport_s": 0.002191006999884854, + "worker_faults": 68, + "worker_maxrss_mib": 159, + "cleanup_s": 0.07959010300055525, + "k_nr_written": 32770, + "k_pgpgout": 131096, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.19538793000083388 + }, + { + "path": "disk", + "tool": "image_max", + "export_s": 0.045616275000611495, + "export_fsync_s": 0.128924716000256, + "host_export_faults": 0, + "task_wall_s": 0.06485080899983586, + "load_s": 0.0544, + "tool_s": 0.0085, + "write_s": 0.0001, + "transport_s": 0.0018508089998358652, + "worker_faults": 65, + "worker_maxrss_mib": 159, + "cleanup_s": 0.06544505600049888, + "k_nr_written": 32769, + "k_pgpgout": 131092, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.17591214000094624 + } + ], + "summary": { + "cleanup_s": { + "median": 0.06544505600049888, + "min": 0.06432725299964659, + "max": 0.07959010300055525 + }, + "export_fsync_s": { + "median": 0.11215446300047915, + "min": 0.10494965599991701, + "max": 0.128924716000256 + }, + "export_s": { + "median": 0.045616275000611495, + "min": 0.03810682000039378, + "max": 0.6102052249998451 + }, + "host_export_faults": { + "median": 0, + "min": 0, + "max": 2 + }, + "k_allocstall_normal": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_nr_written": { + "median": 32769, + "min": 32769, + "max": 32770 + }, + "k_pgpgout": { + "median": 131096, + "min": 131092, + "max": 131156 + }, + "k_pgscan_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgscan_kswapd": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgsteal_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_psi_some_us": { + "median": 0, + "min": 0, + "max": 0 + }, + "load_s": { + "median": 0.0662, + "min": 0.0544, + "max": 0.6703 + }, + "task_wall_s": { + "median": 0.07769100699988485, + "min": 0.06485080899983586, + "max": 0.6833688699998675 + }, + "tool_s": { + "median": 0.0092, + "min": 0.0085, + "max": 0.0102 + }, + "total_s": { + "median": 0.19538793000083388, + "min": 0.17591214000094624, + "max": 1.3579013479993591 + }, + "transport_s": { + "median": 0.002191006999884854, + "min": 0.0018508089998358652, + "max": 0.002768869999867449 + }, + "worker_faults": { + "median": 68, + "min": 65, + "max": 927 + }, + "worker_maxrss_mib": { + "median": 159, + "min": 159, + "max": 159 + }, + "write_s": { + "median": 0.0001, + "min": 0.0001, + "max": 0.0001 + } + } + }, + "shm": { + "rows": [ + { + "path": "shm", + "tool": "image_max", + "shm_create_s": 0.0012808709998353152, + "shm_fill_s": 0.10773395999967761, + "export_s": 0.10901483099951292, + "host_export_faults": 32768, + "task_wall_s": 0.08459788399977697, + "load_s": 0.0734, + "tool_s": 0.0093, + "write_s": 0.0001, + "transport_s": 0.001797883999776962, + "worker_faults": 2402, + "worker_maxrss_mib": 291, + "cleanup_s": 0.024909403000492603, + "k_nr_written": 0, + "k_pgpgout": 0, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.2185221179997825 + }, + { + "path": "shm", + "tool": "image_max", + "shm_create_s": 0.00011343000005581416, + "shm_fill_s": 0.0958701250001468, + "export_s": 0.09598355500020261, + "host_export_faults": 32768, + "task_wall_s": 0.07307373000003281, + "load_s": 0.061, + "tool_s": 0.0103, + "write_s": 0.0001, + "transport_s": 0.0016737300000328117, + "worker_faults": 2114, + "worker_maxrss_mib": 291, + "cleanup_s": 0.017776978999791027, + "k_nr_written": 0, + "k_pgpgout": 0, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.18683426400002645 + }, + { + "path": "shm", + "tool": "image_max", + "shm_create_s": 9.963199954654556e-05, + "shm_fill_s": 0.10874952300036966, + "export_s": 0.10884915499991621, + "host_export_faults": 32768, + "task_wall_s": 0.06452581199937413, + "load_s": 0.0536, + "tool_s": 0.0088, + "write_s": 0.0001, + "transport_s": 0.0020258119993741253, + "worker_faults": 2114, + "worker_maxrss_mib": 291, + "cleanup_s": 0.023937529000249924, + "k_nr_written": 0, + "k_pgpgout": 0, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.19731249599954026 + } + ], + "summary": { + "cleanup_s": { + "median": 0.023937529000249924, + "min": 0.017776978999791027, + "max": 0.024909403000492603 + }, + "export_s": { + "median": 0.10884915499991621, + "min": 0.09598355500020261, + "max": 0.10901483099951292 + }, + "host_export_faults": { + "median": 32768, + "min": 32768, + "max": 32768 + }, + "k_allocstall_normal": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_nr_written": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgpgout": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgscan_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgscan_kswapd": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgsteal_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_psi_some_us": { + "median": 0, + "min": 0, + "max": 0 + }, + "load_s": { + "median": 0.061, + "min": 0.0536, + "max": 0.0734 + }, + "shm_create_s": { + "median": 0.00011343000005581416, + "min": 9.963199954654556e-05, + "max": 0.0012808709998353152 + }, + "shm_fill_s": { + "median": 0.10773395999967761, + "min": 0.0958701250001468, + "max": 0.10874952300036966 + }, + "task_wall_s": { + "median": 0.07307373000003281, + "min": 0.06452581199937413, + "max": 0.08459788399977697 + }, + "tool_s": { + "median": 0.0093, + "min": 0.0088, + "max": 0.0103 + }, + "total_s": { + "median": 0.19731249599954026, + "min": 0.18683426400002645, + "max": 0.2185221179997825 + }, + "transport_s": { + "median": 0.001797883999776962, + "min": 0.0016737300000328117, + "max": 0.0020258119993741253 + }, + "worker_faults": { + "median": 2114, + "min": 2114, + "max": 2402 + }, + "worker_maxrss_mib": { + "median": 291, + "min": 291, + "max": 291 + }, + "write_s": { + "median": 0.0001, + "min": 0.0001, + "max": 0.0001 + } + } + }, + "cli": { + "rows": [ + { + "path": "cli", + "tool": "image_max", + "export_s": 0.03483270199922117, + "cli_wall_s": 0.3725225179996414 + }, + { + "path": "cli", + "tool": "image_max", + "export_s": 0.039233894999597396, + "cli_wall_s": 0.3736197379994337 + }, + { + "path": "cli", + "tool": "image_max", + "export_s": 0.031893348999801674, + "cli_wall_s": 0.3741724940000495 + } + ], + "summary": { + "cli_wall_s": { + "median": 0.3736197379994337, + "min": 0.3725225179996414, + "max": 0.3741724940000495 + }, + "export_s": { + "median": 0.03483270199922117, + "min": 0.031893348999801674, + "max": 0.039233894999597396 + } + } + } + }, + "invert": { + "disk": { + "rows": [ + { + "path": "disk", + "tool": "invert", + "export_s": 0.0353079999995316, + "export_fsync_s": 0.12401059300009365, + "host_export_faults": 0, + "task_wall_s": 1.4132313109994357, + "load_s": 0.0456, + "tool_s": 0.6793, + "write_s": 0.685, + "transport_s": 0.0033313109994355106, + "worker_faults": 650, + "worker_maxrss_mib": 291, + "result_read_s": 0.07874105000064446, + "cleanup_s": 0.0815519759999006, + "k_nr_written": 32769, + "k_pgpgout": 131092, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 1.6088323369995123 + }, + { + "path": "disk", + "tool": "invert", + "export_s": 0.03580998100005672, + "export_fsync_s": 0.13195719999930589, + "host_export_faults": 0, + "task_wall_s": 0.14813791500000661, + "load_s": 0.0602, + "tool_s": 0.0478, + "write_s": 0.035, + "transport_s": 0.005137915000006606, + "worker_faults": 644, + "worker_maxrss_mib": 291, + "result_read_s": 0.053243323999595304, + "cleanup_s": 0.07803785299984156, + "k_nr_written": 32769, + "k_pgpgout": 131092, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.3152290729995002 + }, + { + "path": "disk", + "tool": "invert", + "export_s": 0.041873742999996466, + "export_fsync_s": 0.1283532199995534, + "host_export_faults": 1, + "task_wall_s": 0.1744857290004802, + "load_s": 0.0515, + "tool_s": 0.0399, + "write_s": 0.0803, + "transport_s": 0.0027857290004802276, + "worker_faults": 642, + "worker_maxrss_mib": 291, + "result_read_s": 0.06461603400020977, + "cleanup_s": 0.07559647000016412, + "k_nr_written": 32769, + "k_pgpgout": 131092, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.35657197600085055 + } + ], + "summary": { + "cleanup_s": { + "median": 0.07803785299984156, + "min": 0.07559647000016412, + "max": 0.0815519759999006 + }, + "export_fsync_s": { + "median": 0.1283532199995534, + "min": 0.12401059300009365, + "max": 0.13195719999930589 + }, + "export_s": { + "median": 0.03580998100005672, + "min": 0.0353079999995316, + "max": 0.041873742999996466 + }, + "host_export_faults": { + "median": 0, + "min": 0, + "max": 1 + }, + "k_allocstall_normal": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_nr_written": { + "median": 32769, + "min": 32769, + "max": 32769 + }, + "k_pgpgout": { + "median": 131092, + "min": 131092, + "max": 131092 + }, + "k_pgscan_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgscan_kswapd": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgsteal_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_psi_some_us": { + "median": 0, + "min": 0, + "max": 0 + }, + "load_s": { + "median": 0.0515, + "min": 0.0456, + "max": 0.0602 + }, + "result_read_s": { + "median": 0.06461603400020977, + "min": 0.053243323999595304, + "max": 0.07874105000064446 + }, + "task_wall_s": { + "median": 0.1744857290004802, + "min": 0.14813791500000661, + "max": 1.4132313109994357 + }, + "tool_s": { + "median": 0.0478, + "min": 0.0399, + "max": 0.6793 + }, + "total_s": { + "median": 0.35657197600085055, + "min": 0.3152290729995002, + "max": 1.6088323369995123 + }, + "transport_s": { + "median": 0.0033313109994355106, + "min": 0.0027857290004802276, + "max": 0.005137915000006606 + }, + "worker_faults": { + "median": 644, + "min": 642, + "max": 650 + }, + "worker_maxrss_mib": { + "median": 291, + "min": 291, + "max": 291 + }, + "write_s": { + "median": 0.0803, + "min": 0.035, + "max": 0.685 + } + } + }, + "shm": { + "rows": [ + { + "path": "shm", + "tool": "invert", + "shm_create_s": 0.00012169299952802248, + "shm_fill_s": 0.11310731499997928, + "export_s": 0.1132290079995073, + "host_export_faults": 32768, + "task_wall_s": 0.13859232899994822, + "load_s": 0.0636, + "tool_s": 0.0363, + "write_s": 0.036, + "transport_s": 0.0026923289999482222, + "worker_faults": 2690, + "worker_maxrss_mib": 291, + "result_read_s": 0.0444417999997313, + "cleanup_s": 0.03084860800026945, + "k_nr_written": 0, + "k_pgpgout": 0, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.3271117449994563 + }, + { + "path": "shm", + "tool": "invert", + "shm_create_s": 0.00012969600084034028, + "shm_fill_s": 0.11679409200041846, + "export_s": 0.1169237880012588, + "host_export_faults": 32768, + "task_wall_s": 0.14088192700000945, + "load_s": 0.0612, + "tool_s": 0.0434, + "write_s": 0.0337, + "transport_s": 0.0025819270000094485, + "worker_faults": 2689, + "worker_maxrss_mib": 291, + "result_read_s": 0.051320173000021896, + "cleanup_s": 0.03248381499997777, + "k_nr_written": 0, + "k_pgpgout": 0, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.3416097030012679 + }, + { + "path": "shm", + "tool": "invert", + "shm_create_s": 0.00010394000037194928, + "shm_fill_s": 0.11597305899977073, + "export_s": 0.11607699900014268, + "host_export_faults": 32768, + "task_wall_s": 0.5714464780003254, + "load_s": 0.0561, + "tool_s": 0.0389, + "write_s": 0.4739, + "transport_s": 0.002546478000325425, + "worker_faults": 2690, + "worker_maxrss_mib": 291, + "result_read_s": 0.044122816999333736, + "cleanup_s": 0.02429971200035652, + "k_nr_written": 299, + "k_pgpgout": 1196, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.7559460060001584 + } + ], + "summary": { + "cleanup_s": { + "median": 0.03084860800026945, + "min": 0.02429971200035652, + "max": 0.03248381499997777 + }, + "export_s": { + "median": 0.11607699900014268, + "min": 0.1132290079995073, + "max": 0.1169237880012588 + }, + "host_export_faults": { + "median": 32768, + "min": 32768, + "max": 32768 + }, + "k_allocstall_normal": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_nr_written": { + "median": 0, + "min": 0, + "max": 299 + }, + "k_pgpgout": { + "median": 0, + "min": 0, + "max": 1196 + }, + "k_pgscan_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgscan_kswapd": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgsteal_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_psi_some_us": { + "median": 0, + "min": 0, + "max": 0 + }, + "load_s": { + "median": 0.0612, + "min": 0.0561, + "max": 0.0636 + }, + "result_read_s": { + "median": 0.0444417999997313, + "min": 0.044122816999333736, + "max": 0.051320173000021896 + }, + "shm_create_s": { + "median": 0.00012169299952802248, + "min": 0.00010394000037194928, + "max": 0.00012969600084034028 + }, + "shm_fill_s": { + "median": 0.11597305899977073, + "min": 0.11310731499997928, + "max": 0.11679409200041846 + }, + "task_wall_s": { + "median": 0.14088192700000945, + "min": 0.13859232899994822, + "max": 0.5714464780003254 + }, + "tool_s": { + "median": 0.0389, + "min": 0.0363, + "max": 0.0434 + }, + "total_s": { + "median": 0.3416097030012679, + "min": 0.3271117449994563, + "max": 0.7559460060001584 + }, + "transport_s": { + "median": 0.0025819270000094485, + "min": 0.002546478000325425, + "max": 0.0026923289999482222 + }, + "worker_faults": { + "median": 2690, + "min": 2689, + "max": 2690 + }, + "worker_maxrss_mib": { + "median": 291, + "min": 291, + "max": 291 + }, + "write_s": { + "median": 0.036, + "min": 0.0337, + "max": 0.4739 + } + } + } + }, + "invert_to_shm": { + "disk": { + "rows": [ + { + "path": "disk", + "tool": "invert_to_shm", + "export_s": 0.030847171999994316, + "export_fsync_s": 0.12446107100004156, + "host_export_faults": 1, + "task_wall_s": 0.14680142900033388, + "load_s": 0.0484, + "tool_s": 0.0958, + "write_s": 0.0001, + "transport_s": 0.002501429000333888, + "worker_faults": 32834, + "worker_maxrss_mib": 291, + "result_attach_s": 0.00014787800046178745, + "result_copy_s": 0.050785681999514054, + "result_read_s": 0.05093355999997584, + "cleanup_s": 0.06311917600032757, + "k_nr_written": 32769, + "k_pgpgout": 131092, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.2917013370006316 + }, + { + "path": "disk", + "tool": "invert_to_shm", + "export_s": 0.03216091300055268, + "export_fsync_s": 0.11971342800006823, + "host_export_faults": 0, + "task_wall_s": 0.1608263709995299, + "load_s": 0.046, + "tool_s": 0.1124, + "write_s": 0.0001, + "transport_s": 0.0023263709995299006, + "worker_faults": 32835, + "worker_maxrss_mib": 291, + "result_attach_s": 0.00011488699965411797, + "result_copy_s": 0.0652283740000712, + "result_read_s": 0.06534326099972532, + "cleanup_s": 0.06647633699958533, + "k_nr_written": 32769, + "k_pgpgout": 131092, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.3248068819993932 + }, + { + "path": "disk", + "tool": "invert_to_shm", + "export_s": 0.03744805199949042, + "export_fsync_s": 0.13271942400024273, + "host_export_faults": 0, + "task_wall_s": 0.1430810020001445, + "load_s": 0.0512, + "tool_s": 0.0884, + "write_s": 0.0001, + "transport_s": 0.0033810020001445065, + "worker_faults": 32834, + "worker_maxrss_mib": 291, + "result_attach_s": 0.00012023500039504142, + "result_copy_s": 0.06509653299963247, + "result_read_s": 0.06521676800002751, + "cleanup_s": 0.06307070299953921, + "k_nr_written": 32769, + "k_pgpgout": 131092, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.30881652499920165 + } + ], + "summary": { + "cleanup_s": { + "median": 0.06311917600032757, + "min": 0.06307070299953921, + "max": 0.06647633699958533 + }, + "export_fsync_s": { + "median": 0.12446107100004156, + "min": 0.11971342800006823, + "max": 0.13271942400024273 + }, + "export_s": { + "median": 0.03216091300055268, + "min": 0.030847171999994316, + "max": 0.03744805199949042 + }, + "host_export_faults": { + "median": 0, + "min": 0, + "max": 1 + }, + "k_allocstall_normal": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_nr_written": { + "median": 32769, + "min": 32769, + "max": 32769 + }, + "k_pgpgout": { + "median": 131092, + "min": 131092, + "max": 131092 + }, + "k_pgscan_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgscan_kswapd": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgsteal_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_psi_some_us": { + "median": 0, + "min": 0, + "max": 0 + }, + "load_s": { + "median": 0.0484, + "min": 0.046, + "max": 0.0512 + }, + "result_attach_s": { + "median": 0.00012023500039504142, + "min": 0.00011488699965411797, + "max": 0.00014787800046178745 + }, + "result_copy_s": { + "median": 0.06509653299963247, + "min": 0.050785681999514054, + "max": 0.0652283740000712 + }, + "result_read_s": { + "median": 0.06521676800002751, + "min": 0.05093355999997584, + "max": 0.06534326099972532 + }, + "task_wall_s": { + "median": 0.14680142900033388, + "min": 0.1430810020001445, + "max": 0.1608263709995299 + }, + "tool_s": { + "median": 0.0958, + "min": 0.0884, + "max": 0.1124 + }, + "total_s": { + "median": 0.30881652499920165, + "min": 0.2917013370006316, + "max": 0.3248068819993932 + }, + "transport_s": { + "median": 0.002501429000333888, + "min": 0.0023263709995299006, + "max": 0.0033810020001445065 + }, + "worker_faults": { + "median": 32834, + "min": 32834, + "max": 32835 + }, + "worker_maxrss_mib": { + "median": 291, + "min": 291, + "max": 291 + }, + "write_s": { + "median": 0.0001, + "min": 0.0001, + "max": 0.0001 + } + } + }, + "shm": { + "rows": [ + { + "path": "shm", + "tool": "invert_to_shm", + "shm_create_s": 0.00011359600011928705, + "shm_fill_s": 0.11909060400012095, + "export_s": 0.11920420000024023, + "host_export_faults": 32768, + "task_wall_s": 0.15764323299936223, + "load_s": 0.0725, + "tool_s": 0.0832, + "write_s": 0.0001, + "transport_s": 0.0018432329993622349, + "worker_faults": 34881, + "worker_maxrss_mib": 291, + "result_attach_s": 0.00022414399973058607, + "result_copy_s": 0.05807644899959996, + "result_read_s": 0.05830059299933055, + "cleanup_s": 0.02191927800049598, + "k_nr_written": 0, + "k_pgpgout": 0, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.357067303999429 + }, + { + "path": "shm", + "tool": "invert_to_shm", + "shm_create_s": 9.301600039179903e-05, + "shm_fill_s": 0.09931637799945747, + "export_s": 0.09940939399984927, + "host_export_faults": 32768, + "task_wall_s": 0.16683050299980096, + "load_s": 0.0658, + "tool_s": 0.0987, + "write_s": 0.0001, + "transport_s": 0.0022305029998009626, + "worker_faults": 34881, + "worker_maxrss_mib": 291, + "result_attach_s": 0.00010267900051985634, + "result_copy_s": 0.05763456699969538, + "result_read_s": 0.05773724600021524, + "cleanup_s": 0.024969197000245913, + "k_nr_written": 0, + "k_pgpgout": 0, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.3489463400001114 + }, + { + "path": "shm", + "tool": "invert_to_shm", + "shm_create_s": 9.496300026512472e-05, + "shm_fill_s": 0.09874432200012961, + "export_s": 0.09883928500039474, + "host_export_faults": 32768, + "task_wall_s": 0.14725053500023932, + "load_s": 0.0569, + "tool_s": 0.0882, + "write_s": 0.0001, + "transport_s": 0.0020505350002393177, + "worker_faults": 34882, + "worker_maxrss_mib": 291, + "result_attach_s": 0.0001117330002671224, + "result_copy_s": 0.05467596200014668, + "result_read_s": 0.054787695000413805, + "cleanup_s": 0.023648319999665546, + "k_nr_written": 0, + "k_pgpgout": 0, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.3245258350007134 + } + ], + "summary": { + "cleanup_s": { + "median": 0.023648319999665546, + "min": 0.02191927800049598, + "max": 0.024969197000245913 + }, + "export_s": { + "median": 0.09940939399984927, + "min": 0.09883928500039474, + "max": 0.11920420000024023 + }, + "host_export_faults": { + "median": 32768, + "min": 32768, + "max": 32768 + }, + "k_allocstall_normal": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_nr_written": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgpgout": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgscan_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgscan_kswapd": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgsteal_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_psi_some_us": { + "median": 0, + "min": 0, + "max": 0 + }, + "load_s": { + "median": 0.0658, + "min": 0.0569, + "max": 0.0725 + }, + "result_attach_s": { + "median": 0.0001117330002671224, + "min": 0.00010267900051985634, + "max": 0.00022414399973058607 + }, + "result_copy_s": { + "median": 0.05763456699969538, + "min": 0.05467596200014668, + "max": 0.05807644899959996 + }, + "result_read_s": { + "median": 0.05773724600021524, + "min": 0.054787695000413805, + "max": 0.05830059299933055 + }, + "shm_create_s": { + "median": 9.496300026512472e-05, + "min": 9.301600039179903e-05, + "max": 0.00011359600011928705 + }, + "shm_fill_s": { + "median": 0.09931637799945747, + "min": 0.09874432200012961, + "max": 0.11909060400012095 + }, + "task_wall_s": { + "median": 0.15764323299936223, + "min": 0.14725053500023932, + "max": 0.16683050299980096 + }, + "tool_s": { + "median": 0.0882, + "min": 0.0832, + "max": 0.0987 + }, + "total_s": { + "median": 0.3489463400001114, + "min": 0.3245258350007134, + "max": 0.357067303999429 + }, + "transport_s": { + "median": 0.0020505350002393177, + "min": 0.0018432329993622349, + "max": 0.0022305029998009626 + }, + "worker_faults": { + "median": 34881, + "min": 34881, + "max": 34882 + }, + "worker_maxrss_mib": { + "median": 291, + "min": 291, + "max": 291 + }, + "write_s": { + "median": 0.0001, + "min": 0.0001, + "max": 0.0001 + } + } + } + } + }, + "512": { + "image_max": { + "disk": { + "rows": [ + { + "path": "disk", + "tool": "image_max", + "export_s": 2.4196500409998407, + "export_fsync_s": 0.45451723499991203, + "host_export_faults": 0, + "task_wall_s": 3.3138497429999916, + "load_s": 3.273, + "tool_s": 0.0372, + "write_s": 0.0001, + "transport_s": 0.0035497429999914484, + "worker_faults": 258, + "worker_maxrss_mib": 547, + "cleanup_s": 0.292102538999643, + "k_nr_written": 131077, + "k_pgpgout": 524324, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 6.025602322999475 + }, + { + "path": "disk", + "tool": "image_max", + "export_s": 0.1777742969998144, + "export_fsync_s": 0.44013136600005964, + "host_export_faults": 0, + "task_wall_s": 0.23451032100001612, + "load_s": 0.1935, + "tool_s": 0.0367, + "write_s": 0.0001, + "transport_s": 0.004210321000016111, + "worker_faults": 257, + "worker_maxrss_mib": 547, + "cleanup_s": 0.27990580900041095, + "k_nr_written": 131073, + "k_pgpgout": 524312, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.6921904270002415 + }, + { + "path": "disk", + "tool": "image_max", + "export_s": 0.15090104000046267, + "export_fsync_s": 0.44507356499980233, + "host_export_faults": 0, + "task_wall_s": 1.5152677489995767, + "load_s": 1.4756, + "tool_s": 0.0355, + "write_s": 0.0001, + "transport_s": 0.004067748999576705, + "worker_faults": 257, + "worker_maxrss_mib": 547, + "cleanup_s": 0.24576745800004574, + "k_nr_written": 131073, + "k_pgpgout": 524312, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 1.9119362470000851 + } + ], + "summary": { + "cleanup_s": { + "median": 0.27990580900041095, + "min": 0.24576745800004574, + "max": 0.292102538999643 + }, + "export_fsync_s": { + "median": 0.44507356499980233, + "min": 0.44013136600005964, + "max": 0.45451723499991203 + }, + "export_s": { + "median": 0.1777742969998144, + "min": 0.15090104000046267, + "max": 2.4196500409998407 + }, + "host_export_faults": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_allocstall_normal": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_nr_written": { + "median": 131073, + "min": 131073, + "max": 131077 + }, + "k_pgpgout": { + "median": 524312, + "min": 524312, + "max": 524324 + }, + "k_pgscan_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgscan_kswapd": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgsteal_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_psi_some_us": { + "median": 0, + "min": 0, + "max": 0 + }, + "load_s": { + "median": 1.4756, + "min": 0.1935, + "max": 3.273 + }, + "task_wall_s": { + "median": 1.5152677489995767, + "min": 0.23451032100001612, + "max": 3.3138497429999916 + }, + "tool_s": { + "median": 0.0367, + "min": 0.0355, + "max": 0.0372 + }, + "total_s": { + "median": 1.9119362470000851, + "min": 0.6921904270002415, + "max": 6.025602322999475 + }, + "transport_s": { + "median": 0.004067748999576705, + "min": 0.0035497429999914484, + "max": 0.004210321000016111 + }, + "worker_faults": { + "median": 257, + "min": 257, + "max": 258 + }, + "worker_maxrss_mib": { + "median": 547, + "min": 547, + "max": 547 + }, + "write_s": { + "median": 0.0001, + "min": 0.0001, + "max": 0.0001 + } + } + }, + "shm": { + "rows": [ + { + "path": "shm", + "tool": "image_max", + "shm_create_s": 0.00016064600004028762, + "shm_fill_s": 0.47262430199953087, + "export_s": 0.47278494799957116, + "host_export_faults": 131072, + "task_wall_s": 0.753331967000122, + "load_s": 0.7137, + "tool_s": 0.0362, + "write_s": 0.0001, + "transport_s": 0.0033319670001219453, + "worker_faults": 8449, + "worker_maxrss_mib": 1059, + "cleanup_s": 0.07218995899984293, + "k_nr_written": 154, + "k_pgpgout": 608, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 1.298306873999536 + }, + { + "path": "shm", + "tool": "image_max", + "shm_create_s": 9.584899999026675e-05, + "shm_fill_s": 0.4250412379997215, + "export_s": 0.42513708699971176, + "host_export_faults": 131072, + "task_wall_s": 1.9381652649999523, + "load_s": 1.8947, + "tool_s": 0.0386, + "write_s": 0.0001, + "transport_s": 0.0047652649999522885, + "worker_faults": 8449, + "worker_maxrss_mib": 1059, + "cleanup_s": 0.08237137700052699, + "k_nr_written": 0, + "k_pgpgout": 0, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 2.445673729000191 + }, + { + "path": "shm", + "tool": "image_max", + "shm_create_s": 0.00010384699999121949, + "shm_fill_s": 0.46577522400002636, + "export_s": 0.4658790710000176, + "host_export_faults": 131072, + "task_wall_s": 0.2662500810001802, + "load_s": 0.2215, + "tool_s": 0.0416, + "write_s": 0.0001, + "transport_s": 0.003050081000180216, + "worker_faults": 8449, + "worker_maxrss_mib": 1059, + "cleanup_s": 0.09604634799961786, + "k_nr_written": 0, + "k_pgpgout": 0, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.8281754999998157 + } + ], + "summary": { + "cleanup_s": { + "median": 0.08237137700052699, + "min": 0.07218995899984293, + "max": 0.09604634799961786 + }, + "export_s": { + "median": 0.4658790710000176, + "min": 0.42513708699971176, + "max": 0.47278494799957116 + }, + "host_export_faults": { + "median": 131072, + "min": 131072, + "max": 131072 + }, + "k_allocstall_normal": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_nr_written": { + "median": 0, + "min": 0, + "max": 154 + }, + "k_pgpgout": { + "median": 0, + "min": 0, + "max": 608 + }, + "k_pgscan_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgscan_kswapd": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgsteal_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_psi_some_us": { + "median": 0, + "min": 0, + "max": 0 + }, + "load_s": { + "median": 0.7137, + "min": 0.2215, + "max": 1.8947 + }, + "shm_create_s": { + "median": 0.00010384699999121949, + "min": 9.584899999026675e-05, + "max": 0.00016064600004028762 + }, + "shm_fill_s": { + "median": 0.46577522400002636, + "min": 0.4250412379997215, + "max": 0.47262430199953087 + }, + "task_wall_s": { + "median": 0.753331967000122, + "min": 0.2662500810001802, + "max": 1.9381652649999523 + }, + "tool_s": { + "median": 0.0386, + "min": 0.0362, + "max": 0.0416 + }, + "total_s": { + "median": 1.298306873999536, + "min": 0.8281754999998157, + "max": 2.445673729000191 + }, + "transport_s": { + "median": 0.0033319670001219453, + "min": 0.003050081000180216, + "max": 0.0047652649999522885 + }, + "worker_faults": { + "median": 8449, + "min": 8449, + "max": 8449 + }, + "worker_maxrss_mib": { + "median": 1059, + "min": 1059, + "max": 1059 + }, + "write_s": { + "median": 0.0001, + "min": 0.0001, + "max": 0.0001 + } + } + }, + "cli": { + "rows": [ + { + "path": "cli", + "tool": "image_max", + "export_s": 0.7599541800000225, + "cli_wall_s": 2.1988431449999553 + }, + { + "path": "cli", + "tool": "image_max", + "export_s": 0.18506456300019636, + "cli_wall_s": 0.5198442480004815 + }, + { + "path": "cli", + "tool": "image_max", + "export_s": 0.1419402129995433, + "cli_wall_s": 0.5247767259998 + } + ], + "summary": { + "cli_wall_s": { + "median": 0.5247767259998, + "min": 0.5198442480004815, + "max": 2.1988431449999553 + }, + "export_s": { + "median": 0.18506456300019636, + "min": 0.1419402129995433, + "max": 0.7599541800000225 + } + } + } + }, + "invert": { + "disk": { + "rows": [ + { + "path": "disk", + "tool": "invert", + "export_s": 0.1831158819995835, + "export_fsync_s": 0.4283779620000132, + "host_export_faults": 0, + "task_wall_s": 6.671277673000077, + "load_s": 1.3458, + "tool_s": 2.7106, + "write_s": 2.61, + "transport_s": 0.004877673000076577, + "worker_faults": 1025, + "worker_maxrss_mib": 1059, + "result_read_s": 0.16840853900066577, + "cleanup_s": 0.2787314590004826, + "k_nr_written": 131096, + "k_pgpgout": 524404, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 7.301533553000809 + }, + { + "path": "disk", + "tool": "invert", + "export_s": 0.14806435499940562, + "export_fsync_s": 0.43109546000050614, + "host_export_faults": 0, + "task_wall_s": 0.5741594199998872, + "load_s": 0.2168, + "tool_s": 0.1747, + "write_s": 0.1775, + "transport_s": 0.005159419999887199, + "worker_faults": 1025, + "worker_maxrss_mib": 1059, + "result_read_s": 0.21077747399976943, + "cleanup_s": 0.4617904629994882, + "k_nr_written": 131073, + "k_pgpgout": 524312, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 1.3947917119985505 + }, + { + "path": "disk", + "tool": "invert", + "export_s": 0.6000384070002838, + "export_fsync_s": 0.43789995499992074, + "host_export_faults": 0, + "task_wall_s": 4.752136760000212, + "load_s": 1.2577, + "tool_s": 0.1523, + "write_s": 3.3355, + "transport_s": 0.006636760000212405, + "worker_faults": 1025, + "worker_maxrss_mib": 1059, + "result_read_s": 0.27069982700049877, + "cleanup_s": 0.3254463700004635, + "k_nr_written": 131073, + "k_pgpgout": 524312, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 5.948321364001458 + } + ], + "summary": { + "cleanup_s": { + "median": 0.3254463700004635, + "min": 0.2787314590004826, + "max": 0.4617904629994882 + }, + "export_fsync_s": { + "median": 0.43109546000050614, + "min": 0.4283779620000132, + "max": 0.43789995499992074 + }, + "export_s": { + "median": 0.1831158819995835, + "min": 0.14806435499940562, + "max": 0.6000384070002838 + }, + "host_export_faults": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_allocstall_normal": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_nr_written": { + "median": 131073, + "min": 131073, + "max": 131096 + }, + "k_pgpgout": { + "median": 524312, + "min": 524312, + "max": 524404 + }, + "k_pgscan_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgscan_kswapd": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgsteal_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_psi_some_us": { + "median": 0, + "min": 0, + "max": 0 + }, + "load_s": { + "median": 1.2577, + "min": 0.2168, + "max": 1.3458 + }, + "result_read_s": { + "median": 0.21077747399976943, + "min": 0.16840853900066577, + "max": 0.27069982700049877 + }, + "task_wall_s": { + "median": 4.752136760000212, + "min": 0.5741594199998872, + "max": 6.671277673000077 + }, + "tool_s": { + "median": 0.1747, + "min": 0.1523, + "max": 2.7106 + }, + "total_s": { + "median": 5.948321364001458, + "min": 1.3947917119985505, + "max": 7.301533553000809 + }, + "transport_s": { + "median": 0.005159419999887199, + "min": 0.004877673000076577, + "max": 0.006636760000212405 + }, + "worker_faults": { + "median": 1025, + "min": 1025, + "max": 1025 + }, + "worker_maxrss_mib": { + "median": 1059, + "min": 1059, + "max": 1059 + }, + "write_s": { + "median": 2.61, + "min": 0.1775, + "max": 3.3355 + } + } + }, + "shm": { + "rows": [ + { + "path": "shm", + "tool": "invert", + "shm_create_s": 0.00011054999959014822, + "shm_fill_s": 0.463913128999593, + "export_s": 0.4640236789991832, + "host_export_faults": 131072, + "task_wall_s": 0.5182689809998919, + "load_s": 0.2334, + "tool_s": 0.1517, + "write_s": 0.1269, + "transport_s": 0.006268980999891927, + "worker_faults": 9217, + "worker_maxrss_mib": 1059, + "result_read_s": 0.20031812400065974, + "cleanup_s": 0.14795998799945664, + "k_nr_written": 20596, + "k_pgpgout": 82384, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 1.3305707719991915 + }, + { + "path": "shm", + "tool": "invert", + "shm_create_s": 0.00010171600024477812, + "shm_fill_s": 0.4791659980000986, + "export_s": 0.4792677140003434, + "host_export_faults": 131072, + "task_wall_s": 3.9367845830001897, + "load_s": 2.0417, + "tool_s": 0.2056, + "write_s": 1.6841, + "transport_s": 0.0053845830001897355, + "worker_faults": 9218, + "worker_maxrss_mib": 1059, + "result_read_s": 0.1606671749996167, + "cleanup_s": 0.1453394179998213, + "k_nr_written": 41442, + "k_pgpgout": 165768, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 4.722058889999971 + }, + { + "path": "shm", + "tool": "invert", + "shm_create_s": 0.00013014999967708718, + "shm_fill_s": 0.42643762700026855, + "export_s": 0.42656777699994564, + "host_export_faults": 131072, + "task_wall_s": 0.5568246840002757, + "load_s": 0.2251, + "tool_s": 0.1699, + "write_s": 0.1539, + "transport_s": 0.007924684000275767, + "worker_faults": 9217, + "worker_maxrss_mib": 1059, + "result_read_s": 0.16126488400004746, + "cleanup_s": 0.11010965000059514, + "k_nr_written": 20543, + "k_pgpgout": 82172, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 1.254766995000864 + } + ], + "summary": { + "cleanup_s": { + "median": 0.1453394179998213, + "min": 0.11010965000059514, + "max": 0.14795998799945664 + }, + "export_s": { + "median": 0.4640236789991832, + "min": 0.42656777699994564, + "max": 0.4792677140003434 + }, + "host_export_faults": { + "median": 131072, + "min": 131072, + "max": 131072 + }, + "k_allocstall_normal": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_nr_written": { + "median": 20596, + "min": 20543, + "max": 41442 + }, + "k_pgpgout": { + "median": 82384, + "min": 82172, + "max": 165768 + }, + "k_pgscan_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgscan_kswapd": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgsteal_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_psi_some_us": { + "median": 0, + "min": 0, + "max": 0 + }, + "load_s": { + "median": 0.2334, + "min": 0.2251, + "max": 2.0417 + }, + "result_read_s": { + "median": 0.16126488400004746, + "min": 0.1606671749996167, + "max": 0.20031812400065974 + }, + "shm_create_s": { + "median": 0.00011054999959014822, + "min": 0.00010171600024477812, + "max": 0.00013014999967708718 + }, + "shm_fill_s": { + "median": 0.463913128999593, + "min": 0.42643762700026855, + "max": 0.4791659980000986 + }, + "task_wall_s": { + "median": 0.5568246840002757, + "min": 0.5182689809998919, + "max": 3.9367845830001897 + }, + "tool_s": { + "median": 0.1699, + "min": 0.1517, + "max": 0.2056 + }, + "total_s": { + "median": 1.3305707719991915, + "min": 1.254766995000864, + "max": 4.722058889999971 + }, + "transport_s": { + "median": 0.006268980999891927, + "min": 0.0053845830001897355, + "max": 0.007924684000275767 + }, + "worker_faults": { + "median": 9217, + "min": 9217, + "max": 9218 + }, + "worker_maxrss_mib": { + "median": 1059, + "min": 1059, + "max": 1059 + }, + "write_s": { + "median": 0.1539, + "min": 0.1269, + "max": 1.6841 + } + } + } + }, + "invert_to_shm": { + "disk": { + "rows": [ + { + "path": "disk", + "tool": "invert_to_shm", + "export_s": 0.1275790079998842, + "export_fsync_s": 0.4325049830003991, + "host_export_faults": 1, + "task_wall_s": 0.6520995060000132, + "load_s": 0.291, + "tool_s": 0.3578, + "write_s": 0.0001, + "transport_s": 0.0031995060000132194, + "worker_faults": 131330, + "worker_maxrss_mib": 1059, + "result_attach_s": 0.00010156499956792686, + "result_copy_s": 0.22223255199969572, + "result_read_s": 0.22233411699926364, + "cleanup_s": 0.2587697010003467, + "k_nr_written": 131073, + "k_pgpgout": 524312, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 1.2607823319995077 + }, + { + "path": "disk", + "tool": "invert_to_shm", + "export_s": 0.15228971899978205, + "export_fsync_s": 0.4476721470000484, + "host_export_faults": 0, + "task_wall_s": 0.5606463020003503, + "load_s": 0.2082, + "tool_s": 0.349, + "write_s": 0.0001, + "transport_s": 0.0033463020003502877, + "worker_faults": 131330, + "worker_maxrss_mib": 1059, + "result_attach_s": 0.0001232130007338128, + "result_copy_s": 0.2756389969999873, + "result_read_s": 0.2757622100007211, + "cleanup_s": 0.27910591599993495, + "k_nr_written": 131075, + "k_pgpgout": 524320, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 1.2678041470007884 + }, + { + "path": "disk", + "tool": "invert_to_shm", + "export_s": 0.144492330000503, + "export_fsync_s": 0.42632907000006526, + "host_export_faults": 0, + "task_wall_s": 0.5741308160004337, + "load_s": 0.1847, + "tool_s": 0.3858, + "write_s": 0.0001, + "transport_s": 0.0035308160004337455, + "worker_faults": 131332, + "worker_maxrss_mib": 1059, + "result_attach_s": 0.0012136689992985339, + "result_copy_s": 1.103185611000299, + "result_read_s": 1.1043992799995976, + "cleanup_s": 0.26592987599997286, + "k_nr_written": 131073, + "k_pgpgout": 524312, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 2.088952302000507 + } + ], + "summary": { + "cleanup_s": { + "median": 0.26592987599997286, + "min": 0.2587697010003467, + "max": 0.27910591599993495 + }, + "export_fsync_s": { + "median": 0.4325049830003991, + "min": 0.42632907000006526, + "max": 0.4476721470000484 + }, + "export_s": { + "median": 0.144492330000503, + "min": 0.1275790079998842, + "max": 0.15228971899978205 + }, + "host_export_faults": { + "median": 0, + "min": 0, + "max": 1 + }, + "k_allocstall_normal": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_nr_written": { + "median": 131073, + "min": 131073, + "max": 131075 + }, + "k_pgpgout": { + "median": 524312, + "min": 524312, + "max": 524320 + }, + "k_pgscan_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgscan_kswapd": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgsteal_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_psi_some_us": { + "median": 0, + "min": 0, + "max": 0 + }, + "load_s": { + "median": 0.2082, + "min": 0.1847, + "max": 0.291 + }, + "result_attach_s": { + "median": 0.0001232130007338128, + "min": 0.00010156499956792686, + "max": 0.0012136689992985339 + }, + "result_copy_s": { + "median": 0.2756389969999873, + "min": 0.22223255199969572, + "max": 1.103185611000299 + }, + "result_read_s": { + "median": 0.2757622100007211, + "min": 0.22233411699926364, + "max": 1.1043992799995976 + }, + "task_wall_s": { + "median": 0.5741308160004337, + "min": 0.5606463020003503, + "max": 0.6520995060000132 + }, + "tool_s": { + "median": 0.3578, + "min": 0.349, + "max": 0.3858 + }, + "total_s": { + "median": 1.2678041470007884, + "min": 1.2607823319995077, + "max": 2.088952302000507 + }, + "transport_s": { + "median": 0.0033463020003502877, + "min": 0.0031995060000132194, + "max": 0.0035308160004337455 + }, + "worker_faults": { + "median": 131330, + "min": 131330, + "max": 131332 + }, + "worker_maxrss_mib": { + "median": 1059, + "min": 1059, + "max": 1059 + }, + "write_s": { + "median": 0.0001, + "min": 0.0001, + "max": 0.0001 + } + } + }, + "shm": { + "rows": [ + { + "path": "shm", + "tool": "invert_to_shm", + "shm_create_s": 0.00025295300019934075, + "shm_fill_s": 0.4490946100004294, + "export_s": 0.4493475630006287, + "host_export_faults": 131072, + "task_wall_s": 0.7733160010002393, + "load_s": 0.353, + "tool_s": 0.4174, + "write_s": 0.0001, + "transport_s": 0.0028160010002393657, + "worker_faults": 139521, + "worker_maxrss_mib": 1059, + "result_attach_s": 0.00012443300056474982, + "result_copy_s": 0.20974128499983635, + "result_read_s": 0.2098657180004011, + "cleanup_s": 0.07751800200003345, + "k_nr_written": 0, + "k_pgpgout": 0, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 1.5100472840013026 + }, + { + "path": "shm", + "tool": "invert_to_shm", + "shm_create_s": 9.292800041293958e-05, + "shm_fill_s": 0.4177970640002968, + "export_s": 0.41788999200070975, + "host_export_faults": 131072, + "task_wall_s": 0.5851098579996687, + "load_s": 0.2105, + "tool_s": 0.3715, + "write_s": 0.0001, + "transport_s": 0.0030098579996687305, + "worker_faults": 139521, + "worker_maxrss_mib": 1059, + "result_attach_s": 0.00013893100003770087, + "result_copy_s": 0.24247879700033081, + "result_read_s": 0.24261772800036852, + "cleanup_s": 0.07755790800001705, + "k_nr_written": 7, + "k_pgpgout": 28, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 1.323175486000764 + }, + { + "path": "shm", + "tool": "invert_to_shm", + "shm_create_s": 8.734299990464933e-05, + "shm_fill_s": 0.41301136699985364, + "export_s": 0.4130987099997583, + "host_export_faults": 131072, + "task_wall_s": 0.6856555409995053, + "load_s": 0.2585, + "tool_s": 0.4236, + "write_s": 0.0001, + "transport_s": 0.0034555409995053357, + "worker_faults": 139521, + "worker_maxrss_mib": 1059, + "result_attach_s": 0.0001279640000575455, + "result_copy_s": 0.21067199499975686, + "result_read_s": 0.2107999589998144, + "cleanup_s": 0.1176344870000321, + "k_nr_written": 342, + "k_pgpgout": 1368, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 1.42718869699911 + } + ], + "summary": { + "cleanup_s": { + "median": 0.07755790800001705, + "min": 0.07751800200003345, + "max": 0.1176344870000321 + }, + "export_s": { + "median": 0.41788999200070975, + "min": 0.4130987099997583, + "max": 0.4493475630006287 + }, + "host_export_faults": { + "median": 131072, + "min": 131072, + "max": 131072 + }, + "k_allocstall_normal": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_nr_written": { + "median": 7, + "min": 0, + "max": 342 + }, + "k_pgpgout": { + "median": 28, + "min": 0, + "max": 1368 + }, + "k_pgscan_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgscan_kswapd": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgsteal_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_psi_some_us": { + "median": 0, + "min": 0, + "max": 0 + }, + "load_s": { + "median": 0.2585, + "min": 0.2105, + "max": 0.353 + }, + "result_attach_s": { + "median": 0.0001279640000575455, + "min": 0.00012443300056474982, + "max": 0.00013893100003770087 + }, + "result_copy_s": { + "median": 0.21067199499975686, + "min": 0.20974128499983635, + "max": 0.24247879700033081 + }, + "result_read_s": { + "median": 0.2107999589998144, + "min": 0.2098657180004011, + "max": 0.24261772800036852 + }, + "shm_create_s": { + "median": 9.292800041293958e-05, + "min": 8.734299990464933e-05, + "max": 0.00025295300019934075 + }, + "shm_fill_s": { + "median": 0.4177970640002968, + "min": 0.41301136699985364, + "max": 0.4490946100004294 + }, + "task_wall_s": { + "median": 0.6856555409995053, + "min": 0.5851098579996687, + "max": 0.7733160010002393 + }, + "tool_s": { + "median": 0.4174, + "min": 0.3715, + "max": 0.4236 + }, + "total_s": { + "median": 1.42718869699911, + "min": 1.323175486000764, + "max": 1.5100472840013026 + }, + "transport_s": { + "median": 0.0030098579996687305, + "min": 0.0028160010002393657, + "max": 0.0034555409995053357 + }, + "worker_faults": { + "median": 139521, + "min": 139521, + "max": 139521 + }, + "worker_maxrss_mib": { + "median": 1059, + "min": 1059, + "max": 1059 + }, + "write_s": { + "median": 0.0001, + "min": 0.0001, + "max": 0.0001 + } + } + } + } + } + } +} \ No newline at end of file diff --git a/benchmarks/results/sandbox_fiji_java_export.jsonl b/benchmarks/results/sandbox_fiji_java_export.jsonl new file mode 100644 index 0000000..9892c46 --- /dev/null +++ b/benchmarks/results/sandbox_fiji_java_export.jsonl @@ -0,0 +1,12 @@ +{"MiB":128,"tiff_disk_s":0.332,"tiff_read_s":0.350,"shm_to_short_array_s":0.105,"tiff_shmfs_s":0.160,"shm_appose_s":0.089,"shm_mmap_s":0.090} +{"MiB":128,"tiff_disk_s":0.100,"tiff_read_s":0.196,"shm_to_short_array_s":0.100,"tiff_shmfs_s":0.118,"shm_appose_s":0.077,"shm_mmap_s":0.076} +{"MiB":128,"tiff_disk_s":0.098,"tiff_read_s":0.186,"shm_to_short_array_s":0.097,"tiff_shmfs_s":0.109,"shm_appose_s":0.076,"shm_mmap_s":0.076} +{"MiB":512,"tiff_disk_s":2.391,"tiff_read_s":0.914,"shm_to_short_array_s":0.433,"tiff_shmfs_s":0.527,"shm_appose_s":0.323,"shm_mmap_s":0.343} +{"MiB":512,"tiff_disk_s":0.832,"tiff_read_s":0.809,"shm_to_short_array_s":0.393,"tiff_shmfs_s":0.439,"shm_appose_s":0.310,"shm_mmap_s":0.304} +{"MiB":512,"tiff_disk_s":0.478,"tiff_read_s":0.553,"shm_to_short_array_s":0.163,"tiff_shmfs_s":0.437,"shm_appose_s":0.305,"shm_mmap_s":0.319} +{"MiB":512,"tiff_disk_s":2.745,"tiff_read_s":0.916,"shm_to_short_array_s":0.399,"tiff_shmfs_s":0.699,"shm_appose_s":0.416,"shm_mmap_s":0.414} +{"MiB":512,"tiff_disk_s":1.407,"tiff_read_s":0.782,"shm_to_short_array_s":0.367,"tiff_shmfs_s":0.433,"shm_appose_s":0.321,"shm_mmap_s":0.298} +{"MiB":512,"tiff_disk_s":0.393,"tiff_read_s":0.565,"shm_to_short_array_s":0.157,"tiff_shmfs_s":0.430,"shm_appose_s":0.310,"shm_mmap_s":0.317} +{"MiB":512,"tiff_disk_s":1.708,"tiff_read_s":0.930,"shm_to_short_array_s":0.375,"tiff_shmfs_s":0.505,"shm_appose_s":0.338,"shm_mmap_s":0.384} +{"MiB":512,"tiff_disk_s":0.439,"tiff_read_s":0.758,"shm_to_short_array_s":0.385,"tiff_shmfs_s":0.427,"shm_appose_s":0.303,"shm_mmap_s":0.342} +{"MiB":512,"tiff_disk_s":0.396,"tiff_read_s":0.604,"shm_to_short_array_s":0.192,"tiff_shmfs_s":0.437,"shm_appose_s":0.325,"shm_mmap_s":0.310} diff --git a/benchmarks/results/sandbox_prewarm_1024_image_max.json b/benchmarks/results/sandbox_prewarm_1024_image_max.json new file mode 100644 index 0000000..0225299 --- /dev/null +++ b/benchmarks/results/sandbox_prewarm_1024_image_max.json @@ -0,0 +1,366 @@ +{ + "env": { + "python": "3.11.15", + "numpy": "2.4.6", + "tifffile": "2026.3.3", + "cpus": 4, + "scratch": "/home/user/tmp_shm/tmp/lc-shm-bench-8xx3yvpz", + "out_scratch": "/home/user/tmp_shm/tmp/lc-shm-bench-8xx3yvpz", + "cold": false, + "prewarm": 2 + }, + "runs": { + "1024": { + "image_max": { + "disk": { + "rows": [ + { + "path": "disk", + "tool": "image_max", + "export_s": 1.0284729989998596, + "export_fsync_s": 0.9588908999994601, + "host_export_faults": 1, + "task_wall_s": 0.4223197080000318, + "load_s": 0.3415, + "tool_s": 0.0762, + "write_s": 0.0001, + "transport_s": 0.004519708000031794, + "worker_faults": 1877, + "worker_maxrss_mib": 1055, + "cleanup_s": 0.5207951080001294, + "k_nr_written": 263021, + "k_pgpgout": 1052084, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 68, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 74, + "k_psi_some_us": 36685, + "total_s": 1.9715878150000208 + }, + { + "path": "disk", + "tool": "image_max", + "export_s": 2.480064448000121, + "export_fsync_s": 0.6417977159999282, + "host_export_faults": 0, + "task_wall_s": 0.5215460980007265, + "load_s": 0.4325, + "tool_s": 0.0827, + "write_s": 0.0001, + "transport_s": 0.006246098000726496, + "worker_faults": 1016, + "worker_maxrss_mib": 1055, + "cleanup_s": 0.5630859009997948, + "k_nr_written": 262698, + "k_pgpgout": 1050800, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 3.5646964470006424 + }, + { + "path": "disk", + "tool": "image_max", + "export_s": 1.3658968399995501, + "export_fsync_s": 0.7007161159999669, + "host_export_faults": 0, + "task_wall_s": 0.501343248000012, + "load_s": 0.3935, + "tool_s": 0.0856, + "write_s": 0.0001, + "transport_s": 0.022143248000011943, + "worker_faults": 1013, + "worker_maxrss_mib": 1055, + "cleanup_s": 0.6867223059998651, + "k_nr_written": 262304, + "k_pgpgout": 1049224, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 6291, + "total_s": 2.553962393999427 + } + ], + "summary": { + "cleanup_s": { + "median": 0.5630859009997948, + "min": 0.5207951080001294, + "max": 0.6867223059998651 + }, + "export_fsync_s": { + "median": 0.7007161159999669, + "min": 0.6417977159999282, + "max": 0.9588908999994601 + }, + "export_s": { + "median": 1.3658968399995501, + "min": 1.0284729989998596, + "max": 2.480064448000121 + }, + "host_export_faults": { + "median": 0, + "min": 0, + "max": 1 + }, + "k_allocstall_normal": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_nr_written": { + "median": 262698, + "min": 262304, + "max": 263021 + }, + "k_pgpgout": { + "median": 1050800, + "min": 1049224, + "max": 1052084 + }, + "k_pgscan_direct": { + "median": 0, + "min": 0, + "max": 74 + }, + "k_pgscan_kswapd": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgsteal_direct": { + "median": 0, + "min": 0, + "max": 68 + }, + "k_psi_some_us": { + "median": 6291, + "min": 0, + "max": 36685 + }, + "load_s": { + "median": 0.3935, + "min": 0.3415, + "max": 0.4325 + }, + "task_wall_s": { + "median": 0.501343248000012, + "min": 0.4223197080000318, + "max": 0.5215460980007265 + }, + "tool_s": { + "median": 0.0827, + "min": 0.0762, + "max": 0.0856 + }, + "total_s": { + "median": 2.553962393999427, + "min": 1.9715878150000208, + "max": 3.5646964470006424 + }, + "transport_s": { + "median": 0.006246098000726496, + "min": 0.004519708000031794, + "max": 0.022143248000011943 + }, + "worker_faults": { + "median": 1016, + "min": 1013, + "max": 1877 + }, + "worker_maxrss_mib": { + "median": 1055, + "min": 1055, + "max": 1055 + }, + "write_s": { + "median": 0.0001, + "min": 0.0001, + "max": 0.0001 + } + } + }, + "shm": { + "rows": [ + { + "path": "shm", + "tool": "image_max", + "shm_create_s": 0.0008703470002728864, + "shm_fill_s": 0.9189544430000751, + "export_s": 0.919824790000348, + "host_export_faults": 262134, + "task_wall_s": 0.5565328479997333, + "load_s": 0.4589, + "tool_s": 0.092, + "write_s": 0.0001, + "transport_s": 0.0055328479997333755, + "worker_faults": 17705, + "worker_maxrss_mib": 2081, + "cleanup_s": 0.43683848599994235, + "k_nr_written": 0, + "k_pgpgout": 0, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 38116, + "total_s": 1.9131961240000237 + }, + { + "path": "shm", + "tool": "image_max", + "shm_create_s": 0.00011484399965411285, + "shm_fill_s": 0.8914726049997626, + "export_s": 0.8915874489994167, + "host_export_faults": 262134, + "task_wall_s": 0.5618545890001769, + "load_s": 0.432, + "tool_s": 0.1224, + "write_s": 0.0001, + "transport_s": 0.007354589000176939, + "worker_faults": 17398, + "worker_maxrss_mib": 2081, + "cleanup_s": 0.12949653600026068, + "k_nr_written": 0, + "k_pgpgout": 0, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 33626, + "total_s": 1.5829385739998543 + }, + { + "path": "shm", + "tool": "image_max", + "shm_create_s": 0.00011262099997111363, + "shm_fill_s": 0.8483023759999924, + "export_s": 0.8484149969999635, + "host_export_faults": 262134, + "task_wall_s": 0.5395799550005904, + "load_s": 0.4562, + "tool_s": 0.0787, + "write_s": 0.0001, + "transport_s": 0.004579955000590416, + "worker_faults": 17398, + "worker_maxrss_mib": 2081, + "cleanup_s": 0.22229223900012585, + "k_nr_written": 0, + "k_pgpgout": 0, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 13426, + "total_s": 1.6102871910006797 + } + ], + "summary": { + "cleanup_s": { + "median": 0.22229223900012585, + "min": 0.12949653600026068, + "max": 0.43683848599994235 + }, + "export_s": { + "median": 0.8915874489994167, + "min": 0.8484149969999635, + "max": 0.919824790000348 + }, + "host_export_faults": { + "median": 262134, + "min": 262134, + "max": 262134 + }, + "k_allocstall_normal": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_nr_written": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgpgout": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgscan_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgscan_kswapd": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgsteal_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_psi_some_us": { + "median": 33626, + "min": 13426, + "max": 38116 + }, + "load_s": { + "median": 0.4562, + "min": 0.432, + "max": 0.4589 + }, + "shm_create_s": { + "median": 0.00011484399965411285, + "min": 0.00011262099997111363, + "max": 0.0008703470002728864 + }, + "shm_fill_s": { + "median": 0.8914726049997626, + "min": 0.8483023759999924, + "max": 0.9189544430000751 + }, + "task_wall_s": { + "median": 0.5565328479997333, + "min": 0.5395799550005904, + "max": 0.5618545890001769 + }, + "tool_s": { + "median": 0.092, + "min": 0.0787, + "max": 0.1224 + }, + "total_s": { + "median": 1.6102871910006797, + "min": 1.5829385739998543, + "max": 1.9131961240000237 + }, + "transport_s": { + "median": 0.0055328479997333755, + "min": 0.004579955000590416, + "max": 0.007354589000176939 + }, + "worker_faults": { + "median": 17398, + "min": 17398, + "max": 17705 + }, + "worker_maxrss_mib": { + "median": 2081, + "min": 2081, + "max": 2081 + }, + "write_s": { + "median": 0.0001, + "min": 0.0001, + "max": 0.0001 + } + } + } + } + } + } +} \ No newline at end of file diff --git a/benchmarks/results/sandbox_prewarm_128_512.json b/benchmarks/results/sandbox_prewarm_128_512.json new file mode 100644 index 0000000..bf718a4 --- /dev/null +++ b/benchmarks/results/sandbox_prewarm_128_512.json @@ -0,0 +1,2314 @@ +{ + "env": { + "python": "3.11.15", + "numpy": "2.4.6", + "tifffile": "2026.3.3", + "cpus": 4, + "scratch": "/home/user/tmp_shm/tmp/lc-shm-bench-p6izxxdi", + "out_scratch": "/home/user/tmp_shm/tmp/lc-shm-bench-p6izxxdi", + "cold": false, + "prewarm": 2 + }, + "runs": { + "128": { + "image_max": { + "disk": { + "rows": [ + { + "path": "disk", + "tool": "image_max", + "export_s": 0.2125721180000255, + "export_fsync_s": 0.1297139230000539, + "host_export_faults": 2, + "task_wall_s": 0.06594296799994481, + "load_s": 0.0556, + "tool_s": 0.0081, + "write_s": 0.0001, + "transport_s": 0.0021429679999448166, + "worker_faults": 927, + "worker_maxrss_mib": 159, + "cleanup_s": 0.0657371150000472, + "k_nr_written": 32769, + "k_pgpgout": 131100, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.3442522010000175 + }, + { + "path": "disk", + "tool": "image_max", + "export_s": 0.04210666000017227, + "export_fsync_s": 0.1162169740000536, + "host_export_faults": 0, + "task_wall_s": 0.06875989600030152, + "load_s": 0.0578, + "tool_s": 0.0085, + "write_s": 0.0001, + "transport_s": 0.002359896000301526, + "worker_faults": 68, + "worker_maxrss_mib": 159, + "cleanup_s": 0.07369677600036084, + "k_nr_written": 32769, + "k_pgpgout": 131092, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.18456333200083463 + }, + { + "path": "disk", + "tool": "image_max", + "export_s": 0.03050595200056705, + "export_fsync_s": 0.1257499530001951, + "host_export_faults": 0, + "task_wall_s": 0.42376738199982356, + "load_s": 0.4127, + "tool_s": 0.0087, + "write_s": 0.0001, + "transport_s": 0.0022673819998235453, + "worker_faults": 65, + "worker_maxrss_mib": 159, + "cleanup_s": 0.06422027300050104, + "k_nr_written": 32769, + "k_pgpgout": 131092, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.5184936070008916 + } + ], + "summary": { + "cleanup_s": { + "median": 0.0657371150000472, + "min": 0.06422027300050104, + "max": 0.07369677600036084 + }, + "export_fsync_s": { + "median": 0.1257499530001951, + "min": 0.1162169740000536, + "max": 0.1297139230000539 + }, + "export_s": { + "median": 0.04210666000017227, + "min": 0.03050595200056705, + "max": 0.2125721180000255 + }, + "host_export_faults": { + "median": 0, + "min": 0, + "max": 2 + }, + "k_allocstall_normal": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_nr_written": { + "median": 32769, + "min": 32769, + "max": 32769 + }, + "k_pgpgout": { + "median": 131092, + "min": 131092, + "max": 131100 + }, + "k_pgscan_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgscan_kswapd": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgsteal_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_psi_some_us": { + "median": 0, + "min": 0, + "max": 0 + }, + "load_s": { + "median": 0.0578, + "min": 0.0556, + "max": 0.4127 + }, + "task_wall_s": { + "median": 0.06875989600030152, + "min": 0.06594296799994481, + "max": 0.42376738199982356 + }, + "tool_s": { + "median": 0.0085, + "min": 0.0081, + "max": 0.0087 + }, + "total_s": { + "median": 0.3442522010000175, + "min": 0.18456333200083463, + "max": 0.5184936070008916 + }, + "transport_s": { + "median": 0.0022673819998235453, + "min": 0.0021429679999448166, + "max": 0.002359896000301526 + }, + "worker_faults": { + "median": 68, + "min": 65, + "max": 927 + }, + "worker_maxrss_mib": { + "median": 159, + "min": 159, + "max": 159 + }, + "write_s": { + "median": 0.0001, + "min": 0.0001, + "max": 0.0001 + } + } + }, + "shm": { + "rows": [ + { + "path": "shm", + "tool": "image_max", + "shm_create_s": 0.0005622170001515769, + "shm_fill_s": 0.10785552099969209, + "export_s": 0.10841773799984367, + "host_export_faults": 32768, + "task_wall_s": 0.08350324399998499, + "load_s": 0.0735, + "tool_s": 0.0081, + "write_s": 0.0001, + "transport_s": 0.001803243999984993, + "worker_faults": 2402, + "worker_maxrss_mib": 291, + "cleanup_s": 0.03220361900002899, + "k_nr_written": 0, + "k_pgpgout": 0, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.22412460099985765 + }, + { + "path": "shm", + "tool": "image_max", + "shm_create_s": 0.00011283999992883764, + "shm_fill_s": 0.10397530299997015, + "export_s": 0.10408814299989899, + "host_export_faults": 32768, + "task_wall_s": 0.0916405140005736, + "load_s": 0.07, + "tool_s": 0.0189, + "write_s": 0.0001, + "transport_s": 0.0026405140005735963, + "worker_faults": 2114, + "worker_maxrss_mib": 291, + "cleanup_s": 0.030917789999875822, + "k_nr_written": 0, + "k_pgpgout": 0, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.22664644700034842 + }, + { + "path": "shm", + "tool": "image_max", + "shm_create_s": 0.00011513199933688156, + "shm_fill_s": 0.11255369300033635, + "export_s": 0.11266882499967323, + "host_export_faults": 32768, + "task_wall_s": 0.07263152999985323, + "load_s": 0.0601, + "tool_s": 0.0105, + "write_s": 0.0001, + "transport_s": 0.0019315299998532269, + "worker_faults": 2114, + "worker_maxrss_mib": 291, + "cleanup_s": 0.02039513299951068, + "k_nr_written": 0, + "k_pgpgout": 0, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.20569548799903714 + } + ], + "summary": { + "cleanup_s": { + "median": 0.030917789999875822, + "min": 0.02039513299951068, + "max": 0.03220361900002899 + }, + "export_s": { + "median": 0.10841773799984367, + "min": 0.10408814299989899, + "max": 0.11266882499967323 + }, + "host_export_faults": { + "median": 32768, + "min": 32768, + "max": 32768 + }, + "k_allocstall_normal": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_nr_written": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgpgout": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgscan_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgscan_kswapd": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgsteal_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_psi_some_us": { + "median": 0, + "min": 0, + "max": 0 + }, + "load_s": { + "median": 0.07, + "min": 0.0601, + "max": 0.0735 + }, + "shm_create_s": { + "median": 0.00011513199933688156, + "min": 0.00011283999992883764, + "max": 0.0005622170001515769 + }, + "shm_fill_s": { + "median": 0.10785552099969209, + "min": 0.10397530299997015, + "max": 0.11255369300033635 + }, + "task_wall_s": { + "median": 0.08350324399998499, + "min": 0.07263152999985323, + "max": 0.0916405140005736 + }, + "tool_s": { + "median": 0.0105, + "min": 0.0081, + "max": 0.0189 + }, + "total_s": { + "median": 0.22412460099985765, + "min": 0.20569548799903714, + "max": 0.22664644700034842 + }, + "transport_s": { + "median": 0.0019315299998532269, + "min": 0.001803243999984993, + "max": 0.0026405140005735963 + }, + "worker_faults": { + "median": 2114, + "min": 2114, + "max": 2402 + }, + "worker_maxrss_mib": { + "median": 291, + "min": 291, + "max": 291 + }, + "write_s": { + "median": 0.0001, + "min": 0.0001, + "max": 0.0001 + } + } + }, + "cli": { + "rows": [ + { + "path": "cli", + "tool": "image_max", + "export_s": 0.034310989000005065, + "cli_wall_s": 0.850521581999601 + }, + { + "path": "cli", + "tool": "image_max", + "export_s": 0.03440624399991066, + "cli_wall_s": 0.382776866000313 + }, + { + "path": "cli", + "tool": "image_max", + "export_s": 0.03503728799933015, + "cli_wall_s": 0.3581825139999637 + } + ], + "summary": { + "cli_wall_s": { + "median": 0.382776866000313, + "min": 0.3581825139999637, + "max": 0.850521581999601 + }, + "export_s": { + "median": 0.03440624399991066, + "min": 0.034310989000005065, + "max": 0.03503728799933015 + } + } + } + }, + "invert": { + "disk": { + "rows": [ + { + "path": "disk", + "tool": "invert", + "export_s": 0.033251609000217286, + "export_fsync_s": 0.12538313400000334, + "host_export_faults": 0, + "task_wall_s": 1.4938407259996893, + "load_s": 0.4885, + "tool_s": 0.5875, + "write_s": 0.4153, + "transport_s": 0.0025407259996893528, + "worker_faults": 651, + "worker_maxrss_mib": 291, + "result_read_s": 0.040391419000116, + "cleanup_s": 0.06935784399956901, + "k_nr_written": 32769, + "k_pgpgout": 131092, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 1.6368415979995916 + }, + { + "path": "disk", + "tool": "invert", + "export_s": 0.03429184000015084, + "export_fsync_s": 0.12365854299969214, + "host_export_faults": 0, + "task_wall_s": 0.17692666800030565, + "load_s": 0.0685, + "tool_s": 0.0475, + "write_s": 0.057, + "transport_s": 0.003926668000305646, + "worker_faults": 643, + "worker_maxrss_mib": 291, + "result_read_s": 0.04131818200039561, + "cleanup_s": 0.0682677650002006, + "k_nr_written": 32769, + "k_pgpgout": 131092, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.3208044550010527 + }, + { + "path": "disk", + "tool": "invert", + "export_s": 0.031726584000352887, + "export_fsync_s": 0.13891009200051485, + "host_export_faults": 1, + "task_wall_s": 0.2631992770002398, + "load_s": 0.051, + "tool_s": 0.0478, + "write_s": 0.1617, + "transport_s": 0.002699277000239808, + "worker_faults": 642, + "worker_maxrss_mib": 291, + "result_read_s": 0.05172752100042999, + "cleanup_s": 0.07293445600043924, + "k_nr_written": 32769, + "k_pgpgout": 131092, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.41958783800146193 + } + ], + "summary": { + "cleanup_s": { + "median": 0.06935784399956901, + "min": 0.0682677650002006, + "max": 0.07293445600043924 + }, + "export_fsync_s": { + "median": 0.12538313400000334, + "min": 0.12365854299969214, + "max": 0.13891009200051485 + }, + "export_s": { + "median": 0.033251609000217286, + "min": 0.031726584000352887, + "max": 0.03429184000015084 + }, + "host_export_faults": { + "median": 0, + "min": 0, + "max": 1 + }, + "k_allocstall_normal": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_nr_written": { + "median": 32769, + "min": 32769, + "max": 32769 + }, + "k_pgpgout": { + "median": 131092, + "min": 131092, + "max": 131092 + }, + "k_pgscan_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgscan_kswapd": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgsteal_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_psi_some_us": { + "median": 0, + "min": 0, + "max": 0 + }, + "load_s": { + "median": 0.0685, + "min": 0.051, + "max": 0.4885 + }, + "result_read_s": { + "median": 0.04131818200039561, + "min": 0.040391419000116, + "max": 0.05172752100042999 + }, + "task_wall_s": { + "median": 0.2631992770002398, + "min": 0.17692666800030565, + "max": 1.4938407259996893 + }, + "tool_s": { + "median": 0.0478, + "min": 0.0475, + "max": 0.5875 + }, + "total_s": { + "median": 0.41958783800146193, + "min": 0.3208044550010527, + "max": 1.6368415979995916 + }, + "transport_s": { + "median": 0.002699277000239808, + "min": 0.0025407259996893528, + "max": 0.003926668000305646 + }, + "worker_faults": { + "median": 643, + "min": 642, + "max": 651 + }, + "worker_maxrss_mib": { + "median": 291, + "min": 291, + "max": 291 + }, + "write_s": { + "median": 0.1617, + "min": 0.057, + "max": 0.4153 + } + } + }, + "shm": { + "rows": [ + { + "path": "shm", + "tool": "invert", + "shm_create_s": 0.00011386599999241298, + "shm_fill_s": 0.10769614499986346, + "export_s": 0.10781001099985588, + "host_export_faults": 32768, + "task_wall_s": 0.1274250819997178, + "load_s": 0.054, + "tool_s": 0.037, + "write_s": 0.034, + "transport_s": 0.002425081999717811, + "worker_faults": 2690, + "worker_maxrss_mib": 291, + "result_read_s": 0.03935305199956929, + "cleanup_s": 0.02941239699975995, + "k_nr_written": 0, + "k_pgpgout": 0, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.3040005419989029 + }, + { + "path": "shm", + "tool": "invert", + "shm_create_s": 0.00012013800005661324, + "shm_fill_s": 0.12800430999959644, + "export_s": 0.12812444799965306, + "host_export_faults": 32768, + "task_wall_s": 0.6605489029998353, + "load_s": 0.0624, + "tool_s": 0.0474, + "write_s": 0.5481, + "transport_s": 0.002648902999835223, + "worker_faults": 2689, + "worker_maxrss_mib": 291, + "result_read_s": 0.04524896000020817, + "cleanup_s": 0.03223841300041386, + "k_nr_written": 0, + "k_pgpgout": 0, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.8661607240001103 + }, + { + "path": "shm", + "tool": "invert", + "shm_create_s": 0.00011451200043666176, + "shm_fill_s": 0.14864918300008867, + "export_s": 0.14876369500052533, + "host_export_faults": 32768, + "task_wall_s": 0.4892250379998586, + "load_s": 0.0558, + "tool_s": 0.0493, + "write_s": 0.3744, + "transport_s": 0.009725037999858577, + "worker_faults": 2690, + "worker_maxrss_mib": 291, + "result_read_s": 0.046984992000034254, + "cleanup_s": 0.03224322599999141, + "k_nr_written": 0, + "k_pgpgout": 0, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.7172169510004096 + } + ], + "summary": { + "cleanup_s": { + "median": 0.03223841300041386, + "min": 0.02941239699975995, + "max": 0.03224322599999141 + }, + "export_s": { + "median": 0.12812444799965306, + "min": 0.10781001099985588, + "max": 0.14876369500052533 + }, + "host_export_faults": { + "median": 32768, + "min": 32768, + "max": 32768 + }, + "k_allocstall_normal": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_nr_written": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgpgout": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgscan_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgscan_kswapd": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgsteal_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_psi_some_us": { + "median": 0, + "min": 0, + "max": 0 + }, + "load_s": { + "median": 0.0558, + "min": 0.054, + "max": 0.0624 + }, + "result_read_s": { + "median": 0.04524896000020817, + "min": 0.03935305199956929, + "max": 0.046984992000034254 + }, + "shm_create_s": { + "median": 0.00011451200043666176, + "min": 0.00011386599999241298, + "max": 0.00012013800005661324 + }, + "shm_fill_s": { + "median": 0.12800430999959644, + "min": 0.10769614499986346, + "max": 0.14864918300008867 + }, + "task_wall_s": { + "median": 0.4892250379998586, + "min": 0.1274250819997178, + "max": 0.6605489029998353 + }, + "tool_s": { + "median": 0.0474, + "min": 0.037, + "max": 0.0493 + }, + "total_s": { + "median": 0.7172169510004096, + "min": 0.3040005419989029, + "max": 0.8661607240001103 + }, + "transport_s": { + "median": 0.002648902999835223, + "min": 0.002425081999717811, + "max": 0.009725037999858577 + }, + "worker_faults": { + "median": 2690, + "min": 2689, + "max": 2690 + }, + "worker_maxrss_mib": { + "median": 291, + "min": 291, + "max": 291 + }, + "write_s": { + "median": 0.3744, + "min": 0.034, + "max": 0.5481 + } + } + } + }, + "invert_to_shm": { + "disk": { + "rows": [ + { + "path": "disk", + "tool": "invert_to_shm", + "export_s": 0.03458827700069378, + "export_fsync_s": 0.20837880900035088, + "host_export_faults": 1, + "task_wall_s": 0.16472875900035433, + "load_s": 0.0489, + "tool_s": 0.1137, + "write_s": 0.0001, + "transport_s": 0.0020287590003543357, + "worker_faults": 32834, + "worker_maxrss_mib": 291, + "result_attach_s": 0.00017237799966096645, + "result_copy_s": 0.05188357299994095, + "result_read_s": 0.05205595099960192, + "cleanup_s": 0.06982928199977323, + "k_nr_written": 32769, + "k_pgpgout": 131092, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.32120226900042326 + }, + { + "path": "disk", + "tool": "invert_to_shm", + "export_s": 0.04533916600030352, + "export_fsync_s": 0.19146455000009155, + "host_export_faults": 0, + "task_wall_s": 0.1317177509999965, + "load_s": 0.0396, + "tool_s": 0.09, + "write_s": 0.0001, + "transport_s": 0.002017750999996504, + "worker_faults": 32835, + "worker_maxrss_mib": 291, + "result_attach_s": 0.00015295299999706913, + "result_copy_s": 0.04490199900010339, + "result_read_s": 0.04505495200010046, + "cleanup_s": 0.06169028200019966, + "k_nr_written": 32769, + "k_pgpgout": 131092, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.28380215100060013 + }, + { + "path": "disk", + "tool": "invert_to_shm", + "export_s": 0.03605508900000132, + "export_fsync_s": 0.11580424100066011, + "host_export_faults": 0, + "task_wall_s": 0.1557798300000286, + "load_s": 0.0387, + "tool_s": 0.1152, + "write_s": 0.0001, + "transport_s": 0.001779830000028601, + "worker_faults": 32834, + "worker_maxrss_mib": 291, + "result_attach_s": 0.00017894699976750417, + "result_copy_s": 0.05700627900023392, + "result_read_s": 0.05718522600000142, + "cleanup_s": 0.08900765599992155, + "k_nr_written": 32769, + "k_pgpgout": 131092, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.3380278009999529 + } + ], + "summary": { + "cleanup_s": { + "median": 0.06982928199977323, + "min": 0.06169028200019966, + "max": 0.08900765599992155 + }, + "export_fsync_s": { + "median": 0.19146455000009155, + "min": 0.11580424100066011, + "max": 0.20837880900035088 + }, + "export_s": { + "median": 0.03605508900000132, + "min": 0.03458827700069378, + "max": 0.04533916600030352 + }, + "host_export_faults": { + "median": 0, + "min": 0, + "max": 1 + }, + "k_allocstall_normal": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_nr_written": { + "median": 32769, + "min": 32769, + "max": 32769 + }, + "k_pgpgout": { + "median": 131092, + "min": 131092, + "max": 131092 + }, + "k_pgscan_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgscan_kswapd": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgsteal_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_psi_some_us": { + "median": 0, + "min": 0, + "max": 0 + }, + "load_s": { + "median": 0.0396, + "min": 0.0387, + "max": 0.0489 + }, + "result_attach_s": { + "median": 0.00017237799966096645, + "min": 0.00015295299999706913, + "max": 0.00017894699976750417 + }, + "result_copy_s": { + "median": 0.05188357299994095, + "min": 0.04490199900010339, + "max": 0.05700627900023392 + }, + "result_read_s": { + "median": 0.05205595099960192, + "min": 0.04505495200010046, + "max": 0.05718522600000142 + }, + "task_wall_s": { + "median": 0.1557798300000286, + "min": 0.1317177509999965, + "max": 0.16472875900035433 + }, + "tool_s": { + "median": 0.1137, + "min": 0.09, + "max": 0.1152 + }, + "total_s": { + "median": 0.32120226900042326, + "min": 0.28380215100060013, + "max": 0.3380278009999529 + }, + "transport_s": { + "median": 0.002017750999996504, + "min": 0.001779830000028601, + "max": 0.0020287590003543357 + }, + "worker_faults": { + "median": 32834, + "min": 32834, + "max": 32835 + }, + "worker_maxrss_mib": { + "median": 291, + "min": 291, + "max": 291 + }, + "write_s": { + "median": 0.0001, + "min": 0.0001, + "max": 0.0001 + } + } + }, + "shm": { + "rows": [ + { + "path": "shm", + "tool": "invert_to_shm", + "shm_create_s": 0.0001430930005881237, + "shm_fill_s": 0.10925349900026049, + "export_s": 0.10939659200084861, + "host_export_faults": 32768, + "task_wall_s": 0.20865021299960063, + "load_s": 0.0687, + "tool_s": 0.1366, + "write_s": 0.0001, + "transport_s": 0.0032502129996006437, + "worker_faults": 34881, + "worker_maxrss_mib": 291, + "result_attach_s": 0.00018390600052953232, + "result_copy_s": 0.06011599199973716, + "result_read_s": 0.060299898000266694, + "cleanup_s": 0.01985899999999674, + "k_nr_written": 0, + "k_pgpgout": 0, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.3982057030007127 + }, + { + "path": "shm", + "tool": "invert_to_shm", + "shm_create_s": 0.00011213299967494095, + "shm_fill_s": 0.1011766509991503, + "export_s": 0.10128878399882524, + "host_export_faults": 32768, + "task_wall_s": 0.13948026100024435, + "load_s": 0.053, + "tool_s": 0.0845, + "write_s": 0.0001, + "transport_s": 0.001880261000244357, + "worker_faults": 34881, + "worker_maxrss_mib": 291, + "result_attach_s": 0.00016109300031530438, + "result_copy_s": 0.04446367000036844, + "result_read_s": 0.04462476300068374, + "cleanup_s": 0.024030006999964826, + "k_nr_written": 262, + "k_pgpgout": 988, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.30942381499971816 + }, + { + "path": "shm", + "tool": "invert_to_shm", + "shm_create_s": 0.00016054400020948378, + "shm_fill_s": 0.10764521599958243, + "export_s": 0.10780575999979192, + "host_export_faults": 32768, + "task_wall_s": 0.1437791879998258, + "load_s": 0.0526, + "tool_s": 0.0885, + "write_s": 0.0001, + "transport_s": 0.002579187999825805, + "worker_faults": 34882, + "worker_maxrss_mib": 291, + "result_attach_s": 0.00018830099998012884, + "result_copy_s": 0.04265331900023739, + "result_read_s": 0.04284162000021752, + "cleanup_s": 0.030977262999840605, + "k_nr_written": 0, + "k_pgpgout": 0, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.32540383099967585 + } + ], + "summary": { + "cleanup_s": { + "median": 0.024030006999964826, + "min": 0.01985899999999674, + "max": 0.030977262999840605 + }, + "export_s": { + "median": 0.10780575999979192, + "min": 0.10128878399882524, + "max": 0.10939659200084861 + }, + "host_export_faults": { + "median": 32768, + "min": 32768, + "max": 32768 + }, + "k_allocstall_normal": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_nr_written": { + "median": 0, + "min": 0, + "max": 262 + }, + "k_pgpgout": { + "median": 0, + "min": 0, + "max": 988 + }, + "k_pgscan_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgscan_kswapd": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgsteal_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_psi_some_us": { + "median": 0, + "min": 0, + "max": 0 + }, + "load_s": { + "median": 0.053, + "min": 0.0526, + "max": 0.0687 + }, + "result_attach_s": { + "median": 0.00018390600052953232, + "min": 0.00016109300031530438, + "max": 0.00018830099998012884 + }, + "result_copy_s": { + "median": 0.04446367000036844, + "min": 0.04265331900023739, + "max": 0.06011599199973716 + }, + "result_read_s": { + "median": 0.04462476300068374, + "min": 0.04284162000021752, + "max": 0.060299898000266694 + }, + "shm_create_s": { + "median": 0.0001430930005881237, + "min": 0.00011213299967494095, + "max": 0.00016054400020948378 + }, + "shm_fill_s": { + "median": 0.10764521599958243, + "min": 0.1011766509991503, + "max": 0.10925349900026049 + }, + "task_wall_s": { + "median": 0.1437791879998258, + "min": 0.13948026100024435, + "max": 0.20865021299960063 + }, + "tool_s": { + "median": 0.0885, + "min": 0.0845, + "max": 0.1366 + }, + "total_s": { + "median": 0.32540383099967585, + "min": 0.30942381499971816, + "max": 0.3982057030007127 + }, + "transport_s": { + "median": 0.002579187999825805, + "min": 0.001880261000244357, + "max": 0.0032502129996006437 + }, + "worker_faults": { + "median": 34881, + "min": 34881, + "max": 34882 + }, + "worker_maxrss_mib": { + "median": 291, + "min": 291, + "max": 291 + }, + "write_s": { + "median": 0.0001, + "min": 0.0001, + "max": 0.0001 + } + } + } + } + }, + "512": { + "image_max": { + "disk": { + "rows": [ + { + "path": "disk", + "tool": "image_max", + "export_s": 0.1411465640003371, + "export_fsync_s": 0.4141554500001803, + "host_export_faults": 0, + "task_wall_s": 0.215396323999812, + "load_s": 0.1771, + "tool_s": 0.0352, + "write_s": 0.0001, + "transport_s": 0.0029963239998120022, + "worker_faults": 258, + "worker_maxrss_mib": 547, + "cleanup_s": 0.24998944900016795, + "k_nr_written": 131076, + "k_pgpgout": 524324, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.6065323370003171 + }, + { + "path": "disk", + "tool": "image_max", + "export_s": 0.13988099800008058, + "export_fsync_s": 0.428360320000138, + "host_export_faults": 0, + "task_wall_s": 0.24632236999968882, + "load_s": 0.1984, + "tool_s": 0.0447, + "write_s": 0.0001, + "transport_s": 0.0031223699996888277, + "worker_faults": 257, + "worker_maxrss_mib": 547, + "cleanup_s": 0.3934259709994876, + "k_nr_written": 131075, + "k_pgpgout": 524320, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.779629338999257 + }, + { + "path": "disk", + "tool": "image_max", + "export_s": 0.13557724700058316, + "export_fsync_s": 0.4967937339997661, + "host_export_faults": 0, + "task_wall_s": 0.2524048639998, + "load_s": 0.214, + "tool_s": 0.0351, + "write_s": 0.0001, + "transport_s": 0.003204863999800005, + "worker_faults": 257, + "worker_maxrss_mib": 547, + "cleanup_s": 0.2564752589996715, + "k_nr_written": 131078, + "k_pgpgout": 524328, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.6444573700000547 + } + ], + "summary": { + "cleanup_s": { + "median": 0.2564752589996715, + "min": 0.24998944900016795, + "max": 0.3934259709994876 + }, + "export_fsync_s": { + "median": 0.428360320000138, + "min": 0.4141554500001803, + "max": 0.4967937339997661 + }, + "export_s": { + "median": 0.13988099800008058, + "min": 0.13557724700058316, + "max": 0.1411465640003371 + }, + "host_export_faults": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_allocstall_normal": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_nr_written": { + "median": 131076, + "min": 131075, + "max": 131078 + }, + "k_pgpgout": { + "median": 524324, + "min": 524320, + "max": 524328 + }, + "k_pgscan_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgscan_kswapd": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgsteal_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_psi_some_us": { + "median": 0, + "min": 0, + "max": 0 + }, + "load_s": { + "median": 0.1984, + "min": 0.1771, + "max": 0.214 + }, + "task_wall_s": { + "median": 0.24632236999968882, + "min": 0.215396323999812, + "max": 0.2524048639998 + }, + "tool_s": { + "median": 0.0352, + "min": 0.0351, + "max": 0.0447 + }, + "total_s": { + "median": 0.6444573700000547, + "min": 0.6065323370003171, + "max": 0.779629338999257 + }, + "transport_s": { + "median": 0.0031223699996888277, + "min": 0.0029963239998120022, + "max": 0.003204863999800005 + }, + "worker_faults": { + "median": 257, + "min": 257, + "max": 258 + }, + "worker_maxrss_mib": { + "median": 547, + "min": 547, + "max": 547 + }, + "write_s": { + "median": 0.0001, + "min": 0.0001, + "max": 0.0001 + } + } + }, + "shm": { + "rows": [ + { + "path": "shm", + "tool": "image_max", + "shm_create_s": 0.00010942399967461824, + "shm_fill_s": 0.4194858689998, + "export_s": 0.4195952929994746, + "host_export_faults": 131072, + "task_wall_s": 0.25100816099984513, + "load_s": 0.2105, + "tool_s": 0.0374, + "write_s": 0.0001, + "transport_s": 0.003008160999845136, + "worker_faults": 8449, + "worker_maxrss_mib": 1059, + "cleanup_s": 0.0790782140002193, + "k_nr_written": 0, + "k_pgpgout": 0, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.7496816679995391 + }, + { + "path": "shm", + "tool": "image_max", + "shm_create_s": 0.00012208799944346538, + "shm_fill_s": 0.45146386199940025, + "export_s": 0.4515859499988437, + "host_export_faults": 131072, + "task_wall_s": 0.9336723779997556, + "load_s": 0.8866, + "tool_s": 0.0438, + "write_s": 0.0001, + "transport_s": 0.0031723779997555007, + "worker_faults": 8449, + "worker_maxrss_mib": 1059, + "cleanup_s": 0.11455120899972826, + "k_nr_written": 0, + "k_pgpgout": 0, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 1.4998095369983275 + }, + { + "path": "shm", + "tool": "image_max", + "shm_create_s": 0.00011255400022491813, + "shm_fill_s": 0.440267945999949, + "export_s": 0.4403805000001739, + "host_export_faults": 131072, + "task_wall_s": 0.24348199899941392, + "load_s": 0.2056, + "tool_s": 0.0346, + "write_s": 0.0001, + "transport_s": 0.003181998999413914, + "worker_faults": 8449, + "worker_maxrss_mib": 1059, + "cleanup_s": 0.06959383899993554, + "k_nr_written": 0, + "k_pgpgout": 0, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.7534563379995234 + } + ], + "summary": { + "cleanup_s": { + "median": 0.0790782140002193, + "min": 0.06959383899993554, + "max": 0.11455120899972826 + }, + "export_s": { + "median": 0.4403805000001739, + "min": 0.4195952929994746, + "max": 0.4515859499988437 + }, + "host_export_faults": { + "median": 131072, + "min": 131072, + "max": 131072 + }, + "k_allocstall_normal": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_nr_written": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgpgout": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgscan_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgscan_kswapd": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgsteal_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_psi_some_us": { + "median": 0, + "min": 0, + "max": 0 + }, + "load_s": { + "median": 0.2105, + "min": 0.2056, + "max": 0.8866 + }, + "shm_create_s": { + "median": 0.00011255400022491813, + "min": 0.00010942399967461824, + "max": 0.00012208799944346538 + }, + "shm_fill_s": { + "median": 0.440267945999949, + "min": 0.4194858689998, + "max": 0.45146386199940025 + }, + "task_wall_s": { + "median": 0.25100816099984513, + "min": 0.24348199899941392, + "max": 0.9336723779997556 + }, + "tool_s": { + "median": 0.0374, + "min": 0.0346, + "max": 0.0438 + }, + "total_s": { + "median": 0.7534563379995234, + "min": 0.7496816679995391, + "max": 1.4998095369983275 + }, + "transport_s": { + "median": 0.0031723779997555007, + "min": 0.003008160999845136, + "max": 0.003181998999413914 + }, + "worker_faults": { + "median": 8449, + "min": 8449, + "max": 8449 + }, + "worker_maxrss_mib": { + "median": 1059, + "min": 1059, + "max": 1059 + }, + "write_s": { + "median": 0.0001, + "min": 0.0001, + "max": 0.0001 + } + } + }, + "cli": { + "rows": [ + { + "path": "cli", + "tool": "image_max", + "export_s": 0.12224076399979822, + "cli_wall_s": 2.796873432999746 + }, + { + "path": "cli", + "tool": "image_max", + "export_s": 0.13489822199971968, + "cli_wall_s": 0.5483289730000251 + }, + { + "path": "cli", + "tool": "image_max", + "export_s": 0.1977381400001832, + "cli_wall_s": 0.5436285099995075 + } + ], + "summary": { + "cli_wall_s": { + "median": 0.5483289730000251, + "min": 0.5436285099995075, + "max": 2.796873432999746 + }, + "export_s": { + "median": 0.13489822199971968, + "min": 0.12224076399979822, + "max": 0.1977381400001832 + } + } + } + }, + "invert": { + "disk": { + "rows": [ + { + "path": "disk", + "tool": "invert", + "export_s": 0.1207257739997658, + "export_fsync_s": 0.40106455800014373, + "host_export_faults": 0, + "task_wall_s": 3.1922183970000333, + "load_s": 0.1565, + "tool_s": 0.1701, + "write_s": 2.8608, + "transport_s": 0.004818397000033503, + "worker_faults": 1025, + "worker_maxrss_mib": 1059, + "result_read_s": 0.1638675840003998, + "cleanup_s": 0.3142993709998336, + "k_nr_written": 131226, + "k_pgpgout": 524900, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 3.7911111260000325 + }, + { + "path": "disk", + "tool": "invert", + "export_s": 0.14227091900011146, + "export_fsync_s": 0.42791872399993736, + "host_export_faults": 0, + "task_wall_s": 1.3479691090005872, + "load_s": 0.1848, + "tool_s": 0.165, + "write_s": 0.9938, + "transport_s": 0.004369109000587068, + "worker_faults": 1025, + "worker_maxrss_mib": 1059, + "result_read_s": 0.15723483400051919, + "cleanup_s": 0.3016918909997912, + "k_nr_written": 131077, + "k_pgpgout": 524328, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 1.949166753001009 + }, + { + "path": "disk", + "tool": "invert", + "export_s": 0.14719489799972507, + "export_fsync_s": 0.41179039500002546, + "host_export_faults": 0, + "task_wall_s": 1.2195302870004525, + "load_s": 0.1836, + "tool_s": 0.1643, + "write_s": 0.8658, + "transport_s": 0.0058302870004525165, + "worker_faults": 1025, + "worker_maxrss_mib": 1059, + "result_read_s": 0.17326400100046158, + "cleanup_s": 0.32047864500054857, + "k_nr_written": 131075, + "k_pgpgout": 524320, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 1.8604678310011877 + } + ], + "summary": { + "cleanup_s": { + "median": 0.3142993709998336, + "min": 0.3016918909997912, + "max": 0.32047864500054857 + }, + "export_fsync_s": { + "median": 0.41179039500002546, + "min": 0.40106455800014373, + "max": 0.42791872399993736 + }, + "export_s": { + "median": 0.14227091900011146, + "min": 0.1207257739997658, + "max": 0.14719489799972507 + }, + "host_export_faults": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_allocstall_normal": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_nr_written": { + "median": 131077, + "min": 131075, + "max": 131226 + }, + "k_pgpgout": { + "median": 524328, + "min": 524320, + "max": 524900 + }, + "k_pgscan_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgscan_kswapd": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgsteal_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_psi_some_us": { + "median": 0, + "min": 0, + "max": 0 + }, + "load_s": { + "median": 0.1836, + "min": 0.1565, + "max": 0.1848 + }, + "result_read_s": { + "median": 0.1638675840003998, + "min": 0.15723483400051919, + "max": 0.17326400100046158 + }, + "task_wall_s": { + "median": 1.3479691090005872, + "min": 1.2195302870004525, + "max": 3.1922183970000333 + }, + "tool_s": { + "median": 0.165, + "min": 0.1643, + "max": 0.1701 + }, + "total_s": { + "median": 1.949166753001009, + "min": 1.8604678310011877, + "max": 3.7911111260000325 + }, + "transport_s": { + "median": 0.004818397000033503, + "min": 0.004369109000587068, + "max": 0.0058302870004525165 + }, + "worker_faults": { + "median": 1025, + "min": 1025, + "max": 1025 + }, + "worker_maxrss_mib": { + "median": 1059, + "min": 1059, + "max": 1059 + }, + "write_s": { + "median": 0.9938, + "min": 0.8658, + "max": 2.8608 + } + } + }, + "shm": { + "rows": [ + { + "path": "shm", + "tool": "invert", + "shm_create_s": 0.00012304300071264151, + "shm_fill_s": 0.4264009270000315, + "export_s": 0.42652397000074416, + "host_export_faults": 131072, + "task_wall_s": 0.9030682299999171, + "load_s": 0.246, + "tool_s": 0.5302, + "write_s": 0.1221, + "transport_s": 0.004768229999917092, + "worker_faults": 9217, + "worker_maxrss_mib": 1059, + "result_read_s": 0.19405010599984962, + "cleanup_s": 0.12341774199921929, + "k_nr_written": 20662, + "k_pgpgout": 82648, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 1.6470600479997302 + }, + { + "path": "shm", + "tool": "invert", + "shm_create_s": 0.00013715299974137451, + "shm_fill_s": 0.41051108200008457, + "export_s": 0.41064823499982595, + "host_export_faults": 131072, + "task_wall_s": 0.9829408069999772, + "load_s": 0.207, + "tool_s": 0.6422, + "write_s": 0.128, + "transport_s": 0.005740806999977255, + "worker_faults": 9218, + "worker_maxrss_mib": 1059, + "result_read_s": 0.19995787599964387, + "cleanup_s": 0.11760396599947853, + "k_nr_written": 20533, + "k_pgpgout": 82132, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 1.7111508839989256 + }, + { + "path": "shm", + "tool": "invert", + "shm_create_s": 0.00010189899967372185, + "shm_fill_s": 0.42482093799935683, + "export_s": 0.42492283699903055, + "host_export_faults": 131072, + "task_wall_s": 3.35938829800034, + "load_s": 0.6717, + "tool_s": 0.3112, + "write_s": 2.3717, + "transport_s": 0.0047882980003399744, + "worker_faults": 9217, + "worker_maxrss_mib": 1059, + "result_read_s": 0.194331374000285, + "cleanup_s": 0.14117435499974818, + "k_nr_written": 20532, + "k_pgpgout": 82128, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 4.119816863999404 + } + ], + "summary": { + "cleanup_s": { + "median": 0.12341774199921929, + "min": 0.11760396599947853, + "max": 0.14117435499974818 + }, + "export_s": { + "median": 0.42492283699903055, + "min": 0.41064823499982595, + "max": 0.42652397000074416 + }, + "host_export_faults": { + "median": 131072, + "min": 131072, + "max": 131072 + }, + "k_allocstall_normal": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_nr_written": { + "median": 20533, + "min": 20532, + "max": 20662 + }, + "k_pgpgout": { + "median": 82132, + "min": 82128, + "max": 82648 + }, + "k_pgscan_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgscan_kswapd": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgsteal_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_psi_some_us": { + "median": 0, + "min": 0, + "max": 0 + }, + "load_s": { + "median": 0.246, + "min": 0.207, + "max": 0.6717 + }, + "result_read_s": { + "median": 0.194331374000285, + "min": 0.19405010599984962, + "max": 0.19995787599964387 + }, + "shm_create_s": { + "median": 0.00012304300071264151, + "min": 0.00010189899967372185, + "max": 0.00013715299974137451 + }, + "shm_fill_s": { + "median": 0.42482093799935683, + "min": 0.41051108200008457, + "max": 0.4264009270000315 + }, + "task_wall_s": { + "median": 0.9829408069999772, + "min": 0.9030682299999171, + "max": 3.35938829800034 + }, + "tool_s": { + "median": 0.5302, + "min": 0.3112, + "max": 0.6422 + }, + "total_s": { + "median": 1.7111508839989256, + "min": 1.6470600479997302, + "max": 4.119816863999404 + }, + "transport_s": { + "median": 0.0047882980003399744, + "min": 0.004768229999917092, + "max": 0.005740806999977255 + }, + "worker_faults": { + "median": 9217, + "min": 9217, + "max": 9218 + }, + "worker_maxrss_mib": { + "median": 1059, + "min": 1059, + "max": 1059 + }, + "write_s": { + "median": 0.128, + "min": 0.1221, + "max": 2.3717 + } + } + } + }, + "invert_to_shm": { + "disk": { + "rows": [ + { + "path": "disk", + "tool": "invert_to_shm", + "export_s": 0.16421952299970144, + "export_fsync_s": 0.5957818320002843, + "host_export_faults": 1, + "task_wall_s": 0.7053865679999944, + "load_s": 0.2375, + "tool_s": 0.4639, + "write_s": 0.0001, + "transport_s": 0.0038865679999944727, + "worker_faults": 131330, + "worker_maxrss_mib": 1059, + "result_attach_s": 0.0001846450004450162, + "result_copy_s": 0.2620244019999518, + "result_read_s": 0.2622090470003968, + "cleanup_s": 0.29680310000003374, + "k_nr_written": 131073, + "k_pgpgout": 524312, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 1.4286182380001264 + }, + { + "path": "disk", + "tool": "invert_to_shm", + "export_s": 0.13078046899954643, + "export_fsync_s": 0.4262329030007095, + "host_export_faults": 0, + "task_wall_s": 0.5579681039998832, + "load_s": 0.1992, + "tool_s": 0.3557, + "write_s": 0.0001, + "transport_s": 0.002968103999883165, + "worker_faults": 131330, + "worker_maxrss_mib": 1059, + "result_attach_s": 0.00017777300035959342, + "result_copy_s": 0.19363375099965197, + "result_read_s": 0.19381152400001156, + "cleanup_s": 0.24444662899986724, + "k_nr_written": 131077, + "k_pgpgout": 524328, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 1.1270067259993084 + }, + { + "path": "disk", + "tool": "invert_to_shm", + "export_s": 0.12845307299994602, + "export_fsync_s": 0.39602584000022034, + "host_export_faults": 0, + "task_wall_s": 0.5157004259999667, + "load_s": 0.1624, + "tool_s": 0.3502, + "write_s": 0.0001, + "transport_s": 0.003000425999966683, + "worker_faults": 131332, + "worker_maxrss_mib": 1059, + "result_attach_s": 0.00019632200019259471, + "result_copy_s": 0.1973116700000901, + "result_read_s": 0.19750799200028268, + "cleanup_s": 0.26353284400011034, + "k_nr_written": 131073, + "k_pgpgout": 524312, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 1.1051943350003057 + } + ], + "summary": { + "cleanup_s": { + "median": 0.26353284400011034, + "min": 0.24444662899986724, + "max": 0.29680310000003374 + }, + "export_fsync_s": { + "median": 0.4262329030007095, + "min": 0.39602584000022034, + "max": 0.5957818320002843 + }, + "export_s": { + "median": 0.13078046899954643, + "min": 0.12845307299994602, + "max": 0.16421952299970144 + }, + "host_export_faults": { + "median": 0, + "min": 0, + "max": 1 + }, + "k_allocstall_normal": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_nr_written": { + "median": 131073, + "min": 131073, + "max": 131077 + }, + "k_pgpgout": { + "median": 524312, + "min": 524312, + "max": 524328 + }, + "k_pgscan_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgscan_kswapd": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgsteal_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_psi_some_us": { + "median": 0, + "min": 0, + "max": 0 + }, + "load_s": { + "median": 0.1992, + "min": 0.1624, + "max": 0.2375 + }, + "result_attach_s": { + "median": 0.0001846450004450162, + "min": 0.00017777300035959342, + "max": 0.00019632200019259471 + }, + "result_copy_s": { + "median": 0.1973116700000901, + "min": 0.19363375099965197, + "max": 0.2620244019999518 + }, + "result_read_s": { + "median": 0.19750799200028268, + "min": 0.19381152400001156, + "max": 0.2622090470003968 + }, + "task_wall_s": { + "median": 0.5579681039998832, + "min": 0.5157004259999667, + "max": 0.7053865679999944 + }, + "tool_s": { + "median": 0.3557, + "min": 0.3502, + "max": 0.4639 + }, + "total_s": { + "median": 1.1270067259993084, + "min": 1.1051943350003057, + "max": 1.4286182380001264 + }, + "transport_s": { + "median": 0.003000425999966683, + "min": 0.002968103999883165, + "max": 0.0038865679999944727 + }, + "worker_faults": { + "median": 131330, + "min": 131330, + "max": 131332 + }, + "worker_maxrss_mib": { + "median": 1059, + "min": 1059, + "max": 1059 + }, + "write_s": { + "median": 0.0001, + "min": 0.0001, + "max": 0.0001 + } + } + }, + "shm": { + "rows": [ + { + "path": "shm", + "tool": "invert_to_shm", + "shm_create_s": 0.00012005700045847334, + "shm_fill_s": 0.40672034099952725, + "export_s": 0.4068403979999857, + "host_export_faults": 131072, + "task_wall_s": 0.6663341060002494, + "load_s": 0.2904, + "tool_s": 0.3721, + "write_s": 0.0004, + "transport_s": 0.0034341060002494707, + "worker_faults": 139521, + "worker_maxrss_mib": 1059, + "result_attach_s": 0.0001813569997466402, + "result_copy_s": 0.1737807959998463, + "result_read_s": 0.17396215299959294, + "cleanup_s": 0.08811027999945509, + "k_nr_written": 0, + "k_pgpgout": 0, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 1.3352469369992832 + }, + { + "path": "shm", + "tool": "invert_to_shm", + "shm_create_s": 0.0001060089998645708, + "shm_fill_s": 0.42825788099980855, + "export_s": 0.4283638899996731, + "host_export_faults": 131307, + "task_wall_s": 0.6893382649996056, + "load_s": 0.2708, + "tool_s": 0.4156, + "write_s": 0.0001, + "transport_s": 0.002838264999605589, + "worker_faults": 139521, + "worker_maxrss_mib": 1059, + "result_attach_s": 0.0001934080000864924, + "result_copy_s": 0.21261356500053807, + "result_read_s": 0.21280697300062457, + "cleanup_s": 0.07077619299980142, + "k_nr_written": 0, + "k_pgpgout": 0, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 1.4012853209997047 + }, + { + "path": "shm", + "tool": "invert_to_shm", + "shm_create_s": 9.528699956717901e-05, + "shm_fill_s": 0.39801368600001297, + "export_s": 0.39810897299958015, + "host_export_faults": 131072, + "task_wall_s": 0.5296056059996772, + "load_s": 0.2068, + "tool_s": 0.3192, + "write_s": 0.0001, + "transport_s": 0.0035056059996772418, + "worker_faults": 139521, + "worker_maxrss_mib": 1059, + "result_attach_s": 0.0015061720005178358, + "result_copy_s": 0.19309101399994688, + "result_read_s": 0.19459718600046472, + "cleanup_s": 0.07658412300042983, + "k_nr_written": 0, + "k_pgpgout": 0, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 1.198895888000152 + } + ], + "summary": { + "cleanup_s": { + "median": 0.07658412300042983, + "min": 0.07077619299980142, + "max": 0.08811027999945509 + }, + "export_s": { + "median": 0.4068403979999857, + "min": 0.39810897299958015, + "max": 0.4283638899996731 + }, + "host_export_faults": { + "median": 131072, + "min": 131072, + "max": 131307 + }, + "k_allocstall_normal": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_nr_written": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgpgout": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgscan_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgscan_kswapd": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgsteal_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_psi_some_us": { + "median": 0, + "min": 0, + "max": 0 + }, + "load_s": { + "median": 0.2708, + "min": 0.2068, + "max": 0.2904 + }, + "result_attach_s": { + "median": 0.0001934080000864924, + "min": 0.0001813569997466402, + "max": 0.0015061720005178358 + }, + "result_copy_s": { + "median": 0.19309101399994688, + "min": 0.1737807959998463, + "max": 0.21261356500053807 + }, + "result_read_s": { + "median": 0.19459718600046472, + "min": 0.17396215299959294, + "max": 0.21280697300062457 + }, + "shm_create_s": { + "median": 0.0001060089998645708, + "min": 9.528699956717901e-05, + "max": 0.00012005700045847334 + }, + "shm_fill_s": { + "median": 0.40672034099952725, + "min": 0.39801368600001297, + "max": 0.42825788099980855 + }, + "task_wall_s": { + "median": 0.6663341060002494, + "min": 0.5296056059996772, + "max": 0.6893382649996056 + }, + "tool_s": { + "median": 0.3721, + "min": 0.3192, + "max": 0.4156 + }, + "total_s": { + "median": 1.3352469369992832, + "min": 1.198895888000152, + "max": 1.4012853209997047 + }, + "transport_s": { + "median": 0.0034341060002494707, + "min": 0.002838264999605589, + "max": 0.0035056059996772418 + }, + "worker_faults": { + "median": 139521, + "min": 139521, + "max": 139521 + }, + "worker_maxrss_mib": { + "median": 1059, + "min": 1059, + "max": 1059 + }, + "write_s": { + "median": 0.0001, + "min": 0.0001, + "max": 0.0004 + } + } + } + } + } + } +} \ No newline at end of file diff --git a/benchmarks/results/sandbox_prewarm_zero_copy.json b/benchmarks/results/sandbox_prewarm_zero_copy.json new file mode 100644 index 0000000..96b012b --- /dev/null +++ b/benchmarks/results/sandbox_prewarm_zero_copy.json @@ -0,0 +1,738 @@ +{ + "env": { + "python": "3.11.15", + "numpy": "2.4.6", + "tifffile": "2026.3.3", + "cpus": 4, + "scratch": "/home/user/tmp_shm/tmp/lc-shm-bench-s64b6oik", + "out_scratch": "/home/user/tmp_shm/tmp/lc-shm-bench-s64b6oik", + "cold": false, + "prewarm": 2 + }, + "runs": { + "128": { + "view_max": { + "shm": { + "rows": [ + { + "path": "shm", + "tool": "view_max", + "shm_create_s": 0.00044798399903811514, + "shm_fill_s": 0.10152180200020666, + "export_s": 0.10196978599924478, + "host_export_faults": 32768, + "task_wall_s": 0.038635947999864584, + "load_s": 0.0002, + "tool_s": 0.0367, + "write_s": 0.0001, + "transport_s": 0.0016359479998645815, + "worker_faults": 2304, + "worker_maxrss_mib": 160, + "cleanup_s": 0.020598013999915565, + "k_nr_written": 0, + "k_pgpgout": 12, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.16120374799902493 + }, + { + "path": "shm", + "tool": "view_max", + "shm_create_s": 0.000228225000682869, + "shm_fill_s": 0.10900254099942686, + "export_s": 0.10923076600010972, + "host_export_faults": 32768, + "task_wall_s": 0.02694780899946636, + "load_s": 0.0002, + "tool_s": 0.0252, + "write_s": 0.0001, + "transport_s": 0.0014478089994663615, + "worker_faults": 2048, + "worker_maxrss_mib": 160, + "cleanup_s": 0.026113117000932107, + "k_nr_written": 3, + "k_pgpgout": 0, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.1622916920005082 + }, + { + "path": "shm", + "tool": "view_max", + "shm_create_s": 0.00010306799958925694, + "shm_fill_s": 0.10018837000097847, + "export_s": 0.10029143800056772, + "host_export_faults": 32768, + "task_wall_s": 0.033709107998220134, + "load_s": 0.0002, + "tool_s": 0.032, + "write_s": 0.0001, + "transport_s": 0.001409107998220134, + "worker_faults": 2048, + "worker_maxrss_mib": 160, + "cleanup_s": 0.017383558000801713, + "k_nr_written": 0, + "k_pgpgout": 0, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.15138410399958957 + } + ], + "summary": { + "cleanup_s": { + "median": 0.020598013999915565, + "min": 0.017383558000801713, + "max": 0.026113117000932107 + }, + "export_s": { + "median": 0.10196978599924478, + "min": 0.10029143800056772, + "max": 0.10923076600010972 + }, + "host_export_faults": { + "median": 32768, + "min": 32768, + "max": 32768 + }, + "k_allocstall_normal": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_nr_written": { + "median": 0, + "min": 0, + "max": 3 + }, + "k_pgpgout": { + "median": 0, + "min": 0, + "max": 12 + }, + "k_pgscan_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgscan_kswapd": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgsteal_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_psi_some_us": { + "median": 0, + "min": 0, + "max": 0 + }, + "load_s": { + "median": 0.0002, + "min": 0.0002, + "max": 0.0002 + }, + "shm_create_s": { + "median": 0.000228225000682869, + "min": 0.00010306799958925694, + "max": 0.00044798399903811514 + }, + "shm_fill_s": { + "median": 0.10152180200020666, + "min": 0.10018837000097847, + "max": 0.10900254099942686 + }, + "task_wall_s": { + "median": 0.033709107998220134, + "min": 0.02694780899946636, + "max": 0.038635947999864584 + }, + "tool_s": { + "median": 0.032, + "min": 0.0252, + "max": 0.0367 + }, + "total_s": { + "median": 0.16120374799902493, + "min": 0.15138410399958957, + "max": 0.1622916920005082 + }, + "transport_s": { + "median": 0.0014478089994663615, + "min": 0.001409107998220134, + "max": 0.0016359479998645815 + }, + "worker_faults": { + "median": 2048, + "min": 2048, + "max": 2304 + }, + "worker_maxrss_mib": { + "median": 160, + "min": 160, + "max": 160 + }, + "write_s": { + "median": 0.0001, + "min": 0.0001, + "max": 0.0001 + } + } + } + }, + "image_max": { + "shm": { + "rows": [ + { + "path": "shm", + "tool": "image_max", + "shm_create_s": 0.00011328199980198406, + "shm_fill_s": 0.1014408730006835, + "export_s": 0.10155415500048548, + "host_export_faults": 32768, + "task_wall_s": 0.71712946200023, + "load_s": 0.7038, + "tool_s": 0.0111, + "write_s": 0.0001, + "transport_s": 0.0021294620002299965, + "worker_faults": 2116, + "worker_maxrss_mib": 289, + "cleanup_s": 0.019590030000472325, + "k_nr_written": 2, + "k_pgpgout": 8, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.8382736470011878 + }, + { + "path": "shm", + "tool": "image_max", + "shm_create_s": 0.00013325899999472313, + "shm_fill_s": 0.11290607099908812, + "export_s": 0.11303932999908284, + "host_export_faults": 32768, + "task_wall_s": 0.419893330999912, + "load_s": 0.4091, + "tool_s": 0.0089, + "write_s": 0.0001, + "transport_s": 0.0017933309999119764, + "worker_faults": 2113, + "worker_maxrss_mib": 289, + "cleanup_s": 0.025611600000047474, + "k_nr_written": 0, + "k_pgpgout": 4, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.5585442609990423 + }, + { + "path": "shm", + "tool": "image_max", + "shm_create_s": 0.00015294399963750038, + "shm_fill_s": 0.1101433719995839, + "export_s": 0.1102963159992214, + "host_export_faults": 32768, + "task_wall_s": 0.0752851790002751, + "load_s": 0.0641, + "tool_s": 0.0085, + "write_s": 0.0001, + "transport_s": 0.0025851790002750885, + "worker_faults": 2115, + "worker_maxrss_mib": 289, + "cleanup_s": 0.020836288000282366, + "k_nr_written": 0, + "k_pgpgout": 0, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.20641778299977886 + } + ], + "summary": { + "cleanup_s": { + "median": 0.020836288000282366, + "min": 0.019590030000472325, + "max": 0.025611600000047474 + }, + "export_s": { + "median": 0.1102963159992214, + "min": 0.10155415500048548, + "max": 0.11303932999908284 + }, + "host_export_faults": { + "median": 32768, + "min": 32768, + "max": 32768 + }, + "k_allocstall_normal": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_nr_written": { + "median": 0, + "min": 0, + "max": 2 + }, + "k_pgpgout": { + "median": 4, + "min": 0, + "max": 8 + }, + "k_pgscan_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgscan_kswapd": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgsteal_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_psi_some_us": { + "median": 0, + "min": 0, + "max": 0 + }, + "load_s": { + "median": 0.4091, + "min": 0.0641, + "max": 0.7038 + }, + "shm_create_s": { + "median": 0.00013325899999472313, + "min": 0.00011328199980198406, + "max": 0.00015294399963750038 + }, + "shm_fill_s": { + "median": 0.1101433719995839, + "min": 0.1014408730006835, + "max": 0.11290607099908812 + }, + "task_wall_s": { + "median": 0.419893330999912, + "min": 0.0752851790002751, + "max": 0.71712946200023 + }, + "tool_s": { + "median": 0.0089, + "min": 0.0085, + "max": 0.0111 + }, + "total_s": { + "median": 0.5585442609990423, + "min": 0.20641778299977886, + "max": 0.8382736470011878 + }, + "transport_s": { + "median": 0.0021294620002299965, + "min": 0.0017933309999119764, + "max": 0.0025851790002750885 + }, + "worker_faults": { + "median": 2115, + "min": 2113, + "max": 2116 + }, + "worker_maxrss_mib": { + "median": 289, + "min": 289, + "max": 289 + }, + "write_s": { + "median": 0.0001, + "min": 0.0001, + "max": 0.0001 + } + } + } + } + }, + "512": { + "view_max": { + "shm": { + "rows": [ + { + "path": "shm", + "tool": "view_max", + "shm_create_s": 0.00011828700007754378, + "shm_fill_s": 0.44878298999901745, + "export_s": 0.448901276999095, + "host_export_faults": 131072, + "task_wall_s": 0.08035967700016045, + "load_s": 0.0001, + "tool_s": 0.0788, + "write_s": 0.0001, + "transport_s": 0.0013596770001604475, + "worker_faults": 8192, + "worker_maxrss_mib": 545, + "cleanup_s": 0.08264743499967153, + "k_nr_written": 0, + "k_pgpgout": 0, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.611908388998927 + }, + { + "path": "shm", + "tool": "view_max", + "shm_create_s": 0.0001103470003727125, + "shm_fill_s": 0.39821787099936046, + "export_s": 0.39832821799973317, + "host_export_faults": 131072, + "task_wall_s": 0.09466356400116638, + "load_s": 0.0002, + "tool_s": 0.0928, + "write_s": 0.0001, + "transport_s": 0.0015635640011663788, + "worker_faults": 8192, + "worker_maxrss_mib": 545, + "cleanup_s": 0.11019318000035128, + "k_nr_written": 176, + "k_pgpgout": 704, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.6031849620012508 + }, + { + "path": "shm", + "tool": "view_max", + "shm_create_s": 0.00011411699961172417, + "shm_fill_s": 0.414911788999234, + "export_s": 0.4150259059988457, + "host_export_faults": 131072, + "task_wall_s": 0.08719475900034013, + "load_s": 0.0001, + "tool_s": 0.0855, + "write_s": 0.0001, + "transport_s": 0.001494759000340118, + "worker_faults": 8192, + "worker_maxrss_mib": 545, + "cleanup_s": 0.09082825899895397, + "k_nr_written": 2, + "k_pgpgout": 8, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.5930489239981398 + } + ], + "summary": { + "cleanup_s": { + "median": 0.09082825899895397, + "min": 0.08264743499967153, + "max": 0.11019318000035128 + }, + "export_s": { + "median": 0.4150259059988457, + "min": 0.39832821799973317, + "max": 0.448901276999095 + }, + "host_export_faults": { + "median": 131072, + "min": 131072, + "max": 131072 + }, + "k_allocstall_normal": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_nr_written": { + "median": 2, + "min": 0, + "max": 176 + }, + "k_pgpgout": { + "median": 8, + "min": 0, + "max": 704 + }, + "k_pgscan_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgscan_kswapd": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgsteal_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_psi_some_us": { + "median": 0, + "min": 0, + "max": 0 + }, + "load_s": { + "median": 0.0001, + "min": 0.0001, + "max": 0.0002 + }, + "shm_create_s": { + "median": 0.00011411699961172417, + "min": 0.0001103470003727125, + "max": 0.00011828700007754378 + }, + "shm_fill_s": { + "median": 0.414911788999234, + "min": 0.39821787099936046, + "max": 0.44878298999901745 + }, + "task_wall_s": { + "median": 0.08719475900034013, + "min": 0.08035967700016045, + "max": 0.09466356400116638 + }, + "tool_s": { + "median": 0.0855, + "min": 0.0788, + "max": 0.0928 + }, + "total_s": { + "median": 0.6031849620012508, + "min": 0.5930489239981398, + "max": 0.611908388998927 + }, + "transport_s": { + "median": 0.001494759000340118, + "min": 0.0013596770001604475, + "max": 0.0015635640011663788 + }, + "worker_faults": { + "median": 8192, + "min": 8192, + "max": 8192 + }, + "worker_maxrss_mib": { + "median": 545, + "min": 545, + "max": 545 + }, + "write_s": { + "median": 0.0001, + "min": 0.0001, + "max": 0.0001 + } + } + } + }, + "image_max": { + "shm": { + "rows": [ + { + "path": "shm", + "tool": "image_max", + "shm_create_s": 9.839399899647105e-05, + "shm_fill_s": 0.450560311001027, + "export_s": 0.4506587050000235, + "host_export_faults": 131072, + "task_wall_s": 0.3218063210006221, + "load_s": 0.2801, + "tool_s": 0.0387, + "write_s": 0.0001, + "transport_s": 0.002906321000622106, + "worker_faults": 8449, + "worker_maxrss_mib": 1057, + "cleanup_s": 0.08499044299969682, + "k_nr_written": 2, + "k_pgpgout": 8, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.8574554690003424 + }, + { + "path": "shm", + "tool": "image_max", + "shm_create_s": 0.00010618699889164418, + "shm_fill_s": 0.4704555459993571, + "export_s": 0.47056173299824877, + "host_export_faults": 131072, + "task_wall_s": 0.2982461069987039, + "load_s": 0.2496, + "tool_s": 0.044, + "write_s": 0.0001, + "transport_s": 0.004546106998703922, + "worker_faults": 8449, + "worker_maxrss_mib": 1057, + "cleanup_s": 0.10807691400077601, + "k_nr_written": 2, + "k_pgpgout": 8, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.8768847539977287 + }, + { + "path": "shm", + "tool": "image_max", + "shm_create_s": 0.0004535669995675562, + "shm_fill_s": 0.46541466700000456, + "export_s": 0.4658682339995721, + "host_export_faults": 131072, + "task_wall_s": 0.267297686999882, + "load_s": 0.226, + "tool_s": 0.0384, + "write_s": 0.0001, + "transport_s": 0.0027976869998819864, + "worker_faults": 8449, + "worker_maxrss_mib": 1057, + "cleanup_s": 0.09693116800008283, + "k_nr_written": 20, + "k_pgpgout": 200, + "k_allocstall_normal": 0, + "k_pgsteal_direct": 0, + "k_pgscan_kswapd": 0, + "k_pgscan_direct": 0, + "k_psi_some_us": 0, + "total_s": 0.8300970889995369 + } + ], + "summary": { + "cleanup_s": { + "median": 0.09693116800008283, + "min": 0.08499044299969682, + "max": 0.10807691400077601 + }, + "export_s": { + "median": 0.4658682339995721, + "min": 0.4506587050000235, + "max": 0.47056173299824877 + }, + "host_export_faults": { + "median": 131072, + "min": 131072, + "max": 131072 + }, + "k_allocstall_normal": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_nr_written": { + "median": 2, + "min": 2, + "max": 20 + }, + "k_pgpgout": { + "median": 8, + "min": 8, + "max": 200 + }, + "k_pgscan_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgscan_kswapd": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_pgsteal_direct": { + "median": 0, + "min": 0, + "max": 0 + }, + "k_psi_some_us": { + "median": 0, + "min": 0, + "max": 0 + }, + "load_s": { + "median": 0.2496, + "min": 0.226, + "max": 0.2801 + }, + "shm_create_s": { + "median": 0.00010618699889164418, + "min": 9.839399899647105e-05, + "max": 0.0004535669995675562 + }, + "shm_fill_s": { + "median": 0.46541466700000456, + "min": 0.450560311001027, + "max": 0.4704555459993571 + }, + "task_wall_s": { + "median": 0.2982461069987039, + "min": 0.267297686999882, + "max": 0.3218063210006221 + }, + "tool_s": { + "median": 0.0387, + "min": 0.0384, + "max": 0.044 + }, + "total_s": { + "median": 0.8574554690003424, + "min": 0.8300970889995369, + "max": 0.8768847539977287 + }, + "transport_s": { + "median": 0.002906321000622106, + "min": 0.0027976869998819864, + "max": 0.004546106998703922 + }, + "worker_faults": { + "median": 8449, + "min": 8449, + "max": 8449 + }, + "worker_maxrss_mib": { + "median": 1057, + "min": 1057, + "max": 1057 + }, + "write_s": { + "median": 0.0001, + "min": 0.0001, + "max": 0.0001 + } + } + } + } + } + } +} \ No newline at end of file diff --git a/benchmarks/shm_bench.py b/benchmarks/shm_bench.py new file mode 100644 index 0000000..5ebcc26 --- /dev/null +++ b/benchmarks/shm_bench.py @@ -0,0 +1,453 @@ +#!/usr/bin/env python3 +"""Measure how much a big image costs on the way host -> worker -> host: TIFF on disk versus shared memory. + +Run (from a checkout of LabConstrictor-Tools, numpy + tifffile installed): + + python benchmarks/shm_bench.py --sizes 128 512 1024 --repeats 3 --json out.json + python benchmarks/shm_bench.py --scratch /dev/shm/lc-bench ... # when the disk has no room (then "disk" is tmpfs) + python benchmarks/shm_bench.py --cold ... # drop the page cache before each task (needs root) + +It plays the host (what Napari does: an in-memory array, `tifffile.imwrite` or a shared-memory block) against a real worker +(`python -m labconstrictor_tools serve`) running `shm_bench_app`. Every time is a wall-clock second measured by this process +except `load/tool/write`, which are the worker's own `timings` from COMPLETION. Image: uint16, 2-D, random, `MB` mebibytes. +Memory and page faults come from getrusage (worker: the `probe` tool, host: this process). +""" + +from __future__ import annotations + +import argparse +import json +import os +import resource +import shutil +import statistics +import sys +import tempfile +import time +from multiprocessing import shared_memory +from pathlib import Path + +import numpy as np +import tifffile + +HERE = Path(__file__).resolve().parent +sys.path.insert(0, str(HERE.parent)) # run against the checkout, not an installed Tools +from labconstrictor_tools.client import WorkerProcess + + +def faults() -> int: + return resource.getrusage(resource.RUSAGE_SELF).ru_minflt + + +def make_image(megabytes: int) -> np.ndarray: + side = int((megabytes * 1024 * 1024 // 2) ** 0.5) + return np.random.default_rng(0).integers(0, 65535, size=(side, side), dtype=np.uint16) + + +VMSTAT_KEYS = ( + "pgscan_direct", + "pgscan_kswapd", + "allocstall_normal", + "pgsteal_direct", + "pgpgout", + "nr_written", +) + + +def telemetry() -> dict: + """Kernel counters that say whether the machine was short of memory (Linux only; empty elsewhere).""" + out: dict = {} + try: + for line in Path("/proc/vmstat").read_text().splitlines(): + key, _, value = line.partition(" ") + if key in VMSTAT_KEYS: + out[key] = int(value) + some = Path("/proc/pressure/memory").read_text().splitlines()[0] + out["psi_some_us"] = int(some.split("total=")[1]) + except (OSError, IndexError, ValueError): + pass + return out + + +def mem_available_mib() -> int: + try: + for line in Path("/proc/meminfo").read_text().splitlines(): + if line.startswith("MemAvailable:"): + return int(line.split()[1]) // 1024 + except OSError: + pass + return 1 << 30 + + +def start_guard(floor_mib: int, worker_ref: list) -> None: + """Abort the run (kill the worker, remove the scratch folders) before the sandbox runs out of memory: nothing here may take + down other work on a shared machine.""" + import threading + + def watch() -> None: + while True: + if mem_available_mib() < floor_mib: + print("MemAvailable below %d MiB: aborting the benchmark" % floor_mib, flush=True) + for w in worker_ref: + w.kill() + shutil.rmtree(SCRATCH, ignore_errors=True) + shutil.rmtree(OUT_SCRATCH, ignore_errors=True) + os._exit(3) + time.sleep(0.05) + + threading.Thread(target=watch, daemon=True).start() + + +def prewarm(megabytes: int) -> None: + """Touch and free `megabytes` of fresh memory so the guest kernel has pages the hypervisor already backs. On a micro-VM + (this sandbox) the first touch of memory the host has not backed costs 1-3 s per 512 MiB instead of 0.1 s; on a laptop this + changes nothing. Called outside every timer, right before the step that allocates.""" + block = np.empty(megabytes * 1024 * 1024, dtype=np.uint8) + block.fill(1) + del block + + +def drop_caches() -> bool: + try: + os.sync() + Path("/proc/sys/vm/drop_caches").write_text("3") + return True + except OSError: + return False + + +def run_task(worker: WorkerProcess, tool: str, inputs: dict) -> tuple[float, dict]: + t = time.perf_counter() + task = worker.task(tool, inputs).wait(600) + wall = time.perf_counter() - t + if task.status != "COMPLETE": + raise RuntimeError("%s: %s %s" % (tool, task.status, task.error)) + return wall, task.outputs + + +def values(outputs: dict) -> dict: + for result in outputs["results"]: + if result["type"] == "values": + return result["values"] + return {} + + +def worker_rusage(worker: WorkerProcess) -> dict: + return values(run_task(worker, "probe", {"_job_dir": str(Path(tempfile.mkdtemp(dir=SCRATCH)))})[1]) + + +def one_run( + worker: WorkerProcess, image: np.ndarray, path_kind: str, tool: str, cold: bool, readback: bool = True +) -> dict: + """One end-to-end task. path_kind: 'disk' or 'shm'. Returns every phase in seconds.""" + job = Path(tempfile.mkdtemp(dir=SCRATCH, prefix="job_")) + out_dir = Path( + tempfile.mkdtemp(dir=OUT_SCRATCH, prefix="out_") + ) # where the worker writes results (the host-owned _job_dir) + row: dict = {"path": path_kind, "tool": tool} + if PREWARM: + prewarm(PREWARM * image.nbytes // (1024 * 1024)) + before = worker_rusage(worker) + tele0, host_f0 = telemetry(), faults() + block = None + tif = job / "input.tif" + # ---- host export + t = time.perf_counter() + if path_kind == "disk": + tifffile.imwrite(tif, image) + row["export_s"] = time.perf_counter() - t + t = time.perf_counter() + with open(tif, "rb") as handle: + os.fsync(handle.fileno()) + row["export_fsync_s"] = time.perf_counter() - t # what the disk still owed after imwrite returned + value: object = str(tif) + else: + block = shared_memory.SharedMemory(create=True, size=image.nbytes) + row["shm_create_s"] = time.perf_counter() - t + t = time.perf_counter() + np.ndarray(image.shape, dtype=image.dtype, buffer=block.buf)[...] = image + row["shm_fill_s"] = time.perf_counter() - t + row["export_s"] = row["shm_create_s"] + row["shm_fill_s"] + value = { + "appose_type": "ndarray", + "shm": {"name": block.name}, + "shape": list(image.shape), + "dtype": "uint16", + } + row["host_export_faults"] = faults() - host_f0 + if cold: + row["cache_dropped"] = drop_caches() + # ---- task + if PREWARM: + prewarm(PREWARM * image.nbytes // (1024 * 1024)) + if tool == "view_max": # zero-copy prototype: the tool maps the block itself + task_inputs = { + "block": block.name, + "rows": image.shape[0], + "cols": image.shape[1], + "_job_dir": str(out_dir), + } + else: + task_inputs = {"image": value, "_job_dir": str(out_dir)} + wall, outputs = run_task(worker, tool, task_inputs) + timings = outputs["timings"] + row["task_wall_s"] = wall + row["load_s"], row["tool_s"], row["write_s"] = ( + timings["load_inputs_s"], + timings["tool_s"], + timings["write_results_s"], + ) + row["transport_s"] = ( + wall - row["load_s"] - row["tool_s"] - row["write_s"] + ) # pipes, JSON, scheduling, worker bookkeeping + after = worker_rusage(worker) + row["worker_faults"] = after["minflt"] - before["minflt"] + row["worker_maxrss_mib"] = after["maxrss_kib"] // 1024 + # ---- result return + if PREWARM and readback: + prewarm(image.nbytes // (1024 * 1024)) + t = time.perf_counter() + if not readback: + if tool == "invert_to_shm": + d = next(r for r in outputs["results"] if r["type"] == "values")["values"]["descriptor"] + leftover = shared_memory.SharedMemory(name=d["shm"]["name"]) + leftover.close() + leftover.unlink() + elif tool in ("invert", "passthrough"): + out_path = next(r["path"] for r in outputs["results"] if r["type"] == "image") + result = tifffile.imread(out_path) + row["result_read_s"] = time.perf_counter() - t + assert result.shape == image.shape + del result + elif ( + tool == "invert_to_shm" + ): # (readback False would leak the block: the guard path never uses this tool) + d = next(r for r in outputs["results"] if r["type"] == "values")["values"]["descriptor"] + out = shared_memory.SharedMemory(name=d["shm"]["name"]) + view = np.ndarray(d["shape"], dtype=d["dtype"], buffer=out.buf) + row["result_attach_s"] = time.perf_counter() - t # zero-copy view: the host could display from this + t = time.perf_counter() + copy = view.copy() # what a host that needs its own array (Napari layer) does + row["result_copy_s"] = time.perf_counter() - t + row["result_read_s"] = row["result_attach_s"] + row["result_copy_s"] + del view, copy + out.close() + out.unlink() + # ---- cleanup + t = time.perf_counter() + if block is not None: + block.close() + block.unlink() + shutil.rmtree(job, ignore_errors=True) + shutil.rmtree(out_dir, ignore_errors=True) + row["cleanup_s"] = time.perf_counter() - t + tele1 = telemetry() + for key, value in tele1.items(): + row["k_" + key] = value - tele0.get(key, 0) # kernel counters over the whole run + row["total_s"] = ( + row["export_s"] + + row.get("export_fsync_s", 0) * 0 + + row["task_wall_s"] + + row.get("result_read_s", 0) + + row["cleanup_s"] + ) + return row + + +def cli_run(image: np.ndarray, tool: str, home: Path) -> dict: + """The real command line: `labconstrictor-tools run APP TOOL image=FILE`, a new worker per call (cold start).""" + import subprocess + + job = Path(tempfile.mkdtemp(dir=SCRATCH, prefix="cli_")) + tif = job / "input.tif" + t = time.perf_counter() + tifffile.imwrite(tif, image) + export = time.perf_counter() - t + env = dict(os.environ, LC_HOME=str(home), PYTHONPATH=str(HERE.parent), PYTHONSAFEPATH="") + t = time.perf_counter() + proc = subprocess.run( + [ + sys.executable, + "-m", + "labconstrictor_tools", + "run", + "shm_bench", + tool, + "image=%s" % tif, + "--out", + str(job / "out"), + "--no-record", + ], + env=env, + capture_output=True, + text=True, + timeout=900, + ) + wall = time.perf_counter() - t + if proc.returncode != 0: + raise RuntimeError(proc.stdout + proc.stderr) + shutil.rmtree(job, ignore_errors=True) + return {"path": "cli", "tool": tool, "export_s": export, "cli_wall_s": wall} + + +def summarize(rows: list[dict]) -> dict: + keys = sorted( + {k for r in rows for k, v in r.items() if isinstance(v, (int, float)) and not isinstance(v, bool)} + ) + out = {} + for k in keys: + xs = [r[k] for r in rows if k in r] + out[k] = {"median": statistics.median(xs), "min": min(xs), "max": max(xs)} + return out + + +def main() -> None: + global SCRATCH + ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("--sizes", type=int, nargs="+", default=[128, 512, 1024], help="image sizes in MiB") + ap.add_argument("--repeats", type=int, default=3) + ap.add_argument("--paths", nargs="+", default=["disk", "shm"], choices=["disk", "shm"]) + ap.add_argument( + "--tools", + nargs="+", + default=["image_max", "invert"], + choices=["image_max", "invert", "passthrough", "invert_to_shm", "view_max"], + ) + ap.add_argument( + "--scratch", default=None, help="folder for the files (default: a private folder under $TMPDIR)" + ) + ap.add_argument( + "--out-scratch", + default=None, + help="folder for the worker's result files (default: same as --scratch)", + ) + ap.add_argument( + "--cold", action="store_true", help="drop the page cache between export and task (root only)" + ) + ap.add_argument( + "--cli", + action="store_true", + help="also time the real `labconstrictor-tools run` (cold worker, disk path)", + ) + ap.add_argument( + "--prewarm", + type=int, + default=0, + metavar="K", + help="before the export and the task, touch and free K x image size of memory (micro-VM first-touch cost)", + ) + ap.add_argument( + "--no-readback", + action="store_true", + help="the host does not read the result back (saves memory at 1 GiB)", + ) + ap.add_argument( + "--guard-mib", + type=int, + default=700, + help="abort when MemAvailable falls below this many MiB (0 = off)", + ) + ap.add_argument("--json", default=None) + args = ap.parse_args() + + global OUT_SCRATCH, PREWARM + PREWARM = args.prewarm + SCRATCH = tempfile.mkdtemp(prefix="lc-shm-bench-", dir=args.scratch) + OUT_SCRATCH = ( + tempfile.mkdtemp(prefix="lc-shm-out-", dir=args.out_scratch) if args.out_scratch else SCRATCH + ) + results: dict = { + "env": { + "python": sys.version.split()[0], + "numpy": np.__version__, + "tifffile": tifffile.__version__, + "cpus": os.cpu_count(), + "scratch": SCRATCH, + "out_scratch": OUT_SCRATCH, + "cold": args.cold, + "prewarm": args.prewarm, + }, + "runs": {}, + } + try: + worker = WorkerProcess(module="shm_bench_app", pythonpath=[str(HERE)]) + if args.guard_mib: + start_guard(args.guard_mib, [worker]) + run_task(worker, "probe", {"_job_dir": tempfile.mkdtemp(dir=SCRATCH)}) # warm the worker (imports) + home = Path(tempfile.mkdtemp(dir=SCRATCH, prefix="home_")) + if args.cli: + import subprocess + + subprocess.run( + [ + sys.executable, + "-m", + "labconstrictor_tools", + "register", + "--name", + "shm_bench", + "--prefix", + sys.prefix, + "--module", + "shm_bench_app", + "--pythonpath", + str(HERE), + ], + env=dict(os.environ, LC_HOME=str(home), PYTHONPATH=str(HERE.parent)), + check=True, + capture_output=True, + ) + for mb in args.sizes: + image = make_image(mb) + print("== %d MiB (%s, %s)" % (mb, image.shape, image.dtype), flush=True) + for tool in args.tools: + for kind in args.paths: + rows = [] + for i in range(args.repeats): + rows.append(one_run(worker, image, kind, tool, args.cold, not args.no_readback)) + r = rows[-1] + print( + " %-9s %-5s run%d export %.2f task %.2f (load %.2f tool %.2f write %.2f other %.3f) back %.2f total %.2f worker faults %d rss %d MiB psi %dms scan %d" + % ( + tool, + kind, + i + 1, + r["export_s"], + r["task_wall_s"], + r["load_s"], + r["tool_s"], + r["write_s"], + r["transport_s"], + r.get("result_read_s", 0), + r["total_s"], + r["worker_faults"], + r["worker_maxrss_mib"], + r.get("k_psi_some_us", 0) // 1000, + r.get("k_pgscan_direct", 0), + ), + flush=True, + ) + results["runs"].setdefault(str(mb), {}).setdefault(tool, {})[kind] = { + "rows": rows, + "summary": summarize(rows), + } + if args.cli: + rows = [cli_run(image, "image_max", home) for _ in range(args.repeats)] + results["runs"][str(mb)].setdefault("image_max", {})["cli"] = { + "rows": rows, + "summary": summarize(rows), + } + print(" cli image_max: %s" % [round(r["cli_wall_s"], 2) for r in rows], flush=True) + del image + worker.close() + finally: + shutil.rmtree(SCRATCH, ignore_errors=True) + shutil.rmtree(OUT_SCRATCH, ignore_errors=True) + if args.json: + Path(args.json).write_text(json.dumps(results, indent=1)) + + +SCRATCH = OUT_SCRATCH = "" +PREWARM = 0 +if __name__ == "__main__": + main() diff --git a/benchmarks/shm_bench_app.py b/benchmarks/shm_bench_app.py new file mode 100644 index 0000000..5febd2e --- /dev/null +++ b/benchmarks/shm_bench_app.py @@ -0,0 +1,109 @@ +"""Tools used by shm_bench.py: the smallest apps that separate "move the pixels" from "do the science". + +Not a real app: no registration needed, `shm_bench.py` starts it with `WorkerProcess(module="shm_bench_app")`. +""" + +from __future__ import annotations + +import resource +import sys +from typing import Annotated + +from labconstrictor_tools import Image, ImageOut, Name, Scalars, tool + + +def _rusage() -> dict: + ru = resource.getrusage(resource.RUSAGE_SELF) + # ru_maxrss is KiB on Linux, bytes on macOS + scale = 1 if sys.platform != "darwin" else 1 / 1024 + return {"minflt": ru.ru_minflt, "majflt": ru.ru_majflt, "maxrss_kib": int(ru.ru_maxrss * scale)} + + +@tool("Probe") +def probe() -> Scalars: + """Cumulative page faults and peak resident memory of this worker so far.""" + return _rusage() + + +@tool("Image max") +def image_max(image: Image) -> Scalars: + """Input transport only: reads the whole image once (no copy), returns a number.""" + return {"max": int(image.max()), **_rusage()} + + +@tool("View max (zero copy)") +def view_max(block: str, rows: int, cols: int) -> Scalars: + """PROTOTYPE of a borrowed read-only view (plan item 2): map the host's block, read it in place, never copy.""" + from multiprocessing import resource_tracker, shared_memory + + import numpy as np + + register = resource_tracker.register + resource_tracker.register = ( + lambda *_a, **_k: None + ) # attach without taking over the block (convert._attach_shared_memory does the same) + try: + shm = shared_memory.SharedMemory(name=block) + finally: + resource_tracker.register = register + view = np.ndarray((rows, cols), dtype=np.uint16, buffer=shm.buf) + view.flags.writeable = False + result = int(view.max()) + del view + shm.close() + return {"max": result, **_rusage()} + + +@tool("Image checksum") +def image_checksum(image: Image) -> Scalars: + """Sum of all pixels as an unsigned 64-bit integer, plus the first pixel (catches byte-order and signedness mistakes).""" + import numpy as np + + return { + "sum": int(image.astype(np.uint64).sum()), + "first": int(image.flat[0]), + "shape": list(image.shape), + "dtype": str(image.dtype), + } + + +@tool("Invert") +def invert(image: Image) -> Annotated[ImageOut, Name("inverted")]: + """Round trip: one new array in the tool, written back as a TIFF by the worker (the current result path).""" + import numpy as np + + return np.iinfo(image.dtype).max - image + + +@tool("Pass through") +def passthrough(image: Image) -> Annotated[ImageOut, Name("same")]: + """No new array in the tool: isolates the result write (build_results) from the tool's own work.""" + return image + + +@tool("Invert to shared memory") +def invert_to_shm(image: Image) -> Scalars: + """PROTOTYPE of a shared-memory result: the tool writes its result straight into a new block and returns the + descriptor. Not part of the protocol today; used to price the return leg.""" + from multiprocessing import resource_tracker, shared_memory + + import numpy as np + + # the block must outlive this worker's resource tracker: do what convert._attach_shared_memory does, for creation + register = resource_tracker.register + resource_tracker.register = lambda *_a, **_k: None + try: + shm = shared_memory.SharedMemory(create=True, size=image.nbytes) + finally: + resource_tracker.register = register + out = np.ndarray(image.shape, dtype=image.dtype, buffer=shm.buf) + np.subtract(np.iinfo(image.dtype).max, image, out=out) + descriptor = { + "appose_type": "ndarray", + "shm": {"name": shm.name}, + "shape": list(image.shape), + "dtype": str(image.dtype), + } + del out + shm.close() + return {"descriptor": descriptor} diff --git a/benchmarks/shm_breakdown.py b/benchmarks/shm_breakdown.py new file mode 100644 index 0000000..67388c3 --- /dev/null +++ b/benchmarks/shm_breakdown.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python3 +"""Where do the seconds go inside the worker for one big image? Replays the worker's steps one by one in a fresh process +and reports wall, user CPU, system CPU and page faults for each step (the "unexplained" worker time of issue #66). + + python benchmarks/shm_breakdown.py --mb 512 --repeats 3 --disk-dir /path/on/disk --tmp-dir /dev/shm + +Steps (same calls as labconstrictor_tools.convert and worker._execute): + attach SharedMemory(name=...) (the host created and filled the block before) + copy np.ndarray(buffer=shm.buf).copy() (convert._ndarray_from_shared_memory: the one worker copy) + copy_warm the same copy into memory that was already touched (what a reused buffer would cost: no page faults) + tool 255 - image (a tool that makes one new array: page faults on new memory) + tiff_disk tifffile.imwrite to --disk-dir (build_results for an image output) + tiff_fsync fsync of that file (what the disk still owes; a host does not wait for it) + tiff_tmpfs tifffile.imwrite to --tmp-dir (RAM) (the same CPU work without a disk) + tiff_read tifffile.imread of the disk file (page cache) (what a host does with a result) +""" + +import argparse +import json +import os +import resource +import statistics +import tempfile +import time +from multiprocessing import shared_memory +from pathlib import Path + +import numpy as np +import tifffile + +PREWARM_MIB = 0 + + +def measure(fn): + if ( + PREWARM_MIB + ): # touch and free fresh memory first (outside the timer): on a micro-VM the guest then reuses pages the host already backs + block = np.empty(PREWARM_MIB * 1024 * 1024, dtype=np.uint8) + block.fill(1) + del block + r0, t0 = resource.getrusage(resource.RUSAGE_SELF), time.perf_counter() + value = fn() + t1, r1 = time.perf_counter(), resource.getrusage(resource.RUSAGE_SELF) + return value, { + "wall_s": t1 - t0, + "user_s": r1.ru_utime - r0.ru_utime, + "sys_s": r1.ru_stime - r0.ru_stime, + "faults": r1.ru_minflt - r0.ru_minflt, + } + + +def once(mb: int, disk_dir: str, tmp_dir: str) -> dict: + side = int((mb * 1024 * 1024 // 2) ** 0.5) + src = np.random.default_rng(0).integers(0, 65535, size=(side, side), dtype=np.uint16) + block = shared_memory.SharedMemory(create=True, size=src.nbytes) + np.ndarray(src.shape, dtype=src.dtype, buffer=block.buf)[...] = src + out: dict = {} + attached, out["attach"] = measure(lambda: shared_memory.SharedMemory(name=block.name)) + view = np.ndarray(src.shape, dtype=src.dtype, buffer=attached.buf) + image, out["copy"] = measure(view.copy) + _, out["copy_warm"] = measure(lambda: np.copyto(image, view)) + result, out["tool"] = measure(lambda: np.iinfo(image.dtype).max - image) + path = Path(disk_dir) / "breakdown.tif" + _, out["tiff_disk"] = measure(lambda: tifffile.imwrite(path, result)) + + def sync(): + with open(path, "rb") as handle: + os.fsync(handle.fileno()) + + _, out["tiff_fsync"] = measure(sync) + path2 = Path(tmp_dir) / "breakdown.tif" + _, out["tiff_tmpfs"] = measure(lambda: tifffile.imwrite(path2, result)) + back, out["tiff_read"] = measure(lambda: tifffile.imread(path)) + out["peak_rss_mib"] = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss // 1024 + del back + view = None # release the mapping before close() + attached.close() + block.close() + block.unlink() + path.unlink() + path2.unlink() + return out + + +def main() -> None: + ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("--mb", type=int, default=512) + ap.add_argument("--repeats", type=int, default=3) + ap.add_argument("--disk-dir", default=tempfile.gettempdir()) + ap.add_argument("--tmp-dir", default="/dev/shm" if os.path.isdir("/dev/shm") else tempfile.gettempdir()) + ap.add_argument( + "--prewarm", + action="store_true", + help="touch and free one image's worth of memory before every step (not timed)", + ) + ap.add_argument("--json") + args = ap.parse_args() + global PREWARM_MIB + PREWARM_MIB = args.mb if args.prewarm else 0 + runs = [once(args.mb, args.disk_dir, args.tmp_dir) for _ in range(args.repeats)] + print( + "%d MiB, %d repeats (median [min..max]); wall / user / sys seconds, page faults" + % (args.mb, args.repeats) + ) + summary = {} + for step in runs[0]: + if step == "peak_rss_mib": + print(" peak RSS %s MiB" % [r[step] for r in runs]) + continue + row = {k: [r[step][k] for r in runs] for k in runs[0][step]} + summary[step] = {k: statistics.median(v) for k, v in row.items()} + print( + " %-11s wall %.3f [%.3f..%.3f] user %.3f sys %.3f faults %d" + % ( + step, + summary[step]["wall_s"], + min(row["wall_s"]), + max(row["wall_s"]), + summary[step]["user_s"], + summary[step]["sys_s"], + summary[step]["faults"], + ) + ) + if args.json: + Path(args.json).write_text(json.dumps({"mb": args.mb, "runs": runs, "median": summary}, indent=1)) + + +if __name__ == "__main__": + main() diff --git a/benchmarks/shm_fill.py b/benchmarks/shm_fill.py new file mode 100644 index 0000000..d678d16 --- /dev/null +++ b/benchmarks/shm_fill.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python3 +"""How a host should fill a shared block: page-faulting through the mapping (what multiprocessing.shared_memory does and what +a Java MappedByteBuffer does) versus write() into the file descriptor versus MAP_POPULATE. Linux only (/dev/shm). + + python benchmarks/shm_fill.py --mb 512 --repeats 3 +""" + +import argparse +import mmap +import os +import statistics +import time +from multiprocessing import shared_memory + +import numpy as np + + +def main() -> None: + ap = argparse.ArgumentParser() + ap.add_argument("--mb", type=int, default=512) + ap.add_argument("--repeats", type=int, default=3) + args = ap.parse_args() + n = args.mb * 1024 * 1024 + src = np.random.default_rng(0).integers(0, 255, size=n, dtype=np.uint8) + results = {} + for _ in range(args.repeats): + # 1. SharedMemory + copy through the mapping + t = time.perf_counter() + b = shared_memory.SharedMemory(create=True, size=n) + np.ndarray(src.shape, dtype=src.dtype, buffer=b.buf)[...] = src + results.setdefault("mmap_fault_fill", []).append(time.perf_counter() - t) + b.close() + b.unlink() + # 2. write() into the descriptor (no page faults in the writer), then map + t = time.perf_counter() + name = "/dev/shm/lc_fill_%d" % os.getpid() + fd = os.open(name, os.O_CREAT | os.O_RDWR, 0o600) + mv = memoryview(src) + done = 0 + while done < n: + done += os.write(fd, mv[done : done + (64 << 20)]) + results.setdefault("write_fd_fill", []).append(time.perf_counter() - t) + os.close(fd) + os.unlink(name) + # 3. MAP_POPULATE: the kernel allocates every page up front, then memcpy + t = time.perf_counter() + fd = os.open(name, os.O_CREAT | os.O_RDWR, 0o600) + os.ftruncate(fd, n) + m = mmap.mmap(fd, n, flags=mmap.MAP_SHARED | getattr(mmap, "MAP_POPULATE", 0)) + np.frombuffer(m, dtype=np.uint8)[...] = src + results.setdefault("map_populate_fill", []).append(time.perf_counter() - t) + del m + os.close(fd) + os.unlink(name) + # 4. the same copy into ordinary memory (the floor) + t = time.perf_counter() + dst = np.empty_like(src) + dst[...] = src + results.setdefault("anon_memory_copy", []).append(time.perf_counter() - t) + del dst + for key, xs in results.items(): + print( + "%-18s %d MiB: median %.3f s [%.3f..%.3f]" + % (key, args.mb, statistics.median(xs), min(xs), max(xs)) + ) + + +if __name__ == "__main__": + main() diff --git a/benchmarks/shm_lifetime.py b/benchmarks/shm_lifetime.py new file mode 100644 index 0000000..2ed589d --- /dev/null +++ b/benchmarks/shm_lifetime.py @@ -0,0 +1,158 @@ +#!/usr/bin/env python3 +"""Small proofs about the life of a shared block on POSIX (run on Linux; macOS and Windows differ, see docs/PERF_SHARED_MEMORY.md). + + python benchmarks/shm_lifetime.py + +T1 host killed (SIGKILL), its resource tracker alive -> the tracker unlinks the block +T2 host and tracker both killed (whole process group) -> the block LEAKS in /dev/shm (needs a sweep at the next start) +T3 unlink while a reader still maps the block -> the reader keeps reading, memory is freed when the last map goes +T4 SharedMemory.close() while a numpy view exists -> silent, and the view then segfaults (T4b: a plain mmap refuses) +T5 non-contiguous layer data (transpose, strided slice) -> np.copyto into the block gives the same pixels as a TIFF round trip +""" + +import os +import signal +import subprocess +import sys +import textwrap +import time +from multiprocessing import shared_memory +from pathlib import Path + +import numpy as np + +SHM = Path("/dev/shm") +results = [] + + +def check(name: str, ok: bool, detail: str = "") -> None: + results.append(ok) + print("%-4s %-4s %s" % (name, "PASS" if ok else "FAIL", detail)) + + +def host_script(name: str) -> str: + return textwrap.dedent(""" + import sys, time + from multiprocessing import shared_memory + b = shared_memory.SharedMemory(name=%r, create=True, size=1 << 20) + print("ready", flush=True) + time.sleep(60) + """ % name) + + +def exists(name: str) -> bool: + return (SHM / name).exists() + + +# T1: host SIGKILL, tracker alive +name = "lc_t1_%d" % os.getpid() +p = subprocess.Popen([sys.executable, "-c", host_script(name)], stdout=subprocess.PIPE, text=True) +p.stdout.readline() +before = exists(name) +os.kill(p.pid, signal.SIGKILL) +p.wait() +time.sleep(1.0) +check( + "T1", + before and not exists(name), + "block existed while the host lived: %s; after SIGKILL of the host only: exists=%s" + % (before, exists(name)), +) +(SHM / name).unlink(missing_ok=True) + +# T2: host and tracker killed together (a host started in its own process group and killed as a group, like a crashed IDE/terminal) +name = "lc_t2_%d" % os.getpid() +p = subprocess.Popen( + [sys.executable, "-c", host_script(name)], stdout=subprocess.PIPE, text=True, start_new_session=True +) +p.stdout.readline() +os.killpg(p.pid, signal.SIGKILL) +p.wait() +time.sleep(1.0) +leaked = exists(name) +check( + "T2", + leaked, + "after SIGKILL of the whole group the block is still in /dev/shm: %s (so a start-up sweep is needed)" + % leaked, +) +(SHM / name).unlink(missing_ok=True) + +# T3: unlink while mapped +b = shared_memory.SharedMemory(create=True, size=1 << 20) +np.ndarray((1 << 20,), dtype=np.uint8, buffer=b.buf)[:] = 7 +r = shared_memory.SharedMemory(name=b.name) +b.close() +b.unlink() +check( + "T3", + not exists(b.name) and int(np.ndarray((1 << 20,), dtype=np.uint8, buffer=r.buf)[123]) == 7, + "name gone from /dev/shm, the attached reader still sees the pixels", +) +r.close() + +# T4: SharedMemory.close() (and SharedMemory.__del__) with a live numpy view: no error, then the view is a dangling pointer +crash = subprocess.run( + [ + sys.executable, + "-c", + textwrap.dedent(""" + import numpy as np + from multiprocessing import shared_memory + b = shared_memory.SharedMemory(create=True, size=1 << 20) + v = np.ndarray((1 << 20,), dtype=np.uint8, buffer=b.buf) + b.close() # no BufferError on this Python + print(v[5]) # reads unmapped memory +"""), + ], + capture_output=True, + text=True, +) +check( + "T4", + crash.returncode == -signal.SIGSEGV, + "SharedMemory.close() with a live view is silent, reading the view then ends the process with SIGSEGV (exit %d): a host that hands out a shared-memory array must keep the mapping alive with the array" + % crash.returncode, +) + +# T4b: a plain mmap keeps itself alive behind the array and refuses to close under it +import mmap + +fd = os.open("/dev/shm/lc_t4b_%d" % os.getpid(), os.O_CREAT | os.O_RDWR, 0o600) +os.ftruncate(fd, 1 << 20) +m = mmap.mmap(fd, 1 << 20) +arr = np.frombuffer(m, dtype=np.uint8) +try: + m.close() + check("T4b", False, "mmap.close() under a live array did not raise") +except BufferError: + check( + "T4b", + True, + "mmap.close() under a live numpy array raises BufferError: an mmap-backed array is safe to hand to a viewer layer", + ) +del arr +m.close() +os.close(fd) +os.unlink("/dev/shm/lc_t4b_%d" % os.getpid()) + +# T5: non-contiguous input +rng = np.random.default_rng(0) +base = rng.integers(0, 65535, size=(600, 800), dtype=np.uint16) +for label, layer in ( + ("transpose", base.T), + ("strided", base[::2, ::3]), + ("fortran", np.asfortranarray(base)), +): + blk = shared_memory.SharedMemory(create=True, size=layer.nbytes) + dst = np.ndarray( + layer.shape, dtype=layer.dtype, buffer=blk.buf + ) # C order, the only order the descriptor can express + np.copyto(dst, layer) + ok = np.array_equal(dst, layer) and dst.flags["C_CONTIGUOUS"] + del dst + blk.close() + blk.unlink() + check("T5", ok, "%s layer copied into a C-ordered block, pixels identical" % label) + +sys.exit(0 if all(results) else 1) diff --git a/benchmarks/shm_table.py b/benchmarks/shm_table.py new file mode 100644 index 0000000..6364a75 --- /dev/null +++ b/benchmarks/shm_table.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 +"""Print the markdown tables of docs/PERF_SHARED_MEMORY.md from benchmarks/results/*.json (median [min-max] seconds). + +python benchmarks/shm_table.py benchmarks/results/sandbox_default_128_512.json ... +""" + +import json +import sys + +COLS = [ + ("export_s", "export"), + ("load_s", "worker load"), + ("tool_s", "tool"), + ("write_s", "worker write"), + ("result_read_s", "host read result"), + ("cleanup_s", "cleanup"), + ("total_s", "TOTAL"), +] + + +def cell(summary, key): + if key not in summary: + return "-" + s = summary[key] + return "%.2f [%.2f-%.2f]" % (s["median"], s["min"], s["max"]) + + +for path in sys.argv[1:]: + data = json.load(open(path)) + env = data["env"] + print("\n%s (prewarm=%s, cold cache=%s)\n" % (path.split("/")[-1], env.get("prewarm"), env.get("cold"))) + print("| MiB | tool | path | " + " | ".join(label for _, label in COLS) + " |") + print("|---|---|---|" + "---|" * len(COLS)) + for mb, tools in data["runs"].items(): + for tool, paths in tools.items(): + for kind, block in paths.items(): + if kind == "cli": + s = block["summary"] + print( + "| %s | %s | cli (cold worker) | %s |" + % ( + mb, + tool, + "export %s, whole `run` %s" % (cell(s, "export_s"), cell(s, "cli_wall_s")), + ) + ) + continue + s = block["summary"] + print( + "| %s | %s | %s | " % (mb, tool, kind) + + " | ".join(cell(s, key) for key, _ in COLS) + + " |" + ) diff --git a/benchmarks/tiff_memmap.py b/benchmarks/tiff_memmap.py new file mode 100644 index 0000000..e8fcaa0 --- /dev/null +++ b/benchmarks/tiff_memmap.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python3 +"""The no-protocol-change alternative: the worker memory-maps the host's uncompressed TIFF instead of reading it +(`tifffile.memmap`, read-only). Compares imread (copy) with memmap for a tool that reads every pixel once. + + python benchmarks/tiff_memmap.py --mb 512 --repeats 3 --dir /path/on/disk [--cold] +""" + +import argparse +import os +import statistics +import tempfile +import time +from pathlib import Path + +import numpy as np +import tifffile + + +def main() -> None: + ap = argparse.ArgumentParser() + ap.add_argument("--mb", type=int, default=512) + ap.add_argument("--repeats", type=int, default=3) + ap.add_argument("--dir", default=tempfile.gettempdir()) + ap.add_argument("--cold", action="store_true", help="drop the page cache before each read (root, Linux)") + args = ap.parse_args() + side = int((args.mb * 1024 * 1024 // 2) ** 0.5) + path = Path(args.dir) / "memmap_bench.tif" + tifffile.imwrite(path, np.random.default_rng(0).integers(0, 65535, size=(side, side), dtype=np.uint16)) + with open(path, "rb") as handle: + os.fsync(handle.fileno()) + out = {"imread": [], "memmap": []} + for _ in range(args.repeats): + for how in ("imread", "memmap"): + if args.cold: + os.sync() + Path("/proc/sys/vm/drop_caches").write_text("3") + fresh = np.empty(args.mb * 1024 * 1024, dtype=np.uint8) + fresh.fill(1) + del fresh # warm memory, not timed + t = time.perf_counter() + array = tifffile.imread(path) if how == "imread" else tifffile.memmap(path, mode="r") + load = time.perf_counter() - t + t = time.perf_counter() + int(array.max()) + use = time.perf_counter() - t + out[how].append((load, use)) + del array + print("%d MiB, %s cache" % (args.mb, "cold" if args.cold else "warm")) + for how, rows in out.items(): + loads, uses = [r[0] for r in rows], [r[1] for r in rows] + print( + " %-7s load %.3f [%.3f-%.3f] first full pass %.3f [%.3f-%.3f] load+pass %.3f" + % ( + how, + statistics.median(loads), + min(loads), + max(loads), + statistics.median(uses), + min(uses), + max(uses), + statistics.median(a + b for a, b in rows), + ) + ) + path.unlink() + + +if __name__ == "__main__": + main() diff --git a/docs/PERF_SHARED_MEMORY.md b/docs/PERF_SHARED_MEMORY.md new file mode 100644 index 0000000..3166c35 --- /dev/null +++ b/docs/PERF_SHARED_MEMORY.md @@ -0,0 +1,226 @@ +# Shared memory for big images: measurements, feasibility per host, recommendation (issue #66) + +Status: research result, nothing here is implemented. Written 2026-10-13 against Tools `main` (0f97d65). The scripts that produced every number are in [`benchmarks/`](../benchmarks) and the raw results in `benchmarks/results/`. + +## 1. Answer first + +**Recommendation: do it for Fiji only, as an opt-in input transport with a size threshold (about 256 MiB), after a small Tools change. Do not do it for Napari or QuPath now. Do not add shared-memory results (outputs) yet.** The expected gain is modest (about 0.5 s per 512 MiB on Fiji at the median, more when the machine or disk is under stress), so this is a medium-low priority feature, never to be on by default until it is measured on real Windows and macOS hardware. + +Why, in five lines (details and caveats below): + +1. **Transport is not the cost.** A warm task round trip adds 2 to 5 ms (`transport_s`, JSON and pipes) and the JSON line carrying a descriptor is about 150 bytes. Everything that costs time is moving pixels: allocating and touching fresh memory, writing and reading the TIFF. +2. **Against a warm page cache the TIFF path is as fast as shared memory on a Python host.** At 512 MiB the median end to end difference between the two is under 0.1 s in the sandbox ("prewarmed" rows), because `tifffile` writes and reads at memory speed and the shared path needs the same number of fresh 512 MiB buffers (section 4.3). Shared memory mostly removes variance (writeback stalls, 512 MiB of block I/O) and the disk, not a copy. +3. **Fiji is where it pays.** Fiji's own TIFF encoder and reader (`ij.io.FileSaver`, `Opener`) cost 0.83 s write and 0.78 s read per 512 MiB at the median (range 0.39 to 2.75 s), against 0.32 s to fill and 0.38 s to read back a block, with the Appose class Fiji already ships and a Java 8 compatible build. A real Java to Python proof passes (section 5.2). +4. **Napari gains nothing on input** (`tifffile.imwrite` 0.14 s versus 0.18 to 0.40 s to fill a block). Its only real gain is showing a result without a second copy, which needs care (section 5.1). **QuPath** exports at most 100 megapixels per plane from a slide whose decode time dominates, converts a `BufferedImage` before any block exists, and has no guaranteed JNA (section 5.3). +5. **Shared memory raises the hard memory floor.** A block cannot be evicted like page cache. At 1 GiB the shared round trip was killed by the kernel OOM killer in the 16 GB sandbox, where the TIFF round trip finished (section 4.4). + +A cheaper change helps every host and needs no protocol work: let the worker memory-map an uncompressed TIFF read-only/copy-on-write (`tifffile.memmap`, the plan's performance idea 3). Load goes from 0.19 s to 0.04 s at 512 MiB (warm) and from 0.58 s to 0.24 s (cold), and no private copy is made (section 4.5). It is a Tools-only change and should be tried before, or together with, shared memory. + +## 2. What exists today (read from the code) + +* **Input.** `convert._read_image` accepts a TIFF path or an Appose-shaped descriptor `{"appose_type": "ndarray", "shm": {"name"}, "shape", "dtype"}`. `_ndarray_from_shared_memory` attaches (`track=False` on Python 3.13, a patched `resource_tracker.register` before that, so the worker never unlinks the host's block), builds `np.ndarray(shape, dtype, buffer=shm.buf)`, **copies** it (`view.copy()`) and closes. That is one fresh array in the worker. It validates name, dtype kind and that the block is large enough. It **ignores any `order` key** (an `F_ORDER` descriptor would silently be read as C order, i.e. transposed: see section 6). +* **Output.** `build_results` always writes images as `.tif` with `tifffile.imwrite` into the host-owned `_job_dir`; `np.asarray` and `portable_dtype` do not copy for uint8/uint16/float32 (they copy for bool, float64 and wide integers, with temporaries). +* **Hosts.** Napari writes `export_layer` TIFFs with `tifffile` and reads results back with `tifffile.imread` (the array becomes the layer data). Fiji drives the worker through the Appose Java `Service` and saves images with `FileSaver.saveAsTiff`, results come back through `IJ.openImage`. QuPath has its own Groovy JSON-lines client (`LcWorker`, `ProcessBuilder`), no Appose, and exports with `ImageWriterTools.writeImageRegion`. +* **Tests.** `tests/test_roundtrip_shared_memory.py` covers ownership (the worker leaves the block alone). + +## 3. Method, and what the sandbox cannot represent + +`benchmarks/shm_bench.py` plays the host (an in-memory uint16 array, as a Napari layer or an ImageJ plane) against a **real worker** (`python -m labconstrictor_tools serve --module shm_bench_app`, warm, one process for all runs) and times each phase with `perf_counter`. The worker's own phases (`load_inputs_s`, `tool_s`, `write_results_s`) are the `timings` field of `COMPLETION`. Tools are in `benchmarks/shm_bench_app.py`: `image_max` (reads the image once, tiny result: input transport only), `invert` (one new array, a TIFF result: the full round trip), `passthrough`, and two prototypes that are not in the protocol (`invert_to_shm`: result returned as a block; `view_max`: borrowed read-only view, no worker copy). The real command line (`labconstrictor-tools run`, a new worker per call) is timed with `--cli`. Each cell is **median [min-max] of 3 runs**, uint16 square images of 128, 512 and 1024 MiB. + +Two modes are reported because the sandbox has a property a laptop does not: + +* **default**: the sandbox as it is. +* **prewarm**: before each export, task and read, the driver touches and frees K x image size of memory (not timed). On this micro-VM that makes the guest reuse pages the hypervisor already backs, which is closer to bare hardware. + +**What this sandbox cannot represent. Read this before using any absolute number.** + +* It is a Firecracker-style micro-VM, 4 cores, 16 GB, no swap, about 8.5 GB of it already held in tmpfs by another tenant (so about 6 GB usable), a virtual disk, Python 3.11. **First touch of memory the hypervisor has not backed costs 1 to 3 s per 512 MiB** (system time), against 0.1 s when it has (section 4.2). This single effect explains the large spreads and the "unexplained" times, and it is not what a user's machine does. +* The disk is not slow for reads here (a 512 MiB cold-cache read took 0.34 s), and writes mostly land in page cache. A real slow disk, a network home directory, an HDD, antivirus scanning of temporary files (Windows Defender) and cloud-sync folders are **not** represented. Those are exactly the cases where shared memory would win more. +* No GPU, no real host applications (no Fiji, QuPath or Napari were run; the host side is modelled by a Python process and by the Java snippets), Linux only: **Windows and macOS behaviour below is from documentation and code reading, not measured.** +* THP is `madvise` here, so numpy arrays use huge pages and show few page faults; Windows and macOS differ. + +## 4. Results + +### 4.1 End to end (host export, worker, result read, cleanup), seconds + +`image_max` = input transport only (Napari-like host, tifffile). `invert` = full round trip, result as TIFF. Disk path = TIFF in a scratch folder on the sandbox disk; shm = `SharedMemory` block. Export does not wait for the disk (no fsync) in the "export" column, as a host would not. Full tables: `python benchmarks/shm_table.py benchmarks/results/*.json`. + +| MiB | tool | mode | disk path total | shared-memory total | +|---|---|---|---|---| +| 128 | image_max | default | 0.20 [0.18-1.36] | 0.20 [0.19-0.22] | +| 128 | invert | default | 0.36 [0.32-1.61] | 0.34 [0.33-0.76] | +| 512 | image_max | default | 1.91 [0.69-6.03] | 1.30 [0.83-2.45] | +| 512 | image_max | prewarm | 0.64 [0.61-0.78] | 0.75 [0.75-1.50] | +| 512 | image_max | cold page cache (prewarm) | 0.96 [0.58-0.98] | 0.90 [0.78-0.91] | +| 512 | invert | default | 5.95 [1.39-7.30] | 1.33 [1.25-4.72] | +| 512 | invert | prewarm | 1.95 [1.86-3.79] | 1.71 [1.65-4.12] | +| 1024 | image_max | default | 3.53 [1.74-15.33] | 3.01 [2.69-3.02] | +| 1024 | image_max | prewarm | 2.55 [1.97-3.56] | 1.61 [1.58-1.91] | +| 1024 | invert | default (3 runs) | 15.29, 6.46, 3.94 | killed by the OOM killer (worker exit -9) | +| 1024 | passthrough | default, results in tmpfs | 1.90 [1.73-12.70] | 4.14 [3.76-6.02] | + +Per phase at 512 MiB, `invert`, prewarm mode, medians: disk path export 0.14, worker load 0.18, tool 0.17, worker write 0.99, host read 0.16, cleanup 0.31; shared path export 0.42, load 0.25, tool 0.53, write 0.13, read 0.19, cleanup 0.12. The task round trip outside the worker's own timings (`transport_s`: pipes, JSON, scheduling) is **0.00 to 0.01 s in every row**, including at 1 GiB. The real CLI (`run`, cold worker) takes 0.37 s at 128 MiB and 0.52 s at 512 MiB for `image_max`, about 0.15 to 0.2 s of which is interpreter start. + +Reading the table honestly: the sandbox gives shared memory a clear lead only in "default" mode, where it is mostly avoiding an erratic disk path, and no lead at all in "prewarm" mode for a Python host. At 1 GiB `passthrough` shows the shared path worse (the worker's TIFF write after two fresh gigabytes stalled). None of this is a stable speed-up measurement; it is evidence that the gain is small and conditional. + +The two things shared memory does remove, from the kernel counters in the JSON (`k_nr_written`): **512 MiB of block I/O per input** (131073 pages written for the TIFF, 0 for the block), and the erratic part of the disk path's spread. + +### 4.2 The "unexplained" numbers of the plan are explained + +| Plan figure | Reproduced here | Cause | +|---|---|---| +| TIFF read 3.7 s per 512 MiB | `image_max` disk, run 1: worker load 3.28 s; warm 0.19 s; cold-cache read of the same file 0.34 s | not the file: **first touch of fresh memory** for the destination array (system time), hypervisor backing | +| host TIFF write 3 s per 512 MiB | export 3.41 s in run 1, Java `FileSaver` 2.4 to 2.8 s in the first run, 0.14 s warm (tifffile), 0.39 to 0.83 s (ImageJ) | page backing of the page-cache pages plus dirty-page throttling | +| shm conversion 0.44 s per 512 MiB | 0.21 to 0.28 s warm, up to 1.9 s when memory is cold | one copy: 0.065 s of memcpy plus about 0.15 s of page faults, or 1 to 3 s of hypervisor backing | +| 2.4 s in the worker for a 512 MiB shared-memory task | **reproduced exactly**: `invert`, shm, run 3: load 1.09 + tool 0.18 + write 1.15 = 2.42 s | the conversion is only the first of **three** steps that each allocate or fill fresh 512 MiB (input copy, the tool's output array, the TIFF write); each costs 0.1 to 0.2 s when memory is backed and 1 to 3 s when it is not | +| 15 s for 1 GiB | **reproduced**: 15.29 s total for `invert` 1 GiB, run 1 (load 5.74 + tool 5.33 + export 2.75 + read) and 12.7 s for `passthrough` run 1 (export 5.75 + load 5.82); the second and third run took 6.5 and 3.9 s | same effect at twice the size, on the first big allocations of a cold VM; not memory pressure in the reclaim sense | + +Evidence for the cause, from `benchmarks/shm_breakdown.py` (the worker's steps replayed one by one in a fresh process, 5 repeats, 512 MiB): + +| step | as-is: wall median [min-max], system CPU | prewarmed: wall median [min-max] | +|---|---|---| +| copy block to a new array | 0.216 [0.181-2.917], sys 0.12 | 0.203 [0.185-0.228] | +| copy again into already touched memory | 0.068 | 0.067 | +| tool: one new array | 0.267 [0.174-2.709] | 0.149 [0.140-0.273] | +| `tifffile.imwrite` (disk) | 0.247 [0.150-3.186] | 0.140 [0.124-0.146] | +| `tifffile.imread` (page cache) | 2.266 [2.207-2.961], **sys 2.21** | 0.178 [0.153-0.192] | + +The user CPU of every step is about 0.07 s (memory bandwidth); the rest is kernel time faulting in memory. A micro-benchmark (allocate and fill 512 MiB six times) gave 2.91, 0.12, 0.11, 0.10, 0.11, 1.10 s: bimodal, 0.1 s versus 1 to 3 s. Direct reclaim and memory pressure stall counters stayed at 0 in the 128 and 512 MiB runs (`k_pgscan_direct`, `k_allocstall_normal`, `k_psi_some_us`), so the slow steps are not reclaim. **Real memory pressure did appear at 1 GiB**: see 4.4. + +Copy count, which is what transfers to real machines. Fresh 512 MiB buffers touched for one `invert` round trip: + +| path | buffers | which | +|---|---|---| +| TIFF in, TIFF out (today) | 5 | page-cache pages (host write), worker array, tool output, page-cache pages (worker write), host array (the layer data) | +| block in, TIFF out | 5 | block pages replace the first buffer; nothing is saved | +| block in with a borrowed view (no worker copy), block out, host maps the block | 3 | block (host), tool output, result block; the host's layer is the mapping | + +So shared memory by itself does not reduce copies; the borrowed read-only view in the worker (plan idea 2) and a result block the host maps without copying do. The prototype of the view (`view_max`) took 0.09 s at 512 MiB against 0.30 s for copy plus tool, and 545 MiB worker RSS against 1057 MiB (section 4.1 file `sandbox_prewarm_zero_copy.json`). + +### 4.3 How a host should fill a block + +`benchmarks/shm_fill.py`, 512 MiB, 4 repeats: filling through the mapping (what `multiprocessing.shared_memory` and a Java `MappedByteBuffer` do) 0.396 s; `write()` into the descriptor 0.184 s; `MAP_POPULATE` 0.404 s; plain anonymous memory 1.6 s median [0.15-2.85]. A Python host that wants the minimum should create the block and `os.write` into its descriptor, not fill the mapping page by page. + +### 4.4 Memory + +* Worker RSS at 512 MiB: 547 MiB (TIFF read), 1059 MiB (block mapped plus copy), 545 MiB (borrowed view). The block is shared memory, not evictable without swap. +* `shm_bench` at 1 GiB, `invert`, shared input: host array 1 + block 1 + worker copy 1 + tool output 1 + result 1 (tmpfs) is 5 GiB with about 6 GiB available: the worker was SIGKILLed by the OOM killer (`code -9`, "out of memory?" in the host message), and the run aborted. The disk path of the same task finished three times because its input was clean, evictable page cache. This was the only run in this work that hit real memory pressure. A block per image is a hard commitment of RAM (and on Windows of commit charge) for the whole run. + +### 4.5 No-protocol alternative: the worker maps the TIFF + +`benchmarks/tiff_memmap.py`, 512 MiB uncompressed TIFF, read-only memmap versus `imread`, then one full pass: + +| cache | `imread` load + pass | `tifffile.memmap` load + pass | +|---|---|---| +| warm | 0.192 s | 0.037 s | +| cold | 0.576 s | 0.239 s | + +No private copy and no extra resident memory (the pages are the page cache). Constraints: only uncompressed, contiguous TIFFs (what Napari, Fiji and tifffile write); the mapping must be copy-on-write (`mode="c"`) so a tool that modifies its input cannot change the host's file; on Windows an open mapping blocks deleting the file, so the worker must drop it before `COMPLETION` and the host's `rmtree` and `prune` must tolerate a late release. This is the plan's idea 3; it is independent of everything below. + +### 4.6 What the Java hosts pay (Fiji's ImageJ 1.54p, JDK 21, same sandbox) + +`benchmarks/java/FijiExportBench.java`, 512 MiB (16384 x 16384 `ShortProcessor`), 9 samples: `FileSaver.saveAsTiff` **0.83 s [0.39-2.75]**; `Opener.openImage` of the result **0.78 s [0.55-0.93]**; Appose `SharedMemory.create` plus `ShortBuffer.put(short[])` **0.32 s [0.30-0.42]**; block to a new `short[]` **0.38 s [0.16-0.43]**. At 128 MiB everything is 0.1 to 0.2 s. The shared path is steady where the TIFF path is erratic, and it is about 2 to 2.5 times faster at the median for the whole export plus import. That is 0.5 s on the way out and 0.4 s on the way back per 512 MiB image. + +## 5. Feasibility per host + +| Host | Block from the host's own data, directly | Copies before the block | Verdict | +|---|---|---|---| +| Napari | yes (`SharedMemory` plus `np.copyto`) | 1 (layer array to block); 0 extra for numpy, 1 extra for dask/zarr unless stored chunk by chunk | **no gain on input; maybe on results** | +| Fiji | **yes**, with the Appose `SharedMemory`/`NDArray` already shipped | 1 (`short[]` plane to block) | **yes, first host** | +| QuPath | **maybe**: JDK-only works on Linux only; Windows and macOS need JNA or FFM | 2 to 3 (tile cache, `BufferedImage`, conversion) | **no, not now** | + +### 5.1 Napari (Python) + +* **Direct from layer data.** `export_layer` already does `np.asarray(layer.data[0] if multiscale else layer.data)`; the block version is `np.copyto(np.ndarray(shape, dtype, buffer=block.buf), data)`: **one copy** for numpy data, correct for non-contiguous input (transpose, strided slice and Fortran order all land in a C-ordered block with identical pixels, `benchmarks/shm_lifetime.py` T5); a dask or zarr layer needs `dask.array.store` into the view to avoid a temporary. RGB layers (`picked`) copy one colour channel. The 4 GiB `MAX_EXPORT_BYTES` guard stays. +* **Measured gain.** Export of 512 MiB: tifffile write 0.14 s versus block fill 0.40 s (mapping) or 0.18 s (`write()`); worker load 0.18 s versus 0.25 s. Nothing to win. +* **Results.** The only real Napari gain is mapping a result block as the layer's data (no TIFF decode, no allocation, about 0.2 s and 512 MiB saved at 512 MiB). Hazard measured: on Python 3.11 `SharedMemory.close()` (and `SharedMemory.__del__`) with a live numpy view on `shm.buf` **raises nothing and the view then segfaults** (T4). A shared-memory layer must hold an `mmap` object (T4b: `mmap.close()` under a live array raises `BufferError`, and the array keeps the mapping alive), not a bare `SharedMemory`. +* **Lifetime and crash.** Host `SIGKILL` with its resource tracker alive: the tracker unlinks the block (T1). Host and tracker killed together (process group, a crashed IDE or terminal): **the block stays in `/dev/shm`** (T2), so a start-up sweep is needed. POSIX allows unlinking while mapped (T3), so a host that maps a result can unlink it at once. +* **Windows.** `multiprocessing.shared_memory` creates a **pagefile-backed named section** (`CreateFileMapping(INVALID_HANDLE_VALUE, ..., name)`): no file, freed when the last handle closes (a crashed host leaves nothing), but it counts against the commit limit and can be paged out; the worker must open the name while the host still holds its handle. Python does not add `Local\` and Appose adds it for Java: both name the session-local object. Unverified here. +* **macOS.** POSIX shm: no filesystem entry, so no sweep by listing; names are limited to 31 characters (Python's `psm_xxxxxxxx` and Appose's 14-character names fit); size is rounded to the page size (16 KiB on Apple silicon) and a block survives a crashed creator until reboot unless something unlinks it (Python's resource tracker does, T1 logic). Unverified here. + +### 5.2 Fiji (Java 8 bytecode, Groovy script and jar) + +* **Java version.** The jar targets Java 8 bytecode ("runs in every Fiji bundle, Java 8 to 21", `pom.xml`). The current "Fiji with Java" distribution used in the project's clean-sandbox test was Java 21.0.7 (`docs/CLEAN_TEST_REPORT_2026-10-06.md`); older bundles ship an 8. Whatever is chosen must run on 8. +* **Options checked, each with a result.** + * **Appose `SharedMemory` / `NDArray` (JNA)**: `shm_open` + `ftruncate` + `mmap` on Linux, a bundled helper dylib on macOS (shm_open is variadic), `CreateFileMapping("Local\\" + name)` on Windows. It is the class the host already depends on (the Fiji host drives the worker with `org.apposed.appose.Service`; Appose 0.12.0 is what issue #66 cites). I compiled its 0.12.0 shm sources with `--release 8` against JNA 5.14 and ran a **real proof**: a Java process filled a `short[]` of random 16-bit values into an Appose block and the **real LabConstrictor worker** read it; the sum of all pixels, the first pixel, the shape and dtype matched exactly (`benchmarks/java_shm_proof.py --mode appose`: PASS, 32 MiB and 512 MiB). Byte order and unsigned values survive because the proof sets the buffer to native order explicitly (a plain big-endian `ByteBuffer` would not match numpy). Appose is only prior art for the user's parked decision, but the Fiji host already loads it, so this is no new dependency. + * **`MappedByteBuffer` on a file in `/dev/shm` (JDK only, Java 8+)**: PASS (`--mode mmap`), 0.32 s for 512 MiB. Linux only. Is it "not on disk"? On Linux `/dev/shm` is tmpfs: RAM, yes. On macOS there is no tmpfs path; a RAM disk needs privileges. On Windows a mapped temp file is file-backed: the cache manager still writes the dirty pages to disk later, Defender may scan it, and Java cannot unmap a `MappedByteBuffer` deterministically on 8 to 21, so the file stays locked and cannot be deleted while the process lives. So **a mapped temp file is "not on disk" only on Linux.** + * **Java 21 Foreign Function and Memory API**: PASS with `--enable-preview` (`--mode ffm`, `shm_open`/`mmap` straight from libc). It is a preview API in 21 (final in 22), needs a JVM flag Fiji's launcher does not set and does not exist on 8 to 20: **no**. + * **JNI**: would need a compiled library per OS: no. **ImgLib2**: no shared-memory support of its own (it can wrap a `ByteBuffer`, which Appose provides). Appose-like approaches are covered above. +* **Copies.** `ImagePlus` holds one `short[]`/`byte[]`/`float[]`/`int[]` per plane: one copy per plane into `block.buf(from, to)`. A `ByteBuffer` is limited to 2 GiB, so a larger image is filled in per-plane windows of one block (the block itself can be larger; the descriptor is unchanged). Stack axis order (ImageJ is channel, then Z, then T interleaved) and RGB (`int[]` to uint8) need explicit mapping to the declared axes; calibration stays explicit parameters. +* **Lifetime.** Appose creates with unlink-on-close. The host closes it in the existing `finally` (`closeWorker` path), including cancel and kill. A crashed Fiji leaves a block on Linux and macOS (no tracker in the JVM), nothing on Windows. + +### 5.3 QuPath (Groovy on QuPath's JVM) + +* **How pixels leave QuPath.** `ImageWriterTools.writeImageRegion(server, RegionRequest, path)`: tiles come from the `ImageServer` (decoded, possibly cached), are assembled into a `BufferedImage` (packed `int` ARGB for RGB images, `DataBufferUShort`/`Float` bands for fluorescence), then encoded. Before any block exists there are already 2 copies (server read plus the assembled `BufferedImage`), plus a third to reorder bands or unpack ARGB into the bytes numpy expects. The block would replace only the final encode and the file, and it must run through `BufferedImage` raster access (`getDataElements` per band) because the layout is not the worker's. +* **Scale.** The host refuses anything above 100 megapixels per plane (`MAX_EXPORT_PIXELS`), 200 MB for one 16-bit channel; large slides are read in regions whose decode time (JPEG, JPEG 2000) is of the same order as the TIFF write. The saving is a fraction of a second per run. +* **Mechanism.** The host has its own `LcWorker` (no Appose), so the descriptor goes through `Gson` easily, but the memory side is open: QuPath runs a bundled JDK (21, I believe, not verifiable here); JDK-only `MappedByteBuffer` on `/dev/shm` works only on Linux; I could not establish whether QuPath's `lib/app` contains JNA (`build.sh` compiles against `$QUPATH/lib/app/*`; check that folder). FFM is preview in 21. **Verdict: no for now**; revisit only if QuPath is changed to read regions into a worker-native layout and measured to matter. + +## 6. Protocol implications + +Everything is additive within protocol 1; nothing below changes the TIFF path. + +1. **Descriptor** (input, already accepted): `{"appose_type": "ndarray", "shm": {"name": ""}, "shape": [Y, X] or [Z, Y, X] ..., "dtype": "uint16"}`. Required additions to the worker, before any host sends one in anger: + * **`order`**: Appose's Java `NDArray.Shape` has an `Order` (C or F) and an ImgLib2-style host naturally has x fastest with shape `[x, y]`. The worker ignores `order`, so such a descriptor would be read **transposed with no error**: wrong science. Rule: a descriptor with `order` other than `C` is `unreadable_image`, or honoured with `np.ndarray(..., order="F")`; hosts must send C-order shapes (`[Y, X]`) anyway. Add a test with a non-square image. + * The shape must be consistent with the declared `axes` (issue #56) and the block size is checked before mapping; refuse more than a configured maximum. +2. **Feature flag**: `shm_input_v1` in `features.py` and in the PROTOCOL.md feature table: "the worker validates shared-memory image descriptors (order, size, dtype) and never unlinks a host block". A host sends a descriptor only when the schema's `features` list contains it (compat rules 2 and 3 already handle a missing list: refuse or file path). A schema without it means "send a TIFF". Never ask an unknown worker and fall back after partial work. +3. **Results (not recommended yet)**: a reserved input `_transport: {"image_out": "shm"}` (an old worker ignores it by `reserved_inputs_v1` and answers with a `path`, so the host falls back by looking at the answer) and a result `{type, name, axes, shm: {name}, shape, dtype}` with feature `shm_output_v1`. Ownership: the worker creates and detaches without a tracker (as `convert._attach_shared_memory` does for reading), the host maps, **unlinks at once**, and owns the mapping. Costs that are not technical: the results folder then holds no image file, so "keep my results", run records and `prune` expectations change; a durable copy has to be an explicit `FileOut`, as the issue already says. +4. **Run records and commands** must show the original source (file path or layer name), never the block name (`runs.record`, `command.py`, the "Copy as command" snippets): a block name is meaningless after the run. + +## 7. Cleanup, retention, crashes, Windows locking + +* **Blocks are not result folders.** They are never under `results/` or `runs/`, carry no `.lc-owner.json` or `.lc-done.json` and are never touched by `prune` (which only deletes marker-owned finished folders). The retention contract is unaffected for inputs. For shared results see 6.3. +* **Naming and ownership.** Name `lc__` (Linux `/dev/shm/lc_...`; at most 31 characters including the slash for macOS). The host writes the name into `/state/shm-.json` before creating it and deletes the file after unlinking. +* **Crash leftovers.** Host killed alone: Python's tracker removes the block (T1); the JVM has no tracker. Host and tracker both killed, or a JVM killed: Linux leaves `/dev/shm/lc_*` (T2); macOS leaves a kernel object until reboot or unlink; Windows leaves nothing. Remedy: at host start, read `state/shm-*.json` of dead pids and unlink those names (macOS) and glob `/dev/shm/lc_*` with a dead pid (Linux). This sweep is separate from `prune` and must never touch `results/` or `runs/`. +* **Worker side.** The worker never unlinks a host block (documented and tested). If the worker is killed mid-copy the host still owns the block and unlinks it in its `finally`. On Windows the worker closing its handle early is harmless. +* **Windows file locking.** The TIFF path already has the problem that a host `rmtree` of the job folder can fail while Defender or a viewer holds the file; blocks have no file. A memory-mapped TIFF in the worker (4.5) reintroduces it unless released before `COMPLETION`. Java file mappings (`MappedByteBuffer`) cannot be released deterministically on Java 8 to 21: do not use them on Windows. + +## 8. Recommended design (Fiji first) + +1. **Tools** (prerequisite, about 3 days): validate `order` and size in `_ndarray_from_shared_memory`; add `shm_input_v1` and its PROTOCOL.md row; a small `labconstrictor_tools.shm` helper (name scheme, create with `write()` fill, mmap-owning array, sweep); tests on Linux, macOS and Windows runners (attach, stale name, wrong order, wrong size, non-square image, worker killed); keep the copy in the worker (the borrowed view is a separate item with its own opt-in marker). +2. **Fiji** (about 4 to 5 days plus 2 to 3 days of Windows and macOS testing): in `exportOpenImage`, when the schema lists `shm_input_v1`, the image is at least 256 MiB (a setting, default off at first) and the tool input is an open image: create an Appose `NDArray`, fill per plane, send the descriptor, close in `finally`; any exception before the send falls back to the TIFF path; axis and RGB mapping with round-trip tests against the TIFF path (identical arrays for uint8, uint16, float32, RGB, stacks, a non-square image). Files chosen by the user are never copied into a block (the file path is already optimal). +3. **Measure on real Windows and macOS machines**, with Defender on, a spinning or network temp folder and a 1 to 2 GiB image, before any default change. Decision rule: default-on only if the median gain is at least 1 s at 512 MiB and the peak memory does not exceed the TIFF path by more than one image. +4. **Later, only if justified**: the worker's borrowed read-only view; results as blocks for Napari and Fiji as display-only previews. + +Total effort for steps 1 and 2: about 2 weeks including review and the three-OS run. Napari and QuPath: not scheduled. + +## 9. Risks + +* Memory: an extra, unevictable image per run (section 4.4); mitigate with the threshold, a free-memory check (refuse and use the TIFF path when available memory is below 3 times the image) and releasing the host-side copy early. +* Silent wrong pixels: axis order, `order`, byte order, signedness, ImageJ's channel-first stack order, 2 GiB `ByteBuffer` windows. Mitigation: the `order` check, the round-trip tests above, the TIFF path kept as the reference. +* Leaks after crashes (section 7) and Windows commit charge. +* Platform divergence: Linux proven here, Windows and macOS only read; a macOS helper dylib inside Appose; JNA availability in Fiji and QuPath bundles. +* Product semantics of shared results (6.3). +* The measured gain is small on a warm cache; a user with a fast SSD and an image under 256 MiB gets nothing. + +## 10. What I could not verify + +* Windows and macOS behaviour of every item (named sections, commit charge, shm name limits, helper dylib, Defender). Section 5 and 7 statements for those OSes are from documentation and source reading. +* Real Fiji, QuPath and Napari runs (GUI, ImageJ stack layouts, `BufferedImage` conversion cost, display time of large results). The Fiji numbers are ImageJ 1.54p library calls in a headless JVM. +* Which Java versions current Fiji bundles ship beyond the 21.0.7 recorded in the clean-test report, and whether JNA and Appose 0.12.0 are in a given Fiji bundle (the host script imports Appose, so it must be; not checked in a Fiji install). +* QuPath's bundled JDK and whether its `lib/app` contains JNA. +* Slow disks, network folders, antivirus: the sandbox disk reads at 1.5 GB/s warm or cold, which a user's will not. +* The 1 GiB shared round trip never completed (OOM), so there is no 1 GiB number for it; a bigger machine is needed. +* Maven Central returned HTTP 429, so Appose was compiled from its 0.12.0 sources (fetched from GitHub raw, `--release 8`) with JNA 5.14.0 from Maven Central, not taken from the released jar. +* Statistical weight: 3 runs per cell (the user's request), 9 for the Java numbers; spreads are shown because they are large and the sandbox is shared. + +## 11. Reproduce + +``` +python -m pip install numpy tifffile pandas +python benchmarks/shm_bench.py --sizes 128 512 1024 --repeats 3 --cli --json out.json # default mode +python benchmarks/shm_bench.py --sizes 128 512 --repeats 3 --prewarm 2 --json out2.json # prewarmed +python benchmarks/shm_bench.py --sizes 512 --tools image_max --cold --prewarm 2 # drops the page cache (root) +python benchmarks/shm_bench.py --sizes 1024 --tools passthrough --no-readback --out-scratch /dev/shm/x # memory-careful 1 GiB +python benchmarks/shm_breakdown.py --mb 512 --repeats 5 [--prewarm] +python benchmarks/shm_fill.py --mb 512 +python benchmarks/tiff_memmap.py --mb 512 [--cold] +python benchmarks/shm_lifetime.py # Linux: crash, unlink and view hazards +python benchmarks/shm_table.py benchmarks/results/*.json +# Java (JDK 21; Appose 0.12.0 jar or its sources, JNA 5.14 and jna-platform on the class path; ij-1.54p for FijiExportBench): +javac --release 8 -cp appose.jar:jna.jar -d out benchmarks/java/ShmProof.java benchmarks/java/FijiExportBench.java +javac --release 21 --enable-preview -d out benchmarks/java/ShmProofFfm.java +python benchmarks/java_shm_proof.py --mode appose|mmap|ffm --classpath out:appose.jar:jna.jar:jna-platform.jar +java -cp out:ij.jar:appose.jar:jna.jar:jna-platform.jar FijiExportBench 16384 3 /tmp +``` + +The harness aborts and removes its scratch folders when `MemAvailable` falls below 700 MiB (`--guard-mib`), because the machine it was written on is shared. diff --git a/pyproject.toml b/pyproject.toml index b5b02d1..f2ec48b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,6 +43,7 @@ ignore = ["E501", "UP031", "UP032", "B905"] [tool.ruff.lint.per-file-ignores] "tests/**" = ["E402", "B007", "S", "BLE", "RUF100"] # test scripts set up sys.path / env before importing; they assert, run subprocesses and expect failures on purpose +"benchmarks/**" = ["E402", "S"] # measurement scripts: they put the checkout on sys.path, start processes, use /dev/shm and the temp folder on purpose "tests/vulture_whitelist.py" = ["B018", "F821"] # bare names on purpose: that is how vulture is told a name is used [tool.coverage.run]