Skip to content

P/Invoke TickCount64 for .NET Standard on Windows #578

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 10, 2024

Conversation

bitfaster
Copy link
Owner

@bitfaster bitfaster commented May 10, 2024

Note; this introduces a test hole: there are currently no tests that verify .NET standard when it is not running on Windows (we only execute NET4.8 on Windows to test .NET Standard). Since code coverage analysis only runs for .NET Core build targets, this is not observable in the code coverage report.

@bitfaster
Copy link
Owner Author

bitfaster commented May 10, 2024

Static bool check for OS is elided by the JIT on .NET 4.8.

Original code (v2.5.0 baseline)

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

; BitFaster.Caching.Benchmarks.TimeBenchmarks.DurationSinceEpoch()
       sub       rsp,28
;             return Duration.SinceEpoch();
;             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
       call      System.Diagnostics.Stopwatch.GetTimestamp()
       nop
       add       rsp,28
       ret
; Total bytes of code 15

Raw P/Invoke

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

; BitFaster.Caching.Benchmarks.TimeBenchmarks.PInvokeTickCount64()
       sub       rsp,28
       call      BitFaster.Caching.Benchmarks.TickCount64.GetTickCount64()
       nop
       add       rsp,28
       ret
; Total bytes of code 15

PInvoke method
BitFaster.Caching.Benchmarks.TickCount64.GetTickCount64()

New code (static bool check, then pinvoke)

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

; BitFaster.Caching.Benchmarks.TimeBenchmarks.DurationSinceEpoch()
       sub       rsp,28
;             return Duration.SinceEpoch();
;             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
       call      BitFaster.Caching.Duration.GetTickCount64()
       nop
       add       rsp,28
       ret
; Total bytes of code 15

PInvoke method
BitFaster.Caching.Duration.GetTickCount64()

@bitfaster
Copy link
Owner Author

Duration.SinceEpoch is almost identical to raw p/invoke:

BenchmarkDotNet v0.13.12, Windows 11 (10.0.22621.3447/22H2/2022Update/SunValley2)
Intel Xeon W-2133 CPU 3.60GHz, 1 CPU, 12 logical and 6 physical cores
  [Host]             : .NET Framework 4.8.1 (4.8.9232.0), X64 RyuJIT VectorSize=256
  .NET Framework 4.8 : .NET Framework 4.8.1 (4.8.9232.0), X64 RyuJIT VectorSize=256
Method Runtime Mean Error StdDev Ratio Code Size
DateTimeUtcNow .NET Framework 4.8 58.1916 ns 0.5423 ns 0.4529 ns 1.000 1,048 B
DateTimeOffsetUtcNow .NET Framework 4.8 69.9188 ns 0.2347 ns 0.1832 ns 1.201 11,579 B
EnvironmentTickCount .NET Framework 4.8 1.5896 ns 0.0619 ns 0.0579 ns 0.027 13 B
EnvironmentTickCount64 .NET Framework 4.8 0.0000 ns 0.0000 ns 0.0000 ns 0.000 3 B
PInvokeTickCount64 .NET Framework 4.8 10.0051 ns 0.2299 ns 0.2038 ns 0.172 15 B
StopWatchGetElapsed .NET Framework 4.8 25.6634 ns 0.5401 ns 0.6633 ns 0.444 171 B
StopWatchGetTimestamp .NET Framework 4.8 23.4942 ns 0.3226 ns 0.3018 ns 0.404 117 B
DurationSinceEpoch .NET Framework 4.8 10.2168 ns 0.2194 ns 0.1832 ns 0.176 15 B

@coveralls
Copy link

coveralls commented May 10, 2024

Coverage Status

coverage: 99.318%. remained the same
when pulling aa3ca98 on users/alexpeck/winpinvoke
into a825808 on main.

@bitfaster bitfaster merged commit 4223d10 into main May 10, 2024
13 checks passed
@bitfaster bitfaster deleted the users/alexpeck/winpinvoke branch May 10, 2024 23:34
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.

2 participants