Commit 35e4dbd5 authored by Jon Skeet's avatar Jon Skeet

Improve string encoding times.

Cache a reference to Encoding.UTF8 - the property access is (rather surprisingly) significant.
Additionally, when we detect that the string is all ASCII (due to the computed length in bytes being the length in characters), we can perform the encoding very efficiently ourselves.
parent 954e7208
...@@ -135,7 +135,7 @@ namespace Google.Protobuf ...@@ -135,7 +135,7 @@ namespace Google.Protobuf
/// </summary> /// </summary>
public static int ComputeStringSize(int fieldNumber, String value) public static int ComputeStringSize(int fieldNumber, String value)
{ {
int byteArraySize = Encoding.UTF8.GetByteCount(value); int byteArraySize = UTF8.GetByteCount(value);
return ComputeTagSize(fieldNumber) + return ComputeTagSize(fieldNumber) +
ComputeRawVarint32Size((uint) byteArraySize) + ComputeRawVarint32Size((uint) byteArraySize) +
byteArraySize; byteArraySize;
...@@ -323,7 +323,7 @@ namespace Google.Protobuf ...@@ -323,7 +323,7 @@ namespace Google.Protobuf
/// </summary> /// </summary>
public static int ComputeStringSizeNoTag(String value) public static int ComputeStringSizeNoTag(String value)
{ {
int byteArraySize = Encoding.UTF8.GetByteCount(value); int byteArraySize = UTF8.GetByteCount(value);
return ComputeRawVarint32Size((uint) byteArraySize) + return ComputeRawVarint32Size((uint) byteArraySize) +
byteArraySize; byteArraySize;
} }
......
...@@ -58,6 +58,8 @@ namespace Google.Protobuf ...@@ -58,6 +58,8 @@ namespace Google.Protobuf
/// </remarks> /// </remarks>
public sealed partial class CodedOutputStream : ICodedOutputStream public sealed partial class CodedOutputStream : ICodedOutputStream
{ {
private static readonly Encoding UTF8 = Encoding.UTF8;
/// <summary> /// <summary>
/// The buffer size used by CreateInstance(Stream). /// The buffer size used by CreateInstance(Stream).
/// </summary> /// </summary>
...@@ -294,16 +296,26 @@ namespace Google.Protobuf ...@@ -294,16 +296,26 @@ namespace Google.Protobuf
WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited); WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
// Optimise the case where we have enough space to write // Optimise the case where we have enough space to write
// the string directly to the buffer, which should be common. // the string directly to the buffer, which should be common.
int length = Encoding.UTF8.GetByteCount(value); int length = UTF8.GetByteCount(value);
WriteRawVarint32((uint) length); WriteRawVarint32((uint) length);
if (limit - position >= length) if (limit - position >= length)
{ {
Encoding.UTF8.GetBytes(value, 0, value.Length, buffer, position); if (length == value.Length) // Must be all ASCII...
{
for (int i = 0; i < length; i++)
{
buffer[position + i] = (byte)value[i];
}
}
else
{
UTF8.GetBytes(value, 0, value.Length, buffer, position);
}
position += length; position += length;
} }
else else
{ {
byte[] bytes = Encoding.UTF8.GetBytes(value); byte[] bytes = UTF8.GetBytes(value);
WriteRawBytes(bytes); WriteRawBytes(bytes);
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment