Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1850)

Unified Diff: base/metrics/field_trial.cc

Issue 2449783007: Use pickle for field trial entries in shared memory (Closed)
Patch Set: address nits Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/metrics/field_trial.cc
diff --git a/base/metrics/field_trial.cc b/base/metrics/field_trial.cc
index bb6ae0cb83fd02fa52b8d17584ee911fcef105ca..253170ae1ba2ea40af08e4b4d7b2b63d3e69113e 100644
--- a/base/metrics/field_trial.cc
+++ b/base/metrics/field_trial.cc
@@ -13,6 +13,7 @@
#include "base/feature_list.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
+#include "base/pickle.h"
#include "base/process/memory.h"
#include "base/rand_util.h"
#include "base/strings/string_number_conversions.h"
@@ -46,29 +47,31 @@ const uint32_t kFieldTrialType = 0xABA17E13 + 1; // SHA1(FieldTrialEntry) v1
const size_t kFieldTrialAllocationSize = 4 << 10; // 4 KiB = one page
#endif
-// We create one FieldTrialEntry struct per field trial in shared memory (via
-// field_trial_allocator_). It contains whether or not it's activated, and the
-// offset from the start of the allocated memory to the group name. We don't
-// need the offset into the trial name because that's always a fixed position
-// from the start of the struct. Two strings will be appended to the end of this
-// structure in allocated memory, so the result will look like this:
-// ---------------------------------
-// | fte | trial_name | group_name |
-// ---------------------------------
+// We create one FieldTrialEntry per field trial in shared memory, via
+// AddToAllocatorWhileLocked. The FieldTrialEntry is followed by a base::Pickle
+// object that we unpickle and read from.
struct FieldTrialEntry {
bool activated;
- uint32_t group_name_offset;
- const char* GetTrialName() const {
- const char* src =
- reinterpret_cast<char*>(const_cast<FieldTrialEntry*>(this));
- return src + sizeof(FieldTrialEntry);
- }
+ // Size of the pickled structure, NOT the total size of this entry.
+ uint32_t size;
+
+ // Calling this is only valid when the entry is initialized. That is, it
+ // resides in shared memory and has a pickle containing the trial name and
+ // group name following it.
+ bool GetTrialAndGroupName(StringPiece* trial_name,
+ StringPiece* group_name) const {
+ char* src = reinterpret_cast<char*>(const_cast<FieldTrialEntry*>(this)) +
+ sizeof(FieldTrialEntry);
+
+ Pickle pickle(src, size);
+ PickleIterator pickle_iter(pickle);
- const char* GetGroupName() const {
- const char* src =
- reinterpret_cast<char*>(const_cast<FieldTrialEntry*>(this));
- return src + this->group_name_offset;
+ if (!pickle_iter.ReadStringPiece(trial_name))
+ return false;
+ if (!pickle_iter.ReadStringPiece(group_name))
+ return false;
+ return true;
}
};
@@ -798,15 +801,25 @@ void FieldTrialList::CreateTrialsFromSharedMemory(
std::unique_ptr<SharedMemory> shm) {
const SharedPersistentMemoryAllocator shalloc(std::move(shm), 0,
kAllocatorName, true);
- PersistentMemoryAllocator::Iterator iter(&shalloc);
+ PersistentMemoryAllocator::Iterator mem_iter(&shalloc);
SharedPersistentMemoryAllocator::Reference ref;
- while ((ref = iter.GetNextOfType(kFieldTrialType)) !=
+ while ((ref = mem_iter.GetNextOfType(kFieldTrialType)) !=
SharedPersistentMemoryAllocator::kReferenceNull) {
const FieldTrialEntry* entry =
shalloc.GetAsObject<const FieldTrialEntry>(ref, kFieldTrialType);
+
+ StringPiece trial_name;
+ StringPiece group_name;
+ if (!entry->GetTrialAndGroupName(&trial_name, &group_name)) {
+ NOTREACHED();
+ continue;
+ }
+
+ // TODO(lawrencewu): Convert the API for CreateFieldTrial to take
+ // StringPieces.
FieldTrial* trial =
- CreateFieldTrial(entry->GetTrialName(), entry->GetGroupName());
+ CreateFieldTrial(trial_name.as_string(), group_name.as_string());
if (entry->activated) {
// Call |group()| to mark the trial as "used" and notify observers, if
@@ -866,34 +879,25 @@ void FieldTrialList::AddToAllocatorWhileLocked(FieldTrial* field_trial) {
if (!field_trial->GetState(&trial_state))
return;
- size_t trial_name_size = trial_state.trial_name.size() + 1;
- size_t group_name_size = trial_state.group_name.size() + 1;
- size_t size = sizeof(FieldTrialEntry) + trial_name_size + group_name_size;
+ Pickle pickle;
+ pickle.WriteString(trial_state.trial_name);
+ pickle.WriteString(trial_state.group_name);
- // Allocate just enough memory to fit the FieldTrialEntry struct, trial name,
- // and group name.
+ size_t total_size = sizeof(FieldTrialEntry) + pickle.size();
SharedPersistentMemoryAllocator::Reference ref =
- allocator->Allocate(size, kFieldTrialType);
+ allocator->Allocate(total_size, kFieldTrialType);
if (ref == SharedPersistentMemoryAllocator::kReferenceNull)
return;
- // Calculate offsets into the shared memory segment.
FieldTrialEntry* entry =
allocator->GetAsObject<FieldTrialEntry>(ref, kFieldTrialType);
- uint32_t trial_name_offset = sizeof(FieldTrialEntry);
- uint32_t group_name_offset = trial_name_offset + trial_name_size;
-
- // Copy over the data.
entry->activated = trial_state.activated;
- entry->group_name_offset = group_name_offset;
- char* trial_name = reinterpret_cast<char*>(entry) + trial_name_offset;
- char* group_name = reinterpret_cast<char*>(entry) + group_name_offset;
- memcpy(trial_name, trial_state.trial_name.data(), trial_name_size);
- memcpy(group_name, trial_state.group_name.data(), group_name_size);
-
- // Null terminate the strings.
- trial_name[trial_state.trial_name.size()] = '\0';
- group_name[trial_state.group_name.size()] = '\0';
+ entry->size = pickle.size();
+
+ // TODO(lawrencewu): Modify base::Pickle to be able to write over a section in
+ // memory, so we can avoid this memcpy.
+ char* dst = reinterpret_cast<char*>(entry) + sizeof(FieldTrialEntry);
+ memcpy(dst, pickle.data(), pickle.size());
allocator->MakeIterable(ref);
field_trial->ref_ = ref;
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698