有人给了我一段代码,让它"不使用反射",因为它太慢了。代码目前使用反射来获取205个字段的值,将其全部附加到StringBuilder中并返回。它看起来像这样:
public String reflection()
{
StringBuilder sb = new StringBuilder();
sb.append("ExecutionEvent(");
// This will be very slow. We need to hard code the string
// encoding for this event type
// For now I am using reflection to quickly flesh out the framework
// code.
// TODO: fix this to not use reflection
String delim = "";
for (Field f : this.getClass().getFields())
{
try
{
Object o = f.get(this);
if (f.getType() == String.class)
{
// We wrap values with double quotes so cannot contain a double quote within a value.
// Change to single quote.
String value = o == null ? "" : o.toString().replace(""", "'");
// value = value.replace("'", "\'");
// value = value.replaceAll("\\", "");
sb.append(delim);
sb.append(""");
sb.append(value);
sb.append(""");
}
else
{
sb.append(delim);
String value = o.toString();
sb.append(value);
}
delim = ",";
}
catch (Exception ex)
{
logger.error("Cannot get value for field. {}", ex.getMessage());
}
}
if (sb.toString().contains("\"))
{
sb.replace(sb.indexOf("\"), sb.indexOf("\") + 1, "");
}
sb.append(")");
return sb.toString();
}
我把这段代码改成了:
public String noReflection() {
StringBuilder sb = new StringBuilder();
sb.append("ExecutionEvent(");
String delim = "";
for (Object o : getFields()) {
if(o instanceof String || o == null){
o = o == null ? "" : ((String) o).replace(""", "");
sb.append(String.format("%s"%s"", delim, o));
}
else
sb.append(String.format("%s%s", delim, o.toString()));
delim = ",";
}
if (sb.toString().contains("\")) {
sb.replace(sb.indexOf("\"), sb.indexOf("\") + 1, "");
}
sb.append(")");
return sb.toString();
}
for循环中的getFields()
方法引用我创建的另一个方法:
private List<Object> getFields(){
List<Object> values = new ArrayList<Object>();
values.add(announcementDate);
//Another ~200 values.add(fieldName);
values.add(whenIssuedIndicator);
return values;
}
我并排运行了这两种方法,它们是我唯一要改变的东西。我使用现有代码的基准测试来测量速度:
try ( ResultSet resultSet = stmt.executeQuery(sqls.get(8));) {
StopWatch timer = new StopWatch();
timer.start();
while (resultSet.next()) {
processRow(resultSet, runDate);
count++;
if (count % 100000 == 0) {
logger.info(feedName+ " | "+ new Object() {}.getClass().getEnclosingMethod().getName()+ " | OceanOrderFeed processed {} orders",
decimalFormat.format(count));
}
}
timer.stop();
int hours = (int) (timer.getTotalTimeSeconds() / 3600);
int minutes = (int) ((timer.getTotalTimeSeconds() - (hours * 3600)) / 60);
int seconds = (int) ((timer.getTotalTimeSeconds() - (hours * 3600) - (minutes * 60)));
logger.info(
feedName+ " | "+ new Object() {}.getClass().getEnclosingMethod().getName()
+ " | OceanOrderFeed completed. Processed {} orders in {} Hours : {} Minutes : {} Seconds",
decimalFormat.format(count), hours, minutes, seconds);
}
基准测试给出了以下结果:
No reflection
Processed 1,000,000 orders in 0 Hours : 8 Minutes : 49 Seconds
Processed 1,000,000 orders in 0 Hours : 9 Minutes : 3 Seconds
Processed 1,000,000 orders in 0 Hours : 10 Minutes : 11 Seconds
Reflection
Processed 1,000,000 orders in 0 Hours : 4 Minutes : 46 Seconds
Processed 1,000,000 orders in 0 Hours : 4 Minutes : 27 Seconds
Processed 1,000,000 orders in 0 Hours : 4 Minutes : 34 Seconds
使用反射全面更快。是否有一个问题,在代码我已经发布,导致的东西,应该是更快更慢?
问题是,我在我的循环中使用String.format()
时,我应该在原始代码中使用StringBuilder.append()
。
进一步阅读。原因是在当前的实现String。格式先使用正则表达式解析输入,然后填充参数。另一方面,带加号的串联得到了优化使用javac(而不是JIT)并使用StringBuilder。直接添加。