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)
但没有明显的改善..
所以我想知道,如何优化这部分?我感谢任何解决方案.谢谢!
^在性能关键代码中连接一堆字符串,因为它会导致二次复杂性;*printf当性能很重要时尽量不要依赖函数(尽管在OCaml 4.02中它很快);因此,鉴于上述建议,我们有以下内容:
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.
所以,个人资料.