我得到修复消息字符串(ASCII)作为ByteBuffer。我解析标记值对,并将值作为原始对象存储在树映射中,并将标记作为键。因此,我需要根据类型将date值转换为int/double/ byte[]等。
最简单的方法是创建新字符串并将其传递给标准转换器函数。例如:
int convertToInt(byte[] buffer, int offset, int length)
{
String valueStr = new String(buffer, offset, length);
return Integer.parseInt(valueStr);
}我知道在Java中,创建新对象是非常便宜的,还是有办法将这个ascii byte[]直接转换成原语类型的。我尝试了手写函数来做这件事,但发现它很耗时,并且没有带来更好的性能。
有没有第三方库可以做到这一点,最重要的是,这是值得做的吗?
发布于 2012-02-07 15:40:29
最重要的是它值得去做吗?
几乎可以肯定不是-而且在采取重大努力缓解它之前,您应该采取措施检查这是否是一个性能瓶颈。
你现在的表现怎么样?它需要是什么?(“越快越好”不是一个好的目标,否则你永远不会停下来--什么时候你可以说你“完成”了。)
分析代码--字符串创建真的有问题吗?检查你进行垃圾收集的频率等(同样,使用分析器)。
每种解析类型可能具有不同的特征。例如,对于解析整数,如果你发现在很大程度上你得到了一个数字,你可能想要在特殊情况下:
if (length == 1)
{
char c = buffer[index];
if (c >= '0' && c <= '9')
{
return c - '0';
}
// Invalid - throw an exception or whatever
}..。但是在你走上这条路之前,检查一下这种情况发生的频率。对从未实际出现的特定优化应用大量检查会适得其反。
发布于 2013-09-20 11:52:11
然而,在处理许多修复消息时,这很快就会积累起来,这一点同意Jon的观点。下面的方法将允许使用空格填充的数字。如果你需要处理小数,那么代码会稍有不同。两种方法之间的速度差异是11倍。ConvertToLong结果为0 GC。下面的代码是c#格式的:
///<summary>
///Converts a byte[] of characters that represent a number into a .net long type. Numbers can be padded from left
/// with spaces.
///</summary>
///<param name="buffer">The buffer containing the number as characters</param>
///<param name="startIndex">The startIndex of the number component</param>
///<param name="endIndex">The EndIndex of the number component</param>
///<returns>The price will be returned as a long from the ASCII characters</returns>
public static long ConvertToLong(this byte[] buffer, int startIndex, int endIndex)
{
long result = 0;
for (int i = startIndex; i <= endIndex; i++)
{
if (buffer[i] != 0x20)
{
// 48 is the decimal value of the '0' character. So to convert the char value
// of an int to a number we subtract 48. e.g '1' = 49 -48 = 1
result = result * 10 + (buffer[i] - 48);
}
}
return result;
}
/// <summary>
/// Same as above but converting to string then to long
/// </summary>
public static long ConvertToLong2(this byte[] buffer, int startIndex, int endIndex)
{
for (int i = startIndex; i <= endIndex; i++)
{
if (buffer[i] != SpaceChar)
{
return long.Parse(System.Text.Encoding.UTF8.GetString(buffer, i, (endIndex - i) + 1));
}
}
return 0;
}
[Test]
public void TestPerformance(){
const int iterations = 200 * 1000;
const int testRuns = 10;
const int warmUp = 10000;
const string number = " 123400";
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(number);
double result = 0;
for (int i = 0; i < warmUp; i++){
result = buffer.ConvertToLong(0, buffer.Length - 1);
}
for (int testRun = 0; testRun < testRuns; testRun++){
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < iterations; i++){
result = buffer.ConvertToLong(0, buffer.Length - 1);
}
sw.Stop();
Console.WriteLine("Test {4}: {0} ticks, {1}ms, 1 conversion takes = {2}μs or {3}ns. GCs: {5}", sw.ElapsedTicks,
sw.ElapsedMilliseconds, (((decimal) sw.ElapsedMilliseconds)/((decimal) iterations))*1000,
(((decimal) sw.ElapsedMilliseconds)/((decimal) iterations))*1000*1000, testRun,
GC.CollectionCount(0) + GC.CollectionCount(1) + GC.CollectionCount(2));
}
}
RESULTS
ConvertToLong:
Test 0: 9243 ticks, 4ms, 1 conversion takes = 0.02000μs or 20.00000ns. GCs: 2
Test 1: 8339 ticks, 4ms, 1 conversion takes = 0.02000μs or 20.00000ns. GCs: 2
Test 2: 8425 ticks, 4ms, 1 conversion takes = 0.02000μs or 20.00000ns. GCs: 2
Test 3: 8333 ticks, 4ms, 1 conversion takes = 0.02000μs or 20.00000ns. GCs: 2
Test 4: 8332 ticks, 4ms, 1 conversion takes = 0.02000μs or 20.00000ns. GCs: 2
Test 5: 8331 ticks, 4ms, 1 conversion takes = 0.02000μs or 20.00000ns. GCs: 2
Test 6: 8409 ticks, 4ms, 1 conversion takes = 0.02000μs or 20.00000ns. GCs: 2
Test 7: 8334 ticks, 4ms, 1 conversion takes = 0.02000μs or 20.00000ns. GCs: 2
Test 8: 8335 ticks, 4ms, 1 conversion takes = 0.02000μs or 20.00000ns. GCs: 2
Test 9: 8331 ticks, 4ms, 1 conversion takes = 0.02000μs or 20.00000ns. GCs: 2
ConvertToLong2:
Test 0: 109067 ticks, 55ms, 1 conversion takes = 0.275000μs or 275.000000ns. GCs: 4
Test 1: 109861 ticks, 56ms, 1 conversion takes = 0.28000μs or 280.00000ns. GCs: 8
Test 2: 102888 ticks, 52ms, 1 conversion takes = 0.26000μs or 260.00000ns. GCs: 9
Test 3: 105164 ticks, 53ms, 1 conversion takes = 0.265000μs or 265.000000ns. GCs: 10
Test 4: 104083 ticks, 53ms, 1 conversion takes = 0.265000μs or 265.000000ns. GCs: 11
Test 5: 102756 ticks, 52ms, 1 conversion takes = 0.26000μs or 260.00000ns. GCs: 13
Test 6: 102219 ticks, 52ms, 1 conversion takes = 0.26000μs or 260.00000ns. GCs: 14
Test 7: 102086 ticks, 52ms, 1 conversion takes = 0.26000μs or 260.00000ns. GCs: 15
Test 8: 102672 ticks, 52ms, 1 conversion takes = 0.26000μs or 260.00000ns. GCs: 17
Test 9: 102025 ticks, 52ms, 1 conversion takes = 0.26000μs or 260.00000ns. GCs: 18发布于 2012-02-07 15:28:05
看看ByteBuffer吧。它具有这样的功能,包括处理字节顺序(字节顺序)。
https://stackoverflow.com/questions/9172402
复制相似问题