Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf: don't use boost time in validation.cpp #5616

Merged
merged 3 commits into from
Oct 19, 2023

Conversation

PastaPastaPasta
Copy link
Member

(over a 13 minute segment of reindex) boost time took about 9+9+9 = 27%!! of total cycles!!!

During the same time segment, GetTimeMicros() used roughly 0.2% of total cycles! (even though it's used a lot more)

Over my entire roughly 40 minute profiling session, boost time appears to use about 6% of cycles; still too much, while GetTimeMicros used about 0.4%

image
image

Checklist:

Go over all the following points, and put an x in all the boxes that apply.

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated relevant unit/integration/functional/e2e tests
  • I have made corresponding changes to the documentation
  • I have assigned this pull request to a milestone (for repository code-owners and collaborators only)

@PastaPastaPasta PastaPastaPasta added this to the 20 milestone Oct 16, 2023
src/validation.cpp Outdated Show resolved Hide resolved
src/validation.cpp Outdated Show resolved Hide resolved
src/validation.cpp Outdated Show resolved Hide resolved
@@ -944,7 +942,7 @@ bool MemPoolAccept::Finalize(ATMPArgs& args, Workspace& ws)

bool MemPoolAccept::AcceptSingleTransaction(const CTransactionRef& ptx, ATMPArgs& args)
{
boost::posix_time::ptime start = boost::posix_time::microsec_clock::local_time();
auto start = GetTimeMicros();
Copy link
Collaborator

@knst knst Oct 16, 2023

Choose a reason for hiding this comment

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

imo better to switch just to std::chrono::microseconds rather than int64_t counter.

Helper GetTimeMicro has been introduced back in 2014 year:

+int64_t GetTimeMicros()
+{
+    return (boost::posix_time::ptime(boost::posix_time::microsec_clock::universal_time()) -
+            boost::posix_time::ptime(boost::gregorian::date(1970,1,1))).total_microseconds();
+}

But now wrapper over std::chrono is useful only for the old already written code; it has std::chrono inside since this commit a3bc3fd

int64_t GetTimeMicros()
 {
-    int64_t now = (boost::posix_time::microsec_clock::universal_time() -
-                   boost::posix_time::ptime(boost::gregorian::date(1970,1,1))).total_microseconds();
+    int64_t now = std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::system_clock::now()).time_since_epoch().count();
     assert(now > 0);
     return now;
 }

Let's use std::chrono directly instead wrappers.

Btw, conceptually ACK, bitcoin switched from posix time to std::chrono long time ago, for example this PR: https://github.com/bitcoin/bitcoin/pull/18234/files

Suggested change
auto start = GetTimeMicros();
auto start = std::chrono::system_clock::now()

(over a 13 minute segment of reindex) boost time took about 9+9+9 = 27%!! of total cycles!!!

During the same time segment, GetTimeMicros() used roughly 0.2% of total cycles! (even though it's used a lot more)

Over my entire roughly 40 minute profiling session, boost time appears to use about 6% of cycles; still too much, while GetTimeMicros used about 0.4%

(now using std::chrono directly)
@PastaPastaPasta
Copy link
Member Author

Updated to std::chrono directly; should be (very marginally) faster also as we avoid an assert here now inside of GetTimeMicros()

@UdjinM6
Copy link

UdjinM6 commented Oct 17, 2023

CI fails

Copy link
Collaborator

@knst knst left a comment

Choose a reason for hiding this comment

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

several nits

@@ -1498,7 +1496,7 @@ void InitScriptExecutionCache() {
*/
bool CheckInputScripts(const CTransaction& tx, TxValidationState &state, const CCoinsViewCache &inputs, unsigned int flags, bool cacheSigStore, bool cacheFullScriptStore, PrecomputedTransactionData& txdata, std::vector<CScriptCheck> *pvChecks) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
boost::posix_time::ptime start = boost::posix_time::microsec_clock::local_time();
auto start = std::chrono::system_clock::now();
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: maybe const here (and similar places)?

Suggested change
auto start = std::chrono::system_clock::now();
const auto start = std::chrono::system_clock::now();

statsClient.timing("CheckInputScripts_ms", diff.total_milliseconds(), 1.0f);
auto finish = std::chrono::system_clock::now();
auto diff = finish - start;
statsClient.timing("CheckInputScripts_ms", count_microseconds(diff), 1.0f);
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: doesn't seems as finish is used anywhere else

-    auto finish = std::chrono::system_clock::now();
-    auto diff = finish - start;
+    const auto diff = std::chrono::system_clock::now() - start;
     statsClient.timing("CheckInputScripts_ms", count_microseconds(diff), 1.0f);

statsClient.timing("CheckInputScripts_ms", diff.total_milliseconds(), 1.0f);
auto finish = std::chrono::system_clock::now();
auto diff = finish - start;
statsClient.timing("CheckInputScripts_ms", count_microseconds(diff), 1.0f);
Copy link
Collaborator

@knst knst Oct 17, 2023

Choose a reason for hiding this comment

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

Suggested change
statsClient.timing("CheckInputScripts_ms", count_microseconds(diff), 1.0f);
statsClient.timing("CheckInputScripts_µs", count_microseconds(diff), 1.0f);

or

Suggested change
statsClient.timing("CheckInputScripts_ms", count_microseconds(diff), 1.0f);
statsClient.timing("CheckInputScripts_us", count_microseconds(diff), 1.0f);

UPD: should be miliseconds

validation.cpp: In member function ‘bool CChainState::ActivateBestChain(BlockValidationState&, std::shared_ptr<const CBlock>)’:
validation.cpp:3203:67: error: could not convert ‘diff’ from ‘duration<[...],ratio<[...],1000000000>>’ to ‘duration<[...],ratio<[...],1000000>>’
 3203 |     statsClient.timing("ActivateBestChain_ms", count_microseconds(diff), 1.0f);

statsClient.timing("ActivateBestChain_ms", diff.total_milliseconds(), 1.0f);
auto finish = std::chrono::system_clock::now();
auto diff = finish - start;
statsClient.timing("ActivateBestChain_ms", count_microseconds(diff), 1.0f);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
statsClient.timing("ActivateBestChain_ms", count_microseconds(diff), 1.0f);
statsClient.timing("ActivateBestChain_us", count_microseconds(diff), 1.0f);

Copy link
Collaborator

@knst knst left a comment

Choose a reason for hiding this comment

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

(CI)

statsClient.timing("AcceptToMemoryPool_ms", diff.total_milliseconds(), 1.0f);
auto finish = std::chrono::system_clock::now();
auto diff = finish - start;
statsClient.timing("AcceptToMemoryPool_us", count_microseconds(diff), 1.0f);
Copy link

Choose a reason for hiding this comment

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

hmm... I think this is going to break stats on already running instances (if there any). Should keep string the same and use count_milliseconds instead imo. (same for similar changes below)

Copy link
Member Author

Choose a reason for hiding this comment

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

If I change it to count_milliseconds it doesn't compile; I'd probably need to duration_cast it to milliseconds or something like that. Do you think would be good?

Copy link

Choose a reason for hiding this comment

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

We could do it like 4b57881 maybe?

Class std::chrono::steady_clock represents a monotonic clock. The time points of this clock cannot decrease as physical time moves forward and the time between ticks of this clock is constant. This clock is not related to wall clock time (for example, it can be time since last reboot), and is most suitable for measuring intervals.

https://en.cppreference.com/w/cpp/chrono/steady_clock

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, that seems pretty reasonable to me

Copy link

@UdjinM6 UdjinM6 left a comment

Choose a reason for hiding this comment

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

utACK

@PastaPastaPasta PastaPastaPasta requested a review from knst October 19, 2023 14:32
Copy link
Collaborator

@knst knst left a comment

Choose a reason for hiding this comment

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

utACK

@PastaPastaPasta PastaPastaPasta merged commit 59d6442 into dashpay:develop Oct 19, 2023
8 checks passed
PastaPastaPasta pushed a commit that referenced this pull request Oct 23, 2023
## Issue being fixed or feature implemented
We went from milliseconds to microseconds for these silently in #5616 🙈 

## What was done?
make it milliseconds again

## How Has This Been Tested?
n/a

## Breaking Changes
n/a

## Checklist:
- [x] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have added or updated relevant unit/integration/functional/e2e
tests
- [ ] I have made corresponding changes to the documentation
- [x] I have assigned this pull request to a milestone _(for repository
code-owners and collaborators only)_
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants