1

我写了以下函数

let getTriangles maxPerimeter =
    let mutable count = 0
    for c in 1..maxPerimeter do
        let cc = (int64 (c*c))
        for b in 1..Math.Min(c-1, maxPerimeter-c-1) do
            let bb = (int64 (b*b))
            for a in 1..Math.Min(maxPerimeter-c-b, (int (Math.Ceiling(Math.Sqrt(float (cc+1L-bb)))))) do
                let aa = (int64 (a*a))
                if cc + 1L = aa + bb then
                    count <- count + 1
    count

现在是时候调整它了。

为此,我已经dot Trace Performance在我的应用程序上安装并运行了一个非常大的maxPerimeter,以确保程序需要一段时间才能运行。

这就是我得到的:

在此处输入图像描述

正如您可能想象的那样,我真正想知道的是使用时间 getTriangles'函数体内是如何分布的,所以这似乎没有特别的帮助。我尝试在Build窗格中关闭代码优化,但它似乎对我没有一点帮助。

  1. 难道我做错了什么?
  2. 我应该如何分析这个功能?
  3. 这是 F# 或 CLR 特定的行为吗?

我所拥有的所有性能分析经验都与 Java 相关,所以我可能对 CLR 世界有点偏离。我也涉足过 ANTS Performance,但结果是一样的。

4

1 回答 1

4

我不了解 dotTrace,我使用 ANTS Performance Profiler,因为我发现它与 F# 配合得很好;我最近一直在使用新版本 (v8) 来分析我的fsharp-tools项目。

在 ANTS Performance Profiler 中完成分析运行并显示结果后,默认视图仅显示您拥有源的方法(即,您正在分析的 .exe/.dll 旁边有一个 .pdb 指向您机器上的一些有效源位置)。您可以使用下拉菜单(参见屏幕截图)显示所有方法,这对于 F# 代码非常有用;因为您正在传递函数,执行堆栈往往会进出您可能正在使用的库,因此查看“所有方法”可以更好地了解您的代码实际在做什么,以及来自外部库的代码如何可能会影响代码的性能。

ANTS Performance Profiler v8 截图,分析 F# 代码(fsharp-tools)

也就是说——F# 有两种不同的for循环;它们看起来很相似,但实际上在引擎盖下却大不相同。您使用的 ( for x in y do) 大致相当于foreachC# 中的循环——也就是说,循环编译为一个迭代器,该迭代器从某个值序列中提取每个值。第二种更快的循环(for i = x to y dofor i = x downto y do)编译为非常简单的 IL,就像您for在 C#、Java、C 等中使用循环一样。

这是使用第二种for循环的函数的修改版本。在这种情况下,它只是稍微快一点(13.749svs. 13.520sN = 5000在我的笔记本电脑上),但毫无疑问,如果您在数值范围内进行任何紧密循环,您想要编写代码的方式。

let getTriangles' maxPerimeter =
    let mutable count = 0
    for c = 1 to maxPerimeter do
        let cc = int64 (c * c)
        for b = 1 to min (c-1) (maxPerimeter-c-1) do
            let bb = int64 (b * b)
            for a = 1 to min (maxPerimeter-c-b) (int <| ceil (sqrt <| float (cc+1L-bb))) do
                let aa = int64 (a * a)
                if cc + 1L = aa + bb then
                    count <- count + 1
    count

至于函数内的行为,ANTS Performance Profiler 还可以为您提供行级计时(但仅适用于您拥有源代码的方法)。我编译并分析了您的函数和我的修改版本(带有maxPerimeter = 2000):

ANTS Performance Profiler v8,F# 项目的行级时序

于 2013-06-16T20:56:04.810 回答