From 73368f2d5f96364eca26f52860176717bb30677a Mon Sep 17 00:00:00 2001 From: Jonathon Belotti Date: Sun, 30 Jun 2024 19:33:38 -0400 Subject: [PATCH] computers-are-fast --- .../spam/a_plan_for_spam/mail_server.py | 2 +- performance/computers-are-fast/Cargo.lock | 489 ++++++++++++++++++ performance/computers-are-fast/Cargo.toml | 21 + performance/computers-are-fast/README.md | 3 + performance/computers-are-fast/benches.py | 203 ++++++++ performance/computers-are-fast/main.py | 153 ++++++ performance/computers-are-fast/message.json | 1 + .../computers-are-fast/modal_runtime.py | 25 + performance/computers-are-fast/src/lib.rs | 155 ++++++ performance/computers-are-fast/src/main.rs | 328 ++++++++++++ 10 files changed, 1379 insertions(+), 1 deletion(-) create mode 100644 performance/computers-are-fast/Cargo.lock create mode 100644 performance/computers-are-fast/Cargo.toml create mode 100644 performance/computers-are-fast/README.md create mode 100644 performance/computers-are-fast/benches.py create mode 100644 performance/computers-are-fast/main.py create mode 100644 performance/computers-are-fast/message.json create mode 100644 performance/computers-are-fast/modal_runtime.py create mode 100644 performance/computers-are-fast/src/lib.rs create mode 100644 performance/computers-are-fast/src/main.rs diff --git a/machine_learning/applications/spam/a_plan_for_spam/mail_server.py b/machine_learning/applications/spam/a_plan_for_spam/mail_server.py index 7c67239..99dc850 100644 --- a/machine_learning/applications/spam/a_plan_for_spam/mail_server.py +++ b/machine_learning/applications/spam/a_plan_for_spam/mail_server.py @@ -115,7 +115,7 @@ def check_for_spam(email_bytes: bytes) -> bool: [str(component) for component in config.spam_detect_api_addr] ) - req = urllib.request.Request(f"http://{spam_detect_api_url}") + req.add_header("Content-Type", "application/json; charset=utf-8") data = json.dumps(body) data_b = data.encode("utf-8") diff --git a/performance/computers-are-fast/Cargo.lock b/performance/computers-are-fast/Cargo.lock new file mode 100644 index 0000000..4944085 --- /dev/null +++ b/performance/computers-are-fast/Cargo.lock @@ -0,0 +1,489 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "anyhow" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "computers-are-fast" +version = "0.1.0" +dependencies = [ + "anyhow", + "paste", + "prettyplease 0.2.20", + "proc-macro2", + "quote", + "rust-format", + "serde", + "serde_json", + "sha2", + "syn 2.0.68", + "sysinfo", + "tempfile", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "fastrand" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "libc" +version = "0.2.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "ntapi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" +dependencies = [ + "winapi", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "prettyplease" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86" +dependencies = [ + "proc-macro2", + "syn 1.0.109", +] + +[[package]] +name = "prettyplease" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" +dependencies = [ + "proc-macro2", + "syn 2.0.68", +] + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "rust-format" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60e7c00b6c3bf5e38a880eec01d7e829d12ca682079f8238a464def3c4b31627" +dependencies = [ + "prettyplease 0.1.25", + "proc-macro2", + "syn 1.0.109", +] + +[[package]] +name = "rustix" +version = "0.38.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "serde" +version = "1.0.203" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.203" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "serde_json" +version = "1.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sysinfo" +version = "0.30.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "732ffa00f53e6b2af46208fba5718d9662a421049204e156328b66791ffa15ae" +dependencies = [ + "cfg-if", + "core-foundation-sys", + "libc", + "ntapi", + "once_cell", + "rayon", + "windows", +] + +[[package]] +name = "tempfile" +version = "3.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +dependencies = [ + "cfg-if", + "fastrand", + "rustix", + "windows-sys", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" +dependencies = [ + "windows-core", + "windows-targets", +] + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" diff --git a/performance/computers-are-fast/Cargo.toml b/performance/computers-are-fast/Cargo.toml new file mode 100644 index 0000000..69a6c76 --- /dev/null +++ b/performance/computers-are-fast/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "computers-are-fast" +version = "0.1.0" +edition = "2021" + +[lib] +proc-macro = true + +[dependencies] +anyhow = "1.0.86" +paste = "1.0.15" +prettyplease = "0.2.20" +proc-macro2 = "1.0.86" +quote = "1.0.36" +rust-format = {version="0.3.4", features=["pretty_please"]} +serde = {version = "1.0.203", features = ["derive"] } +serde_json = "1.0.117" +sha2 = "0.10.8" +syn = {version = "2.0.68", features = ["full"]} +sysinfo = "0.30.12" +tempfile = "3.10.1" diff --git a/performance/computers-are-fast/README.md b/performance/computers-are-fast/README.md new file mode 100644 index 0000000..abfe591 --- /dev/null +++ b/performance/computers-are-fast/README.md @@ -0,0 +1,3 @@ +### Computers are (still) Fast + +Code for the 'Computers Are Fast' blog post at [thundergolfer.com/blog](https://thundergolfer.com/blog). diff --git a/performance/computers-are-fast/benches.py b/performance/computers-are-fast/benches.py new file mode 100644 index 0000000..b5c077c --- /dev/null +++ b/performance/computers-are-fast/benches.py @@ -0,0 +1,203 @@ +import hashlib +import json +import pathlib +import os +import subprocess +import tempfile +import urllib.request +from http.server import BaseHTTPRequestHandler +BaseHTTPRequestHandler +from io import BytesIO, StringIO + + +hints: dict[str, list] = {} +notes: dict[str, list] = {} + +def bench_loop(n: int): + """ + Number to guess: How many iterations of an empty loop can we go through in a second? + """ + for _ in range(n): + pass + +hints[bench_loop.__name__] = [ + "A CPU can execute around a few billion instructions per second." +] + +def bench_parse_http_request(n: int): + """ + Number to guess: How many HTTP GET requests can we parse in a second? + """ + class HTTPRequest(BaseHTTPRequestHandler): + def __init__(self, request_data: bytes): + self.rfile = BytesIO(request_data) + self.raw_requestline = self.rfile.readline() + self.error_code = self.error_message = None + self.parse_request() + + def send_error(self, code, message): + self.error_code = code + self.error_message = message + + request = b"""GET / HTTP/1.1 +Host: localhost:8001 +Connection: keep-alive +Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 +Upgrade-Insecure-Requests: 1 +User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 +Accept-Encoding: gzip, deflate, sdch +Accept-Language: en-GB,en-US;q=0.8,en;q=0.6 +""" + for _ in range(n): + _parsed = HTTPRequest(request) + + +def bench_dict_mutation(n: int): + """ + Number to guess: How many entries can we add to a dictionary in a second? + """ + d = {} + max_entries = 1000 + for i in range(n): + d[i % max_entries] = i + + +def bench_download_webpage(n: int): + """ + Number to guess: How many times can we download google.com in a second? + """ + for _ in range(n): + response = urllib.request.urlopen("http://google.com") + response.read() + +hints[bench_download_webpage.__name__] = [ + "This inefficiently establishes a new HTTP connection on each iteration" +] + +def bench_run_python(n: int): + """ + Number to guess: How many times can we start the Python interpreter in a second? + """ + for _ in range(n): + subprocess.run("python3 -c ''", shell=True, check=True) + +hints[bench_run_python.__name__] = [ + "This is much less than 100 million :)", + "On startup Python reads of 100 files!", + "Before running any code Python executes around 1000 syscalls", +] + +def bench_create_files(n: int): + """ + How many fsync'd files can be created against an SSD in a second? + """ + with tempfile.TemporaryDirectory() as temp_dir: + for i in range(n): + file_path = os.path.join(temp_dir, f"{i}.txt") + with open(file_path, "w") as file: + file.flush() + # Sync the directory to ensure the file metadata is written to disk + dir_fd = os.open(temp_dir, os.O_RDONLY) + try: + os.fsync(dir_fd) + finally: + os.close(dir_fd) + + +hints[bench_create_files.__name__] = [ + "The fsync syscall per-file significantly impacts performance", +] + +def bench_write_to_disk(n: int): + """ + Number to guess: How many bytes can we write to an output file in a second? + """ + def cleanup(f, name): + f.flush() + os.fsync(f.fileno()) + f.close() + try: + os.remove(name) + except OSError: + pass + + chunk_size = 1_000_000 # 1 megabyte + data_chunk = b"a" * chunk_size + name = "/tmp/bench-write-to-disk" + bytes_written = 0 + with open(name, 'wb') as f: + while bytes_written < n: + written = f.write(data_chunk) + bytes_written += chunk_size + assert written == chunk_size, "incomplete disk write" + cleanup(f, name) + + +hints[bench_write_to_disk.__name__] = [ + "We make sure everything is sync'd to disk before exiting" +] + +def bench_write_to_memory(n: int): + """ + Number to guess: How many bytes can we write to a string in memory in a second? + """ + chunk_size = 1_000_000 # 1 megabyte + data_chunk = "a" * chunk_size + output = StringIO() + bytes_written = 0 + while bytes_written < n: + _ = output.write(data_chunk) + bytes_written += chunk_size + output.getvalue() + + +def bench_json_parse(n: int): + """ + Number to guess: parse iterations possible within one second. + """ + data = pathlib.Path("message.json").read_text() + for _ in range(n): + json.loads(data) + + +def bench_sha256_digest(n: int): + """ + Number to guess: bytes hashed in one second. + """ + CHUNK_SIZE = 10_000 + s = b'a' * CHUNK_SIZE + h = hashlib.md5() + bytes_hashed = 0 + while bytes_hashed < n: + h.update(s) + bytes_hashed += CHUNK_SIZE + h.digest() + +hints[bench_sha256_digest.__name__] = [ + "sha256 is cryptographically secure and slower than md5, siphash, CRC32." +] + + +def bench_fill_array(n: int): + """ + Number to guess: bytes written to array in one second. + """ + array = bytearray(n) + for i in range(n): + array[i] = i % 256 # Ensure value fits in a byte + print(array[n // 7], end='') + + +def bench_fill_array_out_of_order(n: int): + """ + Number to guess: bytes written to array in one second. + """ + array = bytearray(n) + jmp_around = 1 + for _ in range(n): + jmp_around = jmp_around * 2 + if jmp_around > n: + jmp_around -= n + array[jmp_around % n] = jmp_around % 256 # Ensure index and value fit in range + + print(array[n // 7]) diff --git a/performance/computers-are-fast/main.py b/performance/computers-are-fast/main.py new file mode 100644 index 0000000..9dd6be3 --- /dev/null +++ b/performance/computers-are-fast/main.py @@ -0,0 +1,153 @@ +import dataclasses +import json +import pathlib +import platform +import sys +import timeit + +import benches + +benchmarks = [ + "bench_loop", + "bench_dict_mutation", + "bench_parse_http_request", + "bench_download_webpage", + "bench_run_python", + "bench_create_files", + "bench_write_to_disk", + "bench_write_to_memory", + "bench_json_parse", + "bench_sha256_digest", + "bench_fill_array", + "bench_fill_array_out_of_order", +] + +# The possible guesses proceed through 10 orders of magnitude. +choices = [10 ** i for i in range(10)] + +@dataclasses.dataclass +class BenchResult: + name: str + platform: str + lang_version: str + # TODO: cpu info, mem info, ssd info + # TODO: mount info for /tmp/ + answer: int + # How many milliseconds benchmark took on answer. + answer_duration_ms: float + # Estimation/extrapolation of what N would be for bench + # to take exactly one second. + estimated_n: int + bench_source: str + bench_doc: str + hints: list[str] | None = None + language: str = "python" + +def snake_number_format(z: int): + if z < 0: + return '-' + snake_number_format(-z) + s = [] + while z: + if len(s) % 4 == 3: + s.append("_") + s.append(str(z % 10)) + z //= 10 + return ''.join(reversed(s)) + +def extract_clean_bench_source(bench_fn: callable) -> tuple[str, str]: + """ + Grab the source code of the bench function without the docstring. + """ + import inspect + import textwrap + src = inspect.getsource(bench_fn) + src = textwrap.dedent(src) + seen_start_of_docstring = False + lines = [ln.replace(" ", "\t") for ln in src.splitlines()] + for i, line in enumerate(lines): + if not seen_start_of_docstring and line.strip().startswith('"""'): + seen_start_of_docstring = True + continue + elif line.strip().endswith('"""'): + if seen_start_of_docstring: + break + else: + RuntimeError("unexpected end of docstring") + return inspect.getdoc(bench_fn), textwrap.dedent("\n".join(lines[i+1:])) + + +def run_benchmark(name: str, validate: bool = True) -> BenchResult: + """ + Exercises a benchmark by first gathering hardware and OS information + about the host and then running the bench function against each 'guess' + option until it reaches the correct answer. + + This function is slow because it runs 5 iterations to confirm the + correct answer. + """ + print(f"running benchmark {name} on {platform.platform()} {sys.version}") + + bench_fn = getattr(benches, name) + for n in choices: + stmt = lambda: bench_fn(n) # noqa: E731 + duration_s = timeit.timeit(stmt, number=1) + print(f"N {snake_number_format(n):10}: {duration_s * 1000:.3f}ms") + # Found answer. + # If we ran next answer we'd exceed one second. + # NB: we're assuming that all benchmarks have linear scaling. + if 0.1 < duration_s <= 1.0: + estimated_n = int(n / duration_s) + print( + f"benchmark {name} answer: {snake_number_format(n)} (est. exact N={snake_number_format(estimated_n)})" + ) + break + else: + estimated_n = int(n / duration_s) + + # Confirm by measure on estimated_n for more iterations. + if validate: + cofirm_stmt = lambda: bench_fn(estimated_n) # noqa: E731 + if name in {"bench_write_to_disk", "bench_write_to_memory", "bench_download_webpage"}: + delta_tolerance = 0.5 + elif n < 10_000: + delta_tolerance = 0.25 + else: + delta_tolerance = 0.2 + iterations = 5 + duration_total_s = timeit.timeit(cofirm_stmt, number=iterations) + duration_s = duration_total_s / 5 + delta = abs(duration_s - 1.0) + assert delta < delta_tolerance, f"inaccurate benchmark on {name}: {delta=} (took {duration_s}s on N={estimated_n})" + print(f"accurate benchmark on {name}: {delta=} (took {duration_s}s on N={estimated_n})") + + doc, source = extract_clean_bench_source(bench_fn) + return BenchResult( + name=name, + platform=platform.platform(), + lang_version=sys.version, + answer=n, + answer_duration_ms=duration_s * 1000, + estimated_n=estimated_n, + bench_doc=doc, + bench_source=source, + hints=benches.hints.get(name, []), + ) + + +def main(): + skip = { + # Uncomment if running without internet connectivity. + # "bench_download_webpage" + } + results = [ + run_benchmark(b) + for b in benchmarks + if b not in skip + ] + out = pathlib.Path("out.json") + out.write_text(json.dumps([dataclasses.asdict(d) for d in results])) + + + +if __name__ == "__main__": + main() diff --git a/performance/computers-are-fast/message.json b/performance/computers-are-fast/message.json new file mode 100644 index 0000000..c1e885b --- /dev/null +++ b/performance/computers-are-fast/message.json @@ -0,0 +1 @@ +{"rep_int": [0, 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], "flag": true, "id": 123, "nested_msgs": [{"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}, {"url": "http://localhost/", "id": 456, "title": "test title"}]} diff --git a/performance/computers-are-fast/modal_runtime.py b/performance/computers-are-fast/modal_runtime.py new file mode 100644 index 0000000..d58c5dc --- /dev/null +++ b/performance/computers-are-fast/modal_runtime.py @@ -0,0 +1,25 @@ +""" +Execute the computers-are-fast benchmarks in Modal to gather data +from the Modal runtime. Allows easily gathering data across Python +versions and cloud provider. +""" +import json +import os +import pathlib + +import modal + +image = modal.Image.debian_slim(python_version="3.11") +app = modal.App("computers-are-fast", image=image) + +import main + +@app.function(mounts=[modal.Mount.from_local_file( + local_path="./message.json", + remote_path="/root/message.json", +)]) +def run(): + cloud_provider = os.environ["MODAL_CLOUD_PROVIDER"] + print(f"{cloud_provider=}") + main.main() + print(json.dumps(pathlib.Path("out.json").read_text())) diff --git a/performance/computers-are-fast/src/lib.rs b/performance/computers-are-fast/src/lib.rs new file mode 100644 index 0000000..40901ef --- /dev/null +++ b/performance/computers-are-fast/src/lib.rs @@ -0,0 +1,155 @@ +use proc_macro2::Span; +use quote::{quote, ToTokens}; +use rust_format::{Formatter, PrettyPlease}; +use syn::Attribute; +use syn::Meta; +use syn::{parse_macro_input, ItemFn, Lit, ReturnType, Type}; + +/// Procedural macro that provides easy access (via two generated functions) to +/// the documentation and source code body of a function. +/// Used as part of the benchmarking data export. +#[proc_macro_attribute] +pub fn gen_docs( + _attr: proc_macro::TokenStream, + item: proc_macro::TokenStream, +) -> proc_macro::TokenStream { + // Extract a well-formatted fn body is actually pretty annoying. + // We must: + // 1. Remove the doc string comments + // 2. Remove the fn signature, which is identical for each bench and thus boring boilerplate + // 3. Format the fn signature-less code, which is hella fiddly. + // 4. Stripe the surrounding braces from the code block. + // + // Only after all those steps do we get the function body un-indented and nicely formatted. + let input_fn = parse_macro_input!(item as ItemFn); + // (1) Filter out doc attributes from the fn AST. + let non_doc_attrs: Vec<&Attribute> = input_fn + .attrs + .iter() + .filter(|attr| !attr.path().is_ident("doc")) + .collect(); + let func_without_docs = ItemFn { + attrs: non_doc_attrs.into_iter().cloned().collect(), + ..input_fn.clone() + }; + // (2) Remove fn signature it's boring + let block = func_without_docs.block; + let input_fn_src = block.to_token_stream().to_string(); + // (3) Annoyingly rust_format can't format just a single code block, so we temporary give this + // a fake fn wrapping. + let mut source = "fn foo() ".to_string(); + source.push_str(&input_fn_src); + source = PrettyPlease::default().format_str(source).unwrap(); + let source = source + .strip_prefix("fn foo() ") + .unwrap() + .replace(" ", "\t"); + // (4) We now have this: + // + // { + // BODY + // } + // + // Remove the braces and un-indent. + let source: String = source + .split("\n") + .skip(1) + .take_while(|x| !x.starts_with("}")) + .map(|l| l.strip_prefix("\t").unwrap_or(l)) + .collect::>() + .join("\n"); + + // Create the function which returns fn body source code (with "_src" suffix) + let fn_name = &input_fn.sig.ident; + let src_fn_name = syn::Ident::new(&format!("{}_src", fn_name), fn_name.span()); + let src_fn = syn::ItemFn { + attrs: vec![], + vis: input_fn.vis.clone(), + sig: syn::Signature { + output: ReturnType::Type( + syn::token::RArrow::default(), + Box::new(Type::Reference(syn::TypeReference { + and_token: syn::token::And::default(), + lifetime: Some(syn::Lifetime::new("'static", Span::call_site())), + mutability: None, + elem: Box::new(Type::Path(syn::TypePath { + qself: None, + path: syn::Path::from(syn::Ident::new("str", Span::call_site())), + })), + })), + ), + inputs: syn::punctuated::Punctuated::new(), + variadic: None, + ident: src_fn_name, + ..input_fn.sig.clone() + }, + block: Box::new(syn::parse_quote!({ + const SOURCE: &'static str = #source; + SOURCE + })), + }; + + // Create the function which returns fn doc string (with "_doc" suffix) + let doc_fn_name = syn::Ident::new(&format!("{}_doc", fn_name), fn_name.span()); + let doc_string = extract_doc_strings(&input_fn).join("\n"); + let doc_fn = syn::ItemFn { + attrs: vec![], + vis: input_fn.vis.clone(), + sig: syn::Signature { + output: ReturnType::Type( + syn::token::RArrow::default(), + Box::new(Type::Reference(syn::TypeReference { + and_token: syn::token::And::default(), + lifetime: Some(syn::Lifetime::new("'static", Span::call_site())), + mutability: None, + elem: Box::new(Type::Path(syn::TypePath { + qself: None, + path: syn::Path::from(syn::Ident::new("str", Span::call_site())), + })), + })), + ), + inputs: syn::punctuated::Punctuated::new(), + variadic: None, + ident: doc_fn_name, + ..input_fn.sig.clone() + }, + block: Box::new(syn::parse_quote!({ + const DOCS: &'static str = #doc_string; + DOCS + })), + }; + + // Generate the output, including both the original and new function + let output = quote! { + #input_fn + + #src_fn + + #doc_fn + }; + + output.into() +} + +fn extract_doc_strings(item_fn: &ItemFn) -> Vec { + item_fn + .attrs + .iter() + .filter_map(|attr| { + if attr.path().is_ident("doc") { + match &attr.meta { + Meta::NameValue(name_value) => match &name_value.value { + syn::Expr::Lit(expr_lit) => match &expr_lit.lit { + Lit::Str(ls) => Some(ls.value()), + _ => None, + }, + _ => None, + }, + _ => None, + } + } else { + None + } + }) + .collect() +} diff --git a/performance/computers-are-fast/src/main.rs b/performance/computers-are-fast/src/main.rs new file mode 100644 index 0000000..7ed1642 --- /dev/null +++ b/performance/computers-are-fast/src/main.rs @@ -0,0 +1,328 @@ +use std::fs::{File, OpenOptions}; +use std::io::{Read, Write}; +use std::net::TcpStream; +use std::time::Instant; +use std::{collections::HashMap, hint::black_box}; + +use anyhow::Result; +use computers_are_fast::gen_docs; +use serde::{Deserialize, Serialize}; +use sysinfo::System; +use tempfile::tempdir; + +const CHOICES: [u64; 10] = [ + 1, + 10, + 100, + 1_000, + 10_000, + 100_000, + 1_000_000, + 10_000_000, + 100_000_000, + 1_000_000_000, +]; + +#[derive(Deserialize, Debug, Serialize)] +struct BenchResult { + name: String, + platform: String, + lang_version: String, + answer: i32, + answer_duration_ms: f64, + estimated_n: u64, + bench_source: String, + bench_doc: String, + hints: Option>, + language: Option, +} + +struct Bench { + name: String, + f: fn(n: u64), + source: &'static str, + doc: &'static str, + hints: Option>, +} + +macro_rules! bnchmrk { + ($b_name:ident) => { + bnchmrk!($b_name, None) + }; + ($b_name:ident, $hints:expr) => { + Bench { + name: stringify!($b_name).to_string(), + f: $b_name, + source: paste::item! { [<$b_name _src>]() }, + doc: paste::item! { [<$b_name _doc>]() }, + hints: $hints, + } + }; +} + +/// Number to guess: How many iterations of an empty loop can we go through in a second? +#[gen_docs] +fn bench_loop(n: u64) { + for _ in 0..n { + black_box(()); + } +} + +/// Number to guess: How many entries can we add to a std::HashMap in a second? +#[gen_docs] +fn bench_dict_mutation(n: u64) { + let mut m = HashMap::new(); + + let max_entries = 1000; + + for i in 0..n { + m.insert(i % max_entries, i); + } +} + +/// Number to guess: How many times can we download google.com in a second? +#[gen_docs] +fn bench_download_webpage(n: u64) { + for _ in 0..n { + let mut stream = TcpStream::connect("google.com:80").unwrap(); + + let request = "GET / HTTP/1.1\r\nHost: google.com\r\nConnection: close\r\n\r\n"; + + stream.write_all(request.as_bytes()).unwrap(); + + let mut response = String::new(); + stream.read_to_string(&mut response).unwrap(); + } +} + +/// Number to guess: How many times can we start the Python interpreter in a second? +#[gen_docs] +fn bench_run_python(n: u64) { + for _ in 0..n { + let mut child = std::process::Command::new("python3") + .args(["-c", "''"]) + .spawn() + .expect("failed to execute child"); + let ecode = child.wait().expect("failed to wait on child"); + assert!(ecode.success()); + } +} + +/// Number to guess: How many fsync'd files can be created against an SSD in a second? +#[gen_docs] +fn bench_create_files(n: u64) { + let dir = tempdir().unwrap(); + for i in 0..n { + let file_path = dir.path().join(format!("{}.txt", i)); + let file = File::create(file_path).unwrap(); + file.sync_all().unwrap(); + } + let dir_path = dir.path(); + let dir_file = OpenOptions::new().read(true).open(dir_path).unwrap(); + dir_file.sync_all().unwrap(); +} + +/// Number to guess: How many bytes can we write to an output file in a second? +#[gen_docs] +fn bench_write_to_disk(n: u64) { + const CHUNK_SIZE: usize = 1_000_000; // 1 megabyte + let data_chunk: [u8; CHUNK_SIZE] = [b'a'; CHUNK_SIZE]; + let mut f = std::fs::File::create("/tmp/bench-write-to-disk").unwrap(); + let mut bytes_written = 0; + while bytes_written < n { + let written = f.write(&data_chunk).unwrap(); + bytes_written += CHUNK_SIZE as u64; + assert_eq!(written, CHUNK_SIZE, "incomplete disk write"); + } + f.sync_all().unwrap(); +} + +/// Number to guess: How many bytes can we write to a string in memory in a second? +#[gen_docs] +fn bench_write_to_memory(n: u64) { + const CHUNK_SIZE: usize = 1_000_000; // 1 megabyte + let data_chunk: [u8; CHUNK_SIZE] = [b'a'; CHUNK_SIZE]; + let mut buffer: Vec = vec![]; + let mut bytes_written = 0; + while bytes_written < n { + buffer.extend(&data_chunk); + bytes_written += CHUNK_SIZE as u64; + } + assert!(buffer.len() >= n as usize); +} + +/// Number to guess: parse iterations possible within one second. +#[gen_docs] +fn bench_json_parse(n: u64) { + // NB: reading the 64KiB file is a small constant overhead on each run. + // WARN: no err handling + let data = std::fs::read_to_string("message.json").unwrap(); + for _ in 0..n { + let _json: serde_json::Value = serde_json::from_str(&data).unwrap(); + } +} + +/// Number to guess: bytes hashed in one second. +#[gen_docs] +fn bench_sha256_digest(n: u64) { + use sha2::{Digest, Sha256}; + const CHUNK_SIZE: usize = 10_000; + let s = "a".repeat(CHUNK_SIZE); + let mut bytes_hashed: usize = 0; + let mut h = Sha256::new(); + + while bytes_hashed < (n as usize) { + h.update(s.as_bytes()); + bytes_hashed += CHUNK_SIZE; + } + + h.finalize(); +} + +/// Number to guess: bytes written to array in one second. +#[gen_docs] +fn bench_fill_array(n: u64) { + let n: usize = n as usize; + let mut a = vec![0u8; n]; // mem alloc + let mut j: usize = 1; + for i in 0..n { + j *= 2; + if j > n { + j -= n; + } + a[i] = (j % 256) as u8; // Ensure value fits in a byte + } + println!("{}", a[n / 7]); +} + +/// Number to guess: bytes written to array in one second. +#[gen_docs] +fn bench_fill_array_out_of_order(n: u64) { + let n: usize = n as usize; + let mut a = vec![0u8; n]; + let mut jump_around: usize = 1; + for _ in 0..n { + jump_around *= 2; + if jump_around > n { + jump_around -= n; + } + a[jump_around % n] = (jump_around % 256) as u8; // Ensure index and value fit in range + } + println!("{}", a[n / 7]); +} + +fn snake_number_format(mut z: u64) -> String { + let mut s = Vec::new(); + while z > 0 { + if s.len() % 4 == 3 { + s.push('_'); + } + s.push(char::from_digit((z % 10) as u32, 10).unwrap()); + z /= 10; + } + + if s.is_empty() { + return "0".to_string(); + } + + s.reverse(); + s.into_iter().collect() +} + +// Exercises a benchmark by first gathering hardware and OS information +// about the host and then running the bench function against each 'guess' +// option until it reaches the correct answer. + +// This function is slow because it runs 5 iterations to confirm the +// correct answer. +fn run_benchmark(b: &Bench) -> BenchResult { + let name = &b.name; + let f = b.f; + + println!("running benchmark {}", name); + let mut answer = None; + let mut elapsed_ms = std::time::Duration::MAX.as_millis() as u64; + let mut estimated_n = 0; + for n in CHOICES { + let now = Instant::now(); + + black_box(f(black_box(n))); + + let elapsed = now.elapsed(); + elapsed_ms = elapsed.as_millis() as u64; + println!("Elapsed: {:.2?}", elapsed); + if elapsed_ms > 100 { + estimated_n = n * 1000 / elapsed_ms; + // Found answer. + // If we ran next answer we'd exceed one second. + // NB: we're assuming that all benchmarks have linear scaling. + println!( + "benchmark {} answer: {} (est. exact N={})", + name, + snake_number_format(n), + snake_number_format(estimated_n), + ); + answer = Some(n); + break; + } + } + + let answer: u64 = answer.unwrap_or(*CHOICES.last().expect("hardcoded non-empty")); + + let platform = format!( + "{}-{}-{}", + System::name().unwrap(), + System::os_version().unwrap(), + System::cpu_arch().unwrap() + ); + + BenchResult { + name: name.to_string(), + platform, + // NB: only the *minimum* version, not the actual version. + lang_version: env!("CARGO_PKG_RUST_VERSION").into(), + answer: answer as i32, + answer_duration_ms: elapsed_ms as f64, + estimated_n, + bench_source: b.source.into(), + bench_doc: b.doc.into(), + hints: b.hints.clone(), + language: Some("rust".into()), + } +} + +fn main() -> Result<()> { + let benchmarks: [Bench; 11] = [ + bnchmrk![bench_loop, Some(vec![ + "black_box(()) is used only to avoid compiler optimizing out the loop. It adds no run time overhead.".to_string(), + "A CPU can execute around a few billion instructions per second.".to_string() + ])], + bnchmrk!(bench_dict_mutation), + bnchmrk!(bench_download_webpage), + bnchmrk!(bench_run_python, Some(vec![ + "This is much less than 100 million :)".to_string(), + "On startup Python reads of 100 files!".into(), + "Before running any code Python executes around 1000 syscalls".into(), + ])), + bnchmrk!(bench_create_files), + bnchmrk!(bench_write_to_disk, Some(vec![ + "We make sure everything is sync'd to disk before exiting".to_string(), + ])), + bnchmrk!(bench_write_to_memory), + bnchmrk!(bench_json_parse), + bnchmrk!(bench_sha256_digest, Some(vec![ + "sha256 is cryptographically secure and slower than md5, siphash, CRC32.".to_string() + ])), + bnchmrk!(bench_fill_array), + bnchmrk!(bench_fill_array_out_of_order), + ]; + + let mut results = vec![]; + for b in benchmarks { + let r = black_box(run_benchmark(&b)); + results.push(r); + } + + std::fs::write("out.rs.json", serde_json::to_string(&results)?)?; + Ok(()) +}