1/* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 of the License.
6
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
11
12 You should have received a copy of the GNU General Public License
13 along with this program; if not, write to the Free Software Foundation,
14 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
15
16/**
17 @file storage/perfschema/pfs_autosize.cc
18 Private interface for the server (implementation).
19*/
20
21#include "my_global.h"
22#include "sql_const.h"
23#include "pfs_server.h"
24#include "set_var.h"
25
26#include <algorithm>
27using std::min;
28using std::max;
29
30static const ulong fixed_mutex_instances= 500;
31static const ulong fixed_rwlock_instances= 200;
32static const ulong fixed_cond_instances= 50;
33static const ulong fixed_file_instances= 200;
34static const ulong fixed_socket_instances= 10;
35static const ulong fixed_thread_instances= 50;
36
37static const ulong mutex_per_connection= 3;
38static const ulong rwlock_per_connection= 1;
39static const ulong cond_per_connection= 2;
40static const ulong file_per_connection= 0;
41static const ulong socket_per_connection= 1;
42static const ulong thread_per_connection= 1;
43
44static const ulong mutex_per_handle= 0;
45static const ulong rwlock_per_handle= 0;
46static const ulong cond_per_handle= 0;
47static const ulong file_per_handle= 0;
48static const ulong socket_per_handle= 0;
49static const ulong thread_per_handle= 0;
50
51static const ulong mutex_per_share= 5;
52static const ulong rwlock_per_share= 3;
53static const ulong cond_per_share= 1;
54static const ulong file_per_share= 3;
55static const ulong socket_per_share= 0;
56static const ulong thread_per_share= 0;
57
58struct PFS_sizing_data
59{
60 /** Default value for @c PFS_param.m_account_sizing. */
61 ulong m_account_sizing;
62 /** Default value for @c PFS_param.m_user_sizing. */
63 ulong m_user_sizing;
64 /** Default value for @c PFS_param.m_host_sizing. */
65 ulong m_host_sizing;
66
67 /** Default value for @c PFS_param.m_events_waits_history_sizing. */
68 ulong m_events_waits_history_sizing;
69 /** Default value for @c PFS_param.m_events_waits_history_long_sizing. */
70 ulong m_events_waits_history_long_sizing;
71 /** Default value for @c PFS_param.m_events_stages_history_sizing. */
72 ulong m_events_stages_history_sizing;
73 /** Default value for @c PFS_param.m_events_stages_history_long_sizing. */
74 ulong m_events_stages_history_long_sizing;
75 /** Default value for @c PFS_param.m_events_statements_history_sizing. */
76 ulong m_events_statements_history_sizing;
77 /** Default value for @c PFS_param.m_events_statements_history_long_sizing. */
78 ulong m_events_statements_history_long_sizing;
79 /** Default value for @c PFS_param.m_digest_sizing. */
80 ulong m_digest_sizing;
81 /** Default value for @c PFS_param.m_session_connect_attrs_sizing. */
82 ulong m_session_connect_attrs_sizing;
83
84 /**
85 Minimum number of tables to keep statistics for.
86 On small deployments, all the tables can fit into the table definition cache,
87 and this value can be 0.
88 On big deployments, the table definition cache is only a subset of all the tables
89 in the database, which are accounted for here.
90 */
91 ulong m_min_number_of_tables;
92
93 /**
94 Load factor for 'volatile' objects (mutexes, table handles, ...).
95 Instrumented objects that:
96 - use little memory
97 - are created/destroyed very frequently
98 should be stored in a low density (mostly empty) memory buffer,
99 to optimize for speed.
100 */
101 float m_load_factor_volatile;
102 /**
103 Load factor for 'normal' objects (files).
104 Instrumented objects that:
105 - use a medium amount of memory
106 - are created/destroyed
107 should be stored in a medium density memory buffer,
108 as a trade off between space and speed.
109 */
110 float m_load_factor_normal;
111 /**
112 Load factor for 'static' objects (table shares).
113 Instrumented objects that:
114 - use a lot of memory
115 - are created/destroyed very rarely
116 can be stored in a high density (mostly packed) memory buffer,
117 to optimize for space.
118 */
119 float m_load_factor_static;
120};
121
122PFS_sizing_data small_data=
123{
124 /* Account / user / host */
125 10, 5, 20,
126 /* History sizes */
127 10, 100, 10, 100, 10, 100,
128 /* Digests */
129 1000,
130 /* Session connect attrs. */
131 512,
132 /* Min tables */
133 200,
134 /* Load factors */
135 0.90f, 0.90f, 0.90f
136};
137
138PFS_sizing_data medium_data=
139{
140 /* Account / user / host */
141 100, 100, 100,
142 /* History sizes */
143 20, 1000, 20, 1000, 20, 1000,
144 /* Digests */
145 5000,
146 /* Session connect attrs. */
147 512,
148 /* Min tables */
149 500,
150 /* Load factors */
151 0.70f, 0.80f, 0.90f
152};
153
154PFS_sizing_data large_data=
155{
156 /* Account / user / host */
157 100, 100, 100,
158 /* History sizes */
159 20, 10000, 20, 10000, 20, 10000,
160 /* Digests */
161 10000,
162 /* Session connect attrs. */
163 512,
164 /* Min tables */
165 10000,
166 /* Load factors */
167 0.50f, 0.65f, 0.80f
168};
169
170static inline ulong apply_load_factor(ulong raw_value, float factor)
171{
172 float value = ((float) raw_value) / factor;
173 return (ulong) ceil(value);
174}
175
176PFS_sizing_data *estimate_hints(PFS_global_param *param)
177{
178 if ((param->m_hints.m_max_connections <= MAX_CONNECTIONS_DEFAULT) &&
179 (param->m_hints.m_table_definition_cache <= TABLE_DEF_CACHE_DEFAULT) &&
180 (param->m_hints.m_table_open_cache <= TABLE_OPEN_CACHE_DEFAULT))
181 {
182 /* The my.cnf used is either unchanged, or lower than factory defaults. */
183 return & small_data;
184 }
185
186 if ((param->m_hints.m_max_connections <= MAX_CONNECTIONS_DEFAULT * 2) &&
187 (param->m_hints.m_table_definition_cache <= TABLE_DEF_CACHE_DEFAULT * 2) &&
188 (param->m_hints.m_table_open_cache <= TABLE_OPEN_CACHE_DEFAULT * 2))
189 {
190 /* Some defaults have been increased, to "moderate" values. */
191 return & medium_data;
192 }
193
194 /* Looks like a server in production. */
195 return & large_data;
196}
197
198static void apply_heuristic(PFS_global_param *p, PFS_sizing_data *h)
199{
200 ulong count;
201 ulong con = p->m_hints.m_max_connections;
202 ulong handle = p->m_hints.m_table_open_cache;
203 ulong share = p->m_hints.m_table_definition_cache;
204 ulong file = p->m_hints.m_open_files_limit;
205
206 if (p->m_table_sizing < 0)
207 {
208 count= handle;
209
210 SYSVAR_AUTOSIZE(p->m_table_sizing,
211 apply_load_factor(count, h->m_load_factor_volatile));
212 }
213
214 if (p->m_table_share_sizing < 0)
215 {
216 count= share;
217
218 count= max<ulong>(count, h->m_min_number_of_tables);
219 SYSVAR_AUTOSIZE(p->m_table_share_sizing,
220 apply_load_factor(count, h->m_load_factor_static));
221 }
222
223 if (p->m_account_sizing < 0)
224 {
225 SYSVAR_AUTOSIZE(p->m_account_sizing,
226 h->m_account_sizing);
227 }
228
229 if (p->m_user_sizing < 0)
230 {
231 SYSVAR_AUTOSIZE(p->m_user_sizing,
232 h->m_user_sizing);
233 }
234
235 if (p->m_host_sizing < 0)
236 {
237 SYSVAR_AUTOSIZE(p->m_host_sizing,
238 h->m_host_sizing);
239 }
240
241 if (p->m_events_waits_history_sizing < 0)
242 {
243 SYSVAR_AUTOSIZE(p->m_events_waits_history_sizing,
244 h->m_events_waits_history_sizing);
245 }
246
247 if (p->m_events_waits_history_long_sizing < 0)
248 {
249 SYSVAR_AUTOSIZE(p->m_events_waits_history_long_sizing,
250 h->m_events_waits_history_long_sizing);
251 }
252
253 if (p->m_events_stages_history_sizing < 0)
254 {
255 SYSVAR_AUTOSIZE(p->m_events_stages_history_sizing,
256 h->m_events_stages_history_sizing);
257 }
258
259 if (p->m_events_stages_history_long_sizing < 0)
260 {
261 SYSVAR_AUTOSIZE(p->m_events_stages_history_long_sizing,
262 h->m_events_stages_history_long_sizing);
263 }
264
265 if (p->m_events_statements_history_sizing < 0)
266 {
267 SYSVAR_AUTOSIZE(p->m_events_statements_history_sizing,
268 h->m_events_statements_history_sizing);
269 }
270
271 if (p->m_events_statements_history_long_sizing < 0)
272 {
273 SYSVAR_AUTOSIZE(p->m_events_statements_history_long_sizing,
274 h->m_events_statements_history_long_sizing);
275 }
276
277 if (p->m_digest_sizing < 0)
278 {
279 SYSVAR_AUTOSIZE(p->m_digest_sizing,
280 h->m_digest_sizing);
281 }
282
283 if (p->m_session_connect_attrs_sizing < 0)
284 {
285 SYSVAR_AUTOSIZE(p->m_session_connect_attrs_sizing,
286 h->m_session_connect_attrs_sizing);
287 }
288
289 if (p->m_mutex_sizing < 0)
290 {
291 count= fixed_mutex_instances
292 + con * mutex_per_connection
293 + handle * mutex_per_handle
294 + share * mutex_per_share;
295
296 SYSVAR_AUTOSIZE(p->m_mutex_sizing,
297 apply_load_factor(count, h->m_load_factor_volatile));
298 }
299
300 if (p->m_rwlock_sizing < 0)
301 {
302 count= fixed_rwlock_instances
303 + con * rwlock_per_connection
304 + handle * rwlock_per_handle
305 + share * rwlock_per_share;
306
307 SYSVAR_AUTOSIZE(p->m_rwlock_sizing,
308 apply_load_factor(count, h->m_load_factor_volatile));
309 }
310
311 if (p->m_cond_sizing < 0)
312 {
313 ulong count;
314 count= fixed_cond_instances
315 + con * cond_per_connection
316 + handle * cond_per_handle
317 + share * cond_per_share;
318
319 SYSVAR_AUTOSIZE(p->m_cond_sizing,
320 apply_load_factor(count, h->m_load_factor_volatile));
321 }
322
323 if (p->m_file_sizing < 0)
324 {
325 count= fixed_file_instances
326 + con * file_per_connection
327 + handle * file_per_handle
328 + share * file_per_share;
329
330 count= max<ulong>(count, file);
331 SYSVAR_AUTOSIZE(p->m_file_sizing,
332 apply_load_factor(count, h->m_load_factor_normal));
333 }
334
335 if (p->m_socket_sizing < 0)
336 {
337 count= fixed_socket_instances
338 + con * socket_per_connection
339 + handle * socket_per_handle
340 + share * socket_per_share;
341
342 SYSVAR_AUTOSIZE(p->m_socket_sizing,
343 apply_load_factor(count, h->m_load_factor_volatile));
344 }
345
346 if (p->m_thread_sizing < 0)
347 {
348 count= fixed_thread_instances
349 + con * thread_per_connection
350 + handle * thread_per_handle
351 + share * thread_per_share;
352
353 SYSVAR_AUTOSIZE(p->m_thread_sizing,
354 apply_load_factor(count, h->m_load_factor_volatile));
355 }
356}
357
358void pfs_automated_sizing(PFS_global_param *param)
359{
360 PFS_sizing_data *heuristic;
361 heuristic= estimate_hints(param);
362 apply_heuristic(param, heuristic);
363
364 DBUG_ASSERT(param->m_account_sizing >= 0);
365 DBUG_ASSERT(param->m_digest_sizing >= 0);
366 DBUG_ASSERT(param->m_host_sizing >= 0);
367 DBUG_ASSERT(param->m_user_sizing >= 0);
368
369 DBUG_ASSERT(param->m_events_waits_history_sizing >= 0);
370 DBUG_ASSERT(param->m_events_waits_history_long_sizing >= 0);
371 DBUG_ASSERT(param->m_events_stages_history_sizing >= 0);
372 DBUG_ASSERT(param->m_events_stages_history_long_sizing >= 0);
373 DBUG_ASSERT(param->m_events_statements_history_sizing >= 0);
374 DBUG_ASSERT(param->m_events_statements_history_long_sizing >= 0);
375 DBUG_ASSERT(param->m_session_connect_attrs_sizing >= 0);
376
377 DBUG_ASSERT(param->m_mutex_sizing >= 0);
378 DBUG_ASSERT(param->m_rwlock_sizing >= 0);
379 DBUG_ASSERT(param->m_cond_sizing >= 0);
380 DBUG_ASSERT(param->m_file_sizing >= 0);
381 DBUG_ASSERT(param->m_socket_sizing >= 0);
382 DBUG_ASSERT(param->m_thread_sizing >= 0);
383 DBUG_ASSERT(param->m_table_sizing >= 0);
384 DBUG_ASSERT(param->m_table_share_sizing >= 0);
385}
386
387