11 from xml
.dom
import minidom
17 def comp_platform_info(compiler
):
19 so
= commands
.getstatusoutput('cat /proc/cpuinfo | grep \'cpu MHz\'')
21 ret
+= '<li>CPU speed - %s</li>\n' % so
[1]
22 so
= commands
.getstatusoutput('cat /proc/meminfo | grep \'MemTotal\'')
24 ret
+= '<li>Memory - %s</li>\n' % so
[1]
25 ret
+= '<li>Platform - %s</li>\n' % platform
.platform()
26 so
= commands
.getstatusoutput(compiler
+ ' --version')
28 ret
+= '<li>Compiler - %s</li>\n' % so
[1]
35 A 'structure' representing the results of a test.
37 def __init__(self
, x_label
, y_label
, cntnr_list
, cntnr_descs
, res_sets
):
38 self
.x_label
= x_label
39 self
.y_label
= y_label
40 self
.cntnr_list
= cntnr_list
41 self
.cntnr_descs
= cntnr_descs
42 self
.res_sets
= res_sets
47 This class returns a res object for some test.
50 def __accum(self
, results
):
52 for result
in results
:
53 total
= total
+ result
[1]
56 def sort(self
, cntnr_list
, res_sets
):
57 cntnrs_and_totals
= []
58 for cntnr
in cntnr_list
:
59 results
= res_sets
[cntnr
]
60 total
= self
.__accum
(results
)
61 cntnrs_and_totals
.append((cntnr
, total
))
62 by_total
= lambda x
,y
: x
[1] > y
[1] and -1 or 1
63 cntnrs_and_totals
.sort(by_total
)
65 for cntnr_and_total
in cntnrs_and_totals
:
66 cntnr
= cntnr_and_total
[0]
70 def __init__(self
, test_infos_f_name
):
71 self
.__test
_to
_container
_res
_sets
= {}
72 self
.__test
_to
_f
_names
= {}
73 tests_dat
= minidom
.parse(test_infos_f_name
)
74 for test
in tests_dat
.getElementsByTagName('test'):
75 test_name
= test
.attributes
['name'].value
76 self
.__test
_to
_f
_names
[test_name
] = test
.getElementsByTagName('file')[0].attributes
['name'].value
78 for cntnr
in test
.getElementsByTagName('cntnr'):
79 cntnr_list
.append(cntnr
.attributes
['name'].value
)
80 self
.__test
_to
_container
_res
_sets
[test_name
] = cntnr_list
82 def __get_label(self
, tst_dat
, label_name
):
83 label
= tst_dat
.getElementsByTagName(label_name
)[0].firstChild
.data
84 label
= string
.strip(label
, '\n')
85 label
= string
.strip(label
)
88 def __parse_res_sets(self
, f_name
, cntnr_list
):
89 tst_dat
= minidom
.parse(f_name
)
90 x_label
= self
.__get
_label
(tst_dat
, 'x_name')
91 y_label
= self
.__get
_label
(tst_dat
, 'y_name')
92 parsed_container_list
= tst_dat
.getElementsByTagName('cntnr')
95 for cntnr
in parsed_container_list
:
96 cntnr_name
= cntnr
.attributes
["name"].value
97 res_sets
[cntnr_name
] = []
98 for cntnr
in parsed_container_list
:
99 cntnr_name
= cntnr
.attributes
["name"].value
100 cntnr_desc
= cntnr
.getElementsByTagName('desc')
101 if res_sets
.has_key(cntnr_name
):
103 result_list
= cntnr
.getElementsByTagName('result')
104 for result
in result_list
:
105 x
= string
.atol(result
.attributes
["x"].value
)
106 y
= string
.atof(result
.attributes
["y"].value
)
107 res_set
.append((x
, y
))
108 res_sets
[cntnr_name
] = res_set
109 cntnr_descs
[cntnr_name
] = cntnr_desc
[0]
110 return (x_label
, y_label
, cntnr_descs
, res_sets
)
112 def get(self
, res_dir
, test_name
):
113 cntnr_list
= self
.__test
_to
_container
_res
_sets
[test_name
]
114 f_name
= res_dir
+ '/' + self
.__test
_to
_f
_names
[test_name
]
115 parsed
= self
.__parse
_res
_sets
(f_name
, cntnr_list
)
118 cntnr_descs
= parsed
[2]
120 cntnr_list
= self
.__sorter
().sort(cntnr_list
, res_sets
)
121 return res(x_label
, y_label
, cntnr_list
, cntnr_descs
, res_sets
)
126 This class creates a png file from a result set.
128 class __style_chooser
:
130 self
.native_re
= re
.compile(r
'n_(?:.*?)')
132 self
.native_tick_mark_0
= tick_mark
.Circle(size
= 4)
133 self
.native_tick_mark_1
= tick_mark
.Square(size
= 4)
134 self
.native_line_style_0
= line_style
.T(color
= color
.black
, width
=2)
135 self
.native_line_style_1
= line_style
.T(color
= color
.black
, width
=2)
137 self
.mask_re
= re
.compile(r
'mask(?:.*?)')
138 self
.mod_re
= re
.compile(r
'mod(?:.*?)')
140 self
.rb_tree_mmap_rb_tree_set_re
= re
.compile(r
'rb_tree_mmap_rb_tree_set(?:.*?)')
141 self
.rb_tree_mmap_lu_mtf_set_re
= re
.compile(r
'rb_tree_mmap_lu_mtf_set(?:.*?)')
143 self
.splay_re
= re
.compile(r
'splay(?:.*?)')
144 self
.rb_tree_re
= re
.compile(r
'rb_tree(?:.*?)')
145 self
.ov_tree_re
= re
.compile(r
'ov_tree(?:.*?)')
146 self
.splay_tree_re
= re
.compile(r
'splay_tree(?:.*?)')
148 self
.pat_trie_re
= re
.compile(r
'pat_trie(?:.*?)')
150 self
.lc_1div8_1div2_re
= re
.compile(r
'lc_1div8_1div2(?:.*?)')
151 self
.lc_1div8_1div1_re
= re
.compile(r
'lc_1div8_1div1(?:.*?)')
152 self
.mcolc_1div2_re
= re
.compile(r
'mcolc_1div2(?:.*?)')
154 def choose(self
, cntnr
):
155 if self
.native_re
.search(cntnr
):
156 if cntnr
== 'n_pq_vector':
157 return (self
.native_tick_mark_1
, self
.native_line_style_1
)
159 return (self
.native_tick_mark_0
, self
.native_line_style_0
)
161 # tick_mark predefined
162 # square, circle3, dia, tri, dtri, star, plus5, x5, gray70dia, blackdtri, blackdia
163 if self
.mask_re
.search(cntnr
):
165 elif self
.mod_re
.search(cntnr
):
167 elif self
.rb_tree_mmap_rb_tree_set_re
.search(cntnr
):
168 clr
= color
.mediumblue
169 tm
= tick_mark
.square
170 elif self
.rb_tree_mmap_lu_mtf_set_re
.search(cntnr
) or cntnr
== 'rc_binomial_heap':
173 elif self
.splay_tree_re
.search(cntnr
) or cntnr
== 'binomial_heap':
176 elif self
.rb_tree_re
.search(cntnr
) or cntnr
== 'binary_heap':
179 elif self
.ov_tree_re
.search(cntnr
) or cntnr
== 'thin_heap':
180 clr
= color
.orangered1
182 elif self
.pat_trie_re
.search(cntnr
) or cntnr
== 'pairing_heap':
183 clr
= color
.blueviolet
186 sys
.stderr
.write(cntnr
+ '\n')
190 if cntnr
.find('lc_1div8_1div') <> -1:
191 if cntnr
.find('mask') <> -1:
193 if self
.lc_1div8_1div2_re
.search(cntnr
):
194 if cntnr
.find('nsth') <> -1:
197 tm
= tick_mark
.gray70dia
198 if self
.lc_1div8_1div1_re
.search(cntnr
):
199 if cntnr
.find('nsth') <> -1:
202 tm
= tick_mark
.circle3
205 if self
.lc_1div8_1div2_re
.search(cntnr
):
206 if cntnr
.find('nsth') <> -1:
209 tm
= tick_mark
.square
210 if self
.lc_1div8_1div1_re
.search(cntnr
):
211 if cntnr
.find('nsth') <> -1:
216 if self
.mcolc_1div2_re
.search(cntnr
):
217 tm
= tick_mark
.circle3
219 return (tm
, line_style
.T(color
= clr
, width
= 2))
223 self
.__sc
= self
.__style
_chooser
()
224 self
.__mmap
_re
= re
.compile('mmap_')
226 def __container_label_name(self
, cntnr
):
227 return self
.__mmap
_re
.sub('\nmmap_\n', cntnr
)
229 def make(self
, res
, of_name
):
230 theme
.output_format
= 'png'
231 theme
.output_file
= of_name
232 theme
.scale_factor
= 2
233 # theme.default_font_size = 5
236 y_tick_interval
= self
.__get
_y
_tics
(res
)
237 xaxis
= axis
.X(format
= '/a90/hL%d',
240 yaxis
= axis
.Y(format
= '%.2e',
241 tic_interval
= y_tick_interval
,
243 legend_lines
= len(res
.cntnr_list
)
244 legend_vloc
= 50 + (legend_lines
* 10)
245 ar
= area
.T(x_axis
= xaxis
, y_axis
= yaxis
,
246 legend
= legend
.T(loc
=(0,-legend_vloc
),
247 frame_line_style
=None,
251 for cntnr
in res
.cntnr_list
:
252 style
= self
.__sc
.choose(cntnr
)
254 pl
= line_plot
.T(label
= self
.__container
_label
_name
(cntnr
),
255 data
= res
.res_sets
[cntnr
],
256 tick_mark
= style
[0],
257 line_style
= style
[1])
259 for plot
in plot_list
:
264 def __get_y_tics(self
, res
):
266 for cntnr
in res
.cntnr_list
:
267 m
= max(d
[1] for d
in res
.res_sets
[cntnr
])
274 return '<tt>' + s
+ '</tt>'
277 return '<b>' + s
+ '</b>'
280 return '<tt><b>' + s
+ '</b></tt>'
283 return '<i>' + s
+ '</i>'
285 def make_pb_ds_class_href(c_name
):
286 return '<a href = "' + c_name
+ '.html">' + make_tt(c_name
) + '</a>\n'
288 def build_value_to_pb_ds_class_href(s_desc
):
289 value
= s_desc
.attributes
['value'].value
290 ret
= make_pb_ds_class_href(value
)
293 class hash_desc_to_html_builder
:
294 def build_specific_comb_hash_fn(self
, s_desc
):
295 comb_hash_fn_desc
= s_desc
.getElementsByTagName('Comb_Hash_Fn')[0]
296 ret
= make_tt('Comb_Hash_Fn')
298 ret
= ret
+ build_value_to_pb_ds_class_href(comb_hash_fn_desc
)
301 def __build_nom_denom(self
, s_desc
):
302 nom_denom
= s_desc
.attributes
['nom'].value
+ '/' + s_desc
.attributes
['denom'].value
303 return make_i(nom_denom
)
305 def __build_lc_trigger_desc(self
, s_desc
):
306 ret
= build_value_to_pb_ds_class_href(s_desc
)
307 ret
= ret
+ ' with ' + make_i('α<sub>min</sub>')
308 ret
= ret
+ ' = ' + self
.__build
_nom
_denom
(s_desc
.getElementsByTagName('alpha_min')[0])
309 ret
= ret
+ ' and ' + make_i('α<sub>max</sub>')
310 ret
= ret
+ ' = ' + self
.__build
_nom
_denom
(s_desc
.getElementsByTagName('alpha_max')[0])
313 def build_specific_resize_policy(self
, s_desc
):
314 ret
= make_tt('Resize_Policy')
316 resize_policy_desc
= s_desc
.getElementsByTagName('Resize_Policy')[0]
317 ret
= ret
+ build_value_to_pb_ds_class_href(resize_policy_desc
)
318 ret
= ret
+ ' with ' + make_tt('Size_Policy')
320 size_policy_desc
= resize_policy_desc
.getElementsByTagName('Size_Policy')[0]
321 ret
= ret
+ build_value_to_pb_ds_class_href(size_policy_desc
)
322 ret
= ret
+ ', and ' + make_tt('Trigger_Policy')
324 trigger_policy_desc
= resize_policy_desc
.getElementsByTagName('Trigger_Policy')[0]
325 if trigger_policy_desc
.attributes
['value'].value
== 'hash_load_check_resize_trigger':
326 ret
= ret
+ self
.__build
_lc
_trigger
_desc
(trigger_policy_desc
)
332 class cc_hash_desc_to_html_builder
:
334 self
.__hash
_builder
= hash_desc_to_html_builder()
336 def build(self
, s_desc
):
337 ret
= build_value_to_pb_ds_class_href(s_desc
)
338 ret
= ret
+ 'with ' + self
.__hash
_builder
.build_specific_comb_hash_fn(s_desc
)
339 ret
= ret
+ ', and ' + self
.__hash
_builder
.build_specific_resize_policy(s_desc
)
343 class gp_hash_desc_to_html_builder
:
345 self
.__hash
_builder
= hash_desc_to_html_builder()
347 def build(self
, s_desc
):
348 ret
= build_value_to_pb_ds_class_href(s_desc
)
349 ret
= ret
+ ' with ' + self
.__hash
_builder
.build_specific_comb_hash_fn(s_desc
)
350 ret
= ret
+ ', ' + self
.__hash
_builder
.build_specific_resize_policy(s_desc
)
351 ret
= ret
+ ', and ' + make_tt('Probe_Fn')
353 probe_fn
= s_desc
.getElementsByTagName('Probe_Fn')[0].attributes
['value'].value
354 ret
= ret
+ make_pb_ds_class_href(probe_fn
)
358 class basic_tree_like_desc_to_html_builder
:
359 def build_tag(self
, s_desc
):
362 tag_desc
= s_desc
.getElementsByTagName('Tag')[0]
363 ret
= ret
+ build_value_to_pb_ds_class_href(tag_desc
)
366 def build_node_update(self
, s_desc
):
367 ret
= make_tt('Node_Update')
369 node_update_desc
= s_desc
.getElementsByTagName('Node_Update')[0]
370 ret
= ret
+ build_value_to_pb_ds_class_href(node_update_desc
)
374 class basic_tree_desc_to_html_builder
:
376 self
.__tree
_like
_builder
= basic_tree_like_desc_to_html_builder()
378 def build(self
, s_desc
):
379 ret
= build_value_to_pb_ds_class_href(s_desc
)
380 ret
= ret
+ ' with ' + self
.__tree
_like
_builder
.build_tag(s_desc
)
381 ret
= ret
+ ', and ' + self
.__tree
_like
_builder
.build_node_update(s_desc
)
385 class basic_trie_desc_to_html_builder
:
387 self
.__tree
_like
_builder
= basic_tree_like_desc_to_html_builder()
389 def build(self
, s_desc
):
390 ret
= build_value_to_pb_ds_class_href(s_desc
)
391 ret
= ret
+ ' with ' + self
.__tree
_like
_builder
.build_tag(s_desc
)
392 ret
= ret
+ ', and ' + self
.__tree
_like
_builder
.build_node_update(s_desc
)
395 class lu_desc_to_html_builder
:
396 def build(self
, s_desc
):
397 ret
= build_value_to_pb_ds_class_href(s_desc
)
398 ret
= ret
+ ' with ' + make_tt('Update_Policy')
400 update_policy_desc
= s_desc
.getElementsByTagName('Update_Policy')[0]
401 ret
= ret
+ build_value_to_pb_ds_class_href(update_policy_desc
)
405 class std_desc_to_html_builder
:
406 def build(self
, s_desc
):
407 value
= s_desc
.attributes
['value'].value
408 return make_tt(value
.replace('std_', 'std::'))
411 class std_tr1_desc_to_html_builder
:
412 def build(self
, s_desc
):
413 value
= s_desc
.attributes
['value'].value
414 ret
= make_tt(value
.replace('std_tr1_', 'std::tr1::'))
415 ret
= ret
+ ' with ' + make_tt('cache_hash_code')
417 cache_hash_code
= s_desc
.getElementsByTagName('cache_hash_code')[0].attributes
['value'].value
418 ret
= ret
+ make_ttb(cache_hash_code
)
421 class gnucxx_desc_to_html_builder
:
422 def build(self
, s_desc
):
423 value
= s_desc
.attributes
['value'].value
424 return make_tt(value
.replace('__gnucxx_', '__gnucxx::'))
426 class stdext_desc_to_html_builder
:
427 def build(self
, s_desc
):
428 value
= s_desc
.attributes
['value'].value
429 return make_tt(value
.replace('stdext_', 'stdext::'))
431 class npq_desc_to_html_builder
:
432 def build(self
, vector
):
434 under
= make_tt('std::vector')
436 under
= make_tt('std::deque')
438 return make_tt('std::priority_queue') + ' adapting ' + under
440 class binary_heap_desc_to_html_builder
:
441 def build(self
, s_desc
):
442 ret
= make_pb_ds_class_href('priority_queue')
443 ret
= ret
+ ' with ' + make_tt('Tag')
444 ret
= ret
+ ' = ' + make_pb_ds_class_href('binary_heap_tag')
447 class thin_heap_desc_to_html_builder
:
448 def build(self
, s_desc
):
449 ret
= make_pb_ds_class_href('priority_queue')
450 ret
= ret
+ ' with ' + make_tt('Tag')
451 ret
= ret
+ ' = ' + make_pb_ds_class_href('thin_heap_tag')
454 class binomial_heap_desc_to_html_builder
:
455 def build(self
, s_desc
):
456 ret
= make_pb_ds_class_href('priority_queue')
457 ret
= ret
+ ' with ' + make_tt('Tag')
458 ret
= ret
+ ' = ' + make_pb_ds_class_href('binomial_heap_tag')
461 class rc_binomial_heap_desc_to_html_builder
:
462 def build(self
, s_desc
):
463 ret
= make_pb_ds_class_href('priority_queue')
464 ret
= ret
+ ' with ' + make_tt('Tag')
465 ret
= ret
+ ' = ' + make_pb_ds_class_href('rc_binomial_heap_tag')
468 class pairing_heap_desc_to_html_builder
:
469 def build(self
, s_desc
):
470 ret
= make_pb_ds_class_href('priority_queue')
471 ret
= ret
+ ' with ' + make_tt('Tag')
472 ret
= ret
+ ' = ' + make_pb_ds_class_href('pairing_heap_tag')
475 class legend_desc_builder
:
477 Returns a string corresponding to a specific container type.
480 self
.__cc
_hash
_builder
= cc_hash_desc_to_html_builder()
481 self
.__gp
_hash
_builder
= gp_hash_desc_to_html_builder()
482 self
.__basic
_tree
_builder
= basic_tree_desc_to_html_builder()
483 self
.__basic
_trie
_builder
= basic_trie_desc_to_html_builder()
484 self
.__lu_builder
= lu_desc_to_html_builder()
485 self
.__std
_builder
= std_desc_to_html_builder()
486 self
.__std
_tr
1_builder
= std_tr1_desc_to_html_builder()
487 self
.__gnucxx
_builder
= gnucxx_desc_to_html_builder()
488 self
.__stdext
_builder
= stdext_desc_to_html_builder()
489 self
.__npq
_builder
= npq_desc_to_html_builder()
490 self
.__thin
_heap
_builder
= thin_heap_desc_to_html_builder()
491 self
.__thin
_heap
_builder
= thin_heap_desc_to_html_builder()
492 self
.__binary
_heap
_builder
= binary_heap_desc_to_html_builder()
493 self
.__binomial
_heap
_builder
= binomial_heap_desc_to_html_builder()
494 self
.__rc
_binomial
_heap
_builder
= rc_binomial_heap_desc_to_html_builder()
495 self
.__pairing
_heap
_builder
= pairing_heap_desc_to_html_builder()
497 def __build_specific(self
, s_desc
):
498 type = s_desc
.attributes
['value'].value
500 if type == 'thin_heap':
501 return self
.__thin
_heap
_builder
.build(s_desc
)
502 if type == 'binary_heap':
503 return self
.__binary
_heap
_builder
.build(s_desc
)
504 if type == 'binomial_heap':
505 return self
.__binomial
_heap
_builder
.build(s_desc
)
506 if type == 'rc_binomial_heap':
507 return self
.__rc
_binomial
_heap
_builder
.build(s_desc
)
508 if type == 'pairing_heap':
509 return self
.__pairing
_heap
_builder
.build(s_desc
)
510 if type == 'cc_hash_table':
511 ret
= self
.__cc
_hash
_builder
.build(s_desc
)
512 elif type == 'gp_hash_table':
513 ret
= self
.__gp
_hash
_builder
.build(s_desc
)
515 ret
= self
.__basic
_tree
_builder
.build(s_desc
)
517 ret
= self
.__basic
_trie
_builder
.build(s_desc
)
518 elif type == 'list_update':
519 ret
= self
.__lu_builder
.build(s_desc
)
520 elif type == 'std::priority_queue_vector':
521 return self
.__npq
_builder
.build(True)
522 elif type == 'std::priority_queue_deque':
523 return self
.__npq
_builder
.build(False)
524 elif type == 'std_set' or type == 'std_map' or type == 'std_multimap':
525 return self
.__std
_builder
.build(s_desc
)
526 elif type == 'std_tr1_unordered_set' or type == 'std_tr1_unordered_map':
527 return self
.__std
_tr
1_builder
.build(s_desc
)
528 elif type == 'stdext_hash_set' or type == 'stdext_hash_map' or type == 'stdext_hash_multimap':
529 return self
.__stdext
_builder
.build(s_desc
)
530 elif type == '__gnucxx_hash_set' or type == '__gnucxx_hash_map' or type == '__gnucxx_hash_multimap':
531 return self
.__gnucxx
_builder
.build(s_desc
)
533 sys
.stderr
.write('cannot recognize %s\n' % type)
538 def build(self
, desc
):
539 s_descs
= desc
.getElementsByTagName('type')
540 if s_descs
.length
== 0:
545 for s_desc
in s_descs
:
547 ret
= ret
+ ', mapping each key to '
548 ret
= ret
+ self
.__build
_specific
(s_desc
)
553 def main(doc_dir
, res_dir
, test_infos_f_name
, test_name
, build_name
):
554 res_gtr
= res_getter(test_infos_f_name
)
555 res
= res_gtr
.get(res_dir
, test_name
)
556 png_mkr
= png_maker()
557 png_of_name
= doc_dir
+ '/' + test_name
+ '_' + build_name
+ '.png'
559 png_mkr
.make(res
, png_of_name
)
562 if __name__
== "__main__":
564 This module takes 6 parameters from the command line:
567 Tests info XML file name
572 usg
= "make_graph.py <doc_dir> <res_dir> <test_info_file> <test_name> <build_name>\n"
573 if len(sys
.argv
) != 6:
574 sys
.stderr
.write(usg
)
576 main(sys
.argv
[1], sys
.argv
[2], sys
.argv
[3], sys
.argv
[4], sys
.argv
[5])