снижение производительности передачи сообщений в отличие от общих данных - PullRequest
8 голосов
/ 27 ноября 2009

В наши дни очень много шума от использования блокировок и использования подходов передачи сообщений, таких как Erlang. Или об использовании неизменяемых структур данных, как в функциональном программировании по сравнению с C ++ / Java.

Но меня беспокоит следующее:

  1. AFAIK, Erlang не гарантирует доставку сообщений. Сообщения могут быть потеряны. Разве алгоритм и код не будут раздуваться и снова усложняться, если вам придется беспокоиться о потере сообщений? Какой бы распределенный алгоритм вы ни использовали, он не должен зависеть от гарантированной доставки сообщений.
  2. Что если Сообщение является сложным объектом? Разве нет огромного снижения производительности при копировании и отправке сообщений или, скажем, при хранении его в общем месте (например, в БД, к которой могут обращаться оба процесса)?
  3. Можете ли вы действительно полностью покончить с общими состояниями? Я так не думаю. Например, в БД вы должны получить доступ и изменить одну и ту же запись. Вы не можете использовать передачу сообщений там. Вы должны иметь блокировку или предположить механизмы управления оптимистичным параллелизмом, а затем выполнять откат на ошибки. Как работает Mnesia?
  4. Кроме того, не всегда нужно беспокоиться о параллелизме. Любой проект также будет иметь большой кусок кода, который вообще ничего не должен делать с параллелизмом или транзакциями (но они действительно заботятся о производительности и скорости). Многие из этих алгоритмов зависят от общих состояний (именно поэтому передача по ссылке или указатели так полезны).

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

Ответы [ 7 ]

6 голосов
/ 27 ноября 2009
  1. Это реальная жизнь : вам необходимо учитывать эту возможность независимо от языка / платформы. В распределенном мире (реальном мире) вещи терпят неудачу: живи с этим.

  2. Конечно, есть стоимость : в нашей вселенной нет ничего бесплатного. Но не следует ли вам использовать другую среду (например, file, db) вместо "больших объектов" в каналах связи? Вы всегда можете использовать «сообщение» для ссылки на «большие объекты», хранящиеся где-то.

  3. Конечно, нет: идея, лежащая в основе функционального программирования / Erlang OTP, заключается в том, чтобы " изолировать ", насколько это возможно, чтобы манипулировать областями, в которых было "общее состояние". Кроме того, четкое обозначение мест , в которых изменяется общее состояние, помогает тестируемости и отслеживаемости.

  4. Я полагаю, что вы упускаете суть: не существует такой вещи, как серебряная пуля. Если ваше приложение не может быть успешно построено с использованием Erlang, не делайте этого. Вы всегда можете использовать какую-то другую часть всей системы другим способом, то есть использовать другой язык / платформу. Erlang ничем не отличается от других языков в этом отношении: используйте правильный инструмент для правильной работы .

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

3 голосов
/ 30 ноября 2009

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

Что произойдет, если приложение настолько велико, что не помещается на одной машине? Что произойдет, если приложение перерастет одну машину?

Вы не хотите иметь один способ программирования приложения, если оно умещается на одной машине и совершенно другой способ его программирования, как только он превосходит одну машину.

Что произойдет, если вы захотите сделать отказоустойчивое приложение? Чтобы сделать что-то отказоустойчивое, вам нужны как минимум две физически разделенные машины и без общего доступа . Когда вы говорите о совместном использовании и базах данных, вы не упоминаете о таких вещах, как mySQL кластера достичь отказоустойчивости точно, поддерживая синхронизированные копии данные в физически разделенных машинах - много сообщений и копирование, которое вы не видите на поверхности - Эрланг просто разоблачает это.

Способ, которым вы программируете, не должен внезапно меняться для обеспечения отказоустойчивости и масштабируемости.

Erlang был разработан в первую очередь для создания отказоустойчивых приложений.

Совместно используемые данные на многоядерном ПК имеют свои собственные проблемы - при доступе к общим данным вам нужно приобрести блокировку - если вы используете глобальную блокировку (самый простой подход), вы можете в конечном итоге остановка всех ядер при доступе к общим данным. Общий доступ к данным на многоядерном может быть проблематичным из-за проблем с кэшированием, если ядра имеют локальные кэши данных, тогда доступ к «удаленным» данным (в некоторых других процессорах) может быть очень дорогим

Многие проблемы внутренне распределены, и данные никогда не доступны в одном месте. в то же время так - подобные проблемы хорошо сочетаются с мышлением Эрланга.

В распределенном параметре «гарантированная доставка сообщений» - невозможно - возможно, произошел сбой конечного компьютера. Таким образом, Erlang не может гарантировать доставку сообщений. он использует другой подход - система сообщит вам, если не удалось доставить сообщение (но только если вы использовали механизм ссылок) - тогда вы можете написать свою собственную ошибку восстановление.) * * тысяча двадцать-одна

Для чистого числа хрусталя Erlang не подходит - но в гибридной системе Erlang хорошо справляется с распределением вычислений между доступными процессорами, поэтому мы видим множество систем, в которых Erlang управляет распределением и отказоустойчивыми аспектами проблемы, но сама проблема решается на другом языке.

и другие языки используются

3 голосов
/ 27 ноября 2009

Реальные системы в любом случае всегда гибриды : я не верю, что современные парадигмы на практике пытаются избавиться от изменяемых данных и общего состояния.

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

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

Быстродействующему, но неработающему нет никакого преимущества : Но для нового кода или кода, которому не уделяется так много внимания, может случиться так, что он просто не является поточно-ориентированным и он не будет обрабатывать истинный параллелизм, и поэтому относительная «эффективность» не имеет значения. Один способ работает, а другой нет.

Не забывайте о тестируемости: Кроме того, какое значение вы можете придать тестированию? Параллелизм совместно используемой памяти на основе потоков просто не тестируется. Параллельный обмен сообщениями есть. Так что теперь у вас есть ситуация, когда вы можете проверить одну парадигму, но не другую. Итак, в чем смысл знать, что код был протестирован? Опасность даже в том, чтобы не знать, будет ли другой код работать в любой ситуации?

2 голосов
/ 28 ноября 2009

Несколько комментариев о недоразумении, которое у вас есть об Эрланге:

  • Erlang гарантирует, что сообщения не будут потеряны и что они будут доставлены в отправленном порядке. Основная ошибка состоит в том, что машина A не может общаться с машиной B. Когда это происходит, мониторы процессов и ссылки сработает, и системные сообщения об отключении узла будут отправлены зарегистрированным для него процессам. Ничто не будет отброшено. Процессы "вылетят", и супервизоры (если таковые имеются) попытаются перезапустить их.
  • Объекты не могут быть видоизменены, поэтому они всегда копируются. Одним из способов обеспечения неизменности является копирование значений в кучи других процессов erlang. Другим способом является выделение объектов в общей куче, ссылки на них в сообщениях и просто отсутствие каких-либо операций, которые их изменяют. Эрланг делает первым по производительности! Реальное время страдает, если вам нужно остановить все процессы, чтобы собрать мусор в общей куче. Спросите Java.
  • В Erlang есть общее состояние. Erlang этим не гордится, но прагматично в этом. Одним из примеров является локальный реестр процессов, который представляет собой глобальную карту, которая отображает имя на процесс, так что системные процессы могут быть перезапущены и получить свое старое имя. Эрланг просто пытается избежать общего состояния, если возможно . Таблицы ETS, которые являются общедоступными, являются еще одним примером.
  • Да, иногда Erlang работает слишком медленно. Это происходит на всех языках. Иногда Java слишком медленная. Иногда C ++ слишком медленный. Только из-за того, что в игре нужно было замкнуть замкнутый цикл, чтобы запустить серьезную векторную математику на основе SIMD, нельзя сделать вывод, что все должно быть написано на ассемблере, потому что это единственный язык, который быстр, когда это важно. Важно иметь возможность писать системы с хорошей производительностью, а Эрланг справляется довольно хорошо. См. Тесты по рысканию или кролику.

Ваши факты не являются фактами об Эрланге. Даже если вы думаете, что программирование на Erlang - это боль, вы обнаружите, что другие люди создают отличное программное обеспечение благодаря этому. Вы должны попытаться написать IRC-сервер на Erlang или что-то еще очень параллельное. Даже если вы больше никогда не будете использовать Erlang, вы бы научились думать о параллелизме по-другому. Но, конечно, вы это сделаете, потому что Эрланг просто удивителен.

Те, кто не понимает Erlang, обречены на плохую реализацию.

Хорошо, оригинал был про Лисп, но ... это правда!

1 голос
/ 27 ноября 2009

Например, в БД вы должны получить доступ и изменить одну и ту же запись

Но это обрабатывается БД. Как пользователь базы данных, вы просто выполняете свой запрос, и база данных обеспечивает его выполнение изолированно.

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

Многие оптимизации компилятора зависят также от отсутствия побочных эффектов и общего состояния.

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

Многие проблемы, сходные с проблемами параллелизма, возникают в однопотоковом коде. Современные процессоры конвейерны, выполняют команды не по порядку и могут выполнять 3-4 из них за цикл. Поэтому даже в однопоточной программе жизненно важно, чтобы компилятор и ЦП могли определять, какие инструкции могут чередоваться и выполняться параллельно.

0 голосов
/ 30 ноября 2009
  1. Erlang предоставляет супервизоры и обратные вызовы gen_server для синхронных вызовов, поэтому вы будете знать об этом, если сообщение не доставлено: либо вызов gen_server возвращает тайм-аут, либо весь ваш узел будет отключен и запущен, если супервизор сработает .
  2. обычно, если процессы находятся на одном и том же узле, языки передачи сообщений оптимизируют копирование данных, так что это почти похоже на разделяемую память, за исключением того, что объект изменяется впоследствии, что используется обоими впоследствии, что также невозможно сделать с помощью разделяемой памяти в любом случае
  3. Существует некоторое состояние, которое поддерживается процессами, передавая его себе в рекурсивных хвостовых вызовах, также некоторое состояние может, конечно, передаваться через сообщения. Я не очень много использую mnesia, но это транзакционная база данных, поэтому после того, как вы передали операцию mnesia (и она вернулась), вы в значительной степени гарантированно пройдете ..
  4. Именно поэтому такие приложения легко объединить в erlang с использованием портов или драйверов. Самыми простыми являются порты, они во многом похожи на канал Unix, хотя я думаю, что производительность не так уж велика ... и, как уже было сказано, передача сообщений обычно заканчивается просто передачей указателей, так как ВМ / компилятор оптимизирует копирование памяти .
0 голосов
/ 27 ноября 2009

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

Если скорость - это то, что вас беспокоит, сначала сделайте это однопоточным, а настройте дневное освещение из нее Тогда, если у вас есть несколько ядер и вы знаете, как разделить работу, используйте параллелизм.

...