Optimize luminance function as simple look-up#4437
Conversation
|
I forgot to mention: If the plan with USWDS v3 is to drop support for non-Dart SASS (i.e. use SASS module syntax), then this could also be solved by using the new built-in The main advantage of this implementation is that it works across all compilers. |
mejiaj
left a comment
There was a problem hiding this comment.
Pretty nice! Thanks for this.
I wonder if we should move the $luminance-values somewhere else. Either inside the function or to core/_variables.scss. Otherwise LGTM!
|
Thanks for the review, @mejiaj !
Yeah, I think that could make sense to move it to Keeping it outside the function might be a soft preference for me, since while I don't know how SASS optimizes variables within functions, I might worry if it's the sort of thing where the 255-entry list would be allocated/garbage collected for every call. |
That's a good point. Moving this to final review 🙂 |
For what it's worth, digging into this, it might be related to maximum integer size in Dart, causing the Example script to reproduce: @function factorial($value) {
$result: 1;
@if $value == 0 {
@return $result;
}
@for $index from 1 through $value {
$result: $result * $index;
@debug 'index #{$index}, result #{$result}';
}
@return $result;
}
@debug factorial(99); |
|
Thank you! |
|
@thisisdano @aduth Just wanted to pop in and say THANK YOU THANK YOU THANK YOU. It has always confused me why the CSS build step took so long in my application and this made a noticeable dent. |
Description
This pull request seeks to improve the performance of the
luminancefunction, which is currently implemented using a combination of math polyfills necessary to compute an fractional exponent value following the relative luminance formula.Additional information
Because the relative luminance formula uses the same calculation for each of the R(ed), G(reen), and B(lue) components of a color, and because RGB component values are guaranteed to be a value between 0 and 255, it is possible to reasonably pre-compute the result for each value between 0 and 255, allowing for a trivial O(1) dictionary lookup.
I calculated the results using the following JavaScript script:
Evaluated using Node.js:
Results
The performance of the previous implementation seemed to worsen exponentially based on the number of times it's called. In a reasonable benchmarking scenario of 20 calls, execution time is reduced by ~94%.
Benchmarking code:
Results, using Ruby Sass:
I had attempted to measure results in (native) Dart Sass, but the math of the previous logic seems to not work at all for me in Dart Sass, due to a division by zero (see related #4438). Thus, this refactoring could also serve as a bug fix for Dart Sass.
Before you hit Submit, make sure you’ve done whichever of these applies to you:
npm testand make sure the tests for the files you have changed have passed.