Skip to content

Commit 6785ee1

Browse files
authored
Reorganize the system-heap measurement. (#232)
Introduced a new jstest_memstat.c file that contains all the memory monitoring functions (from the patch files). Added custom allocator functions (jstest_malloc, jstest_realloc, ...) that can allocate memory and monitor its usage. In this case the content of the system-heap patches can be reduced, because it's simply enough to use the jstest allocator functions instead of the system allocator ones. JSRemoteTest-DCO-1.0-Signed-off-by: Roland Takacs [email protected]
1 parent 78b2594 commit 6785ee1

File tree

5 files changed

+202
-210
lines changed

5 files changed

+202
-210
lines changed

jstest/builder/modules/iotjs.build.config

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,12 @@
5252
"--cmake-param=-DENABLE_MODULE_MYMODULE1=ON",
5353
"--cmake-param=-DENABLE_MODULE_MYMODULE2=ON"
5454
]
55+
},
56+
{
57+
"condition": "%{test-build} and %{memstat}",
58+
"args": [
59+
"--compile-flag=-DJSTEST_MEMSTAT_ENABLED"
60+
]
5561
}
5662
]
5763
},
@@ -114,6 +120,14 @@
114120
]
115121
}
116122
},
123+
{
124+
"condition": "%{test-build} and %{memstat}",
125+
"env": {
126+
"IOTJS_BUILD_OPTION": [
127+
"--compile-flag=-DJSTEST_MEMSTAT_ENABLED"
128+
]
129+
}
130+
},
117131
{
118132
"condition": "%{memstat}",
119133
"env": { "IOTJS_BUILD_OPTION": ["--jerry-memstat"] }
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/* Copyright 2018-present Samsung Electronics Co., Ltd. and other contributors
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
/*
17+
* Memory statistic for system allocator.
18+
*
19+
* When allocating a chunk of memory, the real size (required memory with padding) is
20+
* located in a descriptor (mm_freenode_s) before the allocated memory area:
21+
*
22+
* struct mm_freenode_s
23+
* {
24+
* mmsize_t size; // Size of the chunk
25+
* mmsize_t preceding; // Size of the preceding chunk
26+
* ...
27+
* };
28+
*
29+
* +---------------+--------------------------------------+
30+
* | mm_freenode_s | allocated memory chunk |
31+
* +---------------+--------------------------------------+
32+
* ^
33+
* pointer to the data
34+
*
35+
* Note: on NuttX and TizenRT, the `size` variable contains the size of the
36+
* mm_freenode_s as well, but that is not calculated into the statistic.
37+
*/
38+
#if defined(JSTEST_MEMSTAT_ENABLED)
39+
#include <stdio.h>
40+
#include <stdlib.h>
41+
42+
#if defined(__NUTTX__)
43+
#include <nuttx/mm/mm.h>
44+
#elif defined(__TIZENRT__)
45+
#include <tinyara/mm/mm.h>
46+
#else
47+
#error "The current target is not supported to track the memory consumption."
48+
#endif
49+
50+
static size_t allocated_bytes = 0;
51+
static size_t peak_allocated_bytes = 0;
52+
53+
54+
static size_t read_memsize(char* ptr) {
55+
struct mm_freenode_s* node;
56+
57+
if (ptr == NULL) {
58+
return 0;
59+
}
60+
61+
node = (struct mm_freenode_s*)(ptr - SIZEOF_MM_ALLOCNODE);
62+
// Note: the allocnode descriptor size is not calculated
63+
// into the allocated memory.
64+
return node->size - SIZEOF_MM_ALLOCNODE;
65+
}
66+
67+
68+
static void mem_stat_alloc(void* ptr)
69+
{
70+
allocated_bytes += read_memsize(ptr);
71+
72+
if (allocated_bytes > peak_allocated_bytes) {
73+
peak_allocated_bytes = allocated_bytes;
74+
}
75+
}
76+
77+
78+
static void mem_stat_free(void* ptr)
79+
{
80+
allocated_bytes -= read_memsize(ptr);
81+
}
82+
83+
84+
void* jstest_malloc(size_t size) {
85+
void* mem = malloc(size);
86+
87+
mem_stat_alloc(mem);
88+
89+
return mem;
90+
}
91+
92+
93+
void* jstest_calloc(size_t n, size_t elem_size) {
94+
void* mem = calloc(n, elem_size);
95+
96+
mem_stat_alloc(mem);
97+
98+
return mem;
99+
}
100+
101+
102+
void* jstest_realloc(void* oldmem, size_t size) {
103+
mem_stat_free(oldmem);
104+
105+
void* newmem = realloc(oldmem, size);
106+
107+
mem_stat_alloc(newmem);
108+
109+
return newmem;
110+
}
111+
112+
113+
void jstest_free(void *mem) {
114+
mem_stat_free(mem);
115+
116+
free(mem);
117+
}
118+
119+
120+
void print_mem_stat() {
121+
printf("Heap stats:\n");
122+
printf(" Malloc peak allocated: %u bytes\n", peak_allocated_bytes);
123+
}
124+
125+
#endif /* JSTEST_MEMSTAT_ENABLED */
Lines changed: 33 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,17 @@
11
diff --git a/src/iotjs.c b/src/iotjs.c
2-
index 5a93eb7..4a5a8bd 100644
2+
index 2df7e0f..bd7b62f 100644
33
--- a/src/iotjs.c
44
+++ b/src/iotjs.c
5-
@@ -242,6 +242,9 @@ terminate:
5+
@@ -234,6 +234,8 @@ void iotjs_conf_console_out(int (*out)(int lv, const char* fmt, ...)) {
6+
iotjs_set_console_out(out);
7+
}
8+
9+
+void print_mem_stat();
10+
+
11+
int iotjs_entry(int argc, char** argv) {
12+
int ret_code = 0;
13+
14+
@@ -265,6 +267,9 @@ terminate:
615
iotjs_terminate(env);
716

817
exit:
@@ -13,130 +22,45 @@ index 5a93eb7..4a5a8bd 100644
1322
iotjs_environment_config(env)->debugger->context_reset) {
1423
iotjs_environment_release();
1524
diff --git a/src/iotjs_util.c b/src/iotjs_util.c
16-
index abd7a86..cc6b4e3 100644
25+
index abd7a86..5668015 100644
1726
--- a/src/iotjs_util.c
1827
+++ b/src/iotjs_util.c
19-
@@ -75,12 +75,76 @@ iotjs_string_t iotjs_file_read(const char* path) {
20-
}
28+
@@ -27,6 +27,11 @@
29+
30+
void force_terminate();
31+
32+
+void jstest_free(void*);
33+
+void* jstest_malloc(size_t);
34+
+void* jstest_calloc(size_t, size_t);
35+
+void* jstest_realloc(void*, size_t);
36+
+
37+
iotjs_string_t iotjs_file_read(const char* path) {
38+
FILE* file = fopen(path, "rb");
39+
if (file == NULL) {
40+
@@ -76,7 +81,7 @@ iotjs_string_t iotjs_file_read(const char* path) {
2141

2242

23-
+/*
24-
+ * Memory statistic for system allocator.
25-
+ *
26-
+ *
27-
+ * When allocating a chunk of memory, the real size (with padding) is
28-
+ * located in a descriptor (mm_allocnode_s) before the allocated memory area:
29-
+ *
30-
+ * struct mm_freenode_s
31-
+ * {
32-
+ * mmsize_t size; // Size of the chunk
33-
+ * ...
34-
+ * };
35-
+ *
36-
+ * The SIZEOF_MM_ALLOCNODE defines the size of the mm_allocnode_s structure,
37-
+ * that helps to find the size variable.
38-
+ *
39-
+ * Note: on NuttX and TizenRT, the size variable contains the size of the
40-
+ * mm_freenode_s as well, but that is not calculated into the statistic.
41-
+ *
42-
+ * The SIZEOF_MM_ALLOCNODE is defined in:
43-
+ *
44-
+ * NuttX: include/nuttx/mm/mm.h
45-
+ * TizenRT: os/include/tinyara/mm/mm.h
46-
+ */
47-
+
48-
+#if defined(__NUTTX__) || defined(__TIZENRT__)
49-
+#if !defined(NDEBUG) && defined(__TIZENRT__)
50-
+#define SIZEOF_MM_ALLOCNODE 16
51-
+#else
52-
+#define SIZEOF_MM_ALLOCNODE 8
53-
+#endif
54-
+#else
55-
+#error "Undefined memory allocation chunk size."
56-
+#endif
57-
+
58-
+size_t allocated_bytes = 0;
59-
+size_t peak_allocated_bytes = 0;
60-
+
61-
+void mem_stat_alloc(size_t size)
62-
+{
63-
+ allocated_bytes += size;
64-
+
65-
+ if (allocated_bytes > peak_allocated_bytes) {
66-
+ peak_allocated_bytes = allocated_bytes;
67-
+ }
68-
+}
69-
+
70-
+void mem_stat_free(size_t size)
71-
+{
72-
+ allocated_bytes -= size;
73-
+}
74-
+
75-
+void print_mem_stat()
76-
+{
77-
+ printf("Heap stats:\n");
78-
+ printf(" Malloc peak allocated: %u bytes\n", peak_allocated_bytes);
79-
+}
80-
+
8143
char* iotjs_buffer_allocate(size_t size) {
82-
char* buffer = (char*)(calloc(size, sizeof(char)));
44+
- char* buffer = (char*)(calloc(size, sizeof(char)));
45+
+ char* buffer = (char*)(jstest_calloc(size, sizeof(char)));
8346
if (buffer == NULL) {
8447
DLOG("Out of memory");
8548
force_terminate();
86-
}
87-
+
88-
+ // memstat
89-
+ size_t new_size;
90-
+ memcpy(&new_size, (buffer - SIZEOF_MM_ALLOCNODE), sizeof(size_t));
91-
+ mem_stat_alloc(new_size - SIZEOF_MM_ALLOCNODE);
92-
+
93-
return buffer;
94-
}
95-
96-
@@ -99,17 +163,31 @@ char* iotjs_buffer_allocate_from_number_array(size_t size,
49+
@@ -99,7 +104,7 @@ char* iotjs_buffer_allocate_from_number_array(size_t size,
9750

9851
char* iotjs_buffer_reallocate(char* buffer, size_t size) {
9952
IOTJS_ASSERT(buffer != NULL);
100-
+
101-
+ size_t old_size;
102-
+ memcpy(&old_size, (buffer - SIZEOF_MM_ALLOCNODE), sizeof(size_t));
103-
+ mem_stat_free(old_size - SIZEOF_MM_ALLOCNODE);
104-
+
105-
char* newbuffer = (char*)(realloc(buffer, size));
53+
- char* newbuffer = (char*)(realloc(buffer, size));
54+
+ char* newbuffer = (char*)(jstest_realloc(buffer, size));
10655
if (newbuffer == NULL) {
10756
DLOG("Out of memmory");
10857
force_terminate();
109-
}
110-
+
111-
+ size_t new_size;
112-
+ memcpy(&new_size, (newbuffer - SIZEOF_MM_ALLOCNODE), sizeof(size_t));
113-
+ mem_stat_alloc(new_size - SIZEOF_MM_ALLOCNODE);
114-
+
115-
return newbuffer;
116-
}
117-
58+
@@ -110,7 +115,7 @@ char* iotjs_buffer_reallocate(char* buffer, size_t size) {
11859

11960
void iotjs_buffer_release(char* buffer) {
12061
if (buffer) {
121-
+ size_t size;
122-
+ memcpy(&size, (buffer - SIZEOF_MM_ALLOCNODE), sizeof(size_t));
123-
+ mem_stat_free(size - SIZEOF_MM_ALLOCNODE);
124-
+
125-
free(buffer);
62+
- free(buffer);
63+
+ jstest_free(buffer);
12664
}
12765
}
128-
diff --git a/src/iotjs_util.h b/src/iotjs_util.h
129-
index a891604..786830e 100644
130-
--- a/src/iotjs_util.h
131-
+++ b/src/iotjs_util.h
132-
@@ -23,6 +23,10 @@
133-
// Return value should be released with iotjs_string_destroy()
134-
iotjs_string_t iotjs_file_read(const char* path);
13566

136-
+void mem_stat_alloc(size_t size);
137-
+void mem_stat_free(size_t size);
138-
+void print_mem_stat();
139-
+
140-
char* iotjs_buffer_allocate(size_t size);
141-
char* iotjs_buffer_allocate_from_number_array(size_t size,
142-
const jerry_value_t array);

0 commit comments

Comments
 (0)