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

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

Issue 2530573002: Share field trial allocator on zygote-using Linuxes (Closed)
Patch Set: make handle read-only 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/debug/alias.h" 13 #include "base/debug/alias.h"
14 #include "base/feature_list.h" 14 #include "base/feature_list.h"
15 #include "base/logging.h" 15 #include "base/logging.h"
16 #include "base/pickle.h" 16 #include "base/pickle.h"
17 #include "base/process/memory.h" 17 #include "base/process/memory.h"
18 #include "base/rand_util.h" 18 #include "base/rand_util.h"
19 #include "base/strings/string_number_conversions.h" 19 #include "base/strings/string_number_conversions.h"
20 #include "base/strings/string_util.h" 20 #include "base/strings/string_util.h"
21 #include "base/strings/stringprintf.h" 21 #include "base/strings/stringprintf.h"
22 #include "base/strings/utf_string_conversions.h" 22 #include "base/strings/utf_string_conversions.h"
23 23
24 #if defined(OS_POSIX)
25 #include "base/posix/global_descriptors.h"
26 #endif
27
24 namespace base { 28 namespace base {
25 29
26 namespace { 30 namespace {
27 31
28 // Define a separator character to use when creating a persistent form of an 32 // 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 33 // 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). 34 // second process to mimic our state (i.e., provide the same group name).
31 const char kPersistentStringSeparator = '/'; // Currently a slash. 35 const char kPersistentStringSeparator = '/'; // Currently a slash.
32 36
33 // Define a marker character to be used as a prefix to a trial name on the 37 // Define a marker character to be used as a prefix to a trial name on the
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
226 #if defined(OS_WIN) 230 #if defined(OS_WIN)
227 HANDLE CreateReadOnlyHandle(FieldTrialList::FieldTrialAllocator* allocator) { 231 HANDLE CreateReadOnlyHandle(FieldTrialList::FieldTrialAllocator* allocator) {
228 HANDLE src = allocator->shared_memory()->handle().GetHandle(); 232 HANDLE src = allocator->shared_memory()->handle().GetHandle();
229 ProcessHandle process = GetCurrentProcess(); 233 ProcessHandle process = GetCurrentProcess();
230 DWORD access = SECTION_MAP_READ | SECTION_QUERY; 234 DWORD access = SECTION_MAP_READ | SECTION_QUERY;
231 HANDLE dst; 235 HANDLE dst;
232 if (!::DuplicateHandle(process, src, process, &dst, access, true, 0)) 236 if (!::DuplicateHandle(process, src, process, &dst, access, true, 0))
233 return nullptr; 237 return nullptr;
234 return dst; 238 return dst;
235 } 239 }
240 #elif defined(OS_POSIX) && !defined(OS_NACL)
Alexei Svitkine (slow) 2016/11/23 17:49:55 Instead of these #elif chains that are confusing -
lawrencewu 2016/11/23 18:59:44 Done.
241 int CreateReadOnlyHandle(FieldTrialList::FieldTrialAllocator* allocator) {
242 SharedMemoryHandle new_handle;
243 allocator->shared_memory()->ShareReadOnlyToProcess(GetCurrentProcessHandle(),
244 &new_handle);
245 int fd = SharedMemory::GetFdFromSharedMemoryHandle(new_handle);
246 return fd;
Alexei Svitkine (slow) 2016/11/23 17:49:55 Nit: Merge with line above.
lawrencewu 2016/11/23 18:59:44 Done.
247 }
236 #endif 248 #endif
237 249
238 } // namespace 250 } // namespace
239 251
240 // statics 252 // statics
241 const int FieldTrial::kNotFinalized = -1; 253 const int FieldTrial::kNotFinalized = -1;
242 const int FieldTrial::kDefaultGroupNumber = 0; 254 const int FieldTrial::kDefaultGroupNumber = 0;
243 bool FieldTrial::enable_benchmarking_ = false; 255 bool FieldTrial::enable_benchmarking_ = false;
244 256
245 int FieldTrialList::kNoExpirationYear = 0; 257 int FieldTrialList::kNoExpirationYear = 0;
(...skipping 484 matching lines...) Expand 10 before | Expand all | Expand 10 after
730 } 742 }
731 return true; 743 return true;
732 } 744 }
733 745
734 // static 746 // static
735 void FieldTrialList::CreateTrialsFromCommandLine( 747 void FieldTrialList::CreateTrialsFromCommandLine(
736 const CommandLine& cmd_line, 748 const CommandLine& cmd_line,
737 const char* field_trial_handle_switch) { 749 const char* field_trial_handle_switch) {
738 global_->create_trials_from_command_line_called_ = true; 750 global_->create_trials_from_command_line_called_ = true;
739 751
740 #if defined(OS_WIN) && !defined(OS_NACL)
741 if (cmd_line.HasSwitch(field_trial_handle_switch)) { 752 if (cmd_line.HasSwitch(field_trial_handle_switch)) {
742 std::string arg = cmd_line.GetSwitchValueASCII(field_trial_handle_switch); 753 std::string arg = cmd_line.GetSwitchValueASCII(field_trial_handle_switch);
743 int field_trial_handle = std::stoi(arg); 754 #if defined(OS_WIN)
744 HANDLE handle = reinterpret_cast<HANDLE>(field_trial_handle); 755 bool result = CreateTrialsFromWindowsSwitch(arg);
745 bool result = CreateTrialsFromWindowsHandle(handle);
746 DCHECK(result); 756 DCHECK(result);
757 #elif defined(OS_POSIX) && !defined(OS_NACL)
758 bool result = CreateTrialsFromPosixSwitch(arg);
759 DCHECK(result);
760 #endif
747 } 761 }
748 #endif
749 762
750 if (cmd_line.HasSwitch(switches::kForceFieldTrials)) { 763 if (cmd_line.HasSwitch(switches::kForceFieldTrials)) {
751 bool result = FieldTrialList::CreateTrialsFromString( 764 bool result = FieldTrialList::CreateTrialsFromString(
752 cmd_line.GetSwitchValueASCII(switches::kForceFieldTrials), 765 cmd_line.GetSwitchValueASCII(switches::kForceFieldTrials),
753 std::set<std::string>()); 766 std::set<std::string>());
754 DCHECK(result); 767 DCHECK(result);
755 } 768 }
756 } 769 }
757 770
758 #if defined(OS_WIN) 771 #if defined(OS_WIN)
759 // static 772 // static
760 void FieldTrialList::AppendFieldTrialHandleIfNeeded( 773 void FieldTrialList::AppendFieldTrialHandleIfNeeded(
761 HandlesToInheritVector* handles) { 774 HandlesToInheritVector* handles) {
762 if (!global_) 775 if (!global_)
763 return; 776 return;
764 if (kUseSharedMemoryForFieldTrials) { 777 if (kUseSharedMemoryForFieldTrials) {
765 InstantiateFieldTrialAllocatorIfNeeded(); 778 InstantiateFieldTrialAllocatorIfNeeded();
766 if (global_->readonly_allocator_handle_) 779 if (global_->readonly_allocator_handle_)
767 handles->push_back(global_->readonly_allocator_handle_); 780 handles->push_back(global_->readonly_allocator_handle_);
768 } 781 }
769 } 782 }
783 #elif defined(OS_POSIX) && !defined(OS_NACL)
784 // static
785 int FieldTrialList::FieldTrialHandle() {
786 if (!global_)
787 return -1;
788 if (kUseSharedMemoryForFieldTrials) {
789 InstantiateFieldTrialAllocatorIfNeeded();
790 if (global_->readonly_allocator_handle_ != -1)
791 return global_->readonly_allocator_handle_;
792 }
793 return -1;
794 }
770 #endif 795 #endif
771 796
772 // static 797 // static
773 void FieldTrialList::CopyFieldTrialStateToFlags( 798 void FieldTrialList::CopyFieldTrialStateToFlags(
774 const char* field_trial_handle_switch, 799 const char* field_trial_handle_switch,
775 CommandLine* cmd_line) { 800 CommandLine* cmd_line) {
776 // TODO(lawrencewu): Ideally, having the global would be guaranteed. However, 801 // TODO(lawrencewu): Ideally, having the global would be guaranteed. However,
777 // content browser tests currently don't create a FieldTrialList because they 802 // content browser tests currently don't create a FieldTrialList because they
778 // don't run ChromeBrowserMainParts code where it's done for Chrome. 803 // don't run ChromeBrowserMainParts code where it's done for Chrome.
779 if (!global_) 804 if (!global_)
(...skipping 15 matching lines...) Expand all
795 // int (uintptr_t, to be exact), stringify the int, and pass it as a 820 // int (uintptr_t, to be exact), stringify the int, and pass it as a
796 // command-line flag. The child process will do the reverse conversions to 821 // command-line flag. The child process will do the reverse conversions to
797 // retrieve the handle. See http://stackoverflow.com/a/153077 822 // retrieve the handle. See http://stackoverflow.com/a/153077
798 auto uintptr_handle = 823 auto uintptr_handle =
799 reinterpret_cast<uintptr_t>(global_->readonly_allocator_handle_); 824 reinterpret_cast<uintptr_t>(global_->readonly_allocator_handle_);
800 std::string field_trial_handle = std::to_string(uintptr_handle); 825 std::string field_trial_handle = std::to_string(uintptr_handle);
801 cmd_line->AppendSwitchASCII(field_trial_handle_switch, field_trial_handle); 826 cmd_line->AppendSwitchASCII(field_trial_handle_switch, field_trial_handle);
802 global_->field_trial_allocator_->UpdateTrackingHistograms(); 827 global_->field_trial_allocator_->UpdateTrackingHistograms();
803 return; 828 return;
804 } 829 }
830 #elif defined(OS_POSIX) && !defined(OS_NACL)
831 // Use shared memory to pass the state if the feature is enabled, otherwise
832 // fallback to passing it via the command line as a string.
833 if (kUseSharedMemoryForFieldTrials) {
834 InstantiateFieldTrialAllocatorIfNeeded();
835 // If the readonly handle didn't get duplicated properly, then fallback to
836 // original behavior.
837 if (global_->readonly_allocator_handle_ == -1) {
838 AddForceFieldTrialsFlag(cmd_line);
839 return;
840 }
841
842 std::string field_trial_handle =
843 std::to_string(global_->readonly_allocator_handle_);
844 cmd_line->AppendSwitchASCII(field_trial_handle_switch, field_trial_handle);
845 global_->field_trial_allocator_->UpdateTrackingHistograms();
846 return;
847 }
805 #endif 848 #endif
806 849
807 AddForceFieldTrialsFlag(cmd_line); 850 AddForceFieldTrialsFlag(cmd_line);
808 } 851 }
809 852
810 // static 853 // static
811 FieldTrial* FieldTrialList::CreateFieldTrial( 854 FieldTrial* FieldTrialList::CreateFieldTrial(
812 const std::string& name, 855 const std::string& name,
813 const std::string& group_name) { 856 const std::string& group_name) {
814 DCHECK(global_); 857 DCHECK(global_);
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
885 // static 928 // static
886 size_t FieldTrialList::GetFieldTrialCount() { 929 size_t FieldTrialList::GetFieldTrialCount() {
887 if (!global_) 930 if (!global_)
888 return 0; 931 return 0;
889 AutoLock auto_lock(global_->lock_); 932 AutoLock auto_lock(global_->lock_);
890 return global_->registered_.size(); 933 return global_->registered_.size();
891 } 934 }
892 935
893 #if defined(OS_WIN) 936 #if defined(OS_WIN)
894 // static 937 // static
895 bool FieldTrialList::CreateTrialsFromWindowsHandle(HANDLE handle) { 938 bool FieldTrialList::CreateTrialsFromWindowsSwitch(std::string cli_switch) {
939 int field_trial_handle = std::stoi(cli_switch);
940 HANDLE handle = reinterpret_cast<HANDLE>(field_trial_handle);
896 SharedMemoryHandle shm_handle(handle, GetCurrentProcId()); 941 SharedMemoryHandle shm_handle(handle, GetCurrentProcId());
942 return FieldTrialList::CreateTrialsFromSharedMemoryHandle(shm_handle);
943 }
944 #elif defined(OS_POSIX) && !defined(OS_NACL)
945 // static
946 bool FieldTrialList::CreateTrialsFromPosixSwitch(std::string cli_switch) {
947 int fd_key = std::stoi(cli_switch);
948 int fd = GlobalDescriptors::GetInstance()->Get(fd_key);
949 SharedMemoryHandle shm_handle(fd, true);
950 return FieldTrialList::CreateTrialsFromSharedMemoryHandle(shm_handle);
951 }
952 #endif
897 953
954 #if !defined(OS_NACL)
955 // static
956 bool FieldTrialList::CreateTrialsFromSharedMemoryHandle(
957 SharedMemoryHandle shm_handle) {
898 // shm gets deleted when it gets out of scope, but that's OK because we need 958 // shm gets deleted when it gets out of scope, but that's OK because we need
899 // it only for the duration of this method. 959 // it only for the duration of this method.
900 std::unique_ptr<SharedMemory> shm(new SharedMemory(shm_handle, true)); 960 std::unique_ptr<SharedMemory> shm(new SharedMemory(shm_handle, true));
901 if (!shm.get()->Map(kFieldTrialAllocationSize)) 961 if (!shm.get()->Map(kFieldTrialAllocationSize))
902 TerminateBecauseOutOfMemory(kFieldTrialAllocationSize); 962 TerminateBecauseOutOfMemory(kFieldTrialAllocationSize);
903 963
904 return FieldTrialList::CreateTrialsFromSharedMemory(std::move(shm)); 964 return FieldTrialList::CreateTrialsFromSharedMemory(std::move(shm));
905 } 965 }
906 #endif 966 #endif
907 967
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
977 #if !defined(OS_NACL) 1037 #if !defined(OS_NACL)
978 // static 1038 // static
979 void FieldTrialList::InstantiateFieldTrialAllocatorIfNeeded() { 1039 void FieldTrialList::InstantiateFieldTrialAllocatorIfNeeded() {
980 if (!global_) 1040 if (!global_)
981 return; 1041 return;
982 AutoLock auto_lock(global_->lock_); 1042 AutoLock auto_lock(global_->lock_);
983 // Create the allocator if not already created and add all existing trials. 1043 // Create the allocator if not already created and add all existing trials.
984 if (global_->field_trial_allocator_ != nullptr) 1044 if (global_->field_trial_allocator_ != nullptr)
985 return; 1045 return;
986 1046
1047 SharedMemoryCreateOptions options;
1048 options.size = kFieldTrialAllocationSize;
1049 options.share_read_only = true;
1050
987 std::unique_ptr<SharedMemory> shm(new SharedMemory()); 1051 std::unique_ptr<SharedMemory> shm(new SharedMemory());
988 if (!shm->CreateAndMapAnonymous(kFieldTrialAllocationSize)) 1052 if (!shm->Create(options))
1053 TerminateBecauseOutOfMemory(kFieldTrialAllocationSize);
1054
1055 if (!shm->Map(kFieldTrialAllocationSize))
989 TerminateBecauseOutOfMemory(kFieldTrialAllocationSize); 1056 TerminateBecauseOutOfMemory(kFieldTrialAllocationSize);
990 1057
991 global_->field_trial_allocator_.reset( 1058 global_->field_trial_allocator_.reset(
992 new FieldTrialAllocator(std::move(shm), 0, kAllocatorName, false)); 1059 new FieldTrialAllocator(std::move(shm), 0, kAllocatorName, false));
993 global_->field_trial_allocator_->CreateTrackingHistograms(kAllocatorName); 1060 global_->field_trial_allocator_->CreateTrackingHistograms(kAllocatorName);
994 1061
995 // Add all existing field trials. 1062 // Add all existing field trials.
996 for (const auto& registered : global_->registered_) { 1063 for (const auto& registered : global_->registered_) {
997 AddToAllocatorWhileLocked(registered.second); 1064 AddToAllocatorWhileLocked(registered.second);
998 } 1065 }
999 1066
1000 #if defined(OS_WIN) 1067 #if defined(OS_WIN) || defined(OS_POSIX)
1001 // Set |readonly_allocator_handle_| so we can pass it to be inherited and 1068 // Set |readonly_allocator_handle_| so we can pass it to be inherited and
1002 // via the command line. 1069 // via the command line.
1003 global_->readonly_allocator_handle_ = 1070 global_->readonly_allocator_handle_ =
1004 CreateReadOnlyHandle(global_->field_trial_allocator_.get()); 1071 CreateReadOnlyHandle(global_->field_trial_allocator_.get());
1005 #endif 1072 #endif
1006 } 1073 }
1007 #endif 1074 #endif
1008 1075
1009 // static 1076 // static
1010 void FieldTrialList::AddToAllocatorWhileLocked(FieldTrial* field_trial) { 1077 void FieldTrialList::AddToAllocatorWhileLocked(FieldTrial* field_trial) {
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
1105 return; 1172 return;
1106 } 1173 }
1107 AutoLock auto_lock(global_->lock_); 1174 AutoLock auto_lock(global_->lock_);
1108 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name(); 1175 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name();
1109 trial->AddRef(); 1176 trial->AddRef();
1110 trial->SetTrialRegistered(); 1177 trial->SetTrialRegistered();
1111 global_->registered_[trial->trial_name()] = trial; 1178 global_->registered_[trial->trial_name()] = trial;
1112 } 1179 }
1113 1180
1114 } // namespace base 1181 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698