Должен ли я кэшировать систему.метод getproperty("линии.разделитель")?

рассмотрим такой метод:

@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 ответов


Я вижу, что ваш вопрос представляет собой ложную дихотомию. Я бы ни за что не позвонил 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 вызов против всего, что строковое здание очень, очень маловероятно, что это будет заметно.


вам не нужно бояться, что разделитель строк изменится во время работы вашего кода, поэтому я не вижу причин против его кэширования.

кэширование значения, безусловно, быстрее, чем выполнение вызова снова и снова, но разница, вероятно, будет незначительной.


Так как это так легко сделать, почему нет? по крайней мере реализация System.getProperty() придется сделать поиск хэш-таблицы (даже если кэшируется внутри), чтобы найти запрашиваемое свойство, а затем виртуальный метод getString() будет вызываться для результирующего объекта. Ни один из них не очень дорогим, но должен быть вызван несколько раз. Не говоря уже о многих String временные будут созданы и нуждаются в GCing после.

Если вы переместите это на вершину ваш цикл и повторное использование одного и того же значения, вы избегаете всех этих проблем. Так почему бы и нет?


если вы узнали о проблеме производительности, которая, как вы знаете, относится к этому, да.

если у вас нет, то нет, поиск вряд ли будет иметь достаточно накладных расходов, чтобы иметь значение.

это подпадает под одну или обе общие категории "микро-оптимизация" и "преждевременная оптимизация".":-)


но если вы беспокоитесь об эффективности, вы, вероятно, есть много больше возможностей в ваш toString метод регенерация строки каждый раз. Если toString будет вызываться много, а не кэшировать Терминатор строки, кэшировать сгенерированную строку и ясно, что всякий раз, когда ваша карта комнат меняется. Например:

@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;

это много больше взрыва для доллара (доллар является накладными расходами дополнительного поля). Предоставлено это на экземпляр, а не на класс, поэтому (ссылка на более ранний комментарий об эффективности) только сделайте это, если у тебя есть на то веская причина.


Если системное свойство гарантированно останется постоянным во время приложения, его можно кэшировать, но в целом вы потеряете функцию свойства, которая изменяет поведение при его изменении.

например, генератор текста может использовать свойство для генерации текста для windows или linux и позволяет динамически изменять свойство в приложении, почему бы и нет ?

В общем случае улавливание свойства подразумевает бесполезность функции методов-setproperty.