diff options
author | robertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-03 19:34:38 +0000 |
---|---|---|
committer | robertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-03 19:34:38 +0000 |
commit | 63840115077d79cfbb6df87312694b7118647a67 (patch) | |
tree | 0594bfe82fbb38f102ae5b8285d280fd588cf11e | |
parent | 5e866d5b45c3fd9982815e416af6b7337d40b978 (diff) | |
download | chromium_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.cc | 5 | ||||
-rw-r--r-- | chrome/browser/fragmentation_checker_unittest_win.cc | 24 | ||||
-rw-r--r-- | chrome/browser/fragmentation_checker_win.cc | 111 | ||||
-rw-r--r-- | chrome/browser/fragmentation_checker_win.h | 28 | ||||
-rw-r--r-- | chrome/chrome_browser.gypi | 2 | ||||
-rw-r--r-- | chrome/chrome_tests.gypi | 1 |
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', |