Thanks to visit codestin.com
Credit goes to github.com

Skip to content

fix KeySet.hashCode; enable multiple web tests #52861

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

Merged
merged 2 commits into from
Mar 20, 2020

Conversation

yjbanov
Copy link
Contributor

@yjbanov yjbanov commented Mar 18, 2020

Description

Fix and enable several tests that were previously skipped/broken on the Web.

@gspencergoog Please have a look at the change in shortcuts.dart. I think I fixed a hashCode bug, but want to make sure I'm not creating a bug :)

@yjbanov yjbanov requested review from ferhatb and gspencergoog March 18, 2020 23:31
@fluttergithubbot fluttergithubbot added a: accessibility Accessibility, e.g. VoiceOver or TalkBack. (aka a11y) a: tests "flutter test", flutter_test, or one of our tests f: material design flutter/packages/flutter/material repository. framework flutter/packages/flutter repository. See also f: labels. c: contributor-productivity Team-specific productivity, code health, technical debt. labels Mar 18, 2020
@yjbanov yjbanov changed the title fix and enable multiple web tests fix KeySet.hashCode; enable multiple web tests Mar 18, 2020
@skia-gold
Copy link

Gold has detected one or more untriaged digests on patchset 1.
Please triage them at https://flutter-gold.skia.org/search?issue=52861.

@override
int get hashCode {
return hashList(_keys);
// Keys are first sorted by hash to make sure the result of hashList is order independent.
if (_hashCode == null) {
Copy link
Contributor

Choose a reason for hiding this comment

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

No, as far as I know, this isn't necessary. HashSet is stable and not based on insertion order (LinkedHashSet, on the other hand is based on insertion order). Do you have an example that shows that it's not stable?

I switched to using a HashSet in #38936 to fix the bug I think you're trying to fix.

From the docs for HashSet:

"The iteration order of the set is not specified and depends on the hashcodes of the provided elements. However, the order is stable: multiple iterations over the same set produce the same order, as long as the set is not modified."

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The issue is that the insertion order is not what affects the computation of the hash code. What affects it is the order of elements we pass to hashList. While LinkedHashSet guarantees insertion order, HashSet does not guarantee any order. However, when you iterate over the elements of a HashSet it will return the elements in some order. So when we pass it to hashList the elements are iterated in some unpredictable order.

Copy link
Contributor

Choose a reason for hiding this comment

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

But a consistent order, based on the hash. Isn't that all we need? I mean, your sorted version is just that: consistent and based on the hash.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm, perhaps the difference is that on the VM HashSet iteration order depends only on the hashcodes of its elements while on the Web they do not. In general, AFAIK hash is not the only thing that determines the iteration order in a hash table. Two elements with different hashes can still end up in the same bucket, at which point there's no way to guarantee which of the two elements is extracted first. Let me poke at it for bit.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Confirmed. Here's the difference between Web and VM:

Web:
set2: a (hash: 97) b (hash: 98) c (hash: 99) d (hash: 100)
set3: d (hash: 100) c (hash: 99) b (hash: 98) a (hash: 97)

VM:
set2: a (hash: 97) b (hash: 98) c (hash: 99) d (hash: 100)
set3: a (hash: 97) b (hash: 98) c (hash: 99) d (hash: 100)

This was printed using:

print(set2.keys.map((k) => '${k.keyLabel} (hash: ${k.hashCode})').join(' '));
print(set3.keys.map((k) => '${k.keyLabel} (hash: ${k.hashCode})').join(' '));

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, you mean the first access to hashCode. So, the numbers are as follows:

  • 1-key sets improved by 16%
  • 2-key sets improved by 0.84%
  • 3-key sets regressed by 21%
  • 4-key sets regressed by 20%

This is first access only. If the hash code is used a second time anywhere at all, it's offset immediately by the cache.

How many 3- and 4-key sets do we have in Flutter?

Copy link
Contributor

@gspencergoog gspencergoog Mar 19, 2020

Choose a reason for hiding this comment

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

None, and I wouldn't expect many.

Copy link
Contributor

Choose a reason for hiding this comment

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

OK, let's go ahead with your changes. Seems like a win, generally.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks! I'll keep an eye on the benchmarks for regressions.

Copy link
Contributor

Choose a reason for hiding this comment

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

One thing that occurred to me: since you're now sorting things by hash, is it any faster to use the default Set implementation instead of HashSet? It might be able to be constructed faster.

@fluttergithubbot
Copy link
Contributor

Golden file changes have been found for this pull request. Click here to view and triage (e.g. because this is an intentional change).

Changes to golden files are considered breaking changes, so consult Handling Breaking Changes to proceed. While there are exceptions to this rule, if this patch modifies an existing golden file, it is probably not an exception. Only new golden file tests, or downstream changes like those from skia updates are considered non-breaking.

For more guidance, visit Writing a golden file test for package:flutter.

Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing.

Changes reported for pull request #52861 at sha 0d0cd82fd2e2c8f8cdd4fa1562471475f52400d6

@fluttergithubbot fluttergithubbot added c: API break Backwards-incompatible API changes will affect goldens Changes to golden files labels Mar 19, 2020
@yjbanov yjbanov force-pushed the enable-web-tests-2 branch from 0d0cd82 to 772f053 Compare March 19, 2020 17:36
@yjbanov yjbanov force-pushed the enable-web-tests-2 branch from 772f053 to a8fbfca Compare March 19, 2020 17:40
Copy link
Contributor

@gspencergoog gspencergoog left a comment

Choose a reason for hiding this comment

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

32384589-a60f0e74-c078-11e7-9bc1-e5b5287aea9d

@yjbanov yjbanov merged commit 5ea13b8 into flutter:master Mar 20, 2020
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 1, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
a: accessibility Accessibility, e.g. VoiceOver or TalkBack. (aka a11y) a: tests "flutter test", flutter_test, or one of our tests c: API break Backwards-incompatible API changes c: contributor-productivity Team-specific productivity, code health, technical debt. f: material design flutter/packages/flutter/material repository. framework flutter/packages/flutter repository. See also f: labels. will affect goldens Changes to golden files
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants