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

Add block download progress to metrics UI #2484

Merged
merged 3 commits into from
Jul 29, 2017

Conversation

str4d
Copy link
Contributor

@str4d str4d commented Jun 26, 2017

No description provided.

@str4d str4d added A-metrics-screen Area: Metrics screen usability labels Jun 26, 2017
@str4d str4d added this to the 1.0.11 Release milestone Jun 26, 2017
@daira daira removed this from the 1.0.11 Release milestone Jul 3, 2017
Copy link
Contributor

@daira daira left a comment

Choose a reason for hiding this comment

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

utACK modulo comments.

src/metrics.cpp Outdated
double averageSpacing = (targetSpacing + checkpointSpacing) / 2;
int netheight = medianHeight + ((GetTime() - tipmediantime) / averageSpacing);
// Round to nearest ten to reduce noise
netheight = (netheight / 10) * 10;
Copy link
Contributor

Choose a reason for hiding this comment

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

This is not rounding to the nearest 10; it's rounding down to a multiple of 10.

src/metrics.cpp Outdated
// checkpoint, and use that to estimate the current network height.
auto chainParams = Params();
auto checkpointData = chainParams.Checkpoints();
int medianHeight = height - 5;
Copy link
Contributor

Choose a reason for hiding this comment

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

Use CBlockIndex::nMedianTimeSpan / 2 instead of 5.

@str4d str4d force-pushed the block-download-completion branch from 92bea1d to 4d9c9e0 Compare July 11, 2017 14:51
@str4d
Copy link
Contributor Author

str4d commented Jul 11, 2017

@daira comments addressed.

Copy link
Contributor

@daira daira left a comment

Choose a reason for hiding this comment

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

utACK. I'm not sure what our testing policy is for changes that obviously only affect non-essential output; do we need to test this @nathan-at-least ?

@daira daira added this to the 1.0.11 Release milestone Jul 25, 2017
Copy link
Contributor

@nathan-at-least nathan-at-least left a comment

Choose a reason for hiding this comment

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

Requested change: unit tests of arithmetic.

src/metrics.cpp Outdated
int netheight = medianHeight + ((GetTime() - tipmediantime) / averageSpacing);
// Round to nearest ten to reduce noise
netheight = ((netheight + 5) / 10) * 10;
int downloadPercent = height * 100 / netheight;
Copy link
Contributor

Choose a reason for hiding this comment

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

Imagine there were some bug in the arithmetic. Could we factor out the "sensor" code (which reads from blockchain state, ex IsInitialBlockDownload() and chainParams.Checkpoints, arithmetic functional code, and display code, and then unittest at least the arithmetic functional code?

Then if there were an arithmetic bug, that would imply either we missed a test specification, or the specification was buggy.

Copy link
Contributor

Choose a reason for hiding this comment

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

@str4d will write a unit test for this.

@daira daira assigned str4d and unassigned str4d Jul 25, 2017
@str4d str4d force-pushed the block-download-completion branch from 4d9c9e0 to 047aec1 Compare July 26, 2017 00:51
@str4d
Copy link
Contributor Author

str4d commented Jul 26, 2017

Refactored the code and added unit tests. I force-pushed to squash this into the existing commit.

Copy link
Contributor

@daira daira left a comment

Choose a reason for hiding this comment

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

ut(ACK+cov)

src/metrics.cpp Outdated
// We average the target spacing with the observed spacing to the last
// checkpoint, and use that to estimate the current network height.
int medianHeight = height - CBlockIndex::nMedianTimeSpan / 2;
double checkpointSpacing = (double (tipmediantime - timeLastCheckpoint)) / (medianHeight - heightLastCheckpoint);
Copy link
Contributor

Choose a reason for hiding this comment

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

Under what conditions could this potentially divide by zero?

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, can checkpointSpacing become negative in pathological cases?

Copy link
Contributor

@daira daira Jul 27, 2017

Choose a reason for hiding this comment

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

double division-by-zero is well-defined (for IEEE arithmetic) to produce infinity or -infinity. Dividing a double by an infinity gives zero.

Copy link
Contributor

Choose a reason for hiding this comment

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

Provided we have floating point non-stop mode enabled (via feholdexcept or fesetexceptflag). I assumed we did because we use infinities in the fee handling code.

Copy link
Contributor

Choose a reason for hiding this comment

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

I suggest avoiding the issue by using:

double checkpointSpacing = max(1.0d, (double (tipmediantime - timeLastCheckpoint)) / max(1.0d, double (medianHeight - heightLastCheckpoint)));

(and adding tests that exercise the clamping).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@ebfull raises a good point. I have addressed this in a different way: while the current height is <= the last checkpoint, estimate the checkpoint spacing using the interval [genesis, lastCheckpoint] instead of [lastCheckpoint, tip].

Copy link
Contributor

@nathan-at-least nathan-at-least left a comment

Choose a reason for hiding this comment

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

utACK.

There are some pathological cases and I'm not sure if they are reachable.

If not, an improvement would be to add precondition assertions to guard against undefined behavior (if that is indeed C++ divide by zero behavior). Otherwise test cases for them and error recovery would be good. I don't see either of those as requirements for merging this.

src/metrics.cpp Outdated
// We average the target spacing with the observed spacing to the last
// checkpoint, and use that to estimate the current network height.
int medianHeight = height - CBlockIndex::nMedianTimeSpan / 2;
double checkpointSpacing = (double (tipmediantime - timeLastCheckpoint)) / (medianHeight - heightLastCheckpoint);
Copy link
Contributor

Choose a reason for hiding this comment

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

Also, can checkpointSpacing become negative in pathological cases?

src/metrics.cpp Outdated
int medianHeight = height - CBlockIndex::nMedianTimeSpan / 2;
double checkpointSpacing = (double (tipmediantime - timeLastCheckpoint)) / (medianHeight - heightLastCheckpoint);
double averageSpacing = (targetSpacing + checkpointSpacing) / 2;
int netheight = medianHeight + ((GetTime() - tipmediantime) / averageSpacing);
Copy link
Contributor

Choose a reason for hiding this comment

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

Under what conditions could averageSpacing == 0? Three cases to consider:

  • targetSpacing == checkpointSpacing == 0
  • One is negative (which seem unexpected).
  • The other is negative.

src/metrics.cpp Outdated
Checkpoints::GetTotalBlocksEstimate(checkpointData),
checkpointData.nTimeLastCheckpoint,
chainParams.GetConsensus().nPowTargetSpacing);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I personally like factoring out the "I/O" into this outer function. What's your opinion @str4d?

Copy link
Contributor

Choose a reason for hiding this comment

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

I like it too.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Could you clarify what you mean? If you mean pulling the stdio calls from the parent into here, I would like to point out that having them in their current function makes aligning the UI significantly easier, as all the common calls are together (in this case, inside printStats()).

src/metrics.cpp Outdated
height, tipmediantime,
Checkpoints::GetTotalBlocksEstimate(checkpointData),
checkpointData.nTimeLastCheckpoint,
chainParams.GetConsensus().nPowTargetSpacing);
Copy link
Contributor

Choose a reason for hiding this comment

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

Answering my edge-case questions above:

  • nPowTargetSpacing is defined in one place as an int64_t and is our target block time and it would be quite unlikely we wouldn't notice changing this to negative.
  • I haven't determined what the pathological conditions for checkpointData.nTimeLastCheckpoint or Checkpoints::GetTotalBlockEstimate() would be.

I suspect the worst case behavior for those pathological conditions would be just incorrect display, although it sounds like division by 0 can be undefined behavior.

@daira
Copy link
Contributor

daira commented Jul 28, 2017

Note that we're behind schedule on the release and this is the last feature PR. It's in danger of getting kicked out if the edge case issues are not resolved today (Friday).

Corrections are to the median block times, which were generated by subtracting
CBlockIndex::nMedianTimeSpan / 2 from the block height and then multiplying by
the target spacing. GetMedianTimePast() takes an array sorted by std::sort() and
returns element CBlockIndex::nMedianTimeSpan / 2, meaning that if
CBlockIndex::nMedianTimeSpan is odd (which it is), there is an out-by-one error
in the subtraction.
@daira
Copy link
Contributor

daira commented Jul 29, 2017

ut(ACK+cov)

@daira
Copy link
Contributor

daira commented Jul 29, 2017

@zkbot r+

@zkbot
Copy link
Contributor

zkbot commented Jul 29, 2017

📌 Commit 92bfde0 has been approved by daira

@zkbot
Copy link
Contributor

zkbot commented Jul 29, 2017

⌛ Testing commit 92bfde0 with merge 10acd8a...

zkbot added a commit that referenced this pull request Jul 29, 2017
Add block download progress to metrics UI
@zkbot
Copy link
Contributor

zkbot commented Jul 29, 2017

☀️ Test successful - pr-merge
Approved by: daira
Pushing 10acd8a to master...

@zkbot zkbot merged commit 92bfde0 into zcash:master Jul 29, 2017
@str4d str4d deleted the block-download-completion branch August 3, 2017 13:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-metrics-screen Area: Metrics screen usability
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants