[ledger][benchmarks] Randomize keys.

Keys generated for the benchmarks had the index as a prefix, making
them partially sequential (e.g. 1, 10, 2, 3, 4, 5, 6, 7, 8, 9). After
this CL, keys will have the index as a suffix, forcing a random order
in insertions/updates, while still allowing retrieving the keys' ids.

Note that this change will likely change some of the results in the
dashboard, because of the re-ordering of the keys.

Test: All benchmarks are still running correctly.
Change-Id: If88eeb556dbccf1a668d3af2040614d9b068d7b1
diff --git a/bin/ledger/testing/data_generator.cc b/bin/ledger/testing/data_generator.cc
index e282d32..82d1b98 100644
--- a/bin/ledger/testing/data_generator.cc
+++ b/bin/ledger/testing/data_generator.cc
@@ -15,6 +15,11 @@
 #include "peridot/lib/convert/convert.h"
 
 namespace ledger {
+namespace {
+
+constexpr fxl::StringView kKeyIdSeparator = "-";
+
+}  // namespace
 
 DataGenerator::DataGenerator(rng::Random* random)
     : generator_(random->NewBitGenerator<uint64_t>()) {}
@@ -23,11 +28,11 @@
 
 std::vector<uint8_t> DataGenerator::MakeKey(int i, size_t size) {
   std::string i_str = std::to_string(i);
-  FXL_DCHECK(i_str.size() + 1 <= size);
-  auto rand_bytes = MakeValue(size - i_str.size() - 1);
+  FXL_DCHECK(i_str.size() + kKeyIdSeparator.size() <= size);
+  auto rand_bytes = MakeValue(size - i_str.size() - kKeyIdSeparator.size());
 
-  return convert::ToArray(
-      fxl::Concatenate({i_str, "-", convert::ExtendedStringView(rand_bytes)}));
+  return convert::ToArray(fxl::Concatenate(
+      {convert::ExtendedStringView(rand_bytes), kKeyIdSeparator, i_str}));
 }
 
 PageId DataGenerator::MakePageId() {
@@ -55,4 +60,12 @@
   return keys;
 }
 
+size_t DataGenerator::GetKeyId(const std::vector<uint8_t>& key) {
+  std::string key_str = convert::ToString(key);
+  size_t split_index = key_str.find_last_of(kKeyIdSeparator.ToString());
+  FXL_CHECK(split_index != std::string::npos &&
+            split_index + kKeyIdSeparator.size() < key_str.size());
+  return std::stoul(key_str.substr(split_index + kKeyIdSeparator.size()));
+}
+
 }  // namespace ledger
diff --git a/bin/ledger/testing/data_generator.h b/bin/ledger/testing/data_generator.h
index 47cbf57..8dbf326 100644
--- a/bin/ledger/testing/data_generator.h
+++ b/bin/ledger/testing/data_generator.h
@@ -22,9 +22,8 @@
 
   ~DataGenerator();
 
-  // Builds a key of the given length as "<the given int>-<random data>", so
-  // that deterministic ordering of entries can be ensured by using a different
-  // |i| value each time, but the resulting B-tree nodes are always distinct.
+  // Builds a key of the given |size| as "<random data>-<i>". The id (|i|) of
+  // the result can be retrieved by calling |GetKeyId|.
   std::vector<uint8_t> MakeKey(int i, size_t size);
 
   // Builds a random value that can be used as a page id.
@@ -35,9 +34,12 @@
 
   // Builds a vector of length |key_count| containing keys of size |key_size|,
   // |unique_key_count| of which are unique.
-  std::vector<std::vector<uint8_t>> MakeKeys(size_t key_count,
-                                                 size_t key_size,
-                                                 size_t unique_key_count);
+  std::vector<std::vector<uint8_t>> MakeKeys(size_t key_count, size_t key_size,
+                                             size_t unique_key_count);
+
+  // Returns the id of |key|. |key| is assumed to have been created by this
+  // DataGenerator, using either |MakeKey| or |MakeKeys|.
+  size_t GetKeyId(const std::vector<uint8_t>& key);
 
  private:
   std::independent_bits_engine<rng::Random::BitGenerator<uint64_t>, CHAR_BIT,
diff --git a/bin/ledger/tests/benchmark/put/put.cc b/bin/ledger/tests/benchmark/put/put.cc
index b55d54a..55847d1 100644
--- a/bin/ledger/tests/benchmark/put/put.cc
+++ b/bin/ledger/tests/benchmark/put/put.cc
@@ -162,22 +162,21 @@
         }
         page_ = std::move(page);
 
-        InitializeKeys(
-            [this](std::vector<std::vector<uint8_t>> keys) mutable {
-              if (transaction_size_ > 0) {
-                page_->StartTransaction(
-                    [this, keys = std::move(keys)](Status status) mutable {
-                      if (QuitOnError(QuitLoopClosure(), status,
-                                      "Page::StartTransaction")) {
-                        return;
-                      }
-                      TRACE_ASYNC_BEGIN("benchmark", "transaction", 0);
-                      BindWatcher(std::move(keys));
-                    });
-              } else {
-                BindWatcher(std::move(keys));
-              }
-            });
+        InitializeKeys([this](std::vector<std::vector<uint8_t>> keys) mutable {
+          if (transaction_size_ > 0) {
+            page_->StartTransaction(
+                [this, keys = std::move(keys)](Status status) mutable {
+                  if (QuitOnError(QuitLoopClosure(), status,
+                                  "Page::StartTransaction")) {
+                    return;
+                  }
+                  TRACE_ASYNC_BEGIN("benchmark", "transaction", 0);
+                  BindWatcher(std::move(keys));
+                });
+          } else {
+            BindWatcher(std::move(keys));
+          }
+        });
       });
 }
 
@@ -185,7 +184,7 @@
                             ResultState /*result_state*/,
                             OnChangeCallback callback) {
   for (auto const& change : page_change.changed_entries) {
-    size_t key_number = std::stoul(convert::ToString(change.key));
+    size_t key_number = generator_.GetKeyId(change.key);
     if (keys_to_receive_.find(key_number) != keys_to_receive_.end()) {
       TRACE_ASYNC_END("benchmark", "local_change_notification", key_number);
       keys_to_receive_.erase(key_number);
@@ -206,11 +205,11 @@
     keys_cloned.push_back(keys[i]);
     if (transaction_size_ == 0 ||
         i % transaction_size_ == transaction_size_ - 1) {
-      keys_to_receive_.insert(std::stoul(convert::ToString(keys[i])));
+      keys_to_receive_.insert(generator_.GetKeyId(keys[i]));
     }
   }
   // Last key should always be recorded so the last transaction is not lost.
-  size_t last_key_number = std::stoul(convert::ToString(keys.back()));
+  size_t last_key_number = generator_.GetKeyId(keys.back());
   keys_to_receive_.insert(last_key_number);
   if (!update_) {
     on_done(std::move(keys));
@@ -242,15 +241,14 @@
       });
 }
 
-void PutBenchmark::RunSingle(int i,
-                             std::vector<std::vector<uint8_t>> keys) {
+void PutBenchmark::RunSingle(int i, std::vector<std::vector<uint8_t>> keys) {
   if (i == entry_count_) {
     // All sent, waiting for watcher notification before shutting down.
     return;
   }
 
   fidl::VectorPtr<uint8_t> value = generator_.MakeValue(value_size_);
-  size_t key_number = std::stoul(convert::ToString(keys[i]));
+  size_t key_number = generator_.GetKeyId(keys[i]);
   if (transaction_size_ == 0) {
     TRACE_ASYNC_BEGIN("benchmark", "local_change_notification", key_number);
   }
@@ -312,8 +310,8 @@
       });
 }
 
-void PutBenchmark::CommitAndRunNext(
-    int i, size_t key_number, std::vector<std::vector<uint8_t>> keys) {
+void PutBenchmark::CommitAndRunNext(int i, size_t key_number,
+                                    std::vector<std::vector<uint8_t>> keys) {
   TRACE_ASYNC_BEGIN("benchmark", "local_change_notification", key_number);
   TRACE_ASYNC_BEGIN("benchmark", "commit", i / transaction_size_);
   page_->Commit([this, i, keys = std::move(keys)](Status status) mutable {
diff --git a/bin/ledger/tests/benchmark/sync/sync.cc b/bin/ledger/tests/benchmark/sync/sync.cc
index 7f38b34..d0cc4df 100644
--- a/bin/ledger/tests/benchmark/sync/sync.cc
+++ b/bin/ledger/tests/benchmark/sync/sync.cc
@@ -210,8 +210,7 @@
 void SyncBenchmark::OnChange(PageChange page_change, ResultState result_state,
                              OnChangeCallback callback) {
   FXL_DCHECK(!page_change.changed_entries.empty());
-  size_t i =
-      std::stoul(convert::ToString(page_change.changed_entries.at(0).key));
+  size_t i = generator_.GetKeyId(page_change.changed_entries.at(0).key);
   changed_entries_received_ += page_change.changed_entries.size();
   if (result_state == ResultState::COMPLETED ||
       result_state == ResultState::PARTIAL_STARTED) {
@@ -233,7 +232,8 @@
 
   std::vector<std::vector<uint8_t>> keys(entries_per_change_);
   for (size_t i = 0; i < entries_per_change_; i++) {
-    // Keys are distinct, but have the common prefix <i>.
+    // Keys are distinct, but they all have the same id (|change_number|), which
+    // will be used to end the trace.
     keys[i] = generator_.MakeKey(change_number, kKeySize);
   }