Skip to content

Commit

Permalink
Apply Adam's suggestion of concatenating the strings. This allows CPU…
Browse files Browse the repository at this point in the history
… caches to hit
  • Loading branch information
Joannis committed May 10, 2024
1 parent 1f6d21b commit 6d56cad
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 21 deletions.
18 changes: 12 additions & 6 deletions Sources/Hummingbird/Router/Trie/RouterTrie.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@
@usableFromInline
enum TrieToken: Equatable, Sendable {
case null
case path(constantIndex: UInt16)
case capture(parameterIndex: UInt16)
case prefixCapture(parameterIndex: UInt16, suffixIndex: UInt16)
case suffixCapture(prefixIndex: UInt16, parameterIndex: UInt16)
case prefixWildcard(suffixIndex: UInt16)
case suffixWildcard(prefixIndex: UInt16)
case path(constantIndex: UInt32)
case capture(parameterIndex: UInt32)
case prefixCapture(parameterIndex: UInt32, suffixIndex: UInt32)
case suffixCapture(prefixIndex: UInt32, parameterIndex: UInt32)
case prefixWildcard(suffixIndex: UInt32)
case suffixWildcard(prefixIndex: UInt32)
case wildcard, recursiveWildcard
case deadEnd
}
Expand Down Expand Up @@ -49,6 +49,12 @@ struct Trie: Sendable {
@usableFromInline
var nodes = [TrieNode]()

@usableFromInline
var allParameters = String()

@usableFromInline
var allConstants = String()

@usableFromInline
var parameters = [Substring]()

Expand Down
8 changes: 5 additions & 3 deletions Sources/Hummingbird/Router/Trie/Trie+resolve.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ extension RouterTrie {
}

/// Match sibling node for path component
@usableFromInline
@inlinable
internal func matchComponent(
_ component: Substring,
atNodeIndex nodeIndex: inout Int,
Expand All @@ -82,11 +82,13 @@ extension RouterTrie {
return TrieNode(valueIndex: 0, token: .deadEnd, nextSiblingNodeIndex: .max)
}

private enum MatchResult {
@usableFromInline
enum MatchResult {
case match, mismatch, ignore, deadEnd
}

private func matchComponent(
@inlinable
func matchComponent(
_ component: Substring,
node: TrieNode,
parameters: inout Parameters
Expand Down
33 changes: 21 additions & 12 deletions Sources/Hummingbird/Router/Trie/Trie+serialize.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import NIOCore

extension RouterTrie {
@usableFromInline
@inlinable
static func serialize(
_ node: RouterPathTrieBuilder<Value>.Node,
trie: inout Trie,
Expand All @@ -27,23 +27,31 @@ extension RouterTrie {

let token: TrieToken

func setConstant(_ constant: Substring) -> UInt16 {
func setConstant(_ constant: Substring) -> UInt32 {
if let index = trie.constants.firstIndex(of: constant) {
return UInt16(index)
return UInt32(index)
} else {
let startIndex = trie.allConstants.endIndex
trie.allConstants.append(contentsOf: constant)
let endIndex = trie.allConstants.endIndex

let index = trie.constants.count
trie.constants.append(constant)
return UInt16(index)
trie.constants.append(trie.allConstants[startIndex ..< endIndex])
return UInt32(index)
}
}

func setParameter(_ parameter: Substring) -> UInt16 {
func setParameter(_ parameter: Substring) -> UInt32 {
if let index = trie.parameters.firstIndex(of: parameter) {
return UInt16(index)
return UInt32(index)
} else {
let startIndex = trie.allParameters.endIndex
trie.allParameters.append(contentsOf: parameter)
let endIndex = trie.allParameters.endIndex

let index = trie.parameters.count
trie.parameters.append(parameter)
return UInt16(index)
trie.parameters.append(trie.allParameters[startIndex ..< endIndex])
return UInt32(index)
}
}

Expand Down Expand Up @@ -92,7 +100,7 @@ extension RouterTrie {
trie.nodes[nodeIndex].nextSiblingNodeIndex = trie.nodes.count
}

@usableFromInline
@inlinable
static func serializeChildren(
of node: RouterPathTrieBuilder<Value>.Node,
trie: inout Trie,
Expand All @@ -105,14 +113,15 @@ extension RouterTrie {
}
}

@usableFromInline
@inlinable
internal static func highestPriorityFirst(lhs: RouterPathTrieBuilder<Value>.Node, rhs: RouterPathTrieBuilder<Value>.Node) -> Bool {
lhs.key.priority > rhs.key.priority
}
}

extension RouterPath.Element {
fileprivate var priority: Int {
@usableFromInline
var priority: Int {
switch self {
case .prefixCapture, .suffixCapture:
// Most specific
Expand Down
5 changes: 5 additions & 0 deletions Sources/Hummingbird/Router/TrieRouter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,13 @@ import HummingbirdCore

/// Trie Node. Each node represents one component of a URI path
@_spi(Internal) public final class Node {
@usableFromInline
let key: RouterPath.Element

@usableFromInline
var children: [Node]

@usableFromInline
var value: Value?

init(key: RouterPath.Element, output: Value?) {
Expand Down

0 comments on commit 6d56cad

Please sign in to comment.