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

Added locale support to utility functions in format-numbers.js #1394

Merged
merged 10 commits into from Nov 7, 2018
Merged

Added locale support to utility functions in format-numbers.js #1394

merged 10 commits into from Nov 7, 2018

Conversation

ghost
Copy link

@ghost ghost commented Oct 20, 2018

This was a fix for issue #1322

@codecov
Copy link

codecov bot commented Oct 20, 2018

Codecov Report

Merging #1394 into master will decrease coverage by 2.6%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1394      +/-   ##
==========================================
- Coverage   80.69%   78.09%   -2.61%     
==========================================
  Files         157      155       -2     
  Lines       10789    10539     -250     
  Branches     2622     2560      -62     
==========================================
- Hits         8706     8230     -476     
- Misses       1884     2082     +198     
- Partials      199      227      +28
Impacted Files Coverage Δ
src/utils/format-numbers.js 84.31% <100%> (+0.98%) ⬆️
src/profile-logic/call-tree.js 99.27% <100%> (+3.32%) ⬆️
src/components/app/Root.js 0% <0%> (-74.03%) ⬇️
src/components/shared/thread/ActivityGraphFills.js 55.09% <0%> (-37.97%) ⬇️
.../components/shared/thread/SelectedActivityGraph.js 64.28% <0%> (-28.58%) ⬇️
src/components/shared/thread/ActivityGraph.js 75.4% <0%> (-18.04%) ⬇️
src/components/app/FooterLinks.js 0% <0%> (-14.29%) ⬇️
src/actions/profile-view.js 83.45% <0%> (-6.7%) ⬇️
src/components/shared/StackSettings.js 60% <0%> (-6.67%) ⬇️
src/profile-logic/profile-data.js 78.58% <0%> (-5.74%) ⬇️
... and 26 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 01ece9d...6bb436b. Read the comment docs.

Copy link
Contributor

@julienw julienw left a comment

Choose a reason for hiding this comment

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

Hey @monikamaheshwari, thanks for the patch!
The goal of this patch is to change the existing formatNumber to use the locale-aware function, and then use it. Can you look into it?

@ghost
Copy link
Author

ghost commented Oct 23, 2018

@julienw You want me to remove toFixed function and use toLocaleString ?

@julienw
Copy link
Contributor

julienw commented Oct 23, 2018

Yes I think that's the goal here.
Then I'd like to test the performance of this, because I believe toLocaleString can have performance issues, but I'm not sure... but we need to write the code to know it :)

@brisad
Copy link
Contributor

brisad commented Oct 23, 2018

Also note that when formatNumber get localized, the formatMilliseconds function will also be localized since it uses the former. That in turn means we can use the latter for the displayData totalTimeWithUnit instead of manually concatenating 'ms' to the end.

Though it does introduce extra function calls for a very simple thing, so we should check that is does not negatively impact performance as @julienw notes.

@julienw
Copy link
Contributor

julienw commented Oct 25, 2018

@monikamaheshwari hey, kind reminder that this PR is still awaiting some changes :-)

@ghost
Copy link
Author

ghost commented Oct 26, 2018

Do I need to add value.toLocaleString(undefined, { maxFractionalDigits: places }) instead of value.toFixed(places).

@julienw
Copy link
Contributor

julienw commented Oct 26, 2018

I believe you can even replace the whole function by: value.toLocaleString(undefined, { maximumFractionDigits: maxFractionalDigits, minimumSignificantDigits: significantDigits }.

You can also rename the arguments to minimumSignificantDigits and maximumFractionDigits so that you can use the shorthand: value.toLocaleString(undefined, { maximumFractionDigits, minimumSignificantDigits }.

Be careful to use the right property names.

I haven't tried this, so maybe this will need a bit more tweaking.

@ghost
Copy link
Author

ghost commented Oct 26, 2018

This is not working value.toLocaleString(undefined, { maximumFractionDigits: maxFractionalDigits, minimumSignificantDigits: significantDigits } nor value.toLocaleString(undefined, { maximumFractionalDigits: places })

Copy link
Contributor

@julienw julienw left a comment

Choose a reason for hiding this comment

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

I added a comment that seem to work. + some other comments to change more things in format-numbers.js.

And now you can remove formatNumberToString :)

src/utils/format-numbers.js Show resolved Hide resolved
? _formatIntegerNumber
: _formatDecimalNumber;
const formattedTotalTime = formatNumber(totalTime, 2, 1);
const formattedSelfTime = formatNumber(selfTime, 2, 1);
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 you still want to check for _isIntegerInterval: then you can pass "0" as second parameter if it's true. And the first parameter should always be 1.

return value.toLocaleString(undefined, {
maximumSignificantDigits: significantDigits,
maximumFractionDigits: maxFractionalDigits,
});
}

export function formatPercent(value: number): string {
Copy link
Contributor

Choose a reason for hiding this comment

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

you can also change this function, and use { style: 'percent' } in the second argument of toLocaleString.

Then you can use this in src/profile-logic/call-tree.js to format the %age value as well.

Copy link
Author

Choose a reason for hiding this comment

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

Adding only { style:'percent' } is not giving correct results.

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 tell m what you tried and what this yields? Thanks!

Copy link
Author

@ghost ghost Oct 30, 2018

Choose a reason for hiding this comment

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

export function formatPercent(value: number): string { return value.toLocaleString(undefined, { style:'percent' }); }
This is not giving percentage in one point decimal

Copy link
Contributor

Choose a reason for hiding this comment

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

Of course not, because you need to give the right arguments to toLocaleString...

Copy link
Author

@ghost ghost Oct 30, 2018

Choose a reason for hiding this comment

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

return value.toLocaleString(undefined, { minimumFractionDigits: 1, style:'percent' }); is giving one point decimal but when we divide it should not give percentage in decimal

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 give me an example so that I can follow you better?

Copy link
Author

@ghost ghost Oct 30, 2018

Choose a reason for hiding this comment

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

<div className="tooltipLabel">
              Cells evicted:
            </div>
    -       15.9K / 26.6K (60%)
    +       15.9K / 26.6K (59.6%)

Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe formatPercent should take the number of maximumFractionDigits so that we could use it in different ways ?

Copy link
Author

Choose a reason for hiding this comment

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

minimumFractionalDigits seems to work

*/
* Note that numDigitsOnLeft can be negative when the first non-zero digit
* is on the right of the decimal point. 0.01 = -1
*/
Copy link
Contributor

Choose a reason for hiding this comment

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

note: I see you added a space in the indention, please remove it

return value.toLocaleString(undefined, {
maximumSignificantDigits: significantDigits,
maximumFractionDigits: maxFractionalDigits,
});
}

export function formatPercent(value: number): string {
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 tell m what you tried and what this yields? Thanks!

Copy link
Contributor

@julienw julienw left a comment

Choose a reason for hiding this comment

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

Hey Monika, thanks for the change!

I think that we can do better for formatPercent, see below for more explanations.

maxFractionalDigits
);

const formattedSelfTime = formatNumber(selfTime, 2, maxFractionalDigits);
Copy link
Contributor

Choose a reason for hiding this comment

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

I tried it and I think we should use 3 instead of 2 for these 2 calls, so that values like 13.3 are displayed. Previously we did it for all values (because toFixed(1) was used for all values), but for bigger values this is less useful.

return value.toLocaleString(undefined, {
minimumFractionDigits: minFractionalDigits,
style: 'percent',
});
Copy link
Contributor

Choose a reason for hiding this comment

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

I see there are a few differences with what we were doing before.
For example, in markers (see this profile, by hovering the "GCMajor" marker), you can see that some values like "66%" are now shown with "66.0%".

I tried other things like using maximumFractionDigits but this brings other issues.
For example, here is what we want in the markers tooltips:

  • 0.01356 => 0.0 (possibly 0.01)
  • 0.1356 => 0.1 (possibly 0.14)
  • 1.356 => 1.3
  • 13.56 => 13

This means that we can't use maximumSignificantDigits: 2 because we'd get 0.014 for the first example. We can't use maximumFractionDigits: 1 because we'd get 13.6 for the last example. This means we need something in-between, and that's what we did in formatNumbers above.

That's why I now think we should reuse formatNumbers above, exactly like the previous code did. This can be done if formatNumbers can take a style parameter with a default "decimal" for other uses, but so that we can pass percent in this function.

Then the parameter we pass to formatPercent could be the maxFractionalDigits we pass to formatNumbers directly, with a default of 1. We can also use significantDigits = 2 in the call like we did before.

timings.mmu_50ms,
formatPercent
{_markerDetail('gcmmu50ms', 'MMU 50ms', timings.mmu_50ms, x =>
formatPercent(x, 1)
Copy link
Contributor

Choose a reason for hiding this comment

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

1 is the default already, so you can use the existing code instead of changing it

@@ -117,7 +120,7 @@ export function formatValueTotal(
const value_total = formatNum(a) + ' / ' + formatNum(b);
let percent = '';
if (includePercent) {
percent = ' (' + formatPercent(a / b) + ')';
percent = ' (' + formatPercent(a / b, 0) + ')';
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 that with the previous change, then we don't need to change this code.

@ghost
Copy link
Author

ghost commented Nov 1, 2018

<div  className="tooltipLabel">
              Cells evicted
              :
            </div>
    -       15.9K / 26.6K (60%)
    +       15.9K / 26.6K (59.6%)``` 
not working in this case

Copy link
Contributor

@julienw julienw left a comment

Choose a reason for hiding this comment

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

Thanks fo the changes! We're nearly there :-)

Here are a few more changes to fix a problem I realized when testing it, and I believe this should also fix the problem in the tests you mentioned.

Thanks again!

@@ -25,12 +25,13 @@ import type { Microseconds, Milliseconds } from '../types/units';
export function formatNumber(
value: number,
significantDigits: number = 2,
maxFractionalDigits: number = 3
maxFractionalDigits: number = 3,
style: string = 'decimal'
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: because the style can be either 'percent' or 'decimal', this should be reflected in the Flow typing. Can you please replace this line by:

style: 'decimal' | 'percent' = 'decimal' 

*/
* Note that numDigitsOnLeft can be negative when the first non-zero digit
* is on the right of the decimal point. 0.01 = -1
*/
const numDigitsOnLeft = Math.floor(Math.log10(Math.abs(value))) + 1;
Copy link
Contributor

Choose a reason for hiding this comment

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

I realized something.
The value we pass for "percent" is something like 0.4 and not 40. Therefore numDigitsOnLeft is too small and we need to add 2 here when style is percent. Something like this:

  let numDigitsOnLeft = Math.floor(Math.log10(Math.abs(value))) + 1; 
  if (style === 'percent') {
    // We receive percent values as `0.4` but display them as `40`, so we
    // should add `2` here to account for this difference.
    numDigitsOnLeft += 2;
  }
  ...

Copy link
Contributor

Choose a reason for hiding this comment

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

I believe this should fix the difference we see in the tests.

Copy link
Author

Choose a reason for hiding this comment

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

<span
                        className="treeViewRowColumn treeViewFixedColumn totalTimePercent"
                        key="totalTimePercent"
    -                   title="100.0%"
    +                   title="100%"
                      >
    -                   100.0%
    +                   100%
                      </span>
                      <span
                        className="treeViewRowColumn treeViewFixedColumn totalTime"
                        key="totalTime"
                        title="1"
    @@ -226,13 +226,13 @@
                      }
                    >

Not working in this case.

Copy link
Contributor

Choose a reason for hiding this comment

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

But this is actually better :) 100.0 was bad!

You can update the snapshots by running yarn test -u.

@julienw julienw merged commit 1d92528 into firefox-devtools:master Nov 7, 2018
hashi93 pushed a commit to hashi93/perf.html that referenced this pull request Nov 12, 2018
…fox-devtools#1394)

Then these functions are used in a lot of places, especially in the call tree and in tooltips.

Fixes firefox-devtools#1322
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