Таблицы Erlang ETS против передачи сообщений: проблемы оптимизации?
Я вхожу в существующий (игровой) проект, серверный компонент которого написан полностью в erlang. Время от времени, может быть мучительным, чтобы получить часть данных из этой системы (меня интересует, сколько виджета игрока 56) от процесса, которому это принадлежит. Предполагая, что я могу найти процесс, который владеет данными, я могу передать сообщение этому процессу и дождаться его передачи сообщения назад, но это не масштабируется хорошо для нескольких машин, и оно убивает время отклика.
Я рассматриваю возможность замены многих задач, которые существуют в этой игре, с системой, в которой информация, к которой часто обращаются несколько процессов, будет храниться в защищенной таблице ets. Владелец таблицы ничего не делал, кроме как получать сообщения об обновлениях (игрок только что потратил пять виджетов) и соответствующим образом обновил таблицу. Он перехватит все исключения и просто перейдет к следующему сообщению об обновлении. Любой процесс, который хотел бы знать, есть ли у игрока достаточные виджеты для покупки fooble, должен был бы только заглянуть за стол. (Да, я понимаю, что сообщение может быть в буфере, что уменьшает количество виджетов, но я имею эту проблему под контролем.)
Я боюсь, что мой вопрос - это не вопрос, а вопрос о комментариях. Я поддержу все, что полезно и достаточно объяснено или указано.
Каковы вероятные недостатки такой реализации? Меня интересуют подробности споров о блокировке, которые я, скорее всего, увижу, когда у вас есть один-писатель-несколько читателей, какие проблемы я буду распространять на разных компьютерах, и особенно: вклад от людей, которые сделали это раньше.
Ответы
Ответ 1
в первую очередь, поведение по умолчанию ETS является последовательным, как вы можете видеть по документации: Erlang ETS.
Он обеспечивает атомарность и изоляцию, а также множество обновлений/считываний, если они выполняются в одной и той же функции (помните, что в Erlang вызов функции примерно эквивалентен сокращению, единица измерения Erlang планировщик использует для совместного использования времени между процессами, поэтому многофункция ETS операция может быть разделена на большее количество деталей, создавая возможное состояние гонки).
Если вы заинтересованы в архитектуре ETS с несколькими узлами, возможно, вам стоит взглянуть на mnesia, если вы хотите использовать несколько узлов OOTB concurrency с ETS: Mnesia.
(подсказка: я говорю конкретно о таблицах ram_copies, методах add_table_copy и change_config).
При этом я не понимаю проблему с процессом (возможно, подкрепленную таблицей не названных ets).
Я объясняю лучше: главная проблема с вашим проектом - первое, основное предположение.
Это просто: у вас нет ни одного процесса написания!
Каждый раз, когда игрок берет объект, нажимает на игрока и т.д., он вызывает функцию бесплатного обновления без побочных эффектов, поэтому, даже если у вас есть один процесс, управляющий игровым состоянием, он также должен сообщать другим игрокам о том, эй, ты помнишь этот объект там? Просто забудь это!'; поэтому основная проблема многих многопользовательских игр - отставание: отставание, когда сетевое взаимодействие не является основной проблемой, много раз из-за блокировки процедур отправки/получения.
С этой точки зрения, используя непосредственно таблицу ETS, используя постоянную таблицу, словарь процесса (BAD!!!) и т.д. - это то же самое, потому что вы должны учитывать проблемы синхронизации, например, в объектно-ориентированном программировании языки с использованием общей памяти (Java, все?).
В конце концов, вы должны рассмотреть только ОДНУЮ главную проблему, связанную с разработкой приложения: согласованность.
После того, как последовательное приложение было разработано, только тогда вам следует сосредоточиться на настройке производительности.
Надеюсь, что это поможет!
Примечание. Я говорил о чем-то вроде сервера MMORPG, потому что думал, что вы говорите о чем-то подобном.
Ответ 2
Таблица ETS не решит ваши проблемы в этом отношении. Ваш код (который хочет получить или установить счетчик виджета игрока) всегда будет выполняться в процессе, и данные должны быть скопированы там.
Является ли это из кучи процесса или таблицы ETS, мало что меняет (при этом чтение из ETS часто происходит быстрее, потому что оно хорошо оптимизировано и не выполняет никакой другой работы, кроме получения и настройки данных). Особенно при получении данных с удаленного устройства node. Для мультиплееров ETS, скорее всего, быстрее, поскольку процесс будет обрабатывать запросы последовательно.
Что бы изменило ситуацию, если данные кэшируются на локальном node или нет. То, что происходит с самореплицирующими системами баз данных, такими как Mnesia, Riak или CouchDB. Mnesia фактически реализована с использованием таблиц ETS.
Что касается блокировки, последняя версия Erlang поставляется с усовершенствованиями ETS, которые позволяют нескольким читателям одновременно считывать из таблицы плюс один записывающий файл, который пишет. Единственным заблокированным элементом является строка, на которую записывается (таким образом, лучшая параллельная производительность, чем обычный процесс, если вы ожидаете много одновременных чтений для одной точки данных).
Обратите внимание, однако, что все взаимодействие с таблицами ETS не является транзакционным! Это означает, что вы не можете полагаться на запись значения на основе предыдущего чтения, потому что значение могло измениться за это время. Mnesia обрабатывает транзакции. Вы все еще можете использовать функции dirty_*
в Mneisa, чтобы выжать почти-ETS-производительность из большинства операций, если вы знаете, что делаете.
Ответ 3
Похоже, у вас есть куча вещей, которые могут произойти в любое время, и вам необходимо объединить данные в безопасном, единообразном виде. Посмотрите на поведение Generic Event. Я бы рекомендовал использовать это, чтобы создать сервер событий, и все эти процессы передают эту информацию через события на ваш сервер, и в этот момент вы можете зарегистрировать его или сохранить где-нибудь (например, таблицу ETS). В стороне, таблицы ETS не подходят для постоянных данных, например, сколько "виджетов" у игрока - рассмотрите Mnesia или отличный сбой только db как CouchDB. Оба они очень хорошо копируются на разных машинах.
Вы вызываете конфликт блокировок - у вас не должно быть замков. Сообщения обрабатываются в синхронном порядке по мере их получения каждым процессом. Фактически, вся суть семантики передачи сообщений, встроенной в язык, заключается в том, чтобы избежать совместного использования concurrency.
Подводя итог, обычно вы общаетесь с сообщениями, от процесса к процессу. Это волосатое для вас, потому что вам нужна информация от процессов, разбросанных повсюду, поэтому моя рекомендация для вас основана на идее сосредоточения всей информации, которая "интересна" вне процессов происхождения, в одном источнике в реальном времени.