diff options
-rw-r--r-- | base/sys_info.h | 4 | ||||
-rw-r--r-- | base/sys_info_posix.cc | 4 | ||||
-rw-r--r-- | base/sys_info_unittest.cc | 7 | ||||
-rw-r--r-- | base/sys_info_win.cc | 53 | ||||
-rw-r--r-- | chrome/browser/metrics/chrome_metrics_service_client.cc | 20 | ||||
-rw-r--r-- | chrome/browser/metrics/chrome_metrics_service_client.h | 5 | ||||
-rw-r--r-- | chrome/browser/metrics/drive_metrics_provider.cc | 79 | ||||
-rw-r--r-- | chrome/browser/metrics/drive_metrics_provider.h | 74 | ||||
-rw-r--r-- | chrome/chrome_browser.gypi | 2 | ||||
-rw-r--r-- | components/metrics/proto/system_profile.proto | 14 |
10 files changed, 249 insertions, 13 deletions
diff --git a/base/sys_info.h b/base/sys_info.h index 660343d..d3476d9 100644 --- a/base/sys_info.h +++ b/base/sys_info.h @@ -48,6 +48,10 @@ class BASE_EXPORT SysInfo { // or -1 on failure. static int64 AmountOfFreeDiskSpace(const FilePath& path); + // Determine whether the device that services |path| has a seek penalty. + // Returns false if it couldn't be determined (e.g., |path| doesn't exist). + static bool HasSeekPenalty(const FilePath& path, bool* has_seek_penalty); + // Returns system uptime in milliseconds. static int64 Uptime(); diff --git a/base/sys_info_posix.cc b/base/sys_info_posix.cc index 3d49bf9..cdb95d7 100644 --- a/base/sys_info_posix.cc +++ b/base/sys_info_posix.cc @@ -96,6 +96,10 @@ int64 SysInfo::AmountOfFreeDiskSpace(const FilePath& path) { return static_cast<int64>(stats.f_bavail) * stats.f_frsize; } +bool SysInfo::HasSeekPenalty(const FilePath& path, bool* has_seek_penalty) { + return false; +} + #if !defined(OS_MACOSX) && !defined(OS_ANDROID) // static std::string SysInfo::OperatingSystemName() { diff --git a/base/sys_info_unittest.cc b/base/sys_info_unittest.cc index 15ae098..da47861 100644 --- a/base/sys_info_unittest.cc +++ b/base/sys_info_unittest.cc @@ -41,6 +41,13 @@ TEST_F(SysInfoTest, AmountOfFreeDiskSpace) { << tmp_path.value(); } +TEST_F(SysInfoTest, HasSeekPenalty) { + FilePath tmp_path; + ASSERT_TRUE(base::GetTempDir(&tmp_path)); + bool unused; + base::SysInfo::HasSeekPenalty(tmp_path, &unused); +} + #if defined(OS_WIN) || defined(OS_MACOSX) TEST_F(SysInfoTest, OperatingSystemVersionNumbers) { int32 os_major_version = -1; diff --git a/base/sys_info_win.cc b/base/sys_info_win.cc index 9cc0cfa..7c12524 100644 --- a/base/sys_info_win.cc +++ b/base/sys_info_win.cc @@ -5,7 +5,9 @@ #include "base/sys_info.h" #include <windows.h> +#include <winioctl.h> +#include "base/files/file.h" #include "base/files/file_path.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" @@ -24,9 +26,7 @@ int64 AmountOfMemory(DWORDLONG MEMORYSTATUSEX::* memory_field) { } int64 rv = static_cast<int64>(memory_info.*memory_field); - if (rv < 0) - rv = kint64max; - return rv; + return rv < 0 ? kint64max : rv; } } // namespace @@ -55,16 +55,51 @@ int64 SysInfo::AmountOfVirtualMemory() { // static int64 SysInfo::AmountOfFreeDiskSpace(const FilePath& path) { - base::ThreadRestrictions::AssertIOAllowed(); + ThreadRestrictions::AssertIOAllowed(); ULARGE_INTEGER available, total, free; - if (!GetDiskFreeSpaceExW(path.value().c_str(), &available, &total, &free)) { + if (!GetDiskFreeSpaceExW(path.value().c_str(), &available, &total, &free)) return -1; - } + int64 rv = static_cast<int64>(available.QuadPart); - if (rv < 0) - rv = kint64max; - return rv; + return rv < 0 ? kint64max : rv; +} + +bool SysInfo::HasSeekPenalty(const FilePath& path, bool* has_seek_penalty) { + ThreadRestrictions::AssertIOAllowed(); + + DCHECK(path.IsAbsolute()); + DCHECK(has_seek_penalty); + + // TODO(dbeam): Vista, XP support. + if (win::GetVersion() < win::VERSION_WIN7) + return false; + + std::vector<FilePath::StringType> components; + path.GetComponents(&components); + + File drive(FilePath(L"\\\\.\\" + components[0]), File::FLAG_OPEN); + if (!drive.IsValid()) + return false; + + STORAGE_PROPERTY_QUERY query; + query.QueryType = PropertyStandardQuery; + query.PropertyId = StorageDeviceSeekPenaltyProperty; + + DEVICE_SEEK_PENALTY_DESCRIPTOR result; + DWORD bytes_returned; + + BOOL success = DeviceIoControl(drive.GetPlatformFile(), + IOCTL_STORAGE_QUERY_PROPERTY, + &query, sizeof(query), + &result, sizeof(result), + &bytes_returned, + NULL); + if (success == FALSE || bytes_returned < sizeof(result)) + return false; + + *has_seek_penalty = result.IncursSeekPenalty != FALSE; + return true; } // static diff --git a/chrome/browser/metrics/chrome_metrics_service_client.cc b/chrome/browser/metrics/chrome_metrics_service_client.cc index c68d2bf..6aa71c8 100644 --- a/chrome/browser/metrics/chrome_metrics_service_client.cc +++ b/chrome/browser/metrics/chrome_metrics_service_client.cc @@ -23,6 +23,7 @@ #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/google/google_brand.h" #include "chrome/browser/metrics/chrome_stability_metrics_provider.h" +#include "chrome/browser/metrics/drive_metrics_provider.h" #include "chrome/browser/metrics/omnibox_metrics_provider.h" #include "chrome/browser/ui/browser_otr_state.h" #include "chrome/common/chrome_constants.h" @@ -122,9 +123,17 @@ bool IsCellularEnabledByExperiment() { ChromeMetricsServiceClient::ChromeMetricsServiceClient( metrics::MetricsStateManager* state_manager) : metrics_state_manager_(state_manager), - chromeos_metrics_provider_(NULL), + chromeos_metrics_provider_(nullptr), waiting_for_collect_final_metrics_step_(false), num_async_histogram_fetches_in_progress_(0), + profiler_metrics_provider_(nullptr), +#if defined(ENABLE_PLUGINS) + plugin_metrics_provider_(nullptr), +#endif +#if defined(OS_WIN) + google_update_metrics_provider_(nullptr), +#endif + drive_metrics_provider_(nullptr), weak_ptr_factory_(this) { DCHECK(thread_checker_.CalledOnValidThread()); RecordCommandLineMetrics(); @@ -314,7 +323,11 @@ void ChromeMetricsServiceClient::Initialize() { metrics_service_->RegisterMetricsProvider( scoped_ptr<metrics::MetricsProvider>(new ChromeStabilityMetricsProvider)); metrics_service_->RegisterMetricsProvider( - scoped_ptr<metrics::MetricsProvider>(new metrics::GPUMetricsProvider())); + scoped_ptr<metrics::MetricsProvider>(new metrics::GPUMetricsProvider)); + + drive_metrics_provider_ = new DriveMetricsProvider; + metrics_service_->RegisterMetricsProvider( + scoped_ptr<metrics::MetricsProvider>(drive_metrics_provider_)); profiler_metrics_provider_ = new metrics::ProfilerMetricsProvider(cellular_callback_); @@ -412,7 +425,8 @@ void ChromeMetricsServiceClient::ReceivedProfilerData( } void ChromeMetricsServiceClient::FinishedReceivingProfilerData() { - finished_gathering_initial_metrics_callback_.Run(); + drive_metrics_provider_->GetDriveMetrics( + finished_gathering_initial_metrics_callback_); } void ChromeMetricsServiceClient::OnMemoryDetailCollectionDone() { diff --git a/chrome/browser/metrics/chrome_metrics_service_client.h b/chrome/browser/metrics/chrome_metrics_service_client.h index c2f1c6e..a29d5c6 100644 --- a/chrome/browser/metrics/chrome_metrics_service_client.h +++ b/chrome/browser/metrics/chrome_metrics_service_client.h @@ -20,6 +20,7 @@ #include "content/public/browser/notification_registrar.h" class ChromeOSMetricsProvider; +class DriveMetricsProvider; class GoogleUpdateMetricsProviderWin; class PluginMetricsProvider; class PrefRegistrySimple; @@ -165,6 +166,10 @@ class ChromeMetricsServiceClient GoogleUpdateMetricsProviderWin* google_update_metrics_provider_; #endif + // The DriveMetricsProvider instance that was registered with MetricsService. + // Has the same lifetime as |metrics_service_|. + DriveMetricsProvider* drive_metrics_provider_; + // Callback that is called when initial metrics gathering is complete. base::Closure finished_gathering_initial_metrics_callback_; diff --git a/chrome/browser/metrics/drive_metrics_provider.cc b/chrome/browser/metrics/drive_metrics_provider.cc new file mode 100644 index 0000000..f2e2ac5 --- /dev/null +++ b/chrome/browser/metrics/drive_metrics_provider.cc @@ -0,0 +1,79 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/metrics/drive_metrics_provider.h" + +#include "base/base_paths.h" +#include "base/bind.h" +#include "base/files/file_path.h" +#include "base/location.h" +#include "base/logging.h" +#include "base/path_service.h" +#include "base/sys_info.h" +#include "chrome/common/chrome_paths.h" +#include "content/public/browser/browser_thread.h" + +DriveMetricsProvider::DriveMetricsProvider() : weak_ptr_factory_(this) {} + +DriveMetricsProvider::~DriveMetricsProvider() {} + +void DriveMetricsProvider::ProvideSystemProfileMetrics( + metrics::SystemProfileProto* system_profile_proto) { + auto* hardware = system_profile_proto->mutable_hardware(); + FillDriveMetrics(metrics_.app_drive, hardware->mutable_app_drive()); + FillDriveMetrics(metrics_.user_data_drive, + hardware->mutable_user_data_drive()); +} + +void DriveMetricsProvider::GetDriveMetrics(const base::Closure& done) { + got_metrics_callback_ = done; + + content::BrowserThread::PostTaskAndReplyWithResult( + content::BrowserThread::FILE, FROM_HERE, + base::Bind(&DriveMetricsProvider::GetDriveMetricsOnFileThread), + base::Bind(&DriveMetricsProvider::GotDriveMetrics, + weak_ptr_factory_.GetWeakPtr())); +} + +DriveMetricsProvider::SeekPenaltyResponse::SeekPenaltyResponse() + : success(false) {} + +// static +DriveMetricsProvider::DriveMetrics +DriveMetricsProvider::GetDriveMetricsOnFileThread() { + DCHECK_CURRENTLY_ON(content::BrowserThread::FILE); + + DriveMetricsProvider::DriveMetrics metrics; + QuerySeekPenalty(base::FILE_EXE, &metrics.app_drive); + QuerySeekPenalty(chrome::FILE_LOCAL_STATE, &metrics.user_data_drive); + return metrics; +} + +// static +void DriveMetricsProvider::QuerySeekPenalty( + int path_service_key, + DriveMetricsProvider::SeekPenaltyResponse* response) { + DCHECK(response); + + base::FilePath path; + if (!PathService::Get(path_service_key, &path)) + return; + + response->success = + base::SysInfo::HasSeekPenalty(path, &response->has_seek_penalty); +} + +void DriveMetricsProvider::GotDriveMetrics( + const DriveMetricsProvider::DriveMetrics& metrics) { + DCHECK(thread_checker_.CalledOnValidThread()); + metrics_ = metrics; + got_metrics_callback_.Run(); +} + +void DriveMetricsProvider::FillDriveMetrics( + const DriveMetricsProvider::SeekPenaltyResponse& response, + metrics::SystemProfileProto::Hardware::Drive* drive) { + if (response.success) + drive->set_has_seek_penalty(response.has_seek_penalty); +} diff --git a/chrome/browser/metrics/drive_metrics_provider.h b/chrome/browser/metrics/drive_metrics_provider.h new file mode 100644 index 0000000..530c0a4 --- /dev/null +++ b/chrome/browser/metrics/drive_metrics_provider.h @@ -0,0 +1,74 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_METRICS_DRIVE_METRICS_PROVIDER_H_ +#define CHROME_BROWSER_METRICS_DRIVE_METRICS_PROVIDER_H_ + +#include "base/callback.h" +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "base/threading/thread_checker.h" +#include "components/metrics/metrics_provider.h" +#include "components/metrics/proto/system_profile.pb.h" + +// Provides metrics about the local drives on a user's computer. Currently only +// checks to see if they incur a seek-time penalty (e.g. if they're SSDs). +// +// Defers gathering metrics until after "rush hour" (startup) so as to not bog +// down the FILE thread. +class DriveMetricsProvider : public metrics::MetricsProvider { + public: + DriveMetricsProvider(); + ~DriveMetricsProvider() override; + + // metrics::MetricsDataProvider: + void ProvideSystemProfileMetrics( + metrics::SystemProfileProto* system_profile_proto) override; + + // Called by ChromeMetricsServiceClient to start gathering metrics. + void GetDriveMetrics(const base::Closure& done); + + private: + // A response to querying a drive as to whether it incurs a seek penalty. + // |has_seek_penalty| is set if |success| is true. + struct SeekPenaltyResponse { + SeekPenaltyResponse(); + bool success; + bool has_seek_penalty; + }; + + struct DriveMetrics { + SeekPenaltyResponse app_drive; + SeekPenaltyResponse user_data_drive; + }; + + // Gather metrics about various drives on the FILE thread. + static DriveMetrics GetDriveMetricsOnFileThread(); + + // Tries to determine whether there is a penalty for seeking on the drive that + // hosts |path_service_key| (for example: the drive that holds "Local State"). + static void QuerySeekPenalty(int path_service_key, + SeekPenaltyResponse* response); + + // Called when metrics are done being gathered from the FILE thread. + void GotDriveMetrics(const DriveMetrics& metrics); + + // Fills |drive| with information from successful |response|s. + void FillDriveMetrics( + const SeekPenaltyResponse& response, + metrics::SystemProfileProto::Hardware::Drive* drive); + + // Information gathered about various important drives. + DriveMetrics metrics_; + + // Called when metrics are done being collected. + base::Closure got_metrics_callback_; + + base::ThreadChecker thread_checker_; + base::WeakPtrFactory<DriveMetricsProvider> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(DriveMetricsProvider); +}; + +#endif // CHROME_BROWSER_METRICS_DRIVE_METRICS_PROVIDER_H_ diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index e2934c7..5718688 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -1703,6 +1703,8 @@ 'browser/metrics/chrome_metrics_service_client.h', 'browser/metrics/chrome_stability_metrics_provider.cc', 'browser/metrics/chrome_stability_metrics_provider.h', + 'browser/metrics/drive_metrics_provider.cc', + 'browser/metrics/drive_metrics_provider.h', 'browser/metrics/field_trial_synchronizer.cc', 'browser/metrics/field_trial_synchronizer.h', 'browser/metrics/first_web_contents_profiler.cc', diff --git a/components/metrics/proto/system_profile.proto b/components/metrics/proto/system_profile.proto index 4b64675..a9bdc1d 100644 --- a/components/metrics/proto/system_profile.proto +++ b/components/metrics/proto/system_profile.proto @@ -92,7 +92,7 @@ message SystemProfileProto { } optional OS os = 5; - // Next tag for Hardware: 16 + // Next tag for Hardware: 18 // Information on the user's hardware. message Hardware { // The CPU architecture (x86, PowerPC, x86_64, ...) @@ -254,6 +254,18 @@ message SystemProfileProto { // Lists vendor and product ids of external touchscreens. // Logged on ChromeOS only. repeated TouchScreen external_touchscreen = 15; + + // Drive messages are logged on Windows 7+ only for now. + message Drive { + // Whether this drive incurs a time penalty when randomly accessed. This + // should be true for spinning disks but false for SSDs or other + // flash-based drives. + optional bool has_seek_penalty = 1; + } + // The drive that the application executable was loaded from. + optional Drive app_drive = 16; + // The drive that the current user data directory was loaded from. + optional Drive user_data_drive = 17; } optional Hardware hardware = 6; |