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

[Qt] Add interactive mempool graph #8550

Closed
wants to merge 2 commits into from

Conversation

jonasschnelli
Copy link
Contributor

Includes #8501

At the moment, the mempool graph is not very prominently placed (next to the debug window).
bildschirmfoto 2016-08-19 um 21 20 48

Features:

  • interactive graph with options for tx count, dynamic memory usage and minRelayFee/KB
  • collects stats in the background, changing the timespan will directly redraw (unlike our bandwidth graph)
  • Dynamic size drawing, window can be resized
  • The mempool graph is a QWidget which means, it could be placed together with other graphs in a combine multi-graph view (screensaver approach)

bildschirmfoto 2016-08-19 um 21 28 09

@jonasschnelli jonasschnelli force-pushed the 2016/08/stats_qt branch 2 times, most recently from ae05dfa to cb2b429 Compare August 19, 2016 19:36
@maflcko
Copy link
Member

maflcko commented Aug 19, 2016

Concept ACK. Will test later.

@jonasschnelli
Copy link
Contributor Author

Added the missing button PNGs now to git. This should fix the compile issue.

@luke-jr
Copy link
Member

luke-jr commented Aug 19, 2016

Nice. Some people might want to see actual byte-size, weights, etc; probably will overflow the one-line-per-item paradigm quickly - maybe have a dropdown box to add stuff?

@jonasschnelli
Copy link
Contributor Author

Yes. Dropdown box could make sense. Adding a second graph below or on the right that just plots different data would probably also look good.

@maflcko
Copy link
Member

maflcko commented Aug 19, 2016

Nit: Fonts appear larger on my system. Otherwise this looks great!

screenshot from 2016-08-19 23-15-51

{
dynMemUsageValueItem->setPlainText(GUIUtil::formatBytes(vSamples.back().dynMemUsage));
txCountValueItem->setPlainText(QString::number(vSamples.back().txCount));
minFeeValueItem->setPlainText(QString::number(vSamples.back().minFeePerK));
Copy link
Member

Choose a reason for hiding this comment

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

Nit: Missing value. I think this is in satoshis. What about using BTC?

@jonasschnelli
Copy link
Contributor Author

Switched to "Arial" as font and added a auto-size-adjustment.
Also added the "charts" icon for the menu.

@maflcko
Copy link
Member

maflcko commented Aug 20, 2016

Nit: run optimize-pngs and mention the icons in assets_attribution?

@jonasschnelli jonasschnelli force-pushed the 2016/08/stats_qt branch 3 times, most recently from 1944167 to f62fae3 Compare August 20, 2016 10:05
@jonasschnelli
Copy link
Contributor Author

Optimized the pngs and added them to the assets attribution file.

@ghost
Copy link

ghost commented Aug 20, 2016

Concept ACK.

@isle2983
Copy link
Contributor

Nit1: The graph window is always drawn on top of the main window, even when the main window is active. It makes it annoying to use the rest of the GUI while this is open.

Nit2: The quantity labels for the Dynamic Memory Usage values on the left hand side of the graph are cramped and cut off some of the characters. See "500.00 KB" in the screenshot. It is like that for larger values once it gets into the 100MBs too.

mempoolstats

@rebroad
Copy link
Contributor

rebroad commented Aug 24, 2016

I'm not sure what I'm doing wrong but I've merged this and the graph is empty, and has been for an hour now... :-s i.e. Dynamic Memory Usage is stuck on 0 bytes, Amount of Txs also 0, MinRelayFee also zero.

@jonasschnelli
Copy link
Contributor Author

@rebroad: what does getmempoolinfo tells you? Are you in sync on mainnet (or testnet)?

@rebroad
Copy link
Contributor

rebroad commented Aug 25, 2016

@jonasschnelli problem solved - I had blocksonly=1 in the config file!! It's working really nicely now - great job!! I love how it can be resized and the period of time changed without the graph resetting (unlike the network traffic graph!).

Also, ACK

@fanquake
Copy link
Member

OS X screenshots:
init
more-than-10

@luke-jr
Copy link
Member

luke-jr commented Aug 27, 2016

Using images for basically-a-checkbox gives a non-native look on every system. It looks like we can just colour a QCheckBox?

@paveljanik
Copy link
Contributor

Rebase needed.

Concept ACK

Agree about checkboxes...

@jonasschnelli
Copy link
Contributor Author

Rebased on top of #8501

@@ -234,6 +237,11 @@ RES_ICONS = \
qt/res/icons/bitcoin.ico \
qt/res/icons/bitcoin_testnet.ico \
qt/res/icons/bitcoin.png \
qt/res/icons/button_off.png \
qt/res/icons/button_on_blue.png \
Copy link
Member

Choose a reason for hiding this comment

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

@jonasschnelli What do you think about using QCheckBox with setPallette() as suggested by @luke-jr ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think Checkboxes are appropriate for now.

But we should consider using non-standard UI elements to improve the look and feel. I know, developers hate this. :-)

But have a look at #5896. I think people liked it because the look and feel was different then just "Arial 12 and standard UI elements".

Copy link
Member

Choose a reason for hiding this comment

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

Non-standard UI elements ruin the look and feel...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not sure. That's probably a matter of taste.
The thing why I'd like to keep the non-standard UI elements is, that I'm using a QGraphicScene at this point. Adding a QWidget (checkbox) at this point breaks the flexibility of reusing the QGraphicScene and draw it in any scale.

I think the checkbox could be different then the one thats currently used. And it probably should be draw internally and not use a PNG.

Copy link
Member

Choose a reason for hiding this comment

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

Because it's a matter of taste is precisely why it should use standard UI elements. The standard element should do all the drawing. If the user doesn't like their standard widgets, they can change them.

src/main.cpp Outdated
@@ -2837,6 +2844,9 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams,
for(unsigned int i=0; i < pblock->vtx.size(); i++)
txChanged.push_back(std::make_tuple(pblock->vtx[i], pindexNew, i));

// update mempool stats
CStats::DefaultStats()->addMempoolSample(mempool.size(), mempool.DynamicMemoryUsage(), mempool.GetMinFee(GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000).GetFeePerK());
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you please do something with this long line? It is there ~3 times and does a simple thing - worth a better method to add a sample?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm.. I think this line is reasonable? How would you improve it?

Copy link
Contributor

Choose a reason for hiding this comment

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

Pass const ref. mempool only and do the rest in the method?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I like the current layering concept. IMO its preferable that the stats.cpp module has no knowledge over the txmempool.h's classes, etc., I prefer to keep it as "dump" as possible.

@jonasschnelli
Copy link
Contributor Author

Rebased.
It's currently not Qt4 compatible due to a lambda signal connect (travis reported / working on it).

@laanwj
Copy link
Member

laanwj commented Nov 23, 2017

It's currently not Qt4 compatible due to a lambda signal connect (travis reported / working on it).

If it's a lot of work, feel free to leave "nice but not critical" features such as this out when compiling with Qt4.

@PierreRochard
Copy link
Contributor

ACK with Qt5

Copy link
Contributor

@jb55 jb55 left a comment

Choose a reason for hiding this comment

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

Hmm for some reason I'm getting this error on my system:

qt/mempoolstats.cpp: In member function ‘void MempoolStats::drawChart()’:
qt/mempoolstats.cpp:183:42: error: ‘ceil’ was not declared in this scope
     maxValueSize = ceil(maxValueSize*0.11)*10; //use size steps of 10dip
                                          ^
qt/mempoolstats.cpp:256:108: error: ‘log10’ was not declared in this scope
     int64_t dynMemUsagelog10Val = pow(10.0f, floor(log10(maxDynMemUsage*paddingTopSizeFactor-minDynMemUsage)));
                                                                                                            ^
qt/mempoolstats.cpp:256:109: error: ‘floor’ was not declared in this scope
     int64_t dynMemUsagelog10Val = pow(10.0f, floor(log10(maxDynMemUsage*paddingTopSizeFactor-minDynMemUsage)));
                                                                                                             ^
qt/mempoolstats.cpp:256:110: error: ‘pow’ was not declared in this scope
     int64_t dynMemUsagelog10Val = pow(10.0f, floor(log10(maxDynMemUsage*paddingTopSizeFactor-minDynMemUsage)));
                                                                                                              ^

I fixed it with this patch:

diff --git a/src/qt/mempoolstats.cpp b/src/qt/mempoolstats.cpp
index 139efa1a9..af33a655b 100644
--- a/src/qt/mempoolstats.cpp
+++ b/src/qt/mempoolstats.cpp
@@ -8,6 +8,7 @@
 #include <qt/clientmodel.h>
 #include <qt/guiutil.h>
 #include <stats/stats.h>
+#include <math.h>
 
 static const char *LABEL_FONT = "Arial";
 static int LABEL_TITLE_SIZE = 22;

Copy link
Member

@Sjors Sjors left a comment

Choose a reason for hiding this comment

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

I did not need @jb55's patch on MacOS 10.13.2.

Although it can wait for a followup commit, I would prefer if more of the UI was built using interface builder (see #11950). That would it easier for other to improve the looks.

This should be easy for the header section above the chart and the duration toggles below. It's probably not realistic for the grid and X, Y axis and colored lines, although it would be nice if they can be styled using visual tools.

I left some inline comments, but didn't see any must-fix stuff.

The drawChart() function is rather large. Some stuff needs to be drawn only once, other stuff maybe only when there's a resize. Maybe that can be split? It might be safer to move some of the calculations into their own functions and test those against boundary values.

@@ -0,0 +1,423 @@
// Copyright (c) 2016 The Bitcoin Core developers
Copy link
Member

Choose a reason for hiding this comment

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

Nit: bump to 2018?

}

// draw vertical grid
int amountOfLinesV = 4;
Copy link
Member

Choose a reason for hiding this comment

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

Nit: numberOfLinesV


QPainterPath dynMemUsageGridPath(QPointF(currentX, bottom));

// draw horizontal grid
Copy link
Member

Choose a reason for hiding this comment

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

Move grid drawing to a function?


if (!titleItem)
{
// create labels (only once)
Copy link
Member

Choose a reason for hiding this comment

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

Move the once-only stuff to another function?

QCheckBox *cb0 = new QCheckBox("Dynamic Memory Usage");
cb0->setStyleSheet("background-color: rgb(255,255,255);");
dynMemUsageSwitch = scene->addWidget(cb0);
connect(cb0, &QCheckBox::stateChanged, [cb0, this](){ drawDynMemUsage = cb0->isChecked(); drawChart(); });
Copy link
Member

@Sjors Sjors Jan 8, 2018

Choose a reason for hiding this comment

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

Move the user interacting bits to another function?

Also, do these really need to get redrawn every time? I'm not worried about performance, just code complexity. Adding and removing UI elements where it's not needed might also make using the interface builder more difficult.

connect(model, SIGNAL(mempoolStatsDidUpdate()), this, SLOT(drawChart()));
}

void MempoolStats::drawChart()
Copy link
Member

Choose a reason for hiding this comment

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

Rename to drawChartFrame()? It draws a lot more than the chart.

allDataLabel->setPos((width()-totalWidth)/2.0+last10MinLabel->boundingRect().width()+lastHourLabel->boundingRect().width()+lastDayLabel->boundingRect().width()+30,height()-filterBottomPadding);

// don't paint the grind/graph if there are no or only a signle sample
if (vSamples.size() < 2)
Copy link
Member

Choose a reason for hiding this comment

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

drawEmptyChart()

{
noDataItem->setVisible(true);
return;
}
Copy link
Member

Choose a reason for hiding this comment

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

else {
  drawChart(vSamples, ...)
}

@laanwj
Copy link
Member

laanwj commented May 14, 2018

This has been lingering for a long time. I would prefer if it makes it in, of course, it has tons of concept ACKs (the most of any open PR, according to bitcoinacks). But otherwise should we close and put this up for grabs?

@laanwj
Copy link
Member

laanwj commented Aug 31, 2018

Although it would be really nice to have, this has been inactive for very long.
Closing and adding "up for grabs".

@rebroad
Copy link
Contributor

rebroad commented Aug 20, 2020

@laanwj A rebased version of this seems to be in Bitcoin Knots. Should I open a new pull request using this rebased version?

@jonatack
Copy link
Contributor

jonatack commented Aug 20, 2020

This looks very nice. @rebroad I would review/test it if you pick it up.

@luke-jr
Copy link
Member

luke-jr commented Aug 20, 2020

Note that #8501 was updated after this, and in a conflicting way. In Knots, I'm using an older version of it.

So there is some work to be done, but it sounds like a good idea since @jonasschnelli seems to have abandoned it.

(If you're not up to merging #8501 with this, maybe it'd be fine to use the older version in Knots and the code can be updated later when the RPC interface is added)

@jarolrod
Copy link
Member

jarolrod commented Mar 4, 2021

@hebasto I guess this isn't up for grabs anymore since it's been picked up again by jonasschnelli over on the GUI repo

@rebroad
Copy link
Contributor

rebroad commented Mar 26, 2021

@hebasto This could still be up for grabs given that it was superior in various ways to the newer implementation - e.g. it could run in a separate window to the debug window - the timescales were changeable, and it also shows memory utilization, and fee filter.

@hebasto
Copy link
Member

hebasto commented Mar 26, 2021

@rebroad

@hebasto This could still be up for grabs given that it was superior in various ways to the newer implementation - e.g. it could run in a separate window to the debug window - the timescales were changeable, and it also shows memory utilization, and fee filter.

The "Up for grabs" label means "nobody's working on it", isn't it?

@laanwj
Copy link
Member

laanwj commented Mar 29, 2021

The "Up for grabs" label means "nobody's working on it", isn't it?

Yes. If you wanted to handle it in a different way, you should have picked it up yourself.

@maflcko
Copy link
Member

maflcko commented Mar 29, 2021

Or leave a suggestion on the pull that picked it up ;)

@rebroad
Copy link
Contributor

rebroad commented May 12, 2021

@rebroad

@hebasto This could still be up for grabs given that it was superior in various ways to the newer implementation - e.g. it could run in a separate window to the debug window - the timescales were changeable, and it also shows memory utilization, and fee filter.

The "Up for grabs" label means "nobody's working on it", isn't it?

Yes, it appears that no one is working on this - the fee graph is a different feature - related, but not the same. I think the UpForGrabs label ought to remain until someone is working on this particular graph.

@luke-jr are you still rebasing this?

@rebroad
Copy link
Contributor

rebroad commented May 16, 2021

A current rebase is here - rebroad@3ecfd95

@bitcoin bitcoin locked as resolved and limited conversation to collaborators Aug 16, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet