Comments 28
все хорошо, только пример подкачал практический:
На массиве из миллиона игроков:
нет пока такой игры в которую одновременно играют миллион связанных игроков, поэтому со структурой код гораздо лучше для такого примера. Такая оптимизация там будет не уместна (фактически в лоб).
Ну вообще то коллега очень кратко пересказывает давно известный в геймдеве SOA против AOS. В примере не обязательно может быть миллион игроков, можно представить миллион юнитов или других элементов из игр.
я может отстал от жизни, но что-то я не могу себе представить чтобы во время игры надо было каким-то миллиону юнитов что-то вдруг прибавить или убавить, эта тема про базы данных скорее, но там это связано с особенностями энергонезависимого хранения и тоже в чистом виде вряд ли встречается.
Вот когда вы этих юнитов на сюрфейс выводите вот там наверно можно что-то подобное найти, потому что с точки зрения сюрфейса все юниты это просто картинки грубо говоря, но там тоже миллионов нет и есть всякие оптимизации чтобы перерисовать только то что изменяется.
первое что пришло в голову - миллион частиц и обновление из позиции со временем.
Миллион <чего бы то ни было> и однопоточный обход - это смерть перфу, извините.
Это могут быть не игроки, а какие нибудь юниты в RTS. И пусть не миллион даже, а десять тысяч, но зато обсчитываемые в 60fps.
ну например Не игровой персонаж, а единица времени зависит от реализации или она 1 от физики (там смотреть надо, например ушли далеко, легко не рисовать Не игрового персонажа, а например как быть с состояниями? их может быть много, вроде можно не обновлять состояния, конечно. Тогда Не игровые персонажи будут при появлении на дистанции отрисовки как бы находится там где игрок от них удалился)
Понятно, что перебор Vector<int> значений будет быстрее, чем Vector<Player>, но ведь нужна какая-то привязка health к игрокам.
Как обстоят дела с ABA в Вашем LockFreeQueue? Есть еще интересное видео для тех, кто интересуется Data Oriented Design от создателя Zig https://www.youtube.com/watch?v=IroPQ150F6c
Как то у вас получился замах на рубль, а удар на копейку. Заявленные темы интересны сами по себе (впрочем и известны давно), но у вас кроме поверхностных сообщений нет никаких захватывающих подробностей.
Ибрагим давай попердим
Если вы постоянно создаёте и удаляете объекты, то возможно вы что-то не так делаете?
Может достаточно определить заранее будут одинаковые объекты в программе/игре и при удалении очередного объекта не удалять его, а просто пометить удалённым? Придёт другой объект и займёт уже подготовленную память, да, данные перезаписать придётся, но зато "тормошить" память постоянно не надо.
для многопоточных приложений не проще определить какая функциональность может работать отдельно, а какая нет?
Понятно дело, что везде это достаточно реализовать, но определённая функциональность изначально понятна и сразу предполагает разделить на потоки. А другая функциональность не предполагает, и она будет больше тормозить очередь, чем помогать в работе.
Просто смотрите, где какую оптимизацию лучше применить.
Может достаточно определить заранее будут одинаковые объекты в программе/игре и при удалении очередного объекта не удалять его, а просто пометить удалённым? Придёт другой объект и займёт уже подготовленную память, да, данные перезаписать придётся, но зато "тормошить" память постоянно не надо.
А разве для этого как раз и не делают кастомные аллокаторы с пуллами памяти? На выделял на кучу объектов, те которые надо освободили, но не освободили на самом деле, а только пометили, а потом переиспользовали. Но конструторы и деструкторы вызывваются по настаяшему, а конкретные классы даже не подозревают каким образом для них добывают память.
кстати, еще заметил, при любом раскладе если имеем допустим 9 террейнов соединенных в 1, допустим 9 квадратов - тоесть мест где, чтото находится, соотв получается первично надо сначала понять где игрок - на каком квадрате->и тут уже списки этого квадрата(это самое тривиальное, конечно, может есть лучше способы )
Увы, статья ни о чем. Есть же книжка про оптимизации на плюсах, покрыто несколько страниц всего. Современные алгоритмы управления памятью настолько крутые что я бы вообще запретил говорить что нью/дэлит медленные в общем. Докажите сперва! Только что в этом убедился на мак ос. Я же умная Клава: выделил нужные куски один раз, стэк свободных элементов без блокировки, по сути всё выделение заключалось в возврате индекса в массиве... Ну и чего вы думаете? Замеры показали что я не выиграл, только лишь приблизился к системному по времени
Статья интересная, но все же было бы неплохо уведет какой-то живой пример, например мы загружаем данные из базы данных и отрисовываем карту, объекты это в вектор рисуем, удаляем. Будет ли в этом случае оптимизация эффективной, имеет ли она вообще смысл, если условно получение фичей из БД и отрисовка их занимает на пару порядков больше времени что даже самая не эффективная аллокация и вставка в вектор.
После множества выделений и освобождений памяти она может стать фрагментированной, что ускорит скорость поиска свободного блока
Ну так "ускоренная скорость" - это же хорошо, э?
Описаный DOD это только первый шаг, на миллионе юнитов все упрется в скорость RAM. Следующий шаг - нарезать данные на блоки и выполнять все операции над одним блоком, потом над другим.
Lock-free надо еще уметь писать. Я как-то сделал "самый быстрый" lock-free алгоритм, затем решил для сравнения добавить более медленные и на тестах с большим отрывом выиграл один из медленных... А все потому что мало кто может оценить производительность lock-free алгоритма на >300 строк кода.
В коде очереди ошибка: value нужно получать не из oldHead->data, а из oldHead->next.load()->data . И в цикле перед этим нужно ждать, чтобы oldHead->next.load() кто-нибудь заполнил. А сейчас у вас очередь просто порвётся, если продюсер не успеет новую ноду подсунуть.
Современные техники оптимизации производительности в C++. Кэш-локальность, аллокаторы и параллелизм