Мы сталкиваемся с некоторыми странными проблемами производительности JVM.
У нас есть большой и несколько непрозрачный компонент графического интерфейса (таблица Actuate Formula 1).
Если мы инициализируем все это из потока диспетчеризации событий (как и следовало бы), мы обнаружим, что код работает значительно медленнее (перетаскивание мыши для выбора ячеек приводит к заметной задержке).
Если мы инициализируем его в первый раз в основном потоке запуска и только потом начнем использовать его в EDT, он будет работать намного быстрее.
Когда я смотрю на то, почему он работает медленно, используя профилировщик, все время вызываются следующие методы:
- java.lang.Object.getClass ()
- java.lang.reflect.Array.newInstance (Класс, интервал)
- java.lang.Class.getComponentType ()
- java.lang.Thread.currentThread ()
Мы используем 64-битную JVM Sun Hotspot в Windows 7 (ту, что поставляется с JDK).
Кто-нибудь знает причину, по которой вышеуказанные методы могут работать намного медленнее, чем обычно?
Я думаю, что, может быть, это как-то связано с порядком загрузки классов ... это разумная теория? Кто-нибудь знает какие-либо другие способы диагностики, почему эти вызовы методов могут занимать много времени?
Прикрепил два скриншота из профилировщика. В обоих случаях все, что я делал, - это перетаскивал мышь по ячейкам электронной таблицы во время работы профилировщика. Таким образом, он просто обновляет компонент графического интерфейса и ничего больше не делает.
Первый тратит много времени на метод под названием «releaseLock ()». По какой-то причине это занимает много времени, потому что "getComponentType ()" занимает гораздо больше времени, чем обычно.
Второй - после того, как я «взломал», чтобы убрать стоимость «releaseLock ()», но теперь он просто тратит много времени на «getLock ()» из-за того, что getClass () и currentThread () занимают намного больше времени, чем обычно. :
Но важно то, что если я просто изменю порядок инициализации кода, выполнение этого кода не займет много времени (он даже не отображается в профилировщике).
Если бы мне пришлось оптимизировать getLock (), приложение все равно работало бы намного медленнее. Проблема действительно в том, что такие методы, как getClass (), занимают слишком много времени. Это невозможно компенсировать - getClass () вызывается слишком во многих местах!
Разница в производительности заметна даже без запущенного профилировщика.
Также помните, что мы не можем изменить этот код - это внешний компонент. Задача состоит в том, чтобы объяснить, почему в одних обстоятельствах код выполняется намного медленнее, чем в других.