-
-
Notifications
You must be signed in to change notification settings - Fork 959
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
Dynamic OperationsPerInvoke
#258
Comments
@AndreyAkinshin Any idea when this is gonna be implemented? Cause we really need it. If you didnt started already I can tell @jbayardo to implement it and send the PR. |
Hi @redknightlois. It seems easy to implement but I'm not sure about API. Do you have any ideas how it should look? Also, I want to add an ability to specify dynamic Params (a method which returns values for Params field/property instead of a constant array). It would be cool to use the same approach for the both cases. |
For OperationsPerInvoke: My preference is for the benchmark method to return an |
I use returning values to avoid dead code elimination issues, so the result approach could not be used generically. Having an |
@redknightlois while I also used return value as an attempt to prevent dead code elimination, I feel there could be a more explicit way (e.g. Using return value has the following advantages: it's still specified in the benchmark method, does not require further reflection, can be easily extended to async ( |
If it can be done, it is actually a very good idea to have a Probably it could be done with something like this: [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization | MethodImplOptions.PreserveSig)]
public void PreventElimination<T>(T value)
{ } We should look into the assembler to be sure, but sounds like a viable thing. |
@AndreyAkinshin : Just realized that in order for this to be backwards-compatible, the benchmark method should still be tagged with an attribute (e.g. Fiddling with code now. |
I think, we shouldn't use the returned value as
@redknightlois, we will have such method in So, I suggest to continue to use returning values to avoid dead code elimination, and come up with another way to specify |
Any further news on this? |
@dazinator, I definitely want to implement it in the nearest future, but I still don't know how the API should look like. |
How about yielding an IEnumerable<>, where each item yielded would represent one operation and therefore the total operations would be something doing a Count() on the other end.. I just raised an issue showing that kind of pattern. #323 |
@AndreyAkinshin |
If the benchmark method yielded an OperationResult, that wouldn't need any attributes either.. ? |
@adamsitnik what do you think, is it possible to easily solve this issue with the same approach which we are using for dynamic values in params? |
@AndreyAkinshin I am not sure if I understand the idea. When the user writes a benchmark, the number of Is the value always the same for all iterations? |
The value should be the same for all iteration, otherwise API will be too complicated and it will be very hard to provide good accuracy in the general case. I think we should support cases when OperationsPerInvoke is discovered in GlobalSetup. Thus, this value can depend on external data (e.g. files or database) or on param values. |
I can see that it would be nice to allow the users to "return" something from the benchmarks. Some people want to check the size of compressed file (to add the size to the perf comparison), some want to add something else (like information about vectorization support). I will try to come up with some universal solution which is not going to affect our accuracy |
I am against this idea of using |
@AndreyAkinshin about return values |
|
@AndreyAkinshin I completely do agree with all of those - the feature, even if implemented should not spoil benchmark results. At the same time the current implementation does allow to cover at least one case for (almost) free, it looks like a low-hanging fruit for me. If this is just a coincidence and the |
The question is not about an easy way to implement it in BenchmarkDotNet. The question is about good API which doesn't provoke new problems. And it's always hard to change the API because it brakes existed benchmarks. I know, it's hard to come up with a perfect API in advance, but we should try. I think it should be consistent (if we use returned values for one purpose and other ways for all other tasks, it's not consistent), it should be obvious, it shouldn't provoke bad benchmark design. I think that it will be better to provide a common way for all additional columns. And we should do it in |
My initial idea was: [Benchmark]
public int CompressA() => magic();
[ExtraResults(nameof(CompressA))]
public IDictionary<string, string> ExtraDataA()
=> new Dictionary<string, string>()
{
{ "benchAcompressSize", CompressA().ToString() },
{ "anotherInterestingThing", "itsValue" }
}; this extra method would be executed once, after stoping the watch, before last iteration/global cleanup. Then serialized and available in the results, so people could use sth like this in the columns: public class MyColumn : IColumn
{
public string GetValue(Summary summary, Benchmark benchmark)
=> summary.ExtraResults[benchmark].GetValue("theKey");
} |
@adamsitnik, it looks ok. Anyway, I don't have better ideas. Let's try to implement it. |
The solution proposed by @adamsitnik would also be a solution to #784 (?) |
As a workaround- I've resorted to using a Source Generator that creates a class named BenchmarkConstants where I have all of the dynamically calculated stuff (like the size of my Enums) placed as constants. |
I load a list of strings externally as data for my benchmarks. My goal is to measure average time for me to process one string. Of course the data is loaded before benchmarking, but since it happens at runtime, I cannot supply
OperationsPerInvoke
attribute param toBenchmarkAttribute
, which requires compile-time constant. Is there a way around?The text was updated successfully, but these errors were encountered: