File tree Expand file tree Collapse file tree 2 files changed +29
-1
lines changed Expand file tree Collapse file tree 2 files changed +29
-1
lines changed Original file line number Diff line number Diff line change @@ -681,13 +681,31 @@ extension _NativeSet {
681
681
internal __consuming func subtracting< S: Sequence > ( _ other: S ) -> _NativeSet
682
682
where S. Element == Element {
683
683
guard count > 0 else { return _NativeSet ( ) }
684
+
685
+ // Find one item that we need to remove before creating a result set.
686
+ var it = other. makeIterator ( )
687
+ var bucket : Bucket ? = nil
688
+ while let next = it. next ( ) {
689
+ let ( b, found) = find ( next)
690
+ if found {
691
+ bucket = b
692
+ break
693
+ }
694
+ }
695
+ guard let bucket = bucket else { return self }
696
+
684
697
// Rather than directly creating a new set, calculate the difference in a
685
698
// bitset first. This ensures we hash each element (in both sets) only once,
686
699
// and that we'll have an exact count for the result set, preventing
687
700
// rehashings during insertions.
688
701
return _UnsafeBitset. withTemporaryCopy ( of: hashTable. bitset) { difference in
689
702
var remainingCount = self . count
690
- for element in other {
703
+
704
+ let removed = difference. uncheckedRemove ( bucket. offset)
705
+ _internalInvariant ( removed)
706
+ remainingCount -= 1
707
+
708
+ while let element = it. next ( ) {
691
709
let ( bucket, found) = find ( element)
692
710
if found {
693
711
if difference. uncheckedRemove ( bucket. offset) {
Original file line number Diff line number Diff line change @@ -1158,6 +1158,16 @@ extension Set {
1158
1158
/// - Returns: A new set.
1159
1159
@inlinable
1160
1160
public __consuming func subtracting( _ other: Set < Element > ) -> Set < Element > {
1161
+ // Heuristic: if `other` is small enough, it's better to make a copy of the
1162
+ // set and remove each item one by one. (The best cutoff point depends on
1163
+ // the `Element` type; the one below is an educated guess.) FIXME: Derive a
1164
+ // better cutoff by benchmarking.
1165
+ if other. count <= self . count / 8 {
1166
+ var copy = self
1167
+ copy. _subtract ( other)
1168
+ return copy
1169
+ }
1170
+ // Otherwise do a regular subtraction using a temporary bitmap.
1161
1171
return self . _subtracting ( other)
1162
1172
}
1163
1173
You can’t perform that action at this time.
0 commit comments