[Update: Span<T>] - Evitando alocações de memória ao ler arquivos textos

12/03/2017 21:05:00 By Felipe Pessoto

Com o release de hoje do Visual Studio 15.5, fiz uma versão utilizando Span<T>, ainda não é possível ver suas vantagens pois muitas APIs ainda não aceitam o ReadOnlySpan<char> no lugar de strings, o que permitiria por exemplo chamar o int.TryParse diretamente (Update 2: Agora permitem, o codigo foi atualizado para refletir isso). Com isso o Span<T> traria o melhor de todas as soluções apresentadas, a simplicidade do Substring, com a performance dos ponteiros, sem utilizar o unsafe.

Ainda assim o Span<T> mostra que sua performance foi a melhor entre os métodos avaliados, sem alocar praticamente nenhuma memória:

[Benchmark]
private long Read_ResultSpan(bool stack)
{
    int bufferSize = GetLineSize();
    Span buffer = stack ? stackalloc char[bufferSize] : new char[bufferSize];
    long total = 0;

    TextReader sr = GetReader();
    {
        while (sr.Read(buffer) > 0)
        {
            int lastIndex = 0;

            for (int i = 0; i < positions.Length; i++)
            {
                ReadOnlySpan result = buffer.Slice(lastIndex, positions[i]);
                lastIndex += positions[i];
                total += int.Parse(result);
            }
        }
    }

    if (total != expected)
    {
        throw new Exception("Wrong result");
    }

    return total;
}

E o resultado final:

Method Mean Ratio Gen 0/1k Op Gen 1/1k Op Gen 2/1k Op Allocated Memory/Op
Minimum 1.522 ms 0.002 - - - 0 B
ReadLine_ResultSubstring 662.002 ms 1.000 78000.0000 - - 157 MB
ReadLine_ResultCharArray 649.625 ms 0.981 78000.0000 - - 157 MB
Read_ResultCharArray 443.691 ms 0.670 57000.0000 - - 114 MB
Read_ResultCharArraySpan 390.457 ms 0.590 - - - 440 B
Read_ResultUseUnsafeCharPointer 551.917 ms 0.834 - - - 1824 B
Read_ResultSpanStackAlloc 369.504 ms 0.558 - - - 0 B
Read_ResultSpanCharArray 397.005 ms 0.600 - - - 360 B
Read_ResultSpanNative 376.109 ms 0.568 - - - 0 B

 

 

O código está disponível em https://github.com/felipepessoto/AvoidingStringAllocation