вторник, 13 сентября 2016 г.

Lazy ByteString или Haskell - кому сказать прощай?

Наверное вы уже знаете, что у меня есть 3 версии RedisSharding: Perl версия, Haskell версия с использованием Lazy ByteString и Strict Haskell версия с использованием attoparsec.

В старой заметке Redis Sharding: Lazy vs Strict (http://by-need.blogspot.com/2013/01/rs.html) утверждается, что Lazy и Strict версии примерно одинаковы по производительности.

Но, так как RedisSharding используется в основном для больших MGET команд, сравнение Lazy и Strict версии в pipeline режиме не производилось. А вот сейчас как-то случайно...

Оказалось, что Lazy версия в pipeline режиме имеет очень маленькую производительность.

cpuset -l 0 ./redis_sharding --port=8090 --nodes=127.0.0.1:8081,127.0.0.1:8082,127.0.0.1:8083,127.0.0.1:8084 +RTS -s -N1 -A10M -qa


Lasy версия.

> redis-benchmark -p 8090 -n 10000 -c 10 -q -t set,get,mset -P 1
SET: 20000.00 requests per second
GET: 19801.98 requests per second
MSET (10 keys): 9891.20 requests per second

> redis-benchmark -p 8090 -n 10000 -c 10 -q -t set,get,mset -P 2
SET: 195.46 requests per second
GET: 196.31 requests per second
MSET (10 keys): 196.29 requests per second

Strict версия.

> redis-benchmark -p 8090 -n 10000 -c 10 -q -t set,get,mset -P 1
SET: 16103.06 requests per second
GET: 15898.25 requests per second
MSET (10 keys): 9337.07 requests per second

> redis-benchmark -p 8090 -n 10000 -c 10 -q -t set,get,mset -P 2
SET: 25906.74 requests per second
GET: 25839.79 requests per second
MSET (10 keys): 12285.01 requests per second


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

Lasy версия
COST CENTRE                           MODULE                               %time %alloc
throwSocketErrorIfMinus1RetryMayBlock Network.Socket.Internal               29.8    0.7
MAIN                                  MAIN                                  11.9    0.8
server_responses                      RedisSharding                         11.2    0.9
client_reader                         RedisSharding                         10.1    5.6
send                                  Network.Socket.ByteString.Lazy.Posix   9.5    8.1
...
key2server                            RedisSharding                          2.3    0.4

Strict версия
COST CENTRE                           MODULE                              %time %alloc
endOfLine                             Data.Attoparsec.ByteString.Internal  13.0    7.5
decimal                               Data.Attoparsec.ByteString.Char8     11.0    8.2
servers_sender                        RedisSharding                        10.6   13.1
throwSocketErrorIfMinus1RetryMayBlock Network.Socket.Internal              10.4    0.5
client_reader                         RedisSharding                         9.8    5.5
...
key2server                            RedisSharding                         1.7    1.2

Но где тут 20 кратное замедление? Возьмем для ориентира чистую функцию key2server, которотая под ключу определяет на какою ноду отправлять данные. В обоих версиях время выполнения ее в процентной отношении соизмеримо. Значит профайлер не показывает обнаруженное 20 кратное замедление. О чем это может говорить? Неужели, причина кроется где то глубоко в Haskell RTS? Что, выходит, Харпер прав?

P.S. Для не threaded режима работы RTS Haskell, цифры аналогичны.

P.S.S. Нужно для объективности еще провести исследования.

Комментариев нет:

Отправить комментарий