diff options
author | dtu@chromium.org <dtu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-16 23:24:15 +0000 |
---|---|---|
committer | dtu@chromium.org <dtu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-16 23:24:15 +0000 |
commit | b882891c004caaf6d50d0217aa690682f4b7ccd1 (patch) | |
tree | 7aac2166bfebb000bdfa2fa68cc4edabfa15168d | |
parent | 78bffa2e0c91305e1b9b89a8d9ba8f2e53cf245e (diff) | |
download | chromium_src-b882891c004caaf6d50d0217aa690682f4b7ccd1.zip chromium_src-b882891c004caaf6d50d0217aa690682f4b7ccd1.tar.gz chromium_src-b882891c004caaf6d50d0217aa690682f4b7ccd1.tar.bz2 |
Retrieve Windows performance assessment information from results files.
Also move libxml_utils from chrome/common/ into base/, because it's now being used to read the results files from content/gpu/
TBR=ben@chromium.org
BUG=chromium:122838,chromium:124325
TEST=Builds on all platforms, and chrome://gpu gives a correct rating after the user re-runs the WinSAT assessment.
Review URL: https://chromiumcodereview.appspot.com/10128002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@137552 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | content/content_gpu.gypi | 1 | ||||
-rw-r--r-- | content/gpu/DEPS | 1 | ||||
-rw-r--r-- | content/gpu/gpu_info_collector_win.cc | 127 |
3 files changed, 91 insertions, 38 deletions
diff --git a/content/content_gpu.gypi b/content/content_gpu.gypi index cda9ae0..b98d991 100644 --- a/content/content_gpu.gypi +++ b/content/content_gpu.gypi @@ -38,6 +38,7 @@ 'dependencies': [ '../third_party/angle/src/build_angle.gyp:libEGL', '../third_party/angle/src/build_angle.gyp:libGLESv2', + '../third_party/libxml/libxml.gyp:libxml', ], 'link_settings': { 'libraries': [ diff --git a/content/gpu/DEPS b/content/gpu/DEPS index 082ffad..46de806 100644 --- a/content/gpu/DEPS +++ b/content/gpu/DEPS @@ -6,4 +6,5 @@ include_rules = [ "+libGLESv2", "+sandbox", "+skia", + "+third_party/libxml", # For parsing WinSAT results files. ] diff --git a/content/gpu/gpu_info_collector_win.cc b/content/gpu/gpu_info_collector_win.cc index d17e0ef..e37d0e9 100644 --- a/content/gpu/gpu_info_collector_win.cc +++ b/content/gpu/gpu_info_collector_win.cc @@ -7,16 +7,18 @@ #include <windows.h> #include <d3d9.h> #include <setupapi.h> -#include <winsatcominterfacei.h> #include "base/command_line.h" #include "base/file_path.h" +#include "base/file_util.h" #include "base/logging.h" +#include "base/metrics/histogram.h" #include "base/scoped_native_library.h" #include "base/string_number_conversions.h" #include "base/string_util.h" #include "base/win/scoped_com_initializer.h" #include "base/win/scoped_comptr.h" +#include "third_party/libxml/chromium/libxml_utils.h" #include "ui/gl/gl_implementation.h" #include "ui/gl/gl_surface_egl.h" @@ -35,66 +37,111 @@ std::string VersionNumberToString(uint32 version_number) { return base::IntToString(hi) + "." + base::IntToString(low); } -float GetAssessmentScore(IProvideWinSATResultsInfo* results, - WINSAT_ASSESSMENT_TYPE type) { - base::win::ScopedComPtr<IProvideWinSATAssessmentInfo> subcomponent; - if (FAILED(results->GetAssessmentInfo(type, subcomponent.Receive()))) +float ReadXMLFloatValue(XmlReader* reader) { + std::string score_string; + if (!reader->ReadElementContent(&score_string)) return 0.0; - float score = 0.0; - if (FAILED(subcomponent->get_Score(&score))) - score = 0.0; - return score; + double score; + if (!base::StringToDouble(score_string, &score)) + return 0.0; + + return static_cast<float>(score); } content::GpuPerformanceStats RetrieveGpuPerformanceStats() { + // If the user re-runs the assessment without restarting, the COM API + // returns WINSAT_ASSESSMENT_STATE_NOT_AVAILABLE. Because of that and + // http://crbug.com/124325, read the assessment result files directly. content::GpuPerformanceStats stats; - base::win::ScopedCOMInitializer com_initializer; - if (!com_initializer.succeeded()) { - LOG(ERROR) << "CoInitializeEx() failed"; + base::TimeTicks start_time = base::TimeTicks::Now(); + + // Get path to WinSAT results files. + wchar_t winsat_results_path[MAX_PATH]; + DWORD size = ExpandEnvironmentStrings( + L"%WinDir%\\Performance\\WinSAT\\DataStore\\", + winsat_results_path, MAX_PATH); + if (size == 0 || size > MAX_PATH) { + LOG(ERROR) << "The path to the WinSAT results is too long: " + << size << " chars."; return stats; } - base::win::ScopedComPtr<IQueryRecentWinSATAssessment> assessment; - HRESULT hr = assessment.CreateInstance(__uuidof(CQueryWinSAT), NULL, - CLSCTX_INPROC_SERVER); - if (FAILED(hr)) { - LOG(ERROR) << "CoCreateInstance() failed"; - return stats; + // Find most recent formal assessment results. + file_util::FileEnumerator file_enumerator( + FilePath(winsat_results_path), + false, // not recursive + file_util::FileEnumerator::FILES, + FILE_PATH_LITERAL("* * Formal.Assessment (*).WinSAT.xml")); + + FilePath current_results; + for (FilePath results = file_enumerator.Next(); !results.empty(); + results = file_enumerator.Next()) { + // The filenames start with the date and time as yyyy-mm-dd hh.mm.ss.xxx, + // so the greatest file lexicographically is also the most recent file. + if (FilePath::CompareLessIgnoreCase(current_results.value(), + results.value())) + current_results = results; } - base::win::ScopedComPtr<IProvideWinSATResultsInfo> results; - hr = assessment->get_Info(results.Receive()); - if (FAILED(hr)) { - LOG(ERROR) << "get_Info() failed"; + std::string current_results_string = current_results.MaybeAsASCII(); + if (current_results_string.empty()) { + LOG(ERROR) << "Can't retrieve a valid WinSAT assessment."; return stats; } - WINSAT_ASSESSMENT_STATE state = WINSAT_ASSESSMENT_STATE_UNKNOWN; - hr = results->get_AssessmentState(&state); - if (FAILED(hr)) { - LOG(ERROR) << "get_AssessmentState() failed"; + // Get relevant scores from results file. XML schema at: + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa969210.aspx + XmlReader reader; + if (!reader.LoadFile(current_results_string)) { + LOG(ERROR) << "Could not open WinSAT results file."; + return stats; + } + // Descend into <WinSAT> root element. + if (!reader.SkipToElement() || !reader.Read()) { + LOG(ERROR) << "Could not read WinSAT results file."; return stats; } - if (state != WINSAT_ASSESSMENT_STATE_VALID && - state != WINSAT_ASSESSMENT_STATE_INCOHERENT_WITH_HARDWARE) { - LOG(ERROR) << "Can't retrieve a valid assessment"; + // Search for <WinSPR> element containing the results. + do { + if (reader.NodeName() == "WinSPR") + break; + } while (reader.Next()); + // Descend into <WinSPR> element. + if (!reader.Read()) { + LOG(ERROR) << "Could not find WinSPR element in results file."; return stats; } - hr = results->get_SystemRating(&stats.overall); - if (FAILED(hr)) - LOG(ERROR) << "Get overall score failed"; + // Read scores. + for (int depth = reader.Depth(); reader.Depth() == depth; reader.Next()) { + std::string node_name = reader.NodeName(); + if (node_name == "SystemScore") + stats.overall = ReadXMLFloatValue(&reader); + else if (node_name == "GraphicsScore") + stats.graphics = ReadXMLFloatValue(&reader); + else if (node_name == "GamingScore") + stats.gaming = ReadXMLFloatValue(&reader); + } - stats.gaming = GetAssessmentScore(results, WINSAT_ASSESSMENT_D3D); + if (stats.overall == 0.0) + LOG(ERROR) << "Could not read overall score from assessment results."; + if (stats.graphics == 0.0) + LOG(ERROR) << "Could not read graphics score from assessment results."; if (stats.gaming == 0.0) - LOG(ERROR) << "Get gaming score failed"; + LOG(ERROR) << "Could not read gaming score from assessment results."; - stats.graphics = GetAssessmentScore(results, WINSAT_ASSESSMENT_GRAPHICS); - if (stats.graphics == 0.0) - LOG(ERROR) << "Get graphics score failed"; + UMA_HISTOGRAM_CUSTOM_COUNTS("GPU.WinSAT.OverallScore", + stats.overall, 0.0, 50.0, 50); + UMA_HISTOGRAM_CUSTOM_COUNTS("GPU.WinSAT.GraphicsScore", + stats.graphics, 0.0, 50.0, 50); + UMA_HISTOGRAM_CUSTOM_COUNTS("GPU.WinSAT.GamingScore", + stats.gaming, 0.0, 50.0, 50); + + UMA_HISTOGRAM_TIMES("GPU.WinSAT.ReadResultsFileTime", + base::TimeTicks::Now() - start_time); return stats; } @@ -106,7 +153,11 @@ namespace gpu_info_collector { bool CollectGraphicsInfo(content::GPUInfo* gpu_info) { DCHECK(gpu_info); - gpu_info->performance_stats = RetrieveGpuPerformanceStats(); + content::GpuPerformanceStats stats = RetrieveGpuPerformanceStats(); + UMA_HISTOGRAM_BOOLEAN( + "GPU.WinSAT.HasResults", + stats.overall != 0.0 && stats.graphics != 0.0 && stats.gaming != 0.0); + gpu_info->performance_stats = stats; if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseGL)) { std::string requested_implementation_name = |