Time F中代码段的可靠计时#

Time F中代码段的可靠计时#,time,f#,performance-testing,Time,F#,Performance Testing,我想知道你是否对如何在F#中精确计时函数有什么建议。我在某处找到了这个函数: let time f = let sw = System.Diagnostics.Stopwatch() sw.Start() let res = f() sw.Stop() (res, sw.Elapsed.TotalMilliseconds) 它只运行给定函数一次,并返回结果和经过的时间。然而,当我使用运行它时,它似乎变化很大,这是我目前测试F#代码的地方 为了进行测试,我为ProjectEu

我想知道你是否对如何在F#中精确计时函数有什么建议。我在某处找到了这个函数:

let time f =
  let sw = System.Diagnostics.Stopwatch()
  sw.Start()
  let res = f()
  sw.Stop()
  (res, sw.Elapsed.TotalMilliseconds)
它只运行给定函数一次,并返回结果和经过的时间。然而,当我使用运行它时,它似乎变化很大,这是我目前测试F#代码的地方

为了进行测试,我为ProjectEuler6()编译了一些不同的替代解决方案:

当我按原样运行它时,我得到(仅列出计时输出):

项目Euler 6的解决方案: 组织:25164150英寸0.037000毫秒 v2:25164150英寸0.092800毫秒 v3:25164150英寸0.049400毫秒 v4:25164150英寸0.018700毫秒 第二次运行给出:

项目Euler 6的解决方案: 组织:25164150英寸0.034400毫秒 v2:25164150英寸0.102300毫秒 v3:25164150英寸0.056700毫秒 v4:25164150英寸0.016200毫秒 刚才这些似乎有点一致,但如果我改变我首先运行和最后运行的测试的顺序,它可以改变数量级的时间。因此,请帮助我找到一种更好或更准确的方法来计时F#中较小代码段的执行(希望是在)


对函数进行计时最重要的方面是尽可能获得不同函数的运行时间之间的相对时间。我知道并接受在不同平台上运行任何给定功能的确切时间会有所不同

基准测试不是一项简单的任务。Visual Studio确实有性能分析器,它随Visual Studio 2015社区免费提供。我觉得它很有用。另一件好事是,您可以运行程序并与之交互,查看各种代码被调用的频率、调用的其他内容以及执行时的平均时间

以下是如何开始使用它的链接:

下面是我对示例F#console应用程序运行后的一个图像:

您需要注意的是cpu完成的分支优化,以及您在测试中遇到的任何重复计算,而不是正常代码执行流的一部分

以下是示例应用程序的代码:

// define the square function
let square x = x * x

// define the sumOfSquares function
let sumOfSquares n = 
   [1..n] |> List.map square |> List.sum

[<EntryPoint>]
let main argv = 
    for i in 1..100 do
        let s = sumOfSquares i
        printfn "%d" s
    0 // return an integer exit code
//定义平方函数
设平方x=x*x
//定义sumOfSquares函数
设sumOfSquares n=
[1..n]|>List.map square |>List.sum
[]
让主argv=
因为我在1..100做
设s=sumofsquaresi
printfn“%d”s
0//返回整数退出代码

在.Net中,时间小于1毫秒的任何内容都将非常可疑。至少试着跑10公里times@JohnPalmer,我试过多次运行它,但后来出现了一些问题,因此,如果您有一些好的替代方法来解决这个问题而不产生副作用,请发布一个答案
[0..10000]|>Seq.iter(fun ->f())
将是一种方法。您还希望调用
f
几次而不进行度量,以避免JIT开销。关于如何在C语言中实现这一点,有很多好东西,我只想把它们翻译成F语言。@JohnPalmer,你提到了JIT开销,我理解这可能会影响一些东西。你知道是否有一些记忆或其他影响时间的效果?建立列表、序列或类似内容?这一切都取决于您需要的准确性。要想做到完美,需要一页页的答案,在C#中有很多很好的方法。
// define the square function
let square x = x * x

// define the sumOfSquares function
let sumOfSquares n = 
   [1..n] |> List.map square |> List.sum

[<EntryPoint>]
let main argv = 
    for i in 1..100 do
        let s = sumOfSquares i
        printfn "%d" s
    0 // return an integer exit code