File 在OCaml中优化文件写入操作?
基本上,在我的项目中,我尝试将字符串列表写入文件,如下所示:File 在OCaml中优化文件写入操作?,file,optimization,ocaml,ml,File,Optimization,Ocaml,Ml,基本上,在我的项目中,我尝试将字符串列表写入文件,如下所示: val mutable rodata_list : (string*string) list = [] ..... let zip1 ll = List.map (fun (h,e) -> h^e) ll in let oc = open_out_gen [Open_append; Open_creat] 0o666 "final_data.s" in List.iter (fun l -> Printf.fpr
val mutable rodata_list : (string*string) list = []
.....
let zip1 ll =
List.map (fun (h,e) -> h^e) ll in
let oc = open_out_gen [Open_append; Open_creat] 0o666 "final_data.s" in
List.iter (fun l -> Printf.fprintf oc "%s\n" l) (zip1 rodata_list);
ocamlbuild myprogram.p.native
这是我的问题,通常rodata_列表
可以达到800000大小,而我们服务器上的上述代码(64位,32核Intel(R)Xeon(R)CPU E5-2690@2.90GHz
)大约需要3.5秒。。我使用的OCaml
版本是4.01.0
这是不可接受的,尤其是我有4段这样的代码要写入一个文件。完全可以用15秒的时间
我试过这个:
Printf.fprintf oc "%s\n" (String.concat "\n" (zip1 rodata_list));
但是没有明显的改善
所以我想知道,如何优化这部分?我感谢任何解决办法。谢谢大家!
^
在性能关键代码中串联一组字符串,因为这将导致二次复杂性李>
*printf
函数(尽管在OCAML4.02中速度非常快)李>
List.iter (fun (x,y) ->
output_string oc x;
output_string oc y;
output_char oc '\n') rodata_list
此外,任何优化都应该从分析开始,以获得使用分析信息编译所需的分析,例如:
val mutable rodata_list : (string*string) list = []
.....
let zip1 ll =
List.map (fun (h,e) -> h^e) ll in
let oc = open_out_gen [Open_append; Open_creat] 0o666 "final_data.s" in
List.iter (fun l -> Printf.fprintf oc "%s\n" l) (zip1 rodata_list);
ocamlbuild myprogram.p.native
然后,您可以运行程序来收集配置文件,该配置文件可以使用gprof
读取。我猜,您将花费所有的时间不在实际的IO中,甚至连在一起,而是在垃圾收集中,因为您的zip将创建数百万个字符串
它应该有多快
为了证明您实际上试图优化代码中错误的部分,我编写了以下小程序:
let rec init_rev acc = function
| 0 -> acc
| n -> init_rev (("hello", "world") :: acc) (n-1)
let () = List.iter (fun (x,y) ->
print_string x;
print_endline y) (init_rev [] 1000_000)
它创建了一个包含一百万个元素的列表,并将其输出:
$ ocamlbuild main.native
$ time ./main.native > data.txt
real 0m0.998s
user 0m0.211s
sys 0m0.783s
这是macbook笔记本电脑上的。此外,我们大部分时间都在系统中,OCaml中只有200毫秒。而不创建列表的1000_000次迭代的简单循环只需要11毫秒
所以,个人资料
^
在性能关键代码中串联一组字符串,因为这将导致二次复杂性李>
*printf
函数(尽管在OCAML4.02中速度非常快)李>
List.iter (fun (x,y) ->
output_string oc x;
output_string oc y;
output_char oc '\n') rodata_list
此外,任何优化都应该从分析开始,以获得使用分析信息编译所需的分析,例如:
val mutable rodata_list : (string*string) list = []
.....
let zip1 ll =
List.map (fun (h,e) -> h^e) ll in
let oc = open_out_gen [Open_append; Open_creat] 0o666 "final_data.s" in
List.iter (fun l -> Printf.fprintf oc "%s\n" l) (zip1 rodata_list);
ocamlbuild myprogram.p.native
然后,您可以运行程序来收集配置文件,该配置文件可以使用gprof
读取。我猜,您将花费所有的时间不在实际的IO中,甚至连在一起,而是在垃圾收集中,因为您的zip将创建数百万个字符串
它应该有多快
为了证明您实际上试图优化代码中错误的部分,我编写了以下小程序:
let rec init_rev acc = function
| 0 -> acc
| n -> init_rev (("hello", "world") :: acc) (n-1)
let () = List.iter (fun (x,y) ->
print_string x;
print_endline y) (init_rev [] 1000_000)
它创建了一个包含一百万个元素的列表,并将其输出:
$ ocamlbuild main.native
$ time ./main.native > data.txt
real 0m0.998s
user 0m0.211s
sys 0m0.783s
这是macbook笔记本电脑上的。此外,我们大部分时间都在系统中,OCaml中只有200毫秒。而不创建列表的1000_000次迭代的简单循环只需要11毫秒
所以,profile.Hello ivg,我尝试了你的建议,在我的代码中编写三个文件片段的总时间从大约8.5秒减少到了6秒。还有什么我可以做的吗?顺便说一句:如果不是
列表
,那么对于大约100万个元素来说,什么是合适的数据结构呢?这是因为您正在尝试优化一些您认为很慢的东西,但实际上瓶颈在其他地方。你需要分析你的代码。关于正确的数据结构,如果不知道细节,很难给出一个好的答案。也许您甚至根本不需要存储数据,而是以增量方式工作。否则,使用数组或字符串可以提供良好的性能。@computereasy:我认为ivg想告诉您的是“如何创建rodata_列表”
?”也许您可以直接打印元素,而不是在打印前将其放入列表中。您好,ivg,我尝试了您的建议,在我的代码中编写三个文件片段的总时间从大约8.5秒减少到6秒。还有什么我可以做的吗?顺便说一句:如果不是列表
,那么对于大约100万个元素来说,什么是合适的数据结构呢?这是因为您正在尝试优化一些您认为很慢的东西,但实际上瓶颈在其他地方。你需要分析你的代码。关于正确的数据结构,如果不知道细节,很难给出一个好的答案。也许您甚至根本不需要存储数据,而是以增量方式工作。否则,使用数组或字符串可以提供良好的性能。@computereasy:我认为ivg试图告诉您的是“如何创建rodata_列表”
?”也许您可以直接打印元素,而不是在打印前将其放入列表中。