Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Java [игнор отключен] [закрыт для гостей] / Генерация повторяющихся String-значений: работает ли при этом intern()-буфер ? / 9 сообщений из 9, страница 1 из 1
12.05.2013, 16:28:06
    #38254340
ozzmosis
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Генерация повторяющихся String-значений: работает ли при этом intern()-буфер ?
Здравствуйте.
В следующем примере в цикле генерятся одни и те же 10 строк, каждая по 1 млн раз:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
class StrTest2 {
    final static int N = 10000000;
    final static String pref = "1234567890abcdefghijklmnopqrstuvwxyz";
    public static void main(String[] args) {
      String st;
      long t0=System.currentTimeMillis();
      for(int i=0; i<N; i++) {
        st=(pref+(char)('a'+(i%10)));
        // ... 
      }
      long t1=System.currentTimeMillis();
      System.out.println("Done in "+(t1-t0)+" ms");
    }
}

Эта штука отрабатывает за ~7 сек. Для сравнения, то же самое через StringBuilder:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
class StrTest3 {
    final static int N = 10000000;
    final static String pref = "1234567890abcdefghijklmnopqrstuvwxyz ";
    public static void main(String[] args) throws IOException {

      StringBuilder sb = new StringBuilder( );
      sb.append(pref.toCharArray());
      long t0=System.currentTimeMillis();
      for(int i=0; i<N; i++) {
        sb.setCharAt( sb.length()-1, (char)('a'+(i % 10)));
      }
      long t1=System.currentTimeMillis();
      System.out.println("Done in "+(t1-t0)+" ms");
    }
}

- отрабатывает за 188 мс.

Каждая строка в яве есть immutable-объект, но при создании строк, значения которых естьString intern() description literal strings and string-valued constant expressions- дока говорит про буфер, в котором ищутся значения для возврата (вместо создания новой строки с тем же содержимым).

ВОПРОС-1. Можно ли как-то заставить яву использовать этот буфер и в случаях, когда строки генерятся так, как показано выше: st=(pref+(char)('a'+(i%10))) ?

ВОПРОС-2. Профилирование первого примера в NetBeans'e заставляет его работать в ТРИ раза дольше, т.е. 22 сек вместо 7! Как уменьшить влияние профилировщика ?

ВОПРОС-3. Профайлер показывает, что в первом примере создавалось 10'000'025 строк, однако объем выделенных байтов оказался равным 25'260'284. Как такое может быть, если каждая строка у мну являет собой 36 байт ? Если Ява как-то "жмёт" создаваемые строки, то где про это почитать ?

ВОПРОС-4. Профайлер (опять-таки) показывает, что создавалось 10'000'011 объектов класса StringBuilder. Чтение доки показало, что это из-за использования оператора "+". Но у коде видно, что оператор "+" используется ровно 10 млн раз внутри цикла и еще два раза вне цикла (в System.out.println("Done in "+(t1-t0)+" ms")).
Откуда тогда еще 9 StringBuilder'ов ?

ЗЫ. Замена "+" на вызов concat():
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
class StrTest2 {
    final static int N = 10000000;
    final static String pref = "1234567890abcdefghijklmnopqrstuvwxyz";
    public static void main(String[] args) {
      String st;
      long t0=System.currentTimeMillis();
      for(int i=0; i<N; i++) {
          st=pref.concat( Character.toString( (char)('a'+(i%10)) )  ); // 2625 ms
          //st=pref+(char)('a'+(i%10)); // 6922 ms
      }
      long t1=System.currentTimeMillis();
      System.out.println("Done in "+(t1-t0)+" ms");
    }
}

- улучшила время более чем в два раза (2625 vs 6922 ms), но всё равно хотелось бы понять, есть ли возможность задействовать внутренний буфер строк в таких случаях, как показано выше.
...
Рейтинг: 0 / 0
12.05.2013, 19:04:23
    #38254428
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Генерация повторяющихся String-значений: работает ли при этом intern()-буфер ?
ozzmosis дока говорит про буфер, в котором ищутся значения для возврата (вместо создания новой строки с тем же содержимым).
Нет там никакого "вместо".

ozzmosisВОПРОС-1. Можно ли как-то заставить яву использовать этот буфер и в случаях, когда строки генерятся так, как показано выше: st=(pref+(char)('a'+(i%10))) ?
Проще свой кэш реализовать. Буфер и кэш это разные понятия.
ozzmosisВОПРОС-2. Профилирование первого примера в NetBeans'e заставляет его работать в ТРИ раза дольше, т.е. 22 сек вместо 7! Как уменьшить влияние профилировщика ?
Там есть сэмплирующий профайлер. Его надо в плагинах доставить. Но не думаю что он сильно поможет на микробенчмарках.

ozzmosisВОПРОС-3. Профайлер показывает, что в первом примере создавалось 10'000'025 строк, однако объем выделенных байтов оказался равным 25'260'284. Как такое может быть, если каждая строка у мну являет собой 36 байт ? Если Ява как-то "жмёт" создаваемые строки, то где про это почитать ?
Часть мог удалить GC. Откуда инфа про 36 байт? На самом деле намного больше. Есть, правда, опция для Compressed Strings. Но не думаю что в ней дело.

ozzmosisВОПРОС-4. Профайлер (опять-таки) показывает, что создавалось 10'000'011 объектов класса StringBuilder. Чтение доки показало, что это из-за использования оператора "+". Но у коде видно, что оператор "+" используется ровно 10 млн раз внутри цикла и еще два раза вне цикла (в System.out.println("Done in "+(t1-t0)+" ms")).
Откуда тогда еще 9 StringBuilder'ов ?

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


ozzmosisулучшила время более чем в два раза (2625 vs 6922 ms), но всё равно хотелось бы понять, есть ли возможность задействовать внутренний буфер строк в таких случаях, как показано выше.
Переключения между server/client JVM, а так же предварительный разогрев для JIT компиляции могут показать ещё более удивительные результаты.
...
Рейтинг: 0 / 0
12.05.2013, 19:43:40
    #38254452
ozzmosis
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Генерация повторяющихся String-значений: работает ли при этом intern()-буфер ?
BlazkowiczНет там никакого "вместо".ну, нет так нет; просто померещилось при чтении:String intern()When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned.

BlazkowiczЧасть мог удалить GC. Откуда инфа про 36 байт? На самом деле намного больше. Есть, правда, опция для Compressed Strings. Но не думаю что в ней дело.вот эта хрень: "1234567890abcdefghijklmnopqrstuvwxyz" - имеет длину = 36 байт. КМК.
...
Рейтинг: 0 / 0
12.05.2013, 19:48:29
    #38254457
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Генерация повторяющихся String-значений: работает ли при этом intern()-буфер ?
ozzmosisКМК.
Домыслы - источник заблуждений.
Во-первых строки - Unicode, а не ASCII.
Во-вторых заходим в класс String видим какие-то поля помимо char[] (зависит от версии Java)
В-третих Java объект сам по себе имет некий заголовок ненулевого размера.
...
Рейтинг: 0 / 0
25.05.2013, 17:36:51
    #38273223
ozzmosis
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Генерация повторяющихся String-значений: работает ли при этом intern()-буфер ?
Подниму-ка тему.

Допустим, прога читает строки из текстового файла (скажем, "Войну и Мир"). И каждую такую строку присваивает одной и той же String-переменной `s`.
Вопрос: будет ли в итоге string pool (в предположении, что он достаточного размера) содержать уникальный список прочитанных строк ?
То есть, если далее я попробую создать новую переменную String s2 = "Пьер Безухов" - будет в строковом буфере эта строка ?
...
Рейтинг: 0 / 0
25.05.2013, 18:28:11
    #38273241
schwa
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Генерация повторяющихся String-значений: работает ли при этом intern()-буфер ?
ozzmosisПодниму-ка тему.

Допустим, прога читает строки из текстового файла (скажем, "Войну и Мир"). И каждую такую строку присваивает одной и той же String-переменной `s`.
Вопрос: будет ли в итоге string pool (в предположении, что он достаточного размера) содержать уникальный список прочитанных строк ??
Там не будет ничего. Ибо все строки будут создаваться через new String(...).
...
Рейтинг: 0 / 0
25.05.2013, 18:45:51
    #38273248
ozzmosis
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Генерация повторяющихся String-значений: работает ли при этом intern()-буфер ?
schwaТам не будет ничего. Ибо все строки будут создаваться через new String(...).это если к ним далее не применять intern()
...
Рейтинг: 0 / 0
25.05.2013, 18:53:11
    #38273256
ozzmosis
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Генерация повторяющихся String-значений: работает ли при этом intern()-буфер ?
PS. Вроде как нашел ответ в ководстве по сдаче SCJP, на странице 472 ("SCJP Sun Certified Programmer for Java 6 Exam 310-065.pdf"). Но не знаю, как проверить сиё: содержимое этого самого стринг-пула как-то можно вытряхнуть в виде дампа или еще чего-то ?
...
Рейтинг: 0 / 0
25.05.2013, 19:26:26
    #38273274
schwa
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Генерация повторяющихся String-значений: работает ли при этом intern()-буфер ?
Код: java
1.
2.
3.
4.
5.
public class S {
  public static void main(String[] args) {
    String s = new String("abc");
  }
}


javap -c SCompiled from "S.java"
public class S {
public S();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return

public static void main(java.lang.String[]);
Code:
0: new #2 // class java/lang/String
3: dup
4: ldc #3 // String abc
6: invokespecial #4 // Method java/lang/String."<init>":(Ljava/lang/String;)V
9: astore_1
10: return
}
...
Рейтинг: 0 / 0
Форумы / Java [игнор отключен] [закрыт для гостей] / Генерация повторяющихся String-значений: работает ли при этом intern()-буфер ? / 9 сообщений из 9, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]