77using Clock = std::chrono::steady_clock;
79double elapsed_ms(
const Clock::time_point start)
81 return std::chrono::duration<double, std::milli>(Clock::now() - start).count();
86 std::cout <<
" " << std::left << std::setw(28) << label << std::right
87 << std::setw(10) << std::fixed << std::setprecision(2) <<
ms <<
" ms"
95 const auto start = Clock::now();
99 const char c =
static_cast<char>(
'a' + (i % 26));
100 s += std::string_view(&c, 1);
102 print_row(
"std::string::operator+=", elapsed_ms(start), s.size());
108 const auto start = Clock::now();
112 const char c =
static_cast<char>(
'a' + (i % 26));
115 print_row(
"Rope::concat (1 char/call)", elapsed_ms(start),
r.size());
129 const auto start = Clock::now();
133 print_row(
"Rope::concat (" + std::to_string(chunk_size) +
" chars/call)",
134 elapsed_ms(start),
r.size());
137 std::string chunk(
static_cast<size_t>(chunk_size),
'a');
142 const std::string_view
piece(chunk.data(),
static_cast<size_t>(piece_size));
146 print_row(
"Rope::concat (" + std::to_string(chunk_size) +
" chars/call)",
147 elapsed_ms(start),
r.size());
155 const auto start = Clock::now();
156 std::string s = base;
157 const std::string marker =
"<<edit>>";
158 std::mt19937
rng(0xEDEDu);
161 std::uniform_int_distribution<size_t>
pos_dist(0, s.size());
163 s.insert(pos, marker);
164 s.erase(pos, marker.size());
166 print_row(
"std::string insert+erase", elapsed_ms(start), s.size());
171 const auto start = Clock::now();
173 const Rope<char> marker{std::string_view(
"<<edit>>")};
174 std::mt19937
rng(0xEDEDu);
177 std::uniform_int_distribution<size_t>
pos_dist(0,
r.size());
179 r =
r.insert(pos, marker);
180 r =
r.erase(pos, marker.size());
182 print_row(
"Rope insert+erase", elapsed_ms(start),
r.size());
191 int chunk_count = 2000000;
194 for (
int i = 1; i <
argc; ++i)
196 const std::string_view
arg =
argv[i];
198 chunk_count = std::atoi(
argv[++i]);
201 else if (
arg ==
"--help")
203 std::cout <<
"Usage: rope_benchmark [--chunks N] [--edits N]\n";
212 std::cout <<
"\n=== Aleph::Rope vs std::string benchmark ===\n\n";
214 std::cout <<
"[1] Large concatenation: " << chunk_count
215 <<
" single-character appends\n";
218 std::cout <<
" (Rope's documented weak case -- every successful "
219 "absorption re-copies the whole receiving leaf; see below "
220 "for the pattern it is actually built for.)\n";
222 constexpr int chunk_size = 1000;
229 chunk_count == 0 ? 0 : (chunk_count - 1) / chunk_size + 1;
231 <<
" chunked concatenations (" << chunk_size
232 <<
" chars/call, Rope's intended "
236 std::cout <<
"\n[2] Structural editing: " <<
edit_count
237 <<
" random middle insert+erase pairs on a "
238 << chunk_count <<
"-character base sequence\n";
239 const std::string
base_string(
static_cast<size_t>(chunk_count),
'x');
244 std::cout <<
"\nDone.\n";
Immutable, structurally-shared rope over a sequence of Char.
Rope concat(const Rope &other) const
Return a new rope that is *this followed by other.
std::chrono::steady_clock Clock
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
size_t piece_size(std::string_view s) noexcept
size_t chunk_count(const size_t n, const size_t chunk_size) noexcept
size_t chunk_size(const size_t n, const size_t num_threads, const size_t min_chunk=64)
Calculate optimal chunk size based on data size and thread count.
Main namespace for Aleph-w library functions.
and
Check uniqueness with explicit hash + equality functors.
Immutable, structurally-shared rope (Aleph::Rope) for large character sequences.