-
Notifications
You must be signed in to change notification settings - Fork 38.6k
tests: add utility to easily profile node performance with perf #14519
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
Conversation
629de1e to
b93a17c
Compare
|
An example of running the generated perf data file through hotspot: |
ryanofsky
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
utACK b93a17c3153f050eb37292b51463b0aaa5860f1a. Context manager seems nice for writing new tests. This is just an idea, but maybe it would be useful if there were an option to collect perf data for all nodes from start to stop to gain insight into performance of existing tests.
d80a092 to
ed471df
Compare
|
Thanks for the review, @ryanofsky. I really like your suggestions and so I've incorporated them all into a rebase. You can now pass $ ./test/functional/p2p_unrequested_blocks.py --perf
2018-10-19T20:36:06.542000Z TestFramework (INFO): Initializing test directory /tmp/test71_cfvsc
...
2018-10-19T20:36:09.206000Z TestFramework (INFO): Stopping nodes
2018-10-19T20:36:09.384000Z TestFramework.node0 (INFO): Wrote perf output to '/tmp/test71_cfvsc/node0/node-0-AcceptBlockTest.perf.data'
2018-10-19T20:36:09.558000Z TestFramework.node1 (INFO): Wrote perf output to '/tmp/test71_cfvsc/node1/node-1-AcceptBlockTest.perf.data'
2018-10-19T20:36:09.608000Z TestFramework (WARNING): Not cleaning up dir /tmp/test71_cfvsc due to perf data
2018-10-19T20:36:09.608000Z TestFramework (INFO): Tests successful
|
2468b4a to
358e757
Compare
|
Concept ACK, very nice! |
|
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ConflictsNo conflicts as of last run. |
|
Concept ACK |
ryanofsky
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
utACK 358e757d566d5f659901acc6f15fa9eb6eb3e741
2cd3185 to
dd22df8
Compare
|
Addressed feedback from @ryanofsky @conscott. |
maflcko
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
utACK
dd22df8 to
ac6a6b3
Compare
|
Pushed feedback from @MarcoFalke. |
c978948 to
a94c68b
Compare
jnewbery
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Concept ACK.
This seems cool. I haven't had a chance to play around with it yet. I've given the code a cursory glance and will review more thoroughly next week.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is really cool. I've now had a chance to play around with it and it's great. I think doing the following would make it even more useful and accessible for developers:
- move the documentation about installing and using
perftodoc/developer-notes.md - move the documentation about using
profile_with_perf()totest/README.md, with a reference todoc/developer-notes.mdfor notes on perf.
|
Concept ACK |
a94c68b to
1ae07ec
Compare
|
Thanks for the review, @jnewbery. I've pushed a rebased tip that addresses the feedback. Here's the diff (excluding the rebase). |
11bc2f3 to
27a895d
Compare
ryanofsky
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
utACK 27a895d72a385bcaa861e08b03bb5c817f8e253f. Changes since last review: rebase, moving & adding documentation, tweaking output paths.
doc/developer-notes.md
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In commit "docs: add perf section to developer docs" (27a895d72a385bcaa861e08b03bb5c817f8e253f)
Slightly strange the link text is "understand the security tradeoffs" instead of just "security tradeoffs."
jnewbery
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great James. A few comments inline.
Introduces `TestNode.profile_with_perf()` context manager which samples node execution to produce profiling data. Also introduces a test framework flag, `--perf`, which will run perf on all nodes for the duration of a given test.
27a895d to
13782b8
Compare
|
Pushed an update addressing feedback from @jnewbery. |
ryanofsky
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
utACK 13782b8. Main change is removing code in example test, and adding to test README instead.
…ith perf 13782b8 docs: add perf section to developer docs (James O'Beirne) 58180b5 tests: add utility to easily profile node performance with perf (James O'Beirne) Pull request description: Adds a context manager to easily (and selectively) profile node performance during functional test execution using `perf`. While writing some tests, I encountered some odd bitcoind slowness. I wrote up a utility (`TestNode.profile_with_perf`) that generates performance diagnostics for a node by running `perf` during the execution of a particular region of test code. `perf` usage is detailed in the excellent (and sadly unmerged) #12649; all due props to @eklitzke. ### Example ```python with node.profile_with_perf("large-msgs"): for i in range(200): node.p2p.send_message(some_large_msg) node.p2p.sync_with_ping() ``` This generates a perf data file in the test node's datadir (`/tmp/testtxmpod0y/node0/node-0-TestName-large-msgs.perf.data`). Running `perf report` generates nice output about where the node spent most of its time while running that part of the test: ```bash $ perf report -i /tmp/testtxmpod0y/node0/node-0-TestName-large-msgs.perf.data --stdio \ | c++filt \ | less # To display the perf.data header info, please use --header/--header-only options. # # # Total Lost Samples: 0 # # Samples: 135 of event 'cycles:pp' # Event count (approx.): 1458205679493582 # # Children Self Command Shared Object Symbol # ........ ........ ............... ................... ........................................................................................................................................................................................................................................................................ # 70.14% 0.00% bitcoin-net bitcoind [.] CNode::ReceiveMsgBytes(char const*, unsigned int, bool&) | ---CNode::ReceiveMsgBytes(char const*, unsigned int, bool&) 70.14% 0.00% bitcoin-net bitcoind [.] CNetMessage::readData(char const*, unsigned int) | ---CNetMessage::readData(char const*, unsigned int) CNode::ReceiveMsgBytes(char const*, unsigned int, bool&) 35.52% 0.00% bitcoin-net bitcoind [.] std::vector<char, zero_after_free_allocator<char> >::_M_fill_insert(__gnu_cxx::__normal_iterator<char*, std::vector<char, zero_after_free_allocator<char> > >, unsigned long, char const&) | ---std::vector<char, zero_after_free_allocator<char> >::_M_fill_insert(__gnu_cxx::__normal_iterator<char*, std::vector<char, zero_after_free_allocator<char> > >, unsigned long, char const&) CNetMessage::readData(char const*, unsigned int) CNode::ReceiveMsgBytes(char const*, unsigned int, bool&) ... ``` Tree-SHA512: 9ac4ceaa88818d5eca00994e8e3c8ad42ae019550d6583972a0a4f7b0c4f61032e3d0c476b4ae58756bc5eb8f8015a19a7fc26c095bd588f31d49a37ed0c6b3e
…mance with perf 13782b8 docs: add perf section to developer docs (James O'Beirne) 58180b5 tests: add utility to easily profile node performance with perf (James O'Beirne) Pull request description: Adds a context manager to easily (and selectively) profile node performance during functional test execution using `perf`. While writing some tests, I encountered some odd bitcoind slowness. I wrote up a utility (`TestNode.profile_with_perf`) that generates performance diagnostics for a node by running `perf` during the execution of a particular region of test code. `perf` usage is detailed in the excellent (and sadly unmerged) bitcoin#12649; all due props to @eklitzke. ### Example ```python with node.profile_with_perf("large-msgs"): for i in range(200): node.p2p.send_message(some_large_msg) node.p2p.sync_with_ping() ``` This generates a perf data file in the test node's datadir (`/tmp/testtxmpod0y/node0/node-0-TestName-large-msgs.perf.data`). Running `perf report` generates nice output about where the node spent most of its time while running that part of the test: ```bash $ perf report -i /tmp/testtxmpod0y/node0/node-0-TestName-large-msgs.perf.data --stdio \ | c++filt \ | less # To display the perf.data header info, please use --header/--header-only options. # # # Total Lost Samples: 0 # # Samples: 135 of event 'cycles:pp' # Event count (approx.): 1458205679493582 # # Children Self Command Shared Object Symbol # ........ ........ ............... ................... ........................................................................................................................................................................................................................................................................ # 70.14% 0.00% bitcoin-net bitcoind [.] CNode::ReceiveMsgBytes(char const*, unsigned int, bool&) | ---CNode::ReceiveMsgBytes(char const*, unsigned int, bool&) 70.14% 0.00% bitcoin-net bitcoind [.] CNetMessage::readData(char const*, unsigned int) | ---CNetMessage::readData(char const*, unsigned int) CNode::ReceiveMsgBytes(char const*, unsigned int, bool&) 35.52% 0.00% bitcoin-net bitcoind [.] std::vector<char, zero_after_free_allocator<char> >::_M_fill_insert(__gnu_cxx::__normal_iterator<char*, std::vector<char, zero_after_free_allocator<char> > >, unsigned long, char const&) | ---std::vector<char, zero_after_free_allocator<char> >::_M_fill_insert(__gnu_cxx::__normal_iterator<char*, std::vector<char, zero_after_free_allocator<char> > >, unsigned long, char const&) CNetMessage::readData(char const*, unsigned int) CNode::ReceiveMsgBytes(char const*, unsigned int, bool&) ... ``` Tree-SHA512: 9ac4ceaa88818d5eca00994e8e3c8ad42ae019550d6583972a0a4f7b0c4f61032e3d0c476b4ae58756bc5eb8f8015a19a7fc26c095bd588f31d49a37ed0c6b3e

Adds a context manager to easily (and selectively) profile node performance during functional test execution using
perf.While writing some tests, I encountered some odd bitcoind slowness. I wrote up a utility (
TestNode.profile_with_perf) that generates performance diagnostics for a node by runningperfduring the execution of a particular region of test code.perfusage is detailed in the excellent (and sadly unmerged) #12649; all due props to @eklitzke.Example
This generates a perf data file in the test node's datadir (
/tmp/testtxmpod0y/node0/node-0-TestName-large-msgs.perf.data).Running
perf reportgenerates nice output about where the node spent most of its time while running that part of the test: