Это было упомянуто, прежде чем то выделение стека просто переместит указатель вершины стека, то есть, единственную инструкцию относительно большей части архитектуры. Сравните это с тем, что обычно происходит в случае выделения "кучи".
операционная система поддерживает части свободной памяти как связанный список с данными полезной нагрузки, состоящими из указателя на начальный адрес бесплатной части и размер бесплатной части. Для выделения X байтов памяти список ссылок пересечен, и каждое примечание посещают в последовательности, проверяя, чтобы видеть, является ли ее размер по крайней мере X. То, когда часть с размером P> = X найдена, P разделяется на два, расстается с размерами X и P-X. Связанный список обновляется, и указатель на первую часть возвращается.
, Как Вы видите, выделение "кучи" зависит от факторов мая как то, сколько памяти Вы запрашиваете, насколько фрагментированный память и так далее.
Если все ваши данные на самом деле будут в формате 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
, пока не доказал , что это узкое место (или, по крайней мере, этот вид уродливого хака не помогает).
Я бы сказал, что то, как вы это делаете сейчас, очень хорошо. Если вас действительно интересует такая оптимизация на очень низком уровне, лучшая рекомендация, которую я могу дать, - это использовать 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;
}
Для чего вы пытаетесь оптимизировать? ПРОЦЕССОР? Пропускная способность?
Если вы хотите оптимизировать полосу пропускания, вы можете попробовать сжать строковые данные заранее.
Во-первых, профилируйте свой код, выясните, какие биты медленные, прежде чем пытаться оптимизировать на таком низком уровне.
Я полагаю, что функция 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, вероятно, не то, что нужно использовать в этом случае, потому что вы бы удвоили количество данных, которые вы отправляете через сокет.
Не имея ни малейшего представления о ваших требованиях к параллелизму (или о чем-либо еще): можете ли вы создать несколько потоков в ThreadPool, которые преобразуют строки в байтовые массивы и помещают их в очередь, и у вас есть еще один поток просмотр очереди и отправка данных?
Как уже говорили другие, класс Encoding уже оптимизирован для этой задачи, поэтому, вероятно, будет сложно сделать это быстрее. Есть одна микрооптимизация, которую вы могли бы сделать: использовать Encoding.ASCII
вместо new ASCIIEncoding ()
. Но, как всем известно, микрооптимизации - это плохо;)
Я бы посоветовал профилировать то, что вы делаете. Я считаю сомнительным, что скорость преобразования строки в массив байтов представляет собой большую проблему с пропускной способностью, чем скорость самого сокета.
Еще один совет: я не знаю, как вы создаете свои начальные строки, но помните, что StringBuilder.Append ("что-то" ) действительно быстрее, чем что-то вроде myString + = "something".
Во всем процессе создания строк и их отправки через сокет-соединение я был бы удивлен, если бы узким местом было преобразование строк в байтовые массивы. Но мне очень интересно, сможет ли кто-нибудь проверить это с помощью профилировщика.
Бен