Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance Seq.map比常规for循环快吗?_Performance_F# - Fatal编程技术网

Performance Seq.map比常规for循环快吗?

Performance Seq.map比常规for循环快吗?,performance,f#,Performance,F#,我正在学习F#,关于这门语言,有一件事让我心神不宁,那就是性能。我编写了一个小的基准测试,将惯用的F#与用同一种语言编写的命令式代码进行比较——令我惊讶的是,函数式版本的速度要快得多 基准包括: 使用file.ReadAllLines读取文本文件 颠倒每行中字符的顺序 使用file.writeAllines将结果写回同一文件 代码如下: open System open System.IO open System.Diagnostics let reverseString(str:string

我正在学习F#,关于这门语言,有一件事让我心神不宁,那就是性能。我编写了一个小的基准测试,将惯用的F#与用同一种语言编写的命令式代码进行比较——令我惊讶的是,函数式版本的速度要快得多

基准包括:

  • 使用file.ReadAllLines读取文本文件
  • 颠倒每行中字符的顺序
  • 使用file.writeAllines将结果写回同一文件
  • 代码如下:

    open System
    open System.IO
    open System.Diagnostics
    
    let reverseString(str:string) =
        new string(Array.rev(str.ToCharArray()))
    
    let CSharpStyle() = 
        let lines = File.ReadAllLines("text.txt")
        for i in 0 .. lines.Length - 1 do
            lines.[i] <- reverseString(lines.[i])
    
        File.WriteAllLines("text.txt", lines)
    
    let FSharpStyle() = 
        File.ReadAllLines("text.txt")
        |> Seq.map reverseString
        |> (fun lines -> File.WriteAllLines("text.txt", lines))
    
    let benchmark func message = 
        // initial call for warm-up
        func()
    
        let sw = Stopwatch.StartNew()
        for i in 0 .. 19 do
            func()
    
        printfn message sw.ElapsedMilliseconds
    
    
    [<EntryPoint>]
    let main args = 
        benchmark CSharpStyle "C# time: %d ms"
        benchmark FSharpStyle "F# time: %d ms"
        0
    
    开放系统
    开放系统
    开放系统诊断
    让反向字符串(str:string)=
    新字符串(Array.rev(str.ToCharArray()))
    让CSharpStyle()
    让lines=File.ReadAllLines(“text.txt”)
    因为我在0。。行。长度-1 do
    行。[i]序列图反向限制
    |>(有趣的行->File.writeAllines(“text.txt”,行))
    让基准函数消息=
    //第一次热身
    func()
    设sw=Stopwatch.StartNew()
    因为我在0。。19做
    func()
    打印FN消息sw.ElapsedMilliseconds
    []
    让主参数=
    基准CSharpStyle“C#时间:%d毫秒”
    基准FSharpStyle“飞行时间:%d毫秒”
    0
    

    无论文件大小如何,“F#style”版本的完成时间约为“C#style”版本的75%。我的问题是,为什么会这样?我认为命令式版本没有明显的低效。

    与常规循环相比,Seq.map表单有几个优点。它可以只预计算一次函数引用;它可以避免变量赋值;它可以使用输入序列长度来预先确定结果数组的大小

    Seq.map
    Array.map
    不同。由于序列(
    IEnumerable
    )在被枚举之前不会被计算,因此在F#风格的代码中,只有在
    File.writeAllines
    循环通过
    Seq.map
    生成的序列(而非数组)时,才会真正进行计算

    换句话说,您的C#风格版本正在反转所有字符串并将反转后的字符串存储在数组中,然后在数组中循环以写入文件。F#风格的版本是反转所有字符串,并或多或少地将它们直接写入文件。这意味着C风格的代码在整个文件中循环三次(读取到数组、构建反向数组、写入数组到文件),而F风格的代码只在整个文件中循环两次(读取到数组、写入反向行到文件)


    如果使用
    File.ReadLines
    而不是
    File.ReadAllLines
    Seq.map
    组合使用,您将获得最好的性能-但是您的输出文件必须与输入文件不同,因为您在写入输出的同时仍在读取输入。

    这看起来非常有效,但是我很难理解你的意思。你能详细说明一下每一点吗?谢谢。啊,我现在看到了——C版本调用File.writeAllines(string,string[]),而F版本调用File.writeAllines(string,IEnumerable)。因此,实际上只有2个循环,而不是3个。我没有想到该方法还有其他重载。谢谢你的解释!感谢Dr_Asik准备充分的问题。