Use string counts to short-circuit string comparisons

Wouldn't that make String un-Sendable? Or will storing the hash trigger a copy-on-write? Maybe use atomic read and write for the hash so the worse that can happen is two threads computing the hash in parallel and overwriting with the same value.

There's always a trade-off: writing the hash is not free and will slow things down for no reason in cases you aren't going to reuse this hash later.


You could however use that strategy locally where it makes sense, like when populating a set or dictionary, by using a wrapper type like this one:

struct PreHashed<Value: Hashable>: Hashable {
	init(_ value: Value) {
		self.value = value
		self.hashValue = value.hashValue
	}
	var value: Value {
		didSet { hashValue = value.hashValue }
	}
	var hashValue: Int

	func hash(into hasher: inout Hasher) {
		hasher.combine(hashValue)
	}
	static func == (a: PreHashed, b: PreHashed) -> Bool {
		// fast path checking hashValue first
		a.hashValue == b.hashValue && a.value == b.value
	}
}

var a = Set([PreHashed("Hello"), PreHashed("World")])
assert(a.contains(PreHashed("Hello"))

While this pre-hashing can make sense for strings, it does not for integers which are too trivial to hash to benefit from a stored hash. Trade-offs again.

2 Likes