Skip to content

Conversation

@bitfaster
Copy link
Owner

@bitfaster bitfaster commented May 18, 2024

AfterAccessPolicy and DiscretePolicy both store the current time in a local Time variable to skip repeated calls to get the current time. On x86, this could result in a torn write/bad time value. Instead, use Interlocked read/write on 32bit.

Results are pretty close for x64, 3x penalty for x86 (this is still incredibly cheap, it's 3x slower than reading a register). This is still at least 2x faster than calling the function to get the time.

Method Jit Platform Runtime Mean Error StdDev Ratio
TimeOriginal RyuJit X64 .NET 6.0 0.2273 ns 0.0351 ns 0.0360 ns 1.00
Time2 RyuJit X64 .NET 6.0 0.2583 ns 0.0089 ns 0.0079 ns 1.16
TimeOriginal RyuJit X64 .NET Framework 4.8 0.0000 ns 0.0000 ns 0.0000 ns ?
Time2 RyuJit X64 .NET Framework 4.8 0.0137 ns 0.0223 ns 0.0239 ns ?
TimeOriginal LegacyJit X86 .NET Framework 4.8 2.4370 ns 0.1943 ns 0.1817 ns 1.00
Time2 LegacyJit X86 .NET Framework 4.8 7.8259 ns 0.1746 ns 0.1548 ns 3.25

Disassembly on X64 shows that assembly is identical for .NET6, and very similar for .NET 4.8, so the JIT is able to elide the branch and this does not introduce any overhead.

.NET 6.0.30 (6.0.3024.21525), X64 RyuJIT AVX2

; BitFaster.Caching.Benchmarks._32bitTImeTest.TimeOriginal()
;             return timeOrig.Last; 
;             ^^^^^^^^^^^^^^^^^^^^^
       mov       rax,26C40258DE0
       mov       rax,[rax]
       mov       rax,[rax+8]
       ret
; Total bytes of code 18

.NET 6.0.30 (6.0.3024.21525), X64 RyuJIT AVX2

; BitFaster.Caching.Benchmarks._32bitTImeTest.Time2()
;             return time.Last; 
;             ^^^^^^^^^^^^^^^^^
       mov       rax,1CCEE588DE8
       mov       rax,[rax]
       mov       rax,[rax+8]
       ret
; Total bytes of code 18

.NET Framework 4.8.1 (4.8.9241.0), X64 RyuJIT VectorSize=256

; BitFaster.Caching.Benchmarks._32bitTImeTest.TimeOriginal()
;             return timeOrig.Last; 
;             ^^^^^^^^^^^^^^^^^^^^^
       mov       rax,[141EBEC8]
       mov       rax,[rax+8]
       ret
; Total bytes of code 13

.NET Framework 4.8.1 (4.8.9241.0), X64 RyuJIT VectorSize=256

; BitFaster.Caching.Benchmarks._32bitTImeTest.Time2()
;             return time.Last; 
;             ^^^^^^^^^^^^^^^^^
       mov       rax,[13B2BED0]
       mov       edx,[rax]
       mov       rax,[rax+8]
       ret
; Total bytes of code 15

@coveralls
Copy link

coveralls commented May 18, 2024

Coverage Status

coverage: 99.13% (+0.003%) from 99.127%
when pulling a6b6c38 on users/alexpeck/ttime
into 80ba526 on main.

@bitfaster bitfaster marked this pull request as ready for review May 18, 2024 20:47
@bitfaster bitfaster merged commit df9eb53 into main May 18, 2024
@bitfaster bitfaster deleted the users/alexpeck/ttime branch May 18, 2024 21:14
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.

3 participants