优化OCaml中的文件写入操作?

lll*_*lll 0 optimization ocaml file 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.fprintf oc "%s\n" l) (zip1 rodata_list);  
Run Code Online (Sandbox Code Playgroud)

这是我的问题,通常rodata_list可以达到800,000大小,我们的服务器(64-bit, 32 core Intel(R) Xeon(R) CPU E5-2690 0 @ 2.90GHz)上面的代码大约需要3.5秒.. OCaml我使用的版本是4.01.0.

这是不可接受的,特别是因为我有4个像这样的代码写入文件.完全他们可以带我超过15秒..

我试过这个:

Printf.fprintf oc "%s\n" (String.concat "\n" (zip1 rodata_list));
Run Code Online (Sandbox Code Playgroud)

但没有明显的改善..

所以我想知道,如何优化这部分?我感谢任何解决方案.谢谢!

ivg*_*ivg 6

  1. 不要用于^在性能关键代码中连接一堆字符串,因为它会导致二次复杂性;
  2. *printf当性能很重要时尽量不要依赖函数(尽管在OCaml 4.02中它很快);
  3. 不要对连续的列表应用多次迭代,因为OCaml没有砍伐森林.尝试在迭代中尽可能多地执行操作;
  4. 如果您使用的是100万个元素的列表,那么您实际上是在做错事.尝试使用不同的数据结构;

因此,鉴于上述建议,我们有以下内容:

List.iter (fun (x,y) -> 
  output_string oc x;
  output_string oc y;
  output_char oc '\n') rodata_list
Run Code Online (Sandbox Code Playgroud)

此外,任何优化都应该从分析开始,以获得使用分析信息编译它所需的配置文件,例如:

 ocamlbuild myprogram.p.native
Run Code Online (Sandbox Code Playgroud)

然后你可以运行程序来收集配置文件,可以阅读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)
Run Code Online (Sandbox Code Playgroud)

它创建一个包含一百万个元素的列表并输出它:

$ ocamlbuild main.native 
$ time ./main.native > data.txt

real    0m0.998s
user    0m0.211s
sys     0m0.783s
Run Code Online (Sandbox Code Playgroud)

这是在macbook笔记本电脑上.此外,我们大部分时间都在系统中,OCaml只有200毫秒.在没有创建列表的情况下进行1000_000次迭代的简单循环只需要11ms.

所以,个人资料.