Сколько времени нужно, чтобы создать 1 миллион потоков в Haskell?
Что я понимаю, у Хаскелла есть зеленые нити. Но насколько они легки. Можно ли создать 1 миллион потоков?
Или сколько времени займет 100 000 потоков?
4 ответа
import Control.Concurrent
import Control.Monad
n = 100000
main = do
left <- newEmptyMVar
right <- foldM make left [0..n-1]
putMVar right 0 -- bang!
x <- takeMVar left -- wait for completion
print x
where
make l n = do
r <- newEmptyMVar
forkIO (thread n l r)
return r
thread :: Int -> MVar Int -> MVar Int -> IO ()
thread _ l r = do
v <- takeMVar r
putMVar l $! v+1
на моем не совсем 2.5-ом ноутбуке это занимает меньше секунды.
установите n на 1000000, и будет трудно написать остальную часть этого поста, потому что ОС пейджинговая как сумасшедшая. определенно используя больше, чем концерт оперативной памяти (не дайте ей закончить). Если у вас достаточно оперативной памяти, она точно будет работать в 10 раз больше, чем версия 100000.
В соответствии с этим, размер стека по умолчанию равен 1 КБ, поэтому я предполагаю, что теоретически было бы возможно создать 1 000 000 потоков - стек занимал бы около 1 ГБ памяти.
Используя тест здесь, http://www.reddit.com/r/programming/comments/a4n7s/stackless_python_outperforms_googles_go/c0ftumi
Вы можете повысить производительность для каждого эталонного теста, уменьшив размер стека потоков до такого, который соответствует эталонному тесту. Например, потоки 1M со стеком 512 байт на поток занимают 2,7 с.
$ time ./A +RTS -s -k0.5k
В этом синтетическом тестовом случае порождение аппаратных потоков приводит к значительным накладным расходам. Работа только с зелеными нитями выглядит как предпочтительный вариант. Обратите внимание, что порождение зеленых нитей в Haskell действительно дешево. Я перезапустил вышеупомянутую программу с n = 1 м на MacBook Pro, i7, 8 ГБ ОЗУ, используя:
$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 7.6.3
Скомпилировано с -threaded и -rtsopts:
$ time ./thr
1000000
real 0m5.974s
user 0m3.748s
sys 0m2.406s
Уменьшение стека помогает немного:
$ time ./thr +RTS -k0.5k
1000000
real 0m4.804s
user 0m3.090s
sys 0m1.923s
Затем компилируется без -поточной:
$ time ./thr
1000000
real 0m2.861s
user 0m2.283s
sys 0m0.572s
И, наконец, без многопоточных и с уменьшенным стеком:
$ time ./thr +RTS -k0.5k
1000000
real 0m2.606s
user 0m2.198s
sys 0m0.404s