Это, вероятно, слишком общий характер, чтобы иметь четкий ответ. Подходы в C или C ++ по сравнению с Java будут сильно отличаться (способ, которым язык определяет объекты).
Основным было бы сохранение данных, к которым будет осуществляться доступ, в тесных циклах. Если ваш цикл работает с типом T и имеет члены m1 ... mN, но в критическом пути используются только m1 ... m4, рассмотрите разбиение T на T1, содержащее m1 ... m4, и T2, содержащее m4. ..mN. Возможно, вы захотите добавить к T1 указатель, который ссылается на T2. Старайтесь избегать объектов, которые не выровнены относительно границ кэша (очень зависит от платформы).
Используйте смежные контейнеры (обычный старый массив в C, vector в C ++) и пытайтесь управлять итерациями, чтобы идти вверх или вниз, но не случайным образом перепрыгивая через контейнер. Связанные списки являются убийцами локальности, два последовательных узла в списке могут находиться в совершенно разных случайных местах.
Контейнеры объектов (и обобщения) в Java также являются убийцами, в то время как в векторе ссылки являются смежными, а реальные объекты - нет (существует дополнительный уровень косвенности). В Java есть много дополнительных переменных (если вы new
два объекта один за другим, объекты, вероятно, окажутся в почти смежных областях памяти, даже если будет некоторая дополнительная информация (обычно два или три указателя) ) данных управления объектами между ними. GC будет перемещать объекты, но, надеюсь, не станет намного хуже, чем до запуска.
Если вы фокусируетесь на Java, создайте компактные структуры данных, если у вас есть объект, который имеет позицию и к которому нужно обращаться в узком цикле, рассмотрите возможность хранения примитивных типов x
и y
внутри вашего объект вместо создания Point
и удержания ссылки на него. Ссылочные типы должны быть обновлены, а это означает другое распределение, дополнительную косвенность и меньшую локальность.