Оптимизация производительности: эффективное

реклама
Оптимизация
производительности:
эффективное
взаимодействие с
виртуальной
машиной
[email protected]
Sun Microsystems
Почему
• на одной машине работает быстрее, чем на
другой?
• падает производительность?
• периодически падает время отклика
приложения и оно увеличивается?
• растет объем используемой памяти?
• ...
Как понять в чем причина и нужно ли что-то
менять в вашем приложении?
2
Содержание
•
•
•
•
Архитектура HotSpot JVM
Эффективное взаимодействие с JIT-компилятором
Эффективное взаимодействие со сборщиком мусора
"out-of-box" производительность
3
Архитектура HotSpot JVM
• Runtime
> class loading, ...
• Сборщики мусора
• Интерпретатор
• JIT
> client
> server
4
Идеальная JVM
время, проведенное в JVM → 0
время, потраченное на сборку мусора → 0
количество кеш-промахов → 0
код, генерируемый динамическим компилятором
оптимален, учитывает специфику работы
приложения
• время на переключения между задачами и
бесполезное ожидание → 0
•
•
•
•
5
HotSpot - идеальная JVM?
“The perfect is the enemy of the good”
6
Содержание
•
•
•
•
Архитектура HotSpot JVM
Эффективное взаимодействие с JIT-компилятором
Эффективное взаимодействие со сборщиком мусора
"out-of-box" производительность
7
Эффективное взаимодействие с JIT
•
•
•
•
•
•
Типы компиляторов
Эргономика
Escape-анализ
Синхронизация
Многоуровневая компиляция
Что лучше – 32bit или 64bit jvm?
8
Типы компиляторов
• client – 32bit
> простой, ориентирован на приложения клиентского типа
(апплеты, игры)
> работает быстро, важна скорость запуска приложений
> генерирует менее оптимальный код
• server – 32bit, 64bit
> сложный, ориентирован на приложения серверного типа
(сервера java приложений, ...)
> работает дольше, важна производительность
создаваемого кода
> более серьезный анализ, сбор большей статистики
=> применение более агрессивных оптимизаций
9
Эргономика
• Машины серверного класса
памяти >= 2Gb
# 2cpu >= 2
• Выбор компилятора
платформа
архитектура
ОС
sparc 32-bit Solaris
Solaris
i586
Linux
Microsoft Windows
sparc64-bit
Solaris
Solaris
amd64
Linux
Microsoft Windows
машина
клиентского типа сервеного типа
client
server
client
server
client
server
client
client
server
server
server
server
server
server
server
server
10
«Какой компилятор работает?»
# jinfo JAVA_PID
Java System Properties:
...
java.vm.version = 14.0-b05
java.vm.name = Java HotSpot(TM) Client VM
...
os.name = Linux
os.arch = i386
os.version = 2.6.8-24-smp
...
java.specification.name = Java Platform API Specification
java.class.version = 51.0
java.vm.specification.version = 1.0
sun.arch.data.model = 32
java.specification.vendor = Sun Microsystems Inc.
java.vm.info = mixed mode
java.version = 1.7.0-ea
...
11
Escape-анализ (1)
• Является частью серверного компилятора
• Анализ непокидающих объектов для данного метода
class Escape1 {
Integer val; Escape1 next;
Escape1(Integer val) { this.val = val }
void example() {
Integer i1 = new Integer(1);
Integer i2 = new Integer(2);
Escape e1 = new Escape1( i1 );
Escape e2 = new Escape1( i2 );
e1.next = e2;
next = e2;
} }
• Oбъект O называется непокидающим для метода M, если:
>
>
>
>
>
выделен внутри метода M
не является объектом класса Thread или производного от него
не имеет финализатора
не сохраняется в статическом поле класса или в поле покидающего объекта
не передается другому методу в качестве аргумента, если только достоверно не
известно, что O не покидает и этот метод
12
Escape-анализ (2)
• Возможные оптимизации:
> устранение блокировок на непокидающих объектах
> оптимизация ссылок на объекты
> в ряде случаяев, размещение объекта в стеке или регистрах,
а не в куче (heap)
class Escape2 {
int fld1, fld2;
Escape2(int v1, int v2) { fld1 = v1; fld2 = v2; }
static void bigMethod() {
// Слишком большой метод, чтобы его встраивать...
}
}
=>
static void example(int v1, int v2) {
Escape2 e1 = new Escape2(v1, 10);
Escape2 e2 = new Escape2(v2, 5 - v1);
bigMethod();
return e1.fld1 + e2.fld2;
}
v1 + (5 – v1) = 5
13
Синхронизация Java объектов (1)
• операции захвата/освобождения блокировки дорогие
• в большинстве случаев захват объекта не является
состязательным (contended). Т.е.
> либо объект был свободным
> либо произошел рекурсивный захват в рамках потока
 Решение > использование легковесных блокировок
– эквивалентны CAS инструкциям - быстро
> использование тяжеловесных блокировок, если
невозможно использовать легковесные
– на порядок медленнее
14
Синхронизация Java объектов (2)
• Использование CAS инструкций может быть дорогим на
многопроцессорных машинах
> Решение — привязанные (biased) блокировки
> минус — дорогая операция отката привязки
– JVM анализирует статистику откатов связывания и может
запретить привязывание блокировки для определенных
типов объектов
> -XX:+UseBiasedLocking
• Адаптивная блокировка / adaptive spinning - выбор между
> взаимоблокировкой (spin) для корткого времени удержания
while (lockStillInUse);
> приостановлением (block) потока в случае длительного
времени удержания
15
Производительость привязанных
блокировок (1)
2xP4
2xAMD
4xAMD
2xUS-III
1xUS-T1
70
60
50
40
30
20
10
0
-10
-20
DB
Jack
Javac
Jess
MTRT
JVM98
Scimark
JBB2000
JBB2005
Volano
16
Производительость привязанных
блокировок (2)
2xP4
2xAMD
4xAMD
2xUS-III
1xUS-T1
300
250
200
150
100
50
0
Scimark2 Monte Carlo Sub-benchmark
17
Синхронизация Java объектов (3)
• Пропуск блокировки / lock elision
> избежание блокировки над локальными переменными
public String getStoogeNames() {
Vector v = new Vector();
v.add("One");
v.add("Two");
return v.toString();
}
> -XX:+DoEscapeAnalysis
• Укрупнение блокировки / lock coarsening
> объединение смежных synchronized блоков
public void addStooges(Vector v) {
v.add("One");
v.add("Two");
}
> -XX:+EliminateLocks
18
Советы по синхронизации
 Сразу расчитывайте на использование вашего кода в
многопоточных приложениях
> экономить на синхронизации нет смысла
> если synchronized не используется, то он ничего не стоит
 Используйте средства обнаружения состязательных
блокировок
> DTrace HotSpot monitor-contended-* пробы
> JVMStat
jstat -J-Djstat.showUnsupported=true -snap <pid> | grep _sync_
19
Оптимизация arraycopy()
• java.lang.System.arraycopy() интенсивно используется
в библиотеках JDK и клиентских приложений
• предыдущие оптимизации ограничивались inline
• в новом HotSpot реализованы ассемблерные
процедуры для всех типов данных
> предполагает неперекрывающийся блок памяти для
массива
20
Многоуровневая компиляция
• Идея – использование клиентского компилятора на
начальном этапе работы приложения и затем
переход к серверному
• преимущества
> улучшение времени запуска по сравнению с серверным
компилятором
> улучшение производительности по сравнению с
клиентским компилятором
• -server -XX:+TieredCompilation
• доступна только в jdk7, для 32bit jvm
21
Нужна ли вам 64bit JVM?
• только если
> необходимо большее адресное пространство
> необходим java heap > 4Gb
 минусы 64bit (-d64) по сравнению с 32bit (-d32) jvm
> растет нагрузка на память в силу использования 64bit указателей
> выравнивание по границам блока в 64-битном режиме увеличивает
размеры объекта
> увеличивается число D-cache промахов
 плюсы 64bit по сравнению с 32bit jvm
> в 2 раза больше регистров
> могут выигрывать приложения, использующие 64-битные вычисления
 Cжатые указатели: -XX:+UseCompressedOops
– использование 32bit указателей в 64bit jvm
– возможность адрессовать до 32Gb памяти
22
Содержание
• Архитектура HotSpot JVM
• Эффективное взаимодействие с JIT-компилятором
• Эффективное взаимодействие со сборщиком
мусора
• "out-of-box" производительность
23
Эффективное взаимодействие с GC
• Принципы работы сборщика мусора
• Взаимодействие со сборщиком мусора
>
>
>
>
>
>
>
>
Аллокация объектов
Большие объекты
NUMA
Группировка объектов
Обнуление указателей
Пулы объектов
Явный вызов сборщика мусора
Излишняя аллокация
• Проблемы с финализацией
• Утечка памяти
• Заключение
24
Сборка мусора (GC)
• Находит и освобождает место занимаемое ненужными
объектами
> Объекты вне транзитивного замыкания включающего roots (стеки
потоков, статические поля классов и т.д.)
• Автоматическая и безопасная
• Проще, если граф объектов “заморожен”
> Stop-the-world паузы
• Возможны различные подходы
> С дефрагментацией или без
> Алгоритмы: copying, mark-sweep, mark-compact, ...
> Аллокация: linear, free lists, ...
25
Сборка мусора с поколениями
• Молодые и старые объекты содержатся отдельно
> В пространствах называемых “поколения” (generations)
> Возможны разные алгоритмы для молодого и старого поколения
• Слабая гипотеза о поколениях
> Большинство объектов временные
> Mолодое поколение можно собирать
отдельно от старого
– Необходимо отслеживать ссылки
из старого поколения в молодое
– Барьер на запись (write barrier)
26
Фоновая сборка мусора
• Уменьшает влияние GC на приложение
• Сборка мусора происходит одновременно с работой
приложения
> Граф объектов модифицируется одновременно со сборкой мусора
> GC должен получать уведомления об этих изменениях (барьер на
запись)
• Если фоновый GC собирает только старшее поколение
> Нет необходимости
отслеживать изменения
в молодом поколении
27
Сборщики мусора в Hotspot VM
Алгоритм GC для
молодого
поколения
Алгоритм GC для
старого поколения
Как включить?
Default GC
Последовательный Последовательный
копирующий
mark-sweep compact
Concurrent
Mark-Sweep
Параллельный
копирующий
Фоновый параллельный -XX:+UseConcMarkSweepGC
mark-sweep
Incremental
Concurrent
Mark-Sweep
Параллельный
копирующий
Пошаговый фоновый
параллельный marksweep
-XX:+UseConcMarkSweepGC
–XX:+CMSIncrementalMode
Parallel
Scavenger
Параллельный
копирующий
Последовательный
mark-sweep-compact
-XX:+UseParallelGC
По умолчанию для -server
Parallel
Scavenger и
Parallel Old
Параллельный
копирующий
Параллельный marksweep-compact
-XX:+UseParallelOldGC
Фоновый
Garbage-First параллельный
(G1)
инкрементальный
копирующий
-XX:+UseSerialGC
По умолчанию для -client на
однопроцессорных машинах
Фоновый параллельный -XX:+UseG1GC
инкрементальный
Скоро в JDK7
копирующий
28
Последовательный/Serial GC
• Молодое поколение - последовательный копирующий GC
• Старое поколение — Mark-Sweep Compact
• отлично подходит для клиентских приложений не
требующих много (<200mb) памяти
• “stop-the-world” сборщик => длительные паузы при больших
объемах
29
Фоновый/Concurrent Mark-Sweep GC
• Предназначен для избежания долгих “stop-the-world” пауз
• Однако, приводит к увеличению нагрузки на процессор,
снижая общее быстродействие - «за все надо платить»
30
Эргономика GC
• Выбор сборщика мусора
> ParallelGC на серверных машинах при работе с
серверным JIT (-server)
> иначе – SerialGC
• Определение максимального размера памяти (-Xmx)
> Serial GC — 64Mb
> Parallel GC
– клиентская машина — min {¼ RAM, 1Gb}
– серверная машина — min {¼ RAM, 32Gb}
31
«Кто убирает ваш мусор?»
# jmap JAVA_PID
Attaching to process ID 12345, please wait...
Debugger attached successfully.
Client compiler detected.
using thread-local object allocation.
Parallel GC with 2 thread(s)
Heap Configuration:
MinHeapFreeRatio
MaxHeapFreeRatio
MaxHeapSize
NewSize
MaxNewSize
OldSize
NewRatio
SurvivorRatio
PermSize
MaxPermSize
...
=
=
=
=
=
=
=
=
=
=
40
70
134217728 (128.0MB)
655360 (0.625MB)
4294901760 (4095.9375MB)
1441792 (1.375MB)
12
8
12582912 (12.0MB)
67108864 (64.0MB)
32
«Netbeans вдруг подвис ...»
# jmap -heap NETBEANS_PID
Parallel GC with 2 thread(s)
Heap Configuration:
MinHeapFreeRatio = 40
MaxHeapFreeRatio = 70
MaxHeapSize
= 134217728 (128.0MB)
NewSize
= 0.625MB, MaxNewSize = 4095.9375MB
OldSize
= 1441792 (1.375MB)
PermSize
= 12.0MB, MaxPermSize = 64.0MB
Heap Usage:
PS Young Generation
Eden Space:
capacity = 7798784 (7.4375MB)
used = 4760384 (4.53985595703125MB)
free = 3038400 (2.89764404296875MB)
61.040080094537814% used
PS Old Generation
capacity = 30998528 (29.5625MB)
used = 10604488 (10.113227844238281MB)
free = 20394040 (19.44927215576172MB)
34.20965021306818% used
PS Perm Generation
capacity = 26083328 (24.875MB)
used = 25991728 (24.787643432617188MB)
free = 91600 (0.0873565673828125MB)
99.64881781956659% used
...
33
«Чем забита память?»
# jmap -histo NETBEANS_PID
...
Object Histogram:
Size Count Class description
------------------------------------------------------6371024 54861 * ConstMethodKlass
4834144 54861 * MethodKlass
3589960 44040 char[]
3519960 88375 * SymbolKlass
3470152 18522 int[]
3104776 4772
* ConstantPoolKlass
2160944 4772
* InstanceKlassKlass
2005360 4467
* ConstantPoolCacheKlass
1926008 5607
byte[]
1084200 45175 java.lang.String
630864 8661
java.lang.Object[]
615168 25632 java.util.HashMap$Entry
549208 8004
short[]
522120 6749
java.util.HashMap$Entry[]
465768 19407 java.awt.Rectangle
451880 5135
java.lang.Class
376776 7911
java.lang.Object[]
350552 1511
org.netbeans.editor.DrawEngine$DrawInfo
145152 3024
org.netbeans.editor.DrawEngineLineView
...
34
«Из-за чего переполнен PermGen?»
Симптом:
Exception in thread X java.lang.OutOfMemoryError: PermGen space
# jmap -permstat NETBEANS_PID
...
finding class loader instances ... done.
computing per loader stat ........done.
Computing liveness...........................done.
class_loader classes bytes parent_loader alive? type
<bootstrap> 1189 2727472 null
live <internal>
0xee431d58 1
1392
0xee22b3d0
dead
sun/reflect/DelegatingClassLoader@0xd4042360
0xee3fbd08 1
1400
0xee227418
dead
sun/reflect/DelegatingClassLoader@0xd4042360
...
total = 65 2303 5900688 N/A alive=11, dead=54 N/A
35
«Хотите знать больше про мусор?»
•
•
•
•
•
•
•
-verbose:gc
-XX:+PrintGC
-XX:+PrintGCDetails
-XX:+PrintHeapAtGC
-XX:+PrintGCTimeStamps
jconsole
jvisualVM
36
Эффективное взаимодействие с GC
• Принципы работы сборщика мусора
• Взаимодействие со сборщиком мусора
>
>
>
>
>
>
>
>
Аллокация объектов
Большие объекты
NUMA
Группировка объектов
Обнуление указателей
Пулы объектов
Явный вызов сборщика мусора
Излишняя аллокация
• Проблемы с финализацией
• Утечка памяти
• Заключение
37
Что создает работу для GC?
• Аллокация
> Большие объемы аллокации подразумевают большее
количество GC
• Объем живых данных
> Сложность GC пропорциональна
• Изменение ссылок в объектах
> Больше влияет на приложение, чем на GC
> Cоздает работу для GC с поколениями/фоновых GC
38
Аллокация объектов (1)
• Быстрая аллокация
>
>
>
>
10 инструкций без атомарных операций
Новый объект выделяется в молодом поколении
Не нужно отслеживать изменения ссылок
Гораздо быстрее чем стандартные аллокаторы для C/C++
• Быстрое освобождение новых объектов
> Сборка молодого поколения
 Совет
> Не бойтесь выделять маленькие объекты для промежуточных
результатов
> Избегайте бессмысленной аллокации (лишние вызовы GC)
39
Аллокация объектов (2)
• Анализ локальности (escape analysis)
> Скаляризация
> Оптимизация блокировок (lock elision)
 Совет
> используйте неизменяемые маложивущие объекты
вместо часто изменяемых долгоживущих объектов
> используйте простой код с большим количеством
аллокаций вместо сложных конструкций с меньшим
количеством аллокаций
40
Большие объекты
• Очень большие объекты
> дорого аллоцировать
– если объект не помещается в молодом поколении
> дорого инициализировать (обнуление)
• Частая аллокация и освобождение объектов разных
размеров приводит к фрагментации
> для GC без дефрагментации или с частичной
дефрагментацией
 Совет
> избегайте использования больших объектов,
но не в ущерб удобству
41
NUMA (1)
• Асимметричный доступ к памяти
> процессоры имеют разные задержки при доступе к
различным участкам памяти
> SPARC, Opteron, будущие процессоры Intel
• NUMA-аллокатор
> память под объект выделяется ближе к процессору на
котором выполняется аллоцирующий поток
> доступ к объектам быстрее из потока, в котором
произведена аллокация
• SPECjbb2005:
– +40% на 8-socket Opteron (8 узлов) SunFire x4600
– +300% на 72-socket (18 узлов) SunFire E25K
42
NUMA (2)
• Включается явно: -XX:+UseNUMA
> JDK6u2, для Solaris ≥ 10
> только в Parallel Scavenger
> В Linux скоро будет поддерживаться
• Паттерн «поставщик-потребитель» (producer-consumer)
 Создавайте локальную копию объекта, если он будет
часто использоваться
43
Группировка объектов
• GC старается расположить объекты ближе к тем, кто на
них ссылается
> На одной странице или даже на одной кэш-линии
> Пример: java.util.HashMap.table[] -> java.util.HashMap.Entry ->
key, value
table[]
Entry
1
key
1
value
1
Entry
2
key
2
value
2
> Не делайте излишних оптимизаций
• Реализовано в Parallel Scavenger и G1
44
Обнуление ссылок в объектах
• Редко помогает GC
> GC в состоянии определить доступен ли объект
> Делает код менее читаемым
> Может породить скрытые ошибки
• Исключения
> Структуры данных основанные на массивах
– Например ArrayList
– В этом случае вы сами занимаетесь управлением памятью
– Пользуйтесь стандартной библиотекой JDK!
> Предотвращение утечки памяти связанной с
финализацией
45
Обнуление локальных ссылок
• Не является необходимым
> JIT-компилятор проводит анализ достижимости
– Хотя интерпретатор обычно этого не делает
void foo() {
int[] array = new int[1024];
populate(array);
print(array); // последнее использование
// array в методе foo()
array = null; // не нужно!
// array не будет рассматриваться как живой объект
// сборщиком мусора
...
}
46
Пулы объектов (1)
• Наследие старых ВМ с очень медленной скоростью
аллокации
• Необходимо помнить
> GC с поколениями оптимизированы для работы с
маложивущими неизменяемыми объектами
> А не с долгоживущими часто модифицируемыми
объектами
> Локальные объекты могут быть оптимизированы
• Неиспользуемые объекты в пулах
> Лишняя работа для GC по сканированию/копированию
> Не приносят пользы – приложение их не использует
47
Пулы объектов (2)
• Исключения
> Объекты, которые дорого инициализировать
> Объекты, которые связаны с редкими ресурсами
(файловые дескрипторы и т.д.).
– пулы потоков (thread pools)
– пулы соединений к БД
> Используйте библиотеки JDK, если это возможно
48
Явный вызов GC (1)
• Не используйте явных вызовов GC!
> GC обладает информацией – скорость аллокации,
заполнение старшего поколения и т.д.
> System.gc() может повредить производительности
• Исключения
> Явный вызов в периоды бездействия приложения
• В HotSpot
> System.gc() вызывает полный stop-the-world GC
> -XX:+DisableExplicitGC позволяет
игнорировать System.gc()
49
Явный вызов GC (2)
• Фоновые GC
> Разработаны для того, чтобы избегать полных GC
> System.gc() делает полное GC!
• В HotSpot (для Concurrent Mark Sweep)
> -XX:+ExplicitGCInvokesConcurrent
 Остерегайтесь
> библиотек, которые вызывают System.gc()
50
Излишняя аллокация (1)
Избегайте ненужных аллокаций
 двойная аллокацию массива:
ArrayList<String> list = new ArrayList<String>();
list.ensureCapacity(1024);
 правильная версия:
ArrayList<String> list = new ArrayList<String>(1024);
51
Излишняя аллокация (2)
 Старайтесь реалистично оценивать размер структур
данных
ArrayList<String> list =
new ArrayList<String>(1024);
 Чем чревато добавление 1,000,000 строк в list?
> произойдет несколько операций по увеличению размера
массива
> многократная аллокация нескольких больших массивов
> многократное копирование содержимого
> потенциальная фрагментация памяти
52
Эффективное взаимодействие с GC
• Принципы работы сборщика мусора
• Взаимодействие со сборщиком мусора
>
>
>
>
>
>
>
>
Аллокация объектов
Большие объекты
NUMA
Группировка объектов
Обнуление указателей
Пулы объектов
Явный вызов сборщика мусора
Излишняя аллокация
• Проблемы с финализацией
• Утечка памяти
• Заключение
53
Финализация
• Метод оповещения приложения о недоступности
объекта
• Основное применение – освобождение
системных ресурсов
• Финализируемые объекты – все с непустым
методом finalize()
54
Аллокация / Освобождение
• Аллокация финализируемых объектов
> Существенно медленнее
> VM должна их отслеживать
• Освобождение финализируемых объектов
> Не менее двух циклов сборки мусора
> 1-й цикл
– Идентифицирует объект как недоступный
– Помещает объект в очередь для финализации
> 2-й цикл
– Освобождает объект после выполнения метода finalize()
– Если finalize() не сделает объект вновь доступным
> Между этими циклами может пройти неопределенное
количество времени и сборок мусора
55
Финализация и системные ресурсы
• Использование финализации для управления
системными ресурсами
> Требует GC перед тем, как объект будет
финализирован
> GC вызывается, когда заканчивается память
> Памяти обычно больше чем других системных
ресурсов
 Совет
> Управляйте ресурсами явно – используйте пулы
56
Эффективное взаимодействие с GC
• Принципы работы сборщика мусора
• Взаимодействие со сборщиком мусора
>
>
>
>
>
>
>
>
Аллокация объектов
Большие объекты
NUMA
Группировка объектов
Обнуление указателей
Пулы объектов
Явный вызов сборщика мусора
Излишняя аллокация
• Проблемы с финализацией
• Утечка памяти
• Заключение
57
Утечка памяти
• GC собирает все недоступные объекты
• Но он не будет собирать объекты, которые все
еще доступны!
• Утечки памяти в системах со сборкой мусора
вызываются
> объектами, которые доступны, но не используются
> использованием механизмов финализации и
объектов-ссылок (временная утечка)
58
Забытые обработчики событий
 Забытые обработчики событий в Swing, AWT и т.д.
{
}
ImageReader reader = new ImageReader();
cancelButton.addActionListener(reader);
Image image = reader.readImage(inputFile);
// reader остается достижимым пока
// cancelButton достижима
 Удаляйте более не используемые обработчики
{
}
ImageReader reader = new ImageReader();
cancelButton.addActionListener(reader);
Image image = reader.readImage(inputFile);
cancelButton.removeActionListener(reader);
59
Исключения могут менять
порядок исполнения (1)
try {
ImageReader reader = new ImageReader();
cancelButton.addActionListener(reader);
Image image = reader.readImage(inputFile);
cancelButton.removeActionListener(reader);
} catch (IOException e) {
// если исключение произошло в readImage()
// то reader останется в множестве обработчиков
// событий cancelButton
}
60
Исключения могут менять
порядок исполнения (2)
 Всегда используйте блок finally:
ImageReader reader = new ImageReader();
cancelButton.addActionListener(reader);
try {
Image image = reader.readImage(inputFile);
} catch (IOException e) {
...
} finally {
cancelButton.removeActionListener(reader);
}
61
Управление метаданными (1)
• Иногда необходимо:
> Ассоциировать метаданные с объектом
> В отдельном ассоциативном массиве
class ImageManager {
private Map<Image,File> map =
new HashMap<Image,File>();
public void add(Image image, File file) { ... }
public void remove(Image image) { ... }
public File get(Image image) { ... }
}
62
Управление метаданными (2)
• Если не вызвать remove(image)?
> Метаданные никогда не будут удалены
> Распространенная причина утечек памяти
• Хотелось бы:
> когда image больше не нужен
– контейнер получил нотификацию
– удалил соответствующий элемент
• Это как раз то, что делает WeakHashMap
private Map<Image,File> map =
new WeakHashMap<Image,File>();
63
Поиск утечек памяти
• Инструменты мониторинга: jconsole, jstat, visual
gc, VisualVM и т.д.
• Выясните на какие объекты ушла память
> постройте гистограмму классов при помощи jmap
> или -XX:+PrintClassHistogram
и Ctrl-Break
• Определите причины утечки
> произведите анализ достижимости при помощи jhat
(встроена в VisualVM)
64
Содержание
•
•
•
•
Архитектура HotSpot JVM
Эффективное взаимодействие с JIT-компилятором
Эффективное взаимодействие со сборщиком мусора
"out-of-box" производительность
65
"out-of-box" производительность
• В jdk6 удалось добиться:
> На тесте SPECjbb2005 Java 6 на
– 40% впереди конкурентов на Intel Core
– 30% впереди конкурентов на процессоре AMD Opteron.
> На тесте SciMark Java 6 на
– 40% впереди конкурентов
> На тесте VolanoMark Java 6
– быстрее Java версии 5 на 20%
> http://blogs.sun.com/vmrobot/entry/производительность_jvm_6_0
• JavaSE 6 performance releases
> Специальные версии Java SE с последними улучшениями в
производительности
> http://java.sun.com/javase/technologies/performance.jsp
66
Normalized to IBM SDK 5.0 32-bit Linux
SPECjbb2005
140
120
100
114.89
100.43
100
89.68
88.8
80
71.2
60
54.98
J2SE 5.0_08
Java SE 6 RC1
IBM 5.0 SR2
BEA JRockit 5.0_06
R26.4
40
20
0
53.83
32-bit JVM
64-bit JVM
67
SciMark2
Normalized to IBM SDK 5.0 32-bit Linux
120
100
112.79
100
105.26
104.9
60
59.57
56.84
J2SE 5.0_08
Java SE 6 RC1
IBM 5.0 SR2
BEA JRockit 5.0_06
R26.4
40
20
0
79.09
77.07
80
32-bit JVM
64-bit JVM
68
Normalized to IBM SDK 5.0 32-bit Linux
Volano 2.5.0.9
119.97
120
100
113.02
110.71
100
96.06
112.02
96.69
88.93
80
60
J2SE 5.0_08
Java SE 6 RC1
IBM 5.0 SR2
BEA JRockit 5.0_06
R26.4
40
20
0
32-bit JVM
64-bit JVM
69
Полезные ссылки (1)
• Производительность
> http://java.sun.com/javase/technologies/performance.jsp
> http://java.sun.com/performance/reference/whitepapers/6_performance.html
• Управление памятью
> http://java.sun.com/j2se/reference/whitepapers/memorymanagement_whitepape
r.pdf
> Finalization, Threads, and the Java Technology Memory Model
– http://developers.sun.com/learning/javaoneonline/2005/coreplatform/TS-328
1.html
> Memory-retention due to finalization article
– http://www.devx.com/Java/Article/30192
• OpenJDK
> http://www.openjdk.org
70
Полезные ссылки (2)
• Средства диагностики и наблюдения
> Monitoring and Management in 6.0
http://java.sun.com/developer/technicalArticles/J2SE/monitoring/
> Troubleshooting guide
http://java.sun.com/javase/6/webnotes/trouble/
> Jconsole
http://java.sun.com/developer/technicalArticles/J2SE/jconsole.html
> VisualVM
https://visualvm.dev.java.net
• Форумы и блоги на русском языке
> http://developers.sun.ru
> http://blogs.sun.com/vmrobot
• Слайды доклада “Оптимизация производительности: эффективное
взаимодействие со сборщиком мусора”, конференция TechDays 2008, СанктПетербург
http://developers.sun.ru/techdays2008
71
Спасибо!
[email protected]
Sun Microsystems
Скачать