public static function run($r) { $compare_tests = array(); $compare_subsystems = array(); foreach ($r as $test_object) { $test_object = pts_types::identifier_to_object($test_object); if ($test_object instanceof pts_test_profile) { array_push($compare_tests, $test_object->get_identifier(false)); if (!isset($compare_subsystems[$test_object->get_test_hardware_type()])) { $compare_subsystems[$test_object->get_test_hardware_type()] = 1; } else { $compare_subsystems[$test_object->get_test_hardware_type()] += 1; } } } if (empty($compare_tests)) { $subsystem_under_test = pts_user_io::prompt_text_menu('Sub-System To Test', array('Processor', 'Graphics', 'Disk')); } else { arsort($compare_subsystems); $compare_subsystems = array_keys($compare_subsystems); $subsystem_under_test = array_shift($compare_subsystems); } $system_info = array_merge(phodevi::system_hardware(false), phodevi::system_software(false)); $to_include = array(); $to_exclude = array(); if (isset($system_info[$subsystem_under_test])) { $compare_component = $system_info[$subsystem_under_test]; } else { return; } switch ($subsystem_under_test) { case 'Processor': self::system_component_to_format($system_info, $to_include, array('OS', 'Compiler', 'Kernel', 'Motherboard'), true); break; case 'Graphics': self::system_component_to_format($system_info, $to_include, array('OS', 'Display Driver', 'OpenGL', 'Processor', 'Kernel', 'Desktop'), true); break; case 'OS': self::system_component_to_format($system_info, $to_include, array('Processor', 'Motherboard', 'Graphics', 'Disk'), true); self::system_component_to_format($system_info, $to_exclude, array('OS')); break; case 'Disk': self::system_component_to_format($system_info, $to_include, array('Processor', 'OS', 'Chipset', 'Motherboard', 'Kernel'), true); break; } $payload = array('subsystem_under_test' => $subsystem_under_test, 'component_under_test' => $compare_component, 'include_components' => implode(',', $to_include), 'exclude_components' => implode(',', $to_exclude), 'include_tests' => implode(',', $compare_tests)); echo PHP_EOL . 'Querying test data from OpenBenchmarking.org...' . PHP_EOL; $json = pts_openbenchmarking::make_openbenchmarking_request('auto_generate_comparison', $payload); $json = json_decode($json, true); if (isset($json['auto_compare']['public_ids']) && isset($json['auto_compare']['count']) && $json['auto_compare']['count'] > 0) { echo 'Found ' . $json['auto_compare']['count'] . ' comparable results on OpenBenchmarking.org with a ' . $json['auto_compare']['accuracy'] . '% accuracy.' . PHP_EOL; $compare_results = array(); foreach ($json['auto_compare']['public_ids'] as $public_id) { $result_xml = pts_openbenchmarking::clone_openbenchmarking_result($public_id, true); if ($result_xml) { $result_file = new pts_result_file($result_xml); $result_objects = $result_file->get_result_objects(); foreach ($result_objects as $i => &$result_object) { if (!empty($compare_tests)) { if (!in_array($result_object->test_profile->get_identifier(false), $compare_tests)) { unset($result_objects[$i]); } } else { if ($result_object->test_profile->get_test_hardware_type() != $subsystem_under_test) { unset($result_objects[$i]); } } } if (count($result_objects) == 0) { continue; } $result_file->override_result_objects($result_objects); array_push($compare_results, $result_file); } } if (count($compare_results) > 0) { $result_xml = pts_merge::merge_test_results_array($compare_results); if (count($compare_results) > 2) { $result_file = new pts_result_file($result_xml); $result_objects = $result_file->get_result_objects(); $system_count = $result_file->get_system_count(); $result_count = count($result_objects); $result_match_count = array(); if ($result_count > 3) { foreach ($result_objects as $i => &$result_object) { $result_match_count[$i] = $result_object->test_result_buffer->get_count(); } arsort($result_match_count); $biggest_size = pts_arrays::first_element($result_match_count); if ($biggest_size == $system_count || $biggest_size > 3) { foreach ($result_match_count as $key => $value) { if ($value < 2) { unset($result_objects[$key]); } } } $result_file->override_result_objects($result_objects); $result_xml = pts_merge::merge_test_results_array(array($result_file)); } } pts_client::save_test_result('auto-comparison/composite.xml', $result_xml); } } pts_test_installer::standard_install(array('auto-comparison')); pts_test_run_manager::standard_run(array('auto-comparison')); }
public static function evaluate_redundant_identifier_words($identifiers) { if (count($identifiers) < 4 || strpos(pts_arrays::first_element($identifiers), ':') !== false) { // Probably not worth shortening so few result identifiers return false; } // Breakup the an identifier into an array by spaces to be used for comparison $common_segments = explode(' ', pts_arrays::first_element($identifiers)); $common_segments_last = explode(' ', pts_arrays::last_element($identifiers)); if (!isset($common_segments_last[2]) || !isset($common_segments[2])) { // If there aren't at least three words in identifier, probably can't be shortened well return false; } foreach (array_reverse($identifiers) as $id) { $words = explode(' ', $id); foreach ($words as $i => $word) { if (isset($common_segments[$i]) && $word != $common_segments[$i] && isset($word[2]) && !ctype_alnum(substr($word, -1))) { // IS COMMON WORD } else { unset($common_segments[$i]); } } if (count($common_segments) == 0) { return false; } } return $common_segments; }
public static function result_file_to_text(&$result_file, $terminal_width = 80) { $result_output = null; $result_output .= $result_file->get_title() . PHP_EOL; $result_output .= $result_file->get_description() . PHP_EOL . PHP_EOL . PHP_EOL; $system_identifiers = array(); $system_hardware = array(); $system_software = array(); foreach ($result_file->get_systems() as $system) { array_push($system_identifiers, $system->get_identifier()); array_push($system_hardware, $system->get_hardware()); array_push($system_software, $system->get_software()); } for ($i = 0; $i < count($system_identifiers); $i++) { $result_output .= $system_identifiers[$i] . ': ' . PHP_EOL . PHP_EOL; $result_output .= "\t" . $system_hardware[$i] . PHP_EOL . PHP_EOL . "\t" . $system_software[$i] . PHP_EOL . PHP_EOL; } $longest_identifier_length = strlen(pts_strings::find_longest_string($system_identifiers)) + 2; foreach ($result_file->get_result_objects() as $result_object) { $result_output .= trim($result_object->test_profile->get_title() . ' ' . $result_object->test_profile->get_app_version() . PHP_EOL . $result_object->get_arguments_description()); if ($result_object->test_profile->get_result_scale() != null) { $result_output .= PHP_EOL . ' ' . $result_object->test_profile->get_result_scale(); } foreach ($result_object->test_result_buffer as &$buffers) { $max_value = 0; $min_value = pts_arrays::first_element($buffers)->get_result_value(); foreach ($buffers as &$buffer_item) { if ($buffer_item->get_result_value() > $max_value) { $max_value = $buffer_item->get_result_value(); } else { if ($buffer_item->get_result_value() < $min_value) { $min_value = $buffer_item->get_result_value(); } } } $longest_result = strlen($max_value) + 1; foreach ($buffers as &$buffer_item) { $val = $buffer_item->get_result_value(); if (stripos($val, ',') !== false) { $vals = explode(',', $val); $val = 'MIN: ' . min($vals) . ' / AVG: ' . round(array_sum($vals) / count($vals), 2) . ' / MAX: ' . max($vals); } $result_output .= PHP_EOL . ' ' . $buffer_item->get_result_identifier() . ' '; $result_length_offset = $longest_identifier_length - strlen($buffer_item->get_result_identifier()); if ($result_length_offset > 0) { $result_output .= str_repeat('.', $result_length_offset) . ' '; } $result_output .= $val; if (is_numeric($val)) { $result_output .= str_repeat(' ', $longest_result - strlen($val)) . '|'; $current_line_length = strlen(substr($result_output, strrpos($result_output, PHP_EOL) + 1)) + 1; $result_output .= str_repeat('=', round($val / $max_value * ($terminal_width - $current_line_length))); } } } $result_output .= PHP_EOL . PHP_EOL; } return $result_output; }
public static function environmental_variables() { // The PTS environmental variables passed during the testing process, etc static $env_variables = null; if ($env_variables == null) { $env_variables = array('PTS_VERSION' => PTS_VERSION, 'PTS_CODENAME' => PTS_CODENAME, 'PTS_DIR' => PTS_PATH, 'PHP_BIN' => PHP_BIN, 'NUM_CPU_CORES' => phodevi::read_property('cpu', 'core-count'), 'NUM_CPU_NODES' => phodevi::read_property('cpu', 'node-count'), 'NUM_CPU_JOBS' => phodevi::read_property('cpu', 'core-count') * 2, 'SYS_MEMORY' => phodevi::read_property('memory', 'capacity'), 'VIDEO_MEMORY' => phodevi::read_property('gpu', 'memory-capacity'), 'VIDEO_WIDTH' => pts_arrays::first_element(phodevi::read_property('gpu', 'screen-resolution')), 'VIDEO_HEIGHT' => pts_arrays::last_element(phodevi::read_property('gpu', 'screen-resolution')), 'VIDEO_MONITOR_COUNT' => phodevi::read_property('monitor', 'count'), 'VIDEO_MONITOR_LAYOUT' => phodevi::read_property('monitor', 'layout'), 'VIDEO_MONITOR_SIZES' => phodevi::read_property('monitor', 'modes'), 'OPERATING_SYSTEM' => phodevi::read_property('system', 'vendor-identifier'), 'OS_VERSION' => phodevi::read_property('system', 'os-version'), 'OS_ARCH' => phodevi::read_property('system', 'kernel-architecture'), 'OS_TYPE' => phodevi::operating_system(), 'THIS_RUN_TIME' => PTS_INIT_TIME, 'DEBUG_REAL_HOME' => pts_core::user_home_directory()); if (!pts_client::executable_in_path('cc') && pts_client::executable_in_path('gcc') && getenv('CC') == false) { // This helps some test profiles build correctly if they don't do a cc check internally $env_variables['CC'] = 'gcc'; } } return $env_variables; }
public function increase_run_count_check(&$active_result_buffer, $scheduled_times_to_run, $latest_test_run_time) { // First make sure this test doesn't take too long to run where we don't want dynamic handling if (floor($latest_test_run_time / 60) > $this->dynamic_run_count_on_length_or_less) { return false; } // Determine if results are statistically significant, otherwise up the run count $std_dev = pts_math::percent_standard_deviation($active_result_buffer->results); if ($std_dev >= $this->dynamic_run_count_std_deviation_threshold) { static $last_run_count = 128; // just a number that should always cause the first check below to be true static $run_std_devs; $times_already_ran = $active_result_buffer->get_trial_run_count(); if ($times_already_ran <= $last_run_count) { // We're now onto a new test so clear out the array $run_std_devs = array(); } $last_run_count = $times_already_ran; $run_std_devs[$last_run_count] = $std_dev; // If we haven't reached scheduled times to run x 2, increase count straight away if ($times_already_ran < $scheduled_times_to_run * 2) { return true; } else { if ($times_already_ran < $scheduled_times_to_run * 3) { // More aggressive determination whether to still keep increasing the run count $first_and_now_diff = pts_arrays::first_element($run_std_devs) - pts_arrays::last_element($run_std_devs); // Increasing the run count at least looks to be helping... if ($first_and_now_diff > pts_arrays::first_element($run_std_devs) / 2) { // If we are at least making progress in the right direction, increase the run count some more return true; } // TODO: could add more checks and take better advantage of the array of data to better determine if it's still worth increasing } } } // Check to see if there is an external/custom script to export the results to in determining whether results are valid if (($ex_file = $this->dynamic_run_count_export_script) != null && is_executable($ex_file) || is_executable($ex_file = PTS_USER_PATH . $this->dynamic_run_count_export_script)) { $exit_status = trim(shell_exec($ex_file . ' ' . $active_result_buffer->get_values_as_string() . ' > /dev/null 2>&1; echo $?')); switch ($exit_status) { case 1: // Run the test again return true; case 2: // Results are bad, abandon testing and do not record results return -1; case 0: default: // Return was 0 or something else, results are valid, or was some other exit status break; } } // No reason to increase the run count with none of the previous checks requesting otherwise return false; }
public static function cpu_default_frequency($cpu_core = 0) { // Find out the processor frequency $info = null; // First, the ideal way, with modern CPUs using CnQ or EIST and cpuinfo reporting the current if (is_file('/sys/devices/system/cpu/cpu' . $cpu_core . '/cpufreq/scaling_max_freq')) { $info = pts_file_io::file_get_contents('/sys/devices/system/cpu/cpu' . $cpu_core . '/cpufreq/scaling_max_freq'); $info = intval($info) / 1000000; if ($info > 9) { // For some reason on Linux 3.10 the scaling_max_freq is reported as 25GHz... $info = null; } } if ($info == null && isset(phodevi::$vfs->cpuinfo)) { $cpu_mhz = self::read_cpuinfo_line('cpu MHz'); $info = $cpu_mhz / 1000; if (empty($info)) { $cpu_mhz = self::read_cpuinfo_line('clock'); $info = $cpu_mhz / 1000; } } else { if ($info == null && phodevi::is_bsd()) { $info = phodevi_bsd_parser::read_sysctl(array('dev.cpu.0.freq_levels')); if ($info != null) { // Popping the top speed off of dev.cpu.0.freq_levels should be the default/highest supported frequency $info = pts_arrays::first_element(explode(' ', str_replace('/', ' ', $info))); if (!is_numeric($info)) { $info = null; } } if ($info == null) { $info = phodevi_bsd_parser::read_sysctl(array('hw.acpi.cpu.px_global', 'machdep.est.frequency.target', 'hw.cpuspeed')); } if ($info == null) { // dev.cpu.0.freq seems to be the real/current frequency, affected by power management, etc so only use as last fallback $info = phodevi_bsd_parser::read_sysctl(array('dev.cpu.0.freq')); } if (is_numeric($info)) { $info = $info / 1000; } else { $info = null; } } else { if ($info == null && phodevi::is_windows()) { $info = phodevi_windows_parser::read_cpuz('Processor 1', 'Stock frequency'); if ($info != null) { if (($e = strpos($info, ' MHz')) !== false) { $info = substr($info, 0, $e); } $info = $info / 1000; } } else { if ($info == null) { $info = phodevi::read_sensor(array('cpu', 'freq')); if ($info > 1000) { // Convert from MHz to GHz $info = $info / 1000; } } } } } return pts_math::set_precision($info, 2); }
public function render_graph_dimensions() { $this->i['graph_max_value'] = $this->maximum_graph_value(); $longest_identifier = $this->test_result->test_result_buffer->get_longest_identifier(); // Make room for tick markings, left hand side if ($this->i['iveland_view'] == false) { if ($this->i['graph_value_type'] == 'NUMERICAL') { $this->i['left_start'] += self::text_string_width($this->i['graph_max_value'], self::$c['size']['tick_mark']) + 2; } if ($this->i['hide_graph_identifiers']) { $this->i['graph_top_end'] += $this->i['top_end_bottom'] / 2; } $this->i['top_start'] += $this->graph_key_height(); } else { if ($this->i['graph_orientation'] == 'HORIZONTAL') { if ($this->is_multi_way_comparison && count($this->results) > 1) { $longest_r = $longest_identifier; $longest_r = explode(' - ', $longest_r); $plus_extra = 0; if (count($longest_r) > 1) { $plus_extra = count($longest_r) * $this->i['identifier_size'] * 1.2; } $longest_identifier_width = self::text_string_width($this->i['graph_max_value'], $this->i['identifier_size']) + 60 + $plus_extra; } else { $longest_identifier_width = self::text_string_width($longest_identifier, $this->i['identifier_size']) + 8; } $longest_identifier_max = $this->i['graph_width'] * 0.5 + 0.01; $this->i['left_start'] = min($longest_identifier_max, max($longest_identifier_width, 70)); $this->i['left_end_right'] = 15; $this->i['graph_left_end'] = $this->i['graph_width'] - $this->i['left_end_right']; } else { if ($this->i['graph_value_type'] == 'NUMERICAL') { $this->i['left_start'] += max(20, self::text_string_width($this->i['graph_max_value'] + 0.01, self::$c['size']['tick_mark']) + 2); } } // Pad 8px on top and bottom + title bar + sub-headings $this->i['top_heading_height'] = 16 + self::$c['size']['headers'] + count($this->graph_sub_titles) * (self::$c['size']['sub_headers'] + 4); if ($this->i['iveland_view']) { // Ensure there is enough room to print PTS logo $this->i['top_heading_height'] = max($this->i['top_heading_height'], 46); } $key_height = $this->graph_key_height(); if ($key_height > $this->i['key_line_height']) { // Increase height so key doesn't take up too much room $this->i['graph_height'] += $key_height; $this->i['graph_top_end'] += $key_height; } $this->i['top_start'] = $this->i['top_heading_height'] + $key_height + 16; // + spacing before graph starts $bottom_heading = 14; if ($this->i['graph_orientation'] == 'HORIZONTAL') { if ($this->is_multi_way_comparison && count($this->results) > 1) { $longest_string = explode(' - ', $longest_identifier); $longest_string = pts_strings::find_longest_string($longest_string); $rotated_text = round(self::text_string_width($longest_string, $this->i['identifier_size']) * 0.96); $per_identifier_height = max(14 + 22 * count($this->results), $rotated_text); } else { if (count($this->results) > 3) { $per_identifier_height = count($this->results) * 18; } else { // If there's too much to plot, reduce the size so each graph doesn't take too much room $id_count = count(pts_arrays::first_element($this->results)); if ($id_count < 10) { $per_identifier_height = 46; } else { if ($id_count < 20) { $per_identifier_height = 36; } else { if ($id_count <= 38) { $this->i['compact_result_view'] = true; $per_identifier_height = 30; } else { $this->i['compact_result_view'] = true; $per_identifier_height = 26; } } } } } $num_identifiers = $this->test_result->test_result_buffer->get_count(); $this->i['graph_top_end'] = $this->i['top_start'] + $num_identifiers * $per_identifier_height; // $this->i['top_end_bottom'] $this->i['graph_height'] = $this->i['graph_top_end'] + 25 + $bottom_heading; } else { $this->i['graph_height'] += $bottom_heading + 4; } if (!empty($this->i['notes'])) { $this->i['graph_height'] += $this->note_display_height(); } } }
public function read_sensor() { // Graphics processor real/current frequency $show_memory = false; $core_freq = 0; $mem_freq = 0; if (phodevi::is_nvidia_graphics()) { $nv_freq = phodevi_parser::read_nvidia_extension('GPUCurrentClockFreqs'); $nv_freq = pts_strings::comma_explode($nv_freq); $core_freq = isset($nv_freq[0]) ? $nv_freq[0] : 0; $mem_freq = isset($nv_freq[1]) ? $nv_freq[1] : 0; } else { if (phodevi::is_ati_graphics() && phodevi::is_linux()) { $od_clocks = phodevi_linux_parser::read_ati_overdrive('CurrentClocks'); if (is_array($od_clocks) && count($od_clocks) >= 2) { $core_freq = array_shift($od_clocks); $mem_freq = array_pop($od_clocks); } } else { if (phodevi::is_linux()) { if (isset(phodevi::$vfs->radeon_pm_info)) { // radeon_pm_info should be present with Linux 2.6.34+ foreach (pts_strings::trim_explode("\n", phodevi::$vfs->radeon_pm_info) as $pm_line) { $pm_line = pts_strings::colon_explode($pm_line); if (isset($pm_line[1])) { list($descriptor, $value) = $pm_line; } else { continue; } switch ($descriptor) { case 'current engine clock': $core_freq = pts_arrays::first_element(explode(' ', $value)) / 1000; break; case 'current memory clock': $mem_freq = pts_arrays::first_element(explode(' ', $value)) / 1000; break; } } if ($core_freq == null && ($x = strpos(phodevi::$vfs->radeon_pm_info, 'sclk: '))) { $x = substr(phodevi::$vfs->radeon_pm_info, $x + strlen('sclk: ')); $x = substr($x, 0, strpos($x, ' ')); if (is_numeric($x)) { if ($x > 1000) { $x = $x / 100; } $core_freq = $x; } } if ($mem_freq == null && ($x = strpos(phodevi::$vfs->radeon_pm_info, 'mclk: '))) { $x = substr(phodevi::$vfs->radeon_pm_info, $x + strlen('mclk: ')); $x = substr($x, 0, strpos($x, ' ')); if (is_numeric($x)) { if ($x > 1000) { $x = $x / 100; } $mem_freq = $x; } } } else { if (is_file('/sys/class/drm/card0/gt_cur_freq_mhz')) { $gt_cur_freq_mhz = pts_file_io::file_get_contents('/sys/class/drm/card0/gt_cur_freq_mhz'); if ($gt_cur_freq_mhz > 2) { $core_freq = $gt_cur_freq_mhz; } } else { if (is_file('/sys/class/drm/card0/device/performance_level')) { $performance_level = pts_file_io::file_get_contents('/sys/class/drm/card0/device/performance_level'); $performance_level = explode(' ', $performance_level); $core_string = array_search('core', $performance_level); if ($core_string !== false && isset($performance_level[$core_string + 1])) { $core_string = str_ireplace('MHz', null, $performance_level[$core_string + 1]); if (is_numeric($core_string) && $core_string > $core_freq) { $core_freq = $core_string; } } $mem_string = array_search('memory', $performance_level); if ($mem_string !== false && isset($performance_level[$mem_string + 1])) { $mem_string = str_ireplace('MHz', null, $performance_level[$mem_string + 1]); if (is_numeric($mem_string) && $mem_string > $mem_freq) { $mem_freq = $mem_string; } } } else { if (isset(phodevi::$vfs->i915_cur_delayinfo)) { $i915_cur_delayinfo = phodevi::$vfs->i915_cur_delayinfo; $cagf = strpos($i915_cur_delayinfo, 'CAGF: '); if ($cagf !== false) { $cagf_mhz = substr($i915_cur_delayinfo, $cagf + 6); $cagf_mhz = substr($cagf_mhz, 0, strpos($cagf_mhz, 'MHz')); if (is_numeric($cagf_mhz)) { $core_freq = $cagf_mhz; } } } } } } } } } if (!is_numeric($core_freq)) { $core_freq = 0; } if (!is_numeric($mem_freq)) { $mem_freq = 0; } if ($core_freq == 0 && $mem_freq == 0) { $show_memory = false; $core_freq = -1; } return $show_memory ? array($core_freq, $mem_freq) : $core_freq; }
public static function gpu_stock_frequency() { // Graphics processor stock frequency $core_freq = 0; $mem_freq = 0; if (phodevi::is_nvidia_graphics() && phodevi::is_macosx() == false) { // GPUDefault3DClockFreqs is the default and does not show under/over-clocking $clock_freqs_3d = pts_strings::comma_explode(phodevi_parser::read_nvidia_extension('GPU3DClockFreqs')); $clock_freqs_current = pts_strings::comma_explode(phodevi_parser::read_nvidia_extension('GPUCurrentClockFreqs')); if (is_array($clock_freqs_3d) && isset($clock_freqs_3d[1])) { list($core_freq, $mem_freq) = $clock_freqs_3d; } if (is_array($clock_freqs_current) && isset($clock_freqs_current[1])) { $core_freq = max($core_freq, $clock_freqs_current[0]); $mem_freq = max($mem_freq, $clock_freqs_current[1]); } } else { if (phodevi::is_ati_graphics() && phodevi::is_linux()) { $od_clocks = phodevi_linux_parser::read_ati_overdrive('CurrentPeak'); if (is_array($od_clocks) && count($od_clocks) >= 2) { list($core_freq, $mem_freq) = $od_clocks; } } else { if (phodevi::is_linux()) { $display_driver = phodevi::read_property('system', 'display-driver'); switch ($display_driver) { case '': case 'nouveau': if (is_file('/sys/class/drm/card0/device/performance_level')) { /* EXAMPLE OUTPUTS: memory 1000MHz core 500MHz voltage 1300mV fanspeed 100% 3: memory 333MHz core 500MHz shader 1250MHz fanspeed 100% c: memory 333MHz core 500MHz shader 1250MHz */ $performance_level = pts_file_io::file_get_contents('/sys/class/drm/card0/device/performance_level'); $performance_level = explode(' ', $performance_level); $core_string = array_search('core', $performance_level); if ($core_string !== false && isset($performance_level[$core_string + 1])) { $core_string = str_ireplace('MHz', null, $performance_level[$core_string + 1]); if (is_numeric($core_string)) { $core_freq = $core_string; } } $mem_string = array_search('memory', $performance_level); if ($mem_string !== false && isset($performance_level[$mem_string + 1])) { $mem_string = str_ireplace('MHz', null, $performance_level[$mem_string + 1]); if (is_numeric($mem_string)) { $mem_freq = $mem_string; } } } else { if (is_file('/sys/class/drm/card0/device/pstate')) { // pstate is present with Linux 3.13 as the new performance states on Fermi/Kepler $performance_state = pts_file_io::file_get_contents('/sys/class/drm/card0/device/pstate'); $performance_level = substr($performance_state, 0, strpos($performance_state, ' *')); if ($performance_level == null) { // Method for Linux 3.17+ $performance_level = substr($performance_state, strpos($performance_state, 'AC: ') + 4); if ($t = strpos($performance_level, PHP_EOL)) { $performance_level = substr($performance_level, 0, $t); } } else { // Method for Linux ~3.13 through Linux 3.16 $performance_level = substr($performance_level, strrpos($performance_level, ': ') + 2); } $performance_level = explode(' ', $performance_level); $core_string = array_search('core', $performance_level); if ($core_string !== false && isset($performance_level[$core_string + 1])) { $core_string = str_ireplace('MHz', null, $performance_level[$core_string + 1]); if (strpos($core_string, '-') !== false) { // to work around a range of values, e.g. // 0a: core 405-1032 MHz memory 1620 MHz AC DC * $core_string = max(explode('-', $core_string)); } if (is_numeric($core_string)) { $core_freq = $core_string; } } $mem_string = array_search('memory', $performance_level); if ($mem_string !== false && isset($performance_level[$mem_string + 1])) { $mem_string = str_ireplace('MHz', null, $performance_level[$mem_string + 1]); if (strpos($mem_string, '-') !== false) { // to work around a range of values, e.g. // 0a: core 405-1032 MHz memory 1620 MHz AC DC * $mem_string = max(explode('-', $mem_string)); } if (is_numeric($mem_string)) { $mem_freq = $mem_string; } } } } if ($display_driver != null) { break; } case 'radeon': if (isset(phodevi::$vfs->radeon_pm_info)) { // radeon_pm_info should be present with Linux 2.6.34+ but was changed with Linux 3.11 Radeon DPM if (stripos(phodevi::$vfs->radeon_pm_info, 'default')) { foreach (pts_strings::trim_explode("\n", phodevi::$vfs->radeon_pm_info) as $pm_line) { if ($pm_line == null) { continue; } list($descriptor, $value) = pts_strings::colon_explode($pm_line); switch ($descriptor) { case 'default engine clock': $core_freq = pts_arrays::first_element(explode(' ', $value)) / 1000; break; case 'default memory clock': $mem_freq = pts_arrays::first_element(explode(' ', $value)) / 1000; break; } } } if ($core_freq == 0 && ($x = stripos(phodevi::$vfs->radeon_pm_info, 'sclk: ')) != false) { $x = substr(phodevi::$vfs->radeon_pm_info, $x + strlen('sclk: ')); $x = substr($x, 0, strpos($x, ' ')); if (is_numeric($x) && $x > 100) { if ($x > 10000) { $x = $x / 100; } $core_freq = $x; } if (($x = stripos(phodevi::$vfs->radeon_pm_info, 'mclk: ')) != false) { $x = substr(phodevi::$vfs->radeon_pm_info, $x + strlen('mclk: ')); $x = substr($x, 0, strpos($x, ' ')); if (is_numeric($x) && $x > 100) { if ($x > 10000) { $x = $x / 100; } $mem_freq = $x; } } } } if ($core_freq == null) { // Attempt to read the LAST power level reported to dmesg, this is the current way for Radeon DPM on Linux 3.11+ $dmesg_parse = isset(phodevi::$vfs->dmesg) ? phodevi::$vfs->dmesg : null; if ($x = strrpos($dmesg_parse, ' sclk:')) { $dmesg_parse = substr($dmesg_parse, $x); $dmesg_parse = explode(' ', substr($dmesg_parse, 0, strpos($dmesg_parse, PHP_EOL))); $sclk = array_search('sclk:', $dmesg_parse); if ($sclk !== false && isset($dmesg_parse[$sclk + 1]) && is_numeric($dmesg_parse[$sclk + 1])) { $sclk = $dmesg_parse[$sclk + 1]; if ($sclk > 10000) { $sclk = $sclk / 100; } $core_freq = $sclk; } $mclk = array_search('mclk:', $dmesg_parse); if ($mclk !== false && isset($dmesg_parse[$mclk + 1]) && is_numeric($dmesg_parse[$mclk + 1])) { $mclk = $dmesg_parse[$mclk + 1]; if ($mclk > 10000) { $mclk = $mclk / 100; } $mem_freq = $mclk; } } } if ($core_freq == null) { // Old ugly way of handling the clock information $log_parse = isset(phodevi::$vfs->xorg_log) ? phodevi::$vfs->xorg_log : null; if ($engine_clock = strpos($log_parse, 'Default Engine Clock: ')) { $core_freq = substr($log_parse, $engine_clock + 22); $core_freq = substr($core_freq, 0, strpos($core_freq, "\n")); $core_freq = is_numeric($core_freq) ? $core_freq / 1000 : 0; if ($core_freq && ($mem_clock = strpos($log_parse, 'Default Memory Clock: '))) { $mem_freq = substr($log_parse, $mem_clock + 22); $mem_freq = substr($mem_freq, 0, strpos($mem_freq, "\n")); $mem_freq = is_numeric($mem_freq) ? $mem_freq / 1000 : 0; } else { $core_freq = 0; } } } if ($display_driver != null) { break; } case 'intel': // try to read the maximum dynamic frequency if (is_file('/sys/class/drm/card0/gt_max_freq_mhz')) { $gt_max_freq_mhz = pts_file_io::file_get_contents('/sys/class/drm/card0/gt_max_freq_mhz'); if (is_numeric($gt_max_freq_mhz) && $gt_max_freq_mhz > 100) { // Tested on Linux 3.11. Assume the max frequency on any competent GPU is beyond 100MHz $core_freq = $gt_max_freq_mhz; } } if ($core_freq == 0 && is_file('/sys/kernel/debug/dri/0/i915_max_freq')) { $i915_max_freq = pts_file_io::file_get_contents('/sys/kernel/debug/dri/0/i915_max_freq'); $freq_mhz = substr($i915_max_freq, strpos($i915_max_freq, ': ') + 2); if (is_numeric($freq_mhz)) { $core_freq = $freq_mhz; } } // Fallback to base frequency if ($core_freq == 0 && isset(phodevi::$vfs->i915_cur_delayinfo)) { $i915_cur_delayinfo = phodevi::$vfs->i915_cur_delayinfo; $freq = strpos($i915_cur_delayinfo, 'Max overclocked frequency: '); if ($freq === false) { $freq = strpos($i915_cur_delayinfo, 'Max non-overclocked (RP0) frequency: '); } if ($freq === false) { $freq = strpos($i915_cur_delayinfo, 'Nominal (RP1) frequency: '); } if ($freq !== false) { $freq_mhz = substr($i915_cur_delayinfo, strpos($i915_cur_delayinfo, ': ', $freq) + 2); $freq_mhz = trim(substr($freq_mhz, 0, strpos($freq_mhz, 'MHz'))); if (is_numeric($freq_mhz)) { $core_freq = $freq_mhz; } } } if ($display_driver != null) { break; } } } } } $core_freq = !is_numeric($core_freq) ? 0 : round($core_freq); $mem_freq = !is_numeric($mem_freq) ? 0 : round($mem_freq); return array($core_freq, $mem_freq); }
public static function memory_string() { $mem_string = null; $mem_prefix = null; $mem_size = false; $mem_speed = false; $mem_type = false; $mem_manufacturer = false; $mem_part = false; if (phodevi::is_macosx()) { $mem_size = phodevi_osx_parser::read_osx_system_profiler('SPMemoryDataType', 'Size', true, array('Empty')); $mem_speed = phodevi_osx_parser::read_osx_system_profiler('SPMemoryDataType', 'Speed'); $mem_type = phodevi_osx_parser::read_osx_system_profiler('SPMemoryDataType', 'Type'); } else { if (phodevi::is_solaris()) { $mem_size = phodevi_solaris_parser::read_sun_ddu_dmi_info('MemoryDevice*,InstalledSize'); $mem_speed = phodevi_solaris_parser::read_sun_ddu_dmi_info('MemoryDevice*,Speed'); $mem_type = phodevi_solaris_parser::read_sun_ddu_dmi_info('MemoryDevice*,MemoryDeviceType'); if (is_array($mem_speed) && count($mem_speed) > 0) { $mem_speed = array_shift($mem_speed); } $mem_speed = str_replace('MHZ', 'MHz', $mem_speed); } else { if (phodevi::is_windows()) { $mem_size = phodevi_windows_parser::read_cpuz('DIMM #', 'Size', true); foreach ($mem_size as $key => &$individual_size) { $individual_size = pts_arrays::first_element(explode(' ', $individual_size)); if (!is_numeric($individual_size)) { unset($mem_size[$key]); } } $mem_type = phodevi_windows_parser::read_cpuz('Memory Type', null); $mem_speed = intval(phodevi_windows_parser::read_cpuz('Memory Frequency', null)) . 'MHz'; } else { if (phodevi::is_linux()) { $mem_size = phodevi_linux_parser::read_dmidecode('memory', 'Memory Device', 'Size', false, array('Not Installed', 'No Module Installed', 'Undefined')); $mem_speed = phodevi_linux_parser::read_dmidecode('memory', 'Memory Device', 'Speed', true, array('Unknown', 'Undefined')); $mem_type = phodevi_linux_parser::read_dmidecode('memory', 'Memory Device', 'Type', true, array('Unknown', 'Other', 'Flash', 'Undefined')); $mem_manufacturer = phodevi_linux_parser::read_dmidecode('memory', 'Memory Device', 'Manufacturer', true, array('Unknown', 'Undefined')); $mem_part = phodevi_linux_parser::read_dmidecode('memory', 'Memory Device', 'Part Number', true, array('Unknown', 'Undefined')); } } } } if (is_array($mem_type)) { $mem_type = array_pop($mem_type); } if ($mem_size != false && (!is_array($mem_size) || count($mem_size) != 0)) { for ($i = 0; $i < count($mem_size); $i++) { switch (substr($mem_size[$i], -1)) { case 'K': // looks like sometimes Solaris now reports flash chip as memory. its string ends with K unset($mem_size[$i]); unset($mem_speed[$i]); unset($mem_type[$i]); break; case 'M': // report megabytes as MB, just not M, as on Solaris $mem_size[$i] .= 'B'; break; case 'B': if (strtolower(substr($mem_size[$i], -2, 1)) == 'k') { // some hardware on Linux via dmidecode reports flash chips unset($mem_size[$i]); //unset($mem_speed[$i]); //unset($mem_type[$i]); } break; } } foreach ($mem_size as $i => $mem_stick) { if (!is_numeric(substr($mem_stick, 0, 3)) && stripos($mem_stick, 'GB') == false) { // If the memory size isn't at least three digits (basically 128MB+), chances are something is wrong, i.e. reporting flash chip from dmidecode, so get rid of it. unset($mem_size[$i]); } } $mem_count = count($mem_size); if (!empty($mem_type)) { if (($cut = strpos($mem_type, ' ')) > 0) { $mem_type = substr($mem_type, 0, $cut); } if (!in_array($mem_type, array('Other')) && (pts_strings::keep_in_string($mem_type, pts_strings::CHAR_NUMERIC | pts_strings::CHAR_LETTER) == $mem_type || phodevi::is_windows())) { $mem_prefix = $mem_type; } } else { $mem_prefix = null; } if (!empty($mem_speed)) { if (($cut = strpos($mem_speed, ' (')) > 0) { $mem_speed = substr($mem_speed, 0, $cut); } if (!empty($mem_prefix)) { $mem_prefix .= '-'; } $mem_prefix .= str_replace(' ', null, $mem_speed); } // TODO: Allow a combination of both functions below, so like 2 x 2GB + 3 x 1GB DDR2-800 if ($mem_count > 1 && count(array_unique($mem_size)) > 1) { $mem_string = implode(' + ', $mem_size) . ' ' . $mem_prefix; } else { if ($mem_count * $mem_size[0] != phodevi::read_property('memory', 'capacity') && phodevi::read_property('memory', 'capacity') % $mem_size[0] == 0) { // This makes sure the correct number of RAM modules is reported... // On at least Linux with dmidecode on an AMD Opteron multi-socket setup it's only showing the data for one socket if ($mem_size[0] < 1024) { $mem_size[0] *= 1024; } $mem_count = phodevi::read_property('memory', 'capacity') / $mem_size[0]; } $product_string = null; if (isset($mem_manufacturer[2]) && ctype_alpha($mem_manufacturer[0]) && stripos($mem_manufacturer, 'manufacturer') === false && stripos($mem_manufacturer, 'part') === false && stripos($mem_manufacturer, 'module') === false && stripos($mem_manufacturer, 'dimm') === false && isset($mem_manufacturer[2]) && ctype_alpha($mem_manufacturer)) { $product_string .= ' ' . $mem_manufacturer; } if (isset($mem_part[2]) && stripos($mem_part, 'part') === false && stripos($mem_part, 'module') === false && stripos($mem_part, 'dimm') === false && substr($mem_part, 0, 2) != '0x' && !isset($mem_part[24]) && ctype_alnum($mem_part)) { $product_string .= ' ' . $mem_part; } if (is_numeric($mem_size[0]) && stripos($mem_size[0], 'b') === false) { if ($mem_size >= 1024) { $mem_size[0] .= ' MB'; } else { $mem_size[0] .= ' GB'; } } $mem_string = $mem_count . ' x ' . $mem_size[0] . ' ' . $mem_prefix . $product_string; } } if (empty($mem_string)) { $mem_string = phodevi::read_property('memory', 'capacity'); if ($mem_string != null) { $mem_string .= 'MB'; } } return trim($mem_string); }
public static function mem_usage($TYPE = 'TOTAL', $READ = 'USED') { // Reads system memory usage $mem_usage = -1; if (pts_client::executable_in_path('free') != false) { $mem = explode("\n", shell_exec('free -t -m 2>&1')); $grab_line = null; $buffers_and_cache = 0; for ($i = 0; $i < count($mem); $i++) { $line_parts = pts_strings::colon_explode($mem[$i]); if (count($line_parts) == 2) { $line_type = $line_parts[0]; if ($TYPE == 'MEMORY' && $line_type == 'Mem') { $grab_line = $line_parts[1]; } else { if ($TYPE == 'SWAP' && $line_type == 'Swap') { $grab_line = $line_parts[1]; } else { if ($TYPE == 'TOTAL' && $line_type == 'Total') { $grab_line = $line_parts[1]; } else { if ($line_type == '-/+ buffers/cache' && $TYPE != 'SWAP') { $buffers_and_cache = pts_arrays::first_element(explode(' ', pts_strings::trim_spaces($line_parts[1]))); } } } } } } if (!empty($grab_line)) { $grab_line = pts_strings::trim_spaces($grab_line); $mem_parts = explode(' ', $grab_line); if ($READ == 'USED') { if (count($mem_parts) >= 2 && is_numeric($mem_parts[1])) { $mem_usage = $mem_parts[1] - $buffers_and_cache; } } else { if ($READ == 'TOTAL') { if (count($mem_parts) >= 1 && is_numeric($mem_parts[0])) { $mem_usage = $mem_parts[0]; } } else { if ($READ == 'FREE') { if (count($mem_parts) >= 3 && is_numeric($mem_parts[2])) { $mem_usage = $mem_parts[2]; } } } } } } else { if (pts_client::executable_in_path('vm_stat') != false) { $vmstats = explode("\n", shell_exec('vm_stat 2>&1')); $grab_line = null; // buffers_and_cache foreach ($vmstats as $vmstat_line) { $line_parts = pts_strings::colon_explode($vmstat_line); if (self::$page_size == -1) { strtok($vmstat_line, ':'); $tok = strtok(' '); while (self::$page_size == -1) { if (is_numeric($tok)) { self::$page_size = $tok; } else { $tok = strtok(' '); } } continue; } //$line_parts[1] = pts_strings::trim_spaces($line_parts[1]); $line_type = strtok($vmstat_line, ':'); $line_value = strtok(' .'); if ($TYPE == 'MEMORY') { if ($line_type == 'Pages active' && $READ == 'USED') { $mem_usage = $line_value / (1048576 / self::$page_size); break; } if ($line_type == 'Pages free' && $READ == 'FREE') { $mem_usage = $line_value / (1048576 / self::$page_size); break; } } } $mem_usage = pts_math::set_precision($mem_usage); } } return $mem_usage; }