我真的很惊讶于F#的printf速度有多慢。我有许多处理大型数据文件和写出大量CSV文件的C#程序。我最初是从使用fprintf writer "%s,%d,%f,%f,%f,%s"开始的,我认为这将是简单和相当有效的。
然而,过了一段时间后,我有点厌倦了等待文件处理。(我有4 4gb的XML文件需要浏览并写出其中的条目。)
当我通过分析器运行我的应用程序时,我惊讶地发现printf是非常慢的方法之一。
我更改了代码,不使用printf,现在性能好多了。Printf性能正在扼杀我的整体应用程序性能。
举个例子,我的原始代码是:
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)我已经将它更改为以下内容
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行的文件。没有什么特别事情。
发布于 2011-06-07 06:36:03
我不确定这有多重要,但是...
检查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. 我认为“反思”这个词或许能回答这个问题。
printf非常适合于编写简单的类型安全输出,但是如果您想在内部循环中获得良好的性能,则可能需要使用较低级的.NET API来编写输出。我还没有做过自己的基准测试。
发布于 2011-06-07 11:36:49
TextWriter已经缓冲了它的输出。我建议使用Write一次输出一个值,而不是格式化整行并将其传递给WriteLine。在我的笔记本电脑上,使用您的函数编写100,000行代码几乎需要一分钟,而使用以下函数,它只需半秒。
let writeRow (writer:TextWriter) siteName (sector:Sector) =
let inline write (value:'a) (delim:char) =
writer.Write(value)
writer.Write(delim)
let inline quote s = "\"" + s + "\""
write (quote sector.Label) ','
write sector.Longitude ','
write sector.Latitude ','
write sector.RNCId ','
write sector.CellId ','
write (quote siteName) ','
write (quote sector.Switch) ','
write (quote sector.Technology) ','
write (int sector.Azimuth) ','
write sector.PrimaryScramblingCode ','
write (int sector.FrequencyBand) ','
write (int sector.Height) ','
write (quote sector.PatternName) ','
write (int sector.Beamwidth) ','
write (int sector.ElectricalTilt) ','
write (int sector.MechanicalTilt) ','
write (int (sector.ElectricalTilt + sector.MechanicalTilt)) ','
write sector.SectorType ','
write (int sector.Radius) '\n'发布于 2013-06-28 19:28:08
现在已经发布了F# 3.1预览版,据称printf的性能提高了40倍。你可能想看看这个:
F# 3.1编译器/库添加
Printf性能
在printf3.1核心库中,F#系列函数用于类型安全格式化的性能得到了改进。例如,使用以下格式字符串的打印速度现在提高到40倍(尽管您的确切里程可能有所不同):
sprintf "%d: %d, %x %X %d %d %s"虽然您确实需要使用F# 3.1 FSharp.Core.dll运行时组件,但不需要对代码进行任何更改即可利用这种改进的性能。
https://stackoverflow.com/questions/6248787
复制相似问题