Safety before Techfest
[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_desc tree tag  Tree.root in
20   let f = Hashtbl.create 4096
21   in
22   let jump t _ =  Tree.tagged_foll_ctx 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_desc tree tag  Tree.root in
45   let f = Hashtbl.create 4096
46   in
47   let jump t _ =  Tree.tagged_foll_ctx 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 "Timing //keyword :" in
68       let r = time (test_loop v) (Tag.tag "keyword") in
69       let _ = Printf.eprintf "Count is %i\n%!" r in 
70       let _ = Printf.eprintf "Timing //keyword 2:" in
71       let r = time (test_loop2 v) (Tag.tag "keyword") in
72       let _ = Printf.eprintf "Count is %i\n%!" r in  
73       let _ = Printf.eprintf "Timing //node() :" in
74       let _ = time (test_full)  v in      *)
75       XPath.Ast.print Format.err_formatter query;
76       Format.fprintf Format.err_formatter "\n%!";
77       Printf.eprintf "Compiling query : ";
78       let auto,ltags,contains = time (XPath.Compile.compile ~querystring:query_string) query in 
79       let _ = Ata.dump Format.err_formatter auto in
80       let _ = Printf.eprintf "%!" in
81       let jump_to = 
82         match contains with
83            None -> (max_int,`NOTHING)
84           | Some ((op,s)) -> 
85               let r = Tree.count v s 
86               in
87               Printf.eprintf "%i documents in the TextCollection\n" (Tree.text_size v);
88               Printf.eprintf "Global count is %i, using " r;
89               if r < !Options.tc_threshold then begin             
90                 Printf.eprintf "TextCollection contains\nCalling global contains : ";
91                 time (Tree.init_textfun op v) s;
92               end
93               else begin
94                 Printf.eprintf "Naive contains\nCalling global contains : ";
95                 time (Tree.init_naive_contains v) s
96               end;(r,`CONTAINS(s))
97       in
98       let test_list = jump_to in
99       (*
100         let test_list = 
101         if (!Options.backward) then begin
102         Printf.eprintf "Finding min occurences : ";
103         time 
104         ( List.fold_left (fun ((min_occ,kind)as acc)  (tag,_) ->
105                               let numtags = Tree.subtree_tags v tag Tree.root in
106                                 if  ((numtags < min_occ) && numtags >= 2)
107                                 then (numtags,`TAG(tag))
108                                 else acc) jump_to) ltags
109           end
110           else (max_int,`NOTHING)
111         in*)
112         let _ = if (snd test_list) != `NOTHING then
113           let occ,s1,s2 = match test_list with
114             | (x,`TAG (tag)) -> (x, "tag", (Tag.to_string tag))
115             | (x,`CONTAINS(s)) -> (x, "contains()", s)
116             | _ -> assert false
117           in
118             Printf.eprintf "Will jump to %s %s occuring %i time\n%!" s1 s2 occ
119         in
120           Printf.eprintf "Execution time %s : "
121             (if !Options.count_only then "(counting only)" else if !Options.backward then "(bottomup)" else "");
122           begin
123             let _ = Gc.full_major();Gc.compact() in
124             let _ = Printf.eprintf "%!" in
125 (*          let _ = Gc.set (disabled_gc) in *)
126               if !Options.backward && ((snd test_list) != `NOTHING )then 
127                 if !Options.count_only then
128                 let r = time_mem (bottom_up_count auto v )(snd test_list)  in
129                 let _ = Printf.eprintf "Number of nodes in the result set : %i\n%!" r 
130                 in ()
131                 else begin
132                 let r = time_mem (bottom_up auto v )(snd test_list)  in
133                 let _ = Printf.eprintf "Number of nodes in the result set : %i\n%!" (IdSet.length r)
134                 in
135                   match output with
136
137                     | None -> ()
138                     | Some f ->               
139                         Printf.eprintf "Serializing results : ";
140                         time( fun () ->
141                                 (*let oc = open_out f in *)
142                                 let oc = Unix.openfile f [ Unix.O_WRONLY;Unix.O_TRUNC;Unix.O_CREAT] 0o644 in
143                                 (*output_string oc "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";*)
144                                 IdSet.iter (fun t -> 
145                                               Tree.print_xml_fast3 v t oc;
146                                               (*output_char oc '\n'; *)                         
147                                            ) r) ();
148                 end
149                      
150               else
151                 let _ = 
152                   if !Options.backward then Printf.eprintf "WARNING: couldn't find a jumping point, running top-down\n" 
153                 in
154                 if !Options.count_only then
155                   let r = time_mem ( top_down_count auto ) v in 
156                   let _ = Printf.eprintf "Number of nodes in the result set : %i\n%!" r
157                   in ()
158                 else      
159                 let module GR = Ata.Test(struct let doc = v end) in
160                   let result = time_mem (GR.top_down auto) v in
161                   let _ = Printf.eprintf "Counting results " in
162                   let rcount = time (GR.Results.length) result in
163                     Printf.eprintf "Number of nodes in the result set : %i\n" rcount;
164                     Printf.eprintf "\n%!";
165                     begin
166                       match output with
167                         | None -> ()
168                         | Some f ->                   
169                             Printf.eprintf "Serializing results : ";
170                             time( fun () ->
171                                     (*let oc = open_out f in *)
172                                     let oc = Unix.openfile f [ Unix.O_WRONLY;Unix.O_TRUNC;Unix.O_CREAT] 0o644 in
173                                       (*output_string oc "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";*)
174                                     let t1 = ref (Unix.gettimeofday()) in
175                                     let count = ref 1 in
176                                     let old_count = ref 1 in
177                                      GR.Results.iter (fun t -> 
178                                                         incr count;
179                                                         begin
180                                                           if (!count mod 15) == 0
181                                                           then
182                                                           let t2 =  Unix.gettimeofday() in
183                                                           let _ = Printf.eprintf "Printing %i elements in %f ms\n"
184                                                             (!count - !old_count) (1000. *.(t2 -. !t1))
185                                                           in
186                                                           ( old_count := !count; t1 := Unix.gettimeofday())
187                                                         end;
188                                                         Tree.print_xml_fast3 v t oc;
189                                                         (*output_char oc '\n'; *)                               
190                                                      ) result) ();
191                     end;
192           end;
193           let _ = Gc.set enabled_gc in
194             Printf.eprintf "Total running time : %fms\n%!" (total_time())
195 ;;
196
197 Options.parse_cmdline();;
198
199 let v =
200   if (Filename.check_suffix !Options.input_file ".srx")
201   then 
202     begin
203       Printf.eprintf "Loading from file : ";
204       time (Tree.load  ~sample:!Options.sample_factor ~load_text:(not !Options.count_only))
205         !Options.input_file;
206         end
207   else 
208     let v = 
209       time (fun () -> let v = Tree.parse_xml_uri !Options.input_file;
210             in Printf.eprintf "Parsing document : %!";v
211            ) () 
212     in
213       if !Options.save_file <> ""
214       then begin
215         Printf.eprintf "Writing file to disk : ";
216         time (Tree.save v) !Options.save_file;
217       end;
218       v
219 in
220   main v !Options.query !Options.output_file;;
221