Commit 07f00b6e authored by Adenilson Cavalcanti's avatar Adenilson Cavalcanti Committed by Commit Bot

Using BoringSSL's SHA1 implementation

The portable implementation in base is nicely written and tested but
could be made way faster by using SIMD and crypto instructions.

Enters BoringSSL: its SHA1 implementation is highly optimized for
many architectures, actively maintained and tested.

It will make SHA1 *way* faster on Intel (6x), ARMv7 (8x) and
ARMv8 (between 16x to 21x faster).

Plus adds a performance benchmark to measure the speed (MB/s) of
the hash implementation.

Unfortunately, thanks to NaCL we still got keep the portable
implementation around for the time being (until it is finally
removed).

Change-Id: Ifc4b6a82a0d36e5157b1fa6d94760c32197b570c
Bug: 974341
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1661110Reviewed-by: default avatarAdenilson Cavalcanti <cavalcantii@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarDavid Benjamin <davidben@chromium.org>
Commit-Queue: Adenilson Cavalcanti <cavalcantii@chromium.org>
Cr-Commit-Position: refs/heads/master@{#678434}
parent 383b1603
......@@ -308,8 +308,6 @@ jumbo_component("base") {
"guid.h",
"hash/hash.cc",
"hash/hash.h",
"hash/sha1.cc",
"hash/sha1.h",
"immediate_crash.h",
"ios/block_types.h",
"ios/crb_protocol_observers.h",
......@@ -1593,16 +1591,19 @@ jumbo_component("base") {
"hash/md5.h",
"hash/md5_constexpr.h",
"hash/md5_constexpr_internal.h",
"hash/sha1.h",
]
if (is_nacl) {
sources += [
"hash/md5_nacl.cc",
"hash/md5_nacl.h",
"hash/sha1.cc",
]
} else {
sources += [
"hash/md5_boringssl.cc",
"hash/md5_boringssl.h",
"hash/sha1_boringssl.cc",
]
public_deps += [ "//third_party/boringssl" ]
}
......@@ -2222,6 +2223,7 @@ component("i18n") {
test("base_perftests") {
sources = [
"hash/sha1_perftest.cc",
"message_loop/message_pump_perftest.cc",
"observer_list_perftest.cc",
"strings/string_util_perftest.cc",
......
// Copyright (c) 2019 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/hash/sha1.h"
#include <stdint.h>
#include "base/strings/string_util.h"
#include "third_party/boringssl/src/include/openssl/crypto.h"
#include "third_party/boringssl/src/include/openssl/sha.h"
namespace base {
void SHA1HashBytes(const unsigned char* data, size_t len, unsigned char* hash) {
CRYPTO_library_init();
SHA1(data, len, hash);
}
std::string SHA1HashString(const std::string& str) {
CRYPTO_library_init();
std::string digest;
SHA1(reinterpret_cast<const uint8_t*>(str.data()), str.size(),
reinterpret_cast<uint8_t*>(base::WriteInto(&digest, kSHA1Length + 1)));
return digest;
}
} // namespace base
// Copyright (c) 2019 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/hash/sha1.h"
#include <stddef.h>
#include <stdint.h>
#include <algorithm>
#include <string>
#include <vector>
#include "base/rand_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/time/time.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/perf/perf_test.h"
static void Timing(const size_t len) {
std::vector<uint8_t> buf(len);
base::RandBytes(buf.data(), len);
const int runs = 111;
std::vector<base::TimeDelta> utime(runs);
unsigned char digest[base::kSHA1Length];
memset(digest, 0, base::kSHA1Length);
double total_test_time = 0.0;
for (int i = 0; i < runs; ++i) {
auto start = base::TimeTicks::Now();
base::SHA1HashBytes(buf.data(), len, digest);
auto end = base::TimeTicks::Now();
utime[i] = end - start;
total_test_time += utime[i].InMicroseconds();
}
std::sort(utime.begin(), utime.end());
const int med = runs / 2;
const int min = 0;
// No need for conversions as length is in bytes and time in usecs:
// MB/s = (len / (bytes/megabytes)) / (usecs / usecs/sec)
// MB/s = (len / 1,000,000)/(usecs / 1,000,000)
// MB/s = (len * 1,000,000)/(usecs * 1,000,000)
// MB/s = len/utime
double median_rate = len / utime[med].InMicroseconds();
double max_rate = len / utime[min].InMicroseconds();
perf_test::PrintResult("len=", base::NumberToString(len), "median",
median_rate, "MB/s", true);
perf_test::PrintResult("usecs=", base::NumberToString(total_test_time), "max",
max_rate, "MB/s", true);
}
TEST(SHA1PerfTest, Speed) {
Timing(1024 * 1024U >> 1);
Timing(1024 * 1024U >> 5);
Timing(1024 * 1024U >> 6);
Timing(1024 * 1024U >> 7);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment