[SR-9323] KeyPaths are quite slow #51793
Labels
bug
A deviation from expected or documented behavior. Also: expected but undesirable behavior.
compiler
The Swift compiler in itself
performance
Attachment: Download
Additional Detail from JIRA
md5: 8a7995ec006b266bd138d8a19ef4ebed
is duplicated by:
Issue Description:
Description
Naively I always assumed KeyPaths are quite fast. In my head they were basically a tuple of two function pointers (a getter and a setter, both not capturing so
@convention(thin)
like) that get just handed around and applied. At least I assumed that would be some sort of fast path when it has enough information at compile-time.To see how fast/slow keypaths are, I made a quick benchmark which just incremented a struct member (
Int
) 100 M times. To have an idea what the theoretical maximum is, I compared that to a version that doesn't use key paths at all and just does `thing.x += 1` in a loop. (I checked the assembly and the compiler does spit out every single increment (for overflow checking) it does however unroll the loop five times). Anyway, the result is:Now I benchmarked that against KeyPaths
and the result is:
which is 200x the runtime of the original one. I used
Apple Swift version 5.0-dev (LLVM cbe8d5e28f, Clang 3452631569, Swift 201dcba300)
, before that it was even slower.Then I tried to understand why Keypaths are so slow and I created yet another benchmark which goes through a pretty naive approximation:
and the loop was
to my absolute surprise, that yielded better performance ("only" 47x slower):
To finish off, I benchmarked against what I thought would kind of approximate the implementation at least in a fast path (just handing two function pointers around):
with the loop just like above. That started to yield reasonable performance
which is only about 10x slower than the direct additions and I think that's reasonable because
INC
is a processor instruction which naturally is a bit faster than 'function call to read the value, increment, function call to write the value'. Also loop unrolling etc...Notes
Compiler
OS
macOS 10.14 on
Observations
I found {{ %5 = keypath $WritableKeyPath<SomeStruct, Int>, (root $SomeStruct; stored_property #SomeStruct.x : $Int) // users: %20, %8}} in the SIL which looks like the compiler has actually quite some understanding of key paths, so maybe there's hope they will soon be faster? 😉
Code
the structs/fake key paths were defined in a module
Foo
and all the calls were always from another moduleTestApp
in order not to get any inlining effects. But even with everything in one module, the slow versions didn't get faster at all.the whole code is attached (the .tar.gz and can be run with just
swift run -c release
), but is also here (note that everything below// MODULE: Foo
is in another module.The text was updated successfully, but these errors were encountered: