1<?php 2 3/* 4 Phoronix Test Suite 5 URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/ 6 Copyright (C) 2009 - 2019, Phoronix Media 7 Copyright (C) 2009 - 2019, Michael Larabel 8 pts_ResultFileTable.php: The result file table object 9 10 This program is free software; you can redistribute it and/or modify 11 it under the terms of the GNU General Public License as published by 12 the Free Software Foundation; either version 3 of the License, or 13 (at your option) any later version. 14 15 This program is distributed in the hope that it will be useful, 16 but WITHOUT ANY WARRANTY; without even the implied warranty of 17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 GNU General Public License for more details. 19 20 You should have received a copy of the GNU General Public License 21 along with this program. If not, see <http://www.gnu.org/licenses/>. 22*/ 23 24class pts_ResultFileTable extends pts_Table 25{ 26 public $flagged_results = array(); 27 28 public function __construct(&$result_file, $system_id_keys = null, $result_object_index = -1, $extra_attributes = null) 29 { 30 list($rows, $columns, $table_data) = pts_ResultFileTable::result_file_to_result_table($result_file, $system_id_keys, $result_object_index, $this->flagged_results, $extra_attributes); 31 parent::__construct($rows, $columns, $table_data, $result_file); 32 $this->result_object_index = $result_object_index; 33 34 if($result_object_index == -1) 35 { 36 $this->i['graph_title'] = $result_file->get_title(); 37 } 38 else 39 { 40 $result_object = $result_file->get_result_objects($result_object_index); 41 if(isset($result_object[0])) 42 { 43 $this->i['graph_title'] = $result_object[0]->test_profile->get_title(); 44 $this->graph_sub_titles[] = $result_object[0]->get_arguments_description(); 45 } 46 } 47 48 // where to start the table values 49 $this->longest_row_identifier = null; 50 $longest_row_title_length = 0; 51 foreach($this->rows as $result_test) 52 { 53 if(($len = strlen($result_test)) > $longest_row_title_length) 54 { 55 $this->longest_row_identifier = $result_test; 56 $longest_row_title_length = $len; 57 } 58 } 59 $this->column_heading_vertical = false; 60 //$this->longest_column_identifier = max(pts_strings::find_longest_string($this->columns), pts_strings::find_longest_string($result_file->get_system_identifiers())); 61 } 62 public static function result_file_to_result_table(&$result_file, &$system_id_keys = null, &$result_object_index = -1, &$flag_delta_results = false, $extra_attributes = null) 63 { 64 $result_table = array(); 65 $result_tests = array(); 66 $result_counter = 0; 67 68 foreach($result_file->get_system_identifiers() as $sys_identifier) 69 { 70 $result_table[$sys_identifier] = null; 71 } 72 73 foreach($result_file->get_result_objects($result_object_index) as $ri => $result_object) 74 { 75 if($result_object->test_profile->get_identifier() == null) 76 { 77 continue; 78 } 79 80 if($extra_attributes != null) 81 { 82 if(isset($extra_attributes['reverse_result_buffer'])) 83 { 84 $result_object->test_result_buffer->buffer_values_reverse(); 85 } 86 if(isset($extra_attributes['normalize_result_buffer'])) 87 { 88 if(isset($extra_attributes['highlight_graph_values']) && is_array($extra_attributes['highlight_graph_values']) && count($extra_attributes['highlight_graph_values']) == 1) 89 { 90 $normalize_against = $extra_attributes['highlight_graph_values'][0]; 91 } 92 else 93 { 94 $normalize_against = false; 95 } 96 97 $result_object->normalize_buffer_values($normalize_against); 98 } 99 } 100 101 if($result_object_index != -1) 102 { 103 if(is_array($result_object_index)) 104 { 105 $result_tests[$result_counter] = new pts_graph_ir_value($result_object->get_arguments_description()); 106 } 107 else 108 { 109 $result_tests[$result_counter] = new pts_graph_ir_value('Results'); 110 } 111 } 112 else 113 { 114 if($result_object->test_profile->get_identifier() != null) 115 { 116 $result_tests[$result_counter] = new pts_graph_ir_value($result_object->test_profile->get_identifier_base_name() . ': ' . $result_object->get_arguments_description_shortened(false)); 117 $result_tests[$result_counter]->set_attribute('title', $result_object->get_arguments_description()); 118 $result_tests[$result_counter]->set_attribute('href', 'https://openbenchmarking.org/test/' . $result_object->test_profile->get_identifier()); 119 } 120 else if($result_object->test_profile->get_title() != null) 121 { 122 $result_tests[$result_counter] = new pts_graph_ir_value($result_object->test_profile->get_title() . ': ' . $result_object->get_arguments_description()); 123 } 124 } 125 126 if(false && $result_object->test_profile->get_identifier() == null) 127 { 128 if($result_object->test_profile->get_display_format() == 'BAR_GRAPH') 129 { 130 //$result_tests[$result_counter]->set_attribute('alert', true); 131 foreach($result_object->test_result_buffer->get_buffer_items() as $index => $buffer_item) 132 { 133 $identifier = $buffer_item->get_result_identifier(); 134 $value = $buffer_item->get_result_value(); 135 $result_table[$identifier][$result_counter] = new pts_graph_ir_value($value, array('alert' => true)); 136 } 137 $result_counter++; 138 } 139 continue; 140 } 141 142 $values_in_buffer = $result_object->test_result_buffer->get_values(); 143 $has_numeric = false; 144 foreach($values_in_buffer as $i => $vb) 145 { 146 if(is_numeric($vb)) 147 { 148 $has_numeric = true; 149 break; 150 } 151 else 152 { 153 unset($values_in_buffer[$i]); 154 } 155 } 156 if(!$has_numeric) 157 { 158 continue; 159 } 160 161 switch($result_object->test_profile->get_display_format()) 162 { 163 case 'BAR_GRAPH': 164 $best_value = 0; 165 $worst_value = 0; 166 167 if(!defined('PHOROMATIC_TRACKER') && count($result_object->test_result_buffer->get_values()) > 1) 168 { 169 switch($result_object->test_profile->get_result_proportion()) 170 { 171 case 'HIB': 172 $best_value = max($result_object->test_result_buffer->get_values()); 173 $worst_value = min($result_object->test_result_buffer->get_values()); 174 break; 175 case 'LIB': 176 $best_value = min($result_object->test_result_buffer->get_values()); 177 $worst_value = max($result_object->test_result_buffer->get_values()); 178 break; 179 } 180 } 181 182 $prev_value = 0; 183 $prev_identifier = null; 184 $prev_identifier_0 = null; 185 186 sort($values_in_buffer); 187 $min_value_in_buffer = $values_in_buffer[0]; 188 189 if(empty($min_value_in_buffer)) 190 { 191 // Go through the values until something not 0, otherwise down in the code will be a divide by zero 192 for($i = 1; $i < count($values_in_buffer) && empty($min_value_in_buffer); $i++) 193 { 194 $min_value_in_buffer = $values_in_buffer[$i]; 195 } 196 } 197 198 $max_value_in_buffer = $values_in_buffer[(count($values_in_buffer) - 1)]; 199 200 foreach($result_object->test_result_buffer->get_buffer_items() as $index => $buffer_item) 201 { 202 $identifier = $buffer_item->get_result_identifier(); 203 $value = $buffer_item->get_result_value(); 204 205 if(!is_numeric($value)) 206 { 207 continue; 208 } 209 210 $raw_values = pts_strings::colon_explode($buffer_item->get_result_raw()); 211 $percent_std = pts_math::set_precision(pts_math::percent_standard_deviation($raw_values), 2); 212 $std_error = pts_math::set_precision(pts_math::standard_error($raw_values), 2); 213 $delta = 0; 214 215 if(defined('PHOROMATIC_TRACKER')) 216 { 217 $identifier_r = pts_strings::colon_explode($identifier); 218 219 if($identifier_r[0] == $prev_identifier_0 && $prev_value != 0) 220 { 221 $delta = pts_math::set_precision(abs(1 - ($value / $prev_value)), 4); 222 223 if($delta > 0.02 && $delta > pts_math::standard_deviation($raw_values)) 224 { 225 switch($result_object->test_profile->get_result_proportion()) 226 { 227 case 'HIB': 228 if($value < $prev_value) 229 { 230 $delta = 0 - $delta; 231 } 232 break; 233 case 'LIB': 234 if($value > $prev_value) 235 { 236 $delta = 0 - $delta; 237 } 238 break; 239 } 240 } 241 else 242 { 243 $delta = 0; 244 } 245 } 246 247 $prev_identifier_0 = $identifier_r[0]; 248 $highlight = false; 249 $alert = false; 250 } 251 else 252 { 253 if($result_file->is_multi_way_comparison()) 254 { 255 // TODO: make it work better for highlighting multiple winners in multi-way comparisons 256 $highlight = false; 257 $alert = false; 258 259 // TODO: get this working right 260 if(false && $index % 2 == 1 && $prev_value != 0) 261 { 262 switch($result_object->test_profile->get_result_proportion()) 263 { 264 case 'HIB': 265 if($value > $prev_value) 266 { 267 $highlight = true; 268 } 269 else 270 { 271 $result_table[$prev_identifier][$result_counter]->set_attribute('highlight', true); 272 $result_table[$prev_identifier][$result_counter]->set_attribute('delta', -1); 273 } 274 break; 275 case 'LIB': 276 if($value < $prev_value) 277 { 278 $highlight = true; 279 } 280 else 281 { 282 $result_table[$prev_identifier][$result_counter]->set_attribute('highlight', true); 283 $result_table[$prev_identifier][$result_counter]->set_attribute('delta', -1); 284 } 285 break; 286 } 287 } 288 } 289 else 290 { 291 $alert = $worst_value == $value; 292 $highlight = $best_value == $value; 293 } 294 295 if($min_value_in_buffer != $max_value_in_buffer) 296 { 297 switch($result_object->test_profile->get_result_proportion()) 298 { 299 case 'HIB': 300 $delta = pts_math::set_precision($value / $min_value_in_buffer, 2); 301 break; 302 case 'LIB': 303 $delta = pts_math::set_precision(1 - ($value / $max_value_in_buffer) + 1, 2); 304 break; 305 } 306 } 307 } 308 309 $attributes = array( 310 'std_percent' => $percent_std, 311 'std_error' => $std_error, 312 'delta' => $delta, 313 'highlight' => $highlight, 314 'alert' => $alert 315 ); 316 317 if($delta > $percent_std && $flag_delta_results !== false) 318 { 319 $flag_delta_results[$ri] = $delta; 320 } 321 322 $result_table[$identifier][$result_counter] = new pts_graph_ir_value($value, $attributes); 323 $prev_identifier = $identifier; 324 $prev_value = $value; 325 } 326 break; 327 case 'LINE_GRAPH': 328 case 'FILLED_LINE_GRAPH': 329 $result_tests[$result_counter] = new pts_graph_ir_value($result_object->test_profile->get_title() . ' (Avg)'); 330 331 foreach($result_object->test_result_buffer->get_buffer_items() as $index => $buffer_item) 332 { 333 $identifier = $buffer_item->get_result_identifier(); 334 $values = pts_strings::comma_explode($buffer_item->get_result_value()); 335 $avg_value = pts_math::set_precision(pts_math::arithmetic_mean($values), 2); 336 $result_table[$identifier][$result_counter] = new pts_graph_ir_value($avg_value); 337 } 338 break; 339 } 340 341 $result_counter++; 342 } 343 344 if($result_counter == 1) 345 { 346 // This should provide some additional information under normal modes 347 $has_written_std = false; 348 $has_written_diff = false; 349 $has_written_error = false; 350 351 foreach($result_table as $identifier => $info) 352 { 353 if(!isset($info[($result_counter - 1)])) 354 { 355 continue; 356 } 357 358 $std_percent = $info[($result_counter - 1)]->get_attribute('std_percent'); 359 $std_error = $info[($result_counter - 1)]->get_attribute('std_error'); 360 $delta = $info[($result_counter - 1)]->get_attribute('delta'); 361 362 if($delta != 0) 363 { 364 $result_table[$identifier][] = new pts_graph_ir_value($delta . 'x'); 365 $has_written_diff = true; 366 } 367 if($std_error != 0) 368 { 369 $result_table[$identifier][] = new pts_graph_ir_value($std_error); 370 $has_written_error = true; 371 } 372 if($std_percent != 0) 373 { 374 $result_table[$identifier][] = new pts_graph_ir_value($std_percent . '%'); 375 $has_written_std = true; 376 } 377 } 378 379 if($has_written_diff) 380 { 381 $result_tests[] = new pts_graph_ir_value('Difference'); 382 } 383 if($has_written_error) 384 { 385 $result_tests[] = new pts_graph_ir_value('Standard Error'); 386 } 387 if($has_written_std) 388 { 389 $result_tests[] = new pts_graph_ir_value('Standard Deviation'); 390 } 391 } 392 393 if(defined('PHOROMATIC_TRACKER')) 394 { 395 // Resort the results by SYSTEM, then date 396 $systems_table = array(); 397 $sorted_table = array(); 398 399 foreach($result_table as $system_identifier => &$identifier_table) 400 { 401 $identifier = pts_strings::colon_explode($system_identifier); 402 403 if(!isset($systems_table[$identifier[0]])) 404 { 405 $systems_table[$identifier[0]] = array(); 406 } 407 408 $systems_table[$identifier[0]][$system_identifier] = $identifier_table; 409 } 410 411 $result_table = array(); 412 $result_systems = array(); 413 414 foreach($systems_table as &$group) 415 { 416 foreach($group as $identifier => $table) 417 { 418 $result_table[$identifier] = $table; 419 420 $identifier = pts_strings::colon_explode($identifier); 421 $show_id = isset($identifier[1]) ? $identifier[1] : $identifier[0];/* 422 423 if($system_id_keys != null && ($s = array_search($identifier[0], $system_id_keys)) !== false) 424 { 425 $system_id = $s; 426 } 427 else 428 { 429 $system_id = null; 430 }*/ 431 432 $result_systems[] = $show_id; 433 } 434 } 435 } 436 else 437 { 438 $result_systems = array(); 439 440 foreach(array_keys($result_table) as $id) 441 { 442 $result_systems[] = $id; 443 } 444 } 445 446 return array($result_tests, $result_systems, $result_table); 447 } 448} 449 450?> 451