Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which is better for performance with Encoding.UTF8.GetBytes with Span - GetByteCount or try/catch

Tags:

c#

.net-core

I'm trying to encode a KeyValuePair<string, string> to UTF-8 key='value' using the Span<byte> overloads in .NET Core 2.1.

Whoever wrote the GetBytes(ReadOnlySpan<char> chars, Span<byte> bytes) method was obviously a disciple of Yoda, because there is no TryGetBytes alternative, which is odd since Utf8Formatter provides TryWrite for all non-string primitive types.

So I have two options for writing an extension method to do this.

Option 1:

public static bool TryGetBytes(this Encoding encoding, ReadOnlySpan<char> str, Span<byte> bytes, out int written)
{
  try
  {
    written = Encoding.UTF8.GetBytes(str, span);
    return true;
  }
  catch (ArgumentException)
  {
    written = 0;
    return false;
  }

Option 2:

public static bool TryGetBytes(this Encoding encoding, ReadOnlySpan<char> str, Span<byte> bytes, out int written)
{
  if (encoding.GetByteCount(str) > span.Length)
  {
    written = 0;
    return false;
  }

  written = Encoding.UTF8.GetBytes(str, span);
  return true;
}

Which is better for performance, assuming that the "not enough space" case will be hit fairly frequently (say, 1 time in 50) on a hot path?

like image 269
Mark Rendle Avatar asked Feb 03 '19 14:02

Mark Rendle


1 Answers

As I was writing this question, I thought "why don't you just BenchmarkDotNet it?" so I did.

Answer: GetByteCount is two orders of magnitude faster than try/catch.

Here are the results:


BenchmarkDotNet=v0.11.3, OS=Windows 10.0.17763.253 (1809/October2018Update/Redstone5)
Intel Core i7-7700HQ CPU 2.80GHz (Kaby Lake), 1 CPU, 8 logical and 4 physical cores
.NET Core SDK=2.2.102
  [Host]     : .NET Core 2.2.1 (CoreCLR 4.6.27207.03, CoreFX 4.6.27207.03), 64bit RyuJIT
  DefaultJob : .NET Core 2.2.1 (CoreCLR 4.6.27207.03, CoreFX 4.6.27207.03), 64bit RyuJIT


|   Method |        Mean |      Error |    StdDev | Gen 0/1k Op | Gen 1/1k Op | Gen 2/1k Op | Allocated Memory/Op |
|--------- |------------:|-----------:|----------:|------------:|------------:|------------:|--------------------:|
| TryCatch | 40,985.9 ns | 800.034 ns | 785.74 ns |      0.4272 |           - |           - |              1392 B |
| TryCount |    366.5 ns |   8.450 ns |  10.38 ns |           - |           - |           - |                   - |
like image 177
Mark Rendle Avatar answered Oct 18 '22 19:10

Mark Rendle