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中速度非常快)
  • 不要对一行中的列表应用多次迭代,因为OCaml没有去叶功能。尝试在迭代中尽可能多地执行操作
  • 如果你使用的是100万个元素的列表,那么你实际上是做错了什么。尽量使用不同的数据结构 因此,根据上述建议,我们有以下几点:

    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中速度非常快)
  • 不要对一行中的列表应用多次迭代,因为OCaml没有去叶功能。尝试在迭代中尽可能多地执行操作
  • 如果你使用的是100万个元素的列表,那么你实际上是做错了什么。尽量使用不同的数据结构 因此,根据上述建议,我们有以下几点:

    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_列表”
    ?”也许您可以直接打印元素,而不是在打印前将其放入列表中。