Мои искренние извинения за нашумевшее название. Вот мелкий шрифт: с трехстрочным изменением кода мы смогли сделать редактор Protocol Buffer ~ в 300 раз быстрее при открытии файлов в проекте Java. Улучшения скорости могут варьироваться в зависимости от размера пути к классам проекта.
Некоторый фон
В Google наши проекты Eclipse больше, чем я когда-либо видел: путь к классам проекта может легко содержать от 4000 до 8000 файлов jar! В результате любые проблемы с производительностью, даже незначительные, значительно усиливаются в нашей среде. Частые задержки и зависания делают использование Eclipse разочаровывающим.
Одна из целей моей команды — сделать Eclipse способным справляться с нашими гигантскими проектами. Чтобы найти проблемы с производительностью (а затем и исправить их), мы регистрируем задержки в потоке пользовательского интерфейса Eclipse. В наших журналах мы обнаружили, что одним из пяти основных нарушителей был, к моему удивлению, Xtext .
Эта проблема
Прежде чем я продолжу, я хотел бы уточнить, что я не хочу разбивать Xtext. ИМХО, Xtext потрясающий и выполняет свое обещание: создать полноценный редактор из определения грамматики. Я считаю Xtext одним из трех лучших проектов Eclipse всех времен.
Хорошо, вернемся к нашей проблеме. Согласно нашим журналам, Xtext требуется несколько секунд, чтобы открыть документ (в нашем случае файл .proto.) Мы использовали Xtext 2.0.3 M6 и Eclipse 3.8 M6, BTW.
Трассировка зарегистрированного стека выглядит следующим образом:
java.util.zip.ZipFile.(ZipFile.java:131) java.util.jar.JarFile.(JarFile.java:150) java.util.jar.JarFile.(JarFile.java:114) org.eclipse.xtext.ui.resource.XtextResourceSetProvider.computePlatformURIMap(XtextResourceSetProvider.java:68) org.eclipse.xtext.ui.resource.XtextResourceSetProvider.get(XtextResourceSetProvider.java:49) org.eclipse.xtext.ui.editor.model.ResourceForIEditorInputFactory.getResourceSet(ResourceForIEditorInputFactory.java:89) org.eclipse.xtext.ui.editor.model.JavaClassPathResourceForIEditorInputFactory.getResourceSet(JavaClassPathResourceForIEditorInputFactory.java:59) org.eclipse.xtext.ui.editor.model.ResourceForIEditorInputFactory.createResourceFor(ResourceForIEditorInputFactory.java:68) org.eclipse.xtext.ui.editor.model.ResourceForIEditorInputFactory.createResource(ResourceForIEditorInputFactory.java:64) org.eclipse.xtext.ui.editor.model.JavaClassPathResourceForIEditorInputFactory.createResource(JavaClassPathResourceForIEditorInputFactory.java:37) org.eclipse.xtext.ui.editor.model.ResourceForIEditorInputFactory.createResource(ResourceForIEditorInputFactory.java:53) org.eclipse.xtext.ui.editor.model.XtextDocumentProvider.setDocumentContent(XtextDocumentProvider.java:118)
Согласно коду XtextResourceSetProvider, при создании документа Xtext (например, открытие файла .proto) Xtext считывает манифест в каждом отдельном банке в пути к классам. Учитывая огромные пути к классам в наших проектах, это сканирование может занять значительное время.
Поскольку мы так и не получили четкого ответа, почему Xtext делает это, у нас было два варианта:
- Прочитайте код Xtext и EMF, чтобы понять проблему. Чтение слоев недокументированного кода не так плохо, как кажется. Однако для понимания кода и его исправления требуется время. К сожалению, у меня его нет. Другие проекты требуют моего немедленного внимания.
- Сделайте обоснованное предположение, чтобы решить проблему. Продолжайте читать, пожалуйста.
Решение
Мы пошли на альтернативу «образованное предположение». При условии:
- мы обнаружили, что редактор прототипов хорошо работает в не-Java проектах (например, в CDT ,)
- мы подозревали, что это сканирование пути к классам было необходимо для пользовательских языков на основе JVM (таких как Xtend ,) и
- язык протокола Buffer не зависит от типов JVM
мы были вполне уверены, что сканирование пути к классам проекта не добавило никакой ценности, и мы могли безопасно удалить его.
Изменение буквально потребовало добавления 3 строк кода. Прелесть Xtext в том, что использует Guice под одеялом. Нам нужно было только заменить XtextResourceSetProvider другой реализацией IResourceSetProvider в модуле проекта пользовательского интерфейса:
@Override public Class<? extends IResourceSetProvider> bindIResourceSetProvider() { return SimpleResourceSetProvider.class; }
Вот и все!
В следующей таблице показано значительное улучшение производительности. Пожалуйста, обратите внимание на смехотворное количество времени, которое затрачивалось на открытие небольших файлов.
LOC | Время открывать | |
---|---|---|
Перед | После | |
199 | 5280 мс | 17 мс |
19 | 3885 мс | 6 мс |
27 | 2033 мс | 7 мс |
Обратите внимание, что строки кода — не единственная метрика, которая влияет на производительность. Есть и другие факторы (например, область видимости), которые необходимо учитывать при измерении производительности.
Мы не потеряли никакой функциональности в наших редакторах после внесения этих изменений. Подсветка синтаксиса, помощь по содержанию, определение объема, гиперссылка и проверка работали нормально.
Вывод
Xtext — отличная среда для создания редакторов для пользовательских языков. Хотя это зрелый проект, все еще есть возможности для улучшения. В этой статье я показал вам, как мы значительно улучшили производительность нашего редактора на основе Xtext с помощью всего лишь нескольких строк кода. Мы смогли устранить проблему в рекордно короткие сроки, используя комбинацию данных, фактов и интуиции.
Обратная связь всегда приветствуется ?