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

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

Issue 2449783007: Use pickle for field trial entries in shared memory (Closed)
Patch Set: address comments 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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"
11 #include "base/build_time.h" 11 #include "base/build_time.h"
12 #include "base/command_line.h" 12 #include "base/command_line.h"
13 #include "base/feature_list.h" 13 #include "base/feature_list.h"
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/metrics/histogram_macros.h" 15 #include "base/metrics/histogram_macros.h"
16 #include "base/pickle.h"
16 #include "base/process/memory.h" 17 #include "base/process/memory.h"
17 #include "base/rand_util.h" 18 #include "base/rand_util.h"
18 #include "base/strings/string_number_conversions.h" 19 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/string_util.h" 20 #include "base/strings/string_util.h"
20 #include "base/strings/stringprintf.h" 21 #include "base/strings/stringprintf.h"
21 #include "base/strings/utf_string_conversions.h" 22 #include "base/strings/utf_string_conversions.h"
22 23
23 namespace base { 24 namespace base {
24 25
25 namespace { 26 namespace {
(...skipping 13 matching lines...) Expand all
39 // crbug.com/653874 40 // crbug.com/653874
40 const bool kUseSharedMemoryForFieldTrials = false; 41 const bool kUseSharedMemoryForFieldTrials = false;
41 42
42 // Constants for the field trial allocator. 43 // Constants for the field trial allocator.
43 const char kAllocatorName[] = "FieldTrialAllocator"; 44 const char kAllocatorName[] = "FieldTrialAllocator";
44 const uint32_t kFieldTrialType = 0xABA17E13 + 1; // SHA1(FieldTrialEntry) v1 45 const uint32_t kFieldTrialType = 0xABA17E13 + 1; // SHA1(FieldTrialEntry) v1
45 #if !defined(OS_NACL) 46 #if !defined(OS_NACL)
46 const size_t kFieldTrialAllocationSize = 4 << 10; // 4 KiB = one page 47 const size_t kFieldTrialAllocationSize = 4 << 10; // 4 KiB = one page
47 #endif 48 #endif
48 49
49 // We create one FieldTrialEntry struct per field trial in shared memory (via 50 // We create one FieldTrialEntry per field trial in shared memory, via
50 // field_trial_allocator_). It contains whether or not it's activated, and the 51 // AddToAllocatorWhileLocked. It contains whether or not it's activated, and a
51 // offset from the start of the allocated memory to the group name. We don't 52 // base::Pickle object that we unpickle and read from.
52 // need the offset into the trial name because that's always a fixed position
53 // from the start of the struct. Two strings will be appended to the end of this
54 // structure in allocated memory, so the result will look like this:
55 // ---------------------------------
56 // | fte | trial_name | group_name |
57 // ---------------------------------
58 struct FieldTrialEntry { 53 struct FieldTrialEntry {
59 bool activated; 54 bool activated;
60 uint32_t group_name_offset; 55 // Size of the pickled structure, NOT the total size of this entry.
56 uint32_t size;
61 57
62 const char* GetTrialName() const { 58 bool GetTrialAndGroupName(StringPiece* trial_name,
Alexei Svitkine (slow) 2016/10/28 15:32:22 Please add a comment, specifically mentioning that
63 const char* src = 59 StringPiece* group_name) const {
64 reinterpret_cast<char*>(const_cast<FieldTrialEntry*>(this)); 60 char* src = reinterpret_cast<char*>(const_cast<FieldTrialEntry*>(this)) +
65 return src + sizeof(FieldTrialEntry); 61 sizeof(FieldTrialEntry);
66 }
67 62
68 const char* GetGroupName() const { 63 Pickle pickle(src, this->size);
Alexei Svitkine (slow) 2016/10/28 15:32:22 Nit: No this->
lawrencewu 2016/10/28 15:38:02 Done.
69 const char* src = 64 PickleIterator pickle_iter(pickle);
70 reinterpret_cast<char*>(const_cast<FieldTrialEntry*>(this)); 65
71 return src + this->group_name_offset; 66 if (!pickle_iter.ReadStringPiece(trial_name))
67 return false;
68 if (!pickle_iter.ReadStringPiece(group_name))
69 return false;
70 return true;
72 } 71 }
73 }; 72 };
74 73
75 // Created a time value based on |year|, |month| and |day_of_month| parameters. 74 // Created a time value based on |year|, |month| and |day_of_month| parameters.
76 Time CreateTimeFromParams(int year, int month, int day_of_month) { 75 Time CreateTimeFromParams(int year, int month, int day_of_month) {
77 DCHECK_GT(year, 1970); 76 DCHECK_GT(year, 1970);
78 DCHECK_GT(month, 0); 77 DCHECK_GT(month, 0);
79 DCHECK_LT(month, 13); 78 DCHECK_LT(month, 13);
80 DCHECK_GT(day_of_month, 0); 79 DCHECK_GT(day_of_month, 0);
81 DCHECK_LT(day_of_month, 32); 80 DCHECK_LT(day_of_month, 32);
(...skipping 709 matching lines...) Expand 10 before | Expand all | Expand 10 after
791 return 0; 790 return 0;
792 AutoLock auto_lock(global_->lock_); 791 AutoLock auto_lock(global_->lock_);
793 return global_->registered_.size(); 792 return global_->registered_.size();
794 } 793 }
795 794
796 // static 795 // static
797 void FieldTrialList::CreateTrialsFromSharedMemory( 796 void FieldTrialList::CreateTrialsFromSharedMemory(
798 std::unique_ptr<SharedMemory> shm) { 797 std::unique_ptr<SharedMemory> shm) {
799 const SharedPersistentMemoryAllocator shalloc(std::move(shm), 0, 798 const SharedPersistentMemoryAllocator shalloc(std::move(shm), 0,
800 kAllocatorName, true); 799 kAllocatorName, true);
801 PersistentMemoryAllocator::Iterator iter(&shalloc); 800 PersistentMemoryAllocator::Iterator mem_iter(&shalloc);
802 801
803 SharedPersistentMemoryAllocator::Reference ref; 802 SharedPersistentMemoryAllocator::Reference ref;
804 while ((ref = iter.GetNextOfType(kFieldTrialType)) != 803 while ((ref = mem_iter.GetNextOfType(kFieldTrialType)) !=
805 SharedPersistentMemoryAllocator::kReferenceNull) { 804 SharedPersistentMemoryAllocator::kReferenceNull) {
806 const FieldTrialEntry* entry = 805 const FieldTrialEntry* entry =
807 shalloc.GetAsObject<const FieldTrialEntry>(ref, kFieldTrialType); 806 shalloc.GetAsObject<const FieldTrialEntry>(ref, kFieldTrialType);
807
808 StringPiece trial_name;
809 StringPiece group_name;
810 if (!entry->GetTrialAndGroupName(&trial_name, &group_name))
811 NOTREACHED();
Alexei Svitkine (slow) 2016/10/28 15:32:22 You can still do a continue after the NOTREACHED j
lawrencewu 2016/10/28 15:38:02 Done.
812
813 // TODO: Convert the API for CreateFieldTrial to take StringPieces.
Alexei Svitkine (slow) 2016/10/28 15:32:22 TODOs should have a username or crbug here. So yo
lawrencewu 2016/10/28 15:38:02 Done.
808 FieldTrial* trial = 814 FieldTrial* trial =
809 CreateFieldTrial(entry->GetTrialName(), entry->GetGroupName()); 815 CreateFieldTrial(trial_name.as_string(), group_name.as_string());
810 816
811 if (entry->activated) { 817 if (entry->activated) {
812 // Call |group()| to mark the trial as "used" and notify observers, if 818 // Call |group()| to mark the trial as "used" and notify observers, if
813 // any. This is useful to ensure that field trials created in child 819 // any. This is useful to ensure that field trials created in child
814 // processes are properly reported in crash reports. 820 // processes are properly reported in crash reports.
815 trial->group(); 821 trial->group();
816 } 822 }
817 } 823 }
818 } 824 }
819 825
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
859 return; 865 return;
860 866
861 // Or if we've already added it. 867 // Or if we've already added it.
862 if (field_trial->ref_ != SharedPersistentMemoryAllocator::kReferenceNull) 868 if (field_trial->ref_ != SharedPersistentMemoryAllocator::kReferenceNull)
863 return; 869 return;
864 870
865 FieldTrial::State trial_state; 871 FieldTrial::State trial_state;
866 if (!field_trial->GetState(&trial_state)) 872 if (!field_trial->GetState(&trial_state))
867 return; 873 return;
868 874
869 size_t trial_name_size = trial_state.trial_name.size() + 1; 875 Pickle pickle;
870 size_t group_name_size = trial_state.group_name.size() + 1; 876 pickle.WriteString(trial_state.trial_name);
871 size_t size = sizeof(FieldTrialEntry) + trial_name_size + group_name_size; 877 pickle.WriteString(trial_state.group_name);
872 878
873 // Allocate just enough memory to fit the FieldTrialEntry struct, trial name, 879 size_t total_size = sizeof(FieldTrialEntry) + pickle.size();
874 // and group name.
875 SharedPersistentMemoryAllocator::Reference ref = 880 SharedPersistentMemoryAllocator::Reference ref =
876 allocator->Allocate(size, kFieldTrialType); 881 allocator->Allocate(total_size, kFieldTrialType);
877 if (ref == SharedPersistentMemoryAllocator::kReferenceNull) 882 if (ref == SharedPersistentMemoryAllocator::kReferenceNull)
878 return; 883 return;
879 884
880 // Calculate offsets into the shared memory segment.
881 FieldTrialEntry* entry = 885 FieldTrialEntry* entry =
882 allocator->GetAsObject<FieldTrialEntry>(ref, kFieldTrialType); 886 allocator->GetAsObject<FieldTrialEntry>(ref, kFieldTrialType);
883 uint32_t trial_name_offset = sizeof(FieldTrialEntry); 887 entry->activated = trial_state.activated;
884 uint32_t group_name_offset = trial_name_offset + trial_name_size; 888 entry->size = pickle.size();
885 889
886 // Copy over the data. 890 // TODO: Modify base::Pickle to be able to write over a section in memory, so
Alexei Svitkine (slow) 2016/10/28 15:32:22 Same comment about the TODO.
lawrencewu 2016/10/28 15:38:02 Done.
887 entry->activated = trial_state.activated; 891 // we can avoid this memcpy.
888 entry->group_name_offset = group_name_offset; 892 char* dst = reinterpret_cast<char*>(entry) + sizeof(FieldTrialEntry);
889 char* trial_name = reinterpret_cast<char*>(entry) + trial_name_offset; 893 memcpy(dst, pickle.data(), pickle.size());
890 char* group_name = reinterpret_cast<char*>(entry) + group_name_offset;
891 memcpy(trial_name, trial_state.trial_name.data(), trial_name_size);
892 memcpy(group_name, trial_state.group_name.data(), group_name_size);
893
894 // Null terminate the strings.
895 trial_name[trial_state.trial_name.size()] = '\0';
896 group_name[trial_state.group_name.size()] = '\0';
897 894
898 allocator->MakeIterable(ref); 895 allocator->MakeIterable(ref);
899 field_trial->ref_ = ref; 896 field_trial->ref_ = ref;
900 } 897 }
901 898
902 // static 899 // static
903 void FieldTrialList::ActivateFieldTrialEntryWhileLocked( 900 void FieldTrialList::ActivateFieldTrialEntryWhileLocked(
904 FieldTrial* field_trial) { 901 FieldTrial* field_trial) {
905 SharedPersistentMemoryAllocator* allocator = 902 SharedPersistentMemoryAllocator* allocator =
906 global_->field_trial_allocator_.get(); 903 global_->field_trial_allocator_.get();
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
944 return; 941 return;
945 } 942 }
946 AutoLock auto_lock(global_->lock_); 943 AutoLock auto_lock(global_->lock_);
947 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name(); 944 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name();
948 trial->AddRef(); 945 trial->AddRef();
949 trial->SetTrialRegistered(); 946 trial->SetTrialRegistered();
950 global_->registered_[trial->trial_name()] = trial; 947 global_->registered_[trial->trial_name()] = trial;
951 } 948 }
952 949
953 } // namespace base 950 } // namespace base
OLDNEW
« 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