/
dev-npgsql
/
npgsql
Обзор
Документация
Войти
/
dev-npgsql
/
npgsql
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
test/Npgsql.Benchmarks/TypeHandlers/TypeHandlerBenchmarks.cs
128 строк
5 KB
Nino Floris
Introduce bind operation on PgConverter surface (#6566)
11 май 2026, 20:01
Не верифицирован
11 май 2026, 20:01
0f4cfd8
Код
Авторство
О чём код?
using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Columns; using BenchmarkDotNet.Configs; using BenchmarkDotNet.Diagnosers; using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Threading; using Npgsql.Internal; namespace Npgsql.Benchmarks.TypeHandlers; public abstract class TypeHandlerBenchmarks<T> { protected class Config : ManualConfig { public Config() { AddColumn(StatisticColumn.OperationsPerSecond); AddDiagnoser(MemoryDiagnoser.Default); } } class EndlessStream : Stream { public override bool CanRead => true; public override bool CanSeek => true; public override bool CanWrite => true; public override long Length => long.MaxValue; public override long Position { get => 0L; set { } } public override void Flush() { } public override int Read(byte[] buffer, int offset, int count) => count; public override long Seek(long offset, SeekOrigin origin) => 0L; public override void SetLength(long value) { } public override void Write(byte[] buffer, int offset, int count) { } } readonly PgConverter<T> _converter; readonly PgReader _reader; readonly PgWriter _writer; readonly NpgsqlWriteBuffer _writeBuffer; readonly NpgsqlReadBuffer _readBuffer; readonly BufferRequirements _binaryRequirements; T? _value; PgValueBinding _valueBinding; PgFieldBinding _fieldBinding; protected TypeHandlerBenchmarks(PgConverter<T> handler) { var stream = new EndlessStream(); _converter = (PgConverter<T>)handler ?? throw new ArgumentNullException(nameof(handler)); _readBuffer = new NpgsqlReadBuffer(null, stream, null, NpgsqlReadBuffer.DefaultSize, NpgsqlWriteBuffer.UTF8Encoding, NpgsqlWriteBuffer.RelaxedUTF8Encoding); _writeBuffer = new NpgsqlWriteBuffer(null, stream, null, NpgsqlWriteBuffer.DefaultSize, NpgsqlWriteBuffer.UTF8Encoding) { MessageLengthValidation = false }; _reader = new PgReader(_readBuffer); _writer = _writeBuffer.GetWriter(new PostgresMinimalDatabaseInfo(), FlushMode.Blocking); _converter.CanConvert(DataFormat.Binary, out _binaryRequirements); } public IEnumerable<T?> Values() => ValuesOverride(); protected virtual IEnumerable<T?> ValuesOverride() => [default]; [ParamsSource(nameof(Values)), MaybeNull] public T Value { get => _value; set { // Workaround for https://github.com/dotnet/BenchmarkDotNet/issues/3049 if (default(T) is null && value is null) return; if (_reader.Initialized) { // Prevent Commit from calling Skip, which would cause us to try and use the null connector. _readBuffer.ReadPosition += _reader.CurrentRemaining; _reader.Commit(); } _value = value; object? writeState = null; var size = _converter.IsDbNull(value, writeState) ? null : (Size?)_converter.Bind(BindContext.CreateUnchecked(DataFormat.Binary, _binaryRequirements.Write, _binaryRequirements.IsBindOptional), value, ref writeState); _valueBinding = new PgValueBinding(DataFormat.Binary, _binaryRequirements.Write, size, writeState); if (!_valueBinding.IsDbNullBinding) { _writer.StartWrite(async: false, _valueBinding, CancellationToken.None).GetAwaiter().GetResult(); _converter.Write(_writer, value!); _writer.EndWrite(_valueBinding.Size.Value); Buffer.BlockCopy(_writeBuffer.Buffer, 0, _readBuffer.Buffer, 0, _writeBuffer.WritePosition); _readBuffer.AddBytesToRead(_writeBuffer.WritePosition); _readBuffer.ReadPosition = 0; _writeBuffer.WritePosition = 0; _reader.Init(_valueBinding.DataFormat, _valueBinding.Size.Value.GetValueOrDefault()); _fieldBinding = new PgFieldBinding(DataFormat.Binary, _binaryRequirements.Read); } } } [Benchmark] public T Read() { if (_valueBinding.IsDbNullBinding) return default!; _readBuffer.ReadPosition = 0; _reader.StartRead(_fieldBinding); var value = _converter.Read(_reader); _reader.EndRead(); return value; } [Benchmark] public void Write() { if (_valueBinding.IsDbNullBinding) return; _writer.RefreshBuffer(); _writer.StartWrite(async: false, _valueBinding, CancellationToken.None).GetAwaiter().GetResult(); _converter.Write(_writer, Value!); _writer.EndWrite(_valueBinding.Size.GetValueOrDefault()); } }