bench: add readblock benchmark #26684

pull andrewtoth wants to merge 1 commits into bitcoin:master from andrewtoth:bench-readblock changing 2 files +54 −0
  1. andrewtoth commented at 2:22 am on December 11, 2022: contributor

    Requested in #13151 (comment). See #26415 and #21319.

    Benchmarking shows a >50x increase in speed on both nvme and spinning disk.

    Benchmark results:

    ns/op op/s err% ins/op cyc/op IPC bra/op miss% total benchmark
    5,377,375.00 185.96 0.2% 60,125,513.00 11,633,676.00 5.168 3,588,800.00 0.4% 0.09 ReadBlockFromDiskTest
    ns/op op/s err% ins/op cyc/op IPC bra/op miss% total benchmark
    89,945.58 11,117.83 0.7% 12,743.90 64,530.33 0.197 2,595.20 0.2% 0.01 ReadRawBlockFromDiskTest
  2. DrahtBot commented at 2:22 am on December 11, 2022: contributor

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    Code Coverage

    For detailed information about the code coverage, see the test coverage report.

    Reviews

    See the guideline for information on the review process.

    Type Reviewers
    ACK maflcko, TheCharlatan, achow101
    Concept ACK kevkevinpal, josibake

    If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

    Conflicts

    No conflicts as of last run.

  3. DrahtBot added the label Tests on Dec 11, 2022
  4. andrewtoth force-pushed on Dec 11, 2022
  5. andrewtoth force-pushed on Dec 11, 2022
  6. andrewtoth force-pushed on Dec 11, 2022
  7. in src/bench/readblock.cpp:24 in 592f8016d4 outdated
    19+
    20+static void SetupReadBlockTest()
    21+{
    22+    // Create params and set blocksdir to /tmp folder
    23+    SelectParams(CBaseChainParams::MAIN);
    24+    gArgs.ForceSetArg("-blocksdir", "/tmp");
    


    kristapsk commented at 5:24 pm on December 11, 2022:
    I’m wondering can’t we do something smarter here to make it work also on Windows?

    andrewtoth commented at 6:13 pm on December 11, 2022:
    Good suggestion. Updated to use fs::temp_directory_path().
  8. andrewtoth force-pushed on Dec 11, 2022
  9. andrewtoth force-pushed on Dec 11, 2022
  10. in src/bench/readblock.cpp:24 in 2142fc9b2a outdated
    19+
    20+static void SetupReadBlockTest()
    21+{
    22+    // Create params and set blocksdir to temporary folder (/tmp usually on linux)
    23+    SelectParams(CBaseChainParams::MAIN);
    24+    gArgs.ForceSetArg("-blocksdir", fs::temp_directory_path().string());
    


    maflcko commented at 10:49 am on December 12, 2022:
    Why can’t you use the test setup m_path_root? Using a hardcoded constant is going to cause crashes if the test is run in parallel or the dir is dirty otherwise.

    andrewtoth commented at 2:02 am on December 13, 2022:
    Done, uses test setup now.
  11. in src/bench/readblock.cpp:27 in 2142fc9b2a outdated
    22+    // Create params and set blocksdir to temporary folder (/tmp usually on linux)
    23+    SelectParams(CBaseChainParams::MAIN);
    24+    gArgs.ForceSetArg("-blocksdir", fs::temp_directory_path().string());
    25+
    26+    // Serialize block
    27+    CDataStream stream(benchmark::data::block413567, SER_NETWORK, PROTOCOL_VERSION);
    


    maflcko commented at 10:50 am on December 12, 2022:
    0    CDataStream stream{benchmark::data::block413567, SER_NETWORK, PROTOCOL_VERSION};
    

    nit (for new code)

  12. in src/bench/readblock.cpp:32 in 2142fc9b2a outdated
    27+    CDataStream stream(benchmark::data::block413567, SER_NETWORK, PROTOCOL_VERSION);
    28+    CBlock block;
    29+    stream >> block;
    30+
    31+    // Write block at first position in <temp_directory>/blocks/blk00000.dat
    32+    CAutoFile fileout(OpenBlockFile(FlatFilePos(0, 0)), SER_DISK, CLIENT_VERSION);
    


    maflcko commented at 10:50 am on December 12, 2022:
    0    CAutoFile fileout{OpenBlockFile(FlatFilePos{0, 0}), SER_DISK, CLIENT_VERSION};
    

    nit

  13. in src/bench/readblock.cpp:31 in 2142fc9b2a outdated
    30+
    31+    // Write block at first position in <temp_directory>/blocks/blk00000.dat
    32+    CAutoFile fileout(OpenBlockFile(FlatFilePos(0, 0)), SER_DISK, CLIENT_VERSION);
    33+    assert(!fileout.IsNull());
    34+    const size_t block_size{GetSerializeSize(block, fileout.GetVersion())};
    35+    fileout << Params().MessageStart() << (uint32_t) block_size << block;
    


    maflcko commented at 10:50 am on December 12, 2022:
    0    fileout << Params().MessageStart() << uint32_t{block_size} << block;
    

    andrewtoth commented at 2:01 am on December 13, 2022:
    This gives a warning about narrowing conversion.
  14. maflcko commented at 10:52 am on December 12, 2022: member
    (feel free to ignore the nits)
  15. andrewtoth force-pushed on Dec 13, 2022
  16. in src/bench/readblock.cpp:21 in 493df1a40b outdated
    16+using node::BLOCK_SERIALIZATION_HEADER_SIZE;
    17+using node::OpenBlockFile;
    18+using node::ReadBlockFromDisk;
    19+using node::ReadRawBlockFromDisk;
    20+
    21+static void WriteBlockToDisk()
    


    stickies-v commented at 3:20 pm on December 14, 2022:

    It seems we’re doing the same thing here already: https://github.com/bitcoin/bitcoin/blob/678889e6c6231cf461de59eefe6fb8eb07468848/src/bench/load_external.cpp#L27-L49.

    Maybe I’m missing some nuance, but can we avoid reimplementing this?


    andrewtoth commented at 4:19 pm on December 14, 2022:
    It’s a little different. Here we are using the OpenBlockFile and FlatFilePos abstractions so that it will work with ReadBlockFromDisk and ReadRawBlockFromDisk. If these are internally changed then this benchmark will still work (in theory). In load_external it’s writing to an arbitrary file that’s passed into LoadExternalBlockFile which doesn’t use these abstractions internally. It’s also filling up the file with repeated blocks, whereas here we only write one.

    andrewtoth commented at 4:27 pm on December 14, 2022:

    It’s actually reimplimenting https://github.com/bitcoin/bitcoin/blob/master/src/node/blockstorage.cpp#L670-L691

    However, it’s private in blockstorage.cpp, but might be worth refactoring it to expose it for this benchmark?


    andrewtoth commented at 5:53 pm on December 14, 2022:
    Updated to use BlockManager::SaveBlockToDisk.
  17. andrewtoth force-pushed on Dec 14, 2022
  18. andrewtoth force-pushed on Dec 14, 2022
  19. andrewtoth force-pushed on Dec 14, 2022
  20. kevkevinpal commented at 1:07 am on December 23, 2022: contributor

    Tested ACK and got these results (compiled with –enable-debug)

    Specs:

    mac book pro 2019 2.3 GHz 8-Core Intel Core i9 16 GB 2667 MHz DDR4 AMD Radeon Pro 5500M 4 GB

    ➜ bitcoin git:(PR26684) ✗ ./src/bench/bench_bitcoin -filter=ReadBlockFromDiskTest

    0Warning, results might be unstable:
    1* DEBUG defined
    2
    3Recommendations
    4* Make sure you compile for Release
    5
    6|               ns/op |                op/s |    err% |     total | benchmark
    7|--------------------:|--------------------:|--------:|----------:|:----------
    8|       21,699,865.00 |               46.08 |    1.8% |      0.24 | `ReadBlockFromDiskTest`
    

    ➜ bitcoin git:(PR26684) ✗ ./src/bench/bench_bitcoin -filter=ReadRawBlockFromDiskTest

    0Warning, results might be unstable:
    1* DEBUG defined
    2
    3Recommendations
    4* Make sure you compile for Release
    5
    6|               ns/op |                op/s |    err% |     total | benchmark
    7|--------------------:|--------------------:|--------:|----------:|:----------
    8|           87,262.00 |           11,459.74 |    5.1% |      0.01 | :wavy_dash: `ReadRawBlockFromDiskTest` (Unstable with ~1.0 iters. Increase `minEpochIterations` to e.g. 10)
    
  21. achow101 requested review from theStack on Apr 25, 2023
  22. achow101 requested review from josibake on Apr 25, 2023
  23. josibake commented at 10:05 am on May 3, 2023: member

    Concept ACK

    Based on the linked PRs, seems like having this benchmark is useful. There’s also been some discussion about XOR’ing block data and having a benchmark for reading blocks would definitely be good to have before jumping into that.

    I would, however, suggest holding off on merging this right now given that it conflicts with BIP324 PRs and is more of a nice to have vs something urgently needed.

  24. DrahtBot added the label CI failed on May 11, 2023
  25. andrewtoth force-pushed on Aug 2, 2023
  26. DrahtBot removed the label CI failed on Aug 3, 2023
  27. andrewtoth force-pushed on Aug 7, 2023
  28. in src/bench/readblock.cpp:32 in 7fba1fba9a outdated
    27+
    28+    CBlock block;
    29+    const auto pos{WriteBlockToDisk(chainman)};
    30+
    31+    bench.run([&] {
    32+        assert(chainman.m_blockman.ReadBlockFromDisk(block, pos));
    


    theStack commented at 4:42 pm on August 7, 2023:

    as per developer notes, assertions shouldn’t have side-effects, so the following would be preferred:

    0        bool success{chainman.m_blockman.ReadBlockFromDisk(block, pos)};
    1        assert(success);
    

    (same for the second test below)


    maflcko commented at 6:21 am on August 8, 2023:
    (Personally, I think this is a style nit and either version is fine here that compiles and has CI pass. Going forward, we should either remove the section from the docs (my preference), or enforce it with clang-tidy or something else in CI)

    theStack commented at 9:51 am on August 8, 2023:
    Agree that my suggestion is non-blocking, this is obviously much less critical for benchmarks and tests as opposed to production code. Having it enforced on the CI would be very nice indeed (I might look into how well this works with clang-tidy and if it’d also catch our own assertion-variants), I personally wouldn’t remove the section from the docs though.

    maflcko commented at 9:54 am on August 8, 2023:

    if it’d also catch our own assertion-variants)

    They are required to have side-effects, as they must return the value that was passed in. So checking them is not possible and it seems better to consistently check nothing than to special case one function.


    theStack commented at 4:21 pm on August 8, 2023:

    Okay, that makes sense. My blind guess was that clang-tidy (or any other similar tool) would only look at the passed expression and not care about the effect of the assert as a whole. Seems like even the passed expression is not side-effect free at several places in the code, e.g. https://github.com/bitcoin/bitcoin/blob/b565485c24c0feacae559a7f6f7b83d7516ca58d/src/init.cpp#L1428

    so it indeed might be better to remove recommendations that we don’t even follow ourselves.

    (Also, I sadly can’t even get clang-tidy to yield anything useful for regular asserts).


    andrewtoth commented at 6:24 pm on November 26, 2023:
    Done
  29. maflcko approved
  30. maflcko commented at 6:43 am on August 8, 2023: member

    lgtm ACK. I think one issue could be that the bench (like for all tests) datadir is on a tmpfs and not the normal storage that blocks are stored on, so the bench is skewed toward highlighting code performance more than it matters, because block storage is generally slower (than tmpfs in memory) and the limiting factor.

    Maybe a hint or comment on how to pick the datadir for this test can be added?

    Edit, not sure if the benchmarks parse args like bench_bitcoin ... -- -datadir=$HOME/temp, but TMPDIR=$HOME/tmp/ may also work, see https://en.cppreference.com/w/cpp/filesystem/temp_directory_path. See also https://github.com/bitcoin/bitcoin/pull/26564

  31. in src/bench/readblock.cpp:15 in 7fba1fba9a outdated
    10+#include <streams.h>
    11+#include <test/util/setup_common.h>
    12+#include <util/chaintype.h>
    13+#include <validation.h>
    14+
    15+static FlatFilePos WriteBlockToDisk(ChainstateManager& chainman) {
    


    maflcko commented at 6:43 am on August 8, 2023:
    style-nit: Forgot to run clang-format on new code?
  32. fanquake referenced this in commit 4e78834ec1 on Oct 3, 2023
  33. Frank-GER referenced this in commit 87e1b7ee41 on Oct 13, 2023
  34. DrahtBot added the label CI failed on Nov 18, 2023
  35. in src/bench/readblock.cpp:16 in 7fba1fba9a outdated
    11+#include <test/util/setup_common.h>
    12+#include <util/chaintype.h>
    13+#include <validation.h>
    14+
    15+static FlatFilePos WriteBlockToDisk(ChainstateManager& chainman) {
    16+    CDataStream stream{benchmark::data::block413567, SER_NETWORK, PROTOCOL_VERSION};
    


    maflcko commented at 11:42 am on November 19, 2023:
    0    DataStream stream{benchmark::data::block413567};
    

    (see compile failure)


    andrewtoth commented at 6:24 pm on November 26, 2023:
    Done
  36. andrewtoth force-pushed on Nov 26, 2023
  37. bench: add readblock benchmark 1c4b9cbe90
  38. andrewtoth force-pushed on Nov 26, 2023
  39. DrahtBot removed the label CI failed on Nov 26, 2023
  40. maflcko commented at 11:56 am on November 27, 2023: member
    lgtm ACK 1c4b9cbe906507295d8b7d52855de1441ad411dd
  41. in src/bench/readblock.cpp:13 in 1c4b9cbe90
     8+#include <consensus/validation.h>
     9+#include <node/blockstorage.h>
    10+#include <streams.h>
    11+#include <test/util/setup_common.h>
    12+#include <util/chaintype.h>
    13+#include <validation.h>
    


    TheCharlatan commented at 9:47 pm on December 20, 2023:
    NIt: Could make this IWYU correct (see the logs from the tidy CI job).
  42. in src/bench/readblock.cpp:27 in 1c4b9cbe90
    22+}
    23+
    24+static void ReadBlockFromDiskTest(benchmark::Bench& bench)
    25+{
    26+    const auto testing_setup{MakeNoLogFileContext<const TestingSetup>(ChainType::MAIN)};
    27+    ChainstateManager& chainman{*testing_setup->m_node.chainman};
    


    TheCharlatan commented at 9:49 pm on December 20, 2023:
    Nit: This could be BlockManager& already.
  43. TheCharlatan approved
  44. TheCharlatan commented at 9:50 pm on December 20, 2023: contributor
    ACK 1c4b9cbe906507295d8b7d52855de1441ad411dd
  45. achow101 commented at 4:06 pm on January 2, 2024: member
    ACK 1c4b9cbe906507295d8b7d52855de1441ad411dd
  46. achow101 merged this on Jan 2, 2024
  47. achow101 closed this on Jan 2, 2024

  48. andrewtoth deleted the branch on Jan 2, 2024

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2024-12-22 09:12 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me