| Index: components/autofill/core/browser/benchmark.cc
|
| diff --git a/components/autofill/core/browser/benchmark.cc b/components/autofill/core/browser/benchmark.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..1582e528dc66c1d96961ada64ee848d5f05f9c53
|
| --- /dev/null
|
| +++ b/components/autofill/core/browser/benchmark.cc
|
| @@ -0,0 +1,170 @@
|
| +// 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.
|
| +
|
| +// This file is not meant to be added to the Chromium source. It is only a
|
| +// benchmark to compare two regexp libraries.
|
| +
|
| +#include <vector>
|
| +
|
| +#include "base/macros.h"
|
| +#include "base/memory/scoped_vector.h"
|
| +#include "base/strings/string16.h"
|
| +#include "base/strings/utf_string_conversions.h"
|
| +#include "base/timer/elapsed_timer.h"
|
| +#include "components/autofill/core/browser/autofill_regex_constants.h"
|
| +#include "components/autofill/core/browser/autofill_regexes.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +#include "third_party/icu/source/i18n/unicode/regex.h"
|
| +#include "third_party/re2/re2/re2.h"
|
| +
|
| +using base::ASCIIToUTF16;
|
| +
|
| +namespace autofill {
|
| +
|
| +namespace {
|
| +
|
| +// Regexp patterns and data to test in the benchmark.
|
| +const char* const kPatterns[] = {kNameOnCardRe, kCityRe, kExpirationDateRe};
|
| +const char* const kData[] = {
|
| + "DER KARTENINHABER, nome del titolare della carta di credito",
|
| + "cidade",
|
| + "city or suburb",
|
| + "gueltig bis",
|
| + "data di scadenza",
|
| + "non-matching snippet 1",
|
| + "longer non-matching snippet abcd@gefh.com 123456789"};
|
| +
|
| +// How many times to repeat each operation (compiling, matching).
|
| +const size_t kRepetitions = 10000u;
|
| +
|
| +void CreatePatternsData(std::vector<base::string16>* patterns,
|
| + std::vector<base::string16>* data) {
|
| + for (size_t i = 0; i < arraysize(kPatterns); ++i) {
|
| + patterns->push_back(ASCIIToUTF16(kPatterns[i]));
|
| + }
|
| +
|
| + for (size_t i = 0; i < arraysize(kData); ++i) {
|
| + data->push_back(ASCIIToUTF16(kData[i]));
|
| + }
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +TEST(Benchmark, ICU_compilation) {
|
| + std::vector<base::string16> patterns;
|
| + std::vector<base::string16> data;
|
| + CreatePatternsData(&patterns, &data);
|
| +
|
| + // Benchmark regex compilation.
|
| + ScopedVector<icu::RegexMatcher> matchers;
|
| + matchers.resize(patterns.size() * kRepetitions);
|
| + size_t matchers_idx = 0;
|
| + base::ElapsedTimer compilation_timer;
|
| + for (const auto& pattern : patterns) {
|
| + for (size_t j = 0; j < kRepetitions; ++j) {
|
| + const icu::UnicodeString icu_pattern(pattern.data(), pattern.length());
|
| + UErrorCode status = U_ZERO_ERROR;
|
| + matchers[matchers_idx] =
|
| + new icu::RegexMatcher(icu_pattern, UREGEX_CASE_INSENSITIVE, status);
|
| + ++matchers_idx;
|
| + }
|
| + }
|
| + base::TimeDelta compilation_elapsed = compilation_timer.Elapsed();
|
| +
|
| + VLOG(0) << "ICU: Compilation of " << patterns.size()
|
| + << " different patterns, repeated " << kRepetitions << " times took "
|
| + << compilation_elapsed.InMicroseconds() << " microseconds.";
|
| +}
|
| +
|
| +TEST(Benchmark, ICU_matching) {
|
| + std::vector<base::string16> patterns;
|
| + std::vector<base::string16> data;
|
| + CreatePatternsData(&patterns, &data);
|
| +
|
| + // Precompile the regexes.
|
| + for (const auto& pattern : patterns) {
|
| + MatchesPattern(base::string16(), pattern);
|
| + }
|
| +
|
| + // Benchmark the matching.
|
| + base::ElapsedTimer matching_timer;
|
| + for (const auto& pattern : patterns) {
|
| + for (const auto& snippet : data) {
|
| + for (size_t j = 0; j < kRepetitions; ++j) {
|
| + MatchesPattern(snippet, pattern);
|
| + }
|
| + }
|
| + }
|
| + base::TimeDelta matching_elapsed = matching_timer.Elapsed();
|
| +
|
| + VLOG(0) << "ICU: Matching of " << data.size() << " different snipets against "
|
| + << patterns.size() << " different patterns, repeated " << kRepetitions
|
| + << " times took " << matching_elapsed.InMicroseconds()
|
| + << " microseconds.";
|
| +}
|
| +
|
| +TEST(Benchmark, RE2_nonprecompiled_matching) {
|
| + // Benchmark the matching.
|
| + base::ElapsedTimer matching_timer;
|
| + for (size_t pat_i = 0; pat_i < arraysize(kPatterns); ++pat_i) {
|
| + for (size_t dat_i = 0; dat_i < arraysize(kData); ++dat_i) {
|
| + for (size_t j = 0; j < kRepetitions; ++j) {
|
| + RE2::FullMatch(kData[dat_i], kPatterns[pat_i]);
|
| + }
|
| + }
|
| + }
|
| + base::TimeDelta matching_elapsed = matching_timer.Elapsed();
|
| +
|
| + VLOG(0) << "RE2, no compilation: Matching of " << arraysize(kData)
|
| + << " different snipets against " << arraysize(kPatterns)
|
| + << " different patterns, repeated " << kRepetitions << " times took "
|
| + << matching_elapsed.InMicroseconds() << " microseconds.";
|
| +}
|
| +
|
| +TEST(Benchmark, RE2_precompiled_matching) {
|
| + ScopedVector<RE2> matchers;
|
| +
|
| + // Precompile the regexes.
|
| + for (size_t pat_i = 0; pat_i < arraysize(kPatterns); ++pat_i) {
|
| + matchers.push_back(new RE2(kPatterns[pat_i]));
|
| + }
|
| +
|
| + // Benchmark the matching.
|
| + base::ElapsedTimer matching_timer;
|
| + for (size_t pat_i = 0; pat_i < arraysize(kPatterns); ++pat_i) {
|
| + const RE2& matcher(*(matchers[pat_i]));
|
| + for (size_t dat_i = 0; dat_i < arraysize(kData); ++dat_i) {
|
| + for (size_t j = 0; j < kRepetitions; ++j) {
|
| + RE2::FullMatch(kData[dat_i], matcher);
|
| + }
|
| + }
|
| + }
|
| + base::TimeDelta matching_elapsed = matching_timer.Elapsed();
|
| +
|
| + VLOG(0) << "RE2, compilation: Matching of " << arraysize(kData)
|
| + << " different snipets against " << arraysize(kPatterns)
|
| + << " different patterns, repeated " << kRepetitions << " times took "
|
| + << matching_elapsed.InMicroseconds() << " microseconds.";
|
| +}
|
| +
|
| +TEST(Benchmark, RE2_compilation) {
|
| + // Benchmark regex compilation.
|
| + ScopedVector<RE2> matchers;
|
| + matchers.resize(arraysize(kPatterns) * kRepetitions);
|
| + size_t matchers_idx = 0;
|
| + base::ElapsedTimer compilation_timer;
|
| + for (size_t pat_i = 0; pat_i < arraysize(kPatterns); ++pat_i) {
|
| + for (size_t j = 0; j < kRepetitions; ++j) {
|
| + matchers[matchers_idx] = new RE2(kPatterns[pat_i]);
|
| + ++matchers_idx;
|
| + }
|
| + }
|
| + base::TimeDelta compilation_elapsed = compilation_timer.Elapsed();
|
| +
|
| + VLOG(0) << "RE2: Compilation of " << arraysize(kPatterns)
|
| + << " different patterns, repeated " << kRepetitions << " times took "
|
| + << compilation_elapsed.InMicroseconds() << " microseconds.";
|
| +}
|
| +
|
| +} // namespace autofill
|
|
|