Skip to content

Conversation

EthanHeilman
Copy link
Contributor

@EthanHeilman EthanHeilman commented Oct 5, 2020

As shown below when resizing the read buffer vData std::max((vData.size() * 3) / 2, nMaxSize) is used. This means that the buffer size immediately jumps to nMaxSize. I believe the intend of this code is to grow the buffer size through several steps rather than immediately resize it to the max size.

    std::vector<unsigned char> vData(250000, 0);
    long ret = 0;
    unsigned long nSize = 0;
    const size_t nMaxSize = 10000000; // Bail out at more than 10MB of performance data
    while (true) {
        nSize = vData.size();
        ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", nullptr, nullptr, vData.data(), &nSize);
        if (ret != ERROR_MORE_DATA || vData.size() >= nMaxSize)
            break;
        vData.resize(std::max((vData.size() * 3) / 2, nMaxSize)); // Grow size of buffer exponentially
    }

vData always starts at size 250,000 and nMaxSize is always 10,000,000 so the first time this line is reached:

vData.resize(std::max((vData.size() * 3) / 2, nMaxSize));

the effect will always be to resize vData to nMaxSize. Then because the loop terminates when vData.size >= 10,000,000 only one resize operation will take place.

To fix this issue we replace std::min with std::max

This PR also adds a comment clarifying the behavior of this function the first time it is called.

@EthanHeilman EthanHeilman force-pushed the perfmon branch 3 times, most recently from 7961f93 to faba3ee Compare October 6, 2020 00:59
@EthanHeilman EthanHeilman changed the title refactor: Minor refactor of RandAddSeedPerfmon + comments [WIP] refactor: Minor refactor of RandAddSeedPerfmon + comments Oct 6, 2020
+ Replaces std::max with std::min to resize buffer in RandAddSeedPerfmon
+ Documents behavior of RandAddSeedPerfmon
@EthanHeilman EthanHeilman changed the title [WIP] refactor: Minor refactor of RandAddSeedPerfmon + comments [bugfix] random: fixes read buffer to use min rather than max Oct 8, 2020
@practicalswift
Copy link
Contributor

Concept ACK: nice find!

@laanwj As the author of 8ae973c would you mind reviewing to make sure that the logic @EthanHeilman suggests corresponds to what was originally intended? :)

Copy link
Contributor

@theStack theStack left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Concept ACK
Looking at the code, it seems pretty obvious that jumping immediately from 250k to 10M is not desired -- changing std::max to std::min leads to the intended behaviour.

Copy link
Member

@fanquake fanquake left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK bd52151 - thanks for taking a look at this Ethan. Swapping from std::max to std::min here certainly seems correct.

@fanquake fanquake merged commit 62af467 into bitcoin:master Oct 19, 2020
@EthanHeilman EthanHeilman deleted the perfmon branch October 19, 2020 13:46
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Oct 19, 2020
…ther than max

bd52151 random: fixes read buffer resizing in RandAddSeedPerfmon (Ethan Heilman)

Pull request description:

  As shown below when resizing the read buffer `vData` `std::max((vData.size() * 3) / 2, nMaxSize)` is used. This means that the buffer size immediately jumps to `nMaxSize`. I believe the intend of this code is to grow the buffer size through several steps rather than immediately resize it to the max size.

  ```cpp
      std::vector<unsigned char> vData(250000, 0);
      long ret = 0;
      unsigned long nSize = 0;
      const size_t nMaxSize = 10000000; // Bail out at more than 10MB of performance data
      while (true) {
          nSize = vData.size();
          ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", nullptr, nullptr, vData.data(), &nSize);
          if (ret != ERROR_MORE_DATA || vData.size() >= nMaxSize)
              break;
          vData.resize(std::max((vData.size() * 3) / 2, nMaxSize)); // Grow size of buffer exponentially
      }
  ```

  vData always starts at size 250,000 and nMaxSize is always 10,000,000 so the first time this line is reached:
  ```cpp
  vData.resize(std::max((vData.size() * 3) / 2, nMaxSize));
  ```
  the effect will always be to resize vData to nMaxSize. Then because the loop terminates when vData.size >= 10,000,000 only one resize operation will take place.

  To fix this issue we replace `std::min` with `std::max`

  This PR also adds a comment clarifying the behavior of this function the first time it is called.

ACKs for top commit:
  fanquake:
    ACK bd52151 - thanks for taking a look at this Ethan. Swapping from `std::max` to `std::min` here certainly seems correct.

Tree-SHA512: 7c65f700e5bbe44bc2f1ffdcdc99ec19c542894c95b5ee9791facd09d02afae88d1f8f35af129719e4860db94bc790856e7adb1d218a395381e7c2913b95f1d0
fanquake pushed a commit to fanquake/bitcoin that referenced this pull request Oct 23, 2020
+ Replaces std::max with std::min to resize buffer in RandAddSeedPerfmon
+ Documents behavior of RandAddSeedPerfmon

Github-Pull: bitcoin#20082
Rebased-From: bd52151
@fanquake
Copy link
Member

Added this for backport to 0.20 in #20166.

@fanquake fanquake mentioned this pull request Oct 23, 2020
maflcko pushed a commit that referenced this pull request Nov 18, 2020
7566af4 doc: Update data directory path comments (Hennadii Stepanov)
09261de util: Add StripRedundantLastElementsOfPath function (Hennadii Stepanov)
8ef0dac macOS deploy: use the new plistlib API (Jonas Schnelli)
314e795 build: fix mutex detection when building bdb on macOS (fanquake)
1f67a30 random: fixes read buffer resizing in RandAddSeedPerfmon (Ethan Heilman)
6113b54 net: Send post-verack handshake messages at most once (MarcoFalke)
bdf15d0 rpc: Adjust witness-tx deserialize error message (MarcoFalke)
731502a rpc: Properly deserialize txs with witness before signing (MarcoFalke)
ee0082b Avoid the use of abs64 in timedata (Pieter Wuille)
05bd0c2 docs: Correct description for getblockstats's txs field (Nadav Ivgi)

Pull request description:

  Backports the following PRs to the 0.20 branch:
  * #19777 - docs: Correct description for getblockstats's txs field
  * #19836 - rpc: Properly deserialize txs with witness before signing
  * #20080 - Strip any trailing `/` in -datadir and -blocksdir paths
  * #20082 - [bugfix] random: fixes read buffer to use min rather than max
  * #20141 - Avoid the use of abs64 in timedata
  * #20146 - net: Send post-verack handshake messages at most once
  * #20195 - build: fix mutex detection when building bdb on macOS
  * #20298 - macOS deploy: use the new plistlib API

  Will add additional commits as they become available.

ACKs for top commit:
  MarcoFalke:
    review ACK 7566af4 🗡

Tree-SHA512: add6bb978313c12c3e07bc232636ae9d1ab0edd0b816705c5c70eeb1cc04097165fd5e29d60c706886943ceb1f749a422020766b4aa2d23be51e9f839157a4bb
Fabcien pushed a commit to Bitcoin-ABC/bitcoin-abc that referenced this pull request Nov 25, 2021
Summary:
+ Replaces std::max with std::min to resize buffer in RandAddSeedPerfmon
+ Documents behavior of RandAddSeedPerfmon
This is a backport of [[bitcoin/bitcoin#20082 | core#20082]]

Test Plan: `ninja all check-all`

Reviewers: #bitcoin_abc, Fabien

Reviewed By: #bitcoin_abc, Fabien

Differential Revision: https://reviews.bitcoinabc.org/D10539
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Feb 15, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants