[Minor Performance Fix] - Reserve vectors, to save reallocation costs. #15182

pull shahzadlone wants to merge 1 commits into bitcoin:master from shahzadlone:master changing 1 files +2 −0
  1. shahzadlone commented at 5:15 PM on January 16, 2019: none

    File: [bitcoin/src/interfaces/node.cpp] Function: [listWalletDir()] Function: [getWallets()]

    Reserving vectors where we already know the size to save on reallocation costs.

  2. [Improve Performance] - Reserve vectors, to save reallocation costs.
    File: [bitcoin/src/interfaces/node.cpp]
    Function: [listWalletDir()]
    Function: [getWallets()]
    
    Reserving vectors where we already know the size to save on reallocation costs.
    338098ba31
  3. MarcoFalke commented at 5:17 PM on January 16, 2019: member

    Do you have any benchmarks that show this is actually faster?

  4. laanwj commented at 5:37 PM on January 16, 2019: member

    Do you have any benchmarks that show this is actually faster?

    I wouldn't expect much performance gain, these are small vectors. I think reserving is mostly a gain when there's a large number of pushes.

    How did you come to optimizing these specific functions? Did they show up in a profiling result?

  5. promag commented at 5:39 PM on January 16, 2019: member

    This code isn't performance critical. IMO simple code is preferred.

  6. shahzadlone commented at 5:40 PM on January 16, 2019: none

    As long as size is bigger than 1, it is mostly useful(which is most likely the case). For example:

    ******************[Incase of NO-reserve]******************: size = 1; initial cap = 1. No Re-Allocations needed. Total Cost: 0 Re-Allocation

    size = 2; initial cap = 1. so needs 1 Re-Allocation, in this case so becomes (prev_cap * 2): size = 2; initial cap = 2. Total Cost: 1 Re-Allocation

    size = 3; initial cap = 1. needs to Re-Allocate in this case so becomes (prev_cap * 2): size = 3; initial cap = 2. needs 1 more Re-Allocation so becomes (prev_cap * 2): size = 3; initial cap = 4. Total Cost: 2 Re-Allocations

    size = 10; initial cap = 1. needs Re-Allocation, so becomes (prev_cap * 2): size = 10; initial cap = 2. needs more Re-Allocation so becomes (prev_cap * 2): size = 10; initial cap = 4. needs more Re-Alocation so becomes (prev_cap * 2): size = 10; initial cap = 8. needs more Re-Alocation so becomes (prev_cap * 2): size = 10; initial cap = 16. Total Cost: 4 Re-Allocations

    ******************[Incase of Reserve]******************: size = 1; initial cap = 1. Reserves once for cap = 1, so no reallocation needed upto size = 1. Total Cost: 1 Re-Allocation

    size = 2; initial cap = 2. Reserves once for cap = 2, so no reallocation needed upto size = 2. Total Cost: 1 Re-Allocation

    size = 3; initial cap = 3 (or up to 4, compiler specifc). Reserved once for upto(atleast) cap = 3, so no reallocation needed upto size = 3. Total Cost: 1 Re-Allocations

    size = 10; initial cap = 10 (or up to 16, compiler specifc). Reserved once for upto(atleast) cap = 10, so no reallocation needed upto size = 10. Total Cost: 1 Re-Allocations

    In-addition to memory-allocation-cost there are more over-heads for each re-allocation like these things for example:

    Makes a new vector of double size each time. (creation time spent).
    Copies each element of the old vector in the new (bigger) sized one. (expensive).
    Then destroys the old one.

    Moreover, this also guarantees that the iterator will remain valid, because early throw/error incase not enough memory for the task. This can potentially save data corruptions.

    Which can all be avoided in this case as we know the size before.

    This is pretty standard practice, infact in this file alone I see this applied in function[getNodesStats(NodesStats& stats)] line 98:

               stats.reserve(stats_temp.size());
                for (auto& node_stats_temp : stats_temp) {
                    stats.emplace_back(std::move(node_stats_temp), false, CNodeStateStats());
                 }
    
  7. shahzadlone commented at 5:42 PM on January 16, 2019: none

    Agreed it's not critically important, but it is better code practice to reserve if you know the size.

  8. promag commented at 5:45 PM on January 16, 2019: member

    Current code is worst since it calls each function twice.

  9. laanwj commented at 6:35 PM on January 16, 2019: member

    Sorry, I'm going to close this, there is no agreement to make this change.

  10. laanwj closed this on Jan 16, 2019

  11. DrahtBot locked this on Dec 16, 2021

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: 2026-05-03 00:15 UTC

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