-
Notifications
You must be signed in to change notification settings - Fork 131
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement a function that gathers data from bunch of string_views int…
…o a single buffer. This is similar to CopyFromIovec, notable distinctions being: 1. It takes string_views instead of iovecs. 2. It does not allocate anything. 3. The next string_view is always prefetched (CopyFromIovec only prefetches the second one at the beginning). The hope is to use it to speed up QuicStreamSendBuffer::WriteStreamData at some point in the future. PiperOrigin-RevId: 698508368
- Loading branch information
1 parent
f49f729
commit 3145fd0
Showing
10 changed files
with
190 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
// Copyright 2024 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 "quiche/common/vectorized_io_utils.h" | ||
|
||
#include <algorithm> | ||
#include <cstddef> | ||
#include <cstring> | ||
|
||
#include "absl/base/optimization.h" | ||
#include "absl/base/prefetch.h" | ||
#include "absl/strings/string_view.h" | ||
#include "absl/types/span.h" | ||
|
||
namespace quiche { | ||
|
||
size_t TotalStringViewSpanSize(absl::Span<const absl::string_view> span) { | ||
size_t total = 0; | ||
for (absl::string_view view : span) { | ||
total += view.size(); | ||
} | ||
return total; | ||
} | ||
|
||
size_t GatherStringViewSpan(absl::Span<const absl::string_view> inputs, | ||
absl::Span<char> output) { | ||
size_t bytes_copied = 0; | ||
for (size_t i = 0; i < inputs.size(); ++i) { | ||
if (inputs[i].empty()) { | ||
continue; | ||
} | ||
const size_t bytes_to_copy = std::min(inputs[i].size(), output.size()); | ||
if (bytes_to_copy == 0) { | ||
break; | ||
} | ||
const absl::Span<char> next_output = output.subspan(bytes_to_copy); | ||
|
||
// Prefetch the first two lines of the next input; the hardware prefetcher | ||
// is expected to take care of the rest. | ||
if (!next_output.empty() && (i + 1) < inputs.size() && | ||
!inputs[i + 1].empty()) { | ||
absl::PrefetchToLocalCache(&inputs[i + 1][0]); | ||
if (inputs[i + 1].size() > ABSL_CACHELINE_SIZE) { | ||
absl::PrefetchToLocalCache(&inputs[i + 1][ABSL_CACHELINE_SIZE]); | ||
} | ||
} | ||
|
||
memcpy(output.data(), inputs[i].data(), bytes_to_copy); | ||
bytes_copied += bytes_to_copy; | ||
output = next_output; | ||
} | ||
return bytes_copied; | ||
} | ||
|
||
} // namespace quiche |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// Copyright 2024 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 QUICHE_COMMON_VECTORIZED_IO_UTILS_H_ | ||
#define QUICHE_COMMON_VECTORIZED_IO_UTILS_H_ | ||
|
||
#include <cstddef> | ||
|
||
#include "absl/strings/string_view.h" | ||
#include "absl/types/span.h" | ||
|
||
namespace quiche { | ||
|
||
// Computes the total size of all strings in the provided span. | ||
size_t TotalStringViewSpanSize(absl::Span<const absl::string_view> span); | ||
|
||
// Copies data contained in `inputs` into `output`, up until either the `output` | ||
// is full or the `inputs` are copied fully; returns the actual number of bytes | ||
// copied. | ||
size_t GatherStringViewSpan(absl::Span<const absl::string_view> inputs, | ||
absl::Span<char> output); | ||
|
||
} // namespace quiche | ||
|
||
#endif // QUICHE_COMMON_VECTORIZED_IO_UTILS_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
// Copyright 2024 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 "quiche/common/vectorized_io_utils.h" | ||
|
||
#include <cstddef> | ||
#include <string> | ||
#include <vector> | ||
|
||
#include "absl/strings/string_view.h" | ||
#include "absl/types/span.h" | ||
#include "quiche/common/platform/api/quiche_test.h" | ||
|
||
namespace quiche { | ||
namespace { | ||
|
||
using ::testing::ElementsAre; | ||
|
||
TEST(VectorizedIoUtils, GatherStringViewSpanEmpty) { | ||
std::vector<absl::string_view> views = {"a", "b", "c"}; | ||
size_t bytes_copied = GatherStringViewSpan(views, absl::Span<char>()); | ||
EXPECT_EQ(bytes_copied, 0); | ||
} | ||
|
||
TEST(VectorizedIoUtils, GatherStringViewSpanSingle) { | ||
std::vector<absl::string_view> views = {"test"}; | ||
char buffer_small[2]; | ||
size_t bytes_copied = | ||
GatherStringViewSpan(views, absl::MakeSpan(buffer_small)); | ||
EXPECT_EQ(bytes_copied, 2); | ||
EXPECT_THAT(buffer_small, ElementsAre('t', 'e')); | ||
|
||
char buffer_exact[4]; | ||
bytes_copied = GatherStringViewSpan(views, absl::MakeSpan(buffer_exact)); | ||
EXPECT_EQ(bytes_copied, 4); | ||
EXPECT_THAT(buffer_exact, ElementsAre('t', 'e', 's', 't')); | ||
|
||
char buffer_large[6] = {'\0'}; | ||
bytes_copied = GatherStringViewSpan(views, absl::MakeSpan(buffer_large)); | ||
EXPECT_EQ(bytes_copied, 4); | ||
EXPECT_THAT(buffer_large, ElementsAre('t', 'e', 's', 't', '\0', '\0')); | ||
} | ||
|
||
TEST(VectorizedIoUtils, GatherStringViewSpanMultiple) { | ||
const std::vector<absl::string_view> views = {"foo", ",", "bar"}; | ||
constexpr absl::string_view kViewsJoined = "foo,bar"; | ||
char buffer[kViewsJoined.size()]; | ||
for (size_t i = 0; i < sizeof(buffer); ++i) { | ||
size_t bytes_copied = | ||
GatherStringViewSpan(views, absl::Span<char>(buffer, i)); | ||
absl::string_view result(buffer, bytes_copied); | ||
EXPECT_EQ(result, kViewsJoined.substr(0, i)); | ||
} | ||
} | ||
|
||
TEST(VectorizedIoUtils, GatherStringViewSpanEmptyElement) { | ||
const std::vector<absl::string_view> views = {"foo", "", "bar"}; | ||
constexpr absl::string_view kViewsJoined = "foobar"; | ||
char buffer[kViewsJoined.size()]; | ||
size_t bytes_copied = GatherStringViewSpan(views, absl::MakeSpan(buffer)); | ||
absl::string_view result(buffer, bytes_copied); | ||
EXPECT_EQ(result, kViewsJoined); | ||
} | ||
|
||
TEST(VectorizedIoUtils, GatherStringViewSpanLarge) { | ||
const std::string a(8192, 'a'); | ||
const std::string b(8192, 'b'); | ||
const std::vector<absl::string_view> views = {a, b}; | ||
const std::string joined = a + b; | ||
char buffer[8192 * 2]; | ||
size_t bytes_copied = GatherStringViewSpan(views, absl::MakeSpan(buffer)); | ||
EXPECT_EQ(bytes_copied, 8192 * 2); | ||
absl::string_view result(buffer, bytes_copied); | ||
EXPECT_EQ(result, joined); | ||
} | ||
|
||
} // namespace | ||
} // namespace quiche |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters