如何分析 F# 脚本
How do I profile F# script
我正在通过使用 F# 脚本自动完成一些任务来学习 F#。我从命令行 运行 使用 "fsi/fsarpi --exec" 这个脚本。我在工作中使用 .Net 核心。我一直在寻找的一件事是如何分析我的 F# 脚本。我主要是在寻找
- 查看我的整个脚本消耗的总时间,我尝试使用秒表类功能,效果很好。有什么可以显示我的各种顶级函数调用的时间吗?或者 timings/counts 用于函数调用。
- 查看我的脚本的整体内存消耗。
- 我的脚本中的热点。
总的来说,我正在尝试了解我的脚本的性能瓶颈。
附带说明一下,有没有办法将 F# 脚本编译为 exe?
我建议对任何基准测试任务使用 BenchmarkDotNet(好吧,micro-benchmarks)。由于它是一种统计工具,因此它可以解决许多 hand-rolled 基准测试无法解决的问题。只需应用一些属性,您就可以获得漂亮的报告。
创建一个 .NET Core 控制台应用程序,添加 BenchmarkDotNet 包,创建一个基准,然后 运行 它以查看结果。这是一个测试两个简单解析函数的示例,其中一个作为比较基准,并通知 BenchmarkDotNet 在 运行 执行基准测试时捕获内存使用统计信息:
open System
open BenchmarkDotNet.Attributes
open BenchmarkDotNet.Running
module Parsing =
/// "123,456" --> (123, 456)
let getNums (str: string) (delim: char) =
let idx = str.IndexOf(delim)
let first = Int32.Parse(str.Substring(0, idx))
let second = Int32.Parse(str.Substring(idx + 1))
first, second
/// "123,456" --> (123, 456)
let getNumsFaster (str: string) (delim: char) =
let sp = str.AsSpan()
let idx = sp.IndexOf(delim)
let first = Int32.Parse(sp.Slice(0, idx))
let second = Int32.Parse(sp.Slice(idx + 1))
struct(first, second)
[<MemoryDiagnoser>]
type ParsingBench() =
let str = "123,456"
let delim = ','
[<Benchmark(Baseline=true)>]
member __.GetNums() =
Parsing.getNums str delim |> ignore
[<Benchmark>]
member __.GetNumsFaster() =
Parsing.getNumsSpan str delim |> ignore
[<EntryPoint>]
let main _ =
let summary = BenchmarkRunner.Run<ParsingBench>()
printfn "%A" summary
0 // return an integer exit code
在这种情况下,结果将显示 getNumsFaster
函数分配 0 个字节并且 运行 快了大约 33%。
一旦您发现始终表现更好且分配更少的东西,您可以将其转移到脚本或代码将实际执行的其他环境中。
至于热点,您最好的工具实际上是 运行 在像 PerfView 这样的分析器下的脚本,并查看 CPU 脚本在执行时引起的时间和分配。这里没有简单的答案:正确解释分析结果是一项具有挑战性且耗时的工作。
无法将 F# 脚本编译为 .NET Core 的可执行文件。仅在 Windows/.NET Framework 上才有可能,但这是被认为已弃用的旧行为。如果您希望 运行 作为可执行文件,建议您将脚本中的代码转换为应用程序。
我正在通过使用 F# 脚本自动完成一些任务来学习 F#。我从命令行 运行 使用 "fsi/fsarpi --exec" 这个脚本。我在工作中使用 .Net 核心。我一直在寻找的一件事是如何分析我的 F# 脚本。我主要是在寻找
- 查看我的整个脚本消耗的总时间,我尝试使用秒表类功能,效果很好。有什么可以显示我的各种顶级函数调用的时间吗?或者 timings/counts 用于函数调用。
- 查看我的脚本的整体内存消耗。
- 我的脚本中的热点。
总的来说,我正在尝试了解我的脚本的性能瓶颈。
附带说明一下,有没有办法将 F# 脚本编译为 exe?
我建议对任何基准测试任务使用 BenchmarkDotNet(好吧,micro-benchmarks)。由于它是一种统计工具,因此它可以解决许多 hand-rolled 基准测试无法解决的问题。只需应用一些属性,您就可以获得漂亮的报告。
创建一个 .NET Core 控制台应用程序,添加 BenchmarkDotNet 包,创建一个基准,然后 运行 它以查看结果。这是一个测试两个简单解析函数的示例,其中一个作为比较基准,并通知 BenchmarkDotNet 在 运行 执行基准测试时捕获内存使用统计信息:
open System
open BenchmarkDotNet.Attributes
open BenchmarkDotNet.Running
module Parsing =
/// "123,456" --> (123, 456)
let getNums (str: string) (delim: char) =
let idx = str.IndexOf(delim)
let first = Int32.Parse(str.Substring(0, idx))
let second = Int32.Parse(str.Substring(idx + 1))
first, second
/// "123,456" --> (123, 456)
let getNumsFaster (str: string) (delim: char) =
let sp = str.AsSpan()
let idx = sp.IndexOf(delim)
let first = Int32.Parse(sp.Slice(0, idx))
let second = Int32.Parse(sp.Slice(idx + 1))
struct(first, second)
[<MemoryDiagnoser>]
type ParsingBench() =
let str = "123,456"
let delim = ','
[<Benchmark(Baseline=true)>]
member __.GetNums() =
Parsing.getNums str delim |> ignore
[<Benchmark>]
member __.GetNumsFaster() =
Parsing.getNumsSpan str delim |> ignore
[<EntryPoint>]
let main _ =
let summary = BenchmarkRunner.Run<ParsingBench>()
printfn "%A" summary
0 // return an integer exit code
在这种情况下,结果将显示 getNumsFaster
函数分配 0 个字节并且 运行 快了大约 33%。
一旦您发现始终表现更好且分配更少的东西,您可以将其转移到脚本或代码将实际执行的其他环境中。
至于热点,您最好的工具实际上是 运行 在像 PerfView 这样的分析器下的脚本,并查看 CPU 脚本在执行时引起的时间和分配。这里没有简单的答案:正确解释分析结果是一项具有挑战性且耗时的工作。
无法将 F# 脚本编译为 .NET Core 的可执行文件。仅在 Windows/.NET Framework 上才有可能,但这是被认为已弃用的旧行为。如果您希望 运行 作为可执行文件,建议您将脚本中的代码转换为应用程序。