-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[stdlib] Speed up bridged Dictionary instances #17742
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
Conversation
Dictionary’s native storage classes and _SwiftDeferredNSDictionary override -[NSDictionary getObjects:andKeys:] instead of its safer replacement, -[NSDictionary getObjects:andKeys:count:]. Overriding the correct method will considerably speed up some Cocoa operations on bridged dictionaries. rdar://problem/39285882
@swift-ci please test |
I don't think we have benchmarks for bridged dictionaries yet, but just in case: @swift-ci please benchmark |
stdlib/public/core/Dictionary.swift
Outdated
// The user is expected to provide a storage of the correct size | ||
if let unmanagedKeys = _UnmanagedAnyObjectArray(keys) { | ||
if let unmanagedObjects = _UnmanagedAnyObjectArray(objects) { | ||
// keys nonnull, objects nonnull | ||
for (offset: i, element: (key: key, value: val)) in full.enumerated() { | ||
unmanagedObjects[i] = _bridgeAnythingToObjectiveC(val) | ||
unmanagedKeys[i] = _bridgeAnythingToObjectiveC(key) | ||
guard i < count else { break } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the drive-by comment, but shouldn’t this be checked before assigning at position i
? (Same applies below)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gah, of course! Serves me right for not adding proper tests. Thanks!
Build comment file:Optimized (O)Regression (1)
Improvement (8)
No Changes (446)
Unoptimized (Onone)Regression (12)
Improvement (9)
No Changes (434)
Hardware Overview
|
I added new microbenchmarks to help us track performance. Copying elements in bulk out of an Improvement (1)
No Changes (2)
|
@swift-ci test |
stdlib/public/core/Dictionary.swift
Outdated
@@ -2961,6 +2975,7 @@ final internal class _SwiftDeferredNSDictionary<Key: Hashable, Value> | |||
// keys null, objects nonnull | |||
for position in 0..<bucketCount { | |||
if bridgedBuffer.isInitializedEntry(at: position) { | |||
guard i < count else { break } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you could eke out a one less loop iteration by checking this after you increment i -- and adding an early out above for count == 0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point! It can often be more than one iteration, too, since the loop skips over empty buckets.
|
…ementations This breaks out of the loop immediately when the last slot has been filled in the output buffer, skipping a final sequence of iterations over empty buckets.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! 🍔
@swift-ci test and merge |
Dictionary
’s native storage classes and_SwiftDeferredNSDictionary
override-[NSDictionary getObjects:andKeys:]
instead of its safer replacement,-[NSDictionary getObjects:andKeys:count:]
.Overriding the correct method will considerably speed up some Cocoa operations on bridged dictionaries.
rdar://problem/39285882