Тонны мусора и минимум полезной работы или скроллинг в Idea

    Совсем недавно, перейдя на новый проект, я решил для разнообразия также перейти с Eclipse на Idea. С идеей у меня уже был опыт еще с 6-й версии, она мне нравилась, но проблем у нее было достаточно много. Тогда я отказался от нее в виду периодических глюков при долгой работе. Увидев, что уже на дворе 11-я версия я обрадовался и решил опять попытать счастья, так как по интерфейсу идея для меня гораздо приятней…

    Около месяца назад заметил, что при активной разработке, когда выделенные под кучу 768мб памяти заполнены под 80%, любое действие, вроде движения мышкой, переключения фокуса, просто прокрутка колесом мышки или непосредственно скроллом в окне вызывает большое потребление памяти и оставшиеся 20% памяти съедаются за несколько секунд работы. После чего, естественно, про комфортную работу можно забыть и приходится перегружать среду в виду постоянного срабатывания сборщика. Сегодня эта ситуация меня окончательно достала и я решил узнать — в чем же собственно проблема?

    Интуитивно я понимал, что вероятней всего каждое движение мышки и любое действие вроде прокрутки генерирует определенные события, которые потом обрабатываются, но ТАК МНОГО этих событий я не ожидал. Для затравки — 2 скриншота потребления памяти при движении мыши в окне редактора и скроллинге внутри открытого класса на 1000 строк:

    Движение: mouse move
    Скроллинг: scrolling

    Обычная прокрутка в окне редактирования кода в пике съедает почти 100мб памяти за несколько секунд… Любое движение мыши генерирует объектов на десятки мегабайт… Единственный позитивный момент во всем этом, что все эти объекты потом собираются.


    Естественно, мне стало интересно, что же такого генерирует идея при таких простых действиях. Итак, повторим эксперимент:

    1.5 млн объектов за прокрутку несколько дороговато, не находите? Зато теперь более менее стало понятно, где таится проблема. Это некий класс IntervalTreeImpl и его внутренний класс NodeCachedOffsets. Теперь у нас есть целых 2 пути для исследования: 1) скачать исходники IntervalTreeImpl и посмотреть и где и как создается NodeCachedOffsets и почему их так много (кстати, большое спасибо разработчикам за открытые исходные коды); 2) Проанализировать стек вызовов при прокрутке.

    Я пошел сначала первым путем, а потом имея представление о том, что происходит, проанализировал стек вызовов, чтобы окончательно убедится в верности выводов… Итак, кому интересно — исходник Вы можете найти тут. Попробуйте сами разобраться просмотрев код, где же таится проблема.

    Проанализировав код, становится более-менее понятно чего же ожидать от стека вызовов, вот собственно его самая интересная часть:

    и


    Обратите внимание на метод computeDeltaUpToRoot() он находится в самом конце стека и кроме этого вызывается довольно часто и в разных разветвлениях стека. Вообщем, имея код, ошибка на лицо — этот метод вызывается очень часто и во многих местах и при этом он постоянно генерирует новые объекты проблемного NodeCachedOffsets класса. Очевидно, что для решения проблемы нужно всего лишь избавится от постоянного создания этих объектов и заменить их, например, просто большим примитивом (как вариант) или изменить сам подход к отрисовке окна редактирования (требует много рефакторинга).

    В целом тут я хотел красиво решить проблему и продемонстрировать ее решение, но… Каково же было мое удивление, когда скачав последние исходники с целью исправления проблемы (git://git.jetbrains.org/idea/community.git), обнаружил, что эта ошибка уже исправлена, да еще и 5 месяцев назад… Сам фикс можно просмотреть тут. Странно, что в последней версии идеи (11.1.2) этого фикса все еще нет. Хотелось бы получить его поскорее… Тем не менее довольно приятно, что ребята заботятся о продукте.

    Похожие публикации

    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 21

      +10
      Неплохое исследование. Все бы так на баги реагировали — жили бы уже давно в мире идеального ПО
        +8
        Ну нечто идеальное это вообще маловероятная ситуация :-)
        Тут уместно выражение: «Уязвимости есть везде, а %productname% еще и удобный!»
        –3
        Хорошее исследование. Конкретно этого бага не замечал, а с тех пор как на работе дали побольше памяти, вообще за идею не волнуюсь.

        А баг не сказать что особо критичный, видимо поэтому и не стали в релизную ветку мержить его. Тут ЕАРы уже на носу, а вы на потребление памяти в джава приложении жалуетесь :)
          +3
          «Дьявол в деталях», на лицо явная архитектурная ошибка. Я было подумал что исправление могли замержить только в платную версию. Подход в стиле «гонка вооружений», когда вы за счет железа исправляете недостатки ПО, ни к чему хорошему не приведет и не важно что там на носу…
            +4
            Платная версия (IntelliJ IDEA Ultimate) отличается от бесплатной (Community) только набором дополнительных плагинов для пачки всяких J2EE, фреймворков, языков и технологий. Код платформы одинаковый.
            Тому, почему не замёрджили фикс, может быть много причин. Например, фикс слишком масштабный, и его опасно класть в ветку.
            Можно найти багрепорт или создать его и попросить в 11.1.3 положить. Не помешает приложить ссылку на этот пост.
              0
              … у меня для IDEA уже выставлено Xmx4096m, чтобы хоть как-то работала без особых тормозов с нашим проектом
              … и с ростом проекта приходится это значение увеличивать
              … на другие IDE переходить не хочется, ввиду отсутствия вменяемых альтернатив, приходится пока только память растить…
                +2
                Если у вас так память растёт, что 4 Гига и более нужно выделять, то здесь явно что-то не так (разве что проект ну совсем уж гигантский). Создайте багрепорт (http://youtrack.jetbrains.com) со снепшотом, в JetBrains вменяемые товарищи: если будет на что смотреть, они посмотрят.
                  0
                  А вы, совершенно случайно, интеграцию с Maven не используете?
                    0
                    А что с мавеном не так?
                      0
                      На большом проекте (~400) модулей всё плохо.

                      Работает всё довольно медленно (открытие, синхронизация по POM, сборка). Даже после всяких хитрых хитростей «Make» занимает секунд 5-10 против 1 секунды в «обычном» проекте.

                      Но самая большая беда — это наличие неких race-condition при импорте проекта. После открытия Maven проекта IDEA «на лету» генерирует обычные проектные файлы (.iml). Так вот, с большой вероятностью, с первого раза она это делает неправильно. Некоторые зависимости просто не импортируются. Нажатие кнопки «Reimport Maven Projects» (иногда приходится тыкать несколько раз) решает эту проблему до следующих изменений в POM файлах. Что хуже всего, на мелких проектах-то всё работает. Проблема, видимо, проявляется, когда количество модулей велико.

                      В последних версиях стало во многом существенно лучше, но всё равно нам пришлось отказываться от интеграции с Maven и возвращаться к сгенерированным проектам (плюс у нас есть некие дополнительные требования, которые проще поддержать в своём генераторе). Т.е у нас есть свой Maven plugin (по типу maven-idea-plugin), который генерирует *.iml файлы & каталог .idea, которые в свою очередь уже открываются в IDEA. Стало гораздо быстрее и стабильнее.

                      Но это наш главный проект (который ко всему прочему ещё и весьма странный в плане сборки), в маленьких «сопутствующих» проектах рекомендуемый подход — интеграция через стандартный плагин IDEA. В них всё работает.

                      Это так, в кратце :)
                        0
                        А для чего нужно столько много модулей? Из какой хоть области проект?
                          0
                          Оказывается, я ошибся, всего ~200 модулей (два раза посчитал из-за target/classes/META-INF/maven/.../pom.xml).

                          Проект — продукты для страховых компаний.
                            0
                            Не, все-таки мой проект лидирует. у меня 225 модулей.
                            Насчет проблемы с мавеном — подтверждаю. Когда модулей много идея перестает быть удобной и юзабельной.

                            Но!
                            Насчет количества модулей — это уже проблема организации проекта. Вы же не правите все 200 модулей? как правила работа ведется на 1-5 модулях. Получается надо разделять проект и в место модулей подцеплять артефакты.
                              0
                              >Насчет количества модулей — это уже проблема организации проекта. Вы же не правите все 200 модулей? как правила работа ведется на 1-5 модулях. Получается надо разделять проект и в место модулей подцеплять артефакты.

                              Совершенно верно. Но всё-таки, хочется, чтобы IDE помогала, и так проблем хватает :) Впрочем, со сгенерированными проектами всё довольно шустро работает.
                    +5
                    Это очень, очень большой размер хипа, пожалуйста дайте нам memory snapshot (http://devnet.jetbrains.net/docs/DOC-192.pdf)
                      0
                      Спасибо за инструкцию, сделаю в ближайшее время.
                    0
                    Пояните, почему вы считаете эту ошибку архитектурной? По мне это рядовая ошибка реализации.
                      +1
                      Ошибкой реализации это было бы если б была ошибка непосредственно в какой-то функции, здесь же метод который лежит глубоко по иерархии и часто вызывается, являясь правильным в то же время.Иерархией занимается архитектор, а не рядовой разработчик, который должен был обратить на это внимание…
                  +16
                  Переложили в 11.1.3, спасибо за детальное описание проблемы!
                    0
                    Вот что мне нравится в JetBrains — так это скорость реакции на сообщения об ошибках.
                    +1
                    И тем не менее Idea одна из самых шустрых IDE

                    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                    Самое читаемое