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

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

Issue 2546653002: Store and retrieve features from shared memory (Closed)
Patch Set: asvitkine@ comments 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(const char* enable_features_switch,
187 const char* disable_features_switch,
188 CommandLine* cmd_line) {
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 FeatureList* feature_list) {
761 // Fallback to command line if not using shared memory.
762 if (!kUseSharedMemoryForFieldTrials ||
763 !global_->field_trial_allocator_.get()) {
764 return feature_list->InitializeFromCommandLine(
765 command_line.GetSwitchValueASCII(enable_features_switch),
766 command_line.GetSwitchValueASCII(disable_features_switch));
767 }
768
769 feature_list->InitializeFromSharedMemory(
770 global_->field_trial_allocator_.get());
771 }
772
744 #if defined(POSIX_WITH_ZYGOTE) 773 #if defined(POSIX_WITH_ZYGOTE)
745 // static 774 // static
746 bool FieldTrialList::CreateTrialsFromDescriptor(int fd_key) { 775 bool FieldTrialList::CreateTrialsFromDescriptor(int fd_key) {
747 if (!kUseSharedMemoryForFieldTrials) 776 if (!kUseSharedMemoryForFieldTrials)
748 return false; 777 return false;
749 778
750 if (fd_key == -1) 779 if (fd_key == -1)
751 return false; 780 return false;
752 781
753 int fd = GlobalDescriptors::GetInstance()->MaybeGet(fd_key); 782 int fd = GlobalDescriptors::GetInstance()->MaybeGet(fd_key);
(...skipping 29 matching lines...) Expand all
783 // We check for an invalid handle where this gets called. 812 // We check for an invalid handle where this gets called.
784 return global_->readonly_allocator_handle_; 813 return global_->readonly_allocator_handle_;
785 } 814 }
786 return kInvalidPlatformFile; 815 return kInvalidPlatformFile;
787 } 816 }
788 #endif 817 #endif
789 818
790 // static 819 // static
791 void FieldTrialList::CopyFieldTrialStateToFlags( 820 void FieldTrialList::CopyFieldTrialStateToFlags(
792 const char* field_trial_handle_switch, 821 const char* field_trial_handle_switch,
822 const char* enable_features_switch,
823 const char* disable_features_switch,
793 CommandLine* cmd_line) { 824 CommandLine* cmd_line) {
794 // TODO(lawrencewu): Ideally, having the global would be guaranteed. However, 825 // TODO(lawrencewu): Ideally, having the global would be guaranteed. However,
795 // content browser tests currently don't create a FieldTrialList because they 826 // content browser tests currently don't create a FieldTrialList because they
796 // don't run ChromeBrowserMainParts code where it's done for Chrome. 827 // don't run ChromeBrowserMainParts code where it's done for Chrome.
797 if (!global_) 828 if (!global_)
798 return; 829 return;
799 830
800 #if defined(OS_WIN) || defined(POSIX_WITH_ZYGOTE) 831 #if defined(OS_WIN) || defined(POSIX_WITH_ZYGOTE)
801 // Use shared memory to pass the state if the feature is enabled, otherwise 832 // 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. 833 // fallback to passing it via the command line as a string.
803 if (kUseSharedMemoryForFieldTrials) { 834 if (kUseSharedMemoryForFieldTrials) {
804 InstantiateFieldTrialAllocatorIfNeeded(); 835 InstantiateFieldTrialAllocatorIfNeeded();
805 // If the readonly handle didn't get duplicated properly, then fallback to 836 // If the readonly handle didn't get duplicated properly, then fallback to
806 // original behavior. 837 // original behavior.
807 if (global_->readonly_allocator_handle_ == kInvalidPlatformFile) { 838 if (global_->readonly_allocator_handle_ == kInvalidPlatformFile) {
808 AddForceFieldTrialsFlag(cmd_line); 839 AddFeatureAndFieldTrialFlags(enable_features_switch,
840 disable_features_switch, cmd_line);
809 return; 841 return;
810 } 842 }
811 843
812 global_->field_trial_allocator_->UpdateTrackingHistograms(); 844 global_->field_trial_allocator_->UpdateTrackingHistograms();
813 845
814 #if defined(OS_WIN) 846 #if defined(OS_WIN)
815 // We need to pass a named anonymous handle to shared memory over the 847 // 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 848 // 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 849 // 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 850 // -- we dup the fd into a fixed fd kFieldTrialDescriptor, so we can just
819 // look it up there. 851 // look it up there.
820 // PlatformFile is typedef'd to HANDLE which is typedef'd to void *. We 852 // 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 853 // 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 854 // the int, and pass it as a command-line flag. The child process will do
823 // the reverse conversions to retrieve the handle. See 855 // the reverse conversions to retrieve the handle. See
824 // http://stackoverflow.com/a/153077 856 // http://stackoverflow.com/a/153077
825 auto uintptr_handle = 857 auto uintptr_handle =
826 reinterpret_cast<uintptr_t>(global_->readonly_allocator_handle_); 858 reinterpret_cast<uintptr_t>(global_->readonly_allocator_handle_);
827 std::string field_trial_handle = std::to_string(uintptr_handle); 859 std::string field_trial_handle = std::to_string(uintptr_handle);
828 cmd_line->AppendSwitchASCII(field_trial_handle_switch, field_trial_handle); 860 cmd_line->AppendSwitchASCII(field_trial_handle_switch, field_trial_handle);
829 #endif 861 #endif
830 return; 862 return;
831 } 863 }
832 #endif 864 #endif
833 865
834 AddForceFieldTrialsFlag(cmd_line); 866 AddFeatureAndFieldTrialFlags(enable_features_switch, disable_features_switch,
867 cmd_line);
835 } 868 }
836 869
837 // static 870 // static
838 FieldTrial* FieldTrialList::CreateFieldTrial( 871 FieldTrial* FieldTrialList::CreateFieldTrial(
839 const std::string& name, 872 const std::string& name,
840 const std::string& group_name) { 873 const std::string& group_name) {
841 DCHECK(global_); 874 DCHECK(global_);
842 DCHECK_GE(name.size(), 0u); 875 DCHECK_GE(name.size(), 0u);
843 DCHECK_GE(group_name.size(), 0u); 876 DCHECK_GE(group_name.size(), 0u);
844 if (name.empty() || group_name.empty() || !global_) 877 if (name.empty() || group_name.empty() || !global_)
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
1000 1033
1001 global_->field_trial_allocator_.reset( 1034 global_->field_trial_allocator_.reset(
1002 new FieldTrialAllocator(std::move(shm), 0, kAllocatorName, false)); 1035 new FieldTrialAllocator(std::move(shm), 0, kAllocatorName, false));
1003 global_->field_trial_allocator_->CreateTrackingHistograms(kAllocatorName); 1036 global_->field_trial_allocator_->CreateTrackingHistograms(kAllocatorName);
1004 1037
1005 // Add all existing field trials. 1038 // Add all existing field trials.
1006 for (const auto& registered : global_->registered_) { 1039 for (const auto& registered : global_->registered_) {
1007 AddToAllocatorWhileLocked(registered.second); 1040 AddToAllocatorWhileLocked(registered.second);
1008 } 1041 }
1009 1042
1043 // Add all existing features.
1044 FeatureList::GetInstance()->AddFeaturesToAllocator(
1045 global_->field_trial_allocator_.get());
1046
1010 #if defined(OS_WIN) || defined(POSIX_WITH_ZYGOTE) 1047 #if defined(OS_WIN) || defined(POSIX_WITH_ZYGOTE)
1011 // Set |readonly_allocator_handle_| so we can pass it to be inherited and 1048 // Set |readonly_allocator_handle_| so we can pass it to be inherited and
1012 // via the command line. 1049 // via the command line.
1013 global_->readonly_allocator_handle_ = 1050 global_->readonly_allocator_handle_ =
1014 CreateReadOnlyHandle(global_->field_trial_allocator_.get()); 1051 CreateReadOnlyHandle(global_->field_trial_allocator_.get());
1015 #endif 1052 #endif
1016 } 1053 }
1017 #endif 1054 #endif
1018 1055
1019 // static 1056 // static
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
1111 return; 1148 return;
1112 } 1149 }
1113 AutoLock auto_lock(global_->lock_); 1150 AutoLock auto_lock(global_->lock_);
1114 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name(); 1151 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name();
1115 trial->AddRef(); 1152 trial->AddRef();
1116 trial->SetTrialRegistered(); 1153 trial->SetTrialRegistered();
1117 global_->registered_[trial->trial_name()] = trial; 1154 global_->registered_[trial->trial_name()] = trial;
1118 } 1155 }
1119 1156
1120 } // namespace base 1157 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698