我应该缓存System.getProperty(“line.separator”)吗?

时间:2013-08-04 17:07:23

标签: java caching optimization

考虑这样的方法:

@Override
public String toString()
{
    final StringBuilder sb = new StringBuilder();
    for (final Room room : map)
    {
        sb.append(room.toString());
        sb.append(System.getProperty("line.separator")); // THIS IS IMPORTANT
    }
    return sb.toString();
}

System.getProperty("line.separator")可以多次调用。

我应该使用public final static String lineSeperator = System.getProperty("line.separator")缓存此值吗? 以后只使用lineSeperator

System.getProperty("line.separator")和使用静态字段一样快?

5 个答案:

答案 0 :(得分:3)

在代码运行时,您不必担心行分隔符会发生变化,因此我认为没有理由不对其进行缓存。

缓存一个值肯定比反复执行一个调用更快,但差异可能可以忽略不计。

答案 1 :(得分:3)

我认为你的问题是错误的二分法。我不会每次都打getProperty,也不会为它声明一个静态字段。我只是将其提取到toString中的局部变量。

@Override
public String toString()
{
    final StringBuilder sb = new StringBuilder();
    final String newline = System.getProperty("line.separator"); 
    for (final Room room : map) sb.append(room.toString()).append(newline);
    return sb.toString();
}

顺便说一下,我已经对电话进行了基准测试。代码:

public class GetProperty
{
  static char[] ary = new char[1];
  @GenerateMicroBenchmark public void everyTime() {
    for (int i = 0; i < 100_000; i++) ary[0] = System.getProperty("line.separator").charAt(0);
  }
  @GenerateMicroBenchmark public void cache() {
    final char c = System.getProperty("line.separator").charAt(0);
    for (int i = 0; i < 100_000; i++) ary[0] = (char)(c | ary[0]);
  }
}

结果:

Benchmark                     Mode Thr    Cnt  Sec         Mean   Mean error    Units
GetProperty.cache            thrpt   1      3    5       10.318        0.223 ops/msec
GetProperty.everyTime        thrpt   1      3    5        0.055        0.000 ops/msec

缓存方法的速度提高了两个多个数量级。

请注意getProperty调用所有字符串构建的整体影响非常非常不可能显着。

答案 2 :(得分:2)

既然这么容易,为什么不呢? 至少 System.getProperty()的实现必须进行哈希表查找(即使在内部缓存)以查找您请求的属性,然后是虚方法getString()将在生成的对象上调用。这些都不是非常昂贵,但需要多次调用。更不用说会创建许多String个临时工具,之后需要GCing。

如果将其移到循环的顶部并重复使用相同的值,则可以避免所有这些问题。那为什么不呢?

答案 3 :(得分:1)

如果您发现了与此相关的性能问题,请确定。

如果你没有,那么不,查找不太可能有足够的开销。

这属于“微优化”和“过早优化”的一般或两个类别。 : - )


但是如果你担心效率,你可能会有一个更大的机会,因为你的toString方法每次都会重新生成字符串。如果toString将被调用很多,而不是缓存行终止符,请缓存生成的字符串,并在房间地图发生变化时清除它。 E.g:

@Override
public String toString()
{
    if (cachedString == null)
    {
        final StringBuilder sb = new StringBuilder();
        final String ls = System.getProperty("line.separator");
        for (final Room room : map)
        {
            sb.append(room.toString());
            sb.append(ls);
        }
        cachedString = sb.toString();
    }
    return cachedString;
}

...当地图发生变化时,请执行

cachedString = null;

这是一个很多更多的降压(降压是额外场的开销)。虽然它是每个实例而不是每个类,所以(参考之前关于效率的评论)只有在你有充分理由的情况下才能这样做。

答案 4 :(得分:0)

如果系统属性在应用程序期间保证保持不变,则可以对其进行缓存,但通常会丢失属性的功能,这会在更改时改变行为。

例如,文本生成器可以使用该属性为Windows或Linux生成文本,并允许在应用程序中动态更改属性,为什么不呢?

通常,捕获属性意味着使函数setProperty变得无用。