Skip to content

Comments

Optimise FlatDictionary init for scenarios where no values are stored and llow inlining access#456

Open
Joannis wants to merge 2 commits intomainfrom
jo/optimise-init-of-flatdictionary
Open

Optimise FlatDictionary init for scenarios where no values are stored and llow inlining access#456
Joannis wants to merge 2 commits intomainfrom
jo/optimise-init-of-flatdictionary

Conversation

@Joannis
Copy link
Member

@Joannis Joannis commented May 19, 2024

This provides specialized access to the type, and virtually eliminates its presence from routes where a flat dictionary is not used. This affects the route parameters primarily, but helps in particular because CoreRequestContext always starts out with an empty Parameters instance.

…. Allow inlining access, providing specialized access
@Joannis Joannis requested a review from adam-fowler May 19, 2024 20:36
@adam-fowler
Copy link
Member

Empty arrays don't allocate any memory, so I'm not sure this is going to be a saving, as you have added a branch whenever accessing the parameters now

@Joannis
Copy link
Member Author

Joannis commented May 20, 2024

I think my measurements are macOS-specific then. Swift arrays do seem to have a different (default) implementation from the ContiguousArray one

Copy link
Member

@adam-fowler adam-fowler left a comment

Choose a reason for hiding this comment

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

Looks good, some minor change requests


@usableFromInline
struct Storage {
@usableFromInline internal /* private */ var elements: [Element]
Copy link
Member

Choose a reason for hiding this comment

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

Can we remove the commented out /* private */ if we require everything to be internal

/// Access element at specific position
public subscript(_ index: Index) -> Element { return self.elements[index] }
@inlinable
public subscript(_ index: Index) -> Element { return self.storage!.elements[index] }
Copy link
Member

Choose a reason for hiding this comment

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

! isn't ideal here, perhaps we should add a precondition that storage exist and provide an out of range message or something similar, given the index will be out of range

/// Returns the index immediately after the given index
public func index(after index: Index) -> Index { self.elements.index(after: index) }
@inlinable
public func index(after index: Index) -> Index { index + 1 }
Copy link
Member

Choose a reason for hiding this comment

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

Any reason you changed this? I know index+1 is correct in most cases, but what is the expected result when index == endIndex?

set {
let hashKey = Self.hashKey(key)
if let index = hashKeys.firstIndex(of: hashKey) {
if var storage, let index = storage.hashKeys.firstIndex(of: hashKey) {
Copy link
Member

Choose a reason for hiding this comment

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

The ordering of the if statements here is slightly confusing. Currently you test for the existence of storage twice when the key doesn't exist. Perhaps it should be

if let storage {
    // do stuff when storage already exists
} else {
    // create storage if needed
}

}

// FlatDictionary is Sendable when Key and Value are Sendable
extension FlatDictionary.Storage: Sendable where Key: Sendable, Value: Sendable {}
Copy link
Member

Choose a reason for hiding this comment

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

I added this in to get rid of a Sendable warning

@adam-fowler
Copy link
Member

@Joannis can I close this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants