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
= 'svg'
231 theme
.output_file
= of_name
232 theme
.scale_factor
= 2
233 theme
.default_font_family
= "Gill Sans Std"
234 theme
.default_line_width
= 0.5
235 theme
.default_font_size
= 7
238 y_tick_interval
= self
.__get
_y
_tics
(res
)
239 # xaxis = axis.X(format = '/a90/hL%d',
240 xaxis
= axis
.X(format
= "/a-50{}%d",
243 # yaxis = axis.Y(format = '%.2e',
244 yaxis
= axis
.Y(format
= "/a-50{}%.2e",
245 tic_interval
= y_tick_interval
,
247 legend_lines
= len(res
.cntnr_list
)
248 legend_vloc
= 50 + (legend_lines
* 10)
250 ar
= area
.T(x_axis
= xaxis
, y_axis
= yaxis
,
251 legend
= legend
.T(loc
=(legend_hloc
,-legend_vloc
),
252 frame_line_style
=None,
256 for cntnr
in res
.cntnr_list
:
257 style
= self
.__sc
.choose(cntnr
)
259 pl
= line_plot
.T(label
= self
.__container
_label
_name
(cntnr
),
260 data
= res
.res_sets
[cntnr
],
261 tick_mark
= style
[0],
262 line_style
= style
[1])
264 for plot
in plot_list
:
269 def __get_y_tics(self
, res
):
271 for cntnr
in res
.cntnr_list
:
272 m
= max(d
[1] for d
in res
.res_sets
[cntnr
])
279 return '<tt>' + s
+ '</tt>'
282 return '<b>' + s
+ '</b>'
285 return '<tt><b>' + s
+ '</b></tt>'
288 return '<i>' + s
+ '</i>'
290 def make_pb_ds_class_href(c_name
):
291 return '<a href = "' + c_name
+ '.html">' + make_tt(c_name
) + '</a>\n'
293 def build_value_to_pb_ds_class_href(s_desc
):
294 value
= s_desc
.attributes
['value'].value
295 ret
= make_pb_ds_class_href(value
)
298 class hash_desc_to_html_builder
:
299 def build_specific_comb_hash_fn(self
, s_desc
):
300 comb_hash_fn_desc
= s_desc
.getElementsByTagName('Comb_Hash_Fn')[0]
301 ret
= make_tt('Comb_Hash_Fn')
303 ret
= ret
+ build_value_to_pb_ds_class_href(comb_hash_fn_desc
)
306 def __build_nom_denom(self
, s_desc
):
307 nom_denom
= s_desc
.attributes
['nom'].value
+ '/' + s_desc
.attributes
['denom'].value
308 return make_i(nom_denom
)
310 def __build_lc_trigger_desc(self
, s_desc
):
311 ret
= build_value_to_pb_ds_class_href(s_desc
)
312 ret
= ret
+ ' with ' + make_i('α<sub>min</sub>')
313 ret
= ret
+ ' = ' + self
.__build
_nom
_denom
(s_desc
.getElementsByTagName('alpha_min')[0])
314 ret
= ret
+ ' and ' + make_i('α<sub>max</sub>')
315 ret
= ret
+ ' = ' + self
.__build
_nom
_denom
(s_desc
.getElementsByTagName('alpha_max')[0])
318 def build_specific_resize_policy(self
, s_desc
):
319 ret
= make_tt('Resize_Policy')
321 resize_policy_desc
= s_desc
.getElementsByTagName('Resize_Policy')[0]
322 ret
= ret
+ build_value_to_pb_ds_class_href(resize_policy_desc
)
323 ret
= ret
+ ' with ' + make_tt('Size_Policy')
325 size_policy_desc
= resize_policy_desc
.getElementsByTagName('Size_Policy')[0]
326 ret
= ret
+ build_value_to_pb_ds_class_href(size_policy_desc
)
327 ret
= ret
+ ', and ' + make_tt('Trigger_Policy')
329 trigger_policy_desc
= resize_policy_desc
.getElementsByTagName('Trigger_Policy')[0]
330 if trigger_policy_desc
.attributes
['value'].value
== 'hash_load_check_resize_trigger':
331 ret
= ret
+ self
.__build
_lc
_trigger
_desc
(trigger_policy_desc
)
337 class cc_hash_desc_to_html_builder
:
339 self
.__hash
_builder
= hash_desc_to_html_builder()
341 def build(self
, s_desc
):
342 ret
= build_value_to_pb_ds_class_href(s_desc
)
343 ret
= ret
+ 'with ' + self
.__hash
_builder
.build_specific_comb_hash_fn(s_desc
)
344 ret
= ret
+ ', and ' + self
.__hash
_builder
.build_specific_resize_policy(s_desc
)
348 class gp_hash_desc_to_html_builder
:
350 self
.__hash
_builder
= hash_desc_to_html_builder()
352 def build(self
, s_desc
):
353 ret
= build_value_to_pb_ds_class_href(s_desc
)
354 ret
= ret
+ ' with ' + self
.__hash
_builder
.build_specific_comb_hash_fn(s_desc
)
355 ret
= ret
+ ', ' + self
.__hash
_builder
.build_specific_resize_policy(s_desc
)
356 ret
= ret
+ ', and ' + make_tt('Probe_Fn')
358 probe_fn
= s_desc
.getElementsByTagName('Probe_Fn')[0].attributes
['value'].value
359 ret
= ret
+ make_pb_ds_class_href(probe_fn
)
363 class basic_tree_like_desc_to_html_builder
:
364 def build_tag(self
, s_desc
):
367 tag_desc
= s_desc
.getElementsByTagName('Tag')[0]
368 ret
= ret
+ build_value_to_pb_ds_class_href(tag_desc
)
371 def build_node_update(self
, s_desc
):
372 ret
= make_tt('Node_Update')
374 node_update_desc
= s_desc
.getElementsByTagName('Node_Update')[0]
375 ret
= ret
+ build_value_to_pb_ds_class_href(node_update_desc
)
379 class basic_tree_desc_to_html_builder
:
381 self
.__tree
_like
_builder
= basic_tree_like_desc_to_html_builder()
383 def build(self
, s_desc
):
384 ret
= build_value_to_pb_ds_class_href(s_desc
)
385 ret
= ret
+ ' with ' + self
.__tree
_like
_builder
.build_tag(s_desc
)
386 ret
= ret
+ ', and ' + self
.__tree
_like
_builder
.build_node_update(s_desc
)
390 class basic_trie_desc_to_html_builder
:
392 self
.__tree
_like
_builder
= basic_tree_like_desc_to_html_builder()
394 def build(self
, s_desc
):
395 ret
= build_value_to_pb_ds_class_href(s_desc
)
396 ret
= ret
+ ' with ' + self
.__tree
_like
_builder
.build_tag(s_desc
)
397 ret
= ret
+ ', and ' + self
.__tree
_like
_builder
.build_node_update(s_desc
)
400 class lu_desc_to_html_builder
:
401 def build(self
, s_desc
):
402 ret
= build_value_to_pb_ds_class_href(s_desc
)
403 ret
= ret
+ ' with ' + make_tt('Update_Policy')
405 update_policy_desc
= s_desc
.getElementsByTagName('Update_Policy')[0]
406 ret
= ret
+ build_value_to_pb_ds_class_href(update_policy_desc
)
410 class std_desc_to_html_builder
:
411 def build(self
, s_desc
):
412 value
= s_desc
.attributes
['value'].value
413 return make_tt(value
.replace('std_', 'std::'))
416 class std_tr1_desc_to_html_builder
:
417 def build(self
, s_desc
):
418 value
= s_desc
.attributes
['value'].value
419 ret
= make_tt(value
.replace('std_tr1_', 'std::tr1::'))
420 ret
= ret
+ ' with ' + make_tt('cache_hash_code')
422 cache_hash_code
= s_desc
.getElementsByTagName('cache_hash_code')[0].attributes
['value'].value
423 ret
= ret
+ make_ttb(cache_hash_code
)
426 class gnucxx_desc_to_html_builder
:
427 def build(self
, s_desc
):
428 value
= s_desc
.attributes
['value'].value
429 return make_tt(value
.replace('__gnucxx_', '__gnucxx::'))
431 class stdext_desc_to_html_builder
:
432 def build(self
, s_desc
):
433 value
= s_desc
.attributes
['value'].value
434 return make_tt(value
.replace('stdext_', 'stdext::'))
436 class npq_desc_to_html_builder
:
437 def build(self
, vector
):
439 under
= make_tt('std::vector')
441 under
= make_tt('std::deque')
443 return make_tt('std::priority_queue') + ' adapting ' + under
445 class binary_heap_desc_to_html_builder
:
446 def build(self
, s_desc
):
447 ret
= make_pb_ds_class_href('priority_queue')
448 ret
= ret
+ ' with ' + make_tt('Tag')
449 ret
= ret
+ ' = ' + make_pb_ds_class_href('binary_heap_tag')
452 class thin_heap_desc_to_html_builder
:
453 def build(self
, s_desc
):
454 ret
= make_pb_ds_class_href('priority_queue')
455 ret
= ret
+ ' with ' + make_tt('Tag')
456 ret
= ret
+ ' = ' + make_pb_ds_class_href('thin_heap_tag')
459 class binomial_heap_desc_to_html_builder
:
460 def build(self
, s_desc
):
461 ret
= make_pb_ds_class_href('priority_queue')
462 ret
= ret
+ ' with ' + make_tt('Tag')
463 ret
= ret
+ ' = ' + make_pb_ds_class_href('binomial_heap_tag')
466 class rc_binomial_heap_desc_to_html_builder
:
467 def build(self
, s_desc
):
468 ret
= make_pb_ds_class_href('priority_queue')
469 ret
= ret
+ ' with ' + make_tt('Tag')
470 ret
= ret
+ ' = ' + make_pb_ds_class_href('rc_binomial_heap_tag')
473 class pairing_heap_desc_to_html_builder
:
474 def build(self
, s_desc
):
475 ret
= make_pb_ds_class_href('priority_queue')
476 ret
= ret
+ ' with ' + make_tt('Tag')
477 ret
= ret
+ ' = ' + make_pb_ds_class_href('pairing_heap_tag')
480 class legend_desc_builder
:
482 Returns a string corresponding to a specific container type.
485 self
.__cc
_hash
_builder
= cc_hash_desc_to_html_builder()
486 self
.__gp
_hash
_builder
= gp_hash_desc_to_html_builder()
487 self
.__basic
_tree
_builder
= basic_tree_desc_to_html_builder()
488 self
.__basic
_trie
_builder
= basic_trie_desc_to_html_builder()
489 self
.__lu_builder
= lu_desc_to_html_builder()
490 self
.__std
_builder
= std_desc_to_html_builder()
491 self
.__std
_tr
1_builder
= std_tr1_desc_to_html_builder()
492 self
.__gnucxx
_builder
= gnucxx_desc_to_html_builder()
493 self
.__stdext
_builder
= stdext_desc_to_html_builder()
494 self
.__npq
_builder
= npq_desc_to_html_builder()
495 self
.__thin
_heap
_builder
= thin_heap_desc_to_html_builder()
496 self
.__thin
_heap
_builder
= thin_heap_desc_to_html_builder()
497 self
.__binary
_heap
_builder
= binary_heap_desc_to_html_builder()
498 self
.__binomial
_heap
_builder
= binomial_heap_desc_to_html_builder()
499 self
.__rc
_binomial
_heap
_builder
= rc_binomial_heap_desc_to_html_builder()
500 self
.__pairing
_heap
_builder
= pairing_heap_desc_to_html_builder()
502 def __build_specific(self
, s_desc
):
503 type = s_desc
.attributes
['value'].value
505 if type == 'thin_heap':
506 return self
.__thin
_heap
_builder
.build(s_desc
)
507 if type == 'binary_heap':
508 return self
.__binary
_heap
_builder
.build(s_desc
)
509 if type == 'binomial_heap':
510 return self
.__binomial
_heap
_builder
.build(s_desc
)
511 if type == 'rc_binomial_heap':
512 return self
.__rc
_binomial
_heap
_builder
.build(s_desc
)
513 if type == 'pairing_heap':
514 return self
.__pairing
_heap
_builder
.build(s_desc
)
515 if type == 'cc_hash_table':
516 ret
= self
.__cc
_hash
_builder
.build(s_desc
)
517 elif type == 'gp_hash_table':
518 ret
= self
.__gp
_hash
_builder
.build(s_desc
)
520 ret
= self
.__basic
_tree
_builder
.build(s_desc
)
522 ret
= self
.__basic
_trie
_builder
.build(s_desc
)
523 elif type == 'list_update':
524 ret
= self
.__lu_builder
.build(s_desc
)
525 elif type == 'std::priority_queue_vector':
526 return self
.__npq
_builder
.build(True)
527 elif type == 'std::priority_queue_deque':
528 return self
.__npq
_builder
.build(False)
529 elif type == 'std_set' or type == 'std_map' or type == 'std_multimap':
530 return self
.__std
_builder
.build(s_desc
)
531 elif type == 'std_tr1_unordered_set' or type == 'std_tr1_unordered_map':
532 return self
.__std
_tr
1_builder
.build(s_desc
)
533 elif type == 'stdext_hash_set' or type == 'stdext_hash_map' or type == 'stdext_hash_multimap':
534 return self
.__stdext
_builder
.build(s_desc
)
535 elif type == '__gnucxx_hash_set' or type == '__gnucxx_hash_map' or type == '__gnucxx_hash_multimap':
536 return self
.__gnucxx
_builder
.build(s_desc
)
538 sys
.stderr
.write('cannot recognize %s\n' % type)
543 def build(self
, desc
):
544 s_descs
= desc
.getElementsByTagName('type')
545 if s_descs
.length
== 0:
550 for s_desc
in s_descs
:
552 ret
= ret
+ ', mapping each key to '
553 ret
= ret
+ self
.__build
_specific
(s_desc
)
558 def main(doc_dir
, res_dir
, test_infos_f_name
, test_name
, build_name
):
559 res_gtr
= res_getter(test_infos_f_name
)
560 res
= res_gtr
.get(res_dir
, test_name
)
561 png_mkr
= png_maker()
562 # png_of_name = doc_dir + '/' + test_name + '_' + build_name + '.png'
563 png_of_name
= doc_dir
+ '/' + test_name
+ '_' + build_name
+ '.svg'
565 png_mkr
.make(res
, png_of_name
)
568 if __name__
== "__main__":
570 This module takes 6 parameters from the command line:
573 Tests info XML file name
578 usg
= "make_graph.py <doc_dir> <res_dir> <test_info_file> <test_name> <build_name>\n"
579 if len(sys
.argv
) != 6:
580 sys
.stderr
.write(usg
)
582 main(sys
.argv
[1], sys
.argv
[2], sys
.argv
[3], sys
.argv
[4], sys
.argv
[5])