Неизменяемые функциональные объекты в сильно изменяемой области - PullRequest
25 голосов
/ 03 октября 2008

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

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

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

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

Ответы [ 8 ]

16 голосов
/ 16 мая 2009

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

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

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

6 голосов
/ 03 октября 2008

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

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

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

4 голосов
/ 03 октября 2008

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

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

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

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

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

3 голосов
/ 04 октября 2008

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

3 голосов
/ 03 октября 2008

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

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

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

3 голосов
/ 03 октября 2008

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

2 голосов
/ 22 февраля 2010

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

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

0 голосов
/ 03 октября 2008

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

У Эрика Липперта есть несколько сообщений на тему неизменности, и они довольно интересны для чтения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...