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

Plotting progress metric added #2525

Merged
merged 6 commits into from
Feb 14, 2024
Merged

Plotting progress metric added #2525

merged 6 commits into from
Feb 14, 2024

Conversation

RomanLabGit
Copy link
Contributor

@RomanLabGit RomanLabGit commented Feb 10, 2024

Code contributor checklist:

Copy link
Member

@nazar-pc nazar-pc left a comment

Choose a reason for hiding this comment

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

Thanks for your contribution!

If I'm reading this correctly, you want to be able to see total plotting progress in metrics.

While this change likely achieves that (modulo naming, it is not really sector plotting progress, it is total farm plotting progress), there is a better and more scalable way to do this.

Instead of tracking percentages, it is better to have metric about total number of sectors in the farm and number of plotted sectors. While at it, adding tracking of sectors that are about to be replotted would be nice too, that way you will be also visualize how much of the farm is still up to date and how much is being updated.

Also I would appreciate if you read contribution guidelines, but I will clean things up if necessary afterwards anyway. You really do need to clone it locally and test and not just change from the browser though.

@RomanLabGit
Copy link
Contributor Author

I decided to track percentages passed into the on_sector_update callback fn to avoid using the async plotted_sectors_count fn. Is it OK to use asyncs for metrics updating? If no, could you suggest another way?

@nazar-pc
Copy link
Member

You don't need to call plotted_sectors_count, you call it once during initialization and then just increment it every time new sector is plotted.

@RomanLabGit
Copy link
Contributor Author

Well, this will work during initial plotting. But in case of replotting there will be an incorrect result. I assumed that the progress percentage passed via SectorPlottingDetails or the plotted_sectors_count fn provide a correct replotting result. How do you suppose to get the replotting details?

@nazar-pc
Copy link
Member

Right, that was only about initial plotting. It can be done in various ways, but I'd probably make a separate metrics for replotting. When about-to-expire sectors are identified, metric will increase to that number of sectors and will decrease as sectors are replotted. And similarly for fully expired sectors.

Then you can visualize the whole plot as a combination of sectors that are:

  • not plotted yet
  • plotted and up to date
  • require replotting, but still viable for farming
  • expired

@RomanLabGit
Copy link
Contributor Author

Can replotting occur during the initial plotting, before all sectors have been plotted at least once? (I hope, NO)
Can the sector update callback fn with the SectorUpdate::Expiration param be called more than once (for ex. with AboutToExpire and Expired) for the same sector before it is replotted? If that's the case, the incremental count of expired sectors you suggested (as I understand it) will not be correct.

@nazar-pc
Copy link
Member

Can replotting occur during the initial plotting, before all sectors have been plotted at least once? (I hope, NO)

No, it can't (for the same farm, other farms can be replotting concurrently). It is not even known which sectors are about to expire during initial plotting, but this part will change at some point, so expired sectors will be known before initial plotting is finished (and it would be possible to show in metrics).

Can the sector update callback fn with the SectorUpdate::Expiration param be called more than once (for ex. with AboutToExpire and Expired) for the same sector before it is replotted? If that's the case, the incremental count of expired sectors you suggested (as I understand it) will not be correct.

Shouldn't be the case right now, if it ever changes we will update the code that relies on this assumption.

@RomanLabGit
Copy link
Contributor Author

Please review the changes.

@@ -664,6 +664,11 @@ where

info!("Finished collecting already plotted pieces successfully");

for (_, single_disk_farm) in single_disk_farms.iter().enumerate() {
farmer_metrics.update_farm_size(single_disk_farm.id(), single_disk_farm.total_sectors_count() as i64);
Copy link
Member

Choose a reason for hiding this comment

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

We don't want signed integers here, it should likely be SectorIndex in size (basically u16), same for below plotted sectors.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

But i64 is already used in the project on the interface of the established_connections gauge. Should I use the same gauge type and convert values in the updating functions?

Copy link
Member

Choose a reason for hiding this comment

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

Yes, that is what I would prefer. We try to use domain-specific types in various places if possible and convert to the actual types of underlying libraries in case they mismatch at the boundaries.

Copy link
Contributor Author

@RomanLabGit RomanLabGit Feb 13, 2024

Choose a reason for hiding this comment

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

Is it OK that single_disk_farm.plotted_sectors_count() and single_disk_farm.total_sectors_count() return different types (usize and SectorIndex)?

Copy link
Member

Choose a reason for hiding this comment

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

There are some technical reasons for it, will likely change in the future to the same type

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is it OK to use .try_into().unwrap() for converting in that case?

Copy link
Member

Choose a reason for hiding this comment

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

I would prefer as in this particular instance and we don't use .unwrap() anywhere except tests as contribution guidelines suggest.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So, should I change now?

Copy link
Member

Choose a reason for hiding this comment

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

I'll update it in the upcoming PR

}
}
SectorUpdate::Expiration(SectorExpirationDetails::AboutToExpire) => {
farmer_metrics.update_farm_expired(&single_disk_farm_id, 1);
Copy link
Member

Choose a reason for hiding this comment

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

This sector is about to expire, but it has not expired yet.

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 we cannot count the Expired and AboutToExpire sectors separately using the incremental counters only, because it isn't possible to determine which sector is replotted within the sector update callback fn. So, I decided to count them together.

Copy link
Member

Choose a reason for hiding this comment

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

We don't need to know "which" sector, we only need to know "how many" and since fully expired sectors are being replotted before those that are about to expire, we already know what to decrement.

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 initially wanted to count expirations and replots cumulatively in the corresponding counter metrics and calculate the difference (actual expired sectors) outside of the farmer, this approach provides a bit more stored data. If you prefer storing only the differences, I can of course change the scheme.

Copy link
Member

Choose a reason for hiding this comment

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

I see. I guess that would work as well, but I'm not sure what would be more flexible. We already have number of sectors plotted in total with metrics before this PR. I'm open for options either way if there is some additional information to be gained from it.

Comment on lines 740 to 744
if let Some(_) = &old_plotted_sector {
farmer_metrics.update_farm_replotted(&single_disk_farm_id, 1);
} else {
farmer_metrics.update_farm_plotted(&single_disk_farm_id, 1);
}
Copy link
Member

Choose a reason for hiding this comment

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

All new methods are called "update", but most of them are actually increments. "update" is fine, but you then need to pass the new value as the result. Specifically, you track sectors that are about to expire and expired below to increment corresponding values, while here you decrement them, such that at the end of replotting number of expired and about to expire sectors is 0 and number of plotted sectors is the same as total number of sectors.

So most of the metrics will be gauges, not counters.

In order to track those totals you'll want to use AtomicU16 to satisfy Rust's ownership rules.

pub(super) fn update_farm_size(
&self,
single_disk_farm_id: &SingleDiskFarmId,
sectors: i64,
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
sectors: i64,
sectors: SectorIndex,

And if you need to convert it to bigger integer prefer u64::from(sectors), this way if some of the types change in incompatible way it'll stop compiling, otherwise as u64 will potentially truncate the data. Just a good practice.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just updated taking into account all the recommendations

nazar-pc
nazar-pc previously approved these changes Feb 13, 2024
Copy link
Member

@nazar-pc nazar-pc left a comment

Choose a reason for hiding this comment

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

This is good enough, I'll do some changes on top in follow-up PR. Waiting for CI. While waiting for CI please do read contribution guidelines, we have a specific way of introducing changes that would be nice to follow next time.

@nazar-pc
Copy link
Member

Well, looks like clippy is not happy, neither is formatting. https://github.com/subspace/subspace/blob/main/CONTRIBUTING.md is your friend, don't check it without actually reading.

@RomanLabGit
Copy link
Contributor Author

cargo-fmt and cargo-clippy worked locally without problems now.

@nazar-pc nazar-pc merged commit 5e59809 into autonomys:main Feb 14, 2024
9 checks passed
@nazar-pc nazar-pc mentioned this pull request Feb 14, 2024
1 task
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.

2 participants