Skip to content

Commit

Permalink
Add prefetching in arena blocks.
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 604441990
  • Loading branch information
protobuf-github-bot authored and Copybara-Service committed Feb 5, 2024
1 parent dbf7adf commit 9e57b8e
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 13 deletions.
3 changes: 2 additions & 1 deletion src/google/protobuf/BUILD.bazel
Expand Up @@ -319,7 +319,7 @@ cc_library(
],
deps = [
"@com_google_absl//absl/base:core_headers",
"@com_google_absl//absl/log:absl_log",
"@com_google_absl//absl/base:prefetch",
],
)

Expand Down Expand Up @@ -388,6 +388,7 @@ cc_library(
"@com_google_absl//absl/log:absl_log",
"@com_google_absl//absl/numeric:bits",
"@com_google_absl//absl/synchronization",
"@com_google_absl//absl/types:span",
"@com_google_absl//absl/utility:if_constexpr",
],
)
Expand Down
24 changes: 23 additions & 1 deletion src/google/protobuf/arena.cc
Expand Up @@ -13,17 +13,21 @@
#include <cstdint>
#include <limits>
#include <string>
#include <typeinfo>
#include <vector>

#include "absl/base/attributes.h"
#include "absl/base/prefetch.h"
#include "absl/container/internal/layout.h"
#include "absl/log/absl_check.h"
#include "absl/log/absl_log.h"
#include "absl/synchronization/mutex.h"
#include "absl/types/span.h"
#include "google/protobuf/arena_allocation_policy.h"
#include "google/protobuf/arena_cleanup.h"
#include "google/protobuf/arenaz_sampler.h"
#include "google/protobuf/port.h"
#include "google/protobuf/serial_arena.h"
#include "google/protobuf/string_block.h"
#include "google/protobuf/thread_safe_arena.h"


Expand Down Expand Up @@ -299,6 +303,7 @@ size_t SerialArena::FreeStringBlocks(StringBlock* string_block,
size_t unused_bytes) {
ABSL_DCHECK(string_block != nullptr);
StringBlock* next = string_block->next();
absl::PrefetchToLocalCacheNta(next);
std::string* end = string_block->end();
for (std::string* s = string_block->AtOffset(unused_bytes); s != end; ++s) {
s->~basic_string();
Expand All @@ -307,6 +312,7 @@ size_t SerialArena::FreeStringBlocks(StringBlock* string_block,

while ((string_block = next) != nullptr) {
next = string_block->next();
absl::PrefetchToLocalCacheNta(next);
for (std::string& s : *string_block) {
s.~basic_string();
}
Expand All @@ -324,6 +330,18 @@ void SerialArena::CleanupList() {
char* limit = b->Limit();
char* it = reinterpret_cast<char*>(b->cleanup_nodes);
ABSL_DCHECK(!b->IsSentry() || it == limit);
// A prefetch distance of 8 here was chosen arbitrarily.
char* prefetch = it;
int prefetch_dist = 8;
for (; prefetch < limit && --prefetch_dist; prefetch += cleanup::Size()) {
cleanup::PrefetchNode(prefetch);
}
for (; prefetch < limit;
it += cleanup::Size(), prefetch += cleanup::Size()) {
cleanup::DestroyNode(it);
cleanup::PrefetchNode(prefetch);
}
absl::PrefetchToLocalCacheNta(b->next);
for (; it < limit; it += cleanup::Size()) {
cleanup::DestroyNode(it);
}
Expand Down Expand Up @@ -780,6 +798,8 @@ void ThreadSafeArena::WalkConstSerialArenaChunk(Functor fn) const {
const SerialArenaChunk* chunk = head_.load(std::memory_order_acquire);

for (; !chunk->IsSentry(); chunk = chunk->next_chunk()) {
// Prefetch the next chunk.
absl::PrefetchToLocalCache(chunk->next_chunk());
fn(chunk);
}
}
Expand All @@ -794,6 +814,8 @@ void ThreadSafeArena::WalkSerialArenaChunk(Functor fn) {
while (!chunk->IsSentry()) {
// Cache next chunk in case this chunk is destroyed.
SerialArenaChunk* next_chunk = chunk->next_chunk();
// Prefetch the next chunk.
absl::PrefetchToLocalCache(next_chunk);
fn(chunk);
chunk = next_chunk;
}
Expand Down
12 changes: 6 additions & 6 deletions src/google/protobuf/arena_cleanup.h
Expand Up @@ -9,15 +9,11 @@
#define GOOGLE_PROTOBUF_ARENA_CLEANUP_H__

#include <cstddef>
#include <cstdint>
#include <string>
#include <cstring>
#include <vector>

#include "absl/base/attributes.h"
#include "absl/log/absl_check.h"
#include "absl/log/absl_log.h"
#include "absl/strings/cord.h"

#include "absl/base/prefetch.h"

// Must be included last.
#include "google/protobuf/port_def.inc"
Expand Down Expand Up @@ -54,6 +50,10 @@ inline ABSL_ATTRIBUTE_ALWAYS_INLINE void CreateNode(void* pos, void* elem,

// Optimization: performs a prefetch on the elem for the cleanup node at `pos`.
inline ABSL_ATTRIBUTE_ALWAYS_INLINE void PrefetchNode(void* pos) {
// We explicitly use NTA prefetch here to avoid polluting remote caches: we
// are destroying these instances, there is no purpose for these cache lines
// to linger around in remote caches.
absl::PrefetchToLocalCacheNta(ToCleanup(pos)->elem);
}

// Destroys the object referenced by the cleanup node.
Expand Down
5 changes: 0 additions & 5 deletions src/google/protobuf/serial_arena.h
Expand Up @@ -15,20 +15,15 @@
#include <cstddef>
#include <cstdint>
#include <string>
#include <type_traits>
#include <typeinfo>
#include <utility>
#include <vector>

#include "google/protobuf/stubs/common.h"
#include "absl/base/attributes.h"
#include "absl/base/optimization.h"
#include "absl/base/prefetch.h"
#include "absl/log/absl_check.h"
#include "absl/numeric/bits.h"
#include "google/protobuf/arena_align.h"
#include "google/protobuf/arena_cleanup.h"
#include "google/protobuf/arenaz_sampler.h"
#include "google/protobuf/port.h"
#include "google/protobuf/string_block.h"

Expand Down

0 comments on commit 9e57b8e

Please sign in to comment.