summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/sys_info.h4
-rw-r--r--base/sys_info_posix.cc4
-rw-r--r--base/sys_info_unittest.cc7
-rw-r--r--base/sys_info_win.cc53
-rw-r--r--chrome/browser/metrics/chrome_metrics_service_client.cc20
-rw-r--r--chrome/browser/metrics/chrome_metrics_service_client.h5
-rw-r--r--chrome/browser/metrics/drive_metrics_provider.cc79
-rw-r--r--chrome/browser/metrics/drive_metrics_provider.h74
-rw-r--r--chrome/chrome_browser.gypi2
-rw-r--r--components/metrics/proto/system_profile.proto14
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;