我正在玩Haskell中实现Redis客户端库,我的目标是尽可能地编码Haskell类型系统中Redis命令的语义.对于那些不知道的人来说,Redis是一个通过网络访问的数据存储区.我会用它来举例说明我的问题,但Redis并不是这个问题的焦点.
考虑这个功能
get :: (RedisValue a) => Key -> Redis a
get k = decodeValue <$> sendCommand ["GET", key]
Run Code Online (Sandbox Code Playgroud)
它向数据存储区发送命令并返回存储在给定下的值Key(对于此示例,您可以考虑type Key = String).至于返回类型:
Redis是的实例Monad和MonadIO.它封装了有关网络连接的信息.sendCommand发送请求并返回数据存储区的回复.
a是多态的,例如可以返回Strings或ByteStrings,具体取决于上下文.
以下代码应阐明上述内容.
data Redis a = ...
instance MonadIO Redis where ...
instance Monad Redis where ...
sendCommand :: [String] -> Redis String
class RedisValue a where
decodeValue :: String -> a
-- example instances
instance RedisValue String where …Run Code Online (Sandbox Code Playgroud) 我对我的库进行了更改,现在速度要慢得多,但我无法弄清楚它花费了多少时间.分析报告没有帮助.请帮我弄清楚原因是什么.
我创建了一个名为Hedis的Redis客户端库,并为它准备了一个基准程序.现在,我对库进行了一些内部更改,以清理架构.这导致性能(按所述基准测量的每秒Redis请求数)下降约2.5倍.
基准测试打开与localhost上的Redis服务器的50个网络连接.两个版本之间的连接处理方式不同:
unsafeInterleaveIO(我在博客文章中广泛描述我的方法)从套接字句柄读取.我对建筑有点不满意,因此我改变了方向Chans进行通信(150个线程在基准测试中运行).可能相关的更多信息:
-threaded).forkIO.不是更贵
forkOS.分析并没有给我一个明显的理由,表明性能下降.根据该分析报告,这两个版本花费的时间超过99%System.IO.hFlush和Data.ByteString.hGetSome.的次数hFlush和hGetSome被称为是在两个版本相同.由于网络流量在两种情况下也相同,因此这些功能不能成为减速的原因.
我可以在两个版本之间测量的唯一显着差异是time(Unix实用程序)告诉我的:慢速版本(线程数量是其三倍)在"sys"而不是"user"中花费的时间明显多于快速版本版.GHC +RTS -s标志将此报告为降低了生产率.
以下是带有+RTS -s标志的两个版本的程序输出:
$ time ./dist/build/hedis-benchmark/hedis-benchmark +RTS -s -p
ping 33305.29 Req/s
get 25802.92 Req/s
mget 18215.94 Req/s
ping (pipelined) 268994.36 Req/s
5,118,163,904 bytes allocated in the heap …Run Code Online (Sandbox Code Playgroud)