Skip to content

Commit 767e089

Browse files
steaphangreenefacebook-github-bot
authored andcommitted
Port v5.1: JEMalloc Stats
Summary: This ports our support for jemalloc stats info in mysqld (only). Update jemalloc stats only when needed Reference Patch: 942ff23 Reviewed By: lth Differential Revision: D7337802 fbshipit-source-id: 2b13933
1 parent 78666a2 commit 767e089

File tree

11 files changed

+234
-1
lines changed

11 files changed

+234
-1
lines changed

include/my_sqlcommand.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ enum enum_sql_command {
203203
SQLCOM_CREATE_SRS,
204204
SQLCOM_DROP_SRS,
205205
SQLCOM_SHOW_ENGINE_TRX,
206+
SQLCOM_SHOW_MEMORY_STATUS,
206207
/* This should be the last !!! */
207208
SQLCOM_END
208209
};

include/mysql/plugin_audit.h.pp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,7 @@
335335
SQLCOM_CREATE_SRS,
336336
SQLCOM_DROP_SRS,
337337
SQLCOM_SHOW_ENGINE_TRX,
338+
SQLCOM_SHOW_MEMORY_STATUS,
338339
SQLCOM_END
339340
};
340341
#include "plugin_audit_message_types.h"
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Skip test if build didn't specify -DHAVE_JEMALLOC
2+
if (`SELECT COUNT(*) = 0 FROM performance_schema.global_status WHERE VARIABLE_NAME LIKE "Jemalloc%"`)
3+
{
4+
--skip Test requires jemalloc
5+
}

mysql-test/r/jemalloc.result

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
select variable_name from performance_schema.global_status where variable_name like "Jemalloc%" order by 1;
2+
variable_name
3+
Jemalloc_arenas_narenas
4+
Jemalloc_opt_narenas
5+
Jemalloc_opt_tcache
6+
Jemalloc_stats_active
7+
Jemalloc_stats_allocated
8+
Jemalloc_stats_mapped

mysql-test/r/mysqld--help-notwin.result

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1671,7 +1671,7 @@ performance-schema-max-socket-classes 10
16711671
performance-schema-max-socket-instances -1
16721672
performance-schema-max-sql-text-length 1024
16731673
performance-schema-max-stage-classes 175
1674-
performance-schema-max-statement-classes 219
1674+
performance-schema-max-statement-classes 220
16751675
performance-schema-max-statement-stack 10
16761676
performance-schema-max-table-handles -1
16771677
performance-schema-max-table-instances -1

mysql-test/t/jemalloc.test

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
--source include/have_jemalloc.inc
2+
3+
select variable_name from performance_schema.global_status where variable_name like "Jemalloc%" order by 1;

sql/mysqld.cc

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -790,6 +790,10 @@ The documentation is based on the source files such as:
790790
#include "sql/dd/upgrade_57/upgrade.h" // dd::upgrade_57::in_progress
791791
#include "sql/srv_session.h"
792792

793+
#ifdef HAVE_JEMALLOC
794+
#include <jemalloc/jemalloc.h>
795+
#endif
796+
793797
using std::max;
794798
using std::min;
795799
using std::vector;
@@ -4040,6 +4044,10 @@ SHOW_VAR com_status_vars[] = {
40404044
(char *)offsetof(System_status_var,
40414045
com_stat[(uint)SQLCOM_SHOW_MASTER_STAT]),
40424046
SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4047+
{"show_memory_status",
4048+
(char *)offsetof(System_status_var,
4049+
com_stat[(uint)SQLCOM_SHOW_MEMORY_STATUS]),
4050+
SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
40434051
{"show_open_tables",
40444052
(char *)offsetof(System_status_var,
40454053
com_stat[(uint)SQLCOM_SHOW_OPEN_TABLES]),
@@ -7985,6 +7993,107 @@ struct my_option my_long_options[] = {
79857993

79867994
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}};
79877995

7996+
#ifdef HAVE_JEMALLOC
7997+
#ifndef EMBEDDED_LIBRARY
7998+
std::atomic_bool need_update_malloc_status;
7999+
8000+
static void update_malloc_status() {
8001+
if (!need_update_malloc_status) return;
8002+
8003+
uint64_t val = 1;
8004+
size_t len = sizeof(val);
8005+
8006+
mallctl("epoch", &val, &len, &val, sizeof(uint64_t));
8007+
need_update_malloc_status = false;
8008+
}
8009+
8010+
static int show_jemalloc_sizet(THD *thd MY_ATTRIBUTE((unused)), SHOW_VAR *var,
8011+
char *buff, const char *stat_name) {
8012+
size_t len, val;
8013+
len = sizeof(val);
8014+
8015+
var->type = SHOW_LONGLONG;
8016+
var->value = buff;
8017+
8018+
if (!mallctl(stat_name, &val, &len, NULL, 0)) {
8019+
*((ulonglong *)buff) = (ulonglong)val;
8020+
} else {
8021+
*((ulonglong *)buff) = 0;
8022+
}
8023+
8024+
/* Always return 0 to avoid worrying about error handling */
8025+
return 0;
8026+
}
8027+
8028+
static int show_jemalloc_unsigned(THD *thd MY_ATTRIBUTE((unused)),
8029+
SHOW_VAR *var, char *buff,
8030+
const char *stat_name) {
8031+
unsigned val;
8032+
size_t len = sizeof(val);
8033+
8034+
var->type = SHOW_LONG;
8035+
var->value = buff;
8036+
8037+
if (!mallctl(stat_name, &val, &len, NULL, 0)) {
8038+
*((ulong *)buff) = (ulong)val;
8039+
} else {
8040+
*((ulong *)buff) = 0;
8041+
}
8042+
8043+
/* Always return 0 to avoid worrying about error handling */
8044+
return 0;
8045+
}
8046+
8047+
static int show_jemalloc_bool(THD *thd MY_ATTRIBUTE((unused)), SHOW_VAR *var,
8048+
char *buff, const char *stat_name) {
8049+
bool val;
8050+
size_t len = sizeof(val);
8051+
8052+
var->type = SHOW_LONG;
8053+
var->value = buff;
8054+
8055+
if (!mallctl(stat_name, &val, &len, NULL, 0)) {
8056+
*((ulong *)buff) = (ulong)val;
8057+
} else {
8058+
*((ulong *)buff) = 0;
8059+
}
8060+
8061+
/* Always return 0 to avoid worrying about error handling */
8062+
return 0;
8063+
}
8064+
8065+
static int show_jemalloc_arenas_narenas(THD *thd, SHOW_VAR *var, char *buff) {
8066+
update_malloc_status();
8067+
return show_jemalloc_unsigned(thd, var, buff, "arenas.narenas");
8068+
}
8069+
8070+
static int show_jemalloc_opt_narenas(THD *thd, SHOW_VAR *var, char *buff) {
8071+
update_malloc_status();
8072+
return show_jemalloc_sizet(thd, var, buff, "opt.narenas");
8073+
}
8074+
8075+
static int show_jemalloc_opt_tcache(THD *thd, SHOW_VAR *var, char *buff) {
8076+
update_malloc_status();
8077+
return show_jemalloc_bool(thd, var, buff, "opt.tcache");
8078+
}
8079+
8080+
static int show_jemalloc_active(THD *thd, SHOW_VAR *var, char *buff) {
8081+
update_malloc_status();
8082+
return show_jemalloc_sizet(thd, var, buff, "stats.active");
8083+
}
8084+
8085+
static int show_jemalloc_allocated(THD *thd, SHOW_VAR *var, char *buff) {
8086+
update_malloc_status();
8087+
return show_jemalloc_sizet(thd, var, buff, "stats.allocated");
8088+
}
8089+
8090+
static int show_jemalloc_mapped(THD *thd, SHOW_VAR *var, char *buff) {
8091+
update_malloc_status();
8092+
return show_jemalloc_sizet(thd, var, buff, "stats.mapped");
8093+
}
8094+
#endif /* EMBEDDED_LIBRARY */
8095+
#endif /* HAVE_JEMALLOC */
8096+
79888097
static int show_queries(THD *thd, SHOW_VAR *var, char *) {
79898098
var->type = SHOW_LONGLONG;
79908099
var->value = (char *)&thd->query_id;
@@ -8507,6 +8616,20 @@ SHOW_VAR status_vars[] = {
85078616
SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
85088617
{"Handler_write", (char *)offsetof(System_status_var, ha_write_count),
85098618
SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
8619+
#ifdef HAVE_JEMALLOC
8620+
{"Jemalloc_arenas_narenas", (char *)&show_jemalloc_arenas_narenas,
8621+
SHOW_FUNC, SHOW_SCOPE_ALL},
8622+
{"Jemalloc_opt_narenas", (char *)&show_jemalloc_opt_narenas, SHOW_FUNC,
8623+
SHOW_SCOPE_ALL},
8624+
{"Jemalloc_opt_tcache", (char *)&show_jemalloc_opt_tcache, SHOW_FUNC,
8625+
SHOW_SCOPE_ALL},
8626+
{"Jemalloc_stats_active", (char *)&show_jemalloc_active, SHOW_FUNC,
8627+
SHOW_SCOPE_ALL},
8628+
{"Jemalloc_stats_allocated", (char *)&show_jemalloc_allocated, SHOW_FUNC,
8629+
SHOW_SCOPE_ALL},
8630+
{"Jemalloc_stats_mapped", (char *)&show_jemalloc_mapped, SHOW_FUNC,
8631+
SHOW_SCOPE_ALL},
8632+
#endif
85108633
{"Key_blocks_not_flushed",
85118634
(char *)offsetof(KEY_CACHE, global_blocks_changed), SHOW_KEY_CACHE_LONG,
85128635
SHOW_SCOPE_GLOBAL},

sql/sp.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2270,6 +2270,7 @@ uint sp_get_flags_for_command(LEX *lex) {
22702270
case SQLCOM_SHOW_EVENTS:
22712271
case SQLCOM_SHOW_KEYS:
22722272
case SQLCOM_SHOW_MASTER_STAT:
2273+
case SQLCOM_SHOW_MEMORY_STATUS:
22732274
case SQLCOM_SHOW_OPEN_TABLES:
22742275
case SQLCOM_SHOW_PRIVILEGES:
22752276
case SQLCOM_SHOW_PROCESSLIST:

sql/sql_parse.cc

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@
2424

2525
#include "my_config.h"
2626

27+
#ifdef HAVE_JEMALLOC
28+
#include "jemalloc/jemalloc.h"
29+
#endif
30+
2731
#include <limits.h>
2832
#include <stdio.h>
2933
#include <stdlib.h>
@@ -546,6 +550,7 @@ void init_sql_command_flags(void) {
546550
sql_command_flags[SQLCOM_SHOW_CREATE_DB] = CF_STATUS_COMMAND;
547551
sql_command_flags[SQLCOM_SHOW_CREATE] = CF_STATUS_COMMAND;
548552
sql_command_flags[SQLCOM_SHOW_MASTER_STAT] = CF_STATUS_COMMAND;
553+
sql_command_flags[SQLCOM_SHOW_MEMORY_STATUS] = CF_STATUS_COMMAND;
549554
sql_command_flags[SQLCOM_SHOW_SLAVE_STAT] = CF_STATUS_COMMAND;
550555
sql_command_flags[SQLCOM_SHOW_CREATE_PROC] = CF_STATUS_COMMAND;
551556
sql_command_flags[SQLCOM_SHOW_CREATE_FUNC] = CF_STATUS_COMMAND;
@@ -2564,6 +2569,69 @@ static bool lock_tables_open_and_lock_tables(THD *thd, TABLE_LIST *tables) {
25642569
return true;
25652570
}
25662571

2572+
typedef struct {
2573+
char *cur;
2574+
char *end;
2575+
} malloc_status;
2576+
2577+
#ifdef HAVE_JEMALLOC
2578+
static void get_jemalloc_status(void *mstat_arg, const char *status) {
2579+
malloc_status *mstat = (malloc_status *)mstat_arg;
2580+
size_t status_len = status ? strlen(status) : 0;
2581+
2582+
if (!status_len || status_len > (size_t)(mstat->end - mstat->cur)) return;
2583+
2584+
strcpy(mstat->cur, status);
2585+
mstat->cur += status_len;
2586+
}
2587+
#endif
2588+
2589+
static int show_memory_status(THD *thd) {
2590+
List<Item> field_list;
2591+
Protocol *protocol = thd->get_protocol();
2592+
malloc_status mstat;
2593+
char *buf;
2594+
/*
2595+
Buffer size in bytes. Should be large enough for per-arena statistics not
2596+
to be truncated.
2597+
*/
2598+
const uint MALLOC_STATUS_LEN = 1000000;
2599+
2600+
field_list.push_back(new Item_empty_string("Status", 10));
2601+
if (thd->send_result_metadata(&field_list,
2602+
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
2603+
return true;
2604+
2605+
protocol->start_row();
2606+
2607+
buf = (char *)my_malloc(PSI_NOT_INSTRUMENTED, MALLOC_STATUS_LEN + 1, MYF(0));
2608+
mstat.cur = buf;
2609+
mstat.end = buf + MALLOC_STATUS_LEN;
2610+
if (!buf) return true;
2611+
2612+
#ifdef HAVE_JEMALLOC
2613+
/*
2614+
get_jemalloc_status will be called many times per call to
2615+
malloc_stats_print.
2616+
*/
2617+
malloc_stats_print(get_jemalloc_status, &mstat, "");
2618+
#else
2619+
strcpy(buf, "You should be using jemalloc");
2620+
mstat.cur += strlen(buf);
2621+
#endif
2622+
2623+
protocol->store(buf, mstat.cur - buf, system_charset_info);
2624+
if (protocol->end_row()) {
2625+
my_free((void *)buf);
2626+
return true;
2627+
}
2628+
2629+
my_free((void *)buf);
2630+
2631+
my_eof(thd);
2632+
return false;
2633+
}
2634+
25672635
/**
25682636
This is a wrapper for MYSQL_BIN_LOG::gtid_end_transaction. For normal
25692637
statements, the function gtid_end_transaction is called in the commit
@@ -3046,6 +3114,13 @@ int mysql_execute_command(THD *thd, bool first_level) {
30463114
System_status_var old_status_var = thd->status_var;
30473115
thd->initial_status_var = &old_status_var;
30483116

3117+
#ifdef HAVE_JEMALLOC
3118+
#ifndef EMBEDDED_LIBRARY
3119+
extern std::atomic_bool need_update_malloc_status;
3120+
need_update_malloc_status = true;
3121+
#endif
3122+
#endif
3123+
30493124
if (!(res = show_precheck(thd, lex, true)))
30503125
res = execute_show(thd, all_tables);
30513126

@@ -3228,6 +3303,12 @@ int mysql_execute_command(THD *thd, bool first_level) {
32283303
res = ha_show_status(thd, lex->create_info->db_type, HA_ENGINE_TRX);
32293304
break;
32303305
}
3306+
case SQLCOM_SHOW_MEMORY_STATUS: {
3307+
if (check_global_access(thd, PROCESS_ACL)) goto error;
3308+
3309+
res = show_memory_status(thd);
3310+
break;
3311+
}
32313312
case SQLCOM_START_GROUP_REPLICATION: {
32323313
Security_context *sctx = thd->security_context();
32333314
if (!sctx->check_access(SUPER_ACL) &&

sql/sql_yacc.yy

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12631,6 +12631,8 @@ show_param:
1263112631
if (prepare_schema_table(YYTHD, lex, 0, SCH_PLUGINS))
1263212632
MYSQL_YYABORT;
1263312633
}
12634+
| MEMORY_SYM STATUS_SYM
12635+
{ Lex->sql_command = SQLCOM_SHOW_MEMORY_STATUS; }
1263412636
| ENGINE_SYM ident_or_text show_engine_param
1263512637
{
1263612638
const bool is_temp_table=

0 commit comments

Comments
 (0)