Skip to content
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

Aggressive optimization and inlining foor PooledList.Span #34

Open
dzmitry-lahoda opened this issue Jul 18, 2019 · 5 comments
Open

Aggressive optimization and inlining foor PooledList.Span #34

dzmitry-lahoda opened this issue Jul 18, 2019 · 5 comments

Comments

@dzmitry-lahoda
Copy link
Contributor

dzmitry-lahoda commented Jul 18, 2019

Is your feature request related to a problem? Please describe.
Next method is kind of slow in Unity runtime (not sure about Core):

public Span<T> Span => _items.AsSpan(0, _size);

Describe the solution you'd like
Mark this method as aggressive optimization and inlining.

Describe alternatives you've considered
Provide unsafe access to writable array as ReadOnlyProperty.

Additional context
We get data from Span by ref.

I know Core 3 optimized Span, but there are issues to measure that because of BDN-JIT instability. Same time Unity is involved into .NET Ecosystem and hopefully will optimize Span in some time (because people will use .NET Standard with Spans and Unity stated it is 2.0 and will be 2.1)

@dzmitry-lahoda
Copy link
Contributor Author

dzmitry-lahoda commented Jul 22, 2019

No optimization tag:

BenchmarkDotNet=v0.11.3, OS=Windows 10.0.17763.615 (1809/October2018Update/Redstone5)
Intel Core i7-7700HQ CPU 2.80GHz (Kaby Lake), 1 CPU, 8 logical and 4 physical cores
.NET Core SDK=3.0.100-preview5-011568
  [Host] : .NET Core 2.2.4 (CoreCLR 4.6.27521.02, CoreFX 4.6.27521.01), 64bit RyuJIT
  Core   : .NET Core 2.2.4 (CoreCLR 4.6.27521.02, CoreFX 4.6.27521.01), 64bit RyuJIT

Job=Core  Runtime=Core  

        Method |      N |     Mean |     Error |    StdDev | Gen 0/1k Op | Gen 1/1k Op | Gen 2/1k Op | Allocated Memory/Op |
-------------- |------- |---------:|----------:|----------:|------------:|------------:|------------:|--------------------:|
 PooledSpan |   1000 | 12.91 us | 0.2546 us | 0.4526 us |           - |           - |           - |                   - |
 PooledSpan |  10000 | 13.42 us | 0.2634 us | 0.4614 us |           - |           - |           - |                   - |
 PooledSpan | 100000 | 13.44 us | 0.2649 us | 0.3882 us |           - |           - |           - |                   - |

@dzmitry-lahoda
Copy link
Contributor Author

Span marked with aggressive inlining:

BenchmarkDotNet=v0.11.3, OS=Windows 10.0.17763.615 (1809/October2018Update/Redstone5)
Intel Core i7-7700HQ CPU 2.80GHz (Kaby Lake), 1 CPU, 8 logical and 4 physical cores
.NET Core SDK=3.0.100-preview5-011568
  [Host] : .NET Core 2.2.4 (CoreCLR 4.6.27521.02, CoreFX 4.6.27521.01), 64bit RyuJIT
  Core   : .NET Core 2.2.4 (CoreCLR 4.6.27521.02, CoreFX 4.6.27521.01), 64bit RyuJIT

Job=Core  Runtime=Core  

              Method |      N |      Mean |     Error |    StdDev | Gen 0/1k Op | Gen 1/1k Op | Gen 2/1k Op | Allocated Memory/Op |
-------------------- |------- |----------:|----------:|----------:|------------:|------------:|------------:|--------------------:|
          PooledSpan |   1000 | 12.844 us | 0.2542 us | 0.3306 us |           - |           - |           - |                   - |
         PooledIndex |   1000 | 16.372 us | 0.3236 us | 0.5752 us |           - |           - |           - |                   - |
 Pooled_public_items |   1000 |  6.894 us | 0.1938 us | 0.5713 us |           - |           - |           - |                   - |
          PooledSpan |  10000 | 13.040 us | 0.2600 us | 0.6665 us |           - |           - |           - |                   - |
         PooledIndex |  10000 | 15.822 us | 0.3127 us | 0.5225 us |           - |           - |           - |                   - |
 Pooled_public_items |  10000 |  6.711 us | 0.2165 us | 0.6281 us |           - |           - |           - |                   - |
          PooledSpan | 100000 | 11.955 us | 0.2294 us | 0.2033 us |           - |           - |           - |                   - |
         PooledIndex | 100000 | 16.045 us | 0.3202 us | 0.7161 us |           - |           - |           - |                   - |
 Pooled_public_items | 100000 |  6.926 us | 0.2220 us | 0.6475 us |           - |           - |           - |                   - |

@dzmitry-lahoda
Copy link
Contributor Author

dzmitry-lahoda commented Jul 22, 2019

So:

  1. Wait for release of .NET Core 3.
  2. Make both - aggressive optimization and inlining.
  3. Measure.

@jtmueller
Copy link
Owner

Sorry for the delayed response. Here's what I'm currently seeing without your suggested optimization, run from the "core3" branch:

Method Runtime N Mean Error StdDev Gen 0 Gen 1 Gen 2 Allocated
PooledSpan .NET 4.8 1000 16.09 us 0.066 us 0.062 us - - - -
PooledIndex .NET 4.8 1000 17.42 us 0.093 us 0.087 us - - - -
PooledSpan .NET Core 3.0 1000 11.34 us 0.108 us 0.101 us - - - -
PooledIndex .NET Core 3.0 1000 17.44 us 0.107 us 0.100 us - - - -
PooledSpan .NET 4.8 10000 16.08 us 0.120 us 0.112 us - - - -
PooledIndex .NET 4.8 10000 17.43 us 0.074 us 0.069 us - - - -
PooledSpan .NET Core 3.0 10000 11.25 us 0.044 us 0.039 us - - - -
PooledIndex .NET Core 3.0 10000 17.38 us 0.108 us 0.101 us - - - -
PooledSpan .NET 4.8 100000 16.03 us 0.066 us 0.062 us - - - -
PooledIndex .NET 4.8 100000 17.41 us 0.110 us 0.103 us - - - -
PooledSpan .NET Core 3.0 100000 11.23 us 0.046 us 0.043 us - - - -
PooledIndex .NET Core 3.0 100000 17.47 us 0.088 us 0.082 us - - - -

And here's what I'm seeing with AggressiveInlining applied to the "Span" property getter. There doesn't seem to be a significant change by doing this. Perhaps I'm misunderstanding what you're proposing?

Method Runtime N Mean Error StdDev Gen 0 Gen 1 Gen 2 Allocated
PooledSpan .NET 4.8 1000 16.28 us 0.327 us 0.480 us - - - -
PooledIndex .NET 4.8 1000 17.41 us 0.138 us 0.130 us - - - -
PooledSpan .NET Core 3.0 1000 11.26 us 0.067 us 0.059 us - - - -
PooledIndex .NET Core 3.0 1000 17.35 us 0.090 us 0.084 us - - - -
PooledSpan .NET 4.8 10000 16.15 us 0.182 us 0.152 us - - - -
PooledIndex .NET 4.8 10000 17.41 us 0.164 us 0.145 us - - - -
PooledSpan .NET Core 3.0 10000 11.25 us 0.075 us 0.070 us - - - -
PooledIndex .NET Core 3.0 10000 17.38 us 0.111 us 0.104 us - - - -
PooledSpan .NET 4.8 100000 16.13 us 0.074 us 0.062 us - - - -
PooledIndex .NET 4.8 100000 17.37 us 0.111 us 0.103 us - - - -
PooledSpan .NET Core 3.0 100000 11.27 us 0.074 us 0.066 us - - - -
PooledIndex .NET Core 3.0 100000 17.38 us 0.079 us 0.070 us - - - -
public Span<T> Span
{
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    get
    {
        return _items.AsSpan(0, _size);
    }
}

@dzmitry-lahoda
Copy link
Contributor Author

MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization ? It may not help either. But at least, in Unity IL2CPP both span and index were slow, so people put items array as public. So if nothing changes, may be leave both optimization in place so that possible other runtimes will have more chances to hit the optimization? Just as idea, but anyway - may close the issue. Thanks

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

No branches or pull requests

2 participants