-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
Optimize spa_get_random(). #12183
Optimize spa_get_random(). #12183
Conversation
14029a0
to
b84b8b1
Compare
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.
Makes good sense to me.
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.
I think it's a little awkward to move spa_get_random()
into the os-specific random.h header file. Would you consider refactoring to introduce something like random_in_range()
which, for freebsd would look like:
static inline uint32_t
random_in_range(uint32_t range)
{
#if __FreeBSD_version >= 1300108
return (prng32_bounded(range));
#else
uint32_t r;
(void) random_get_pseudo_bytes((void *)&r, sizeof (r));
return (r % range);
#endif
}
and then spa_get_random could be left in spa_misc.c and look like:
uint32_t
spa_get_random(uint32_t range)
{
ASSERT(range != 0);
if (range == 1)
return (0);
return (random_in_range(range));
}
@mmaybee I suppose it is about "spa_" in the function name? Otherwise I am not sure why to split one trivial function with two. |
Correct. spa_get_random() should be declared in spa.h, not in random.h |
I think it should not be spa_* then. It has nothing to do with spa or ZFS at all. I'll think how to rename it. |
I think that is a reasonable alternative. |
In all places except two spa_get_random() is used for small values, and the consumers do not require well seeded high quality values. Switch those two exceptions directly to random_get_pseudo_bytes() and optimize spa_get_random(), renaming it to random_in_range(), since it is not related to SPA or ZFS in general. On FreeBSD directly map random_in_range() to new prng32_bounded() KPI added in FreeBSD 13. On Linux and in user-space just reduce the type used to uint32_t to avoid more expensive 64bit division. Signed-off-by: Alexander Motin <mav@FreeBSD.org> Sponsored-By: iXsystems, Inc.
I've renamed spa_get_random() to random_in_range(). |
Any more comments here? |
random_in_range(uint32_t range) | ||
{ | ||
#if __FreeBSD_version >= 1300108 | ||
return (prng32_bounded(range)); |
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.
@amotin shouldn't this be #if defined(_KERNEL) && __FreeBSD_version >= 1300108
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.
I don't think this file is used in user-space. It has separate implementation in include/sys/zfs_context.h. Am I wrong?
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.
I am currently doing the merge to main multiple things break. I will send you an e-mail.
In all places except two spa_get_random() is used for small values, and the consumers do not require well seeded high quality values. Switch those two exceptions directly to random_get_pseudo_bytes() and optimize spa_get_random(), renaming it to random_in_range(), since it is not related to SPA or ZFS in general. On FreeBSD directly map random_in_range() to new prng32_bounded() KPI added in FreeBSD 13. On Linux and in user-space just reduce the type used to uint32_t to avoid more expensive 64bit division. Reviewed-by: Ryan Moeller <ryan@iXsystems.com> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Alexander Motin <mav@FreeBSD.org> Sponsored-By: iXsystems, Inc. Closes openzfs#12183
In all places except two spa_get_random() is used for small values, and the consumers do not require well seeded high quality values. Switch those two exceptions directly to random_get_pseudo_bytes() and optimize spa_get_random(), renaming it to random_in_range(), since it is not related to SPA or ZFS in general. On FreeBSD directly map random_in_range() to new prng32_bounded() KPI added in FreeBSD 13. On Linux and in user-space just reduce the type used to uint32_t to avoid more expensive 64bit division. Reviewed-by: Ryan Moeller <ryan@iXsystems.com> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Alexander Motin <mav@FreeBSD.org> Sponsored-By: iXsystems, Inc. Closes #12183
In all places except two spa_get_random() is used for small values, and the consumers do not require well seeded high quality values. Switch those two exceptions directly to random_get_pseudo_bytes() and optimize spa_get_random(), renaming it to random_in_range(), since it is not related to SPA or ZFS in general. On FreeBSD directly map random_in_range() to new prng32_bounded() KPI added in FreeBSD 13. On Linux and in user-space just reduce the type used to uint32_t to avoid more expensive 64bit division. Reviewed-by: Ryan Moeller <ryan@iXsystems.com> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Alexander Motin <mav@FreeBSD.org> Sponsored-By: iXsystems, Inc. Closes openzfs#12183
In all places except two spa_get_random() is used for small values,
and the consumers do not need well seeded high quality values.
Switch those two exceptions directly to random_get_pseudo_bytes()
and optimize spa_get_random(), renaming it to random_in_range(),
since it is not related to SPA or ZFS in general.
On FreeBSD directly map random_in_range() to new prng32_bounded() KPI
added in FreeBSD 13. On Linux and in user-space just reduce the type
used to uint32_t to avoid more expensive 64bit division.
How Has This Been Tested?
On 40-thread FreeBSD system heavy uncached 4KB reads from 8 ZVOLs show reduction of time spent inside dbuf_evict_one() by ~10%. Previously it was consumed by ChaCha encryption, backing random_get_pseudo_bytes(), producing excessively strong random numbers for this purpose.
Types of changes
Checklist:
Signed-off-by
.