Неизменяемые функциональные объекты в сильно изменяемой области

StackOverflow https://stackoverflow.com/questions/166379

Вопрос

В настоящее время я изучаю функциональное программирование в свое свободное время в Scala, и у меня возник простой вопрос новичка.

Я вижу элегантность наличия неизменных объектов при выполнении чего-то вроде вычисления вейвлет-преобразования Хаара - т.е. когда сами данные, представляемые объектами, не изменяются.

Но я видел блог, где у кого-то была небольшая игра в качестве примера демонстрации неизменности. Если объект существа получил повреждение, он не изменил своего состояния - он возвратил новый объект существа с новыми точками попадания и новым «агро в сторону X»; флаг. Но если бы мы разработали что-то вроде MMORPG, говорят в World of Warcraft. Сотня игроков на поле битвы ... возможно, тысячи атак и эффекты заклинаний "бафф / дебафф", влияющие на них по-разному. Можно ли по-прежнему проектировать систему с полностью неизменными объектами? Мне кажется, что в каждом «тике» будет огромное количество новых экземпляров. А чтобы получить действующий на данный момент экземпляр объектов, всем клиентам постоянно приходится проходить через какой-то центральный «gameworld». объект или?

Масштабируется ли для этого функциональное программирование, или это случай "лучшего инструмента для лучшей работы, вероятно, не неизменный здесь"?

Это было полезно?

Решение

  

Мне бы показалось, что каждый «тик» будет иметь огромный рой новых экземпляров.

Действительно, это так. У меня есть приложение на Haskell, которое читает ленту рыночных данных (около пяти миллионов сообщений в течение шестичасового торгового дня для данных, в которых мы заинтересованы) и поддерживает «текущее состояние»; для различных вещей, таких как самые последние цены предложения и предложения и количества для инструментов, насколько наша модель соответствует рынку и т. д. и т. д. Довольно страшно моделировать прогон этой программы против записанного фида в режиме профилирования и наблюдать он выделяет и собирает около 288 ТБ памяти (или почти в 50 000 раз больше оперативной памяти моей машины) за первые 500 секунд работы. (Эта цифра была бы значительно выше без профилирования, поскольку профилирование не только замедляет работу приложения, но и заставляет все это работать на одном ядре.)

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

Другие советы

Обычно в функциональном программировании у вас не будет конструкторов в стиле C ++. Тогда, даже если концептуально вы создаете объекты постоянно, это не означает, что компилятор должен создавать код для выделения нового объекта, потому что это не может повлиять на поведение программы. Поскольку данные являются неизменяемыми, компилятор может видеть, какие значения вы только что указали, и что было передано в ваши функции.

Затем компилятор может создать действительно сжатый скомпилированный код, который просто вычисляет поля в определенных объектах, когда они необходимы. Насколько хорошо это работает, зависит от качества компилятора, который вы используете. Тем не менее, чистый функциональный программный код сообщает компилятору гораздо больше о вашем коде, чем может предположить компилятор C для аналогичной программы, и поэтому хороший компилятор может генерировать код лучше, чем вы ожидаете.

Так что, по крайней мере, в теории, нет причин для беспокойства; Реализации функционального программирования могут масштабироваться так же, как реализации объектно-ориентированной кучи. На практике вам нужно понимать качество языковой реализации, с которой вы работаете.

MMORPG - это уже пример неизменности. Поскольку игра распространяется по серверам и системам геймеров, абсолютно не существует «игрового мира». объект. Таким образом, любой объект, который отправляется по проводам, является неизменным & # 8212; потому что это не изменяется получателем. Вместо этого новый объект или сообщение отправляется в качестве ответа, если таковой имеется.

Я никогда не писал распределенную игру, поэтому не знаю точно, как они реализованы, но я подозреваю, что обновления объектов либо вычисляются локально, либо отправляются как diff-файлы по проводам.

Например, вы играете в Command & amp; Завоевать. Ваш гигантский танк сидит в режиме готовности, охраняя вашу базу. Ваш противник приближается с легким танком, чтобы исследовать вашу базу. Ваш гигантский танк стреляет и поражает танк противника, нанося урон.

Эта игра довольно простая, поэтому я подозреваю, что многое вычисляется локально, когда это возможно. Предположим, что компьютеры двух игроков изначально синхронизированы с точки зрения состояния игры. Затем ваш противник нажимает, чтобы переместить свой легкий танк в вашу базу. Сообщение (неизменяемое) отправляется вам по проводам. Поскольку алгоритм перемещения танка (вероятно) является детерминированным, ваша копия Command & amp; Завоеватель может перемещать танк противника на экране, обновляя состояние игры (может быть неизменным или изменяемым). Когда легкий танк попадает в зону действия вашего гигантского танка, ваш танк стреляет. На сервере генерируется случайное значение (в этом случае в качестве сервера произвольно выбирается один компьютер), чтобы определить, попал ли выстрел по вашему противнику или нет. Предполагая, что танк был поражен, и обновление танка вашего оппонента должно быть сделано, только diff & # 8212; тот факт, что новый уровень брони танка снизился до 22% & # 8212; отправляется по проводам для синхронизации игр двух игроков. Это сообщение является неизменным.

Является ли объект на компьютере игрока, представляющий танк, изменяемым или неизменным, не имеет значения; это может быть реализовано в любом случае. Каждый игрок напрямую не меняет состояние игры других игроков.

Следует обратить внимание на неизменность того, что (при правильной реализации) создание объекта становится относительно легким. Если поле является неизменным, оно может быть разделено между экземплярами.

При разработке функциональной программы важно учитывать, что, как вы заявляете, неизменяемые объекты будут иметь некоторые накладные расходы. Также важно помнить, что, если объекты в вашей MMORPG-программе будут неизменными, это по своей природе будет более масштабируемым. Таким образом, первоначальные инвестиции в оборудование могут быть выше, но в будущем, по мере развития событий, вы сможете масштабироваться до своей базы игроков.

Еще одна важная вещь, которую следует учитывать, - это то, что сейчас самые мощные машины имеют 6 ядер на процессор. Рассмотрим машину с двумя процессорами по 6 ядер. Одно из этих 12 ядер может выполнять сборку мусора, поэтому накладные расходы на снос большого количества объектов могут быть компенсированы за счет того, что приложение легко масштабируется до остальных 11 ядер.

Также помните, что не каждый объект (и его дочерние объекты) необходимо полностью перестроить на копии. Любой тип ссылки, который не изменился, будет иметь только одно назначение ссылки, когда объект «скопирован».

Не думайте о создании объектов на уровне проводов. Например, оптимизированная среда выполнения для функционального языка, вероятно, сможет «обманывать»; когда дело доходит до замены объекта и фактической мутации существующей структуры, если он ничего не знает, он будет ссылаться на оригинал, а новый заменяет его полностью. Подумайте об оптимизации хвостовой рекурсии, но примените ее к состоянию объекта.

Сегодня я нашел блог, в котором ТОЧНО рассматриваются вопросы, которые я поднял в этом сообщении:

http://prog21.dadgum.com/23.html

Как почти все инструменты программирования, неизменяемые объекты являются мощными, но опасными в неправильной ситуации. Я думаю, что пример игры не очень хороший или, по крайней мере, очень надуманный.

Эрик Липперт имеет несколько интересных постов по этой теме. неизменности, и они довольно интересное чтение.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top