Skip to content

Commit

Permalink
Faster copy from inline Cords to inline Strings
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 714061397
Change-Id: Iad41d5033d7a0f87a54cd97d636aa450e0d6b8b4
  • Loading branch information
Abseil Team authored and copybara-github committed Jan 10, 2025
1 parent f489ceb commit 1d50897
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 22 deletions.
7 changes: 1 addition & 6 deletions absl/strings/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -441,15 +441,13 @@ cc_library(
"//absl/base:config",
"//absl/base:core_headers",
"//absl/base:endian",
"//absl/base:nullability",
"//absl/base:raw_logging_internal",
"//absl/base:throw_delegate",
"//absl/container:compressed_tuple",
"//absl/container:container_memory",
"//absl/container:inlined_vector",
"//absl/container:layout",
"//absl/crc:crc_cord_state",
"//absl/functional:function_ref",
"//absl/meta:type_traits",
"//absl/types:span",
],
)
Expand Down Expand Up @@ -580,14 +578,11 @@ cc_library(
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":cord_internal",
":cordz_functions",
":cordz_info",
":cordz_statistics",
":cordz_update_scope",
":cordz_update_tracker",
":internal",
":strings",
"//absl/base",
"//absl/base:config",
"//absl/base:core_headers",
"//absl/base:endian",
Expand Down
19 changes: 5 additions & 14 deletions absl/strings/cord.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,23 +61,22 @@
#define ABSL_STRINGS_CORD_H_

#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <iosfwd>
#include <iterator>
#include <string>
#include <type_traits>
#include <utility>

#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/base/internal/endian.h"
#include "absl/base/internal/per_thread_tls.h"
#include "absl/base/macros.h"
#include "absl/base/nullability.h"
#include "absl/base/optimization.h"
#include "absl/base/port.h"
#include "absl/container/inlined_vector.h"
#include "absl/crc/internal/crc_cord_state.h"
#include "absl/functional/function_ref.h"
#include "absl/meta/type_traits.h"
Expand All @@ -88,12 +87,10 @@
#include "absl/strings/internal/cord_rep_btree.h"
#include "absl/strings/internal/cord_rep_btree_reader.h"
#include "absl/strings/internal/cord_rep_crc.h"
#include "absl/strings/internal/cordz_functions.h"
#include "absl/strings/internal/cord_rep_flat.h"
#include "absl/strings/internal/cordz_info.h"
#include "absl/strings/internal/cordz_statistics.h"
#include "absl/strings/internal/cordz_update_scope.h"
#include "absl/strings/internal/cordz_update_tracker.h"
#include "absl/strings/internal/resize_uninitialized.h"
#include "absl/strings/internal/string_constant.h"
#include "absl/strings/string_view.h"
#include "absl/types/compare.h"
Expand Down Expand Up @@ -978,15 +975,9 @@ class Cord {

bool IsSame(const InlineRep& other) const { return data_ == other.data_; }

// Copies the inline contents into `dst`. Assumes the cord is not empty.
void CopyTo(absl::Nonnull<std::string*> dst) const {
// memcpy is much faster when operating on a known size. On most supported
// platforms, the small string optimization is large enough that resizing
// to 15 bytes does not cause a memory allocation.
absl::strings_internal::STLStringResizeUninitialized(dst, kMaxInline);
data_.copy_max_inline_to(&(*dst)[0]);
// erase is faster than resize because the logic for memory allocation is
// not needed.
dst->erase(inline_size());
data_.CopyInlineToString(dst);
}

// Copies the inline contents into `dst`. Assumes the cord is not empty.
Expand Down
19 changes: 17 additions & 2 deletions absl/strings/internal/cord_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,18 @@
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <type_traits>
#include <cstring>
#include <string>

#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/base/internal/endian.h"
#include "absl/base/internal/invoke.h"
#include "absl/base/macros.h"
#include "absl/base/nullability.h"
#include "absl/base/optimization.h"
#include "absl/container/internal/compressed_tuple.h"
#include "absl/container/internal/container_memory.h"
#include "absl/meta/type_traits.h"
#include "absl/strings/string_view.h"

// We can only add poisoning if we can detect consteval executions.
Expand Down Expand Up @@ -635,6 +637,19 @@ class InlineData {
poison();
}

void CopyInlineToString(absl::Nonnull<std::string*> dst) const {
assert(!is_tree());
// As Cord can store only 15 bytes it is smaller than std::string's
// small string optimization buffer size. Therefore we will always trigger
// the fast assign short path.
//
// Copying with a size equal to the maximum allows more efficient, wider
// stores to be used and no branching.
dst->assign(rep_.SanitizerSafeCopy().as_chars(), kMaxInline);
// After the copy we then change the size and put in a 0 byte.
dst->erase(inline_size());
}

void copy_max_inline_to(char* dst) const {
assert(!is_tree());
memcpy(dst, rep_.SanitizerSafeCopy().as_chars(), kMaxInline);
Expand Down

0 comments on commit 1d50897

Please sign in to comment.