Информация об изменениях

Сообщение Re[53]: MS забило на дотнет. Питону - да, сишарпу - нет? от 06.09.2021 12:58

Изменено 06.09.2021 13:24 vdimas

Re[53]: MS забило на дотнет. Питону - да, сишарпу - нет?
Здравствуйте, Danchik, Вы писали:

D>Нашли же вы пример. Oracle .NET команда леворукая, это давно известно. Они и асинки не осилили.


Оракл наложил лапки 4 года назад, а по ссылке коммиты и 6-тилетние видны.
С другой стороны, твой комментарий делает бесполезным трату времени на просмотр исходников коннекта к оракловым базам, я правильно понял?

Диверсия от владельца джавы Оракла в сторону дотнета? ))


D>Вот переписаное с нуля опенсорсный провайдер. Кого-то достало.

D>https://github.com/mysql-net/MySqlConnector/blob/1b2757d69f15555fcd05dd8b319a3ae6e3aaf6ad/src/MySqlConnector/Core/Row.cs#L206

Тоже не очень:
    if (ordinal < 0 || ordinal > ResultSet.ColumnDefinitions!.Length)
        throw new ArgumentOutOfRangeException(nameof(ordinal), "value must be between 0 and {0}.".FormatInvariant(ResultSet.ColumnDefinitions!.Length));

В рассмотренных ранее исходниках доп. специальную такую проверку не делали, т.к. она делается системным дотнетным кодом при обращении к массиву.

Т.е., достаточно было описать так:
ColumnDefinitionPayload[] _columnDefinitions;


Это тоже нубство:
if (columnDefinition.ColumnType is ColumnType.Decimal or ColumnType.NewDecimal)
...
else if
...
if(...


И вот это нубство:
ResultSet.ColumnDefinitions

где ResultSet — класс.

И вот это вызывается в теле затем, тоже нубство:
        protected override int GetInt32Core(ReadOnlySpan<byte> data, ColumnDefinitionPayload columnDefinition)
        {
            var isUnsigned = (columnDefinition.ColumnFlags & ColumnFlags.Unsigned) != 0;
            return columnDefinition.ColumnType switch
            {
                ColumnType.Tiny => isUnsigned ? (int) data[0] : (sbyte) data[0],
                ColumnType.Decimal or ColumnType.NewDecimal => Utf8Parser.TryParse(data, out decimal decimalValue, out int bytesConsumed) && bytesConsumed == data.Length ? checked((int) decimalValue) : throw new FormatException(),
                ColumnType.Int24 or ColumnType.Long => isUnsigned ? checked((int) MemoryMarshal.Read<uint>(data)) : MemoryMarshal.Read<int>(data),
                ColumnType.Longlong => isUnsigned ? checked((int) MemoryMarshal.Read<ulong>(data)) : checked((int) MemoryMarshal.Read<long>(data)),
                ColumnType.Short => isUnsigned ? (int) MemoryMarshal.Read<ushort>(data) : MemoryMarshal.Read<short>(data),
                ColumnType.Year => MemoryMarshal.Read<short>(data),
                _ => throw new FormatException(),
            };
        }


Должен быть примерно такой код:
public int GetInt32(int ordinal)
{
    return _columnDefs[ordinal]._converter.ToInt32(_data, _dataOffsets[ordinal]);
}

Вызов либо делегата, либо виртуальной ф-ии.

Например, в случае виртуальных ф-ий:
internal class Int32Converter : IDataConverter {
    public override ToInt32(Memory<byte> data, int offset) => DataReader.ReadInt32(data, offset);
    public override ToUInt32(Memory<byte> data, int offset) => DataReader.ReadUInt32(data, offset);
    public override ToInt16(Memory<byte> data, int offset) => checked((short)DataReader.ReadInt32(data, offset));
    public override ToUInt16(Memory<byte> data, int offset) => checked((ushort)DataReader.ReadUInt32(data, offset));
    ...
}


В последних версиях дотнета можно было бы заменить на указатель на ф-ию и получить максимально-достижимое быстродействие:
internal class DataConverter {
    public delegate *<Memory<byte>, int, int> ToInt32;
    public delegate *<Memory<byte>, int, uint> ToUInt32;
    public delegate *<Memory<byte>, int, short> ToInt16;
    public delegate *<Memory<byte>, int, ushort> ToUInt16;
    ...
}

internal class Int32Converter : DataConverter {
    Int32Converter() {
        ToInt32 = &DataReader.ReadInt32;
        ToUInt32 = &DataReader.ReadUInt32;

        static short toInt16(Memory<byte> data, int offset) => checked((short)DataReader.ReadInt32(data, offset));
        ToInt16 = &toInt16;

        static ushort toUInt16(Memory<byte> data, int offset) => checked((ushort)DataReader.ReadUInt32(data, offset));
        ToUInt16 = &toUInt16;

        ...
    }
}


То бишь, есть простая таблица конвертеров для строки данных.
Динамически в этой таблице ищется строка по ordinal (строка — фактический тип поля) и статически прыгаем на колонку, т.к. запрашиваемый тип в методе известен (в колонке запрашиваемый тип).

И да, внутренней структуре ColumnDefinitionPayload вовсе не требуется быть классом, структура справилась бы.


V>>Лень смотреть еще и на Postgre-дрова, но вот для MySQL ссылку привёл — мрак.

D>А надо было, это один из лучших драйверов. Там за такты и память борются.

Ну, хорошо, если так.
Кто-то должен был справиться с банальной задачей десериализации данных? ))
Re[53]: MS забило на дотнет. Питону - да, сишарпу - нет?
Здравствуйте, Danchik, Вы писали:

D>Нашли же вы пример. Oracle .NET команда леворукая, это давно известно. Они и асинки не осилили.


Оракл наложил лапки 4 года назад, а по ссылке коммиты и 6-тилетние видны.
С другой стороны, твой комментарий делает бесполезным трату времени на просмотр исходников коннекта к оракловым базам, я правильно понял?

Диверсия от владельца джавы Оракла в сторону дотнета? ))


D>Вот переписаное с нуля опенсорсный провайдер. Кого-то достало.

D>https://github.com/mysql-net/MySqlConnector/blob/1b2757d69f15555fcd05dd8b319a3ae6e3aaf6ad/src/MySqlConnector/Core/Row.cs#L206

Тоже не очень:
    if (ordinal < 0 || ordinal > ResultSet.ColumnDefinitions!.Length)
        throw new ArgumentOutOfRangeException(nameof(ordinal), "value must be between 0 and {0}.".FormatInvariant(ResultSet.ColumnDefinitions!.Length));

В рассмотренных ранее исходниках доп. специальную такую проверку не делали, т.к. она делается системным дотнетным кодом при обращении к массиву.

Т.е., достаточно было описать так:
ColumnDefinitionPayload[] _columnDefinitions;


Это тоже нубство:
if (columnDefinition.ColumnType is ColumnType.Decimal or ColumnType.NewDecimal)
...
else if
...
if(...


И вот это нубство:
ResultSet.ColumnDefinitions

где ResultSet — класс.

И вот это вызывается в теле затем, тоже нубство:
        protected override int GetInt32Core(ReadOnlySpan<byte> data, ColumnDefinitionPayload columnDefinition)
        {
            var isUnsigned = (columnDefinition.ColumnFlags & ColumnFlags.Unsigned) != 0;
            return columnDefinition.ColumnType switch
            {
                ColumnType.Tiny => isUnsigned ? (int) data[0] : (sbyte) data[0],
                ColumnType.Decimal or ColumnType.NewDecimal => Utf8Parser.TryParse(data, out decimal decimalValue, out int bytesConsumed) && bytesConsumed == data.Length ? checked((int) decimalValue) : throw new FormatException(),
                ColumnType.Int24 or ColumnType.Long => isUnsigned ? checked((int) MemoryMarshal.Read<uint>(data)) : MemoryMarshal.Read<int>(data),
                ColumnType.Longlong => isUnsigned ? checked((int) MemoryMarshal.Read<ulong>(data)) : checked((int) MemoryMarshal.Read<long>(data)),
                ColumnType.Short => isUnsigned ? (int) MemoryMarshal.Read<ushort>(data) : MemoryMarshal.Read<short>(data),
                ColumnType.Year => MemoryMarshal.Read<short>(data),
                _ => throw new FormatException(),
            };
        }


Должен быть примерно такой код:
public int GetInt32(int ordinal)
{
    return _columnDefs[ordinal]._converter.ToInt32(_data, _dataOffsets[ordinal]);
}

Вызов либо делегата, либо виртуальной ф-ии.

Например, в случае виртуальных ф-ий:
internal class Int32Converter : IDataConverter {
    public override ToInt32(Memory<byte> data, int offset) => DataReader.ReadInt32(data, offset);
    public override ToUInt32(Memory<byte> data, int offset) => DataReader.ReadUInt32(data, offset);
    public override ToInt16(Memory<byte> data, int offset) => checked((short)DataReader.ReadInt32(data, offset));
    public override ToUInt16(Memory<byte> data, int offset) => checked((ushort)DataReader.ReadUInt32(data, offset));
    ...
}


В последних версиях дотнета можно было бы заменить на указатель на ф-ию и получить максимально-достижимое быстродействие:
internal class DataConverter {
    public delegate *<Memory<byte>, int, int> ToInt32;
    public delegate *<Memory<byte>, int, uint> ToUInt32;
    public delegate *<Memory<byte>, int, short> ToInt16;
    public delegate *<Memory<byte>, int, ushort> ToUInt16;
    ...
}

internal class Int32Converter : DataConverter {
    Int32Converter() {
        ToInt32 = &DataReader.ReadInt32;
        ToUInt32 = &DataReader.ReadUInt32;

        static short toInt16(Memory<byte> data, int offset) => checked((short)DataReader.ReadInt32(data, offset));
        ToInt16 = &toInt16;

        static ushort toUInt16(Memory<byte> data, int offset) => checked((ushort)DataReader.ReadUInt32(data, offset));
        ToUInt16 = &toUInt16;

        ...
    }
}


То бишь, есть простая таблица конвертеров для строки данных.
Динамически в этой таблице ищется строка по ordinal (строка — фактический тип поля) и статически прыгаем на колонку, т.к. запрашиваемый тип в методе известен (в колонке запрашиваемый тип).

И да, внутренней структуре ColumnDefinitionPayload вовсе не требуется быть классом, структура справилась бы.


V>>Лень смотреть еще и на Postgre-дрова, но вот для MySQL ссылку привёл — мрак.

D>А надо было, это один из лучших драйверов. Там за такты и память борются.

Ну, хорошо, если так.
Кто-то же должен был справиться с банальной задачей десериализации данных? ))