Skip to content

Commit dc05349

Browse files
d-nettoRAI CI (GitHub Action Automation)
authored andcommitted
page profile (#123)
1 parent f61f5e3 commit dc05349

File tree

6 files changed

+296
-15
lines changed

6 files changed

+296
-15
lines changed

src/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ SRCS := \
4444
jltypes gf typemap smallintset ast builtins module interpreter symbol \
4545
dlload sys init task array staticdata toplevel jl_uv datatype \
4646
simplevector runtime_intrinsics precompile jloptions mtarraylist \
47-
threading partr stackwalk gc gc-debug gc-pages gc-stacks gc-alloc-profiler method \
47+
threading partr stackwalk gc gc-debug gc-pages gc-stacks gc-alloc-profiler gc-page-profiler method \
4848
jlapi signal-handling safepoint timing subtype rtutils gc-heap-snapshot \
4949
crc32c APInt-C processor ircode opaque_closure codegen-stubs coverage runtime_ccall
5050

src/gc-page-profiler.c

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
// This file is a part of Julia. License is MIT: https://julialang.org/license
2+
3+
#include "gc-page-profiler.h"
4+
5+
#ifdef __cplusplus
6+
extern "C" {
7+
#endif
8+
9+
// whether page profiling is enabled
10+
int page_profile_enabled;
11+
// number of pages written
12+
size_t page_profile_pages_written;
13+
// stream to write page profile to
14+
ios_t *page_profile_stream;
15+
// mutex for page profile
16+
uv_mutex_t page_profile_lock;
17+
18+
gc_page_profiler_serializer_t gc_page_serializer_create(void) JL_NOTSAFEPOINT
19+
{
20+
gc_page_profiler_serializer_t serializer;
21+
if (__unlikely(page_profile_enabled)) {
22+
arraylist_new(&serializer.typestrs, GC_PAGE_SZ);
23+
}
24+
else {
25+
serializer.typestrs.len = 0;
26+
}
27+
return serializer;
28+
}
29+
30+
void gc_page_serializer_init(gc_page_profiler_serializer_t *serializer,
31+
jl_gc_pagemeta_t *pg) JL_NOTSAFEPOINT
32+
{
33+
if (__unlikely(page_profile_enabled)) {
34+
serializer->typestrs.len = 0;
35+
serializer->data = (char *)pg->data;
36+
serializer->osize = pg->osize;
37+
}
38+
}
39+
40+
void gc_page_serializer_destroy(gc_page_profiler_serializer_t *serializer) JL_NOTSAFEPOINT
41+
{
42+
if (__unlikely(page_profile_enabled)) {
43+
arraylist_free(&serializer->typestrs);
44+
}
45+
}
46+
47+
void gc_page_serializer_write(gc_page_profiler_serializer_t *serializer,
48+
const char *str) JL_NOTSAFEPOINT
49+
{
50+
if (__unlikely(page_profile_enabled)) {
51+
arraylist_push(&serializer->typestrs, (void *)str);
52+
}
53+
}
54+
55+
void gc_enable_page_profile(void) JL_NOTSAFEPOINT
56+
{
57+
page_profile_enabled = 1;
58+
}
59+
60+
void gc_disable_page_profile(void) JL_NOTSAFEPOINT
61+
{
62+
page_profile_enabled = 0;
63+
}
64+
65+
int gc_page_profile_is_enabled(void) JL_NOTSAFEPOINT
66+
{
67+
return page_profile_enabled;
68+
}
69+
70+
void gc_page_profile_write_preamble(gc_page_profiler_serializer_t *serializer)
71+
JL_NOTSAFEPOINT
72+
{
73+
if (__unlikely(page_profile_enabled)) {
74+
char str[GC_TYPE_STR_MAXLEN];
75+
snprintf(str, GC_TYPE_STR_MAXLEN,
76+
"{\"address\": \"%p\",\"object_size\": %d,\"objects\": [",
77+
serializer->data, serializer->osize);
78+
ios_write(page_profile_stream, str, strlen(str));
79+
}
80+
}
81+
82+
void gc_page_profile_write_epilogue(gc_page_profiler_serializer_t *serializer)
83+
JL_NOTSAFEPOINT
84+
{
85+
if (__unlikely(page_profile_enabled)) {
86+
const char *str = "]}";
87+
ios_write(page_profile_stream, str, strlen(str));
88+
}
89+
}
90+
91+
void gc_page_profile_write_comma(gc_page_profiler_serializer_t *serializer) JL_NOTSAFEPOINT
92+
{
93+
if (__unlikely(page_profile_enabled)) {
94+
// write comma if not first page
95+
if (page_profile_pages_written > 0) {
96+
const char *str = ",";
97+
ios_write(page_profile_stream, str, strlen(str));
98+
}
99+
}
100+
}
101+
102+
void gc_page_profile_write_to_file(gc_page_profiler_serializer_t *serializer)
103+
JL_NOTSAFEPOINT
104+
{
105+
if (__unlikely(page_profile_enabled)) {
106+
// write to file
107+
uv_mutex_lock(&page_profile_lock);
108+
gc_page_profile_write_comma(serializer);
109+
gc_page_profile_write_preamble(serializer);
110+
char str[GC_TYPE_STR_MAXLEN];
111+
for (size_t i = 0; i < serializer->typestrs.len; i++) {
112+
const char *name = (const char *)serializer->typestrs.items[i];
113+
if (name == GC_SERIALIZER_EMPTY) {
114+
snprintf(str, GC_TYPE_STR_MAXLEN, "\"empty\",");
115+
}
116+
else if (name == GC_SERIALIZER_GARBAGE) {
117+
snprintf(str, GC_TYPE_STR_MAXLEN, "\"garbage\",");
118+
}
119+
else {
120+
snprintf(str, GC_TYPE_STR_MAXLEN, "\"%s\",", name);
121+
}
122+
// remove trailing comma for last element
123+
if (i == serializer->typestrs.len - 1) {
124+
str[strlen(str) - 1] = '\0';
125+
}
126+
ios_write(page_profile_stream, str, strlen(str));
127+
}
128+
gc_page_profile_write_epilogue(serializer);
129+
page_profile_pages_written++;
130+
uv_mutex_unlock(&page_profile_lock);
131+
}
132+
}
133+
134+
void gc_page_profile_write_json_preamble(ios_t *stream) JL_NOTSAFEPOINT
135+
{
136+
if (__unlikely(page_profile_enabled)) {
137+
uv_mutex_lock(&page_profile_lock);
138+
const char *str = "{\"pages\": [";
139+
ios_write(stream, str, strlen(str));
140+
uv_mutex_unlock(&page_profile_lock);
141+
}
142+
}
143+
144+
void gc_page_profile_write_json_epilogue(ios_t *stream) JL_NOTSAFEPOINT
145+
{
146+
if (__unlikely(page_profile_enabled)) {
147+
uv_mutex_lock(&page_profile_lock);
148+
const char *str = "]}";
149+
ios_write(stream, str, strlen(str));
150+
uv_mutex_unlock(&page_profile_lock);
151+
}
152+
}
153+
154+
JL_DLLEXPORT void jl_gc_take_page_profile(ios_t *stream)
155+
{
156+
gc_enable_page_profile();
157+
page_profile_pages_written = 0;
158+
page_profile_stream = stream;
159+
gc_page_profile_write_json_preamble(stream);
160+
jl_gc_collect(JL_GC_FULL);
161+
gc_page_profile_write_json_epilogue(stream);
162+
gc_disable_page_profile();
163+
}
164+
165+
#ifdef __cplusplus
166+
}
167+
#endif

src/gc-page-profiler.h

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// This file is a part of Julia. License is MIT: https://julialang.org/license
2+
3+
#ifndef GC_PAGE_PROFILER_H
4+
#define GC_PAGE_PROFILER_H
5+
6+
#include "gc.h"
7+
8+
#ifdef __cplusplus
9+
extern "C" {
10+
#endif
11+
12+
#define GC_TYPE_STR_MAXLEN (512)
13+
14+
typedef struct {
15+
arraylist_t typestrs;
16+
char *data;
17+
int osize;
18+
} gc_page_profiler_serializer_t;
19+
20+
// mutex for page profile
21+
extern uv_mutex_t page_profile_lock;
22+
23+
// Serializer functions
24+
gc_page_profiler_serializer_t gc_page_serializer_create(void) JL_NOTSAFEPOINT;
25+
void gc_page_serializer_init(gc_page_profiler_serializer_t *serializer, jl_gc_pagemeta_t *pg) JL_NOTSAFEPOINT;
26+
void gc_page_serializer_destroy(gc_page_profiler_serializer_t *serializer) JL_NOTSAFEPOINT;
27+
void gc_page_serializer_write(gc_page_profiler_serializer_t *serializer, const char *str) JL_NOTSAFEPOINT;
28+
// Page profile functions
29+
#define GC_SERIALIZER_EMPTY ((const char *)0x1)
30+
#define GC_SERIALIZER_GARBAGE ((const char *)0x2)
31+
STATIC_INLINE void gc_page_profile_write_empty_page(gc_page_profiler_serializer_t *serializer,
32+
int enabled) JL_NOTSAFEPOINT
33+
{
34+
if (__unlikely(enabled)) {
35+
gc_page_serializer_write(serializer, GC_SERIALIZER_EMPTY);
36+
}
37+
}
38+
STATIC_INLINE void gc_page_profile_write_garbage(gc_page_profiler_serializer_t *serializer,
39+
int enabled) JL_NOTSAFEPOINT
40+
{
41+
if (__unlikely(enabled)) {
42+
gc_page_serializer_write(serializer, GC_SERIALIZER_GARBAGE);
43+
}
44+
}
45+
STATIC_INLINE void gc_page_profile_write_live_obj(gc_page_profiler_serializer_t *serializer,
46+
jl_taggedvalue_t *v,
47+
int enabled) JL_NOTSAFEPOINT
48+
{
49+
if (__unlikely(enabled)) {
50+
const char *name = jl_typeof_str(jl_valueof(v));
51+
gc_page_serializer_write(serializer, name);
52+
}
53+
}
54+
void gc_enable_page_profile(void) JL_NOTSAFEPOINT;
55+
void gc_disable_page_profile(void) JL_NOTSAFEPOINT;
56+
int gc_page_profile_is_enabled(void) JL_NOTSAFEPOINT;
57+
void gc_page_profile_write_to_file(gc_page_profiler_serializer_t *serializer) JL_NOTSAFEPOINT;
58+
59+
#ifdef __cplusplus
60+
}
61+
#endif
62+
63+
#endif // GC_PAGE_PROFILER_H

0 commit comments

Comments
 (0)