Системы событий удивительны, они делают чрезвычайно громоздкий код ручным и действительно позволяют динамически создавать игры с помощью простого взаимодействия объектов и игрового цикла. Я испытываю трудности с эффективностью моей текущей реализации. В настоящее время моя небольшая оптимизация разделения списков объектов на события, на которые они отвечают, сделала чудеса, но я должен сделать больше.
В настоящее время у меня есть два метода:
Проще всего : все объекты добавляются в вектор при отправке события, все объекты отправляются событием через метод handle_event ()
Более сложный: у меня есть карта со строкой в качестве ключа и int в качестве значения. Когда тип события добавляется, он добавляется к этой карте, при этом int просто увеличивается (должен быть лучший способ),
чтобы вектор векторов объектов затем возвращал новый вектор для обработки этого типа события.
Когда событие вызывается, оно просто вызывает соответствующее int в сопоставлении eventTypes с типом внутри вектора векторов объектов и отправляет это событие каждому объекту, обрабатывающему этот тип события.
Этот первый метод довольно медленный (очевидно) для многих объектов, но довольно быстрый для очень немногих объектов. Принимая во внимание, что второй метод довольно быстр с большими объектами, которые хотели бы обрабатывать различные типы событий, но медленнее, чем первый метод для объекта с объектами, обрабатывающими события того же типа.
Есть ли более быстрый (мудрый способ) способ? Есть ли более быстрый способ найти int из строкового типа? (Изначально у меня был enum, но он не допускал пользовательских типов, которые необходимы из-за желаемого уровня динамизма.)
источник
Ответы:
Похоже, вы говорите, что узким местом с большой производительностью является поиск идентификаторов событий (целых чисел) по их именам строк. Вы можете предварительно обработать данные игры, чтобы преобразовать все имена событий в целые числа перед запуском игры или, возможно, во время загрузки уровня; тогда вам не придется делать какие-либо преобразования во время игры.
Если объекты часто создаются и уничтожаются, в векторах объектов может быть много откатов. В этом случае вы могли бы извлечь выгоду, используя связанные списки вместо векторов; они быстрее для вставки и удаления.
источник
EventType takeDamageEvent = EventSystem::CacheEventType("takeDamageEvent");
. Сделайте его статическим членом классов, и у вас будет только одна копия в каждом классе, который в этом нуждается.Что ж, давайте сначала разберемся с простыми вещами. У вас есть это
map
между строками (имя события, предположительно) и целыми числами (индекс зарегистрированных слушателей событий).Время поиска в a
map
основано на двух вещах: количестве элементов на карте и времени, которое требуется для сравнения двух ключей (игнорируя проблемы с кэшем). Если время поиска является проблемой, одним из способов его обработки является изменение функции сравнения путем изменения типа строки.Давайте предположим, что вы используете
std::string
иoperator<
для сравнения. Это крайне неэффективно; это делает побайтовое сравнение. Вы не заботитесь о реальной строке меньше, чем сравнение; вам просто нужно какое-то сравнение, которое дает строго-слабый порядок (потомуmap
что иначе не работает).Поэтому вы должны использовать 32-байтовую строку фиксированной длины вместо
std::string
. Я использую их для идентификаторов. Тесты сравнения для этих фиксированных строк не выполняют побайтных сравнений; вместо этого они выполняют 32-битные (или 64-битные) сравнения. Он принимает каждые 4 байта как целое число без знака и сравнивает его с соответствующими 4 байтами другой строки. Таким образом, сравнение занимает максимум 8 сравнений. Это обеспечивает строго-слабое упорядочение, хотя упорядочение не имеет ничего общего с данными в виде символов.При хранении строк длиннее 31 байта (требуется символ NULL) строка усекается (но не с конца, а с середины. Я считаю, что энтропия имеет тенденцию быть наибольшей в начале и в конце). И строки, которые короче этого, дополняют оставшиеся символы
\0
.Теперь вы можете
map
полностью отказаться от использования хеш-таблицы. Если у вас действительно есть более 100 000 различных типов событий, это может быть хорошей идеей. Но я не знаю игры, где это было бы разумно.источник
Чтобы ответить на общий вопрос:
Здесь ничего нет. Все, что вы можете сделать, это определить конкретные потребности, которые у вас возникнут в ваших системах событий (может быть несколько разных), а затем использовать правильный инструмент для правильной работы.
Я реализовал и попытался обобщить тонны систем событий и пришел к такому выводу. Поскольку tradoff действительно разные, если вы делаете это во время компиляции или во время выполнения, если вы используете иерархии объектов или классные доски и т. Д.
Лучший способ - изучить различные виды систем событий, и тогда вы поймете, какую из них использовать в каком случае.
Теперь, если вам нужна действительно самая гибкая система, внедрите черную доску (среду выполнения) с динамическими свойствами событий, и вы получите что-то очень гибкое, но, возможно, очень медленное.
источник