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

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

Issue 2546653002: Store and retrieve features from shared memory (Closed)
Patch Set: Address comments and fallback to command line. Created 4 years 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"
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"
14 #include "base/logging.h" 13 #include "base/logging.h"
15 #include "base/pickle.h" 14 #include "base/pickle.h"
16 #include "base/process/memory.h" 15 #include "base/process/memory.h"
17 #include "base/rand_util.h" 16 #include "base/rand_util.h"
18 #include "base/strings/string_number_conversions.h" 17 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/string_util.h" 18 #include "base/strings/string_util.h"
20 #include "base/strings/stringprintf.h" 19 #include "base/strings/stringprintf.h"
21 #include "base/strings/utf_string_conversions.h" 20 #include "base/strings/utf_string_conversions.h"
22 21
23 // On systems that use the zygote process to spawn child processes, we must 22 // On systems that use the zygote process to spawn child processes, we must
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
177 trials_string_piece.substr(next_item, name_end - next_item); 176 trials_string_piece.substr(next_item, name_end - next_item);
178 entry.group_name = 177 entry.group_name =
179 trials_string_piece.substr(name_end + 1, group_name_end - name_end - 1); 178 trials_string_piece.substr(name_end + 1, group_name_end - name_end - 1);
180 next_item = group_name_end + 1; 179 next_item = group_name_end + 1;
181 180
182 entries->push_back(std::move(entry)); 181 entries->push_back(std::move(entry));
183 } 182 }
184 return true; 183 return true;
185 } 184 }
186 185
187 void AddForceFieldTrialsFlag(CommandLine* cmd_line) { 186 void AddFeatureAndFieldTrialFlags(CommandLine* cmd_line,
187 const char* enable_features_switch,
188 const char* disable_features_switch) {
189 std::string enabled_features;
190 std::string disabled_features;
191 FeatureList::GetInstance()->GetFeatureOverrides(&enabled_features,
192 &disabled_features);
193
194 if (!enabled_features.empty())
195 cmd_line->AppendSwitchASCII(enable_features_switch, enabled_features);
196 if (!disabled_features.empty())
197 cmd_line->AppendSwitchASCII(disable_features_switch, disabled_features);
198
188 std::string field_trial_states; 199 std::string field_trial_states;
189 FieldTrialList::AllStatesToString(&field_trial_states); 200 FieldTrialList::AllStatesToString(&field_trial_states);
190 if (!field_trial_states.empty()) { 201 if (!field_trial_states.empty()) {
191 cmd_line->AppendSwitchASCII(switches::kForceFieldTrials, 202 cmd_line->AppendSwitchASCII(switches::kForceFieldTrials,
192 field_trial_states); 203 field_trial_states);
193 } 204 }
194 } 205 }
195 206
196 #if defined(OS_WIN) 207 #if defined(OS_WIN)
197 HANDLE CreateReadOnlyHandle(FieldTrialList::FieldTrialAllocator* allocator) { 208 HANDLE CreateReadOnlyHandle(FieldTrialList::FieldTrialAllocator* allocator) {
(...skipping 536 matching lines...) Expand 10 before | Expand all | Expand 10 after
734 #endif 745 #endif
735 746
736 if (cmd_line.HasSwitch(switches::kForceFieldTrials)) { 747 if (cmd_line.HasSwitch(switches::kForceFieldTrials)) {
737 bool result = FieldTrialList::CreateTrialsFromString( 748 bool result = FieldTrialList::CreateTrialsFromString(
738 cmd_line.GetSwitchValueASCII(switches::kForceFieldTrials), 749 cmd_line.GetSwitchValueASCII(switches::kForceFieldTrials),
739 std::set<std::string>()); 750 std::set<std::string>());
740 DCHECK(result); 751 DCHECK(result);
741 } 752 }
742 } 753 }
743 754
755 // static
756 void FieldTrialList::CreateFeaturesFromCommandLine(
757 const base::CommandLine& command_line,
758 const char* enable_features_switch,
759 const char* disable_features_switch,
760 std::unique_ptr<FeatureList>& feature_list) {
761 // Fallback to command line if not using shared memory.
762 if (!kUseSharedMemoryForFieldTrials || !global_->field_trial_allocator_.get())
763 return feature_list->InitializeFromCommandLine(
764 command_line.GetSwitchValueASCII(enable_features_switch),
765 command_line.GetSwitchValueASCII(disable_features_switch));
766
767 feature_list->InitializeFromSharedMemory(
768 global_->field_trial_allocator_.get());
769 }
770
744 #if defined(POSIX_WITH_ZYGOTE) 771 #if defined(POSIX_WITH_ZYGOTE)
745 // static 772 // static
746 bool FieldTrialList::CreateTrialsFromDescriptor(int fd_key) { 773 bool FieldTrialList::CreateTrialsFromDescriptor(int fd_key) {
747 if (!kUseSharedMemoryForFieldTrials) 774 if (!kUseSharedMemoryForFieldTrials)
748 return false; 775 return false;
749 776
750 if (fd_key == -1) 777 if (fd_key == -1)
751 return false; 778 return false;
752 779
753 int fd = GlobalDescriptors::GetInstance()->MaybeGet(fd_key); 780 int fd = GlobalDescriptors::GetInstance()->MaybeGet(fd_key);
(...skipping 29 matching lines...) Expand all
783 // We check for an invalid handle where this gets called. 810 // We check for an invalid handle where this gets called.
784 return global_->readonly_allocator_handle_; 811 return global_->readonly_allocator_handle_;
785 } 812 }
786 return kInvalidPlatformFile; 813 return kInvalidPlatformFile;
787 } 814 }
788 #endif 815 #endif
789 816
790 // static 817 // static
791 void FieldTrialList::CopyFieldTrialStateToFlags( 818 void FieldTrialList::CopyFieldTrialStateToFlags(
792 const char* field_trial_handle_switch, 819 const char* field_trial_handle_switch,
820 const char* enable_features_switch,
821 const char* disable_features_switch,
793 CommandLine* cmd_line) { 822 CommandLine* cmd_line) {
794 // TODO(lawrencewu): Ideally, having the global would be guaranteed. However, 823 // TODO(lawrencewu): Ideally, having the global would be guaranteed. However,
795 // content browser tests currently don't create a FieldTrialList because they 824 // content browser tests currently don't create a FieldTrialList because they
796 // don't run ChromeBrowserMainParts code where it's done for Chrome. 825 // don't run ChromeBrowserMainParts code where it's done for Chrome.
797 if (!global_) 826 if (!global_)
798 return; 827 return;
799 828
800 #if defined(OS_WIN) || defined(POSIX_WITH_ZYGOTE) 829 #if defined(OS_WIN) || defined(POSIX_WITH_ZYGOTE)
801 // Use shared memory to pass the state if the feature is enabled, otherwise 830 // Use shared memory to pass the state if the feature is enabled, otherwise
802 // fallback to passing it via the command line as a string. 831 // fallback to passing it via the command line as a string.
803 if (kUseSharedMemoryForFieldTrials) { 832 if (kUseSharedMemoryForFieldTrials) {
804 InstantiateFieldTrialAllocatorIfNeeded(); 833 InstantiateFieldTrialAllocatorIfNeeded();
805 // If the readonly handle didn't get duplicated properly, then fallback to 834 // If the readonly handle didn't get duplicated properly, then fallback to
806 // original behavior. 835 // original behavior.
807 if (global_->readonly_allocator_handle_ == kInvalidPlatformFile) { 836 if (global_->readonly_allocator_handle_ == kInvalidPlatformFile) {
808 AddForceFieldTrialsFlag(cmd_line); 837 AddFeatureAndFieldTrialFlags(cmd_line, enable_features_switch,
838 disable_features_switch);
809 return; 839 return;
810 } 840 }
811 841
812 global_->field_trial_allocator_->UpdateTrackingHistograms(); 842 global_->field_trial_allocator_->UpdateTrackingHistograms();
813 843
814 #if defined(OS_WIN) 844 #if defined(OS_WIN)
815 // We need to pass a named anonymous handle to shared memory over the 845 // We need to pass a named anonymous handle to shared memory over the
816 // command line on Windows, since the child doesn't know which of the 846 // command line on Windows, since the child doesn't know which of the
817 // handles it inherited it should open. On POSIX, we don't need to do this 847 // handles it inherited it should open. On POSIX, we don't need to do this
818 // -- we dup the fd into a fixed fd kFieldTrialDescriptor, so we can just 848 // -- we dup the fd into a fixed fd kFieldTrialDescriptor, so we can just
819 // look it up there. 849 // look it up there.
820 // PlatformFile is typedef'd to HANDLE which is typedef'd to void *. We 850 // PlatformFile is typedef'd to HANDLE which is typedef'd to void *. We
821 // basically cast the handle into an int (uintptr_t, to be exact), stringify 851 // basically cast the handle into an int (uintptr_t, to be exact), stringify
822 // the int, and pass it as a command-line flag. The child process will do 852 // the int, and pass it as a command-line flag. The child process will do
823 // the reverse conversions to retrieve the handle. See 853 // the reverse conversions to retrieve the handle. See
824 // http://stackoverflow.com/a/153077 854 // http://stackoverflow.com/a/153077
825 auto uintptr_handle = 855 auto uintptr_handle =
826 reinterpret_cast<uintptr_t>(global_->readonly_allocator_handle_); 856 reinterpret_cast<uintptr_t>(global_->readonly_allocator_handle_);
827 std::string field_trial_handle = std::to_string(uintptr_handle); 857 std::string field_trial_handle = std::to_string(uintptr_handle);
828 cmd_line->AppendSwitchASCII(field_trial_handle_switch, field_trial_handle); 858 cmd_line->AppendSwitchASCII(field_trial_handle_switch, field_trial_handle);
829 #endif 859 #endif
830 return; 860 return;
831 } 861 }
832 #endif 862 #endif
833 863
834 AddForceFieldTrialsFlag(cmd_line); 864 AddFeatureAndFieldTrialFlags(cmd_line, enable_features_switch,
865 disable_features_switch);
835 } 866 }
836 867
837 // static 868 // static
838 FieldTrial* FieldTrialList::CreateFieldTrial( 869 FieldTrial* FieldTrialList::CreateFieldTrial(
839 const std::string& name, 870 const std::string& name,
840 const std::string& group_name) { 871 const std::string& group_name) {
841 DCHECK(global_); 872 DCHECK(global_);
842 DCHECK_GE(name.size(), 0u); 873 DCHECK_GE(name.size(), 0u);
843 DCHECK_GE(group_name.size(), 0u); 874 DCHECK_GE(group_name.size(), 0u);
844 if (name.empty() || group_name.empty() || !global_) 875 if (name.empty() || group_name.empty() || !global_)
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
1000 1031
1001 global_->field_trial_allocator_.reset( 1032 global_->field_trial_allocator_.reset(
1002 new FieldTrialAllocator(std::move(shm), 0, kAllocatorName, false)); 1033 new FieldTrialAllocator(std::move(shm), 0, kAllocatorName, false));
1003 global_->field_trial_allocator_->CreateTrackingHistograms(kAllocatorName); 1034 global_->field_trial_allocator_->CreateTrackingHistograms(kAllocatorName);
1004 1035
1005 // Add all existing field trials. 1036 // Add all existing field trials.
1006 for (const auto& registered : global_->registered_) { 1037 for (const auto& registered : global_->registered_) {
1007 AddToAllocatorWhileLocked(registered.second); 1038 AddToAllocatorWhileLocked(registered.second);
1008 } 1039 }
1009 1040
1041 // Add all existing features.
1042 FeatureList::GetInstance()->AddFeaturesToAllocator(
1043 global_->field_trial_allocator_.get());
1044
1010 #if defined(OS_WIN) || defined(POSIX_WITH_ZYGOTE) 1045 #if defined(OS_WIN) || defined(POSIX_WITH_ZYGOTE)
1011 // Set |readonly_allocator_handle_| so we can pass it to be inherited and 1046 // Set |readonly_allocator_handle_| so we can pass it to be inherited and
1012 // via the command line. 1047 // via the command line.
1013 global_->readonly_allocator_handle_ = 1048 global_->readonly_allocator_handle_ =
1014 CreateReadOnlyHandle(global_->field_trial_allocator_.get()); 1049 CreateReadOnlyHandle(global_->field_trial_allocator_.get());
1015 #endif 1050 #endif
1016 } 1051 }
1017 #endif 1052 #endif
1018 1053
1019 // static 1054 // static
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
1111 return; 1146 return;
1112 } 1147 }
1113 AutoLock auto_lock(global_->lock_); 1148 AutoLock auto_lock(global_->lock_);
1114 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name(); 1149 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name();
1115 trial->AddRef(); 1150 trial->AddRef();
1116 trial->SetTrialRegistered(); 1151 trial->SetTrialRegistered();
1117 global_->registered_[trial->trial_name()] = trial; 1152 global_->registered_[trial->trial_name()] = trial;
1118 } 1153 }
1119 1154
1120 } // namespace base 1155 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698