我想在Haskell中编写一些基本的基准测试代码,即设计一个函数:
benchmark :: M a -> String -> Int -> M ()
给出action
(相对于我自己的monad M
的monadic值),用于消息传递目的的函数name
和一些iterations
,执行该操作与iterations
一样多次,并在stdout
上显示有关执行代码所花费时间的消息。出于这个问题的目的,我假设monad M
是类MonadIO
的一个实例。特别是我有一些功能:
liftIO :: IO a -> M a
花了很多时间在'真实世界Haskell'上,我被警告说“非严格的评估可以将性能测量和分析变成某个雷区”。但是,我并不是在寻找一个明确的答案,而是寻求关于如何最好地解决这个问题的建议和指导。
我天真的方法是分开时间测量代码:
benchmark action name iterations = do
start <- liftIO getPOSIXTime
runAction action iterations
end <- liftIO getPOSIXTime
let time = realToFrac $ (end - start) :: Double
liftIO $ printf "Benchmark: %s, %d iterations ran in %.3f seconds\n"
name iterations time
来自问题的真正危机,即将action
作为循环运行:
runAction :: Monad m => m a -> Int -> m ()
runAction action iterations
| iterations <= 0 = return ()
| otherwise = do
action
runAction action (iterations -1)
我对我的解决方案的问题是,似乎代码花费更多时间在'样板'而不是运行action
:如果我尝试对最简单的可能操作return ()
进行基准测试,我对于100万次迭代,可能会得到1000毫秒的时间。我可以看到monad M
的细节发挥了重要作用(将M
替换为IO
会将时间缩短到250毫秒而不是1000毫秒)。一百万个循环无效也可能在解释的python
或scheme
中大约需要250毫秒(因此IO
monad并不是那么糟糕),但它的速度要快得多C
。通常Haskell速度非常快(距离C
不远)。我尝试了一个涉及forM
和[1..1000000]
但没有改进的解决方案。
有没有办法解决这个问题,因此'样板'代码不会压倒被测试的代码?
编辑:当使用@luqui建议的-O2
编译器优化选项时,这个问题似乎消失了(即一百万个monadic循环无效,相对于其他语言而言,性能非常好,至少在我的情况下)。因此,就我所见,这个问题已经结束。
答案 0 :(得分:2)
您可以尝试这种方式:
import React, { Component } from 'react';
import { getData } from './Utils';
class BoardContainer extends React.Component {
constructor(props){
super(props);
this.state = { positions: [] };
}
componentWillMount(){
var x = getData('positions'); //simplified code for debugging and example
console.log(x); //ISSUE: x is undefined
}
render() {
return(
<div>Testing Rendering Board Container
//rendering code would be here (child component call)
</div>
)
}
}
或者,您可以重写runAction :: MonadIO m => m a -> Int -> m NominalDiffTime
runAction action = fmap sum . flip replicateM action'
where
action' = do
start <- liftIO getPOSIXTime
action
end <- liftIO getPOSIXTime
let !delta = end - start
return delta
benchmark action name iterations = do
time <- realToFrac <$> runAction action iterations
liftIO $ printf "Benchmark: %s, %d iterations ran in %.3f seconds\n"
name iterations (time :: Double)
:
runAction
或者,只需修复开销:
runAction = flip replicateM_