为什么在 StringBuilder 构造函数中使用连接比调用 append() 快 100 倍?
Why is this usage of concatentation in StringBuilder's constructor 100X faster than calling append()?
我偶然发现了一个与 StringBuilder
的 append
方法相关的奇怪性能问题。我注意到似乎是一个愚蠢的错误 - 使用 StringBuilder
构造函数期间的字符串连接(这甚至在 NetBeans IDE 中显示为警告)。
版本 1
int hash = -1; //lazily computed, also present in Version 2
int blockID = ... //0 to 1000, also present in Version 2
int threadID = ... //0 to 1000, also present in Version 2
boolean hashed = false; //also present in Version 2
@Override
public int hashCode(){
if(!hashed){
StringBuilder s = new StringBuilder(blockID+":"+threadID);
hash = s.toString().hashCode();
hashed= true;
}
return hash;
}
数百万个此类对象是在运行时创建的,所以我认为通过进行以下更改,它会提供一些加速:
版本 2
@Override
public int hashCode(){
if(!hashed){
StringBuilder s = new StringBuilder(blockID);
s.append(":");
s.append(threadID);
hash = s.toString().hashCode();
hashed = true;
}
return hash;
}
错了!事实证明,版本 2 确实比版本 1 慢 100 倍。为什么???
附加信息
我正在根据 Java 6(客户要求)进行编译,并且我正在使用 Oracle 的 JVM。
我的性能测试涉及创建一百万个这样的对象并将它们放入 HashMap 中。使用版本 1 需要半秒,但使用版本 2 将近 50 秒。
因为您无意中设置了 StringBuilder
的初始容量,而不是向其附加 blockID
。参见 constructor documentation here。
public StringBuilder(int capacity)
Constructs a string builder with no
characters in it and an initial capacity specified by the capacity
argument.
试试这个:
StringBuilder s = new StringBuilder(9);
s.append(blockID).append(':').append(threadID);
您需要检查您的测试,因为您的第一个案例实际上正在做。
public int hashCode(){
if(!hashed){
StringBuilder s = new StringBuilder(
new StringBuilder(blockID).append(":").append(threadID).toString());
hash = s.toString().hashCode();
hashed= true;
}
return hash;
}
换句话说,它在第二种情况下做所有事情,而且会做更多,所以它会更慢。
简而言之,我怀疑你的测试是错误的,并不是你的表现越来越好。
我偶然发现了一个与 StringBuilder
的 append
方法相关的奇怪性能问题。我注意到似乎是一个愚蠢的错误 - 使用 StringBuilder
构造函数期间的字符串连接(这甚至在 NetBeans IDE 中显示为警告)。
版本 1
int hash = -1; //lazily computed, also present in Version 2
int blockID = ... //0 to 1000, also present in Version 2
int threadID = ... //0 to 1000, also present in Version 2
boolean hashed = false; //also present in Version 2
@Override
public int hashCode(){
if(!hashed){
StringBuilder s = new StringBuilder(blockID+":"+threadID);
hash = s.toString().hashCode();
hashed= true;
}
return hash;
}
数百万个此类对象是在运行时创建的,所以我认为通过进行以下更改,它会提供一些加速:
版本 2
@Override
public int hashCode(){
if(!hashed){
StringBuilder s = new StringBuilder(blockID);
s.append(":");
s.append(threadID);
hash = s.toString().hashCode();
hashed = true;
}
return hash;
}
错了!事实证明,版本 2 确实比版本 1 慢 100 倍。为什么???
附加信息
我正在根据 Java 6(客户要求)进行编译,并且我正在使用 Oracle 的 JVM。
我的性能测试涉及创建一百万个这样的对象并将它们放入 HashMap 中。使用版本 1 需要半秒,但使用版本 2 将近 50 秒。
因为您无意中设置了 StringBuilder
的初始容量,而不是向其附加 blockID
。参见 constructor documentation here。
public StringBuilder(int capacity)
Constructs a string builder with no characters in it and an initial capacity specified by the capacity argument.
试试这个:
StringBuilder s = new StringBuilder(9);
s.append(blockID).append(':').append(threadID);
您需要检查您的测试,因为您的第一个案例实际上正在做。
public int hashCode(){
if(!hashed){
StringBuilder s = new StringBuilder(
new StringBuilder(blockID).append(":").append(threadID).toString());
hash = s.toString().hashCode();
hashed= true;
}
return hash;
}
换句话说,它在第二种情况下做所有事情,而且会做更多,所以它会更慢。
简而言之,我怀疑你的测试是错误的,并不是你的表现越来越好。