Added benchmarking funtions,
[SXSI/xpathcomp.git] / main.ml
1 (******************************************************************************)
2 (*  SXSI : XPath evaluator                                                    *)
3 (*  Kim Nguyen (Kim.Nguyen@nicta.com.au)                                      *)
4 (*  Copyright NICTA 2008                                                      *)
5 (*  Distributed under the terms of the LGPL (see LICENCE)                     *)
6 (******************************************************************************)
7
8 open Ata
9 INCLUDE "utils.ml"
10 let () = init_timer();;
11
12 let enabled_gc = Gc.get()
13 let disabled_gc = { Gc.get() with
14                       Gc.max_overhead = 1000000; 
15                       Gc.space_overhead = 100 }
16 let hash x = 131*x/(x-1+1)
17
18 let test_loop tree tag =
19   let t' = Tree.tagged_descendant tree tag  Tree.root in
20   let f = Hashtbl.create 4096
21   in
22   let jump t _ =  Tree.tagged_following_below tree tag t Tree.root in
23   let g t ctx = 
24     if t == Tree.nil then 0
25     else 1+ ((Hashtbl.find f (hash 101)) (jump t ctx) ctx)
26   in
27   Hashtbl.add f (hash 101) g;
28   (Hashtbl.find f (hash 101)) t' Tree.root
29
30 let test_full tree = 
31   let root = Tree.root in
32   let fin = Tree.closing tree root in
33   let rec loop t = if t <= fin then
34   let tag = Tree.tag tree t in
35 (*  let _ = Tag.to_string tag in *)
36   if tag == Tag.pcdata then (ignore (Tree.get_text tree t)); 
37   let t = (Obj.magic ((Obj.magic t) + 1)) in
38   loop t
39   in
40   loop root
41
42
43 let test_loop2 tree tag =
44   let t' = Tree.tagged_descendant tree tag  Tree.root in
45   let f = Hashtbl.create 4096
46   in
47   let jump t _ =  Tree.tagged_following_below tree tag t Tree.root in
48   let rec g t ctx = 
49     if t == Tree.nil then 0
50     else 1+ (match (Hashtbl.find f (hash 101)) with
51                 `Foo ->g (jump t ctx) ctx
52             ) 
53   in
54   Hashtbl.add f (hash 101) `Foo;
55   g t' Tree.root
56
57 let main v query_string output =
58  
59     let _ = Tag.init (Tree.tag_pool v) in
60       Printf.eprintf "Parsing query : ";    
61       let query = try
62         time
63           XPath.Parser.parse_string query_string
64       with
65           Ulexer.Loc.Exc_located ((x,y),e) -> Printf.eprintf "character %i-%i %s\n" x y (Printexc.to_string e);exit 1
66       in
67       let _ = Printf.eprintf "Number of nodes %i\n%!" (Tree.size v) in
68       let _ = Printf.eprintf "Timing first_child/next_sibling %!" in
69       let _ = time (Tree.benchmark_fsns)  v in
70       let _ = Printf.eprintf "Timing jump to a %!" in
71       let _ = time (Tree.benchmark_jump v) (Tag.tag "a")  in
72       
73 (*      let _ = Printf.eprintf "Timing //keyword :" in
74       let r = time (test_loop v) (Tag.tag "keyword") in
75       let _ = Printf.eprintf "Count is %i\n%!" r in 
76       let _ = Printf.eprintf "Timing //keyword 2:" in
77       let r = time (test_loop2 v) (Tag.tag "keyword") in
78       let _ = Printf.eprintf "Count is %i\n%!" r in  
79       let _ = Printf.eprintf "Timing //node() :" in
80       let _ = time (test_full)  v in      *)
81       XPath.Ast.print Format.err_formatter query;
82       Format.fprintf Format.err_formatter "\n%!";
83       Printf.eprintf "Compiling query : ";
84       let auto,ltags,contains = time (XPath.Compile.compile ~querystring:query_string) query in 
85       let _ = Ata.dump Format.err_formatter auto in
86       let _ = Printf.eprintf "%!" in
87       let jump_to = 
88         match contains with
89            None -> (max_int,`NOTHING)
90           | Some ((op,s)) -> 
91               let r = Tree.count v s 
92               in
93               Printf.eprintf "%i documents in the TextCollection\n" (Tree.text_size v);
94               Printf.eprintf "Global count is %i, using " r;
95               if r < !Options.tc_threshold then begin             
96                 Printf.eprintf "TextCollection contains\nCalling global contains : ";
97                 time (Tree.init_textfun op v) s;
98               end
99               else begin
100                 Printf.eprintf "Naive contains\nCalling global contains : ";
101                 time (Tree.init_naive_contains v) s
102               end;(r,`CONTAINS(s))
103       in
104       let test_list = jump_to in
105       (*
106         let test_list = 
107         if (!Options.backward) then begin
108         Printf.eprintf "Finding min occurences : ";
109         time 
110         ( List.fold_left (fun ((min_occ,kind)as acc)  (tag,_) ->
111                               let numtags = Tree.subtree_tags v tag Tree.root in
112                                 if  ((numtags < min_occ) && numtags >= 2)
113                                 then (numtags,`TAG(tag))
114                                 else acc) jump_to) ltags
115           end
116           else (max_int,`NOTHING)
117         in*)
118         let _ = if (snd test_list) != `NOTHING then
119           let occ,s1,s2 = match test_list with
120             | (x,`TAG (tag)) -> (x, "tag", (Tag.to_string tag))
121             | (x,`CONTAINS(s)) -> (x, "contains()", s)
122             | _ -> assert false
123           in
124             Printf.eprintf "Will jump to %s %s occuring %i time\n%!" s1 s2 occ
125         in
126           Printf.eprintf "Execution time %s : "
127             (if !Options.count_only then "(counting only)" else if !Options.backward then "(bottomup)" else "");
128           begin
129             let _ = Gc.full_major();Gc.compact() in
130             let _ = Printf.eprintf "%!" in
131 (*          let _ = Gc.set (disabled_gc) in *)
132               if !Options.backward && ((snd test_list) != `NOTHING )then 
133                 if !Options.count_only then
134                 let r = time_mem (bottom_up_count auto v )(snd test_list)  in
135                 let _ = Printf.eprintf "Number of nodes in the result set : %i\n%!" r 
136                 in ()
137                 else begin
138                 let r = time_mem (bottom_up auto v )(snd test_list)  in
139                 let _ = Printf.eprintf "Number of nodes in the result set : %i\n%!" (IdSet.length r)
140                 in
141                   match output with
142
143                     | None -> ()
144                     | Some f ->               
145                         Printf.eprintf "Serializing results : ";
146                         time( fun () ->
147                                 (*let oc = open_out f in *)
148                                 let oc = Unix.openfile f [ Unix.O_WRONLY;Unix.O_TRUNC;Unix.O_CREAT] 0o644 in
149                                 (*output_string oc "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";*)
150                                 IdSet.iter (fun t -> 
151                                               Tree.print_xml_fast3 v t oc;
152                                               (*output_char oc '\n'; *)                         
153                                            ) r) ();
154                 end
155                      
156               else
157                 let _ = 
158                   if !Options.backward then Printf.eprintf "WARNING: couldn't find a jumping point, running top-down\n" 
159                 in
160                 if !Options.count_only then
161                   let r = time_mem ( top_down_count auto ) v in 
162                   let _ = Printf.eprintf "Number of nodes in the result set : %i\n%!" r
163                   in ()
164                 else      
165                 let module GR = Ata.Test(struct let doc = v end) in
166                   let result = time_mem (GR.top_down auto) v in
167                   let _ = Printf.eprintf "Counting results " in
168                   let rcount = time (GR.Results.length) result in
169                     Printf.eprintf "Number of nodes in the result set : %i\n" rcount;
170                     Printf.eprintf "\n%!";
171                     begin
172                       match output with
173                         | None -> ()
174                         | Some f ->                   
175                             Printf.eprintf "Serializing results : ";
176                             time( fun () ->
177                                     (*let oc = open_out f in *)
178                                     let oc = Unix.openfile f [ Unix.O_WRONLY;Unix.O_TRUNC;Unix.O_CREAT] 0o644 in
179                                       (*output_string oc "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";*)
180                                     let t1 = ref (Unix.gettimeofday()) in
181                                     let count = ref 1 in
182                                     let old_count = ref 1 in
183                                      GR.Results.iter (fun t -> 
184                                                         incr count;
185                                                         begin
186                                                           if (!count mod 15) == 0
187                                                           then
188                                                           let t2 =  Unix.gettimeofday() in
189                                                           let _ = Printf.eprintf "Printing %i elements in %f ms\n"
190                                                             (!count - !old_count) (1000. *.(t2 -. !t1))
191                                                           in
192                                                           ( old_count := !count; t1 := Unix.gettimeofday())
193                                                         end;
194                                                         Tree.print_xml_fast3 v t oc;
195                                                         (*output_char oc '\n'; *)                               
196                                                      ) result) ();
197                     end;
198           end;
199           let _ = Gc.set enabled_gc in
200             Printf.eprintf "Total running time : %fms\n%!" (total_time())
201 ;;
202
203 Options.parse_cmdline();;
204
205 let v =
206   if (Filename.check_suffix !Options.input_file ".srx")
207   then 
208     begin
209       Printf.eprintf "Loading from file : ";
210       time (Tree.load  ~sample:!Options.sample_factor ~load_text:(not !Options.count_only))
211         !Options.input_file;
212         end
213   else 
214     let v = 
215       time (fun () -> let v = Tree.parse_xml_uri !Options.input_file;
216             in Printf.eprintf "Parsing document : %!";v
217            ) () 
218     in
219       if !Options.save_file <> ""
220       then begin
221         Printf.eprintf "Writing file to disk : ";
222         time (Tree.save v) !Options.save_file;
223       end;
224       v
225 in
226   main v !Options.query !Options.output_file;;
227