Skip to content

Commit 042e7e9

Browse files
committed
PreTrainedTokenizer: use thread-safe cache for compiled Jinja templates
1 parent 68e3879 commit 042e7e9

File tree

1 file changed

+12
-20
lines changed

1 file changed

+12
-20
lines changed

Sources/Tokenizers/Tokenizer.swift

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import Foundation
99
import Hub
1010
import Jinja
11+
import os
1112

1213
/// A type alias for chat messages, represented as key-value pairs.
1314
public typealias Message = [String: any Sendable]
@@ -609,11 +610,8 @@ public class PreTrainedTokenizer: @unchecked Sendable, Tokenizer {
609610

610611
private let cleanUpTokenizationSpaces: Bool
611612

612-
/// Cache for compiled Jinja templates keyed by their literal template string
613-
private var compiledChatTemplateCache: [String: Template] = [:]
614-
615-
/// Lock to protect the compiled chat template cache from concurrent access
616-
private let cacheLock = NSLock()
613+
/// Thread-safe cache for compiled Jinja templates keyed by their literal template string
614+
private let templateCache = OSAllocatedUnfairLock(initialState: [String: Template]())
617615

618616
/// Initializes a tokenizer from Hugging Face configuration files.
619617
///
@@ -775,28 +773,22 @@ public class PreTrainedTokenizer: @unchecked Sendable, Tokenizer {
775773
}
776774

777775
private func compiledTemplate(for templateString: String) throws -> Template {
778-
// Fast path: check cache under lock
779-
cacheLock.lock()
780-
if let cached = compiledChatTemplateCache[templateString] {
781-
cacheLock.unlock()
776+
// Fast path: check cache
777+
if let cached = templateCache.withLock({ $0[templateString] }) {
782778
return cached
783779
}
784-
cacheLock.unlock()
785780

786781
// Compile template outside of lock to avoid holding lock during expensive operation
787782
let compiled = try Template(templateString)
788783

789-
// Insert into cache under lock (using double-checked locking pattern)
790-
cacheLock.lock()
791-
defer { cacheLock.unlock() }
792-
793-
// Check again in case another thread compiled the same template
794-
if let cached = compiledChatTemplateCache[templateString] {
795-
return cached
784+
// Insert into cache (double-checked in case another thread compiled the same template)
785+
return templateCache.withLock { cache in
786+
if let cached = cache[templateString] {
787+
return cached
788+
}
789+
cache[templateString] = compiled
790+
return compiled
796791
}
797-
798-
compiledChatTemplateCache[templateString] = compiled
799-
return compiled
800792
}
801793

802794
func preTokenize(_ text: String, options: PreTokenizerOptions) -> [String] {

0 commit comments

Comments
 (0)