jemalloc_ctl 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/jemalloc_ctl/jemalloc_ctl.c +84 -17
- data/lib/jemalloc_ctl.rb +13 -0
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a11fb9644350e9484a4e0f6e0d7a4a89445ce6284e9ed5dc00bbb0314139ac7d
|
|
4
|
+
data.tar.gz: d4079ec48055491218452c0f054b742602f61fc55946c418621b7740ca06edcb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 44fcc93f7ac58f5b9e8da956d98e04a5608a4841555be26fa192bff9399e27600ee9048880d9ba15195a17c01f31bd3c501fe00de6e2a3d3b86636c7f791f7e1
|
|
7
|
+
data.tar.gz: b1162525fed73dd1a16c09d0b33d71c53d83c414e9c3731f1de6e83aa69ad0c9e1bf0a6d917d9db815c3342d4a7627b9c8f5504ba0e1cdf32f2e0c1006511947
|
|
@@ -3,11 +3,17 @@
|
|
|
3
3
|
#include <stdbool.h>
|
|
4
4
|
|
|
5
5
|
typedef int (*mallctl_fn)(const char *, void *, size_t *, void *, size_t);
|
|
6
|
+
typedef void (*write_cb_t)(void *, const char *);
|
|
7
|
+
typedef void (*malloc_stats_print_fn)(write_cb_t, void *, const char *);
|
|
6
8
|
|
|
7
9
|
static mallctl_fn my_mallctl = NULL;
|
|
10
|
+
static malloc_stats_print_fn my_malloc_stats_print = NULL;
|
|
8
11
|
|
|
9
12
|
#define JEMALLOC_CTL_DLOPEN_FALLBACK 0
|
|
10
13
|
|
|
14
|
+
// From jemalloc.h: special arena index meaning "all arenas"
|
|
15
|
+
#define MALLCTL_ARENAS_ALL 4096
|
|
16
|
+
|
|
11
17
|
#if JEMALLOC_CTL_DLOPEN_FALLBACK > 0
|
|
12
18
|
// used for testing
|
|
13
19
|
static const char *jemalloc_lib_names[] = {
|
|
@@ -48,12 +54,12 @@ static VALUE rb_jemalloc_ctl_version(VALUE self)
|
|
|
48
54
|
return rb_str_new_cstr(version);
|
|
49
55
|
}
|
|
50
56
|
|
|
51
|
-
static VALUE
|
|
57
|
+
static VALUE rb_jemalloc_ctl_toggle_background_thread(VALUE self, VALUE onoff)
|
|
52
58
|
{
|
|
53
59
|
if (my_mallctl == NULL)
|
|
54
60
|
rb_raise(rb_eRuntimeError, "jemalloc is not available");
|
|
55
61
|
|
|
56
|
-
bool val =
|
|
62
|
+
bool val = RTEST(onoff);
|
|
57
63
|
int err = my_mallctl("background_thread", NULL, NULL, &val, sizeof(bool));
|
|
58
64
|
|
|
59
65
|
if (err != 0)
|
|
@@ -62,34 +68,93 @@ static VALUE rb_jemalloc_ctl_enable_background_thread(VALUE self)
|
|
|
62
68
|
return Qtrue;
|
|
63
69
|
}
|
|
64
70
|
|
|
65
|
-
static VALUE
|
|
71
|
+
static VALUE rb_jemalloc_ctl_toggle_current_thread_tcache(VALUE self, VALUE onoff)
|
|
66
72
|
{
|
|
67
73
|
if (my_mallctl == NULL)
|
|
68
74
|
rb_raise(rb_eRuntimeError, "jemalloc is not available");
|
|
69
75
|
|
|
70
|
-
bool
|
|
71
|
-
int err = my_mallctl("
|
|
76
|
+
bool enabled = RTEST(onoff);
|
|
77
|
+
int err = my_mallctl("thread.tcache.enabled", NULL, NULL, &enabled, sizeof(enabled));
|
|
72
78
|
|
|
73
79
|
if (err != 0)
|
|
74
|
-
rb_raise(rb_eRuntimeError, "mallctl(\"
|
|
80
|
+
rb_raise(rb_eRuntimeError, "mallctl(\"thread.tcache.enabled\") failed with error %d", err);
|
|
81
|
+
|
|
82
|
+
return Qtrue;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
static VALUE rb_jemalloc_ctl_flush_current_thread_tcache(VALUE self)
|
|
86
|
+
{
|
|
87
|
+
if (my_mallctl == NULL)
|
|
88
|
+
rb_raise(rb_eRuntimeError, "jemalloc is not available");
|
|
89
|
+
|
|
90
|
+
int err = my_mallctl("thread.tcache.flush", NULL, NULL, NULL, 0);
|
|
75
91
|
|
|
76
|
-
|
|
92
|
+
if (err != 0)
|
|
93
|
+
rb_raise(rb_eRuntimeError, "mallctl(\"thread.tcache.flush\") failed with error %d", err);
|
|
94
|
+
|
|
95
|
+
return Qtrue;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
static VALUE rb_jemalloc_ctl_purge_arenas(VALUE self)
|
|
99
|
+
{
|
|
100
|
+
if (my_mallctl == NULL)
|
|
101
|
+
rb_raise(rb_eRuntimeError, "jemalloc is not available");
|
|
102
|
+
|
|
103
|
+
char ctl[32];
|
|
104
|
+
snprintf(ctl, sizeof(ctl), "arena.%d.purge", MALLCTL_ARENAS_ALL);
|
|
105
|
+
|
|
106
|
+
int err = my_mallctl(ctl, NULL, NULL, NULL, 0);
|
|
107
|
+
|
|
108
|
+
if (err != 0)
|
|
109
|
+
rb_raise(rb_eRuntimeError, "mallctl(\"%s\") failed with error %d", ctl, err);
|
|
110
|
+
|
|
111
|
+
return Qtrue;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
static void write_stats_cb(void *opaque, const char *buf)
|
|
115
|
+
{
|
|
116
|
+
fputs(buf, (FILE *)opaque);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
static VALUE rb_jemalloc_ctl_print_stats(VALUE self, VALUE filename)
|
|
120
|
+
{
|
|
121
|
+
if (my_malloc_stats_print == NULL)
|
|
122
|
+
rb_raise(rb_eRuntimeError, "malloc_stats_print is not available");
|
|
123
|
+
|
|
124
|
+
const char *path = StringValueCStr(filename);
|
|
125
|
+
FILE *f = fopen(path, "w");
|
|
126
|
+
if (f == NULL)
|
|
127
|
+
rb_sys_fail(path);
|
|
128
|
+
|
|
129
|
+
my_malloc_stats_print(write_stats_cb, f, NULL);
|
|
130
|
+
|
|
131
|
+
fclose(f);
|
|
132
|
+
return Qtrue;
|
|
77
133
|
}
|
|
78
134
|
|
|
79
|
-
static
|
|
135
|
+
static bool find_jemalloc_fns_in(void *handle)
|
|
80
136
|
{
|
|
81
137
|
// Try unprefixed (jemalloc as default allocator) then je_-prefixed
|
|
82
|
-
mallctl_fn
|
|
83
|
-
if (
|
|
84
|
-
|
|
85
|
-
|
|
138
|
+
mallctl_fn mallctl = (mallctl_fn)dlsym(handle, "mallctl");
|
|
139
|
+
if (mallctl == NULL)
|
|
140
|
+
mallctl = (mallctl_fn)dlsym(handle, "je_mallctl");
|
|
141
|
+
if (mallctl == NULL)
|
|
142
|
+
return false;
|
|
143
|
+
|
|
144
|
+
malloc_stats_print_fn print_fn = (malloc_stats_print_fn)dlsym(handle, "malloc_stats_print");
|
|
145
|
+
if (print_fn == NULL)
|
|
146
|
+
print_fn = (malloc_stats_print_fn)dlsym(handle, "je_malloc_stats_print");
|
|
147
|
+
|
|
148
|
+
my_mallctl = mallctl;
|
|
149
|
+
my_malloc_stats_print = print_fn;
|
|
150
|
+
return true;
|
|
86
151
|
}
|
|
87
152
|
|
|
88
153
|
void Init_jemalloc_ctl(void)
|
|
89
154
|
{
|
|
90
155
|
// First: check if mallctl is already in the process
|
|
91
156
|
// (jemalloc compiled into Ruby or LD_PRELOADed)
|
|
92
|
-
|
|
157
|
+
find_jemalloc_fns_in(RTLD_DEFAULT);
|
|
93
158
|
|
|
94
159
|
#if JEMALLOC_CTL_DLOPEN_FALLBACK > 0
|
|
95
160
|
// Fallback: try to dlopen jemalloc from common paths
|
|
@@ -98,8 +163,7 @@ void Init_jemalloc_ctl(void)
|
|
|
98
163
|
for (const char **name = jemalloc_lib_names; *name != NULL; name++) {
|
|
99
164
|
jemalloc_handle = dlopen(*name, RTLD_LAZY);
|
|
100
165
|
if (jemalloc_handle != NULL) {
|
|
101
|
-
|
|
102
|
-
if (my_mallctl != NULL)
|
|
166
|
+
if (find_jemalloc_fns_in(jemalloc_handle))
|
|
103
167
|
break;
|
|
104
168
|
dlclose(jemalloc_handle);
|
|
105
169
|
jemalloc_handle = NULL;
|
|
@@ -111,6 +175,9 @@ void Init_jemalloc_ctl(void)
|
|
|
111
175
|
rb_mJemallocCtl = rb_define_module("JemallocCtl");
|
|
112
176
|
rb_define_singleton_method(rb_mJemallocCtl, "enabled?", rb_jemalloc_ctl_enabled_p, 0);
|
|
113
177
|
rb_define_singleton_method(rb_mJemallocCtl, "version", rb_jemalloc_ctl_version, 0);
|
|
114
|
-
rb_define_singleton_method(rb_mJemallocCtl, "
|
|
115
|
-
rb_define_singleton_method(rb_mJemallocCtl, "
|
|
178
|
+
rb_define_singleton_method(rb_mJemallocCtl, "print_stats", rb_jemalloc_ctl_print_stats, 1);
|
|
179
|
+
rb_define_singleton_method(rb_mJemallocCtl, "toggle_background_thread", rb_jemalloc_ctl_toggle_background_thread, 1);
|
|
180
|
+
rb_define_singleton_method(rb_mJemallocCtl, "purge_arenas", rb_jemalloc_ctl_purge_arenas, 0);
|
|
181
|
+
rb_define_singleton_method(rb_mJemallocCtl, "flush_current_thread_tcache", rb_jemalloc_ctl_flush_current_thread_tcache, 0);
|
|
182
|
+
rb_define_singleton_method(rb_mJemallocCtl, "toggle_current_thread_tcache", rb_jemalloc_ctl_toggle_current_thread_tcache, 1);
|
|
116
183
|
}
|
data/lib/jemalloc_ctl.rb
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
1
1
|
require "jemalloc_ctl/jemalloc_ctl"
|
|
2
2
|
module JemallocCtl
|
|
3
|
+
def self.disable_background_thread
|
|
4
|
+
toggle_background_thread(false)
|
|
5
|
+
end
|
|
6
|
+
def self.enable_background_thread
|
|
7
|
+
toggle_background_thread(true)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def self.disable_current_thread_tcache
|
|
11
|
+
toggle_current_thread_tcache(false)
|
|
12
|
+
end
|
|
13
|
+
def self.enable_current_thread_tcache
|
|
14
|
+
toggle_current_thread_tcache(true)
|
|
15
|
+
end
|
|
3
16
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: jemalloc_ctl
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Luke Gruber
|
|
@@ -40,5 +40,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
40
40
|
requirements: []
|
|
41
41
|
rubygems_version: 4.0.6
|
|
42
42
|
specification_version: 4
|
|
43
|
-
summary: Configure jemalloc via mallctl
|
|
43
|
+
summary: Configure jemalloc via mallctl from Ruby
|
|
44
44
|
test_files: []
|