Skip to content

Commit d5d196a

Browse files
committed
Merge pull request #2417 from swiftix/new-indexing-model-regression-fixes
Fix some Set-related performance regressions introduced by the new in…
2 parents af64977 + b555642 commit d5d196a

File tree

1 file changed

+76
-6
lines changed

1 file changed

+76
-6
lines changed

stdlib/public/core/HashedCollections.swift.gyb

Lines changed: 76 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,11 @@ internal protocol _HashStorage {
229229
@discardableResult
230230
mutating func updateValue(_ value: Value, forKey key: Key) -> Value?
231231

232+
@discardableResult
233+
mutating func insert(
234+
_ value: Value, forKey key: Key
235+
) -> (inserted: Bool, memberAfterInsert: Value)
236+
232237
@discardableResult
233238
mutating func remove(at index: Index) -> SequenceElement
234239

@@ -577,12 +582,7 @@ public struct Set<Element : Hashable> :
577582
public mutating func insert(
578583
_ newMember: Element
579584
) -> (inserted: Bool, memberAfterInsert: Element) {
580-
// FIXME: optimize this to do just one lookup
581-
if let i = index(of: newMember) {
582-
return (inserted: false, memberAfterInsert: self[i])
583-
}
584-
_variantStorage.updateValue(newMember, forKey: newMember)
585-
return (inserted: true, memberAfterInsert: newMember)
585+
return _variantStorage.insert(newMember, forKey: newMember)
586586
}
587587

588588
/// Inserts `newMember` unconditionally.
@@ -2730,6 +2730,14 @@ struct _Native${Self}Storage<${TypeParametersDecl}> :
27302730
"don't call mutating methods on _Native${Self}Storage")
27312731
}
27322732

2733+
@discardableResult
2734+
internal mutating func insert(
2735+
_ value: Value, forKey key: Key
2736+
) -> (inserted: Bool, memberAfterInsert: Value) {
2737+
_sanityCheckFailure(
2738+
"don't call mutating methods on _Native${Self}Storage")
2739+
}
2740+
27332741
@discardableResult
27342742
internal mutating func remove(at index: Index) -> SequenceElement {
27352743
_sanityCheckFailure(
@@ -3421,6 +3429,13 @@ internal struct _Cocoa${Self}Storage : _HashStorage {
34213429
_sanityCheckFailure("cannot mutate NS${Self}")
34223430
}
34233431

3432+
@discardableResult
3433+
internal mutating func insert(
3434+
_ value: Value, forKey key: Key
3435+
) -> (inserted: Bool, memberAfterInsert: Value) {
3436+
_sanityCheckFailure("cannot mutate NS${Self}")
3437+
}
3438+
34243439
@discardableResult
34253440
internal mutating func remove(at index: Index) -> SequenceElement {
34263441
_sanityCheckFailure("cannot mutate NS${Self}")
@@ -3843,6 +3858,61 @@ internal enum _Variant${Self}Storage<${TypeParametersDecl}> : _HashStorage {
38433858
}
38443859
}
38453860

3861+
internal mutating func nativeInsert(
3862+
_ value: Value, forKey key: Key
3863+
) -> (inserted: Bool, memberAfterInsert: Value) {
3864+
var (i, found) = asNative._find(key, startBucket: asNative._bucket(key))
3865+
3866+
if found {
3867+
%if Self == 'Set':
3868+
return (inserted: false, memberAfterInsert: asNative.key(at: i.offset))
3869+
%elif Self == 'Dictionary':
3870+
return (inserted: false, memberAfterInsert: asNative.value(at: i.offset))
3871+
%end
3872+
}
3873+
3874+
let minCapacity = NativeStorage.minimumCapacity(
3875+
minimumCount: asNative.count + 1,
3876+
maxLoadFactorInverse: asNative.maxLoadFactorInverse)
3877+
3878+
let (_, capacityChanged) = ensureUniqueNativeStorage(minCapacity)
3879+
if capacityChanged {
3880+
i = asNative._find(key, startBucket: asNative._bucket(key)).pos
3881+
}
3882+
3883+
%if Self == 'Set':
3884+
asNative.initializeKey(key, at: i.offset)
3885+
asNative.count += 1
3886+
%elif Self == 'Dictionary':
3887+
asNative.initializeKey(key, value: value, at: i.offset)
3888+
asNative.count += 1
3889+
%end
3890+
3891+
return (inserted: true, memberAfterInsert: value)
3892+
}
3893+
3894+
@discardableResult
3895+
internal mutating func insert(
3896+
_ value: Value, forKey key: Key
3897+
) -> (inserted: Bool, memberAfterInsert: Value) {
3898+
3899+
if _fastPath(guaranteedNative) {
3900+
return nativeInsert(value, forKey: key)
3901+
}
3902+
3903+
switch self {
3904+
case .native:
3905+
return nativeInsert(value, forKey: key)
3906+
case .cocoa(let cocoaStorage):
3907+
#if _runtime(_ObjC)
3908+
migrateDataToNativeStorage(cocoaStorage)
3909+
return nativeInsert(value, forKey: key)
3910+
#else
3911+
_sanityCheckFailure("internal error: unexpected cocoa ${Self}")
3912+
#endif
3913+
}
3914+
}
3915+
38463916
/// - parameter idealBucket: The ideal bucket for the element being deleted.
38473917
/// - parameter offset: The offset of the element that will be deleted.
38483918
/// Precondition: there should be an initialized entry at offset.

0 commit comments

Comments
 (0)