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

Rewrote Rational.Str to speed up stringification, Rats somewhat, FatRats a lot #1807

Closed
wants to merge 4 commits into from
Closed

Rewrote Rational.Str to speed up stringification, Rats somewhat, FatRats a lot #1807

wants to merge 4 commits into from

Conversation

thundergnat
Copy link
Contributor

@thundergnat thundergnat commented May 9, 2018

Moved Rational.Str to Rat.Str. Add a fast FatRat.Str multi. Rewrote Rational.Str to speed up Rational stringification across the board. Speeds up Rats marginally. Speeds up FatRats, especially those with large denominators significantly. Takes from half, to 1/200th the time that it used to take.

Spectest clean.

src/core/Rat.pm6 Outdated
) ~ $whole;

if $fract {
if $!denominator.chars < 5 {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can't this be just $!denominator < 10000? That would be faster than converting it to a string to count the chars.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point. I'll fix that.

… Rats.

Significantly faster for large denominator FatRats; 2 to 200 times the speed of the original.
Returns slightly different results. The original sometimes left trailing zeros. This always
removes trailing zeros. Spectest clean.
… Rats.

Slightly faster for all Rats. Significantly faster for large denominator FatRats;
2 to 200 times the speed of the original.

Spectest clean.
@thundergnat thundergnat changed the title Add fast .Str multi for FatRat, split Rational.Str into Rat/FatRat Str Rewrote Rational.Str to speed up stringification, Rats somewhat, FatRats a lot May 10, 2018
# fight floating point noise issues RT#126016
if $fract.Num == 1e0 { ++$whole; $fract = 0 }
if $fract.Num == 1e0 {
if nqp::unbox_s(self.^name) eq 'Rat' {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this could/should be if nqp::eqaddr(self.WHAT,Rat) {. Then you're actually checking against the type itself, not the string representation of its name.

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 am not arguing, but I did just copy that syntax from line 14 in the same file. I can certanly change that if it is a better way to go.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, but that line is intentionally creating a string. Line 12 does nqp::eqaddr(self.WHAT,Rational), because there it's checking for a type. If you grep through the Rakudo sources you'll see a whole lot more uses of nqp::eqaddr(<something>.WHAT, <some type>) than <something>.^name eq <some type name>. What you have would work, it's just slower.

if $fract.Num == 1e0 {
if nqp::unbox_s(self.^name) eq 'Rat' {
$whole += 1;
$fract = 0
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 kind of a nitpick, but I think there's a convention that last statements in blocks only leave off the semi-colon if the value is being returned.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fair enough.

$whole += 1;
$fract = 0
}
$reduce = True
Copy link
Contributor

Choose a reason for hiding this comment

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

Ibid.

$fract *= 1000000;
} else {
$c = $!denominator.chars + 1;
$fract *= nqp::pow_I(10, nqp::decont($c), Num, Int);
Copy link
Contributor

Choose a reason for hiding this comment

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

The use of nqp ops seems a little inconsistent. Why use nqp::pow_I instead of just **? Or conversely, why use e.g., $!denominator.chars instead of nqp::chars($!denominator.Str) a line above?

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 did some testing both ways and the nqp::pow_I seemed to be marginally but measurably faster. I could easily change that back though. I am not really familiar with the different nqp ops and which give enough of a benefit to outweigh the added complexity.

Thanks for your review.

Copy link
Contributor

Choose a reason for hiding this comment

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

What you have is definitely not wrong, so now we're getting into personal preference. But since you're changing the algorithm used (and the original code is almost completely pure Perl 6), maybe a first commit that converts to the new algorithm, and then a second commit that changes some of the new code's slow parts to nqp ops?

# maintain precision (trailing zeros) of large denominator FatRats.
# There are situations where the extra zeros are significant, they
# can be easily removed in userspace but not easily restored
if ($c < 8) || (nqp::unbox_s(self.^name) eq 'Rat') || $reduce {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same thing about nqp::eqaddr(self.WHAT,Rat) as above.

@tbrowder
Copy link
Member

tbrowder commented May 12, 2018

A nit: the cuddled else (1) is not consistent with the rest of the code and (2) ignores the style guide (see CONTRIBUTING.md).

@thundergnat
Copy link
Contributor Author

Obsolete. Rewrote following critiques and suggestions

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.

None yet

3 participants