summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrobertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-03 19:34:38 +0000
committerrobertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-03 19:34:38 +0000
commit63840115077d79cfbb6df87312694b7118647a67 (patch)
tree0594bfe82fbb38f102ae5b8285d280fd588cf11e
parent5e866d5b45c3fd9982815e416af6b7337d40b978 (diff)
downloadchromium_src-63840115077d79cfbb6df87312694b7118647a67.zip
chromium_src-63840115077d79cfbb6df87312694b7118647a67.tar.gz
chromium_src-63840115077d79cfbb6df87312694b7118647a67.tar.bz2
Add a metric to Chrome to measure fragmentation of chrome.dll at startup.
BUG=98033 TEST=None Review URL: http://codereview.chromium.org/8085026 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@103760 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/chrome_browser_main.cc5
-rw-r--r--chrome/browser/fragmentation_checker_unittest_win.cc24
-rw-r--r--chrome/browser/fragmentation_checker_win.cc111
-rw-r--r--chrome/browser/fragmentation_checker_win.h28
-rw-r--r--chrome/chrome_browser.gypi2
-rw-r--r--chrome/chrome_tests.gypi1
6 files changed, 171 insertions, 0 deletions
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index 7c3f5d4..db563bc 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -160,6 +160,7 @@
#include "chrome/browser/browser_util_win.h"
#include "chrome/browser/first_run/try_chrome_dialog_view.h"
#include "chrome/browser/first_run/upgrade_util_win.h"
+#include "chrome/browser/fragmentation_checker_win.h"
#include "chrome/browser/net/url_fixer_upper.h"
#include "chrome/browser/rlz/rlz.h"
#include "chrome/browser/ui/views/user_data_dir_dialog.h"
@@ -1785,6 +1786,10 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunInternal() {
LanguageUsageMetrics::RecordApplicationLanguage(
g_browser_process->GetApplicationLocale());
+#if defined(OS_WIN)
+ fragmentation_checker::RecordFragmentationMetricForCurrentModule();
+#endif
+
#if defined(OS_CHROMEOS)
metrics->StartExternalMetrics();
diff --git a/chrome/browser/fragmentation_checker_unittest_win.cc b/chrome/browser/fragmentation_checker_unittest_win.cc
new file mode 100644
index 0000000..c778d76
--- /dev/null
+++ b/chrome/browser/fragmentation_checker_unittest_win.cc
@@ -0,0 +1,24 @@
+// Copyright (c) 2011 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 "base/file_path.h"
+#include "base/path_service.h"
+#include "chrome/browser/fragmentation_checker_win.h"
+#include "chrome/common/guid.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+TEST(FragmentationChecker, BasicCheck) {
+ FilePath module_path;
+ ASSERT_TRUE(PathService::Get(base::FILE_MODULE, &module_path));
+ int extent_count = fragmentation_checker::CountFileExtents(module_path);
+ EXPECT_GT(extent_count, 0);
+}
+
+TEST(FragmentationChecker, InvalidFile) {
+ FilePath module_path;
+ ASSERT_TRUE(PathService::Get(base::FILE_MODULE, &module_path));
+ module_path = module_path.DirName().AppendASCII(guid::GenerateGUID());
+ int extent_count = fragmentation_checker::CountFileExtents(module_path);
+ EXPECT_EQ(extent_count, 0);
+}
diff --git a/chrome/browser/fragmentation_checker_win.cc b/chrome/browser/fragmentation_checker_win.cc
new file mode 100644
index 0000000..ef91717
--- /dev/null
+++ b/chrome/browser/fragmentation_checker_win.cc
@@ -0,0 +1,111 @@
+// Copyright (c) 2011 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/fragmentation_checker_win.h"
+
+#include <windows.h>
+#include <winioctl.h>
+
+#include <vector>
+
+#include "base/file_path.h"
+#include "base/logging.h"
+#include "base/metrics/histogram.h"
+#include "base/platform_file.h"
+#include "base/path_service.h"
+
+namespace {
+
+size_t ComputeRetrievalPointersBufferSize(int number_of_extents) {
+ RETRIEVAL_POINTERS_BUFFER buffer;
+ return sizeof(buffer) + (number_of_extents - 1) * sizeof(buffer.Extents);
+}
+
+} // namespace
+
+namespace fragmentation_checker {
+
+int CountFileExtents(const FilePath& file_path) {
+ int file_extents_count = 0;
+
+ base::PlatformFileError error_code = base::PLATFORM_FILE_ERROR_FAILED;
+ base::PlatformFile file_handle = CreatePlatformFile(
+ file_path,
+ base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ,
+ NULL,
+ &error_code);
+ if (error_code == base::PLATFORM_FILE_OK) {
+ STARTING_VCN_INPUT_BUFFER starting_vcn_input_buffer = {0};
+
+ // Compute an output size capable of holding 16 extents at first. This will
+ // fail when the number of extents exceeds 16, in which case we make
+ // a bigger buffer capable of holding up to kMaxExtentCounts.
+ int extents_guess = 16;
+ size_t output_size = ComputeRetrievalPointersBufferSize(extents_guess);
+ std::vector<uint8> retrieval_pointers_buffer(output_size);
+
+ DWORD bytes_returned = 0;
+
+ bool result = false;
+ do {
+ result = DeviceIoControl(
+ file_handle,
+ FSCTL_GET_RETRIEVAL_POINTERS,
+ reinterpret_cast<void*>(&starting_vcn_input_buffer),
+ sizeof(starting_vcn_input_buffer),
+ reinterpret_cast<void*>(&retrieval_pointers_buffer[0]),
+ retrieval_pointers_buffer.size(),
+ &bytes_returned,
+ NULL) != FALSE;
+
+ if (!result) {
+ if (GetLastError() == ERROR_MORE_DATA) {
+ // Grow the extents we can handle
+ extents_guess *= 2;
+ if (extents_guess > kMaxExtentCount) {
+ LOG(ERROR) << "FSCTL_GET_RETRIEVAL_POINTERS output buffer exceeded "
+ "maximum size.";
+ file_extents_count = kMaxExtentCount;
+ break;
+ }
+ output_size = ComputeRetrievalPointersBufferSize(extents_guess);
+ retrieval_pointers_buffer.assign(output_size, 0);
+ } else {
+ PLOG(ERROR) << "FSCTL_GET_RETRIEVAL_POINTERS failed.";
+ break;
+ }
+ }
+ } while (!result);
+
+ if (result) {
+ RETRIEVAL_POINTERS_BUFFER* retrieval_pointers =
+ reinterpret_cast<RETRIEVAL_POINTERS_BUFFER*>(
+ &retrieval_pointers_buffer[0]);
+ file_extents_count = static_cast<int>(retrieval_pointers->ExtentCount);
+ } else {
+ LOG(ERROR) << "Failed to retrieve extents.";
+ }
+ } else {
+ LOG(ERROR) << "Failed to open module file to check extents. Error code = "
+ << error_code;
+ }
+
+ return file_extents_count;
+}
+
+void RecordFragmentationMetricForCurrentModule() {
+ FilePath module_path;
+ if (PathService::Get(base::FILE_MODULE, &module_path)) {
+ int file_extent_count = CountFileExtents(module_path);
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Fragmentation.ModuleExtents",
+ file_extent_count,
+ 0,
+ kMaxExtentCount,
+ 50);
+ } else {
+ NOTREACHED() << "Could not get path to current module.";
+ }
+}
+
+} // namespace fragmentation_checker
diff --git a/chrome/browser/fragmentation_checker_win.h b/chrome/browser/fragmentation_checker_win.h
new file mode 100644
index 0000000..02f4231
--- /dev/null
+++ b/chrome/browser/fragmentation_checker_win.h
@@ -0,0 +1,28 @@
+// Copyright (c) 2011 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_FRAGMENTATION_CHECKER_WIN_H_
+#define CHROME_BROWSER_FRAGMENTATION_CHECKER_WIN_H_
+#pragma once
+
+class FilePath;
+
+namespace fragmentation_checker {
+
+const int kMaxExtentCount = 1 << 16;
+
+// Returns the number of extents for the file at |file_path|. The number is
+// capped at kMaxExtentCount, files with more extents than that will be counted
+// as having kMaxExtentCount extents. On failure, this function returns 0.
+int CountFileExtents(const FilePath& file_path);
+
+// Records fragmentation metrics for the current module. This records the number
+// of fragments the current module is stored in.
+// This will be used to determine whether pursuing more aggressive
+// manual defragmentation is worth the effort.
+void RecordFragmentationMetricForCurrentModule();
+
+} // namespace fragmentation_checker
+
+#endif // CHROME_BROWSER_FRAGMENTATION_CHECKER_WIN_H_
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index b04b297..5c1de2d 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1243,6 +1243,8 @@
'browser/first_run/upgrade_util_mac.cc',
'browser/first_run/upgrade_util_win.cc',
'browser/first_run/upgrade_util_win.h',
+ 'browser/fragmentation_checker_win.cc',
+ 'browser/fragmentation_checker_win.h',
'browser/fullscreen.h',
'browser/fullscreen_aura.cc',
'browser/fullscreen_gtk.cc',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 6a768d1..1fc59e2 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1291,6 +1291,7 @@
'browser/external_protocol/external_protocol_handler_unittest.cc',
'browser/favicon/favicon_handler_unittest.cc',
'browser/first_run/first_run_unittest.cc',
+ 'browser/fragmentation_checker_unittest_win.cc',
'browser/geolocation/chrome_geolocation_permission_context_unittest.cc',
'browser/geolocation/geolocation_settings_state_unittest.cc',
'browser/geolocation/wifi_data_provider_unittest_chromeos.cc',