为什么 F# 中的 printf 这么慢? [英] Why is printf in F# so slow?

查看:42
本文介绍了为什么 F# 中的 printf 这么慢?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对 F# 中的 printf 速度如此之慢感到非常惊讶.我有许多 C# 程序可以处理大型数据文件并写出许多 CSV 文件.我最初是使用 fprintf writer "%s,%d,%f,%f,%f,%s" 开始的,我认为这很简单且相当有效.

I've just been really surprised by how slow printf from F# is. I have a number of C# programs that process large data files and write out a number of CSV files. I originally started by using fprintf writer "%s,%d,%f,%f,%f,%s" thinking that that would be simple and reasonably efficient.

但是过了一会儿,我对等待文件处理感到有点厌烦了.(我有 4GB 的 XML 文件要检查并从中写出条目.).

However after a while I was getting a bit fed up with waiting for the files to process. (I've got 4gb XML files to go through and write out entries from them.).

当我通过分析器运行我的应用程序时,我惊讶地发现 printf 是一种非常慢的方法.

When I ran my applications through a profiler, I was amazed to see printf as being one of the really slow methods.

我将代码更改为不使用 printf,现在性能要好得多.Printf 性能正在扼杀我的整体应用程序性能.

I changed the code to not use printf and now performance is so much better. Printf performance was killing my overall application performance.

举个例子,我原来的代码是:

To give an example, my original code is:

fprintf sectorWriter ""%s",%f,%f,%d,%d,"%s","%s","%s",%d,%d,%d,%d,"%s",%d,%d,%d,%d,%s,%d"
    sector.Label sector.Longitude sector.Latitude sector.RNCId sector.CellId
    siteName sector.Switch sector.Technology (int sector.Azimuth) sector.PrimaryScramblingCode
    (int sector.FrequencyBand) (int sector.Height) sector.PatternName (int sector.Beamwidth) 
    (int sector.ElectricalTilt) (int sector.MechanicalTilt) (int (sector.ElectricalTilt + sector.MechanicalTilt))
    sector.SectorType (int sector.Radius)

我已经将其更改为以下内容

And I've changed it to be the following

seq {
    yield sector.Label; yield string sector.Longitude; yield string sector.Latitude; yield string sector.RNCId; yield string sector.CellId; 
    yield siteName; yield sector.Switch; yield sector.Technology; yield string (int sector.Azimuth); yield string sector.PrimaryScramblingCode;
    yield string (int sector.FrequencyBand); yield string (int sector.Height); yield sector.PatternName; yield string (int sector.Beamwidth); 
    yield string (int sector.ElectricalTilt); yield string (int sector.MechanicalTilt); 
    yield string (int (sector.ElectricalTilt + sector.MechanicalTilt));
    yield sector.SectorType; yield string (int sector.Radius)
}
|> writeCSV sectorWriter

辅助函数

let writeDelimited delimiter (writer:TextWriter) (values:seq<string>) =
    values
    |> Seq.fold (fun (s:string) v -> if s.Length = 0 then v else s + delimiter + v) ""
    |> writer.WriteLine

let writeCSV (writer:TextWriter) (values:seq<string>) = writeDelimited "," writer values

我正在写出大约 30,000 行的文件.没什么特别的.

I'm writing out files with about 30,000 rows. Nothing special.

推荐答案

我不确定这有多重要,但是...

I am not sure how much it matters, but...

检查 printf 的代码:

Inspecting the code for printf:

https://github.com/fsharp/fsharp/blob/master/src/fsharp/FSharp.Core/printf.fs

我明白了

// The general technique used this file is to interpret
// a format string and use reflection to construct a function value that matches
// the specification of the format string.  

我认为反射"这个词可能回答了这个问题.

and I think the word 'reflection' probably answers the question.

printf 非常适合编写简单的类型安全输出,但如果您想在内循环中获得良好的性能,则可能需要使用较低级别的 .NET API 来编写输出.我还没有做过自己的基准测试.

printf is great for writing simple type-safe output, but if you want good perf in an inner loop, you might want to use a lower-level .NET API to write output. I haven't done my own benchmarking to see.

这篇关于为什么 F# 中的 printf 这么慢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆