-
-
Notifications
You must be signed in to change notification settings - Fork 978
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
Trivial methods can cause BDN to run only 1 iteration, skip pilot phase, and ignore most attributes #1337
Comments
Just managed to capture the generated executables by simply breaking the the BDN process with Ctrl-C. I decompiled it using Reflector, dumped the output and compared it byte-for-byte: they are the same. My initial thought was that it had something to do with the autogenerated code, but it looks now as if the invocation engine has a problem here. Let me know if I can provide more/better information, I'd love to get to the bottom of this as it is a real showstopper at the moment (simply put: in my main project I cannot reliably run BDN as I keep hitting this issue). |
Here's a much simpler example of how this can go mind-numbingly wrong: namespace BenchMarkBug
open BenchmarkDotNet.Attributes
open BenchmarkDotNet.Running
module Test =
let createOnceAndRun3 =
let foo = sprintf "test %A" "test"
fun() -> true
[<IterationTime(120.)>]
[<SimpleJob()>]
type BenchmarkPatterns() =
let foo =
let foo = sprintf "" // remove this line, or remove the function 'foo' to make it work, or fail
()
[<Benchmark>]
static member old_Star() =
Test.createOnceAndRun3()
|> ignore
module Main =
[<EntryPoint>]
let main _ =
BenchmarkRunner.Run<BenchmarkPatterns>()
|> ignore
0 // return success Observations:
This suggests it has something to do with how BDN initializes assemblies, and may skip over the initialization that is required by first module access by F# projects. But I admit, I'm still very much guessing. It is puzzling. |
Please excuse me for the delay. I've sent a fix: #1573 |
…n lasts longer than IterationTime (#1573) * add the test * if the Jitting took more than IterationTime but still less than 1s (a magic number based on observations of the reported bug) we call it one more time to see if Jitting itself has not dominated the first invocation if it did, it shoud NOT be a single invocation engine (fixes #837, fixes #1337 and fixes #1338)
EDIT 1: see my second comment, I just found a muuuuch easier repro with FSharp that doesn't involve any inref/byref/outref at all, and success is dependent on dummy functions being present.
EDIT 2: in a follow-up issue I explained the likely cause of this being PR #760, that it incorrectly marks micro-tests as RunOncePerIteration.
EDIT 3: This issue is written from an F# standpoint, but the same issue can be exhibited with C# code (that wasn't obvious when I first wrote this).
I've tested the following code with almost any kind of job, different versions of BDN and differents sets of attributes. Changing, for instance, the line
sprintf "%A"
intosprintf "%s"
runs correctly. I checked the IL, but couldn't find reasonable differences.Copy/paste the following in a new .NET Framework F# project (version of .NET doesn't matter):
The above code may seem contrived, but I came to it by attempting to get a minimal working example of the observed behavior. Depending on the chosen attributes, it will show erroneous behavior or succeed. When it fails, adding
KeepBenchmarkFiles
has no effect (they are not kept, or at least I cannot find them), making it harder to diagnose.I've made the following observations that seem to be of influence:
byref
,out
,outref
arguments in the function return value (the example calls the mutable function, but it also shows this behavior if you just return that value, i.e. remove()
invalue()
)."%A"
with"%s"
will change the overall behavior entirely)IterationTime
, it worksA workaround is: assign these values inside a Setup or constructor member. Though you still have to be careful, I came across the "1 iteration per cycle" issue multiple times.
Example of expected output:
Example of unexpected output
As can be observed below, the
WorkloadPilot
phase is skipped, and it consistently stays at1 op
.I'm currently at my limit of how to further investigate this. The code, when compiled and run by hand and not through BDN works correctly. There's no
unsafe
involved. I searched the internet and the issues, but had trouble using any reasonable keywords, apologies if this is a known issue.The text was updated successfully, but these errors were encountered: