Оригинальный вопрос
Я новичок в STM. Одна вещь, которую я хотел бы сделать в Haskell, включает в себя большую часть данных и множество легких потоков, которые читают и записывают на небольшие части упомянутой большой части данных. Места, считываемые и записываемые, могут считаться по существу случайными и малыми. STM кажется большим для этого, но у меня есть некоторые вопросы относительно того, как атаковать проблему. Я вижу несколько возможных подходов, каждый из которых имеет некоторые недостатки, а некоторые из них кажутся довольно глупыми. Некоторые комментарии к этим или другим идеям для альтернатив были бы высоко оценены.
Пусть для простоты предположим, что большая часть данных является Data.Vector a
, где сами элементы сами по себе малы.
-
Весь фрагмент данных как один
TVar (Vector a)
. Я предполагаю, что это заставит много копировать огромную часть данных, поскольку STM будет думать, что каждая отдельная запись, возможно, затронула все общие данные. Разумеется, нет никакой магии, когда STM идентифицирует, что чтения и записи очень локализованы, и что согласованность по большому фрагменту данных не требуется? -
Огромное количество
TVar a
s, по существу одно для каждого элемента, дающее полностью локализованное STM, но по существу дублирование всегоVector a
. Это кажется глупым. -
Компромисс между 1 и 2 путем сегментации данных, чтобы у меня было разумное число
TVar (Vector a)
, соответствующее подвекторам данных. Я считаю, что это решение слишком сильно зависит от эвристики, например, насколько важны сегменты. - Сообщения
. Вместо того, чтобы каждый рабочий читал и записывал данные с помощью STM, каждый пишет сообщения с запросами на чтение данных или фрагменты данных, которые должны быть записаны через некоторый механизм STM, например,
TChan
. Специальный поток получает эти сообщения, передает данные, запрошенные через другойTChan
, или принимает полученные данные и записывает их в общую структуру данных. Это решение кажется свободным от проблем, связанных с решениями 1-3, но мне также кажется, что он по существу отказывается от использования тонкостей STM для обеспечения согласованности данных. Скорее, это просто передача сообщений. Конечно, часть передачи сообщения реализована с помощью STM, но моя реальная проблема решена с помощью передачи сообщений. STM кажется таким замечательным, передача сообщений так... meh.
Я думаю об этом правильно? Есть ли у кого-нибудь какие-либо намеки или другие предложения?
Имейте в виду, что у меня нет опыта работы с STM, и я еще не пробовал вышеуказанные решения. Я выйду из своего кресла, но иногда может быть хорошо подумать об этом, прежде чем что-либо попробовать.
Добавление: Пятый подход приходит от Натана Хауэлла и использует TArray
. Это похоже на то, что я хочу, но документация говорит:
В настоящее время он реализуется как Array ix (TVar e), но в будущем он может быть заменен более эффективной реализацией (однако интерфейс останется прежним).
Я полагаю, это означает, что TArray
- это только мой подход номер 2 в более приятной одежде. Документы, намекающие на "более эффективную" реализацию, интересны, так как намеки на то, что на самом деле есть более хороший подход.
Последующий ответ на вопрос Вагифа Верди
Vagif Verdi answer очень интересен, поэтому я сделал небольшой небольшой эксперимент попробовать. У меня нет времени, чтобы сгладить код прямо сейчас, поэтому те, кто заинтересован в этом, должны будут нести ко мне код, который не просто содержит простые вещи. Я решил использовать изменяемый вектор с 10 ^ 8 Int
как "большую общую часть данных", и пусть несколько читателей/писателей соответствуют потокам, принимаемым в сетевой сокет.
Обратите внимание, что код даже не читает или не записывает в общую часть данных. Он просто там, и каждый поток имеет в нем TVar
.
Так что же происходит? Я запускаю программу, и сразу она занимает около 780 МБ ОЗУ, что и следовало ожидать (это примерно то, что нужно 10 ^ 8 Int
). Теперь, если я использую netcat для подключения нескольких клиентов и напишу немного текста, который программа должна только распечатать и даже не записать в общие данные, процесс "использование ЦП достигает 100% в течение более секунды! Там заметное отставание перед текстом отображается. С яркой стороны использование памяти остается постоянным (в соответствии с ответом Вагифа Верди). Если я удалю вектор и TVar
, т.е. Вытащу все STM и общие данные, все будет очень быстрым и отзывчивым, и нет заметного использования ЦП, когда клиент что-то пишет.
Итак, хотя очень приятно видеть, что общие данные на самом деле не дублируются (хотя я полагаю, что я должен написать общие данные, чтобы полностью проверить это), существует очень тяжелое снижение производительности, связанное с поддержанием согласованного государство. Для меня теперь остается вопрос: как правильно атаковать эту проблему, сохраняя тонкости STM?
Спасибо Вагифу Верди за то, что он поднял очень интересные моменты.