1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
#!/usr/bin/env python3
"""Compare one real immutable-file splice with the selected Linux copy path."""
import argparse
import hashlib
import json
from pathlib import Path
import platform
import re
import subprocess
import tempfile
HERE = Path(__file__).resolve().parent
SUCCESS = re.compile(r'= (\d+)$')
def run(*args):
result = subprocess.run([str(arg) for arg in args], capture_output=True,
timeout=30, check=True)
return result.stdout
def inspect(binary, helper, root, initial, patch):
store = root / binary.parent.name
base = [binary, '--program', HERE / 'examples/editor.pure', '--store', store]
run(*base, 'edit', 'large', 0, 0, 0, initial)
trace = root / (binary.parent.name + '.trace')
run('strace', '-f', '-qq', '-yy', '-e',
'trace=pread64,write,copy_file_range', '-o', trace,
*base, 'edit', 'large', 1, 1_048_575, 1, patch)
expected = b'A' * 1_048_575 + b'Z'
assert run(*base, 'show', 'large') == expected
lines = trace.read_text().splitlines()
reads = [line for line in lines if 'pread64(' in line and '/obj-large>' in line]
copies = [line for line in lines if 'copy_file_range(' in line]
writes = [line for line in lines if 'write(' in line and '/.pending-' in line]
assert all(SUCCESS.search(line) for line in reads + copies + writes)
measured_store = root / (binary.parent.name + '-rss')
measured = [binary, '--program', HERE / 'examples/editor.pure',
'--store', measured_store]
run(*measured, 'edit', 'large', 0, 0, 0, initial)
usage = json.loads(run(helper, *measured, 'edit', 'large', 1, 1_048_575, 1, patch))
assert usage['exit_code'] == 0
assert run(*measured, 'show', 'large') == expected
return {'binary_sha256': hashlib.sha256(binary.read_bytes()).hexdigest(),
'result_sha256': hashlib.sha256(expected).hexdigest(),
'object_pread_calls': len(reads),
'copy_file_range_calls': len(copies),
'copy_file_range_bytes': sum(int(SUCCESS.search(line)[1]) for line in copies),
'pending_write_calls': len(writes),
'pending_write_bytes': sum(int(SUCCESS.search(line)[1]) for line in writes),
'one_mib_splice_peak_rss_kib': usage['max_rss_kib']}
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--baseline', type=Path, required=True)
parser.add_argument('--candidate', type=Path, required=True)
parser.add_argument('--baseline-helper', type=Path, required=True)
parser.add_argument('--candidate-helper', type=Path, required=True)
parser.add_argument('--scratch-dir', type=Path, default=HERE / 'build',
help='parent filesystem for the actual document stores')
parser.add_argument('--output', type=Path)
args = parser.parse_args()
if args.output and args.output.exists():
parser.error('evidence file already exists')
if platform.system() != 'Linux':
parser.error('strace and wait4 RSS evidence require Linux')
args.scratch_dir.mkdir(parents=True, exist_ok=True)
with tempfile.TemporaryDirectory(prefix='pure-copy-path-',
dir=args.scratch_dir.resolve()) as name:
root = Path(name)
filesystem = run('findmnt', '-T', root, '-no', 'FSTYPE').decode().strip().splitlines()[0]
initial, patch = root / 'initial', root / 'patch'
initial.write_bytes(b'A' * 1_048_576)
patch.write_bytes(b'Z')
baseline = inspect(args.baseline.resolve(), args.baseline_helper.resolve(),
root, initial, patch)
candidate = inspect(args.candidate.resolve(), args.candidate_helper.resolve(),
root, initial, patch)
assert baseline['result_sha256'] == candidate['result_sha256']
assert baseline['copy_file_range_calls'] == 0
assert candidate['copy_file_range_bytes'] == 1_048_575
assert candidate['object_pread_calls'] < baseline['object_pread_calls']
result = {'profile': 'linux-immutable-one-mib-last-byte-splice',
'platform': platform.platform(), 'baseline': baseline,
'candidate': candidate,
'filesystem': filesystem,
'scratch_parent': str(args.scratch_dir.resolve()),
'scope': 'Successful object-file syscalls and child peak RSS; excludes physical device writes, page cache and proof of lower latency.'}
body = json.dumps(result, indent=2) + '\n'
if args.output:
args.output.parent.mkdir(parents=True, exist_ok=True)
args.output.write_text(body)
print(body, end='')
if __name__ == '__main__':
main()
|