Skip to content

Add grouping by type #2163

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

Open
wants to merge 9 commits into
base: master
Choose a base branch
from

Conversation

YegorStepanov
Copy link
Contributor

Fixes #1164
Fixes #2022

Look at "Update existing tests" and "Update new tests" to see what has changed.

Fixes:

#1164 (comment)

Master:

|       Type | Method |     Mean |    Error |   StdDev | Ratio |
|----------- |------- |---------:|---------:|---------:|------:|
| Formatting |    Old | 15.52 ms | 0.306 ms | 0.017 ms |  1.00 |
|    Parsing |    Old | 15.54 ms | 1.847 ms | 0.101 ms |  1.00 |
| Formatting |    New | 15.48 ms | 2.415 ms | 0.132 ms |  1.00 |
|    Parsing |    New | 15.49 ms | 1.244 ms | 0.068 ms |  1.00 |

PR:

|       Type | Method |     Mean |    Error |   StdDev | Ratio |
|----------- |------- |---------:|---------:|---------:|------:|
| Formatting |    Old | 15.46 ms | 0.039 ms | 0.035 ms |  1.00 |
| Formatting |    New | 15.62 ms | 0.081 ms | 0.075 ms |  1.01 |
|            |        |          |          |          |       |
|    Parsing |    Old | 15.59 ms | 0.039 ms | 0.036 ms |  1.00 |
|    Parsing |    New | 15.54 ms | 0.076 ms | 0.071 ms |  1.00 |

#2022 (comment)

Master:

         Type |       Method | Pending |     Mean |   Error |  StdDev | LogicalGroup |
------------- |------------- |-------- |---------:|--------:|--------:|------------- |
   AsyncAwait |     Callback |   False | 102.0 ns | 6.09 ns | 1.58 ns |            * |
 ContinueWith |     Callback |   False | 102.0 ns | 6.09 ns | 1.58 ns |            * |
   AsyncAwait | ProtoPromise |   False | 202.0 ns | 6.09 ns | 1.58 ns |            * |
 ContinueWith | ProtoPromise |   False | 202.0 ns | 6.09 ns | 1.58 ns |            * |
   AsyncAwait |   RsgPromise |   False | 302.0 ns | 6.09 ns | 1.58 ns |            * |
 ContinueWith |   RsgPromise |   False | 302.0 ns | 6.09 ns | 1.58 ns |            * |
   AsyncAwait |         Task |   False | 402.0 ns | 6.09 ns | 1.58 ns |            * |
 ContinueWith |         Task |   False | 402.0 ns | 6.09 ns | 1.58 ns |            * |
   AsyncAwait |      UniTask |   False | 502.0 ns | 6.09 ns | 1.58 ns |            * |
 ContinueWith |      UniTask |   False | 502.0 ns | 6.09 ns | 1.58 ns |            * |
   AsyncAwait |    ValueTask |   False | 602.0 ns | 6.09 ns | 1.58 ns |            * |
 ContinueWith |    ValueTask |   False | 602.0 ns | 6.09 ns | 1.58 ns |            * |

PR

         Type |       Method | Pending |     Mean |   Error |  StdDev | LogicalGroup |
------------- |------------- |-------- |---------:|--------:|--------:|------------- |
   AsyncAwait |     Callback |   False | 102.0 ns | 6.09 ns | 1.58 ns |   AsyncAwait |
   AsyncAwait | ProtoPromise |   False | 202.0 ns | 6.09 ns | 1.58 ns |   AsyncAwait |
   AsyncAwait |   RsgPromise |   False | 302.0 ns | 6.09 ns | 1.58 ns |   AsyncAwait |
   AsyncAwait |         Task |   False | 402.0 ns | 6.09 ns | 1.58 ns |   AsyncAwait |
   AsyncAwait |      UniTask |   False | 502.0 ns | 6.09 ns | 1.58 ns |   AsyncAwait |
   AsyncAwait |    ValueTask |   False | 602.0 ns | 6.09 ns | 1.58 ns |   AsyncAwait |
              |              |         |          |         |         |              |
 ContinueWith |     Callback |   False | 102.0 ns | 6.09 ns | 1.58 ns | ContinueWith |
 ContinueWith | ProtoPromise |   False | 202.0 ns | 6.09 ns | 1.58 ns | ContinueWith |
 ContinueWith |   RsgPromise |   False | 302.0 ns | 6.09 ns | 1.58 ns | ContinueWith |
 ContinueWith |         Task |   False | 402.0 ns | 6.09 ns | 1.58 ns | ContinueWith |
 ContinueWith |      UniTask |   False | 502.0 ns | 6.09 ns | 1.58 ns | ContinueWith |
 ContinueWith |    ValueTask |   False | 602.0 ns | 6.09 ns | 1.58 ns | ContinueWith |

#1864 (comment)

Master

                  Type |          Method |   N |     Mean |   Error |  StdDev | LogicalGroup |
---------------------- |---------------- |---- |---------:|--------:|--------:|------------- |
          AsyncPending | ProtoPromise_V1 | 100 | 102.0 ns | 6.09 ns | 1.58 ns |            * |
         AsyncResolved | ProtoPromise_V1 | 100 | 102.0 ns | 6.09 ns | 1.58 ns |            * |
          AwaitPending | ProtoPromise_V1 | 100 | 102.0 ns | 6.09 ns | 1.58 ns |            * |
         AwaitResolved | ProtoPromise_V1 | 100 | 102.0 ns | 6.09 ns | 1.58 ns |            * |
 ContinueWithFromValue | ProtoPromise_V1 | 100 | 102.0 ns | 6.09 ns | 1.58 ns |            * |
   ContinueWithPending | ProtoPromise_V1 | 100 | 102.0 ns | 6.09 ns | 1.58 ns |            * |
  ContinueWithResolved | ProtoPromise_V1 | 100 | 102.0 ns | 6.09 ns | 1.58 ns |            * |
          AsyncPending | ProtoPromise_V2 | 100 | 202.0 ns | 6.09 ns | 1.58 ns |            * |
         AsyncResolved | ProtoPromise_V2 | 100 | 202.0 ns | 6.09 ns | 1.58 ns |            * |
          AwaitPending | ProtoPromise_V2 | 100 | 202.0 ns | 6.09 ns | 1.58 ns |            * |
         AwaitResolved | ProtoPromise_V2 | 100 | 202.0 ns | 6.09 ns | 1.58 ns |            * |
 ContinueWithFromValue | ProtoPromise_V2 | 100 | 202.0 ns | 6.09 ns | 1.58 ns |            * |
   ContinueWithPending | ProtoPromise_V2 | 100 | 202.0 ns | 6.09 ns | 1.58 ns |            * |
  ContinueWithResolved | ProtoPromise_V2 | 100 | 202.0 ns | 6.09 ns | 1.58 ns |            * |

PR

                  Type |          Method |   N |     Mean |   Error |  StdDev |          LogicalGroup |
---------------------- |---------------- |---- |---------:|--------:|--------:|---------------------- |
          AsyncPending | ProtoPromise_V1 | 100 | 102.0 ns | 6.09 ns | 1.58 ns |          AsyncPending |
          AsyncPending | ProtoPromise_V2 | 100 | 202.0 ns | 6.09 ns | 1.58 ns |          AsyncPending |
                       |                 |     |          |         |         |                       |
         AsyncResolved | ProtoPromise_V1 | 100 | 102.0 ns | 6.09 ns | 1.58 ns |         AsyncResolved |
         AsyncResolved | ProtoPromise_V2 | 100 | 202.0 ns | 6.09 ns | 1.58 ns |         AsyncResolved |
                       |                 |     |          |         |         |                       |
          AwaitPending | ProtoPromise_V1 | 100 | 102.0 ns | 6.09 ns | 1.58 ns |          AwaitPending |
          AwaitPending | ProtoPromise_V2 | 100 | 202.0 ns | 6.09 ns | 1.58 ns |          AwaitPending |
                       |                 |     |          |         |         |                       |
         AwaitResolved | ProtoPromise_V1 | 100 | 102.0 ns | 6.09 ns | 1.58 ns |         AwaitResolved |
         AwaitResolved | ProtoPromise_V2 | 100 | 202.0 ns | 6.09 ns | 1.58 ns |         AwaitResolved |
                       |                 |     |          |         |         |                       |
 ContinueWithFromValue | ProtoPromise_V1 | 100 | 102.0 ns | 6.09 ns | 1.58 ns | ContinueWithFromValue |
 ContinueWithFromValue | ProtoPromise_V2 | 100 | 202.0 ns | 6.09 ns | 1.58 ns | ContinueWithFromValue |
                       |                 |     |          |         |         |                       |
   ContinueWithPending | ProtoPromise_V1 | 100 | 102.0 ns | 6.09 ns | 1.58 ns |   ContinueWithPending |
   ContinueWithPending | ProtoPromise_V2 | 100 | 202.0 ns | 6.09 ns | 1.58 ns |   ContinueWithPending |
                       |                 |     |          |         |         |                       |
  ContinueWithResolved | ProtoPromise_V1 | 100 | 102.0 ns | 6.09 ns | 1.58 ns |  ContinueWithResolved |
  ContinueWithResolved | ProtoPromise_V2 | 100 | 202.0 ns | 6.09 ns | 1.58 ns |  ContinueWithResolved |

#1864 (comment)

Master

                 Type |           Method |     Mean |   Error |  StdDev | LogicalGroup |
--------------------- |----------------- |---------:|--------:|--------:|------------- |
      ArrayBenchmarks |            Empty | 102.0 ns | 6.09 ns | 1.58 ns |            * |
      EmptyBenchmarks |  EnumerableEmpty | 102.0 ns | 6.09 ns | 1.58 ns |            * |
 EnumerableBenchmarks |            Empty | 102.0 ns | 6.09 ns | 1.58 ns |            * |
     StringBenchmarks | ConstructorArray | 102.0 ns | 6.09 ns | 1.58 ns |            * |
      EmptyBenchmarks |       ArrayEmpty | 202.0 ns | 6.09 ns | 1.58 ns |            * |
     StringBenchmarks |  ConstructorSpan | 202.0 ns | 6.09 ns | 1.58 ns |            * |

PR

                 Type |           Method |     Mean |   Error |  StdDev |         LogicalGroup |
--------------------- |----------------- |---------:|--------:|--------:|--------------------- |
      ArrayBenchmarks |            Empty | 102.0 ns | 6.09 ns | 1.58 ns |      ArrayBenchmarks |
                      |                  |          |         |         |                      |
      EmptyBenchmarks |  EnumerableEmpty | 102.0 ns | 6.09 ns | 1.58 ns |      EmptyBenchmarks |
      EmptyBenchmarks |       ArrayEmpty | 202.0 ns | 6.09 ns | 1.58 ns |      EmptyBenchmarks |
                      |                  |          |         |         |                      |
 EnumerableBenchmarks |            Empty | 102.0 ns | 6.09 ns | 1.58 ns | EnumerableBenchmarks |
                      |                  |          |         |         |                      |
     StringBenchmarks | ConstructorArray | 102.0 ns | 6.09 ns | 1.58 ns |     StringBenchmarks |
     StringBenchmarks |  ConstructorSpan | 202.0 ns | 6.09 ns | 1.58 ns |     StringBenchmarks |

Tests

Yes, that's a lot of tests, but now it's easy to change the ordering logic as there are a lot of cases covered.

For example, this change produces a better output, but it breaks output for OneBaseline in some test (it starts display baseline numbers instead a question mark):

- if (hasMultipleTypes)
+ if (hasMultipleTypes && explicitRules.IsEmpty())

Question

What is the correct table for this?

[GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByMethod)]
[LogicalGroupColumn, CategoriesColumn, BaselineColumn]
[BenchmarkCategory("A")]
[SimpleJob(id: "Job1"), SimpleJob(id: "Job2")]
public class Bench1
{
    [Params(10, 20)] public int Param;
    [Benchmark(Baseline = true)] public void Foo() { }
    [Benchmark] public void Bar() { }
}

[GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByMethod)]
[LogicalGroupColumn, CategoriesColumn, BaselineColumn]
[BenchmarkCategory("B")]
public class Bench2
{
    [Params(10, 20)] public int Param;
    [Benchmark(Baseline = true)] public void Foo() { }
    [Benchmark] public void Bar() { }
}

Master/PR output is:

   Type | Method |        Job | Categories | Param |     Mean |   Error |  StdDev | Ratio | RatioSD |                     LogicalGroup | Baseline |
------- |------- |----------- |----------- |------ |---------:|--------:|--------:|------:|--------:|--------------------------------- |--------- |
 Bench1 |    Foo |       Job1 |          A |    10 | 102.0 ns | 6.09 ns | 1.58 ns |  1.00 |    0.00 |       Foo-Bench1-[Param=10]-Job1 |      Yes | ^
        |        |            |            |       |          |         |         |       |         |                                  |          |
 Bench1 |    Foo |       Job2 |          A |    10 | 302.0 ns | 6.09 ns | 1.58 ns |  1.00 |    0.00 |       Foo-Bench1-[Param=10]-Job2 |      Yes |
        |        |            |            |       |          |         |         |       |         |                                  |          |
 Bench1 |    Foo |       Job1 |          A |    20 | 502.0 ns | 6.09 ns | 1.58 ns |  1.00 |    0.00 |       Foo-Bench1-[Param=20]-Job1 |      Yes | ^
        |        |            |            |       |          |         |         |       |         |                                  |          |
 Bench1 |    Foo |       Job2 |          A |    20 | 702.0 ns | 6.09 ns | 1.58 ns |  1.00 |    0.00 |       Foo-Bench1-[Param=20]-Job2 |      Yes |
        |        |            |            |       |          |         |         |       |         |                                  |          |
 Bench2 |    Foo | DefaultJob |          B |    10 | 102.0 ns | 6.09 ns | 1.58 ns |  1.00 |    0.00 | Foo-Bench2-[Param=10]-DefaultJob |      Yes | ^
        |        |            |            |       |          |         |         |       |         |                                  |          |
 Bench2 |    Foo | DefaultJob |          B |    20 | 302.0 ns | 6.09 ns | 1.58 ns |  1.00 |    0.00 | Foo-Bench2-[Param=20]-DefaultJob |      Yes | ^
        |        |            |            |       |          |         |         |       |         |                                  |          |
 Bench1 |    Bar |       Job1 |          A |    10 | 202.0 ns | 6.09 ns | 1.58 ns |     ? |       ? |       Bar-Bench1-[Param=10]-Job1 |       No | ^
        |        |            |            |       |          |         |         |       |         |                                  |          |
 Bench1 |    Bar |       Job2 |          A |    10 | 402.0 ns | 6.09 ns | 1.58 ns |     ? |       ? |       Bar-Bench1-[Param=10]-Job2 |       No |
        |        |            |            |       |          |         |         |       |         |                                  |          |
 Bench1 |    Bar |       Job1 |          A |    20 | 602.0 ns | 6.09 ns | 1.58 ns |     ? |       ? |       Bar-Bench1-[Param=20]-Job1 |       No | ^
        |        |            |            |       |          |         |         |       |         |                                  |          |
 Bench1 |    Bar |       Job2 |          A |    20 | 802.0 ns | 6.09 ns | 1.58 ns |     ? |       ? |       Bar-Bench1-[Param=20]-Job2 |       No |
        |        |            |            |       |          |         |         |       |         |                                  |          |
 Bench2 |    Bar | DefaultJob |          B |    10 | 202.0 ns | 6.09 ns | 1.58 ns |     ? |       ? | Bar-Bench2-[Param=10]-DefaultJob |       No | ^
        |        |            |            |       |          |         |         |       |         |                                  |          |
 Bench2 |    Bar | DefaultJob |          B |    20 | 402.0 ns | 6.09 ns | 1.58 ns |     ? |       ? | Bar-Bench2-[Param=20]-DefaultJob |       No | ^

BenchmarkLogicalGroupRule.ByCategory,
BenchmarkLogicalGroupRule.ByType,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ByType should be first by default, I think.

Copy link
Contributor Author

@YegorStepanov YegorStepanov Oct 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know :)

I reordered it and the output didn't change for the tests.

I tried to sort it twice - all tests are passed:

[GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByType)]
[GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByMethod)]
class A { }

I did it for

1) for each rule + ByType
2) for each rule + ByCategory
3) for each rule + ByMethod

but the output is same

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, stop

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everything is right, nothing has changed 🤔

Copy link
Collaborator

@timcassell timcassell Oct 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@YegorStepanov What types are you testing? Do the benchmarks have enough options that the table should actually be different for each group rule-set?

Copy link
Collaborator

@timcassell timcassell Oct 19, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would expect TwoBaselinesWithJobs111 and TwoBaselinesWithJobs222 to be the same. And TwoBaselinesWithJobs333 should order by Type first, then Method. For reasons I explained in my other comment.

Copy link
Collaborator

@timcassell timcassell Oct 19, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tbh, I'm starting to think ByType shouldn't even be override-able. Each Type is meant to be benchmarking a different function, so why would they be grouped any other way? [Edit] The only reason I can think of it needing to be changed is to put ByRuntime in front of it or vice-versa, but that doesn't currently exist. ByType should never be ordered after any of the existing logical group rules.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The output for TwoBaselinesWithJobs111 and TwoBaselinesWithJobs222 is the same (they are slightly differs in the LogicalGroup column).

ByCategory:

TwoBaselinesWithJobs111

   Type | Method |        Job | Categories | Param |     Mean |   Error |  StdDev | Ratio | RatioSD |                     LogicalGroup | Baseline |
------- |------- |----------- |----------- |------ |---------:|--------:|--------:|------:|--------:|--------------------------------- |--------- |
 Bench1 |    Foo |       Job1 |          A |    10 | 102.0 ns | 6.09 ns | 1.58 ns |  1.00 |    0.00 |       A-A-Bench1-[Param=10]-Job1 |      Yes | ^
 Bench1 |    Bar |       Job1 |          A |    10 | 202.0 ns | 6.09 ns | 1.58 ns |  1.98 |    0.02 |       A-A-Bench1-[Param=10]-Job1 |       No |
        |        |            |            |       |          |         |         |       |         |                                  |          |
 Bench1 |    Foo |       Job2 |          A |    10 | 302.0 ns | 6.09 ns | 1.58 ns |  1.00 |    0.00 |       A-A-Bench1-[Param=10]-Job2 |      Yes |
 Bench1 |    Bar |       Job2 |          A |    10 | 402.0 ns | 6.09 ns | 1.58 ns |  1.33 |    0.00 |       A-A-Bench1-[Param=10]-Job2 |       No |
        |        |            |            |       |          |         |         |       |         |                                  |          |
 Bench1 |    Foo |       Job1 |          A |    20 | 502.0 ns | 6.09 ns | 1.58 ns |  1.00 |    0.00 |       A-A-Bench1-[Param=20]-Job1 |      Yes | ^
 Bench1 |    Bar |       Job1 |          A |    20 | 602.0 ns | 6.09 ns | 1.58 ns |  1.20 |    0.00 |       A-A-Bench1-[Param=20]-Job1 |       No |
        |        |            |            |       |          |         |         |       |         |                                  |          |
 Bench1 |    Foo |       Job2 |          A |    20 | 702.0 ns | 6.09 ns | 1.58 ns |  1.00 |    0.00 |       A-A-Bench1-[Param=20]-Job2 |      Yes |
 Bench1 |    Bar |       Job2 |          A |    20 | 802.0 ns | 6.09 ns | 1.58 ns |  1.14 |    0.00 |       A-A-Bench1-[Param=20]-Job2 |       No |
        |        |            |            |       |          |         |         |       |         |                                  |          |
 Bench2 |    Foo | DefaultJob |          B |    10 | 102.0 ns | 6.09 ns | 1.58 ns |  1.00 |    0.00 | B-B-Bench2-[Param=10]-DefaultJob |      Yes | ^
 Bench2 |    Bar | DefaultJob |          B |    10 | 202.0 ns | 6.09 ns | 1.58 ns |  1.98 |    0.02 | B-B-Bench2-[Param=10]-DefaultJob |       No |
        |        |            |            |       |          |         |         |       |         |                                  |          |
 Bench2 |    Foo | DefaultJob |          B |    20 | 302.0 ns | 6.09 ns | 1.58 ns |  1.00 |    0.00 | B-B-Bench2-[Param=20]-DefaultJob |      Yes | ^
 Bench2 |    Bar | DefaultJob |          B |    20 | 402.0 ns | 6.09 ns | 1.58 ns |  1.33 |    0.00 | B-B-Bench2-[Param=20]-DefaultJob |       No |

TwoBaselinesWithJobs222

   Type | Method |        Job | Categories | Param |     Mean |   Error |  StdDev | Ratio | RatioSD |                   LogicalGroup | Baseline |
------- |------- |----------- |----------- |------ |---------:|--------:|--------:|------:|--------:|------------------------------- |--------- |
 Bench1 |    Foo |       Job1 |          A |    10 | 102.0 ns | 6.09 ns | 1.58 ns |  1.00 |    0.00 |       A-Bench1-[Param=10]-Job1 |      Yes | ^
 Bench1 |    Bar |       Job1 |          A |    10 | 202.0 ns | 6.09 ns | 1.58 ns |  1.98 |    0.02 |       A-Bench1-[Param=10]-Job1 |       No |
        |        |            |            |       |          |         |         |       |         |                                |          |
 Bench1 |    Foo |       Job2 |          A |    10 | 302.0 ns | 6.09 ns | 1.58 ns |  1.00 |    0.00 |       A-Bench1-[Param=10]-Job2 |      Yes |
 Bench1 |    Bar |       Job2 |          A |    10 | 402.0 ns | 6.09 ns | 1.58 ns |  1.33 |    0.00 |       A-Bench1-[Param=10]-Job2 |       No |
        |        |            |            |       |          |         |         |       |         |                                |          |
 Bench1 |    Foo |       Job1 |          A |    20 | 502.0 ns | 6.09 ns | 1.58 ns |  1.00 |    0.00 |       A-Bench1-[Param=20]-Job1 |      Yes | ^
 Bench1 |    Bar |       Job1 |          A |    20 | 602.0 ns | 6.09 ns | 1.58 ns |  1.20 |    0.00 |       A-Bench1-[Param=20]-Job1 |       No |
        |        |            |            |       |          |         |         |       |         |                                |          |
 Bench1 |    Foo |       Job2 |          A |    20 | 702.0 ns | 6.09 ns | 1.58 ns |  1.00 |    0.00 |       A-Bench1-[Param=20]-Job2 |      Yes |
 Bench1 |    Bar |       Job2 |          A |    20 | 802.0 ns | 6.09 ns | 1.58 ns |  1.14 |    0.00 |       A-Bench1-[Param=20]-Job2 |       No |
        |        |            |            |       |          |         |         |       |         |                                |          |
 Bench2 |    Foo | DefaultJob |          B |    10 | 102.0 ns | 6.09 ns | 1.58 ns |  1.00 |    0.00 | B-Bench2-[Param=10]-DefaultJob |      Yes | ^
 Bench2 |    Bar | DefaultJob |          B |    10 | 202.0 ns | 6.09 ns | 1.58 ns |  1.98 |    0.02 | B-Bench2-[Param=10]-DefaultJob |       No |
        |        |            |            |       |          |         |         |       |         |                                |          |
 Bench2 |    Foo | DefaultJob |          B |    20 | 302.0 ns | 6.09 ns | 1.58 ns |  1.00 |    0.00 | B-Bench2-[Param=20]-DefaultJob |      Yes | ^
 Bench2 |    Bar | DefaultJob |          B |    20 | 402.0 ns | 6.09 ns | 1.58 ns |  1.33 |    0.00 | B-Bench2-[Param=20]-DefaultJob |       No |

TwoBaselinesWithJobs333

   Type | Method |        Job | Categories | Param |     Mean |   Error |  StdDev | Ratio | RatioSD |                       LogicalGroup | Baseline |
------- |------- |----------- |----------- |------ |---------:|--------:|--------:|------:|--------:|----------------------------------- |--------- |
 Bench1 |    Foo |       Job1 |          A |    10 | 102.0 ns | 6.09 ns | 1.58 ns |  1.00 |    0.00 |       A-Foo-Bench1-[Param=10]-Job1 |      Yes | ^
        |        |            |            |       |          |         |         |       |         |                                    |          |
 Bench1 |    Foo |       Job2 |          A |    10 | 302.0 ns | 6.09 ns | 1.58 ns |  1.00 |    0.00 |       A-Foo-Bench1-[Param=10]-Job2 |      Yes |
        |        |            |            |       |          |         |         |       |         |                                    |          |
 Bench1 |    Foo |       Job1 |          A |    20 | 502.0 ns | 6.09 ns | 1.58 ns |  1.00 |    0.00 |       A-Foo-Bench1-[Param=20]-Job1 |      Yes | ^
        |        |            |            |       |          |         |         |       |         |                                    |          |
 Bench1 |    Foo |       Job2 |          A |    20 | 702.0 ns | 6.09 ns | 1.58 ns |  1.00 |    0.00 |       A-Foo-Bench1-[Param=20]-Job2 |      Yes |
        |        |            |            |       |          |         |         |       |         |                                    |          |
 Bench1 |    Bar |       Job1 |          A |    10 | 202.0 ns | 6.09 ns | 1.58 ns |     ? |       ? |       A-Bar-Bench1-[Param=10]-Job1 |       No | ^
        |        |            |            |       |          |         |         |       |         |                                    |          |
 Bench1 |    Bar |       Job2 |          A |    10 | 402.0 ns | 6.09 ns | 1.58 ns |     ? |       ? |       A-Bar-Bench1-[Param=10]-Job2 |       No |
        |        |            |            |       |          |         |         |       |         |                                    |          |
 Bench1 |    Bar |       Job1 |          A |    20 | 602.0 ns | 6.09 ns | 1.58 ns |     ? |       ? |       A-Bar-Bench1-[Param=20]-Job1 |       No | ^
        |        |            |            |       |          |         |         |       |         |                                    |          |
 Bench1 |    Bar |       Job2 |          A |    20 | 802.0 ns | 6.09 ns | 1.58 ns |     ? |       ? |       A-Bar-Bench1-[Param=20]-Job2 |       No |
        |        |            |            |       |          |         |         |       |         |                                    |          |
 Bench2 |    Foo | DefaultJob |          B |    10 | 102.0 ns | 6.09 ns | 1.58 ns |  1.00 |    0.00 | B-Foo-Bench2-[Param=10]-DefaultJob |      Yes | ^
        |        |            |            |       |          |         |         |       |         |                                    |          |
 Bench2 |    Foo | DefaultJob |          B |    20 | 302.0 ns | 6.09 ns | 1.58 ns |  1.00 |    0.00 | B-Foo-Bench2-[Param=20]-DefaultJob |      Yes | ^
        |        |            |            |       |          |         |         |       |         |                                    |          |
 Bench2 |    Bar | DefaultJob |          B |    10 | 202.0 ns | 6.09 ns | 1.58 ns |     ? |       ? | B-Bar-Bench2-[Param=10]-DefaultJob |       No | ^
        |        |            |            |       |          |         |         |       |         |                                    |          |
 Bench2 |    Bar | DefaultJob |          B |    20 | 402.0 ns | 6.09 ns | 1.58 ns |     ? |       ? | B-Bar-Bench2-[Param=20]-DefaultJob |       No | ^

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I pushed it to another branch.
You can see it (although it's not easy):
YegorStepanov@8629a8b

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need a ByRuntime grouping?

ByJob has EnvironmentCharacteristic, which has RuntimeCharacteristic.
It seems that ByJob should do your desired grouping.

@timcassell
Copy link
Collaborator

timcassell commented Oct 18, 2022

Question

What is the correct table for this?

Old, wrong answer

If [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByMethod)] just moves that order in front, and the other defaults remain in the same order, and if we add ByType so the order should be [ByMethod, ByType, ByCategory, ByParams, ByJob], I think it should look like this:

  Type | Method |        Job | Categories | Param |     Mean |   Error |  StdDev | Ratio | RatioSD |                     LogicalGroup | Baseline |
------- |------- |----------- |----------- |------ |---------:|--------:|--------:|------:|--------:|--------------------------------- |--------- |
Bench1 |    Foo |       Job1 |          A |    10 | 102.0 ns | 6.09 ns | 1.58 ns |  1.00 |    0.00 |       Foo-Bench1-[Param=10]-Job1 |      Yes | ^
       |        |            |            |       |          |         |         |       |         |                                  |          |
Bench1 |    Foo |       Job2 |          A |    10 | 302.0 ns | 6.09 ns | 1.58 ns |  1.00 |    0.00 |       Foo-Bench1-[Param=10]-Job2 |      Yes |
       |        |            |            |       |          |         |         |       |         |                                  |          |
Bench1 |    Foo |       Job1 |          A |    20 | 502.0 ns | 6.09 ns | 1.58 ns |  1.00 |    0.00 |       Foo-Bench1-[Param=20]-Job1 |      Yes | ^
       |        |            |            |       |          |         |         |       |         |                                  |          |
Bench1 |    Foo |       Job2 |          A |    20 | 702.0 ns | 6.09 ns | 1.58 ns |  1.00 |    0.00 |       Foo-Bench1-[Param=20]-Job2 |      Yes |
       |        |            |            |       |          |         |         |       |         |                                  |          |
Bench2 |    Foo | DefaultJob |          B |    10 | 102.0 ns | 6.09 ns | 1.58 ns |  1.00 |    0.00 | Foo-Bench2-[Param=10]-DefaultJob |      Yes | ^
       |        |            |            |       |          |         |         |       |         |                                  |          |
Bench2 |    Foo | DefaultJob |          B |    20 | 302.0 ns | 6.09 ns | 1.58 ns |  1.00 |    0.00 | Foo-Bench2-[Param=20]-DefaultJob |      Yes | ^
       |        |            |            |       |          |         |         |       |         |                                  |          |
Bench1 |    Bar |       Job1 |          A |    10 | 202.0 ns | 6.09 ns | 1.58 ns |     ? |       ? |       Bar-Bench1-[Param=10]-Job1 |       No | ^
       |        |            |            |       |          |         |         |       |         |                                  |          |
Bench1 |    Bar |       Job2 |          A |    10 | 402.0 ns | 6.09 ns | 1.58 ns |     ? |       ? |       Bar-Bench1-[Param=10]-Job2 |       No |
       |        |            |            |       |          |         |         |       |         |                                  |          |
Bench1 |    Bar |       Job1 |          A |    20 | 602.0 ns | 6.09 ns | 1.58 ns |     ? |       ? |       Bar-Bench1-[Param=20]-Job1 |       No | ^
       |        |            |            |       |          |         |         |       |         |                                  |          |
Bench1 |    Bar |       Job2 |          A |    20 | 802.0 ns | 6.09 ns | 1.58 ns |     ? |       ? |       Bar-Bench1-[Param=20]-Job2 |       No |
       |        |            |            |       |          |         |         |       |         |                                  |          |
Bench2 |    Bar | DefaultJob |          B |    10 | 202.0 ns | 6.09 ns | 1.58 ns |     ? |       ? | Bar-Bench2-[Param=10]-DefaultJob |       No | ^
       |        |            |            |       |          |         |         |       |         |                                  |          |
Bench2 |    Bar | DefaultJob |          B |    20 | 402.0 ns | 6.09 ns | 1.58 ns |     ? |       ? | Bar-Bench2-[Param=20]-DefaultJob |       No | ^

[Edit] Oh wait, I think I misunderstood the question. Because the [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByMethod)] could be applied to one Type, and a different [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByParams)] could be applied to a different type, so how should the table look then?

In that case, I think ByType should always be first, unless the group rule is overridden in the config for the entire run (not per type). And each Type should have its own group rule set, since they can be set individually on each Type.

With that said, I think that table should look like this:

   Type | Method |        Job | Categories | Param |     Mean |   Error |  StdDev | Ratio | RatioSD |                     LogicalGroup | Baseline |
------- |------- |----------- |----------- |------ |---------:|--------:|--------:|------:|--------:|--------------------------------- |--------- |
 Bench1 |    Foo |       Job1 |          A |    10 | 102.0 ns | 6.09 ns | 1.58 ns |  1.00 |    0.00 |       Foo-Bench1-[Param=10]-Job1 |      Yes | ^
        |        |            |            |       |          |         |         |       |         |                                  |          |
 Bench1 |    Foo |       Job2 |          A |    10 | 302.0 ns | 6.09 ns | 1.58 ns |  1.00 |    0.00 |       Foo-Bench1-[Param=10]-Job2 |      Yes |
        |        |            |            |       |          |         |         |       |         |                                  |          |
 Bench1 |    Foo |       Job1 |          A |    20 | 502.0 ns | 6.09 ns | 1.58 ns |  1.00 |    0.00 |       Foo-Bench1-[Param=20]-Job1 |      Yes | ^
        |        |            |            |       |          |         |         |       |         |                                  |          |
 Bench1 |    Foo |       Job2 |          A |    20 | 702.0 ns | 6.09 ns | 1.58 ns |  1.00 |    0.00 |       Foo-Bench1-[Param=20]-Job2 |      Yes |
        |        |            |            |       |          |         |         |       |         |                                  |          |
 Bench1 |    Bar |       Job1 |          A |    10 | 202.0 ns | 6.09 ns | 1.58 ns |     ? |       ? |       Bar-Bench1-[Param=10]-Job1 |       No | ^
        |        |            |            |       |          |         |         |       |         |                                  |          |
 Bench1 |    Bar |       Job2 |          A |    10 | 402.0 ns | 6.09 ns | 1.58 ns |     ? |       ? |       Bar-Bench1-[Param=10]-Job2 |       No |
        |        |            |            |       |          |         |         |       |         |                                  |          |
 Bench1 |    Bar |       Job1 |          A |    20 | 602.0 ns | 6.09 ns | 1.58 ns |     ? |       ? |       Bar-Bench1-[Param=20]-Job1 |       No | ^
        |        |            |            |       |          |         |         |       |         |                                  |          |
 Bench1 |    Bar |       Job2 |          A |    20 | 802.0 ns | 6.09 ns | 1.58 ns |     ? |       ? |       Bar-Bench1-[Param=20]-Job2 |       No |
        |        |            |            |       |          |         |         |       |         |                                  |          |
 Bench2 |    Foo | DefaultJob |          B |    10 | 102.0 ns | 6.09 ns | 1.58 ns |  1.00 |    0.00 | Foo-Bench2-[Param=10]-DefaultJob |      Yes | ^
        |        |            |            |       |          |         |         |       |         |                                  |          |
 Bench2 |    Bar | DefaultJob |          B |    10 | 202.0 ns | 6.09 ns | 1.58 ns |     ? |       ? | Bar-Bench2-[Param=10]-DefaultJob |       No | ^
        |        |            |            |       |          |         |         |       |         |                                  |          |
 Bench2 |    Foo | DefaultJob |          B |    20 | 302.0 ns | 6.09 ns | 1.58 ns |  1.00 |    0.00 | Foo-Bench2-[Param=20]-DefaultJob |      Yes | ^
        |        |            |            |       |          |         |         |       |         |                                  |          |
 Bench2 |    Bar | DefaultJob |          B |    20 | 402.0 ns | 6.09 ns | 1.58 ns |     ? |       ? | Bar-Bench2-[Param=20]-DefaultJob |       No | ^

@timcassell
Copy link
Collaborator

A follow-up to this may want to add a ByRuntime group rule, which by default should be ordered before ByType.

@YegorStepanov
Copy link
Contributor Author

I don't like that grouping ByMethod groups them into separate groups, but this seems to be the correct behavior:

How the grouping works:

  1. Look at the LogicalGroup column. It shows the keys to sort by (the keys are truncated from the right if ALL keys in the table are the same)

  2. There is default grouping order: ByType, ByCategory, ByParams, ByJob, ByMethod

  3. When we add a grouping manually ([GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByMethod)]) it adds this key to the left. So it turns out that the groups consist of 1 element.

@YegorStepanov
Copy link
Contributor Author

YegorStepanov commented Oct 18, 2022

I'm converting it to draft until I figure out why nothing changes due to swapping ByCategory<->ByType

[Edit]
There is no difference in order because we always break them into groups if there are multiple types.

@YegorStepanov YegorStepanov marked this pull request as draft October 18, 2022 23:51
@YegorStepanov YegorStepanov changed the title Add ByType logical rule Add grouping by type Oct 21, 2022
@YegorStepanov
Copy link
Contributor Author

I made the most conservative mode. I don't like that there were more groups than I expected (look at the last commit)

assign to @AndreyAkinshin

@YegorStepanov YegorStepanov marked this pull request as ready for review October 21, 2022 15:48
@timcassell
Copy link
Collaborator

timcassell commented Dec 24, 2022

@YegorStepanov I tried these changes and, while it looks better, there's still some weirdness with the table:

|         Type |       Method | Pending |       Mean | Ratio |
|------------- |------------- |-------- |-----------:|------:|
|   AsyncAwait |     Callback |   False |   358.8 ns |  1.00 |
|   AsyncAwait | ProtoPromise |   False |   378.7 ns |  1.05 |
|   AsyncAwait |   RsgPromise |   False |         NA |     ? |
|   AsyncAwait |         Task |   False |   357.7 ns |  1.00 |
|   AsyncAwait |      UniTask |   False |   392.3 ns |  1.09 |
|   AsyncAwait | UnityFxAsync |   False |   538.7 ns |  1.50 |
|   AsyncAwait |    ValueTask |   False |   522.7 ns |  1.46 |
| ContinueWith |     Callback |   False |   347.8 ns |  0.97 |
| ContinueWith | ProtoPromise |   False |   529.0 ns |  1.47 |
| ContinueWith |   RsgPromise |   False |   707.7 ns |  1.97 |
| ContinueWith |         Task |   False | 2,372.0 ns |  6.61 |
| ContinueWith |      UniTask |   False |   742.5 ns |  2.07 |
| ContinueWith | UnityFxAsync |   False | 1,807.4 ns |  5.03 |
| ContinueWith |    ValueTask |   False |         NA |     ? |
|              |              |         |            |       |
|   AsyncAwait |     Callback |    True |   417.9 ns |  1.00 |
|   AsyncAwait | ProtoPromise |    True | 2,166.3 ns |  5.05 |
|   AsyncAwait |   RsgPromise |    True |         NA |     ? |
|   AsyncAwait |         Task |    True | 2,710.6 ns |  6.27 |
|   AsyncAwait |      UniTask |    True | 1,910.4 ns |  4.44 |
|   AsyncAwait | UnityFxAsync |    True | 2,436.0 ns |  5.64 |
|   AsyncAwait |    ValueTask |    True | 3,120.2 ns |  7.26 |
| ContinueWith |     Callback |    True |   396.3 ns |  0.92 |
| ContinueWith | ProtoPromise |    True | 2,380.8 ns |  5.55 |
| ContinueWith |   RsgPromise |    True | 6,537.0 ns | 15.58 |
| ContinueWith |         Task |    True | 3,122.0 ns |  7.22 |
| ContinueWith |      UniTask |    True | 3,172.6 ns |  7.34 |
| ContinueWith | UnityFxAsync |    True | 2,749.3 ns |  6.36 |
| ContinueWith |    ValueTask |    True |         NA |     ? |

It seems to be grouping the parameter ahead of the type, and the ratio column is not segregated for each type (it's shared for the entire parameter, regardless of type).

public abstract class AsyncBenchmark
{
    [Params(true, false)]
    public bool Pending;
}

public partial class AsyncAwait : AsyncBenchmark
{
}

public partial class ContinueWith : AsyncBenchmark
{
}

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.

--join does not respect types and ratio RunAllJoined should consider baseline per type
2 participants