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 {
681681 internal __consuming func subtracting< S: Sequence > ( _ other: S ) -> _NativeSet
682682 where S. Element == Element {
683683 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+
684697 // Rather than directly creating a new set, calculate the difference in a
685698 // bitset first. This ensures we hash each element (in both sets) only once,
686699 // and that we'll have an exact count for the result set, preventing
687700 // rehashings during insertions.
688701 return _UnsafeBitset. withTemporaryCopy ( of: hashTable. bitset) { difference in
689702 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 ( ) {
691709 let ( bucket, found) = find ( element)
692710 if found {
693711 if difference. uncheckedRemove ( bucket. offset) {
Original file line number Diff line number Diff line change @@ -1158,6 +1158,16 @@ extension Set {
11581158 /// - Returns: A new set.
11591159 @inlinable
11601160 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.
11611171 return self . _subtracting ( other)
11621172 }
11631173
You can’t perform that action at this time.
0 commit comments