Оптимизация движка геодаты в L2J

Mosinnik

Знаменитый
Пользователь
Старожил I степени
Сообщения
7
Розыгрыши
0
Репутация
0
Реакции
9
Баллы
1 225
Хроники
  1. Interlude
Сборка
l2j
Занимался какое-то время оптимизацией потребления памяти GeoDriver от L2J и его скоростью работы. По памяти 40-45% экономии, по скорости получения высот из геодрайвера до пяти раз быстрее на отдельных типах блоков.
Код на гитхабе:
И еще статейку на хабр накидал о том что и почему было сделано:
 
Занимался какое-то время оптимизацией потребления памяти GeoDriver от L2J и его скоростью работы. По памяти 40-45% экономии, по скорости получения высот из геодрайвера до пяти раз быстрее на отдельных типах блоков.
Код на гитхабе:
И еще статейку на хабр накидал о том что и почему было сделано:
Если просто спортивный интерес, то понятно. Фактически для продакшена разница между 500 мб и 1200 мб для геоданных - пренебрежительно малая. Основной импакт по производительности на высоконагруженных проектах - случайный доступ к объектам. Оборачивать 400.000.000 ячеек или 15.000.000 блоков в объекты идея так себе изначально. Даже с учетом того, загрузка происходит последовательно, далеко не факт что все фактические ячейки памяти занимаемые геоблоками будут рядом. Прыгать по куче для огромного количества запросов задача сравнительно дорогая. О локальности кеша говорить ваще не приходится в таких ситуациях.

Для современных L2 эмулей давно уже промышленным стандартом является FFM API с дедупликацией, перепаковкой и оптимизированной выгрузкой всех геоданных в отдельный MemorySegment в офхип, с предрасчитанными смещениями для O(1) доступа напрямую, через MemoryLayout. Это обеспечивает эффективную загрузку кеш линий и очень сильно бустит латентность и скорость доступа к произвольным ячейкам и блокам. Переплатить 200-300 мб оперативки на хранения метадаты за снижение CPU расхода на 20-30% - это очень выгодная сделка)

Ну т.е, сам геоблок не обязательно создавать даже как объект. Это может быть статичный ацессор, который работает с входными координатами. Фактически, сами геоблоки(сектора) являются структурами в C++ ПТСа и тянуть их в яву изначально было неудачной попыткой скопировать оригинал без учетам особенностей ЯП реципиента. На ПТС нет отдельного мультислойного сектора. Есть NO_CELL сектора и COMPLEX. Комплексы могут содержать 64 ячейки или больше. Если 64 - одна логика, если больше - немного другая. NO_CELL по сути просто оптимизация. Поэтому один статичный ацессор к MemorySegment который получает на вход координаты, на их основе получает смещение(через lookup-метадату) на "блок" и от него получает нужные данные. Это все можно предрасчитать в рантайм при загрузке любой геодаты за 1-2 секунды при нормально распараллеленном загрузчике.


Так что одобрямс)
 
Последнее редактирование:
мема ради

 
Для современных L2 эмулей давно уже промышленным стандартом является FFM API с дедупликацией, перепаковкой и оптимизированной выгрузкой всех геоданных в отдельный MemorySegment в офхип, с предрасчитанными смещениями для O(1) доступа напрямую, через MemoryLayout. Это обеспечивает эффективную загрузку кеш линий и очень сильно бустит латентность и скорость доступа к произвольным ячейкам и блокам. Переплатить 200-300 мб оперативки на хранения метадаты за снижение CPU расхода на 20-30% - это очень выгодная сделка)

Да про уход в FFM думал, но решил не рапыляться и сделать упор только на память, а улучшения по скорости стали побочным эффектом и уже достаточно радуют. Был бы свой работающий проект или куда бы привлекли, где можно профит/метрики почекать по факту реализации, то может бы и скорость в первую очередь бустил, а так да спортивный интерес)

А есть где почитать/подсмотреть, что за предрасчитаныне смещения за О(1)? Для флет и комплекс вполне очевидно делается ценой памяти, а вот для мультилеера очень интересно узнать подход. Делал несколько попыток, но сделать плоскими данные из мультилеера, чтобы отказатсья вообще от деления на типы блоков и оставить плоскую мегакарту высот так и не выдумал. Буду признателен за ссылки или намеки (хотя бы в лс).

Ну т.е, сам геоблок не обязательно создавать даже как объект. Это может быть статичный ацессор, который работает с входными координатами.
Да как раз к этому и пришел, но не над MemoorySegment+позиция данных, а над простым ByteBuffer+позиция данных. Уход на статические методы сам по себе дал несколько процентов буста
 
Добавил пример того как добавить в актуальный L2J Mobius. Без всяких хитростей, просто лишь бы работало для примера.
Код в модуле l2jmobius_java21 ( ) и там же описание по переносу в сборку.
 
Назад
Сверху Снизу