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

Feat: add first draft of optimize (closes #111) #114

Merged
merged 6 commits into from
Aug 9, 2020
Merged

Conversation

JPeer264
Copy link
Owner

No description provided.

@coveralls
Copy link

coveralls commented Mar 16, 2020

Coverage Status

Coverage increased (+0.06%) to 99.141% when pulling 25a36dc on feat/optimize into 22b8126 on master.

@JPeer264
Copy link
Owner Author

@X-Ryl669 I kinda need your help on this one (you seem to have a better understanding of this kind of algorithms). If you don't have the time it is ok, as the implementation is working. I just think I might miss something where we can save even more bytes.

In the function sortSelectors I wanted to implement the optimization for the selectors.

The basic idea of this function is that I will return a list of array of the new selectors (so the first entry will be a the second entry will be b, ...) - ids, classes, cssVariables, and keyframes have its own sortSelectors call.

Input is a list of selectors with their renamed selectors: [['first-id', 'a'], ['second-id', 'b']]. And the second parameter is the given statistic for either id, class, cssVariable or keyframe. Currently, I just use the second parameter, but I think I should also use the first parameter of this function somehow.

Now, I sort the selectors just based on their appearances but not based on their original translation. You think that would be enough? If so, I would remove the first parameter and just use the statistic object. I am also ok if you could come up with a whole new idea to sort them.

@X-Ryl669
Copy link
Contributor

X-Ryl669 commented Mar 17, 2020

Your intuition might seems correct at first, if I understand you well. One would think it'd be better to allocate the smallest selector to the occurrence whose count * lengthOfInitialSelector is maximum.

Yet, I think it's wrong:
For example, if you have this:

<div class='no'>whatever</div>
<div class='no'>whatever</div>
<div class='yesmen'>whatever</div>
<div class='yesmen'>whatever</div>

Let's say we have only a single "one letter" available for the selector.
If we only look to the occurrence count, no is not more present than yesmen, so in that case it would get the dual letter (let's say: aa), then yesmen would get a.
In that case, the total compression ratio is (2 * 2 (for aa) + 2 * 1 (for a)) / ( 2 * 2 (for no) + 2 * 6 (for yesmen)) = 0.375.
If you only take into account the occurrence count, you'd have allocated a for no then aa for yesmen, thus the compression ratio would have been: (2 * 1 + 2*2) / 16 = 0.375, that is... the exact same compression.

Thus the optimal compression ratio is computed by:
equation

The goal is to minimize the equation above.
The denominator is fixed (it does not depend on the choice we can do: it's only on the input text) thus for minimization we can ignore it.
On the numerator, we can only act on the length of the replaced selector.

Yet, any allocation we do for one selector's length will swap the gain for the other selector so, in the end, it's the same result.

Said differently, intuitively, one would count the compression as wrong idea
but it's wrong since the choice of mapped selector is not independent.
The right equation is really:
equation

So if I were you, you would sort only on the statistic (occurrence count) and allocate the minimal selector length to the items with the highest occurrence, that is, ignore the initial mapped selector, so let's say you have:

  • first-id seen 25 times
  • second-id seen 32 times
  • third-id seen 29 times

You'll need to build a map inverse-sorted by occurrence:

  • 32 => second-id
  • 29 => third-id
  • 25 => first-id

Then, call a reset name generator in this order (since the generator will allocate the smallest selectors first)

  • second-id => a
  • third-id => b
  • first-id => c

@JPeer264 JPeer264 changed the title [WIP] Feat: add first draft of optimize (closes #111) Feat: add first draft of optimize (closes #111) Aug 9, 2020
@JPeer264 JPeer264 merged commit 6dc7b0c into master Aug 9, 2020
@JPeer264 JPeer264 deleted the feat/optimize branch August 9, 2020 06:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants