diff options
Diffstat (limited to 'research/experiments/005-storage-edit-latency')
8 files changed, 1638 insertions, 0 deletions
diff --git a/research/experiments/005-storage-edit-latency/2026-09-24-check-hybrid.log.gz b/research/experiments/005-storage-edit-latency/2026-09-24-check-hybrid.log.gz Binary files differnew file mode 100644 index 0000000..e4c0174 --- /dev/null +++ b/research/experiments/005-storage-edit-latency/2026-09-24-check-hybrid.log.gz diff --git a/research/experiments/005-storage-edit-latency/2026-09-24-ext4-linux-aarch64.json b/research/experiments/005-storage-edit-latency/2026-09-24-ext4-linux-aarch64.json new file mode 100644 index 0000000..f9decda --- /dev/null +++ b/research/experiments/005-storage-edit-latency/2026-09-24-ext4-linux-aarch64.json @@ -0,0 +1,463 @@ +{ + "profile": "native-cli-durable-one-mib-document-last-byte-edit", + "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41", + "filesystem": "ext4 /dev/mmcblk0p2[/home/eunhhu/work/pure]", + "trials_per_variant": 18, + "final_body_sha256": "06cb5e32505f66804f6e8c79e3230105ca4769444e1389ee36f6f11fd61f2d3a", + "scope": "Each sample starts a new CLI process; create and edit each include program parsing, store initialization, file and directory synchronization. Show verifies the final revision but is outside the timed operations. The host page cache, filesystem and device remain uncontrolled.", + "variants": { + "flat": { + "binary_sha256": "23ebc0ce1df9c49216511bee658fd5b9e373509e296bd2c2f8e76e6d3081cded", + "median_create_ms": 83.556, + "median_edit_ms": 78.805, + "samples": [ + { + "trial": 0, + "create_ms": 93.308, + "edit_ms": 86.265, + "store_files": 2, + "store_file_bytes": 1048600, + "store_allocated_bytes": 1052672 + }, + { + "trial": 1, + "create_ms": 66.85, + "edit_ms": 81.315, + "store_files": 2, + "store_file_bytes": 1048600, + "store_allocated_bytes": 1052672 + }, + { + "trial": 2, + "create_ms": 83.243, + "edit_ms": 26.218, + "store_files": 2, + "store_file_bytes": 1048600, + "store_allocated_bytes": 1052672 + }, + { + "trial": 3, + "create_ms": 25.734, + "edit_ms": 81.636, + "store_files": 2, + "store_file_bytes": 1048600, + "store_allocated_bytes": 1052672 + }, + { + "trial": 4, + "create_ms": 80.359, + "edit_ms": 22.923, + "store_files": 2, + "store_file_bytes": 1048600, + "store_allocated_bytes": 1052672 + }, + { + "trial": 5, + "create_ms": 84.855, + "edit_ms": 77.624, + "store_files": 2, + "store_file_bytes": 1048600, + "store_allocated_bytes": 1052672 + }, + { + "trial": 6, + "create_ms": 83.516, + "edit_ms": 24.882, + "store_files": 2, + "store_file_bytes": 1048600, + "store_allocated_bytes": 1052672 + }, + { + "trial": 7, + "create_ms": 100.653, + "edit_ms": 65.551, + "store_files": 2, + "store_file_bytes": 1048600, + "store_allocated_bytes": 1052672 + }, + { + "trial": 8, + "create_ms": 87.547, + "edit_ms": 88.306, + "store_files": 2, + "store_file_bytes": 1048600, + "store_allocated_bytes": 1052672 + }, + { + "trial": 9, + "create_ms": 100.781, + "edit_ms": 89.489, + "store_files": 2, + "store_file_bytes": 1048600, + "store_allocated_bytes": 1052672 + }, + { + "trial": 10, + "create_ms": 29.332, + "edit_ms": 79.987, + "store_files": 2, + "store_file_bytes": 1048600, + "store_allocated_bytes": 1052672 + }, + { + "trial": 11, + "create_ms": 80.05, + "edit_ms": 26.629, + "store_files": 2, + "store_file_bytes": 1048600, + "store_allocated_bytes": 1052672 + }, + { + "trial": 12, + "create_ms": 79.751, + "edit_ms": 24.165, + "store_files": 2, + "store_file_bytes": 1048600, + "store_allocated_bytes": 1052672 + }, + { + "trial": 13, + "create_ms": 85.309, + "edit_ms": 23.163, + "store_files": 2, + "store_file_bytes": 1048600, + "store_allocated_bytes": 1052672 + }, + { + "trial": 14, + "create_ms": 83.597, + "edit_ms": 82.171, + "store_files": 2, + "store_file_bytes": 1048600, + "store_allocated_bytes": 1052672 + }, + { + "trial": 15, + "create_ms": 97.909, + "edit_ms": 85.934, + "store_files": 2, + "store_file_bytes": 1048600, + "store_allocated_bytes": 1052672 + }, + { + "trial": 16, + "create_ms": 25.638, + "edit_ms": 82.514, + "store_files": 2, + "store_file_bytes": 1048600, + "store_allocated_bytes": 1052672 + }, + { + "trial": 17, + "create_ms": 86.699, + "edit_ms": 23.813, + "store_files": 2, + "store_file_bytes": 1048600, + "store_allocated_bytes": 1052672 + } + ] + }, + "copy": { + "binary_sha256": "52c2b828b0cba3564a37e3874f60bec793d1dd7031aff77ba850cee7683977f9", + "median_create_ms": 81.672, + "median_edit_ms": 77.908, + "samples": [ + { + "trial": 0, + "create_ms": 29.767, + "edit_ms": 78.001, + "store_files": 2, + "store_file_bytes": 1048600, + "store_allocated_bytes": 1052672 + }, + { + "trial": 1, + "create_ms": 89.789, + "edit_ms": 91.286, + "store_files": 2, + "store_file_bytes": 1048600, + "store_allocated_bytes": 1052672 + }, + { + "trial": 2, + "create_ms": 83.106, + "edit_ms": 77.868, + "store_files": 2, + "store_file_bytes": 1048600, + "store_allocated_bytes": 1052672 + }, + { + "trial": 3, + "create_ms": 84.346, + "edit_ms": 47.881, + "store_files": 2, + "store_file_bytes": 1048600, + "store_allocated_bytes": 1052672 + }, + { + "trial": 4, + "create_ms": 29.06, + "edit_ms": 78.142, + "store_files": 2, + "store_file_bytes": 1048600, + "store_allocated_bytes": 1052672 + }, + { + "trial": 5, + "create_ms": 29.801, + "edit_ms": 52.17, + "store_files": 2, + "store_file_bytes": 1048600, + "store_allocated_bytes": 1052672 + }, + { + "trial": 6, + "create_ms": 81.026, + "edit_ms": 77.948, + "store_files": 2, + "store_file_bytes": 1048600, + "store_allocated_bytes": 1052672 + }, + { + "trial": 7, + "create_ms": 30.027, + "edit_ms": 87.974, + "store_files": 2, + "store_file_bytes": 1048600, + "store_allocated_bytes": 1052672 + }, + { + "trial": 8, + "create_ms": 45.522, + "edit_ms": 87.955, + "store_files": 2, + "store_file_bytes": 1048600, + "store_allocated_bytes": 1052672 + }, + { + "trial": 9, + "create_ms": 80.228, + "edit_ms": 22.863, + "store_files": 2, + "store_file_bytes": 1048600, + "store_allocated_bytes": 1052672 + }, + { + "trial": 10, + "create_ms": 82.319, + "edit_ms": 77.564, + "store_files": 2, + "store_file_bytes": 1048600, + "store_allocated_bytes": 1052672 + }, + { + "trial": 11, + "create_ms": 94.951, + "edit_ms": 46.186, + "store_files": 2, + "store_file_bytes": 1048600, + "store_allocated_bytes": 1052672 + }, + { + "trial": 12, + "create_ms": 84.607, + "edit_ms": 80.2, + "store_files": 2, + "store_file_bytes": 1048600, + "store_allocated_bytes": 1052672 + }, + { + "trial": 13, + "create_ms": 29.82, + "edit_ms": 86.258, + "store_files": 2, + "store_file_bytes": 1048600, + "store_allocated_bytes": 1052672 + }, + { + "trial": 14, + "create_ms": 94.36, + "edit_ms": 31.893, + "store_files": 2, + "store_file_bytes": 1048600, + "store_allocated_bytes": 1052672 + }, + { + "trial": 15, + "create_ms": 97.289, + "edit_ms": 44.737, + "store_files": 2, + "store_file_bytes": 1048600, + "store_allocated_bytes": 1052672 + }, + { + "trial": 16, + "create_ms": 60.805, + "edit_ms": 80.635, + "store_files": 2, + "store_file_bytes": 1048600, + "store_allocated_bytes": 1052672 + }, + { + "trial": 17, + "create_ms": 85.887, + "edit_ms": 77.182, + "store_files": 2, + "store_file_bytes": 1048600, + "store_allocated_bytes": 1052672 + } + ] + }, + "paged": { + "binary_sha256": "e1c12a2f5e736bb86737ceff7849fe95b1a9d13136e8c5eb3f3398cb3971c6f5", + "median_create_ms": 88.948, + "median_edit_ms": 14.473, + "samples": [ + { + "trial": 0, + "create_ms": 117.897, + "edit_ms": 565.484, + "store_files": 3, + "store_file_bytes": 1065520, + "store_allocated_bytes": 1069056 + }, + { + "trial": 1, + "create_ms": 47.619, + "edit_ms": 13.102, + "store_files": 3, + "store_file_bytes": 1065520, + "store_allocated_bytes": 1069056 + }, + { + "trial": 2, + "create_ms": 89.46, + "edit_ms": 14.779, + "store_files": 3, + "store_file_bytes": 1065520, + "store_allocated_bytes": 1069056 + }, + { + "trial": 3, + "create_ms": 30.501, + "edit_ms": 15.016, + "store_files": 3, + "store_file_bytes": 1065520, + "store_allocated_bytes": 1069056 + }, + { + "trial": 4, + "create_ms": 89.223, + "edit_ms": 13.383, + "store_files": 3, + "store_file_bytes": 1065520, + "store_allocated_bytes": 1069056 + }, + { + "trial": 5, + "create_ms": 88.518, + "edit_ms": 12.718, + "store_files": 3, + "store_file_bytes": 1065520, + "store_allocated_bytes": 1069056 + }, + { + "trial": 6, + "create_ms": 88.992, + "edit_ms": 13.681, + "store_files": 3, + "store_file_bytes": 1065520, + "store_allocated_bytes": 1069056 + }, + { + "trial": 7, + "create_ms": 116.568, + "edit_ms": 23.607, + "store_files": 3, + "store_file_bytes": 1065520, + "store_allocated_bytes": 1069056 + }, + { + "trial": 8, + "create_ms": 100.547, + "edit_ms": 24.497, + "store_files": 3, + "store_file_bytes": 1065520, + "store_allocated_bytes": 1069056 + }, + { + "trial": 9, + "create_ms": 54.374, + "edit_ms": 13.896, + "store_files": 3, + "store_file_bytes": 1065520, + "store_allocated_bytes": 1069056 + }, + { + "trial": 10, + "create_ms": 84.894, + "edit_ms": 13.607, + "store_files": 3, + "store_file_bytes": 1065520, + "store_allocated_bytes": 1069056 + }, + { + "trial": 11, + "create_ms": 92.673, + "edit_ms": 14.166, + "store_files": 3, + "store_file_bytes": 1065520, + "store_allocated_bytes": 1069056 + }, + { + "trial": 12, + "create_ms": 34.961, + "edit_ms": 78.767, + "store_files": 3, + "store_file_bytes": 1065520, + "store_allocated_bytes": 1069056 + }, + { + "trial": 13, + "create_ms": 88.903, + "edit_ms": 13.656, + "store_files": 3, + "store_file_bytes": 1065520, + "store_allocated_bytes": 1069056 + }, + { + "trial": 14, + "create_ms": 57.426, + "edit_ms": 13.968, + "store_files": 3, + "store_file_bytes": 1065520, + "store_allocated_bytes": 1069056 + }, + { + "trial": 15, + "create_ms": 38.675, + "edit_ms": 14.937, + "store_files": 3, + "store_file_bytes": 1065520, + "store_allocated_bytes": 1069056 + }, + { + "trial": 16, + "create_ms": 90.664, + "edit_ms": 15.344, + "store_files": 3, + "store_file_bytes": 1065520, + "store_allocated_bytes": 1069056 + }, + { + "trial": 17, + "create_ms": 90.055, + "edit_ms": 14.926, + "store_files": 3, + "store_file_bytes": 1065520, + "store_allocated_bytes": 1069056 + } + ] + } + } +} diff --git a/research/experiments/005-storage-edit-latency/2026-09-24-sequence-ext4-linux-aarch64.json b/research/experiments/005-storage-edit-latency/2026-09-24-sequence-ext4-linux-aarch64.json new file mode 100644 index 0000000..5efbf8b --- /dev/null +++ b/research/experiments/005-storage-edit-latency/2026-09-24-sequence-ext4-linux-aarch64.json @@ -0,0 +1,862 @@ +{ + "profile": "repeated-durable-one-mib-document-last-byte-edit", + "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41", + "filesystem": "ext4 /dev/mmcblk0p2[/home/eunhhu/work/pure]", + "edits_per_variant": 70, + "final_body_sha256": "3cfc240f48e8e1b8553f3e2670adf7b81cafe34f089d4372fa4c28787dc02151", + "scope": "Same actual source-loaded CLI and editor.pure, two persistent stores, alternating operation order. Timings include each edit process, parser, store init and fsync; creation and final show are not timed. Device state is uncontrolled.", + "variants": { + "flat": { + "binary_sha256": "23ebc0ce1df9c49216511bee658fd5b9e373509e296bd2c2f8e76e6d3081cded", + "median_edit_ms": 83.176, + "samples": [ + { + "edit": 1, + "elapsed_ms": 24.328, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 2, + "elapsed_ms": 79.862, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 3, + "elapsed_ms": 177.059, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 4, + "elapsed_ms": 89.804, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 5, + "elapsed_ms": 92.579, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 6, + "elapsed_ms": 83.733, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 7, + "elapsed_ms": 29.379, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 8, + "elapsed_ms": 78.191, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 9, + "elapsed_ms": 57.551, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 10, + "elapsed_ms": 83.875, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 11, + "elapsed_ms": 78.209, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 12, + "elapsed_ms": 85.296, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 13, + "elapsed_ms": 25.204, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 14, + "elapsed_ms": 28.663, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 15, + "elapsed_ms": 82.153, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 16, + "elapsed_ms": 84.924, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 17, + "elapsed_ms": 82.359, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 18, + "elapsed_ms": 39.211, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 19, + "elapsed_ms": 28.648, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 20, + "elapsed_ms": 82.115, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 21, + "elapsed_ms": 83.895, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 22, + "elapsed_ms": 83.007, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 23, + "elapsed_ms": 84.496, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 24, + "elapsed_ms": 28.525, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 25, + "elapsed_ms": 86.499, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 26, + "elapsed_ms": 25.536, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 27, + "elapsed_ms": 93.217, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 28, + "elapsed_ms": 36.673, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 29, + "elapsed_ms": 84.748, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 30, + "elapsed_ms": 79.529, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 31, + "elapsed_ms": 84.024, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 32, + "elapsed_ms": 82.681, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 33, + "elapsed_ms": 28.903, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 34, + "elapsed_ms": 29.254, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 35, + "elapsed_ms": 86.486, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 36, + "elapsed_ms": 96.679, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 37, + "elapsed_ms": 41.477, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 38, + "elapsed_ms": 82.386, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 39, + "elapsed_ms": 25.063, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 40, + "elapsed_ms": 27.84, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 41, + "elapsed_ms": 86.119, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 42, + "elapsed_ms": 89.284, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 43, + "elapsed_ms": 84.316, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 44, + "elapsed_ms": 86.972, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 45, + "elapsed_ms": 88.795, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 46, + "elapsed_ms": 47.265, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 47, + "elapsed_ms": 32.736, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 48, + "elapsed_ms": 93.95, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 49, + "elapsed_ms": 29.861, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 50, + "elapsed_ms": 25.674, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 51, + "elapsed_ms": 87.319, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 52, + "elapsed_ms": 83.632, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 53, + "elapsed_ms": 83.964, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 54, + "elapsed_ms": 83.345, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 55, + "elapsed_ms": 175.728, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 56, + "elapsed_ms": 92.189, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 57, + "elapsed_ms": 98.676, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 58, + "elapsed_ms": 84.905, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 59, + "elapsed_ms": 81.966, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 60, + "elapsed_ms": 87.203, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 61, + "elapsed_ms": 25.923, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 62, + "elapsed_ms": 29.165, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 63, + "elapsed_ms": 82.076, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 64, + "elapsed_ms": 128.506, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 65, + "elapsed_ms": 91.837, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 66, + "elapsed_ms": 25.832, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 67, + "elapsed_ms": 86.189, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 68, + "elapsed_ms": 83.351, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 69, + "elapsed_ms": 85.479, + "files": 2, + "allocated_bytes": 1052672 + }, + { + "edit": 70, + "elapsed_ms": 77.587, + "files": 2, + "allocated_bytes": 1052672 + } + ] + }, + "paged": { + "binary_sha256": "e1c12a2f5e736bb86737ceff7849fe95b1a9d13136e8c5eb3f3398cb3971c6f5", + "median_edit_ms": 18.858, + "samples": [ + { + "edit": 1, + "elapsed_ms": 16.412, + "files": 3, + "allocated_bytes": 1069056 + }, + { + "edit": 2, + "elapsed_ms": 17.281, + "files": 3, + "allocated_bytes": 1085440 + }, + { + "edit": 3, + "elapsed_ms": 32.037, + "files": 3, + "allocated_bytes": 1101824 + }, + { + "edit": 4, + "elapsed_ms": 29.739, + "files": 3, + "allocated_bytes": 1118208 + }, + { + "edit": 5, + "elapsed_ms": 28.746, + "files": 3, + "allocated_bytes": 1134592 + }, + { + "edit": 6, + "elapsed_ms": 31.822, + "files": 3, + "allocated_bytes": 1150976 + }, + { + "edit": 7, + "elapsed_ms": 16.937, + "files": 3, + "allocated_bytes": 1167360 + }, + { + "edit": 8, + "elapsed_ms": 16.845, + "files": 3, + "allocated_bytes": 1183744 + }, + { + "edit": 9, + "elapsed_ms": 17.18, + "files": 3, + "allocated_bytes": 1200128 + }, + { + "edit": 10, + "elapsed_ms": 18.422, + "files": 3, + "allocated_bytes": 1216512 + }, + { + "edit": 11, + "elapsed_ms": 18.672, + "files": 3, + "allocated_bytes": 1232896 + }, + { + "edit": 12, + "elapsed_ms": 16.399, + "files": 3, + "allocated_bytes": 1249280 + }, + { + "edit": 13, + "elapsed_ms": 18.911, + "files": 3, + "allocated_bytes": 1265664 + }, + { + "edit": 14, + "elapsed_ms": 71.604, + "files": 3, + "allocated_bytes": 1282048 + }, + { + "edit": 15, + "elapsed_ms": 18.821, + "files": 3, + "allocated_bytes": 1298432 + }, + { + "edit": 16, + "elapsed_ms": 16.746, + "files": 3, + "allocated_bytes": 1314816 + }, + { + "edit": 17, + "elapsed_ms": 17.354, + "files": 3, + "allocated_bytes": 1331200 + }, + { + "edit": 18, + "elapsed_ms": 15.468, + "files": 3, + "allocated_bytes": 1347584 + }, + { + "edit": 19, + "elapsed_ms": 15.872, + "files": 3, + "allocated_bytes": 1363968 + }, + { + "edit": 20, + "elapsed_ms": 18.347, + "files": 3, + "allocated_bytes": 1380352 + }, + { + "edit": 21, + "elapsed_ms": 17.311, + "files": 3, + "allocated_bytes": 1396736 + }, + { + "edit": 22, + "elapsed_ms": 18.997, + "files": 3, + "allocated_bytes": 1413120 + }, + { + "edit": 23, + "elapsed_ms": 17.267, + "files": 3, + "allocated_bytes": 1429504 + }, + { + "edit": 24, + "elapsed_ms": 18.52, + "files": 3, + "allocated_bytes": 1445888 + }, + { + "edit": 25, + "elapsed_ms": 34.127, + "files": 3, + "allocated_bytes": 1462272 + }, + { + "edit": 26, + "elapsed_ms": 86.489, + "files": 3, + "allocated_bytes": 1478656 + }, + { + "edit": 27, + "elapsed_ms": 29.105, + "files": 3, + "allocated_bytes": 1495040 + }, + { + "edit": 28, + "elapsed_ms": 37.131, + "files": 3, + "allocated_bytes": 1511424 + }, + { + "edit": 29, + "elapsed_ms": 15.478, + "files": 3, + "allocated_bytes": 1527808 + }, + { + "edit": 30, + "elapsed_ms": 19.623, + "files": 3, + "allocated_bytes": 1544192 + }, + { + "edit": 31, + "elapsed_ms": 90.312, + "files": 3, + "allocated_bytes": 1560576 + }, + { + "edit": 32, + "elapsed_ms": 17.365, + "files": 3, + "allocated_bytes": 1576960 + }, + { + "edit": 33, + "elapsed_ms": 17.109, + "files": 3, + "allocated_bytes": 1593344 + }, + { + "edit": 34, + "elapsed_ms": 126.006, + "files": 3, + "allocated_bytes": 1609728 + }, + { + "edit": 35, + "elapsed_ms": 17.457, + "files": 3, + "allocated_bytes": 1626112 + }, + { + "edit": 36, + "elapsed_ms": 15.908, + "files": 3, + "allocated_bytes": 1642496 + }, + { + "edit": 37, + "elapsed_ms": 18.896, + "files": 3, + "allocated_bytes": 1658880 + }, + { + "edit": 38, + "elapsed_ms": 16.535, + "files": 3, + "allocated_bytes": 1675264 + }, + { + "edit": 39, + "elapsed_ms": 17.568, + "files": 3, + "allocated_bytes": 1691648 + }, + { + "edit": 40, + "elapsed_ms": 71.184, + "files": 3, + "allocated_bytes": 1708032 + }, + { + "edit": 41, + "elapsed_ms": 16.619, + "files": 3, + "allocated_bytes": 1724416 + }, + { + "edit": 42, + "elapsed_ms": 29.265, + "files": 3, + "allocated_bytes": 1740800 + }, + { + "edit": 43, + "elapsed_ms": 21.163, + "files": 3, + "allocated_bytes": 1757184 + }, + { + "edit": 44, + "elapsed_ms": 27.305, + "files": 3, + "allocated_bytes": 1773568 + }, + { + "edit": 45, + "elapsed_ms": 29.526, + "files": 3, + "allocated_bytes": 1789952 + }, + { + "edit": 46, + "elapsed_ms": 27.936, + "files": 3, + "allocated_bytes": 1806336 + }, + { + "edit": 47, + "elapsed_ms": 87.552, + "files": 3, + "allocated_bytes": 1822720 + }, + { + "edit": 48, + "elapsed_ms": 30.512, + "files": 3, + "allocated_bytes": 1839104 + }, + { + "edit": 49, + "elapsed_ms": 17.81, + "files": 3, + "allocated_bytes": 1855488 + }, + { + "edit": 50, + "elapsed_ms": 70.4, + "files": 3, + "allocated_bytes": 1871872 + }, + { + "edit": 51, + "elapsed_ms": 17.115, + "files": 3, + "allocated_bytes": 1888256 + }, + { + "edit": 52, + "elapsed_ms": 18.79, + "files": 3, + "allocated_bytes": 1904640 + }, + { + "edit": 53, + "elapsed_ms": 21.637, + "files": 3, + "allocated_bytes": 1921024 + }, + { + "edit": 54, + "elapsed_ms": 16.47, + "files": 3, + "allocated_bytes": 1937408 + }, + { + "edit": 55, + "elapsed_ms": 53.194, + "files": 3, + "allocated_bytes": 1953792 + }, + { + "edit": 56, + "elapsed_ms": 219.485, + "files": 3, + "allocated_bytes": 1970176 + }, + { + "edit": 57, + "elapsed_ms": 24.517, + "files": 3, + "allocated_bytes": 1986560 + }, + { + "edit": 58, + "elapsed_ms": 16.725, + "files": 3, + "allocated_bytes": 2002944 + }, + { + "edit": 59, + "elapsed_ms": 19.628, + "files": 3, + "allocated_bytes": 2019328 + }, + { + "edit": 60, + "elapsed_ms": 17.158, + "files": 3, + "allocated_bytes": 2035712 + }, + { + "edit": 61, + "elapsed_ms": 72.424, + "files": 3, + "allocated_bytes": 2052096 + }, + { + "edit": 62, + "elapsed_ms": 16.894, + "files": 3, + "allocated_bytes": 2068480 + }, + { + "edit": 63, + "elapsed_ms": 18.918, + "files": 3, + "allocated_bytes": 2084864 + }, + { + "edit": 64, + "elapsed_ms": 16.879, + "files": 3, + "allocated_bytes": 2101248 + }, + { + "edit": 65, + "elapsed_ms": 35.067, + "files": 3, + "allocated_bytes": 1052672 + }, + { + "edit": 66, + "elapsed_ms": 83.189, + "files": 3, + "allocated_bytes": 1069056 + }, + { + "edit": 67, + "elapsed_ms": 16.607, + "files": 3, + "allocated_bytes": 1085440 + }, + { + "edit": 68, + "elapsed_ms": 19.566, + "files": 3, + "allocated_bytes": 1101824 + }, + { + "edit": 69, + "elapsed_ms": 17.47, + "files": 3, + "allocated_bytes": 1118208 + }, + { + "edit": 70, + "elapsed_ms": 20.338, + "files": 3, + "allocated_bytes": 1134592 + } + ] + } + } +} diff --git a/research/experiments/005-storage-edit-latency/copy-memory.json b/research/experiments/005-storage-edit-latency/copy-memory.json new file mode 100644 index 0000000..969250c --- /dev/null +++ b/research/experiments/005-storage-edit-latency/copy-memory.json @@ -0,0 +1,43 @@ +{ + "passed": true, + "failures": [], + "profile": "portable-measurement-no-budget", + "variant": "source-program", + "scope": "Child-process peak RSS for native CLI document creation, read and one-byte revision edit; includes libc and the selected program form, excludes filesystem cache, kernel buffers, TLS, GUI and other apps. No cross-platform memory ceiling is asserted.", + "samples": { + "small_edit_rss_kib": 1056, + "one_mib_edit_rss_kib": 2080, + "one_mib_show_rss_kib": 1104, + "one_mib_splice_rss_kib": 1056 + }, + "raw_samples": { + "small_edit_rss_kib": { + "exit_code": 0, + "max_rss_kib": 1056, + "raw_max_rss": 1056, + "raw_unit": "KiB" + }, + "one_mib_edit_rss_kib": { + "exit_code": 0, + "max_rss_kib": 2080, + "raw_max_rss": 2080, + "raw_unit": "KiB" + }, + "one_mib_show_rss_kib": { + "exit_code": 0, + "max_rss_kib": 1104, + "raw_max_rss": 1104, + "raw_unit": "KiB" + }, + "one_mib_splice_rss_kib": { + "exit_code": 0, + "max_rss_kib": 1056, + "raw_max_rss": 1056, + "raw_unit": "KiB" + } + }, + "budget_sha256": null, + "binary_sha256": "52c2b828b0cba3564a37e3874f60bec793d1dd7031aff77ba850cee7683977f9", + "binary_bytes": 178824, + "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41" +} diff --git a/research/experiments/005-storage-edit-latency/flat-memory.json b/research/experiments/005-storage-edit-latency/flat-memory.json new file mode 100644 index 0000000..3f45eb1 --- /dev/null +++ b/research/experiments/005-storage-edit-latency/flat-memory.json @@ -0,0 +1,43 @@ +{ + "passed": true, + "failures": [], + "profile": "portable-measurement-no-budget", + "variant": "source-program", + "scope": "Child-process peak RSS for native CLI document creation, read and one-byte revision edit; includes libc and the selected program form, excludes filesystem cache, kernel buffers, TLS, GUI and other apps. No cross-platform memory ceiling is asserted.", + "samples": { + "small_edit_rss_kib": 1056, + "one_mib_edit_rss_kib": 2080, + "one_mib_show_rss_kib": 1056, + "one_mib_splice_rss_kib": 1104 + }, + "raw_samples": { + "small_edit_rss_kib": { + "exit_code": 0, + "max_rss_kib": 1056, + "raw_max_rss": 1056, + "raw_unit": "KiB" + }, + "one_mib_edit_rss_kib": { + "exit_code": 0, + "max_rss_kib": 2080, + "raw_max_rss": 2080, + "raw_unit": "KiB" + }, + "one_mib_show_rss_kib": { + "exit_code": 0, + "max_rss_kib": 1056, + "raw_max_rss": 1056, + "raw_unit": "KiB" + }, + "one_mib_splice_rss_kib": { + "exit_code": 0, + "max_rss_kib": 1104, + "raw_max_rss": 1104, + "raw_unit": "KiB" + } + }, + "budget_sha256": null, + "binary_sha256": "23ebc0ce1df9c49216511bee658fd5b9e373509e296bd2c2f8e76e6d3081cded", + "binary_bytes": 178336, + "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41" +} diff --git a/research/experiments/005-storage-edit-latency/measure.py b/research/experiments/005-storage-edit-latency/measure.py new file mode 100644 index 0000000..b390c92 --- /dev/null +++ b/research/experiments/005-storage-edit-latency/measure.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python3 +"""Time the same durable one-MiB document creation and one-byte revision edit.""" +import argparse +import hashlib +import json +from pathlib import Path +import platform +import statistics +import subprocess +import tempfile +import time + +HERE = Path(__file__).resolve().parents[3] +PROGRAM = HERE / 'prototypes/connections/examples/editor.pure' +INITIAL = b'A' * 1_048_576 +EXPECTED = INITIAL[:-1] + b'Z' + + +def invoke(command): + started = time.monotonic_ns() + result = subprocess.run([str(arg) for arg in command], capture_output=True, timeout=30) + elapsed_ms = (time.monotonic_ns() - started) / 1_000_000 + if result.returncode: + raise AssertionError((command, result.returncode, result.stderr[-1000:])) + return result, elapsed_ms + + +def one(binary, root, initial, replacement): + base = [binary, '--program', PROGRAM, '--store', root] + created, create_ms = invoke([*base, 'edit', 'document', 0, 0, 0, initial]) + assert json.loads(created.stdout)['revision'] == '1' + edited, edit_ms = invoke([*base, 'edit', 'document', 1, 1_048_575, 1, replacement]) + assert json.loads(edited.stdout)['revision'] == '2' + shown, _ = invoke([*base, 'show', 'document']) + assert shown.stdout == EXPECTED + assert json.loads(shown.stderr)['revision'] == '2' + files = [path for path in root.iterdir() if path.is_file()] + return {'create_ms': round(create_ms, 3), 'edit_ms': round(edit_ms, 3), + 'store_files': len(files), + 'store_file_bytes': sum(path.stat().st_size for path in files), + 'store_allocated_bytes': sum(path.stat().st_blocks * 512 for path in files)} + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--flat', type=Path, required=True) + parser.add_argument('--copy', type=Path, required=True) + parser.add_argument('--paged', type=Path, required=True) + parser.add_argument('--scratch-parent', type=Path, required=True) + parser.add_argument('--trials', type=int, default=18) + parser.add_argument('--output', type=Path, required=True) + args = parser.parse_args() + if args.trials < 3 or args.trials % 3 or args.output.exists(): + parser.error('trials must be a positive multiple of three and output must be new') + variants = {'flat': args.flat.resolve(), 'copy': args.copy.resolve(), + 'paged': args.paged.resolve()} + for binary in variants.values(): + if not binary.is_file(): + parser.error(f'missing binary: {binary}') + args.scratch_parent.mkdir(parents=True, exist_ok=True) + with tempfile.TemporaryDirectory(prefix='pure-storage-timing-', + dir=args.scratch_parent.resolve()) as name: + root = Path(name) + (root / 'initial').write_bytes(INITIAL) + (root / 'replacement').write_bytes(b'Z') + filesystem = subprocess.run(['findmnt', '-T', str(root), '-no', 'FSTYPE,SOURCE'], + capture_output=True, text=True, check=True).stdout.strip() + samples = {name: [] for name in variants} + names = list(variants) + for trial in range(args.trials): + for name in names[trial % 3:] + names[:trial % 3]: + sample = one(variants[name], root / f'{name}-{trial}', + root / 'initial', root / 'replacement') + samples[name].append({'trial': trial, **sample}) + result = {'profile': 'native-cli-durable-one-mib-document-last-byte-edit', + 'platform': platform.platform(), 'filesystem': filesystem, + 'trials_per_variant': args.trials, + 'final_body_sha256': hashlib.sha256(EXPECTED).hexdigest(), + 'scope': ('Each sample starts a new CLI process; create and edit each ' + 'include program parsing, store initialization, file and ' + 'directory synchronization. Show verifies the final revision ' + 'but is outside the timed operations. The host page cache, ' + 'filesystem and device remain uncontrolled.'), + 'variants': {name: {'binary_sha256': hashlib.sha256(binary.read_bytes()).hexdigest(), + 'median_create_ms': round(statistics.median( + row['create_ms'] for row in samples[name]), 3), + 'median_edit_ms': round(statistics.median( + row['edit_ms'] for row in samples[name]), 3), + 'samples': samples[name]} + for name, binary in variants.items()}} + args.output.parent.mkdir(parents=True, exist_ok=True) + args.output.write_text(json.dumps(result, indent=2) + '\n') + print(json.dumps({name: {key: value for key, value in entry.items() + if key.startswith('median_')} + for name, entry in result['variants'].items()}, indent=2)) + + +if __name__ == '__main__': + main() diff --git a/research/experiments/005-storage-edit-latency/paged-memory.json b/research/experiments/005-storage-edit-latency/paged-memory.json new file mode 100644 index 0000000..a9bef53 --- /dev/null +++ b/research/experiments/005-storage-edit-latency/paged-memory.json @@ -0,0 +1,43 @@ +{ + "passed": true, + "failures": [], + "profile": "portable-measurement-no-budget", + "variant": "source-program", + "scope": "Child-process peak RSS for native CLI document creation, read and one-byte revision edit; includes libc and the selected program form, excludes filesystem cache, kernel buffers, TLS, GUI and other apps. No cross-platform memory ceiling is asserted.", + "samples": { + "small_edit_rss_kib": 1088, + "one_mib_edit_rss_kib": 2112, + "one_mib_show_rss_kib": 1088, + "one_mib_splice_rss_kib": 1056 + }, + "raw_samples": { + "small_edit_rss_kib": { + "exit_code": 0, + "max_rss_kib": 1088, + "raw_max_rss": 1088, + "raw_unit": "KiB" + }, + "one_mib_edit_rss_kib": { + "exit_code": 0, + "max_rss_kib": 2112, + "raw_max_rss": 2112, + "raw_unit": "KiB" + }, + "one_mib_show_rss_kib": { + "exit_code": 0, + "max_rss_kib": 1088, + "raw_max_rss": 1088, + "raw_unit": "KiB" + }, + "one_mib_splice_rss_kib": { + "exit_code": 0, + "max_rss_kib": 1056, + "raw_max_rss": 1056, + "raw_unit": "KiB" + } + }, + "budget_sha256": null, + "binary_sha256": "e1c12a2f5e736bb86737ceff7849fe95b1a9d13136e8c5eb3f3398cb3971c6f5", + "binary_bytes": 200704, + "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41" +} diff --git a/research/experiments/005-storage-edit-latency/sequence.py b/research/experiments/005-storage-edit-latency/sequence.py new file mode 100644 index 0000000..57ff835 --- /dev/null +++ b/research/experiments/005-storage-edit-latency/sequence.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python3 +"""Measure repeated durable edits and page-segment rebuilds on one real document.""" +import argparse +import hashlib +import json +from pathlib import Path +import platform +import statistics +import subprocess +import tempfile + +from measure import INITIAL, PROGRAM, invoke + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--flat', type=Path, required=True) + parser.add_argument('--paged', type=Path, required=True) + parser.add_argument('--scratch-parent', type=Path, required=True) + parser.add_argument('--edits', type=int, default=70) + parser.add_argument('--output', type=Path, required=True) + args = parser.parse_args() + if args.edits < 66 or args.output.exists(): + parser.error('at least 66 edits are needed to observe the current rebuild boundary; output must be new') + binaries = {'flat': args.flat.resolve(), 'paged': args.paged.resolve()} + args.scratch_parent.mkdir(parents=True, exist_ok=True) + with tempfile.TemporaryDirectory(prefix='pure-storage-sequence-', + dir=args.scratch_parent.resolve()) as name: + root = Path(name) + filesystem = subprocess.run(['findmnt', '-T', str(root), '-no', 'FSTYPE,SOURCE'], + capture_output=True, text=True, check=True).stdout.strip() + (root / 'initial').write_bytes(INITIAL) + patches = {'Y': root / 'Y', 'Z': root / 'Z'} + for label, file in patches.items(): + file.write_bytes(label.encode()) + bases = {variant: [binary, '--program', PROGRAM, '--store', root / variant] + for variant, binary in binaries.items()} + for base in bases.values(): + result, _ = invoke([*base, 'edit', 'document', 0, 0, 0, root / 'initial']) + assert json.loads(result.stdout)['revision'] == '1' + samples = {variant: [] for variant in binaries} + for edit in range(1, args.edits + 1): + patch = 'Z' if edit % 2 else 'Y' + order = ('flat', 'paged') if edit % 2 else ('paged', 'flat') + for variant in order: + base = bases[variant] + result, elapsed = invoke([*base, 'edit', 'document', edit, + len(INITIAL) - 1, 1, patches[patch]]) + assert json.loads(result.stdout)['revision'] == str(edit + 1) + files = [file for file in (root / variant).iterdir() if file.is_file()] + samples[variant].append({'edit': edit, 'elapsed_ms': round(elapsed, 3), + 'files': len(files), + 'allocated_bytes': sum(file.stat().st_blocks * 512 + for file in files)}) + expected = INITIAL[:-1] + patches[patch].read_bytes() + for base in bases.values(): + shown, _ = invoke([*base, 'show', 'document']) + assert shown.stdout == expected + assert json.loads(shown.stderr)['revision'] == str(args.edits + 1) + result = {'profile': 'repeated-durable-one-mib-document-last-byte-edit', + 'platform': platform.platform(), 'filesystem': filesystem, + 'edits_per_variant': args.edits, + 'final_body_sha256': hashlib.sha256(expected).hexdigest(), + 'scope': ('Same actual source-loaded CLI and editor.pure, two persistent ' + 'stores, alternating operation order. Timings include each ' + 'edit process, parser, store init and fsync; creation and ' + 'final show are not timed. Device state is uncontrolled.'), + 'variants': {variant: { + 'binary_sha256': hashlib.sha256(binary.read_bytes()).hexdigest(), + 'median_edit_ms': round(statistics.median(row['elapsed_ms'] + for row in samples[variant]), 3), + 'samples': samples[variant]} + for variant, binary in binaries.items()}} + args.output.parent.mkdir(parents=True, exist_ok=True) + args.output.write_text(json.dumps(result, indent=2) + '\n') + print(json.dumps({variant: {'median_edit_ms': row['median_edit_ms'], + 'max_edit_ms': max(sample['elapsed_ms'] + for sample in row['samples']), + 'max_allocated_bytes': max(sample['allocated_bytes'] + for sample in row['samples'])} + for variant, row in result['variants'].items()}, indent=2)) + + +if __name__ == '__main__': + main() |
