1 /*
2 * Knobs.cpp
3 *
4 * This source file is part of the FoundationDB open source project
5 *
6 * Copyright 2013-2018 Apple Inc. and the FoundationDB project authors
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20
21 #include "flow/Knobs.h"
22 #include "flow/flow.h"
23 #include <cmath>
24
25 FlowKnobs const* FLOW_KNOBS = new FlowKnobs();
26
27 #define init( knob, value ) initKnob( knob, value, #knob )
28
FlowKnobs(bool randomize,bool isSimulated)29 FlowKnobs::FlowKnobs(bool randomize, bool isSimulated) {
30 init( AUTOMATIC_TRACE_DUMP, 1 );
31 init( PREVENT_FAST_SPIN_DELAY, .01 );
32 init( CACHE_REFRESH_INTERVAL_WHEN_ALL_ALTERNATIVES_FAILED, 1.0 );
33
34 init( DELAY_JITTER_OFFSET, 0.9 );
35 init( DELAY_JITTER_RANGE, 0.2 );
36 init( BUSY_WAIT_THRESHOLD, 0 ); // 1e100 == never sleep
37 init( CLIENT_REQUEST_INTERVAL, 0.1 ); if( randomize && BUGGIFY ) CLIENT_REQUEST_INTERVAL = 1.0;
38 init( SERVER_REQUEST_INTERVAL, 0.1 ); if( randomize && BUGGIFY ) SERVER_REQUEST_INTERVAL = 1.0;
39
40 init( REACTOR_FLAGS, 0 );
41
42 init( DISABLE_ASSERTS, 0 );
43 init( QUEUE_MODEL_SMOOTHING_AMOUNT, 2.0 );
44
45 init( SLOWTASK_PROFILING_INTERVAL, 0.125 ); // A value of 0 disables SlowTask profiling
46 init( SLOWTASK_PROFILING_MAX_LOG_INTERVAL, 1.0 );
47 init( SLOWTASK_PROFILING_LOG_BACKOFF, 2.0 );
48
49 init( RANDOMSEED_RETRY_LIMIT, 4 );
50 init( FAST_ALLOC_LOGGING_BYTES, 10e6 );
51 init( HUGE_ARENA_LOGGING_BYTES, 100e6 );
52 init( HUGE_ARENA_LOGGING_INTERVAL, 5.0 );
53
54 //connectionMonitor
55 init( CONNECTION_MONITOR_LOOP_TIME, isSimulated ? 0.75 : 1.0 ); if( randomize && BUGGIFY ) CONNECTION_MONITOR_LOOP_TIME = 6.0;
56 init( CONNECTION_MONITOR_TIMEOUT, isSimulated ? 1.50 : 2.0 ); if( randomize && BUGGIFY ) CONNECTION_MONITOR_TIMEOUT = 6.0;
57
58 //FlowTransport
59 init( CONNECTION_REJECTED_MESSAGE_DELAY, 1.0 );
60 init( CONNECTION_ID_TIMEOUT, 600.0 ); if( randomize && BUGGIFY ) CONNECTION_ID_TIMEOUT = 60.0;
61 init( CONNECTION_CLEANUP_DELAY, 100.0 );
62 init( INITIAL_RECONNECTION_TIME, 0.05 );
63 init( MAX_RECONNECTION_TIME, 0.5 );
64 init( RECONNECTION_TIME_GROWTH_RATE, 1.2 );
65 init( RECONNECTION_RESET_TIME, 5.0 );
66 init( CONNECTION_ACCEPT_DELAY, 0.01 );
67 init( TOO_MANY_CONNECTIONS_CLOSED_RESET_DELAY, 5.0 );
68 init( TOO_MANY_CONNECTIONS_CLOSED_TIMEOUT, 20.0 );
69
70 init( TLS_CERT_REFRESH_DELAY_SECONDS, 12*60*60 );
71
72 //AsyncFileCached
73 init( PAGE_CACHE_4K, 2000LL<<20 );
74 init( PAGE_CACHE_64K, 200LL<<20 );
75 init( SIM_PAGE_CACHE_4K, 1e8 );
76 init( SIM_PAGE_CACHE_64K, 1e7 );
77 init( BUGGIFY_SIM_PAGE_CACHE_4K, 1e6 );
78 init( BUGGIFY_SIM_PAGE_CACHE_64K, 1e6 );
79 init( MAX_EVICT_ATTEMPTS, 100 ); if( randomize && BUGGIFY ) MAX_EVICT_ATTEMPTS = 2;
80 init( PAGE_CACHE_TRUNCATE_LOOKUP_FRACTION, 0.1 ); if( randomize && BUGGIFY ) PAGE_CACHE_TRUNCATE_LOOKUP_FRACTION = 0.0; else if( randomize && BUGGIFY ) PAGE_CACHE_TRUNCATE_LOOKUP_FRACTION = 1.0;
81
82 //AsyncFileKAIO
83 init( MAX_OUTSTANDING, 64 );
84 init( MIN_SUBMIT, 10 );
85
86 init( PAGE_WRITE_CHECKSUM_HISTORY, 0 ); if( randomize && BUGGIFY ) PAGE_WRITE_CHECKSUM_HISTORY = 10000000;
87 init( DISABLE_POSIX_KERNEL_AIO, 0 );
88
89 //AsyncFileNonDurable
90 init( MAX_PRIOR_MODIFICATION_DELAY, 1.0 ); if( randomize && BUGGIFY ) MAX_PRIOR_MODIFICATION_DELAY = 10.0;
91
92 //GenericActors
93 init( MAX_DELIVER_DUPLICATE_DELAY, 1.0 ); if( randomize && BUGGIFY ) MAX_DELIVER_DUPLICATE_DELAY = 10.0;
94 init( BUGGIFY_FLOW_LOCK_RELEASE_DELAY, 1.0 );
95
96 //IAsyncFile
97 init( INCREMENTAL_DELETE_TRUNCATE_AMOUNT, 5e8 ); //500MB
98 init( INCREMENTAL_DELETE_INTERVAL, 1.0 ); //every 1 second
99
100 //Net2 and FlowTransport
101 init( MIN_COALESCE_DELAY, 10e-6 ); if( randomize && BUGGIFY ) MIN_COALESCE_DELAY = 0;
102 init( MAX_COALESCE_DELAY, 20e-6 ); if( randomize && BUGGIFY ) MAX_COALESCE_DELAY = 0;
103 init( SLOW_LOOP_CUTOFF, 15.0 / 1000.0 );
104 init( SLOW_LOOP_SAMPLING_RATE, 0.1 );
105 init( TSC_YIELD_TIME, 1000000 );
106
107 //Network
108 init( PACKET_LIMIT, 100LL<<20 );
109 init( PACKET_WARNING, 2LL<<20 ); // 2MB packet warning quietly allows for 1MB system messages
110 init( TIME_OFFSET_LOGGING_INTERVAL, 60.0 );
111
112 //Sim2
113 init( MIN_OPEN_TIME, 0.0002 );
114 init( MAX_OPEN_TIME, 0.0012 );
115 init( SIM_DISK_IOPS, 5000 );
116 init( SIM_DISK_BANDWIDTH, 50000000 );
117 init( MIN_NETWORK_LATENCY, 100e-6 );
118 init( FAST_NETWORK_LATENCY, 800e-6 );
119 init( SLOW_NETWORK_LATENCY, 100e-3 );
120 init( MAX_CLOGGING_LATENCY, 0 ); if( randomize && BUGGIFY ) MAX_CLOGGING_LATENCY = 0.1 * g_random->random01();
121 init( MAX_BUGGIFIED_DELAY, 0 ); if( randomize && BUGGIFY ) MAX_BUGGIFIED_DELAY = 0.2 * g_random->random01();
122
123 //Tracefiles
124 init( ZERO_LENGTH_FILE_PAD, 1 );
125 init( TRACE_FLUSH_INTERVAL, 0.25 );
126 init( TRACE_RETRY_OPEN_INTERVAL, 1.00 );
127 init( MIN_TRACE_SEVERITY, isSimulated ? 0 : 10 ); // Related to the trace severity in Trace.h
128 init( MAX_TRACE_SUPPRESSIONS, 1e4 );
129 init( TRACE_SYNC_ENABLED, 0 );
130 init( TRACE_EVENT_METRIC_UNITS_PER_SAMPLE, 500 );
131 init( TRACE_EVENT_THROTTLER_SAMPLE_EXPIRY, 1800.0 ); // 30 mins
132 init( TRACE_EVENT_THROTTLER_MSG_LIMIT, 20000 );
133
134 //TDMetrics
135 init( MAX_METRICS, 600 );
136 init( MAX_METRIC_SIZE, 2500 );
137 init( MAX_METRIC_LEVEL, 25 );
138 init( METRIC_LEVEL_DIVISOR, log(4) );
139 init( METRIC_LIMIT_START_QUEUE_SIZE, 10 ); // The queue size at which to start restricting logging by disabling levels
140 init( METRIC_LIMIT_RESPONSE_FACTOR, 10 ); // The additional queue size at which to disable logging of another level (higher == less restrictive)
141
142 //Load Balancing
143 init( LOAD_BALANCE_MAX_BACKOFF, 5.0 );
144 init( LOAD_BALANCE_START_BACKOFF, 0.01 );
145 init( LOAD_BALANCE_BACKOFF_RATE, 2.0 );
146 init( MAX_LAGGING_REQUESTS_OUTSTANDING, 100000 );
147 init( INSTANT_SECOND_REQUEST_MULTIPLIER, 2.0 );
148 init( BASE_SECOND_REQUEST_TIME, 0.0005 );
149 init( SECOND_REQUEST_MULTIPLIER_GROWTH, 0.01 );
150 init( SECOND_REQUEST_MULTIPLIER_DECAY, 0.00025 );
151 init( SECOND_REQUEST_BUDGET_GROWTH, 0.05 );
152 init( SECOND_REQUEST_MAX_BUDGET, 100.0 );
153 init( ALTERNATIVES_FAILURE_RESET_TIME, 5.0 );
154 init( ALTERNATIVES_FAILURE_MAX_DELAY, 1.0 );
155 init( ALTERNATIVES_FAILURE_MIN_DELAY, 0.05 );
156 init( ALTERNATIVES_FAILURE_DELAY_RATIO, 0.2 );
157 init( FUTURE_VERSION_INITIAL_BACKOFF, 1.0 );
158 init( FUTURE_VERSION_MAX_BACKOFF, 8.0 );
159 init( FUTURE_VERSION_BACKOFF_GROWTH, 2.0 );
160 }
161
setKnob(std::string const & knob,std::string const & value)162 bool Knobs::setKnob( std::string const& knob, std::string const& value ) {
163 if (double_knobs.count(knob)) {
164 double v;
165 int n=0;
166 if (sscanf(value.c_str(), "%lf%n", &v, &n) != 1 || n != value.size())
167 throw invalid_option_value();
168 *double_knobs[knob] = v;
169 return true;
170 }
171 if (int64_knobs.count(knob) || int_knobs.count(knob)) {
172 int64_t v;
173 int n=0;
174 if (StringRef(value).startsWith(LiteralStringRef("0x"))) {
175 if (sscanf(value.c_str(), "0x%llx%n", &v, &n) != 1 || n != value.size())
176 throw invalid_option_value();
177 } else {
178 if (sscanf(value.c_str(), "%lld%n", &v, &n) != 1 || n != value.size())
179 throw invalid_option_value();
180 }
181 if (int64_knobs.count(knob))
182 *int64_knobs[knob] = v;
183 else {
184 if ( v < std::numeric_limits<int>::min() || v > std::numeric_limits<int>::max() )
185 throw invalid_option_value();
186 *int_knobs[knob] = v;
187 }
188 return true;
189 }
190 if (string_knobs.count(knob)) {
191 *string_knobs[knob] = value;
192 return true;
193 }
194 return false;
195 }
196
toLower(std::string const & name)197 static std::string toLower( std::string const& name ) {
198 std::string lower_name;
199 for(auto c = name.begin(); c != name.end(); ++c)
200 if (*c >= 'A' && *c <= 'Z')
201 lower_name += *c - 'A' + 'a';
202 else
203 lower_name += *c;
204 return lower_name;
205 }
206
initKnob(double & knob,double value,std::string const & name)207 void Knobs::initKnob( double& knob, double value, std::string const& name ) {
208 knob = value;
209 double_knobs[toLower(name)] = &knob;
210 }
211
initKnob(int64_t & knob,int64_t value,std::string const & name)212 void Knobs::initKnob( int64_t& knob, int64_t value, std::string const& name ) {
213 knob = value;
214 int64_knobs[toLower(name)] = &knob;
215 }
216
initKnob(int & knob,int value,std::string const & name)217 void Knobs::initKnob( int& knob, int value, std::string const& name ) {
218 knob = value;
219 int_knobs[toLower(name)] = &knob;
220 }
221
initKnob(std::string & knob,const std::string & value,const std::string & name)222 void Knobs::initKnob( std::string& knob, const std::string& value, const std::string& name ) {
223 knob = value;
224 string_knobs[toLower(name)] = &knob;
225 }
226
trace()227 void Knobs::trace() {
228 for(auto &k : double_knobs)
229 TraceEvent("Knob").detail("Name", k.first.c_str()).detail("Value", *k.second);
230 for(auto &k : int_knobs)
231 TraceEvent("Knob").detail("Name", k.first.c_str()).detail("Value", *k.second);
232 for(auto &k : int64_knobs)
233 TraceEvent("Knob").detail("Name", k.first.c_str()).detail("Value", *k.second);
234 for(auto &k : string_knobs)
235 TraceEvent("Knob").detail("Name", k.first.c_str()).detail("Value", *k.second);
236 }
237