Самый быстрый путь (мудрый производительностью) для превращения строки в байт [], выстраивает в C# с помощью кодировки символов ASCII

Это было упомянуто, прежде чем то выделение стека просто переместит указатель вершины стека, то есть, единственную инструкцию относительно большей части архитектуры. Сравните это с тем, что обычно происходит в случае выделения "кучи".

операционная система поддерживает части свободной памяти как связанный список с данными полезной нагрузки, состоящими из указателя на начальный адрес бесплатной части и размер бесплатной части. Для выделения X байтов памяти список ссылок пересечен, и каждое примечание посещают в последовательности, проверяя, чтобы видеть, является ли ее размер по крайней мере X. То, когда часть с размером P> = X найдена, P разделяется на два, расстается с размерами X и P-X. Связанный список обновляется, и указатель на первую часть возвращается.

, Как Вы видите, выделение "кучи" зависит от факторов мая как то, сколько памяти Вы запрашиваете, насколько фрагментированный память и так далее.

8
задан Tom Blodget 25 July 2018 в 16:57
поделиться

8 ответов

Если все ваши данные на самом деле будут в формате ASCII, то вы сможете сделать это немного быстрее, чем ASCIIEncoding , который имеет различные ( совершенно разумно) битов обработки ошибок и т. д. Вы также можете ускорить это, избегая создания новых массивов байтов все время. Предположим, у вас есть верхняя граница, под которой будут находиться все ваши сообщения:

void QuickAndDirtyAsciiEncode(string chars, byte[] buffer)
{
    int length = chars.Length;
    for (int i = 0; i < length; i++)
    {
        buffer[i] = (byte) (chars[i] & 0x7f);
    }
}

Затем вы должны сделать что-то вроде:

readonly byte[] Buffer = new byte[8192]; // Reuse this repeatedly
...
QuickAndDirtyAsciiEncode(text, Buffer);
// We know ASCII takes one byte per character
socket.Send(Buffer, text.Length, SocketFlags.None);

Это довольно безнадежная оптимизация. Я бы придерживался ASCIIEncoding , пока не доказал , что это узкое место (или, по крайней мере, этот вид уродливого хака не помогает).

15
ответ дан 5 December 2019 в 05:34
поделиться

Я бы сказал, что то, как вы это делаете сейчас, очень хорошо. Если вас действительно интересует такая оптимизация на очень низком уровне, лучшая рекомендация, которую я могу дать, - это использовать Reflector. С рефлектором вы можете сами (большую часть времени) посмотреть код и увидеть, что это за алгоритмы. Если рефлектор не показывает вас, вы всегда можете загрузить Microsoft SSCLI (общая языковая инфраструктура с общим исходным кодом), чтобы увидеть код C ++, лежащий в основе методов MethodImplOptions.InternalCall.

Для справки, вот реальная реализация Encoding.ASCII.GetBytes:

public override int GetBytes(string chars, int charIndex, int charCount, byte[] bytes, int byteIndex)
{
    if ((chars == null) || (bytes == null))
    {
        throw new ArgumentNullException();
    }
    if ((charIndex < 0) || (charCount < 0))
    {
        throw new ArgumentOutOfRangeException();
    }
    if ((chars.Length - charIndex) < charCount)
    {
        throw new ArgumentOutOfRangeException();
    }
    if ((byteIndex < 0) || (byteIndex > bytes.Length))
    {
        throw new ArgumentOutOfRangeException();
    }
    if ((bytes.Length - byteIndex) < charCount)
    {
        throw new ArgumentException();
    }
    int num = charIndex + charCount;
    while (charIndex < num)
    {
        char ch = chars[charIndex++];
        if (ch >= '\x0080')
        {
            ch = '?';
        }
        bytes[byteIndex++] = (byte) ch;
    }
    return charCount;
}
9
ответ дан 5 December 2019 в 05:34
поделиться

Для чего вы пытаетесь оптимизировать? ПРОЦЕССОР? Пропускная способность?

Если вы хотите оптимизировать полосу пропускания, вы можете попробовать сжать строковые данные заранее.

Во-первых, профилируйте свой код, выясните, какие биты медленные, прежде чем пытаться оптимизировать на таком низком уровне.

1
ответ дан 5 December 2019 в 05:34
поделиться

Я полагаю, что функция GetBytes () уже хорошо оптимизирована для этого. Я не могу придумать никаких предложений по повышению скорости вашего существующего кода.

РЕДАКТИРОВАТЬ - Вы знаете, я не знаю, быстрее это или нет. Но здесь' Другой метод, использующий BinaryFormatter:

BinaryFormatter bf = new BinaryFormatter();
MemoryStream ms = new MemoryStream();
bf.Serialize(ms, someString);
byte[] bytes =  ms.ToArray();
ms.Close();
socket.Send(bytes);

Я думаю, что этот может быть быстрее, потому что он пропускает этап кодирования. Я также не совсем уверен, что это будет работать должным образом. Но вы можете попробовать и посмотреть. Конечно, если вам нужна кодировка ascii, это не поможет.

У меня возникла еще одна мысль. Я считаю, что этот код вернет вдвое больше байтов, чем при использовании GetBytes с кодировкой ASCII. Причина в том, что все строки в .NET негласно используют Unicode. И, конечно, Unicode использует 2 байта на символ, тогда как ASCII использует только 1. Так что BinaryFormatter, вероятно, не то, что нужно использовать в этом случае, потому что вы бы удвоили количество данных, которые вы отправляете через сокет.

BinaryFormatter bf = new BinaryFormatter();
MemoryStream ms = new MemoryStream();
bf.Serialize(ms, someString);
byte[] bytes =  ms.ToArray();
ms.Close();
socket.Send(bytes);

Я думаю, что этот может быть быстрее, потому что он пропускает этап кодирования. Я также не совсем уверен, что это будет работать должным образом. Но вы можете попробовать и посмотреть. Конечно, если вам нужна кодировка ascii, это не поможет.

У меня возникла еще одна мысль. Я считаю, что этот код вернет вдвое больше байтов, чем при использовании GetBytes с кодировкой ASCII. Причина в том, что все строки в .NET негласно используют юникод. И, конечно, Unicode использует 2 байта на символ, тогда как ASCII использует только 1. Так что BinaryFormatter, вероятно, не то, что нужно использовать в этом случае, потому что вы бы удвоили количество данных, которые вы отправляете через сокет.

BinaryFormatter bf = new BinaryFormatter();
MemoryStream ms = new MemoryStream();
bf.Serialize(ms, someString);
byte[] bytes =  ms.ToArray();
ms.Close();
socket.Send(bytes);

Я думаю, что этот может быть быстрее, потому что он пропускает этап кодирования. Я также не совсем уверен, что это будет работать должным образом. Но вы можете попробовать и посмотреть. Конечно, если вам нужна кодировка ascii, это не поможет.

У меня возникла еще одна мысль. Я считаю, что этот код вернет вдвое больше байтов, чем при использовании GetBytes с кодировкой ASCII. Причина в том, что все строки в .NET негласно используют Unicode. И, конечно, Unicode использует 2 байта на символ, тогда как ASCII использует только 1. Так что BinaryFormatter, вероятно, не то, что нужно использовать в этом случае, потому что вы бы удвоили количество данных, которые вы отправляете через сокет.

У меня возникла еще одна мысль. Я считаю, что этот код вернет вдвое больше байтов, чем при использовании GetBytes с кодировкой ASCII. Причина в том, что все строки в .NET негласно используют юникод. И, конечно, Unicode использует 2 байта на символ, тогда как ASCII использует только 1. Так что BinaryFormatter, вероятно, не то, что нужно использовать в этом случае, потому что вы бы удвоили количество данных, которые вы отправляете через сокет.

У меня возникла еще одна мысль. Я считаю, что этот код вернет вдвое больше байтов, чем при использовании GetBytes с кодировкой ASCII. Причина в том, что все строки в .NET негласно используют Unicode. И, конечно, Unicode использует 2 байта на символ, тогда как ASCII использует только 1. Так что BinaryFormatter, вероятно, не то, что нужно использовать в этом случае, потому что вы бы удвоили количество данных, которые вы отправляете через сокет.

1
ответ дан 5 December 2019 в 05:34
поделиться

Не имея ни малейшего представления о ваших требованиях к параллелизму (или о чем-либо еще): можете ли вы создать несколько потоков в ThreadPool, которые преобразуют строки в байтовые массивы и помещают их в очередь, и у вас есть еще один поток просмотр очереди и отправка данных?

1
ответ дан 5 December 2019 в 05:34
поделиться

Как уже говорили другие, класс Encoding уже оптимизирован для этой задачи, поэтому, вероятно, будет сложно сделать это быстрее. Есть одна микрооптимизация, которую вы могли бы сделать: использовать Encoding.ASCII вместо new ASCIIEncoding () . Но, как всем известно, микрооптимизации - это плохо;)

0
ответ дан 5 December 2019 в 05:34
поделиться

Я бы посоветовал профилировать то, что вы делаете. Я считаю сомнительным, что скорость преобразования строки в массив байтов представляет собой большую проблему с пропускной способностью, чем скорость самого сокета.

0
ответ дан 5 December 2019 в 05:34
поделиться

Еще один совет: я не знаю, как вы создаете свои начальные строки, но помните, что StringBuilder.Append ("что-то" ) действительно быстрее, чем что-то вроде myString + = "something".

Во всем процессе создания строк и их отправки через сокет-соединение я был бы удивлен, если бы узким местом было преобразование строк в байтовые массивы. Но мне очень интересно, сможет ли кто-нибудь проверить это с помощью профилировщика.

Бен

0
ответ дан 5 December 2019 в 05:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: