- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个包含 6 列和 678,552 行的 csv 文件。不幸的是,我无法分享任何数据样本,但类型很简单:int64
, int64
, date
, date
, string
, string
并且没有缺失值。
是时候使用 read.table
将这些数据加载到 R 中的数据帧中了: ~ 3 秒。
在 F# 中使用 CsvFile.Load 加载此数据的时间:~ 3 秒。
在 F# 中的 Deedle 数据帧中加载此数据的时间:~ 7 秒。
添加 inferTypes=false
并向 Deedle 的 Frame.ReadCsv
提供模式将时间缩短至约 3 秒
在 F# 中使用 CsvProvider 加载此数据的时间: ~ 5 分钟 .
这 5 分钟甚至是在我定义了 Schema
中的类型之后。参数,大概消除了 F# 用来推断它们的时间。
我知道类型提供程序需要比 R 或 CsvFile.Load 做更多的事情才能将数据解析为正确的数据类型,但我对 x100 的速度损失感到惊讶。更令人困惑的是 Deedle 加载数据所需的时间,因为它还需要推断类型并适本地进行转换、按系列组织等。我实际上预计 Deedle 需要比 CsvProvider 更长的时间。
在 this issue CsvProvider 的糟糕性能是由大量列引起的,这不是我的情况。
我想知道我是否做错了什么,或者是否有任何方法可以加快速度。
澄清一下:创建提供者几乎是即时的。当我强制生成的序列由 Seq.length df.Rows
实现时fsharpi 提示返回大约需要 5 分钟。
我在 linux 系统上,F# v4.1 在单声道 v4.6.1 上。
这是 CsvProvider 的代码
let [<Literal>] SEP = "|"
let [<Literal>] CULTURE = "sv-SE"
let [<Literal>] DATAFILE = dataroot + "all_diagnoses.csv"
type DiagnosesProvider = CsvProvider<DATAFILE, Separators=SEP, Culture=CULTURE>
let diagnoses = DiagnosesProvider()
inferTypes=false
添加了 Deedle 所需的时间并提供了一个模式。
CacheRows=false
正如评论中所建议的那样,在 CsvProvider 中对加载时间没有明显影响。
Culture
是罪魁祸首。如果我省略这个参数,CsvProvider 会在 7 秒内加载数据。我不确定是什么原因造成的。我系统的语言环境是 en_US。然而,数据来自瑞典语言环境中的 SQL Server,其中十进制数字由“,”而不是“。”分隔。这个特定的数据集没有任何小数,所以我可以完全省略 Culture。然而,另一组有 2 个十进制列和超过 1,000,000 行。我的下一个任务是在我目前没有的 Windows 系统上进行测试。
System.Globalization.CultureInfo.DefaultThreadCurrentCulture = CultureInfo("sv-SE")
System.Threading.Thread.CurrentThread.CurrentCulture = CultureInfo("sv-SE")
Culture="sv-SE"
来自 CsvProvider 的参数加载时间减少到 ~ 6 秒,并且小数被正确解析。如果有人可以对此行为做出解释,我将保持开放状态。
最佳答案
我正在尝试重现您看到的问题,因为您无法共享我尝试生成一些测试数据的数据。但是,在我的机器上(.NET 4.6.2 F#4.1)我看不到它需要几分钟,它需要几秒钟。
也许您可以尝试查看我的示例应用程序在您的设置中的执行情况,我们可以从中工作吗?
open System
open System.Diagnostics
open System.IO
let clock =
let sw = Stopwatch ()
sw.Start ()
fun () ->
sw.ElapsedMilliseconds
let time a =
let before = clock ()
let v = a ()
let after = clock ()
after - before, v
let generateDataSet () =
let random = Random 19740531
let firstDate = DateTime(1970, 1, 1)
let randomInt () = random.Next () |> int64 |> (+) 10000000000L |> string
let randomDate () = (firstDate + (random.Next () |> float |> TimeSpan.FromSeconds)).ToString("s")
let randomString () =
let inline valid ch =
match ch with
| '"'
| '\\' -> ' '
| _ -> ch
let c = random.Next () % 16
let g i =
if i = 0 || i = c + 1 then '"'
else 32 + random.Next() % (127 - 32) |> char |> valid
Array.init (c + 2) g |> String
let columns =
[|
"Id" , randomInt
"ForeignId" , randomInt
"BirthDate" , randomDate
"OtherDate" , randomDate
"FirstName" , randomString
"LastName" , randomString
|]
use sw = new StreamWriter ("perf.csv")
let headers = columns |> Array.map fst |> String.concat ";"
sw.WriteLine headers
for i = 0 to 700000 do
let values = columns |> Array.map (fun (_, f) -> f ()) |> String.concat ";"
sw.WriteLine values
open FSharp.Data
[<Literal>]
let sample = """Id;ForeignId;BirthDate;OtherDate;FirstName;LastName
11795679844;10287417237;2028-09-14T20:33:17;1993-07-21T17:03:25;",xS@ %aY)N*})Z";"ZP~;"
11127366946;11466785219;2028-02-22T08:39:57;2026-01-24T05:07:53;"H-/QA(";"g8}J?k~"
"""
type PerfFile = CsvProvider<sample, ";">
let readDataWithTp () =
use streamReader = new StreamReader ("perf.csv")
let csvFile = PerfFile.Load streamReader
let length = csvFile.Rows |> Seq.length
printfn "%A" length
[<EntryPoint>]
let main argv =
Environment.CurrentDirectory <- AppDomain.CurrentDomain.BaseDirectory
printfn "Generating dataset..."
let ms, _ = time generateDataSet
printfn " took %d ms" ms
printfn "Reading dataset..."
let ms, _ = time readDataWithTp
printfn " took %d ms" ms
0
Generating dataset...
took 2162 ms
Reading dataset...
took 6156 ms
Generating dataset...
took 4432 ms
Reading dataset...
took 8304 ms
Culture
到 CsvProvider 明确似乎会降低性能很多。它可以是任何文化,而不仅仅是
sv-SE
但为什么?
internal sealed class csvFile@78
{
internal System.Tuple<long, long, System.DateTime, System.DateTime, string, string> Invoke(object arg1, string[] arg2)
{
Microsoft.FSharp.Core.FSharpOption<string> fSharpOption = TextConversions.AsString(arg2[0]);
long arg_C9_0 = TextRuntime.GetNonOptionalValue<long>("Id", TextRuntime.ConvertInteger64("", fSharpOption), fSharpOption);
fSharpOption = TextConversions.AsString(arg2[1]);
long arg_C9_1 = TextRuntime.GetNonOptionalValue<long>("ForeignId", TextRuntime.ConvertInteger64("", fSharpOption), fSharpOption);
fSharpOption = TextConversions.AsString(arg2[2]);
System.DateTime arg_C9_2 = TextRuntime.GetNonOptionalValue<System.DateTime>("BirthDate", TextRuntime.ConvertDateTime("", fSharpOption), fSharpOption);
fSharpOption = TextConversions.AsString(arg2[3]);
System.DateTime arg_C9_3 = TextRuntime.GetNonOptionalValue<System.DateTime>("OtherDate", TextRuntime.ConvertDateTime("", fSharpOption), fSharpOption);
fSharpOption = TextConversions.AsString(arg2[4]);
string arg_C9_4 = TextRuntime.GetNonOptionalValue<string>("FirstName", TextRuntime.ConvertString(fSharpOption), fSharpOption);
fSharpOption = TextConversions.AsString(arg2[5]);
return new System.Tuple<long, long, System.DateTime, System.DateTime, string, string>(arg_C9_0, arg_C9_1, arg_C9_2, arg_C9_3, arg_C9_4, TextRuntime.GetNonOptionalValue<string>("LastName", TextRuntime.ConvertString(fSharpOption), fSharpOption));
}
}
internal sealed class csvFile@78
{
internal System.Tuple<long, long, System.DateTime, System.DateTime, string, string> Invoke(object arg1, string[] arg2)
{
Microsoft.FSharp.Core.FSharpOption<string> fSharpOption = TextConversions.AsString(arg2[0]);
long arg_C9_0 = TextRuntime.GetNonOptionalValue<long>("Id", TextRuntime.ConvertInteger64("sv-SE", fSharpOption), fSharpOption);
fSharpOption = TextConversions.AsString(arg2[1]);
long arg_C9_1 = TextRuntime.GetNonOptionalValue<long>("ForeignId", TextRuntime.ConvertInteger64("sv-SE", fSharpOption), fSharpOption);
fSharpOption = TextConversions.AsString(arg2[2]);
System.DateTime arg_C9_2 = TextRuntime.GetNonOptionalValue<System.DateTime>("BirthDate", TextRuntime.ConvertDateTime("sv-SE", fSharpOption), fSharpOption);
fSharpOption = TextConversions.AsString(arg2[3]);
System.DateTime arg_C9_3 = TextRuntime.GetNonOptionalValue<System.DateTime>("OtherDate", TextRuntime.ConvertDateTime("sv-SE", fSharpOption), fSharpOption);
fSharpOption = TextConversions.AsString(arg2[4]);
string arg_C9_4 = TextRuntime.GetNonOptionalValue<string>("FirstName", TextRuntime.ConvertString(fSharpOption), fSharpOption);
fSharpOption = TextConversions.AsString(arg2[5]);
return new System.Tuple<long, long, System.DateTime, System.DateTime, string, string>(arg_C9_0, arg_C9_1, arg_C9_2, arg_C9_3, arg_C9_4, TextRuntime.GetNonOptionalValue<string>("LastName", TextRuntime.ConvertString(fSharpOption), fSharpOption));
}
}
// Fast
TextRuntime.ConvertDateTime("", fSharpOption), fSharpOption)
// Slow
TextRuntime.ConvertDateTime("sv-SE", fSharpOption), fSharpOption)
ConvertDateTime
转发给
GetCulture
static member GetCulture(cultureStr) =
if String.IsNullOrWhiteSpace cultureStr
then CultureInfo.InvariantCulture
else CultureInfo cultureStr
CultureInfo.InvariantCulture
但是对于每个字段和行的任何其他情况,我们正在创建
CultureInfo
目的。可以进行缓存,但事实并非如此。创建过程本身似乎不会花费太多时间,但是当我们使用新的
CultureInfo
解析时会发生一些事情。每次都反对。
DateTime
在
FSharp.Data
本质上是这个
let dateTimeStyles = DateTimeStyles.AllowWhiteSpaces ||| DateTimeStyles.RoundtripKind
match DateTime.TryParse(text, cultureInfo, dateTimeStyles) with
CultureInfo
对象和另一个我们每次创建的对象。
open System
open System.Diagnostics
open System.Globalization
let clock =
let sw = Stopwatch ()
sw.Start ()
fun () ->
sw.ElapsedMilliseconds
let time a =
let before = clock ()
let v = a ()
let after = clock ()
after - before, v
let perfTest c cf () =
let dateTimeStyles = DateTimeStyles.AllowWhiteSpaces ||| DateTimeStyles.RoundtripKind
let text = DateTime.Now.ToString ("", cf ())
for i = 1 to c do
let culture = cf ()
DateTime.TryParse(text, culture, dateTimeStyles) |> ignore
[<EntryPoint>]
let main argv =
Environment.CurrentDirectory <- AppDomain.CurrentDomain.BaseDirectory
let ct = "sv-SE"
let cct = CultureInfo ct
let count = 10000
printfn "Using cached CultureInfo object..."
let ms, _ = time (perfTest count (fun () -> cct))
printfn " took %d ms" ms
printfn "Using fresh CultureInfo object..."
let ms, _ = time (perfTest count (fun () -> CultureInfo ct))
printfn " took %d ms" ms
0
Using cached CultureInfo object...
took 16 ms
Using fresh CultureInfo object...
took 5328 ms
CultureInfo
FSharp.Data
中的对象应该改进
CsvProvider
当指定文化时,性能显着。
关于f# - FSharp.Data CsvProvider 性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42469637/
我想使用 FSharp.Data.CsvProvider (v1.1.10) 创建一个类型来处理带有“;”的 CSV 文件分隔符和预定义架构。 下面一行报错: type CsvType1 = CsvP
FAOCropsLivestock.csv 包含超过 1400 万行。在我的 .fs 文件中,我声明了 type FAO = CsvProvider 并尝试使用以下代码 FAO.GetSample()
我是 F# 的初学者,我正在尝试使用 CsvProvider 并重现此处给出的示例 http://fsharp.github.io/FSharp.Data/library/CsvProvider.ht
我有一个包含 6 列和 678,552 行的 csv 文件。不幸的是,我无法分享任何数据样本,但类型很简单:int64 , int64 , date , date , string , string并
为什么我用 CsvProvider<> 创建一个新的 CSV 类型在 F# 中是这样的: type ThisCsv = CsvProvider 然后创建/填充/保存 .csv,生成的文件不包含我指定的
我正在使用 FSharp.Data 中的 CsvProvider 在 F# 中读取 CSV 文件。有没有办法添加新的(计算的)列而不将其转换为全新的类型? open FSharp.Data type
我正在尝试将数据从 FSharp.Data.CsvProvider 传递到 Deedle.Frame。 我几乎是 F# 新手,我需要将一些 CSV 文件从文化“it-IT”转换为“en-US”,以便我
我无法使用 fslab 提供的 FSharp.Data csv 提供程序加载 csv 文件,包括示例 adwords.csv 文件。 下面这个错误是什么意思?此外,当我将鼠标悬停在 Visual St
前面的极端菜鸟学习问题:我有一个模块,我想在我的 C#(通用)应用程序中使用。 C# 应用程序将下载并解压缩一个包含 12 个始终遵循相同格式的 CSV 的文件。所以我所做的是提前下载 CSV,并将它
是否可以在 F# 中使用 CSVProvider 读取使用 gzip (tvs.gz) 压缩的 URL?我正在尝试使用此代码: type name = CsvProvider 但是,我收到了这个错误:
我是一名优秀的程序员,十分优秀!