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

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

Issue 2530573002: Share field trial allocator on zygote-using Linuxes (Closed)
Patch Set: fix ifdef 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 #if defined(OS_POSIX) && !defined(OS_NACL) && !defined(OS_MACOSX) && \
6 !defined(OS_ANDROID)
7 #define POSIX_WITH_ZYGOTE 1
8 #endif
Alexei Svitkine (slow) 2016/11/24 17:44:34 Not At the top of the file - put it after all the
lawrencewu 2016/11/24 18:16:13 Done.
9
5 #include "base/metrics/field_trial.h" 10 #include "base/metrics/field_trial.h"
6 11
7 #include <algorithm> 12 #include <algorithm>
8 #include <utility> 13 #include <utility>
9 14
10 #include "base/base_switches.h" 15 #include "base/base_switches.h"
11 #include "base/build_time.h" 16 #include "base/build_time.h"
12 #include "base/command_line.h" 17 #include "base/command_line.h"
13 #include "base/debug/alias.h" 18 #include "base/debug/alias.h"
14 #include "base/feature_list.h" 19 #include "base/feature_list.h"
15 #include "base/logging.h" 20 #include "base/logging.h"
16 #include "base/pickle.h" 21 #include "base/pickle.h"
17 #include "base/process/memory.h" 22 #include "base/process/memory.h"
18 #include "base/rand_util.h" 23 #include "base/rand_util.h"
19 #include "base/strings/string_number_conversions.h" 24 #include "base/strings/string_number_conversions.h"
20 #include "base/strings/string_util.h" 25 #include "base/strings/string_util.h"
21 #include "base/strings/stringprintf.h" 26 #include "base/strings/stringprintf.h"
22 #include "base/strings/utf_string_conversions.h" 27 #include "base/strings/utf_string_conversions.h"
23 28
29 #if defined(POSIX_WITH_ZYGOTE)
30 #include "base/posix/global_descriptors.h"
31 #endif
32
24 namespace base { 33 namespace base {
25 34
26 namespace { 35 namespace {
27 36
28 // Define a separator character to use when creating a persistent form of an 37 // Define a separator character to use when creating a persistent form of an
29 // instance. This is intended for use as a command line argument, passed to a 38 // instance. This is intended for use as a command line argument, passed to a
30 // second process to mimic our state (i.e., provide the same group name). 39 // second process to mimic our state (i.e., provide the same group name).
31 const char kPersistentStringSeparator = '/'; // Currently a slash. 40 const char kPersistentStringSeparator = '/'; // Currently a slash.
32 41
33 // Define a marker character to be used as a prefix to a trial name on the 42 // Define a marker character to be used as a prefix to a trial name on the
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 HANDLE src = allocator->shared_memory()->handle().GetHandle(); 240 HANDLE src = allocator->shared_memory()->handle().GetHandle();
232 ProcessHandle process = GetCurrentProcess(); 241 ProcessHandle process = GetCurrentProcess();
233 DWORD access = SECTION_MAP_READ | SECTION_QUERY; 242 DWORD access = SECTION_MAP_READ | SECTION_QUERY;
234 HANDLE dst; 243 HANDLE dst;
235 if (!::DuplicateHandle(process, src, process, &dst, access, true, 0)) 244 if (!::DuplicateHandle(process, src, process, &dst, access, true, 0))
236 return nullptr; 245 return nullptr;
237 return dst; 246 return dst;
238 } 247 }
239 #endif 248 #endif
240 249
250 #if defined(POSIX_WITH_ZYGOTE)
251 int CreateReadOnlyHandle(FieldTrialList::FieldTrialAllocator* allocator) {
252 SharedMemoryHandle new_handle;
253 allocator->shared_memory()->ShareReadOnlyToProcess(GetCurrentProcessHandle(),
254 &new_handle);
255 return SharedMemory::GetFdFromSharedMemoryHandle(new_handle);
256 }
257 #endif
258
241 } // namespace 259 } // namespace
242 260
243 // statics 261 // statics
244 const int FieldTrial::kNotFinalized = -1; 262 const int FieldTrial::kNotFinalized = -1;
245 const int FieldTrial::kDefaultGroupNumber = 0; 263 const int FieldTrial::kDefaultGroupNumber = 0;
246 bool FieldTrial::enable_benchmarking_ = false; 264 bool FieldTrial::enable_benchmarking_ = false;
247 265
248 int FieldTrialList::kNoExpirationYear = 0; 266 int FieldTrialList::kNoExpirationYear = 0;
249 267
250 //------------------------------------------------------------------------------ 268 //------------------------------------------------------------------------------
(...skipping 482 matching lines...) Expand 10 before | Expand all | Expand 10 after
733 } 751 }
734 return true; 752 return true;
735 } 753 }
736 754
737 // static 755 // static
738 void FieldTrialList::CreateTrialsFromCommandLine( 756 void FieldTrialList::CreateTrialsFromCommandLine(
739 const CommandLine& cmd_line, 757 const CommandLine& cmd_line,
740 const char* field_trial_handle_switch) { 758 const char* field_trial_handle_switch) {
741 global_->create_trials_from_command_line_called_ = true; 759 global_->create_trials_from_command_line_called_ = true;
742 760
743 #if defined(OS_WIN) && !defined(OS_NACL)
744 if (cmd_line.HasSwitch(field_trial_handle_switch)) { 761 if (cmd_line.HasSwitch(field_trial_handle_switch)) {
745 std::string arg = cmd_line.GetSwitchValueASCII(field_trial_handle_switch); 762 std::string handle_switch =
746 int field_trial_handle = std::stoi(arg); 763 cmd_line.GetSwitchValueASCII(field_trial_handle_switch);
747 HANDLE handle = reinterpret_cast<HANDLE>(field_trial_handle); 764 bool result = CreateTrialsFromHandleSwitch(handle_switch);
748 bool result = CreateTrialsFromWindowsHandle(handle);
749 DCHECK(result); 765 DCHECK(result);
750 } 766 }
751 #endif
752 767
753 if (cmd_line.HasSwitch(switches::kForceFieldTrials)) { 768 if (cmd_line.HasSwitch(switches::kForceFieldTrials)) {
754 bool result = FieldTrialList::CreateTrialsFromString( 769 bool result = FieldTrialList::CreateTrialsFromString(
755 cmd_line.GetSwitchValueASCII(switches::kForceFieldTrials), 770 cmd_line.GetSwitchValueASCII(switches::kForceFieldTrials),
756 std::set<std::string>()); 771 std::set<std::string>());
757 DCHECK(result); 772 DCHECK(result);
758 } 773 }
759 } 774 }
760 775
761 #if defined(OS_WIN) 776 #if defined(OS_WIN)
762 // static 777 // static
763 void FieldTrialList::AppendFieldTrialHandleIfNeeded( 778 void FieldTrialList::AppendFieldTrialHandleIfNeeded(
764 HandlesToInheritVector* handles) { 779 HandlesToInheritVector* handles) {
765 if (!global_) 780 if (!global_)
766 return; 781 return;
767 if (kUseSharedMemoryForFieldTrials) { 782 if (kUseSharedMemoryForFieldTrials) {
768 InstantiateFieldTrialAllocatorIfNeeded(); 783 InstantiateFieldTrialAllocatorIfNeeded();
769 if (global_->readonly_allocator_handle_) 784 if (global_->readonly_allocator_handle_)
770 handles->push_back(global_->readonly_allocator_handle_); 785 handles->push_back(global_->readonly_allocator_handle_);
771 } 786 }
772 } 787 }
773 #endif 788 #endif
774 789
790 #if defined(OS_POSIX) && !defined(OS_NACL)
791 // static
792 int FieldTrialList::GetFieldTrialHandle() {
793 if (!global_)
794 return -1;
795 if (kUseSharedMemoryForFieldTrials) {
796 InstantiateFieldTrialAllocatorIfNeeded();
797 if (global_->readonly_allocator_handle_ != -1)
798 return global_->readonly_allocator_handle_;
799 }
800 return -1;
801 }
802 #endif
803
775 // static 804 // static
776 void FieldTrialList::CopyFieldTrialStateToFlags( 805 void FieldTrialList::CopyFieldTrialStateToFlags(
777 const char* field_trial_handle_switch, 806 const char* field_trial_handle_switch,
778 CommandLine* cmd_line) { 807 CommandLine* cmd_line) {
779 // TODO(lawrencewu): Ideally, having the global would be guaranteed. However, 808 // TODO(lawrencewu): Ideally, having the global would be guaranteed. However,
780 // content browser tests currently don't create a FieldTrialList because they 809 // content browser tests currently don't create a FieldTrialList because they
781 // don't run ChromeBrowserMainParts code where it's done for Chrome. 810 // don't run ChromeBrowserMainParts code where it's done for Chrome.
782 if (!global_) 811 if (!global_)
783 return; 812 return;
784 813
(...skipping 15 matching lines...) Expand all
800 // retrieve the handle. See http://stackoverflow.com/a/153077 829 // retrieve the handle. See http://stackoverflow.com/a/153077
801 auto uintptr_handle = 830 auto uintptr_handle =
802 reinterpret_cast<uintptr_t>(global_->readonly_allocator_handle_); 831 reinterpret_cast<uintptr_t>(global_->readonly_allocator_handle_);
803 std::string field_trial_handle = std::to_string(uintptr_handle); 832 std::string field_trial_handle = std::to_string(uintptr_handle);
804 cmd_line->AppendSwitchASCII(field_trial_handle_switch, field_trial_handle); 833 cmd_line->AppendSwitchASCII(field_trial_handle_switch, field_trial_handle);
805 global_->field_trial_allocator_->UpdateTrackingHistograms(); 834 global_->field_trial_allocator_->UpdateTrackingHistograms();
806 return; 835 return;
807 } 836 }
808 #endif 837 #endif
809 838
839 #if defined(POSIX_WITH_ZYGOTE)
840 // Use shared memory to pass the state if the feature is enabled, otherwise
841 // fallback to passing it via the command line as a string.
842 if (kUseSharedMemoryForFieldTrials) {
843 InstantiateFieldTrialAllocatorIfNeeded();
844 // If the readonly handle didn't get duplicated properly, then fallback to
845 // original behavior.
846 if (global_->readonly_allocator_handle_ == -1) {
847 AddForceFieldTrialsFlag(cmd_line);
848 return;
849 }
850
851 std::string field_trial_handle =
852 std::to_string(global_->readonly_allocator_handle_);
853 cmd_line->AppendSwitchASCII(field_trial_handle_switch, field_trial_handle);
854 global_->field_trial_allocator_->UpdateTrackingHistograms();
855 return;
856 }
857 #endif
858
810 AddForceFieldTrialsFlag(cmd_line); 859 AddForceFieldTrialsFlag(cmd_line);
811 } 860 }
812 861
813 // static 862 // static
814 FieldTrial* FieldTrialList::CreateFieldTrial( 863 FieldTrial* FieldTrialList::CreateFieldTrial(
815 const std::string& name, 864 const std::string& name,
816 const std::string& group_name) { 865 const std::string& group_name) {
817 DCHECK(global_); 866 DCHECK(global_);
818 DCHECK_GE(name.size(), 0u); 867 DCHECK_GE(name.size(), 0u);
819 DCHECK_GE(group_name.size(), 0u); 868 DCHECK_GE(group_name.size(), 0u);
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
886 } 935 }
887 936
888 // static 937 // static
889 size_t FieldTrialList::GetFieldTrialCount() { 938 size_t FieldTrialList::GetFieldTrialCount() {
890 if (!global_) 939 if (!global_)
891 return 0; 940 return 0;
892 AutoLock auto_lock(global_->lock_); 941 AutoLock auto_lock(global_->lock_);
893 return global_->registered_.size(); 942 return global_->registered_.size();
894 } 943 }
895 944
945 // static
946 bool FieldTrialList::CreateTrialsFromHandleSwitch(
947 const std::string& handle_switch) {
896 #if defined(OS_WIN) 948 #if defined(OS_WIN)
949 int field_trial_handle = std::stoi(handle_switch);
950 HANDLE handle = reinterpret_cast<HANDLE>(field_trial_handle);
951 SharedMemoryHandle shm_handle(handle, GetCurrentProcId());
952 return FieldTrialList::CreateTrialsFromSharedMemoryHandle(shm_handle);
953 #endif
954
955 #if defined(POSIX_WITH_ZYGOTE)
956 int fd_key = std::stoi(handle_switch);
957 int fd = GlobalDescriptors::GetInstance()->Get(fd_key);
958 SharedMemoryHandle shm_handle(fd, true);
959 return FieldTrialList::CreateTrialsFromSharedMemoryHandle(shm_handle);
960 #endif
961
962 #if !defined(OS_WIN) && !defined(POSIX_WITH_ZYGOTE)
963 return false;
964 #endif
965 }
966
967 #if !defined(OS_NACL)
897 // static 968 // static
898 bool FieldTrialList::CreateTrialsFromWindowsHandle(HANDLE handle) { 969 bool FieldTrialList::CreateTrialsFromSharedMemoryHandle(
899 SharedMemoryHandle shm_handle(handle, GetCurrentProcId()); 970 SharedMemoryHandle shm_handle) {
900
901 // shm gets deleted when it gets out of scope, but that's OK because we need 971 // shm gets deleted when it gets out of scope, but that's OK because we need
902 // it only for the duration of this method. 972 // it only for the duration of this method.
903 std::unique_ptr<SharedMemory> shm(new SharedMemory(shm_handle, true)); 973 std::unique_ptr<SharedMemory> shm(new SharedMemory(shm_handle, true));
904 if (!shm.get()->Map(kFieldTrialAllocationSize)) 974 if (!shm.get()->Map(kFieldTrialAllocationSize))
905 TerminateBecauseOutOfMemory(kFieldTrialAllocationSize); 975 TerminateBecauseOutOfMemory(kFieldTrialAllocationSize);
906 976
907 return FieldTrialList::CreateTrialsFromSharedMemory(std::move(shm)); 977 return FieldTrialList::CreateTrialsFromSharedMemory(std::move(shm));
908 } 978 }
909 #endif 979 #endif
910 980
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
980 #if !defined(OS_NACL) 1050 #if !defined(OS_NACL)
981 // static 1051 // static
982 void FieldTrialList::InstantiateFieldTrialAllocatorIfNeeded() { 1052 void FieldTrialList::InstantiateFieldTrialAllocatorIfNeeded() {
983 if (!global_) 1053 if (!global_)
984 return; 1054 return;
985 AutoLock auto_lock(global_->lock_); 1055 AutoLock auto_lock(global_->lock_);
986 // Create the allocator if not already created and add all existing trials. 1056 // Create the allocator if not already created and add all existing trials.
987 if (global_->field_trial_allocator_ != nullptr) 1057 if (global_->field_trial_allocator_ != nullptr)
988 return; 1058 return;
989 1059
1060 SharedMemoryCreateOptions options;
1061 options.size = kFieldTrialAllocationSize;
1062 options.share_read_only = true;
1063
990 std::unique_ptr<SharedMemory> shm(new SharedMemory()); 1064 std::unique_ptr<SharedMemory> shm(new SharedMemory());
991 if (!shm->CreateAndMapAnonymous(kFieldTrialAllocationSize)) 1065 if (!shm->Create(options))
1066 TerminateBecauseOutOfMemory(kFieldTrialAllocationSize);
1067
1068 if (!shm->Map(kFieldTrialAllocationSize))
992 TerminateBecauseOutOfMemory(kFieldTrialAllocationSize); 1069 TerminateBecauseOutOfMemory(kFieldTrialAllocationSize);
993 1070
994 global_->field_trial_allocator_.reset( 1071 global_->field_trial_allocator_.reset(
995 new FieldTrialAllocator(std::move(shm), 0, kAllocatorName, false)); 1072 new FieldTrialAllocator(std::move(shm), 0, kAllocatorName, false));
996 global_->field_trial_allocator_->CreateTrackingHistograms(kAllocatorName); 1073 global_->field_trial_allocator_->CreateTrackingHistograms(kAllocatorName);
997 1074
998 // Add all existing field trials. 1075 // Add all existing field trials.
999 for (const auto& registered : global_->registered_) { 1076 for (const auto& registered : global_->registered_) {
1000 AddToAllocatorWhileLocked(registered.second); 1077 AddToAllocatorWhileLocked(registered.second);
1001 } 1078 }
1002 1079
1003 #if defined(OS_WIN) 1080 #if defined(OS_WIN) || defined(POSIX_WITH_ZYGOTE)
1004 // Set |readonly_allocator_handle_| so we can pass it to be inherited and 1081 // Set |readonly_allocator_handle_| so we can pass it to be inherited and
1005 // via the command line. 1082 // via the command line.
1006 global_->readonly_allocator_handle_ = 1083 global_->readonly_allocator_handle_ =
1007 CreateReadOnlyHandle(global_->field_trial_allocator_.get()); 1084 CreateReadOnlyHandle(global_->field_trial_allocator_.get());
1008 #endif 1085 #endif
1009 } 1086 }
1010 #endif 1087 #endif
1011 1088
1012 // static 1089 // static
1013 void FieldTrialList::AddToAllocatorWhileLocked(FieldTrial* field_trial) { 1090 void FieldTrialList::AddToAllocatorWhileLocked(FieldTrial* field_trial) {
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
1108 return; 1185 return;
1109 } 1186 }
1110 AutoLock auto_lock(global_->lock_); 1187 AutoLock auto_lock(global_->lock_);
1111 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name(); 1188 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name();
1112 trial->AddRef(); 1189 trial->AddRef();
1113 trial->SetTrialRegistered(); 1190 trial->SetTrialRegistered();
1114 global_->registered_[trial->trial_name()] = trial; 1191 global_->registered_[trial->trial_name()] = trial;
1115 } 1192 }
1116 1193
1117 } // namespace base 1194 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698