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

Optimize a file writing operation in OCaml?

基本上在我的项目中,我试图将字符串列表写入文件,如下所示:

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);  

这是我的问题,通常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));

但没有明显改善..

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

  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

此外,任何优化都应该从分析开始,为了获得您需要的配置文件,您需要使用分析信息对其进行编译,例如:

 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 毫秒。

所以,简介。