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

Side by Side Diff: base/metrics/field_trial.cc

Issue 2463223002: Store field trial parameters in shared memory (Closed)
Patch Set: address comments and write test Created 4 years, 1 month 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/metrics/field_trial.h" 5 #include "base/metrics/field_trial.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/base_switches.h" 10 #include "base/base_switches.h"
(...skipping 28 matching lines...) Expand all
39 // shared memory segment). See https://codereview.chromium.org/2365273004/ and 39 // shared memory segment). See https://codereview.chromium.org/2365273004/ and
40 // crbug.com/653874 40 // crbug.com/653874
41 const bool kUseSharedMemoryForFieldTrials = false; 41 const bool kUseSharedMemoryForFieldTrials = false;
42 42
43 // Constants for the field trial allocator. 43 // Constants for the field trial allocator.
44 const char kAllocatorName[] = "FieldTrialAllocator"; 44 const char kAllocatorName[] = "FieldTrialAllocator";
45 const uint32_t kFieldTrialType = 0xABA17E13 + 1; // SHA1(FieldTrialEntry) v1 45 const uint32_t kFieldTrialType = 0xABA17E13 + 1; // SHA1(FieldTrialEntry) v1
46 #if !defined(OS_NACL) 46 #if !defined(OS_NACL)
47 const size_t kFieldTrialAllocationSize = 4 << 10; // 4 KiB = one page 47 const size_t kFieldTrialAllocationSize = 4 << 10; // 4 KiB = one page
48 #endif 48 #endif
49 const int kFieldTrialParamLimit = 1000;
49 50
50 // We create one FieldTrialEntry per field trial in shared memory, via 51 // We create one FieldTrialEntry per field trial in shared memory, via
51 // AddToAllocatorWhileLocked. The FieldTrialEntry is followed by a base::Pickle 52 // AddToAllocatorWhileLocked. The FieldTrialEntry is followed by a base::Pickle
52 // object that we unpickle and read from. 53 // object that we unpickle and read from.
53 struct FieldTrialEntry { 54 struct FieldTrialEntry {
55 // Whether or not this field trial is activated.
54 bool activated; 56 bool activated;
55 57
56 // Size of the pickled structure, NOT the total size of this entry. 58 // Size of the pickled structure, NOT the total size of this entry.
57 uint32_t size; 59 uint32_t size;
58 60
61 // Returns an iterator over the data used for getting names and params.
62 PickleIterator GetPickleIterator() const {
63 char* src = reinterpret_cast<char*>(const_cast<FieldTrialEntry*>(this)) +
64 sizeof(FieldTrialEntry);
65
66 Pickle pickle(src, size);
67 return PickleIterator(pickle);
68 }
69
59 // Calling this is only valid when the entry is initialized. That is, it 70 // Calling this is only valid when the entry is initialized. That is, it
60 // resides in shared memory and has a pickle containing the trial name and 71 // resides in shared memory and has a pickle containing the trial name and
61 // group name following it. 72 // group name following it.
62 bool GetTrialAndGroupName(StringPiece* trial_name, 73 bool GetTrialAndGroupName(StringPiece* trial_name,
63 StringPiece* group_name) const { 74 StringPiece* group_name) const {
64 char* src = reinterpret_cast<char*>(const_cast<FieldTrialEntry*>(this)) + 75 PickleIterator iter = GetPickleIterator();
65 sizeof(FieldTrialEntry); 76 if (!iter.ReadStringPiece(trial_name))
66
67 Pickle pickle(src, size);
68 PickleIterator pickle_iter(pickle);
69
70 if (!pickle_iter.ReadStringPiece(trial_name))
71 return false; 77 return false;
72 if (!pickle_iter.ReadStringPiece(group_name)) 78 if (!iter.ReadStringPiece(group_name))
73 return false; 79 return false;
74 return true; 80 return true;
75 } 81 }
82
83 bool GetParams(FieldTrialParamAssociator::FieldTrialParams* params) const {
84 PickleIterator iter = GetPickleIterator();
85 StringPiece tmp;
86 if (!iter.ReadStringPiece(&tmp))
87 return false;
88 if (!iter.ReadStringPiece(&tmp))
89 return false;
Alexei Svitkine (slow) 2016/11/01 19:13:27 Can you refactor the code to re-use the GetTrialAn
lawrencewu 2016/11/01 19:59:58 Done.
90
91 for (int i = 0; i < kFieldTrialParamLimit; ++i) {
Alexei Svitkine (slow) 2016/11/01 19:13:27 Instead of having an arbitrary limit, I suggest ju
lawrencewu 2016/11/01 19:59:58 Done.
92 StringPiece key;
93 StringPiece value;
94 if (!iter.ReadStringPiece(&key))
95 return true; // No more params to read.
96 if (!iter.ReadStringPiece(&value))
97 return false;
98 (*params)[key.as_string()] = value.as_string();
99 }
100
101 NOTREACHED() << "Hit field trial param limit";
102 return false;
103 }
76 }; 104 };
77 105
78 // Created a time value based on |year|, |month| and |day_of_month| parameters. 106 // Created a time value based on |year|, |month| and |day_of_month| parameters.
79 Time CreateTimeFromParams(int year, int month, int day_of_month) { 107 Time CreateTimeFromParams(int year, int month, int day_of_month) {
80 DCHECK_GT(year, 1970); 108 DCHECK_GT(year, 1970);
81 DCHECK_GT(month, 0); 109 DCHECK_GT(month, 0);
82 DCHECK_LT(month, 13); 110 DCHECK_LT(month, 13);
83 DCHECK_GT(day_of_month, 0); 111 DCHECK_GT(day_of_month, 0);
84 DCHECK_LT(day_of_month, 32); 112 DCHECK_LT(day_of_month, 32);
85 113
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 HANDLE src = allocator->shared_memory()->handle().GetHandle(); 202 HANDLE src = allocator->shared_memory()->handle().GetHandle();
175 ProcessHandle process = GetCurrentProcess(); 203 ProcessHandle process = GetCurrentProcess();
176 DWORD access = SECTION_MAP_READ | SECTION_QUERY; 204 DWORD access = SECTION_MAP_READ | SECTION_QUERY;
177 HANDLE dst; 205 HANDLE dst;
178 if (!::DuplicateHandle(process, src, process, &dst, access, true, 0)) 206 if (!::DuplicateHandle(process, src, process, &dst, access, true, 0))
179 return nullptr; 207 return nullptr;
180 return dst; 208 return dst;
181 } 209 }
182 #endif 210 #endif
183 211
212 bool PickleFieldTrialState(const FieldTrial::State& trial_state,
213 Pickle* pickle) {
214 pickle->WriteString(trial_state.trial_name);
215 pickle->WriteString(trial_state.group_name);
216
217 std::map<std::string, std::string> params;
218 if (!FieldTrialParamAssociator::GetInstance()->GetFieldTrialParams(
219 trial_state.trial_name.as_string(),
220 trial_state.group_name.as_string(), &params)) {
221 return false;
222 }
223
224 for (const auto& param : params) {
225 pickle->WriteString(StringPiece(param.first));
226 pickle->WriteString(StringPiece(param.second));
227 }
228 return true;
229 }
230
184 } // namespace 231 } // namespace
185 232
186 // statics 233 // statics
187 const int FieldTrial::kNotFinalized = -1; 234 const int FieldTrial::kNotFinalized = -1;
188 const int FieldTrial::kDefaultGroupNumber = 0; 235 const int FieldTrial::kDefaultGroupNumber = 0;
189 bool FieldTrial::enable_benchmarking_ = false; 236 bool FieldTrial::enable_benchmarking_ = false;
190 237
191 int FieldTrialList::kNoExpirationYear = 0; 238 int FieldTrialList::kNoExpirationYear = 0;
192 239
193 //------------------------------------------------------------------------------ 240 //------------------------------------------------------------------------------
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after
520 567
521 // static 568 // static
522 std::string FieldTrialList::FindFullName(const std::string& trial_name) { 569 std::string FieldTrialList::FindFullName(const std::string& trial_name) {
523 FieldTrial* field_trial = Find(trial_name); 570 FieldTrial* field_trial = Find(trial_name);
524 if (field_trial) 571 if (field_trial)
525 return field_trial->group_name(); 572 return field_trial->group_name();
526 return std::string(); 573 return std::string();
527 } 574 }
528 575
529 // static 576 // static
577 bool FieldTrialList::FindParams(
578 const std::string& trial_name,
579 FieldTrialParamAssociator::FieldTrialParams* params) {
580 SharedPersistentMemoryAllocator* allocator =
581 global_->field_trial_allocator_.get();
582 if (allocator == nullptr)
583 return false;
584
585 FieldTrial* field_trial = Find(trial_name);
586 if (field_trial->ref_ == SharedPersistentMemoryAllocator::kReferenceNull)
Alexei Svitkine (slow) 2016/11/01 19:13:27 Please add comments above the early returns that e
lawrencewu 2016/11/01 19:59:58 Done.
587 return false;
588
589 FieldTrialEntry* entry = allocator->GetAsObject<FieldTrialEntry>(
590 field_trial->ref_, kFieldTrialType);
591 return entry->GetParams(params);
592 }
593
594 // static
530 bool FieldTrialList::TrialExists(const std::string& trial_name) { 595 bool FieldTrialList::TrialExists(const std::string& trial_name) {
531 return Find(trial_name) != NULL; 596 return Find(trial_name) != NULL;
532 } 597 }
533 598
534 // static 599 // static
535 bool FieldTrialList::IsTrialActive(const std::string& trial_name) { 600 bool FieldTrialList::IsTrialActive(const std::string& trial_name) {
536 FieldTrial* field_trial = Find(trial_name); 601 FieldTrial* field_trial = Find(trial_name);
537 FieldTrial::ActiveGroup active_group; 602 FieldTrial::ActiveGroup active_group;
538 return field_trial && field_trial->GetActiveGroup(&active_group); 603 return field_trial && field_trial->GetActiveGroup(&active_group);
539 } 604 }
(...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after
897 962
898 // Or if we've already added it. 963 // Or if we've already added it.
899 if (field_trial->ref_ != SharedPersistentMemoryAllocator::kReferenceNull) 964 if (field_trial->ref_ != SharedPersistentMemoryAllocator::kReferenceNull)
900 return; 965 return;
901 966
902 FieldTrial::State trial_state; 967 FieldTrial::State trial_state;
903 if (!field_trial->GetState(&trial_state)) 968 if (!field_trial->GetState(&trial_state))
904 return; 969 return;
905 970
906 Pickle pickle; 971 Pickle pickle;
907 pickle.WriteString(trial_state.trial_name); 972 if (!PickleFieldTrialState(trial_state, &pickle))
908 pickle.WriteString(trial_state.group_name); 973 return;
909 974
910 size_t total_size = sizeof(FieldTrialEntry) + pickle.size(); 975 size_t total_size = sizeof(FieldTrialEntry) + pickle.size();
911 SharedPersistentMemoryAllocator::Reference ref = 976 SharedPersistentMemoryAllocator::Reference ref =
912 allocator->Allocate(total_size, kFieldTrialType); 977 allocator->Allocate(total_size, kFieldTrialType);
913 if (ref == SharedPersistentMemoryAllocator::kReferenceNull) 978 if (ref == SharedPersistentMemoryAllocator::kReferenceNull)
914 return; 979 return;
915 980
916 FieldTrialEntry* entry = 981 FieldTrialEntry* entry =
917 allocator->GetAsObject<FieldTrialEntry>(ref, kFieldTrialType); 982 allocator->GetAsObject<FieldTrialEntry>(ref, kFieldTrialType);
918 entry->activated = trial_state.activated; 983 entry->activated = trial_state.activated;
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
972 return; 1037 return;
973 } 1038 }
974 AutoLock auto_lock(global_->lock_); 1039 AutoLock auto_lock(global_->lock_);
975 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name(); 1040 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name();
976 trial->AddRef(); 1041 trial->AddRef();
977 trial->SetTrialRegistered(); 1042 trial->SetTrialRegistered();
978 global_->registered_[trial->trial_name()] = trial; 1043 global_->registered_[trial->trial_name()] = trial;
979 } 1044 }
980 1045
981 } // namespace base 1046 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698