mirror of
https://github.com/hinto-janai/cuprate.git
synced 2024-12-23 03:59:37 +00:00
Compare commits
2 commits
f3c1a5c2aa
...
01150ab84c
Author | SHA1 | Date | |
---|---|---|---|
|
01150ab84c | ||
|
caa08d5eaa |
42 changed files with 1387 additions and 318 deletions
313
Cargo.lock
generated
313
Cargo.lock
generated
|
@ -29,6 +29,15 @@ dependencies = [
|
||||||
"zerocopy",
|
"zerocopy",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aho-corasick"
|
||||||
|
version = "1.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "android-tzdata"
|
name = "android-tzdata"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
|
@ -44,6 +53,12 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anes"
|
||||||
|
version = "0.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anstyle"
|
name = "anstyle"
|
||||||
version = "1.0.10"
|
version = "1.0.10"
|
||||||
|
@ -347,6 +362,12 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cast"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.1.31"
|
version = "1.1.31"
|
||||||
|
@ -380,6 +401,33 @@ dependencies = [
|
||||||
"windows-targets 0.52.6",
|
"windows-targets 0.52.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ciborium"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e"
|
||||||
|
dependencies = [
|
||||||
|
"ciborium-io",
|
||||||
|
"ciborium-ll",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ciborium-io"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ciborium-ll"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9"
|
||||||
|
dependencies = [
|
||||||
|
"ciborium-io",
|
||||||
|
"half",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "4.5.20"
|
version = "4.5.20"
|
||||||
|
@ -478,6 +526,42 @@ dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "criterion"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f"
|
||||||
|
dependencies = [
|
||||||
|
"anes",
|
||||||
|
"cast",
|
||||||
|
"ciborium",
|
||||||
|
"clap",
|
||||||
|
"criterion-plot",
|
||||||
|
"is-terminal",
|
||||||
|
"itertools",
|
||||||
|
"num-traits",
|
||||||
|
"once_cell",
|
||||||
|
"oorandom",
|
||||||
|
"plotters",
|
||||||
|
"rayon",
|
||||||
|
"regex",
|
||||||
|
"serde",
|
||||||
|
"serde_derive",
|
||||||
|
"serde_json",
|
||||||
|
"tinytemplate",
|
||||||
|
"walkdir",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "criterion-plot"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1"
|
||||||
|
dependencies = [
|
||||||
|
"cast",
|
||||||
|
"itertools",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam"
|
name = "crossbeam"
|
||||||
version = "0.8.4"
|
version = "0.8.4"
|
||||||
|
@ -534,6 +618,12 @@ version = "0.8.20"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
|
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crunchy"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crypto-bigint"
|
name = "crypto-bigint"
|
||||||
version = "0.5.5"
|
version = "0.5.5"
|
||||||
|
@ -583,6 +673,30 @@ dependencies = [
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cuprate-benchmark"
|
||||||
|
version = "0.0.0"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cuprate-benchmark-example",
|
||||||
|
"cuprate-benchmark-lib",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"tracing",
|
||||||
|
"tracing-subscriber",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cuprate-benchmark-example"
|
||||||
|
version = "0.0.0"
|
||||||
|
dependencies = [
|
||||||
|
"cuprate-benchmark-lib",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cuprate-benchmark-lib"
|
||||||
|
version = "0.0.0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cuprate-blockchain"
|
name = "cuprate-blockchain"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
|
@ -685,6 +799,25 @@ dependencies = [
|
||||||
name = "cuprate-constants"
|
name = "cuprate-constants"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cuprate-criterion-example"
|
||||||
|
version = "0.0.0"
|
||||||
|
dependencies = [
|
||||||
|
"criterion",
|
||||||
|
"function_name",
|
||||||
|
"serde_json",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cuprate-criterion-json-rpc"
|
||||||
|
version = "0.0.0"
|
||||||
|
dependencies = [
|
||||||
|
"criterion",
|
||||||
|
"cuprate-json-rpc",
|
||||||
|
"function_name",
|
||||||
|
"serde_json",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cuprate-cryptonight"
|
name = "cuprate-cryptonight"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
@ -1304,6 +1437,21 @@ dependencies = [
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "function_name"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b1ab577a896d09940b5fe12ec5ae71f9d8211fff62c919c03a3750a9901e98a7"
|
||||||
|
dependencies = [
|
||||||
|
"function_name-proc-macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "function_name-proc-macro"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "673464e1e314dd67a0fd9544abc99e8eb28d0c7e3b69b033bcff9b2d00b87333"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "funty"
|
name = "funty"
|
||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
|
@ -1453,6 +1601,16 @@ dependencies = [
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "half"
|
||||||
|
version = "2.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"crunchy",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.14.5"
|
version = "0.14.5"
|
||||||
|
@ -1680,6 +1838,26 @@ dependencies = [
|
||||||
"hashbrown 0.15.0",
|
"hashbrown 0.15.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "is-terminal"
|
||||||
|
version = "0.4.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b"
|
||||||
|
dependencies = [
|
||||||
|
"hermit-abi",
|
||||||
|
"libc",
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itertools"
|
||||||
|
version = "0.10.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.11"
|
version = "1.0.11"
|
||||||
|
@ -1776,6 +1954,15 @@ version = "0.4.22"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
|
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "matchers"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
|
||||||
|
dependencies = [
|
||||||
|
"regex-automata 0.1.10",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "matchit"
|
name = "matchit"
|
||||||
version = "0.7.3"
|
version = "0.7.3"
|
||||||
|
@ -2031,6 +2218,12 @@ version = "1.20.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
|
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "oorandom"
|
||||||
|
version = "11.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openssl-probe"
|
name = "openssl-probe"
|
||||||
version = "0.1.5"
|
version = "0.1.5"
|
||||||
|
@ -2168,6 +2361,34 @@ version = "0.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "plotters"
|
||||||
|
version = "0.3.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a15b6eccb8484002195a3e44fe65a4ce8e93a625797a063735536fd59cb01cf3"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
"plotters-backend",
|
||||||
|
"plotters-svg",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"web-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "plotters-backend"
|
||||||
|
version = "0.3.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "414cec62c6634ae900ea1c56128dfe87cf63e7caece0852ec76aba307cebadb7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "plotters-svg"
|
||||||
|
version = "0.3.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "81b30686a7d9c3e010b84284bdd26a29f2138574f52f5eb6f794fc0ad924e705"
|
||||||
|
dependencies = [
|
||||||
|
"plotters-backend",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ppv-lite86"
|
name = "ppv-lite86"
|
||||||
version = "0.2.20"
|
version = "0.2.20"
|
||||||
|
@ -2242,7 +2463,7 @@ dependencies = [
|
||||||
"rand",
|
"rand",
|
||||||
"rand_chacha",
|
"rand_chacha",
|
||||||
"rand_xorshift",
|
"rand_xorshift",
|
||||||
"regex-syntax",
|
"regex-syntax 0.8.5",
|
||||||
"rusty-fork",
|
"rusty-fork",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"unarray",
|
"unarray",
|
||||||
|
@ -2408,6 +2629,44 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex"
|
||||||
|
version = "1.10.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-automata 0.4.7",
|
||||||
|
"regex-syntax 0.8.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-automata"
|
||||||
|
version = "0.1.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
|
||||||
|
dependencies = [
|
||||||
|
"regex-syntax 0.6.29",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-automata"
|
||||||
|
version = "0.4.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-syntax 0.8.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-syntax"
|
||||||
|
version = "0.6.29"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-syntax"
|
name = "regex-syntax"
|
||||||
version = "0.8.5"
|
version = "0.8.5"
|
||||||
|
@ -2535,6 +2794,15 @@ version = "1.0.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
|
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "same-file"
|
||||||
|
version = "1.0.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "schannel"
|
name = "schannel"
|
||||||
version = "0.1.26"
|
version = "0.1.26"
|
||||||
|
@ -2889,6 +3157,16 @@ version = "0.5.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a693d0c8cf16973fac5a93fbe47b8c6452e7097d4fcac49f3d7a18e39c76e62e"
|
checksum = "a693d0c8cf16973fac5a93fbe47b8c6452e7097d4fcac49f3d7a18e39c76e62e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tinytemplate"
|
||||||
|
version = "1.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tinyvec"
|
name = "tinyvec"
|
||||||
version = "1.8.0"
|
version = "1.8.0"
|
||||||
|
@ -3105,10 +3383,14 @@ version = "0.3.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b"
|
checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"matchers",
|
||||||
"nu-ansi-term",
|
"nu-ansi-term",
|
||||||
|
"once_cell",
|
||||||
|
"regex",
|
||||||
"sharded-slab",
|
"sharded-slab",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"thread_local",
|
"thread_local",
|
||||||
|
"tracing",
|
||||||
"tracing-core",
|
"tracing-core",
|
||||||
"tracing-log",
|
"tracing-log",
|
||||||
]
|
]
|
||||||
|
@ -3214,6 +3496,16 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "walkdir"
|
||||||
|
version = "2.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
|
||||||
|
dependencies = [
|
||||||
|
"same-file",
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "want"
|
name = "want"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
|
@ -3284,6 +3576,16 @@ version = "0.2.95"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d"
|
checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "web-sys"
|
||||||
|
version = "0.3.69"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef"
|
||||||
|
dependencies = [
|
||||||
|
"js-sys",
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webpki-roots"
|
name = "webpki-roots"
|
||||||
version = "0.26.6"
|
version = "0.26.6"
|
||||||
|
@ -3309,6 +3611,15 @@ version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-util"
|
||||||
|
version = "0.1.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi-x86_64-pc-windows-gnu"
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
|
|
95
Cargo.toml
95
Cargo.toml
|
@ -1,36 +1,57 @@
|
||||||
[workspace]
|
[workspace]
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
|
||||||
members = [
|
members = [
|
||||||
|
# Binaries
|
||||||
"binaries/cuprated",
|
"binaries/cuprated",
|
||||||
"constants",
|
|
||||||
|
# Benchmarks
|
||||||
|
"benches/benchmark/bin",
|
||||||
|
"benches/benchmark/lib",
|
||||||
|
"benches/benchmark/example",
|
||||||
|
"benches/criterion/example",
|
||||||
|
"benches/criterion/cuprate-json-rpc",
|
||||||
|
|
||||||
|
# Consensus
|
||||||
"consensus",
|
"consensus",
|
||||||
"consensus/context",
|
"consensus/context",
|
||||||
"consensus/fast-sync",
|
"consensus/fast-sync",
|
||||||
"consensus/rules",
|
"consensus/rules",
|
||||||
"cryptonight",
|
|
||||||
"helper",
|
# Net
|
||||||
"net/epee-encoding",
|
"net/epee-encoding",
|
||||||
"net/fixed-bytes",
|
"net/fixed-bytes",
|
||||||
"net/levin",
|
"net/levin",
|
||||||
"net/wire",
|
"net/wire",
|
||||||
|
|
||||||
|
# P2P
|
||||||
"p2p/p2p",
|
"p2p/p2p",
|
||||||
"p2p/p2p-core",
|
"p2p/p2p-core",
|
||||||
"p2p/bucket",
|
"p2p/bucket",
|
||||||
"p2p/dandelion-tower",
|
"p2p/dandelion-tower",
|
||||||
"p2p/async-buffer",
|
"p2p/async-buffer",
|
||||||
"p2p/address-book",
|
"p2p/address-book",
|
||||||
|
|
||||||
|
# Storage
|
||||||
"storage/blockchain",
|
"storage/blockchain",
|
||||||
"storage/service",
|
"storage/service",
|
||||||
"storage/txpool",
|
"storage/txpool",
|
||||||
"storage/database",
|
"storage/database",
|
||||||
"pruning",
|
|
||||||
"test-utils",
|
# RPC
|
||||||
"types",
|
|
||||||
"rpc/json-rpc",
|
"rpc/json-rpc",
|
||||||
"rpc/types",
|
"rpc/types",
|
||||||
"rpc/interface",
|
"rpc/interface",
|
||||||
|
|
||||||
|
# ZMQ
|
||||||
"zmq/types",
|
"zmq/types",
|
||||||
|
|
||||||
|
# Misc
|
||||||
|
"constants",
|
||||||
|
"cryptonight",
|
||||||
|
"helper",
|
||||||
|
"pruning",
|
||||||
|
"test-utils",
|
||||||
|
"types",
|
||||||
]
|
]
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
|
@ -53,34 +74,36 @@ opt-level = 3
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
# Cuprate members
|
# Cuprate members
|
||||||
cuprate-fast-sync = { path = "consensus/fast-sync", default-features = false }
|
cuprate-benchmark-lib = { path = "benches/benchmark/lib", default-features = false }
|
||||||
cuprate-consensus-rules = { path = "consensus/rules", default-features = false }
|
cuprate-benchmark-example = { path = "benches/benchmark/example", default-features = false }
|
||||||
cuprate-constants = { path = "constants", default-features = false }
|
cuprate-fast-sync = { path = "consensus/fast-sync", default-features = false }
|
||||||
cuprate-consensus = { path = "consensus", default-features = false }
|
cuprate-consensus-rules = { path = "consensus/rules", default-features = false }
|
||||||
cuprate-consensus-context = { path = "consensus/context", default-features = false }
|
cuprate-constants = { path = "constants", default-features = false }
|
||||||
cuprate-cryptonight = { path = "cryptonight", default-features = false }
|
cuprate-consensus = { path = "consensus", default-features = false }
|
||||||
cuprate-helper = { path = "helper", default-features = false }
|
cuprate-consensus-context = { path = "consensus/context", default-features = false }
|
||||||
cuprate-epee-encoding = { path = "net/epee-encoding", default-features = false }
|
cuprate-cryptonight = { path = "cryptonight", default-features = false }
|
||||||
cuprate-fixed-bytes = { path = "net/fixed-bytes", default-features = false }
|
cuprate-helper = { path = "helper", default-features = false }
|
||||||
cuprate-levin = { path = "net/levin", default-features = false }
|
cuprate-epee-encoding = { path = "net/epee-encoding", default-features = false }
|
||||||
cuprate-wire = { path = "net/wire", default-features = false }
|
cuprate-fixed-bytes = { path = "net/fixed-bytes", default-features = false }
|
||||||
cuprate-p2p = { path = "p2p/p2p", default-features = false }
|
cuprate-levin = { path = "net/levin", default-features = false }
|
||||||
cuprate-p2p-core = { path = "p2p/p2p-core", default-features = false }
|
cuprate-wire = { path = "net/wire", default-features = false }
|
||||||
cuprate-p2p-bucket = { path = "p2p/p2p-bucket", default-features = false }
|
cuprate-p2p = { path = "p2p/p2p", default-features = false }
|
||||||
cuprate-dandelion-tower = { path = "p2p/dandelion-tower", default-features = false }
|
cuprate-p2p-core = { path = "p2p/p2p-core", default-features = false }
|
||||||
cuprate-async-buffer = { path = "p2p/async-buffer", default-features = false }
|
cuprate-p2p-bucket = { path = "p2p/p2p-bucket", default-features = false }
|
||||||
cuprate-address-book = { path = "p2p/address-book", default-features = false }
|
cuprate-dandelion-tower = { path = "p2p/dandelion-tower", default-features = false }
|
||||||
cuprate-blockchain = { path = "storage/blockchain", default-features = false }
|
cuprate-async-buffer = { path = "p2p/async-buffer", default-features = false }
|
||||||
cuprate-database = { path = "storage/database", default-features = false }
|
cuprate-address-book = { path = "p2p/address-book", default-features = false }
|
||||||
cuprate-database-service = { path = "storage/service", default-features = false }
|
cuprate-blockchain = { path = "storage/blockchain", default-features = false }
|
||||||
cuprate-txpool = { path = "storage/txpool", default-features = false }
|
cuprate-database = { path = "storage/database", default-features = false }
|
||||||
cuprate-pruning = { path = "pruning", default-features = false }
|
cuprate-database-service = { path = "storage/service", default-features = false }
|
||||||
cuprate-test-utils = { path = "test-utils", default-features = false }
|
cuprate-txpool = { path = "storage/txpool", default-features = false }
|
||||||
cuprate-types = { path = "types", default-features = false }
|
cuprate-pruning = { path = "pruning", default-features = false }
|
||||||
cuprate-json-rpc = { path = "rpc/json-rpc", default-features = false }
|
cuprate-test-utils = { path = "test-utils", default-features = false }
|
||||||
cuprate-rpc-types = { path = "rpc/types", default-features = false }
|
cuprate-types = { path = "types", default-features = false }
|
||||||
cuprate-rpc-interface = { path = "rpc/interface", default-features = false }
|
cuprate-json-rpc = { path = "rpc/json-rpc", default-features = false }
|
||||||
cuprate-zmq-types = { path = "zmq/types", default-features = false }
|
cuprate-rpc-types = { path = "rpc/types", default-features = false }
|
||||||
|
cuprate-rpc-interface = { path = "rpc/interface", default-features = false }
|
||||||
|
cuprate-zmq-types = { path = "zmq/types", default-features = false }
|
||||||
|
|
||||||
# External dependencies
|
# External dependencies
|
||||||
anyhow = { version = "1", default-features = false }
|
anyhow = { version = "1", default-features = false }
|
||||||
|
@ -125,6 +148,8 @@ tracing-subscriber = { version = "0.3", default-features = false }
|
||||||
tracing = { version = "0.1", default-features = false }
|
tracing = { version = "0.1", default-features = false }
|
||||||
|
|
||||||
## workspace.dev-dependencies
|
## workspace.dev-dependencies
|
||||||
|
criterion = { version = "0.5" }
|
||||||
|
function_name = { version = "0.3" }
|
||||||
monero-rpc = { git = "https://github.com/Cuprate/serai.git", rev = "d5205ce" }
|
monero-rpc = { git = "https://github.com/Cuprate/serai.git", rev = "d5205ce" }
|
||||||
monero-simple-request-rpc = { git = "https://github.com/Cuprate/serai.git", rev = "d5205ce" }
|
monero-simple-request-rpc = { git = "https://github.com/Cuprate/serai.git", rev = "d5205ce" }
|
||||||
tempfile = { version = "3" }
|
tempfile = { version = "3" }
|
||||||
|
|
|
@ -1 +1,5 @@
|
||||||
# TODO
|
# Benches
|
||||||
|
This directory contains Cuprate's benchmarks and benchmarking utilities.
|
||||||
|
|
||||||
|
See the [`Benchmarking` section in the Architecture book](https://architecture.cuprate.org/benchmarking/intro.html)
|
||||||
|
to see how to create and run these benchmarks.
|
43
benches/benchmark/bin/Cargo.toml
Normal file
43
benches/benchmark/bin/Cargo.toml
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
[package]
|
||||||
|
name = "cuprate-benchmark"
|
||||||
|
version = "0.0.0"
|
||||||
|
edition = "2021"
|
||||||
|
description = "Cuprate's benchmarking binary"
|
||||||
|
license = "MIT"
|
||||||
|
authors = ["hinto-janai"]
|
||||||
|
repository = "https://github.com/Cuprate/cuprate/tree/main/benches/benchmark/bin"
|
||||||
|
keywords = ["cuprate", "benchmarking", "binary"]
|
||||||
|
|
||||||
|
[features]
|
||||||
|
# All new benchmarks should be added here!
|
||||||
|
all = ["example"]
|
||||||
|
|
||||||
|
# Non-benchmark features.
|
||||||
|
default = []
|
||||||
|
json = []
|
||||||
|
trace = []
|
||||||
|
debug = []
|
||||||
|
warn = []
|
||||||
|
info = []
|
||||||
|
error = []
|
||||||
|
|
||||||
|
# Benchmark features.
|
||||||
|
# New benchmarks should be added here!
|
||||||
|
example = [
|
||||||
|
"dep:cuprate-benchmark-example"
|
||||||
|
]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
cuprate-benchmark-lib = { workspace = true }
|
||||||
|
cuprate-benchmark-example = { workspace = true, optional = true }
|
||||||
|
|
||||||
|
cfg-if = { workspace = true }
|
||||||
|
serde = { workspace = true, features = ["derive"] }
|
||||||
|
serde_json = { workspace = true, features = ["std"] }
|
||||||
|
tracing = { workspace = true, features = ["std", "attributes"] }
|
||||||
|
tracing-subscriber = { workspace = true, features = ["fmt", "std", "env-filter"] }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
27
benches/benchmark/bin/README.md
Normal file
27
benches/benchmark/bin/README.md
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
## `cuprate-benchmark`
|
||||||
|
This crate links all benchmarks together into a single binary that can be run as: `cuprate-benchmark`.
|
||||||
|
|
||||||
|
`cuprate-benchmark` will run all enabled benchmarks sequentially and print data at the end.
|
||||||
|
|
||||||
|
## Benchmarks
|
||||||
|
Benchmarks are opt-in and enabled via features.
|
||||||
|
|
||||||
|
| Feature | Enables which benchmark crate? |
|
||||||
|
|----------|--------------------------------|
|
||||||
|
| example | cuprate-benchmark-example |
|
||||||
|
| database | cuprate-benchmark-database |
|
||||||
|
|
||||||
|
## Features
|
||||||
|
These are features that aren't for enabling benchmarks, but rather for other things.
|
||||||
|
|
||||||
|
Since `cuprate-benchmark` is built right before it is ran,
|
||||||
|
these features almost act like command line arguments.
|
||||||
|
|
||||||
|
| Features | Does what |
|
||||||
|
|----------|-----------|
|
||||||
|
| json | Prints JSON timings instead of a markdown table
|
||||||
|
| trace | Use the `trace` log-level
|
||||||
|
| debug | Use the `debug` log-level
|
||||||
|
| warn | Use the `warn` log-level
|
||||||
|
| info | Use the `info` log-level (default)
|
||||||
|
| error | Use the `error` log-level
|
29
benches/benchmark/bin/src/log.rs
Normal file
29
benches/benchmark/bin/src/log.rs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
use cfg_if::cfg_if;
|
||||||
|
use tracing::{info, instrument, Level};
|
||||||
|
use tracing_subscriber::FmtSubscriber;
|
||||||
|
|
||||||
|
/// Initializes the `tracing` logger.
|
||||||
|
#[instrument]
|
||||||
|
pub(crate) fn init_logger() {
|
||||||
|
const LOG_LEVEL: Level = {
|
||||||
|
cfg_if! {
|
||||||
|
if #[cfg(feature = "trace")] {
|
||||||
|
Level::TRACE
|
||||||
|
} else if #[cfg(feature = "debug")] {
|
||||||
|
Level::DEBUG
|
||||||
|
} else if #[cfg(feature = "warn")] {
|
||||||
|
Level::WARN
|
||||||
|
} else if #[cfg(feature = "info")] {
|
||||||
|
Level::INFO
|
||||||
|
} else if #[cfg(feature = "error")] {
|
||||||
|
Level::ERROR
|
||||||
|
} else {
|
||||||
|
Level::INFO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
FmtSubscriber::builder().with_max_level(LOG_LEVEL).init();
|
||||||
|
|
||||||
|
info!("Log level: {LOG_LEVEL}");
|
||||||
|
}
|
49
benches/benchmark/bin/src/main.rs
Normal file
49
benches/benchmark/bin/src/main.rs
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
#![doc = include_str!("../README.md")]
|
||||||
|
#![allow(
|
||||||
|
unused_crate_dependencies,
|
||||||
|
reason = "this crate imports many potentially unused dependencies"
|
||||||
|
)]
|
||||||
|
|
||||||
|
mod log;
|
||||||
|
mod print;
|
||||||
|
mod run;
|
||||||
|
mod timings;
|
||||||
|
|
||||||
|
use cfg_if::cfg_if;
|
||||||
|
|
||||||
|
/// What `main()` does:
|
||||||
|
/// 1. Run all enabled benchmarks
|
||||||
|
/// 2. Record benchmark timings
|
||||||
|
/// 3. Print timing data
|
||||||
|
///
|
||||||
|
/// To add a new benchmark to be ran here:
|
||||||
|
/// 1. Copy + paste a `cfg_if` block
|
||||||
|
/// 2. Change it to your benchmark's feature flag
|
||||||
|
/// 3. Change it to your benchmark's type
|
||||||
|
#[allow(
|
||||||
|
clippy::allow_attributes,
|
||||||
|
unused_variables,
|
||||||
|
unused_mut,
|
||||||
|
unreachable_code,
|
||||||
|
reason = "clippy does not account for all cfg()s"
|
||||||
|
)]
|
||||||
|
fn main() {
|
||||||
|
log::init_logger();
|
||||||
|
|
||||||
|
let mut timings = timings::Timings::new();
|
||||||
|
|
||||||
|
cfg_if! {
|
||||||
|
if #[cfg(not(any(feature = "example")))] {
|
||||||
|
println!("No feature specified. Use `--features $BENCHMARK_FEATURE` when building.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg_if! {
|
||||||
|
if #[cfg(feature = "example")] {
|
||||||
|
run::run_benchmark::<cuprate_benchmark_example::Example>(&mut timings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
print::print_timings(&timings);
|
||||||
|
}
|
38
benches/benchmark/bin/src/print.rs
Normal file
38
benches/benchmark/bin/src/print.rs
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
#![expect(dead_code, reason = "code hidden behind feature flags")]
|
||||||
|
|
||||||
|
use cfg_if::cfg_if;
|
||||||
|
|
||||||
|
use crate::timings::Timings;
|
||||||
|
|
||||||
|
/// Print the final the final markdown table of benchmark timings.
|
||||||
|
pub(crate) fn print_timings(timings: &Timings) {
|
||||||
|
println!("\nFinished all benchmarks, printing results:");
|
||||||
|
|
||||||
|
cfg_if! {
|
||||||
|
if #[cfg(feature = "json")] {
|
||||||
|
print_timings_json(timings);
|
||||||
|
} else {
|
||||||
|
print_timings_markdown(timings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Default timing formatting.
|
||||||
|
pub(crate) fn print_timings_markdown(timings: &Timings) {
|
||||||
|
let mut s = String::new();
|
||||||
|
s.push_str("| Benchmark | Time (seconds) |\n");
|
||||||
|
s.push_str("|------------------------------------|----------------|");
|
||||||
|
|
||||||
|
#[expect(clippy::iter_over_hash_type)]
|
||||||
|
for (k, v) in timings {
|
||||||
|
s += &format!("\n| {k:<34} | {v:<14} |");
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("\n{s}");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Enabled via `json` feature.
|
||||||
|
pub(crate) fn print_timings_json(timings: &Timings) {
|
||||||
|
let json = serde_json::to_string_pretty(timings).unwrap();
|
||||||
|
println!("\n{json}");
|
||||||
|
}
|
36
benches/benchmark/bin/src/run.rs
Normal file
36
benches/benchmark/bin/src/run.rs
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
use tracing::{info, instrument, trace};
|
||||||
|
|
||||||
|
use cuprate_benchmark_lib::Benchmark;
|
||||||
|
|
||||||
|
use crate::timings::Timings;
|
||||||
|
|
||||||
|
/// Run a [`Benchmark`] and record its timing.
|
||||||
|
#[instrument(skip_all)]
|
||||||
|
pub(crate) fn run_benchmark<B: Benchmark>(timings: &mut Timings) {
|
||||||
|
// Get the benchmark name.
|
||||||
|
let name = B::name();
|
||||||
|
trace!("Running benchmark: {name}");
|
||||||
|
|
||||||
|
// Setup the benchmark input.
|
||||||
|
let input = B::SETUP();
|
||||||
|
|
||||||
|
// Sleep before running the benchmark.
|
||||||
|
trace!("Pre-benchmark, sleeping for: {:?}", B::POST_SLEEP_DURATION);
|
||||||
|
std::thread::sleep(B::PRE_SLEEP_DURATION);
|
||||||
|
|
||||||
|
// Run/time the benchmark.
|
||||||
|
let now = std::time::Instant::now();
|
||||||
|
B::MAIN(input);
|
||||||
|
let time = now.elapsed().as_secs_f32();
|
||||||
|
|
||||||
|
// Print the benchmark timings.
|
||||||
|
info!("{name:>34} ... {time}");
|
||||||
|
assert!(
|
||||||
|
timings.insert(name, time).is_none(),
|
||||||
|
"There were 2 benchmarks with the same name - this collides the final output: {name}",
|
||||||
|
);
|
||||||
|
|
||||||
|
// Sleep for a cooldown period after the benchmark run.
|
||||||
|
trace!("Post-benchmark, sleeping for: {:?}", B::POST_SLEEP_DURATION);
|
||||||
|
std::thread::sleep(B::POST_SLEEP_DURATION);
|
||||||
|
}
|
5
benches/benchmark/bin/src/timings.rs
Normal file
5
benches/benchmark/bin/src/timings.rs
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
/// Benchmark timing data.
|
||||||
|
///
|
||||||
|
/// - Key = benchmark name
|
||||||
|
/// - Value = benchmark time in seconds
|
||||||
|
pub(crate) type Timings = std::collections::HashMap<&'static str, f32>;
|
17
benches/benchmark/example/Cargo.toml
Normal file
17
benches/benchmark/example/Cargo.toml
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
[package]
|
||||||
|
name = "cuprate-benchmark-example"
|
||||||
|
version = "0.0.0"
|
||||||
|
edition = "2021"
|
||||||
|
description = "Example showcasing Cuprate's benchmarking harness"
|
||||||
|
license = "MIT"
|
||||||
|
authors = ["hinto-janai"]
|
||||||
|
repository = "https://github.com/Cuprate/cuprate/tree/main/benches/benchmark/example"
|
||||||
|
keywords = ["cuprate", "benchmarking", "example"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
cuprate-benchmark-lib = { path = "../lib" }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
3
benches/benchmark/example/README.md
Normal file
3
benches/benchmark/example/README.md
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
## `cuprate-benchmark-example`
|
||||||
|
This crate contains a short example benchmark that shows how to implement and use
|
||||||
|
`cuprate-benchmark-lib` so that it can be ran by `cuprate-benchmark`.
|
42
benches/benchmark/example/src/lib.rs
Normal file
42
benches/benchmark/example/src/lib.rs
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
#![doc = include_str!("../README.md")]
|
||||||
|
|
||||||
|
use std::hint::black_box;
|
||||||
|
|
||||||
|
use cuprate_benchmark_lib::Benchmark;
|
||||||
|
|
||||||
|
/// Marker struct that implements [`Benchmark`]
|
||||||
|
pub struct Example;
|
||||||
|
|
||||||
|
/// The input to our benchmark function.
|
||||||
|
pub type ExampleBenchmarkInput = u64;
|
||||||
|
|
||||||
|
/// The setup function that creates the input.
|
||||||
|
pub const fn example_benchmark_setup() -> ExampleBenchmarkInput {
|
||||||
|
1
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The main benchmarking function.
|
||||||
|
#[expect(clippy::unit_arg)]
|
||||||
|
pub fn example_benchmark_main(input: ExampleBenchmarkInput) {
|
||||||
|
// In this case, we're simply benchmarking the
|
||||||
|
// performance of simple arithmetic on the input data.
|
||||||
|
|
||||||
|
fn math(input: ExampleBenchmarkInput, number: u64) {
|
||||||
|
let x = input;
|
||||||
|
let x = black_box(x * number);
|
||||||
|
let x = black_box(x / number);
|
||||||
|
let x = black_box(x + number);
|
||||||
|
let _ = black_box(x - number);
|
||||||
|
}
|
||||||
|
|
||||||
|
for number in 1..100_000_000 {
|
||||||
|
black_box(math(input, number));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This implementation will be run by `cuprate-benchmark`.
|
||||||
|
impl Benchmark for Example {
|
||||||
|
type Input = ExampleBenchmarkInput;
|
||||||
|
const SETUP: fn() -> Self::Input = example_benchmark_setup;
|
||||||
|
const MAIN: fn(Self::Input) = example_benchmark_main;
|
||||||
|
}
|
18
benches/benchmark/lib/Cargo.toml
Normal file
18
benches/benchmark/lib/Cargo.toml
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
[package]
|
||||||
|
name = "cuprate-benchmark-lib"
|
||||||
|
version = "0.0.0"
|
||||||
|
edition = "2021"
|
||||||
|
description = "Cuprate's benchmarking library"
|
||||||
|
license = "MIT"
|
||||||
|
authors = ["hinto-janai"]
|
||||||
|
repository = "https://github.com/Cuprate/cuprate/tree/main/benches/benchmark/lib"
|
||||||
|
keywords = ["cuprate", "benchmarking", "library"]
|
||||||
|
|
||||||
|
[features]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
15
benches/benchmark/lib/README.md
Normal file
15
benches/benchmark/lib/README.md
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
## `cuprate-benchmark-lib`
|
||||||
|
This crate is the glue between
|
||||||
|
[`cuprate-benchmark`](https://github.com/Cuprate/cuprate/tree/benches/benches/benchmark/bin)
|
||||||
|
and all the benchmark crates.
|
||||||
|
|
||||||
|
It defines the [`crate::Benchmark`] trait, which is the behavior of all benchmarks.
|
||||||
|
|
||||||
|
See the [`cuprate-benchmark-example`](https://github.com/Cuprate/cuprate/tree/benches/benches/benchmark/example)
|
||||||
|
crate to see an example implementation of this trait.
|
||||||
|
|
||||||
|
After implementing this trait, a few steps must
|
||||||
|
be done such that the `cuprate-benchmark` binary
|
||||||
|
can actually run your benchmark crate; see the
|
||||||
|
[`Benchmarking` section in the Architecture book](https://architecture.cuprate.org/benchmarking/intro.html)
|
||||||
|
to see how to do this.
|
45
benches/benchmark/lib/src/benchmark.rs
Normal file
45
benches/benchmark/lib/src/benchmark.rs
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
//! Benchmarking trait.
|
||||||
|
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
/// A benchmarking function and its inputs.
|
||||||
|
pub trait Benchmark {
|
||||||
|
/// The benchmark's name.
|
||||||
|
///
|
||||||
|
/// This is automatically implemented
|
||||||
|
/// as the name of the [`Self`] type.
|
||||||
|
//
|
||||||
|
// FIXME: use `const` instead of `fn` when stable
|
||||||
|
// <https://github.com/rust-lang/rust/issues/63084>
|
||||||
|
fn name() -> &'static str {
|
||||||
|
std::any::type_name::<Self>()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Input to the main benchmarking function.
|
||||||
|
///
|
||||||
|
/// This is passed to [`Self::MAIN`].
|
||||||
|
type Input;
|
||||||
|
|
||||||
|
/// Setup function to generate the input.
|
||||||
|
///
|
||||||
|
/// This function is not timed.
|
||||||
|
const SETUP: fn() -> Self::Input;
|
||||||
|
|
||||||
|
/// The main function to benchmark.
|
||||||
|
///
|
||||||
|
/// The start of the timer begins right before
|
||||||
|
/// this function is called and ends after the
|
||||||
|
/// function returns.
|
||||||
|
const MAIN: fn(Self::Input);
|
||||||
|
|
||||||
|
/// `cuprate-benchmark` will sleep for this [`Duration`] after
|
||||||
|
/// creating the [`Self::Input`], but before starting [`Self::MAIN`].
|
||||||
|
///
|
||||||
|
/// 1 second by default.
|
||||||
|
const PRE_SLEEP_DURATION: Duration = Duration::from_secs(1);
|
||||||
|
|
||||||
|
/// `cuprate-benchmark` will sleep for this [`Duration`] after [`Self::MAIN`].
|
||||||
|
///
|
||||||
|
/// 1 second by default.
|
||||||
|
const POST_SLEEP_DURATION: Duration = Duration::from_secs(1);
|
||||||
|
}
|
5
benches/benchmark/lib/src/lib.rs
Normal file
5
benches/benchmark/lib/src/lib.rs
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#![doc = include_str!("../README.md")]
|
||||||
|
|
||||||
|
mod benchmark;
|
||||||
|
|
||||||
|
pub use benchmark::Benchmark;
|
23
benches/criterion/cuprate-json-rpc/Cargo.toml
Normal file
23
benches/criterion/cuprate-json-rpc/Cargo.toml
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
[package]
|
||||||
|
name = "cuprate-criterion-json-rpc"
|
||||||
|
version = "0.0.0"
|
||||||
|
edition = "2021"
|
||||||
|
description = "Criterion benchmarking for cuprate-json-rpc"
|
||||||
|
license = "MIT"
|
||||||
|
authors = ["hinto-janai"]
|
||||||
|
repository = "https://github.com/Cuprate/cuprate/tree/main/benches/criterion/cuprate-json-rpc"
|
||||||
|
keywords = ["cuprate", "json-rpc", "criterion", "benchmark"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
cuprate-json-rpc = { workspace = true }
|
||||||
|
|
||||||
|
criterion = { workspace = true }
|
||||||
|
function_name = { workspace = true }
|
||||||
|
serde_json = { workspace = true, features = ["default"] }
|
||||||
|
|
||||||
|
[[bench]]
|
||||||
|
name = "main"
|
||||||
|
harness = false
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
8
benches/criterion/cuprate-json-rpc/benches/main.rs
Normal file
8
benches/criterion/cuprate-json-rpc/benches/main.rs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
//! Benchmarks for `cuprate-json-rpc`.
|
||||||
|
#![allow(unused_crate_dependencies)]
|
||||||
|
|
||||||
|
mod response;
|
||||||
|
|
||||||
|
criterion::criterion_main! {
|
||||||
|
response::serde,
|
||||||
|
}
|
110
benches/criterion/cuprate-json-rpc/benches/response.rs
Normal file
110
benches/criterion/cuprate-json-rpc/benches/response.rs
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
//! Benchmarks for [`Response`].
|
||||||
|
#![allow(unused_attributes, unused_crate_dependencies)]
|
||||||
|
|
||||||
|
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
||||||
|
use function_name::named;
|
||||||
|
use serde_json::{from_str, to_string_pretty};
|
||||||
|
|
||||||
|
use cuprate_json_rpc::{Id, Response};
|
||||||
|
|
||||||
|
// `serde` benchmarks on `Response`.
|
||||||
|
//
|
||||||
|
// These are benchmarked as `Response` has a custom serde implementation.
|
||||||
|
criterion_group! {
|
||||||
|
name = serde;
|
||||||
|
config = Criterion::default();
|
||||||
|
targets =
|
||||||
|
response_from_str_u8,
|
||||||
|
response_from_str_u64,
|
||||||
|
response_from_str_string_5_len,
|
||||||
|
response_from_str_string_10_len,
|
||||||
|
response_from_str_string_100_len,
|
||||||
|
response_from_str_string_500_len,
|
||||||
|
response_to_string_pretty_u8,
|
||||||
|
response_to_string_pretty_u64,
|
||||||
|
response_to_string_pretty_string_5_len,
|
||||||
|
response_to_string_pretty_string_10_len,
|
||||||
|
response_to_string_pretty_string_100_len,
|
||||||
|
response_to_string_pretty_string_500_len,
|
||||||
|
response_from_str_bad_field_1,
|
||||||
|
response_from_str_bad_field_5,
|
||||||
|
response_from_str_bad_field_10,
|
||||||
|
response_from_str_bad_field_100,
|
||||||
|
response_from_str_missing_field,
|
||||||
|
}
|
||||||
|
criterion_main!(serde);
|
||||||
|
|
||||||
|
/// Generate `from_str` deserialization benchmark functions for [`Response`].
|
||||||
|
macro_rules! impl_from_str_benchmark {
|
||||||
|
(
|
||||||
|
$(
|
||||||
|
$fn_name:ident => $request_type:ty => $request_string:literal,
|
||||||
|
)*
|
||||||
|
) => {
|
||||||
|
$(
|
||||||
|
#[named]
|
||||||
|
fn $fn_name(c: &mut Criterion) {
|
||||||
|
let request_string = $request_string;
|
||||||
|
|
||||||
|
c.bench_function(function_name!(), |b| {
|
||||||
|
b.iter(|| {
|
||||||
|
let _r = from_str::<Response<$request_type>>(
|
||||||
|
black_box(request_string)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_from_str_benchmark! {
|
||||||
|
response_from_str_u8 => u8 => r#"{"jsonrpc":"2.0","id":123,"result":0}"#,
|
||||||
|
response_from_str_u64 => u64 => r#"{"jsonrpc":"2.0","id":123,"result":0}"#,
|
||||||
|
response_from_str_string_5_len => String => r#"{"jsonrpc":"2.0","id":123,"result":"hello"}"#,
|
||||||
|
response_from_str_string_10_len => String => r#"{"jsonrpc":"2.0","id":123,"result":"hellohello"}"#,
|
||||||
|
response_from_str_string_100_len => String => r#"{"jsonrpc":"2.0","id":123,"result":"helloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworld"}"#,
|
||||||
|
response_from_str_string_500_len => String => r#"{"jsonrpc":"2.0","id":123,"result":"helloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworld"}"#,
|
||||||
|
|
||||||
|
// The custom serde currently looks at all fields.
|
||||||
|
// These are for testing the performance if the serde
|
||||||
|
// has to parse through a bunch of unrelated fields.
|
||||||
|
response_from_str_bad_field_1 => u8 => r#"{"bad_field":0,"jsonrpc":"2.0","id":123,"result":0}"#,
|
||||||
|
response_from_str_bad_field_5 => u8 => r#"{"bad_field_1":0,"bad_field_2":0,"bad_field_3":0,"bad_field_4":0,"bad_field_5":0,"jsonrpc":"2.0","id":123,"result":0}"#,
|
||||||
|
response_from_str_bad_field_10 => u8 => r#"{"bad_field_1":0,"bad_field_2":0,"bad_field_3":0,"bad_field_4":0,"bad_field_5":0,"bad_field_6":0,"bad_field_7":0,"bad_field_8":0,"bad_field_9":0,"bad_field_10":0,"jsonrpc":"2.0","id":123,"result":0}"#,
|
||||||
|
response_from_str_bad_field_100 => u8 => r#"{"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":0,"57":0,"58":0,"59":0,"60":0,"61":0,"62":0,"63":0,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"70":0,"71":0,"72":0,"73":0,"74":0,"75":0,"76":0,"77":0,"78":0,"79":0,"80":0,"81":0,"82":0,"83":0,"84":0,"85":0,"86":0,"87":0,"88":0,"89":0,"90":0,"91":0,"92":0,"93":0,"94":0,"95":0,"96":0,"97":0,"98":0,"99":0,"100":0,"jsonrpc":"2.0","id":123,"result":0}"#,
|
||||||
|
|
||||||
|
// These are missing the `jsonrpc` field.
|
||||||
|
response_from_str_missing_field => u8 => r#"{"id":123,"result":0}"#,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generate `to_string_pretty` serialization benchmark functions for [`Response`].
|
||||||
|
macro_rules! impl_to_string_pretty_benchmark {
|
||||||
|
(
|
||||||
|
$(
|
||||||
|
$fn_name:ident => $request_constructor:expr,
|
||||||
|
)*
|
||||||
|
) => {
|
||||||
|
$(
|
||||||
|
#[named]
|
||||||
|
fn $fn_name(c: &mut Criterion) {
|
||||||
|
let request = $request_constructor;
|
||||||
|
|
||||||
|
c.bench_function(function_name!(), |b| {
|
||||||
|
b.iter(|| {
|
||||||
|
let _s = to_string_pretty(black_box(&request)).unwrap();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_to_string_pretty_benchmark! {
|
||||||
|
response_to_string_pretty_u8 => Response::<u8>::ok(Id::Null, 0),
|
||||||
|
response_to_string_pretty_u64 => Response::<u64>::ok(Id::Null, 0),
|
||||||
|
response_to_string_pretty_string_5_len => Response::ok(Id::Null, String::from("hello")),
|
||||||
|
response_to_string_pretty_string_10_len => Response::ok(Id::Null, String::from("hellohello")),
|
||||||
|
response_to_string_pretty_string_100_len => Response::ok(Id::Null, String::from("helloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworld")),
|
||||||
|
response_to_string_pretty_string_500_len => Response::ok(Id::Null, String::from("helloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworld")),
|
||||||
|
}
|
2
benches/criterion/cuprate-json-rpc/src/lib.rs
Normal file
2
benches/criterion/cuprate-json-rpc/src/lib.rs
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
//! Benchmark lib for `cuprate-json-rpc`.
|
||||||
|
#![allow(unused_crate_dependencies, reason = "used in benchmarks")]
|
21
benches/criterion/example/Cargo.toml
Normal file
21
benches/criterion/example/Cargo.toml
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
[package]
|
||||||
|
name = "cuprate-criterion-example"
|
||||||
|
version = "0.0.0"
|
||||||
|
edition = "2021"
|
||||||
|
description = "Criterion benchmarking example for Cuprate"
|
||||||
|
license = "MIT"
|
||||||
|
authors = ["hinto-janai"]
|
||||||
|
repository = "https://github.com/Cuprate/cuprate/tree/main/benches/criterion/example"
|
||||||
|
keywords = ["cuprate", "criterion", "benchmark", "example"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
criterion = { workspace = true }
|
||||||
|
function_name = { workspace = true }
|
||||||
|
serde_json = { workspace = true, features = ["default"] }
|
||||||
|
|
||||||
|
[[bench]]
|
||||||
|
name = "main"
|
||||||
|
harness = false
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
14
benches/criterion/example/README.md
Normal file
14
benches/criterion/example/README.md
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
## `cuprate-criterion-example`
|
||||||
|
An example of using Criterion for benchmarking Cuprate crates.
|
||||||
|
|
||||||
|
Consider copy+pasting this crate to use as a base when creating new Criterion benchmark crates.
|
||||||
|
|
||||||
|
## `src/`
|
||||||
|
Benchmark crates have a `benches/` ran by `cargo bench`, but they are also crates themselves,
|
||||||
|
as in, they have a `src` folder that `benches/` can pull code from.
|
||||||
|
|
||||||
|
The `src` directories in these benchmarking crates are usually filled with
|
||||||
|
helper functions, types, etc, that are used repeatedly in the benchmarks.
|
||||||
|
|
||||||
|
## `benches/`
|
||||||
|
These are the actual benchmarks ran by `cargo bench`.
|
48
benches/criterion/example/benches/example.rs
Normal file
48
benches/criterion/example/benches/example.rs
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
//! Benchmarks.
|
||||||
|
#![allow(unused_attributes, unused_crate_dependencies)]
|
||||||
|
|
||||||
|
use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion, Throughput};
|
||||||
|
use function_name::named;
|
||||||
|
|
||||||
|
use cuprate_criterion_example::SomeHardToCreateObject;
|
||||||
|
|
||||||
|
// This is how you register criterion benchmarks.
|
||||||
|
criterion_group! {
|
||||||
|
name = benches;
|
||||||
|
config = Criterion::default();
|
||||||
|
targets = benchmark_1, benchmark_range,
|
||||||
|
}
|
||||||
|
criterion_main!(benches);
|
||||||
|
|
||||||
|
/// Benchmark a single input.
|
||||||
|
///
|
||||||
|
/// <https://bheisler.github.io/criterion.rs/book/user_guide/benchmarking_with_inputs.html#benchmarking-with-one-input>
|
||||||
|
#[named]
|
||||||
|
fn benchmark_1(c: &mut Criterion) {
|
||||||
|
// It is recommended to use `function_name!()` as a benchmark
|
||||||
|
// identifier instead of manually re-typing the function name.
|
||||||
|
c.bench_function(function_name!(), |b| {
|
||||||
|
b.iter(|| {
|
||||||
|
black_box(SomeHardToCreateObject::from(1));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Benchmark a range of inputs.
|
||||||
|
///
|
||||||
|
/// <https://bheisler.github.io/criterion.rs/book/user_guide/benchmarking_with_inputs.html#benchmarking-with-a-range-of-values>
|
||||||
|
#[named]
|
||||||
|
fn benchmark_range(c: &mut Criterion) {
|
||||||
|
let mut group = c.benchmark_group(function_name!());
|
||||||
|
|
||||||
|
for i in 0..4 {
|
||||||
|
group.throughput(Throughput::Elements(i));
|
||||||
|
group.bench_with_input(BenchmarkId::from_parameter(i), &i, |b, &i| {
|
||||||
|
b.iter(|| {
|
||||||
|
black_box(SomeHardToCreateObject::from(i));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
group.finish();
|
||||||
|
}
|
10
benches/criterion/example/benches/main.rs
Normal file
10
benches/criterion/example/benches/main.rs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
//! Benchmarks examples.
|
||||||
|
#![allow(unused_crate_dependencies)]
|
||||||
|
|
||||||
|
// All modules within `benches/` are `mod`ed here.
|
||||||
|
mod example;
|
||||||
|
|
||||||
|
// And all the Criterion benchmarks are registered like so:
|
||||||
|
criterion::criterion_main! {
|
||||||
|
example::benches,
|
||||||
|
}
|
13
benches/criterion/example/src/lib.rs
Normal file
13
benches/criterion/example/src/lib.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#![doc = include_str!("../README.md")] // See the README for crate documentation.
|
||||||
|
#![allow(unused_crate_dependencies, reason = "used in benchmarks")]
|
||||||
|
|
||||||
|
/// Shared type that all benchmarks can use.
|
||||||
|
#[expect(dead_code)]
|
||||||
|
pub struct SomeHardToCreateObject(u64);
|
||||||
|
|
||||||
|
impl From<u64> for SomeHardToCreateObject {
|
||||||
|
/// Shared function that all benchmarks can use.
|
||||||
|
fn from(value: u64) -> Self {
|
||||||
|
Self(value)
|
||||||
|
}
|
||||||
|
}
|
|
@ -143,9 +143,16 @@
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
- [⚪️ Benchmarking](benchmarking/intro.md)
|
- [🟢 Benchmarking](benchmarking/intro.md)
|
||||||
- [⚪️ Criterion](benchmarking/criterion.md)
|
- [🟢 Criterion](benchmarking/criterion/intro.md)
|
||||||
- [⚪️ Harness](benchmarking/harness.md)
|
- [🟢 Creating](benchmarking/criterion/creating.md)
|
||||||
|
- [🟢 Running](benchmarking/criterion/running.md)
|
||||||
|
- [🟢 `cuprate-benchmark`](benchmarking/cuprate/intro.md)
|
||||||
|
- [🟢 Creating](benchmarking/cuprate/creating.md)
|
||||||
|
- [🟢 Running](benchmarking/cuprate/running.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
- [⚪️ Testing](testing/intro.md)
|
- [⚪️ Testing](testing/intro.md)
|
||||||
- [⚪️ Monero data](testing/monero-data.md)
|
- [⚪️ Monero data](testing/monero-data.md)
|
||||||
- [⚪️ RPC client](testing/rpc-client.md)
|
- [⚪️ RPC client](testing/rpc-client.md)
|
||||||
|
|
|
@ -68,3 +68,11 @@ cargo doc --open --package cuprate-blockchain
|
||||||
| [`cuprate-helper`](https://doc.cuprate.org/cuprate_helper) | [`helper/`](https://github.com/Cuprate/cuprate/tree/main/helper) | Kitchen-sink helper crate for Cuprate
|
| [`cuprate-helper`](https://doc.cuprate.org/cuprate_helper) | [`helper/`](https://github.com/Cuprate/cuprate/tree/main/helper) | Kitchen-sink helper crate for Cuprate
|
||||||
| [`cuprate-test-utils`](https://doc.cuprate.org/cuprate_test_utils) | [`test-utils/`](https://github.com/Cuprate/cuprate/tree/main/test-utils) | Testing utilities for Cuprate
|
| [`cuprate-test-utils`](https://doc.cuprate.org/cuprate_test_utils) | [`test-utils/`](https://github.com/Cuprate/cuprate/tree/main/test-utils) | Testing utilities for Cuprate
|
||||||
| [`cuprate-types`](https://doc.cuprate.org/cuprate_types) | [`types/`](https://github.com/Cuprate/cuprate/tree/main/types) | Shared types across Cuprate
|
| [`cuprate-types`](https://doc.cuprate.org/cuprate_types) | [`types/`](https://github.com/Cuprate/cuprate/tree/main/types) | Shared types across Cuprate
|
||||||
|
|
||||||
|
## Benchmarks
|
||||||
|
| Crate | In-tree path | Purpose |
|
||||||
|
|-------|--------------|---------|
|
||||||
|
| [`cuprate-benchmark`](https://doc.cuprate.org/cuprate_benchmark) | [`benches/benchmark/bin/`](https://github.com/Cuprate/cuprate/tree/main/benches/benchmark/bin) | Cuprate benchmarking binary
|
||||||
|
| [`cuprate-benchmark-lib`](https://doc.cuprate.org/cuprate_benchmark_lib) | [`benches/benchmark/lib/`](https://github.com/Cuprate/cuprate/tree/main/benches/benchmark/lib) | Cuprate benchmarking library
|
||||||
|
| `cuprate-benchmark-*` | [`benches/benchmark/cuprate-*`](https://github.com/Cuprate/cuprate/tree/main/benches/benchmark/) | Benchmark for a Cuprate crate that uses `cuprate-benchmark`
|
||||||
|
| `cuprate-criterion-*` | [`benches/criterion/cuprate-*`](https://github.com/Cuprate/cuprate/tree/main/benches/criterion) | Benchmark for a Cuprate crate that uses [Criterion](https://bheisler.github.io/criterion.rs/book)
|
|
@ -1 +0,0 @@
|
||||||
# ⚪️ Criterion
|
|
21
books/architecture/src/benchmarking/criterion/creating.md
Normal file
21
books/architecture/src/benchmarking/criterion/creating.md
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# Creating
|
||||||
|
Creating a new Criterion-based benchmarking crate for one of Cuprate's crates is relatively simple,
|
||||||
|
although, it requires knowledge of how to use Criterion first:
|
||||||
|
|
||||||
|
1. Read the `Getting Started` section of <https://bheisler.github.io/criterion.rs/book>
|
||||||
|
2. Copy [`benches/criterion/example`](https://github.com/Cuprate/cuprate/tree/main/benches/criterion/example) as base
|
||||||
|
3. Get started
|
||||||
|
|
||||||
|
## Naming
|
||||||
|
New benchmark crates using Criterion should:
|
||||||
|
- Be in [`benches/criterion/`](https://github.com/Cuprate/cuprate/tree/main/benches/criterion/)
|
||||||
|
- Be in the `cuprate-criterion-$CRATE_NAME` format
|
||||||
|
|
||||||
|
For a real example, see:
|
||||||
|
[`cuprate-criterion-json-rpc`](https://github.com/Cuprate/cuprate/tree/main/benches/criterion/cuprate-json-rpc).
|
||||||
|
|
||||||
|
## Workspace
|
||||||
|
Finally, make sure to add the benchmark crate to the workspace
|
||||||
|
[`Cargo.toml`](https://github.com/Cuprate/cuprate/blob/main/Cargo.toml) file.
|
||||||
|
|
||||||
|
Your benchmark is now ready to be ran.
|
4
books/architecture/src/benchmarking/criterion/intro.md
Normal file
4
books/architecture/src/benchmarking/criterion/intro.md
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
# Criterion
|
||||||
|
Each sub-directory in [`benches/criterion/`](https://github.com/Cuprate/cuprate/tree/main/benches/criterion) is a crate that uses [Criterion](https://bheisler.github.io/criterion.rs/book) for timing single functions and/or groups of functions.
|
||||||
|
|
||||||
|
They are generally be small in scope.
|
15
books/architecture/src/benchmarking/criterion/running.md
Normal file
15
books/architecture/src/benchmarking/criterion/running.md
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
# Running
|
||||||
|
To run all Criterion benchmarks, run this from the repository root:
|
||||||
|
```bash
|
||||||
|
cargo bench
|
||||||
|
```
|
||||||
|
|
||||||
|
To run specific package(s), use:
|
||||||
|
```bash
|
||||||
|
cargo bench --package $CRITERION_BENCHMARK_CRATE_NAME
|
||||||
|
```
|
||||||
|
|
||||||
|
For example:
|
||||||
|
```bash
|
||||||
|
cargo bench --package cuprate-criterion-json-rpc
|
||||||
|
```
|
57
books/architecture/src/benchmarking/cuprate/creating.md
Normal file
57
books/architecture/src/benchmarking/cuprate/creating.md
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
# Creating
|
||||||
|
New benchmarks are plugged into `cuprate-benchmark` by:
|
||||||
|
1. Implementing `cuprate_benchmark_lib::Benchmark`
|
||||||
|
1. Registering the benchmark in the `cuprate_benchmark` binary
|
||||||
|
|
||||||
|
See [`benches/benchmark/example`](https://github.com/Cuprate/cuprate/tree/main/benches/benchmark/example)
|
||||||
|
for an example.
|
||||||
|
|
||||||
|
## Creating the benchmark crate
|
||||||
|
Before plugging into `cuprate-benchmark`, your actual benchmark crate must be created:
|
||||||
|
|
||||||
|
1. Create a new crate inside `benches/benchmark` (consider copying `benches/benchmark/example` as a base)
|
||||||
|
1. Pull in `cuprate_benchmark_lib` as a dependency
|
||||||
|
1. Create a benchmark
|
||||||
|
1. Implement `cuprate_benchmark_lib::Benchmark`
|
||||||
|
|
||||||
|
New benchmark crates using `cuprate-database` should:
|
||||||
|
- Be in [`benches/benchmark/`](https://github.com/Cuprate/cuprate/tree/main/benches/benchmark/)
|
||||||
|
- Be in the `cuprate-benchmark-$CRATE_NAME` format
|
||||||
|
|
||||||
|
For a real example, see:
|
||||||
|
[`cuprate-benchmark-database`](https://github.com/Cuprate/cuprate/tree/main/benches/benchmark/cuprate-database).
|
||||||
|
|
||||||
|
## `cuprate_benchmark_lib::Benchmark`
|
||||||
|
This is the trait that standardizes all benchmarks ran under `cuprate-benchmark`.
|
||||||
|
|
||||||
|
It must be implemented by your benchmarking crate.
|
||||||
|
|
||||||
|
See `cuprate-benchmark-lib` crate documentation for a user-guide: <https://doc.cuprate.org/cuprate_benchmark_lib>.
|
||||||
|
|
||||||
|
## Adding a feature to `cuprate-benchmark`
|
||||||
|
After your benchmark's behavior is defined, it must be registered
|
||||||
|
in the binary that is actually ran: `cuprate-benchmark`.
|
||||||
|
|
||||||
|
If your benchmark is new, add a new crate feature to [`cuprate-benchmark`'s Cargo.toml file](https://github.com/Cuprate/cuprate/tree/main/benches/benchmark/bin/Cargo.toml) with an optional dependency to your benchmarking crate.
|
||||||
|
|
||||||
|
Please remember to edit the feature table in the
|
||||||
|
[`README.md`](https://github.com/Cuprate/cuprate/tree/main/benches/benchmark/bin/README.md) as well!
|
||||||
|
|
||||||
|
## Adding to `cuprate-benchmark`'s `main()`
|
||||||
|
After adding your crate's feature, add a conditional line that run the benchmark
|
||||||
|
if the feature is enabled to the `main()` function:
|
||||||
|
|
||||||
|
For example, if your crate's name is `egg`:
|
||||||
|
```rust
|
||||||
|
cfg_if! {
|
||||||
|
if #[cfg(feature = "egg")] {
|
||||||
|
run::run_benchmark::<cuprate_benchmark_egg::Benchmark>(&mut timings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Workspace
|
||||||
|
Finally, make sure to add the benchmark crate to the workspace
|
||||||
|
[`Cargo.toml`](https://github.com/Cuprate/cuprate/blob/main/Cargo.toml) file.
|
||||||
|
|
||||||
|
Your benchmark is now ready to be ran.
|
37
books/architecture/src/benchmarking/cuprate/intro.md
Normal file
37
books/architecture/src/benchmarking/cuprate/intro.md
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
# cuprate-benchmark
|
||||||
|
Cuprate has 2 custom crates for general benchmarking:
|
||||||
|
- `cuprate-benchmark`; the actual binary crate ran
|
||||||
|
- `cuprate-benchmark-lib`; the library that other crates hook into
|
||||||
|
|
||||||
|
The abstract purpose of `cuprate-benchmark` is very simple:
|
||||||
|
1. Set-up the benchmark
|
||||||
|
1. Start timer
|
||||||
|
1. Run benchmark
|
||||||
|
1. Output data
|
||||||
|
|
||||||
|
`cuprate-benchmark` runs the benchmarks found in [`benches/benchmark/cuprate-*`](https://github.com/Cuprate/cuprate/tree/main/benches/benchmark).
|
||||||
|
|
||||||
|
`cuprate-benchmark-lib` defines the `Benchmark` trait that all
|
||||||
|
benchmark crates implement to "plug-in" to the benchmarking harness.
|
||||||
|
|
||||||
|
## Diagram
|
||||||
|
A diagram displaying the relation between `cuprate-benchmark` and related crates.
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────┐
|
||||||
|
│ cuprate_benchmark │
|
||||||
|
│ (actual binary ran) │
|
||||||
|
└──────────┬──────────┘
|
||||||
|
┌──────────────────┴───────────────────┐
|
||||||
|
│ cuprate_benchmark_lib │
|
||||||
|
│ ┌───────────────────────────────────┐│
|
||||||
|
│ │ trait Benchmark ││
|
||||||
|
│ └───────────────────────────────────┘│
|
||||||
|
└──────────────────┬───────────────────┘
|
||||||
|
┌───────────────────────────┐ │ ┌───────────────────────────┐
|
||||||
|
│ cuprate_benchmark_example ├──┼───┤ cuprate_benchmark_* │
|
||||||
|
└───────────────────────────┘ │ └───────────────────────────┘
|
||||||
|
┌───────────────────────────┐ │ ┌───────────────────────────┐
|
||||||
|
│ cuprate_benchmark_* ├──┴───┤ cuprate_benchmark_* │
|
||||||
|
└───────────────────────────┘ └───────────────────────────┘
|
||||||
|
```
|
16
books/architecture/src/benchmarking/cuprate/running.md
Normal file
16
books/architecture/src/benchmarking/cuprate/running.md
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
# Running
|
||||||
|
`cuprate-benchmark` benchmarks are ran with this command:
|
||||||
|
```bash
|
||||||
|
cargo run --release --package cuprate-benchmark --features $BENCHMARK_CRATE_FEATURE
|
||||||
|
```
|
||||||
|
|
||||||
|
For example, to run the example benchmark:
|
||||||
|
```bash
|
||||||
|
cargo run --release --package cuprate-benchmark --features example
|
||||||
|
```
|
||||||
|
|
||||||
|
Use the `all` feature to run all benchmarks:
|
||||||
|
```bash
|
||||||
|
# Run all benchmarks
|
||||||
|
cargo run --release --package cuprate-benchmark --features all
|
||||||
|
```
|
|
@ -1 +0,0 @@
|
||||||
# ⚪️ Harness
|
|
|
@ -1 +1,22 @@
|
||||||
# ⚪️ Benchmarking
|
# Benchmarking
|
||||||
|
Cuprate has 2 types of benchmarks:
|
||||||
|
- [Criterion](https://bheisler.github.io/criterion.rs/book/user_guide/advanced_configuration.html) benchmarks
|
||||||
|
- `cuprate-benchmark` benchmarks
|
||||||
|
|
||||||
|
Criterion is used for micro benchmarks; they time single functions, groups of functions, and generally are small in scope.
|
||||||
|
|
||||||
|
`cuprate-benchmark` and [`cuprate-benchmark-lib`](https://doc.cuprate.org/cuprate_benchmark_lib) are custom in-house crates Cuprate uses for macro benchmarks; these test sub-systems, sections of a sub-system, or otherwise larger or more complicated code that isn't well-suited for micro benchmarks.
|
||||||
|
|
||||||
|
## File layout and purpose
|
||||||
|
All benchmarking related files are in the [`benches/`](https://github.com/Cuprate/cuprate/tree/main/benches) folder.
|
||||||
|
|
||||||
|
This directory is organized like such:
|
||||||
|
|
||||||
|
| Directory | Purpose |
|
||||||
|
|-------------------------------|---------|
|
||||||
|
| [`benches/criterion/`](https://github.com/Cuprate/cuprate/tree/main/benches/criterion) | Criterion (micro) benchmarks
|
||||||
|
| `benches/criterion/cuprate-*` | Criterion benchmarks for the crate with the same name
|
||||||
|
| [`benches/benchmark/`](https://github.com/Cuprate/cuprate/tree/main/benches/benchmark) | Cuprate's custom benchmarking files
|
||||||
|
| [`benches/benchmark/bin`](https://github.com/Cuprate/cuprate/tree/main/benches/benchmark/bin) | The `cuprate-benchmark` crate; the actual binary run that links all benchmarks
|
||||||
|
| [`benches/benchmark/lib`](https://github.com/Cuprate/cuprate/tree/main/benches/benchmark/lib) | The `cuprate-benchmark-lib` crate; the benchmarking framework all benchmarks plug into
|
||||||
|
| `benches/benchmark/cuprate-*` | `cuprate-benchmark` benchmarks for the crate with the same name
|
||||||
|
|
|
@ -9,26 +9,19 @@ use cuprate_fixed_bytes::ByteArrayVec;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[cfg(feature = "epee")]
|
#[cfg(feature = "epee")]
|
||||||
use cuprate_epee_encoding::{
|
use cuprate_epee_encoding::container_as_blob::ContainerAsBlob;
|
||||||
container_as_blob::ContainerAsBlob,
|
|
||||||
epee_object, error,
|
|
||||||
macros::bytes::{Buf, BufMut},
|
|
||||||
read_epee_value, write_field, EpeeObject, EpeeObjectBuilder,
|
|
||||||
};
|
|
||||||
|
|
||||||
use cuprate_types::BlockCompleteEntry;
|
use cuprate_types::BlockCompleteEntry;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
base::AccessResponseBase,
|
base::AccessResponseBase,
|
||||||
macros::{define_request, define_request_and_response, define_request_and_response_doc},
|
macros::define_request_and_response,
|
||||||
misc::{BlockOutputIndices, GetOutputsOut, OutKeyBin, PoolTxInfo, Status},
|
misc::{BlockOutputIndices, GetOutputsOut, OutKeyBin, PoolInfo},
|
||||||
rpc_call::RpcCallValue,
|
rpc_call::RpcCallValue,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(any(feature = "epee", feature = "serde"))]
|
#[cfg(any(feature = "epee", feature = "serde"))]
|
||||||
use crate::defaults::{default_false, default_zero};
|
use crate::defaults::{default_false, default_zero};
|
||||||
#[cfg(feature = "epee")]
|
|
||||||
use crate::misc::PoolInfoExtent;
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------- Definitions
|
//---------------------------------------------------------------------------------------------------- Definitions
|
||||||
define_request_and_response! {
|
define_request_and_response! {
|
||||||
|
@ -115,15 +108,14 @@ define_request_and_response! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------- GetBlocks
|
define_request_and_response! {
|
||||||
define_request! {
|
get_blocksbin,
|
||||||
#[doc = define_request_and_response_doc!(
|
cc73fe71162d564ffda8e549b79a350bca53c454 =>
|
||||||
"response" => GetBlocksResponse,
|
core_rpc_server_commands_defs.h => 162..=262,
|
||||||
get_blocksbin,
|
|
||||||
cc73fe71162d564ffda8e549b79a350bca53c454,
|
GetBlocks,
|
||||||
core_rpc_server_commands_defs, h, 162, 262,
|
|
||||||
)]
|
Request {
|
||||||
GetBlocksRequest {
|
|
||||||
requested_info: u8 = default_zero::<u8>(), "default_zero",
|
requested_info: u8 = default_zero::<u8>(), "default_zero",
|
||||||
// FIXME: This is a `std::list` in `monerod` because...?
|
// FIXME: This is a `std::list` in `monerod` because...?
|
||||||
block_ids: ByteArrayVec<32>,
|
block_ids: ByteArrayVec<32>,
|
||||||
|
@ -131,259 +123,17 @@ define_request! {
|
||||||
prune: bool,
|
prune: bool,
|
||||||
no_miner_tx: bool = default_false(), "default_false",
|
no_miner_tx: bool = default_false(), "default_false",
|
||||||
pool_info_since: u64 = default_zero::<u64>(), "default_zero",
|
pool_info_since: u64 = default_zero::<u64>(), "default_zero",
|
||||||
}
|
},
|
||||||
}
|
|
||||||
|
|
||||||
#[doc = define_request_and_response_doc!(
|
// TODO: add `top_block_hash` field
|
||||||
"request" => GetBlocksRequest,
|
// <https://github.com/monero-project/monero/blame/893916ad091a92e765ce3241b94e706ad012b62a/src/rpc/core_rpc_server_commands_defs.h#L263>
|
||||||
get_blocksbin,
|
AccessResponseBase {
|
||||||
cc73fe71162d564ffda8e549b79a350bca53c454,
|
blocks: Vec<BlockCompleteEntry>,
|
||||||
core_rpc_server_commands_defs, h, 162, 262,
|
start_height: u64,
|
||||||
)]
|
current_height: u64,
|
||||||
///
|
output_indices: Vec<BlockOutputIndices>,
|
||||||
/// This response's variant depends upon [`PoolInfoExtent`].
|
daemon_time: u64,
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
pool_info: PoolInfo,
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
|
||||||
pub enum GetBlocksResponse {
|
|
||||||
/// Will always serialize a [`PoolInfoExtent::None`] field.
|
|
||||||
PoolInfoNone(GetBlocksResponsePoolInfoNone),
|
|
||||||
/// Will always serialize a [`PoolInfoExtent::Incremental`] field.
|
|
||||||
PoolInfoIncremental(GetBlocksResponsePoolInfoIncremental),
|
|
||||||
/// Will always serialize a [`PoolInfoExtent::Full`] field.
|
|
||||||
PoolInfoFull(GetBlocksResponsePoolInfoFull),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for GetBlocksResponse {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::PoolInfoNone(GetBlocksResponsePoolInfoNone::default())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Data within [`GetBlocksResponse::PoolInfoNone`].
|
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
|
||||||
#[derive(Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
|
||||||
pub struct GetBlocksResponsePoolInfoNone {
|
|
||||||
pub status: Status,
|
|
||||||
pub untrusted: bool,
|
|
||||||
pub blocks: Vec<BlockCompleteEntry>,
|
|
||||||
pub start_height: u64,
|
|
||||||
pub current_height: u64,
|
|
||||||
pub output_indices: Vec<BlockOutputIndices>,
|
|
||||||
pub daemon_time: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "epee")]
|
|
||||||
epee_object! {
|
|
||||||
GetBlocksResponsePoolInfoNone,
|
|
||||||
status: Status,
|
|
||||||
untrusted: bool,
|
|
||||||
blocks: Vec<BlockCompleteEntry>,
|
|
||||||
start_height: u64,
|
|
||||||
current_height: u64,
|
|
||||||
output_indices: Vec<BlockOutputIndices>,
|
|
||||||
daemon_time: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Data within [`GetBlocksResponse::PoolInfoIncremental`].
|
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
|
||||||
#[derive(Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
|
||||||
pub struct GetBlocksResponsePoolInfoIncremental {
|
|
||||||
pub status: Status,
|
|
||||||
pub untrusted: bool,
|
|
||||||
pub blocks: Vec<BlockCompleteEntry>,
|
|
||||||
pub start_height: u64,
|
|
||||||
pub current_height: u64,
|
|
||||||
pub output_indices: Vec<BlockOutputIndices>,
|
|
||||||
pub daemon_time: u64,
|
|
||||||
pub added_pool_txs: Vec<PoolTxInfo>,
|
|
||||||
pub remaining_added_pool_txids: ByteArrayVec<32>,
|
|
||||||
pub removed_pool_txids: ByteArrayVec<32>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "epee")]
|
|
||||||
epee_object! {
|
|
||||||
GetBlocksResponsePoolInfoIncremental,
|
|
||||||
status: Status,
|
|
||||||
untrusted: bool,
|
|
||||||
blocks: Vec<BlockCompleteEntry>,
|
|
||||||
start_height: u64,
|
|
||||||
current_height: u64,
|
|
||||||
output_indices: Vec<BlockOutputIndices>,
|
|
||||||
daemon_time: u64,
|
|
||||||
added_pool_txs: Vec<PoolTxInfo>,
|
|
||||||
remaining_added_pool_txids: ByteArrayVec<32>,
|
|
||||||
removed_pool_txids: ByteArrayVec<32>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Data within [`GetBlocksResponse::PoolInfoFull`].
|
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
|
||||||
#[derive(Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
|
||||||
pub struct GetBlocksResponsePoolInfoFull {
|
|
||||||
pub status: Status,
|
|
||||||
pub untrusted: bool,
|
|
||||||
pub blocks: Vec<BlockCompleteEntry>,
|
|
||||||
pub start_height: u64,
|
|
||||||
pub current_height: u64,
|
|
||||||
pub output_indices: Vec<BlockOutputIndices>,
|
|
||||||
pub daemon_time: u64,
|
|
||||||
pub added_pool_txs: Vec<PoolTxInfo>,
|
|
||||||
pub remaining_added_pool_txids: ByteArrayVec<32>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "epee")]
|
|
||||||
epee_object! {
|
|
||||||
GetBlocksResponsePoolInfoFull,
|
|
||||||
status: Status,
|
|
||||||
untrusted: bool,
|
|
||||||
blocks: Vec<BlockCompleteEntry>,
|
|
||||||
start_height: u64,
|
|
||||||
current_height: u64,
|
|
||||||
output_indices: Vec<BlockOutputIndices>,
|
|
||||||
daemon_time: u64,
|
|
||||||
added_pool_txs: Vec<PoolTxInfo>,
|
|
||||||
remaining_added_pool_txids: ByteArrayVec<32>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "epee")]
|
|
||||||
/// [`EpeeObjectBuilder`] for [`GetBlocksResponse`].
|
|
||||||
///
|
|
||||||
/// Not for public usage.
|
|
||||||
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
|
||||||
pub struct __GetBlocksResponseEpeeBuilder {
|
|
||||||
pub status: Option<Status>,
|
|
||||||
pub untrusted: Option<bool>,
|
|
||||||
pub blocks: Option<Vec<BlockCompleteEntry>>,
|
|
||||||
pub start_height: Option<u64>,
|
|
||||||
pub current_height: Option<u64>,
|
|
||||||
pub output_indices: Option<Vec<BlockOutputIndices>>,
|
|
||||||
pub daemon_time: Option<u64>,
|
|
||||||
pub pool_info_extent: Option<PoolInfoExtent>,
|
|
||||||
pub added_pool_txs: Option<Vec<PoolTxInfo>>,
|
|
||||||
pub remaining_added_pool_txids: Option<ByteArrayVec<32>>,
|
|
||||||
pub removed_pool_txids: Option<ByteArrayVec<32>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "epee")]
|
|
||||||
impl EpeeObjectBuilder<GetBlocksResponse> for __GetBlocksResponseEpeeBuilder {
|
|
||||||
fn add_field<B: Buf>(&mut self, name: &str, r: &mut B) -> error::Result<bool> {
|
|
||||||
macro_rules! read_epee_field {
|
|
||||||
($($field:ident),*) => {
|
|
||||||
match name {
|
|
||||||
$(
|
|
||||||
stringify!($field) => { self.$field = Some(read_epee_value(r)?); },
|
|
||||||
)*
|
|
||||||
_ => return Ok(false),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
read_epee_field! {
|
|
||||||
status,
|
|
||||||
untrusted,
|
|
||||||
blocks,
|
|
||||||
start_height,
|
|
||||||
current_height,
|
|
||||||
output_indices,
|
|
||||||
daemon_time,
|
|
||||||
pool_info_extent,
|
|
||||||
added_pool_txs,
|
|
||||||
remaining_added_pool_txids,
|
|
||||||
removed_pool_txids
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn finish(self) -> error::Result<GetBlocksResponse> {
|
|
||||||
const ELSE: error::Error = error::Error::Format("Required field was not found!");
|
|
||||||
|
|
||||||
let status = self.status.ok_or(ELSE)?;
|
|
||||||
let untrusted = self.untrusted.ok_or(ELSE)?;
|
|
||||||
let blocks = self.blocks.ok_or(ELSE)?;
|
|
||||||
let start_height = self.start_height.ok_or(ELSE)?;
|
|
||||||
let current_height = self.current_height.ok_or(ELSE)?;
|
|
||||||
let output_indices = self.output_indices.ok_or(ELSE)?;
|
|
||||||
let daemon_time = self.daemon_time.ok_or(ELSE)?;
|
|
||||||
let pool_info_extent = self.pool_info_extent.ok_or(ELSE)?;
|
|
||||||
|
|
||||||
let this = match pool_info_extent {
|
|
||||||
PoolInfoExtent::None => {
|
|
||||||
GetBlocksResponse::PoolInfoNone(GetBlocksResponsePoolInfoNone {
|
|
||||||
status,
|
|
||||||
untrusted,
|
|
||||||
blocks,
|
|
||||||
start_height,
|
|
||||||
current_height,
|
|
||||||
output_indices,
|
|
||||||
daemon_time,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
PoolInfoExtent::Incremental => {
|
|
||||||
GetBlocksResponse::PoolInfoIncremental(GetBlocksResponsePoolInfoIncremental {
|
|
||||||
status,
|
|
||||||
untrusted,
|
|
||||||
blocks,
|
|
||||||
start_height,
|
|
||||||
current_height,
|
|
||||||
output_indices,
|
|
||||||
daemon_time,
|
|
||||||
added_pool_txs: self.added_pool_txs.ok_or(ELSE)?,
|
|
||||||
remaining_added_pool_txids: self.remaining_added_pool_txids.ok_or(ELSE)?,
|
|
||||||
removed_pool_txids: self.removed_pool_txids.ok_or(ELSE)?,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
PoolInfoExtent::Full => {
|
|
||||||
GetBlocksResponse::PoolInfoFull(GetBlocksResponsePoolInfoFull {
|
|
||||||
status,
|
|
||||||
untrusted,
|
|
||||||
blocks,
|
|
||||||
start_height,
|
|
||||||
current_height,
|
|
||||||
output_indices,
|
|
||||||
daemon_time,
|
|
||||||
added_pool_txs: self.added_pool_txs.ok_or(ELSE)?,
|
|
||||||
remaining_added_pool_txids: self.remaining_added_pool_txids.ok_or(ELSE)?,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "epee")]
|
|
||||||
impl EpeeObject for GetBlocksResponse {
|
|
||||||
type Builder = __GetBlocksResponseEpeeBuilder;
|
|
||||||
|
|
||||||
fn number_of_fields(&self) -> u64 {
|
|
||||||
// [`PoolInfoExtent`] + inner struct fields.
|
|
||||||
let inner_fields = match self {
|
|
||||||
Self::PoolInfoNone(s) => s.number_of_fields(),
|
|
||||||
Self::PoolInfoIncremental(s) => s.number_of_fields(),
|
|
||||||
Self::PoolInfoFull(s) => s.number_of_fields(),
|
|
||||||
};
|
|
||||||
|
|
||||||
1 + inner_fields
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_fields<B: BufMut>(self, w: &mut B) -> error::Result<()> {
|
|
||||||
match self {
|
|
||||||
Self::PoolInfoNone(s) => {
|
|
||||||
s.write_fields(w)?;
|
|
||||||
write_field(PoolInfoExtent::None.to_u8(), "pool_info_extent", w)?;
|
|
||||||
}
|
|
||||||
Self::PoolInfoIncremental(s) => {
|
|
||||||
s.write_fields(w)?;
|
|
||||||
write_field(PoolInfoExtent::Incremental.to_u8(), "pool_info_extent", w)?;
|
|
||||||
}
|
|
||||||
Self::PoolInfoFull(s) => {
|
|
||||||
s.write_fields(w)?;
|
|
||||||
write_field(PoolInfoExtent::Full.to_u8(), "pool_info_extent", w)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,11 +11,11 @@ use serde::{Deserialize, Serialize};
|
||||||
#[cfg(feature = "epee")]
|
#[cfg(feature = "epee")]
|
||||||
use cuprate_epee_encoding::epee_object;
|
use cuprate_epee_encoding::epee_object;
|
||||||
|
|
||||||
use crate::macros::monero_definition_link;
|
|
||||||
|
|
||||||
#[cfg(any(feature = "epee", feature = "serde"))]
|
#[cfg(any(feature = "epee", feature = "serde"))]
|
||||||
use crate::defaults::default_zero;
|
use crate::defaults::default_zero;
|
||||||
|
|
||||||
|
use crate::macros::monero_definition_link;
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------- Macros
|
//---------------------------------------------------------------------------------------------------- Macros
|
||||||
/// This macro (local to this file) defines all the misc types.
|
/// This macro (local to this file) defines all the misc types.
|
||||||
///
|
///
|
||||||
|
|
|
@ -17,6 +17,7 @@ mod distribution;
|
||||||
mod key_image_spent_status;
|
mod key_image_spent_status;
|
||||||
#[expect(clippy::module_inception)]
|
#[expect(clippy::module_inception)]
|
||||||
mod misc;
|
mod misc;
|
||||||
|
mod pool_info;
|
||||||
mod pool_info_extent;
|
mod pool_info_extent;
|
||||||
mod status;
|
mod status;
|
||||||
mod tx_entry;
|
mod tx_entry;
|
||||||
|
@ -30,6 +31,7 @@ pub use misc::{
|
||||||
OutputDistributionData, Peer, PoolTxInfo, PublicNode, SetBan, Span, SpentKeyImageInfo,
|
OutputDistributionData, Peer, PoolTxInfo, PublicNode, SetBan, Span, SpentKeyImageInfo,
|
||||||
SyncInfoPeer, TxBacklogEntry, TxInfo, TxOutputIndices, TxpoolHisto, TxpoolStats,
|
SyncInfoPeer, TxBacklogEntry, TxInfo, TxOutputIndices, TxpoolHisto, TxpoolStats,
|
||||||
};
|
};
|
||||||
|
pub use pool_info::PoolInfo;
|
||||||
pub use pool_info_extent::PoolInfoExtent;
|
pub use pool_info_extent::PoolInfoExtent;
|
||||||
pub use status::Status;
|
pub use status::Status;
|
||||||
pub use tx_entry::TxEntry;
|
pub use tx_entry::TxEntry;
|
||||||
|
|
171
rpc/types/src/misc/pool_info.rs
Normal file
171
rpc/types/src/misc/pool_info.rs
Normal file
|
@ -0,0 +1,171 @@
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[cfg(feature = "epee")]
|
||||||
|
use crate::misc::PoolInfoExtent;
|
||||||
|
#[cfg(feature = "epee")]
|
||||||
|
use cuprate_epee_encoding::{
|
||||||
|
epee_object, error,
|
||||||
|
macros::bytes::{Buf, BufMut},
|
||||||
|
read_epee_value, write_field, EpeeObject, EpeeObjectBuilder,
|
||||||
|
};
|
||||||
|
|
||||||
|
use cuprate_fixed_bytes::ByteArrayVec;
|
||||||
|
|
||||||
|
use crate::misc::PoolTxInfo;
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------------- PoolInfo
|
||||||
|
#[doc = crate::macros::monero_definition_link!(
|
||||||
|
cc73fe71162d564ffda8e549b79a350bca53c454,
|
||||||
|
"rpc/core_rpc_server_commands_defs.h",
|
||||||
|
223..=228
|
||||||
|
)]
|
||||||
|
/// Used in [`crate::bin::GetBlocksResponse`].
|
||||||
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
|
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
#[repr(u8)]
|
||||||
|
pub enum PoolInfo {
|
||||||
|
#[default]
|
||||||
|
None,
|
||||||
|
Incremental(PoolInfoIncremental),
|
||||||
|
Full(PoolInfoFull),
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------------- Internal data
|
||||||
|
/// Data within [`PoolInfo::Incremental`].
|
||||||
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
|
#[derive(Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
pub struct PoolInfoIncremental {
|
||||||
|
pub added_pool_txs: Vec<PoolTxInfo>,
|
||||||
|
pub remaining_added_pool_txids: ByteArrayVec<32>,
|
||||||
|
pub removed_pool_txids: ByteArrayVec<32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "epee")]
|
||||||
|
epee_object! {
|
||||||
|
PoolInfoIncremental,
|
||||||
|
added_pool_txs: Vec<PoolTxInfo>,
|
||||||
|
remaining_added_pool_txids: ByteArrayVec<32>,
|
||||||
|
removed_pool_txids: ByteArrayVec<32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Data within [`PoolInfo::Full`].
|
||||||
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
|
#[derive(Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
pub struct PoolInfoFull {
|
||||||
|
pub added_pool_txs: Vec<PoolTxInfo>,
|
||||||
|
pub remaining_added_pool_txids: ByteArrayVec<32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "epee")]
|
||||||
|
epee_object! {
|
||||||
|
PoolInfoFull,
|
||||||
|
added_pool_txs: Vec<PoolTxInfo>,
|
||||||
|
remaining_added_pool_txids: ByteArrayVec<32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------------- PoolInfo epee impl
|
||||||
|
#[cfg(feature = "epee")]
|
||||||
|
/// [`EpeeObjectBuilder`] for [`GetBlocksResponse`].
|
||||||
|
///
|
||||||
|
/// Not for public usage.
|
||||||
|
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
|
pub struct __PoolInfoEpeeBuilder {
|
||||||
|
/// This is a distinct field in `monerod`,
|
||||||
|
/// which as represented in this library with [`PoolInfo`]'s `u8` tag.
|
||||||
|
pub pool_info_extent: Option<PoolInfoExtent>,
|
||||||
|
|
||||||
|
pub added_pool_txs: Option<Vec<PoolTxInfo>>,
|
||||||
|
pub remaining_added_pool_txids: Option<ByteArrayVec<32>>,
|
||||||
|
pub removed_pool_txids: Option<ByteArrayVec<32>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Custom epee implementation.
|
||||||
|
//
|
||||||
|
// HACK/INVARIANT:
|
||||||
|
// If any data within [`PoolInfo`] changes, the below code should be changed as well.
|
||||||
|
#[cfg(feature = "epee")]
|
||||||
|
impl EpeeObjectBuilder<PoolInfo> for __PoolInfoEpeeBuilder {
|
||||||
|
fn add_field<B: Buf>(&mut self, name: &str, r: &mut B) -> error::Result<bool> {
|
||||||
|
macro_rules! read_epee_field {
|
||||||
|
($($field:ident),*) => {
|
||||||
|
match name {
|
||||||
|
$(
|
||||||
|
stringify!($field) => { self.$field = Some(read_epee_value(r)?); },
|
||||||
|
)*
|
||||||
|
_ => return Ok(false),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
read_epee_field! {
|
||||||
|
pool_info_extent,
|
||||||
|
added_pool_txs,
|
||||||
|
remaining_added_pool_txids,
|
||||||
|
removed_pool_txids
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finish(self) -> error::Result<PoolInfo> {
|
||||||
|
// INVARIANT:
|
||||||
|
// `monerod` omits serializing the field itself when a container is empty,
|
||||||
|
// `unwrap_or_default()` is used over `error()` in these cases.
|
||||||
|
// Some of the uses are when values have default fallbacks: `pool_info_extent`.
|
||||||
|
|
||||||
|
let pool_info_extent = self.pool_info_extent.unwrap_or_default();
|
||||||
|
let this = match pool_info_extent {
|
||||||
|
PoolInfoExtent::None => PoolInfo::None,
|
||||||
|
PoolInfoExtent::Incremental => PoolInfo::Incremental(PoolInfoIncremental {
|
||||||
|
added_pool_txs: self.added_pool_txs.unwrap_or_default(),
|
||||||
|
remaining_added_pool_txids: self.remaining_added_pool_txids.unwrap_or_default(),
|
||||||
|
removed_pool_txids: self.removed_pool_txids.unwrap_or_default(),
|
||||||
|
}),
|
||||||
|
PoolInfoExtent::Full => PoolInfo::Full(PoolInfoFull {
|
||||||
|
added_pool_txs: self.added_pool_txs.unwrap_or_default(),
|
||||||
|
remaining_added_pool_txids: self.remaining_added_pool_txids.unwrap_or_default(),
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "epee")]
|
||||||
|
impl EpeeObject for PoolInfo {
|
||||||
|
type Builder = __PoolInfoEpeeBuilder;
|
||||||
|
|
||||||
|
fn number_of_fields(&self) -> u64 {
|
||||||
|
// Inner struct fields.
|
||||||
|
let inner_fields = match self {
|
||||||
|
Self::None => 0,
|
||||||
|
Self::Incremental(s) => s.number_of_fields(),
|
||||||
|
Self::Full(s) => s.number_of_fields(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// [`PoolInfoExtent`] + inner struct fields
|
||||||
|
1 + inner_fields
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_fields<B: BufMut>(self, w: &mut B) -> error::Result<()> {
|
||||||
|
const FIELD: &str = "pool_info_extent";
|
||||||
|
|
||||||
|
match self {
|
||||||
|
Self::None => {
|
||||||
|
write_field(PoolInfoExtent::None.to_u8(), FIELD, w)?;
|
||||||
|
}
|
||||||
|
Self::Incremental(s) => {
|
||||||
|
s.write_fields(w)?;
|
||||||
|
write_field(PoolInfoExtent::Incremental.to_u8(), FIELD, w)?;
|
||||||
|
}
|
||||||
|
Self::Full(s) => {
|
||||||
|
s.write_fields(w)?;
|
||||||
|
write_field(PoolInfoExtent::Full.to_u8(), FIELD, w)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,8 +2,6 @@
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------- Use
|
//---------------------------------------------------------------------------------------------------- Use
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
use crate::serde::{serde_false, serde_true};
|
|
||||||
#[cfg(feature = "serde")]
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[cfg(feature = "epee")]
|
#[cfg(feature = "epee")]
|
||||||
|
@ -13,6 +11,9 @@ use cuprate_epee_encoding::{
|
||||||
EpeeObject, EpeeObjectBuilder,
|
EpeeObject, EpeeObjectBuilder,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
|
use crate::serde::{serde_false, serde_true};
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------- TxEntry
|
//---------------------------------------------------------------------------------------------------- TxEntry
|
||||||
#[doc = crate::macros::monero_definition_link!(
|
#[doc = crate::macros::monero_definition_link!(
|
||||||
cc73fe71162d564ffda8e549b79a350bca53c454,
|
cc73fe71162d564ffda8e549b79a350bca53c454,
|
||||||
|
|
Loading…
Reference in a new issue