summaryrefslogtreecommitdiffstats
path: root/meta/recipes-extended/lighttpd/lighttpd/0001-core-reuse-large-mem-chunks-fix-mem-usage-fixes-3033.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-extended/lighttpd/lighttpd/0001-core-reuse-large-mem-chunks-fix-mem-usage-fixes-3033.patch')
-rw-r--r--meta/recipes-extended/lighttpd/lighttpd/0001-core-reuse-large-mem-chunks-fix-mem-usage-fixes-3033.patch224
1 files changed, 224 insertions, 0 deletions
diff --git a/meta/recipes-extended/lighttpd/lighttpd/0001-core-reuse-large-mem-chunks-fix-mem-usage-fixes-3033.patch b/meta/recipes-extended/lighttpd/lighttpd/0001-core-reuse-large-mem-chunks-fix-mem-usage-fixes-3033.patch
new file mode 100644
index 0000000000..e226366112
--- /dev/null
+++ b/meta/recipes-extended/lighttpd/lighttpd/0001-core-reuse-large-mem-chunks-fix-mem-usage-fixes-3033.patch
@@ -0,0 +1,224 @@
1From a566fe4cc9f9d0ef9cfdcbc13159ef0644e91c9c Mon Sep 17 00:00:00 2001
2From: Glenn Strauss <gstrauss@gluelogic.com>
3Date: Wed, 23 Dec 2020 23:14:47 -0500
4Subject: [PATCH] reuse large mem chunks (fix mem usage) (fixes #3033)
5
6(cherry picked from commit 7ba521ffb4959f6f74a609d5d4acafc29a038337)
7
8(thx flynn)
9
10fix large memory usage for large file downloads from dynamic backends
11
12reuse or release large memory chunks
13
14x-ref:
15 "Memory Growth with PUT and full buffered streams"
16 https://redmine.lighttpd.net/issues/3033
17
18Upstream-Status: Backport
19Comment: Hunk refreshed to make it backword compatible.
20https://redmine.lighttpd.net/projects/lighttpd/repository/14/revisions/7ba521ffb4959f6f74a609d5d4acafc29a038337
21Signed-off-by: Purushottam Choudhary <Purushottam.Choudhary@kpit.com>
22
23---
24 src/chunk.c | 99 +++++++++++++++++++++++++++++++++---------
25 src/chunk.h | 2 +
26 src/http-header-glue.c | 2 +-
27 3 files changed, 82 insertions(+), 21 deletions(-)
28
29diff --git a/src/chunk.c b/src/chunk.c
30index 133308f..d7259b9 100644
31--- a/src/chunk.c
32+++ b/src/chunk.c
33@@ -28,16 +28,20 @@
34 static size_t chunk_buf_sz = 8192;
35 static chunk *chunks, *chunks_oversized;
36 static chunk *chunk_buffers;
37+static int chunks_oversized_n;
38 static array *chunkqueue_default_tempdirs = NULL;
39 static off_t chunkqueue_default_tempfile_size = DEFAULT_TEMPFILE_SIZE;
40
41 void chunkqueue_set_chunk_size (size_t sz)
42 {
43- chunk_buf_sz = sz > 0 ? ((sz + 1023) & ~1023uL) : 8192;
44+ size_t x = 1024;
45+ while (x < sz && x < (1u << 30)) x <<= 1;
46+ chunk_buf_sz = sz > 0 ? x : 8192;
47 }
48
49 void chunkqueue_set_tempdirs_default_reset (void)
50 {
51+ chunk_buf_sz = 8192;
52 chunkqueue_default_tempdirs = NULL;
53 chunkqueue_default_tempfile_size = DEFAULT_TEMPFILE_SIZE;
54 }
55@@ -120,15 +124,49 @@ static void chunk_free(chunk *c) {
56 free(c);
57 }
58
59-buffer * chunk_buffer_acquire(void) {
60+static chunk * chunk_pop_oversized(size_t sz) {
61+ /* future: might have buckets of certain sizes, up to socket buf sizes */
62+ if (chunks_oversized && chunks_oversized->mem->size >= sz) {
63+ --chunks_oversized_n;
64+ chunk *c = chunks_oversized;
65+ chunks_oversized = c->next;
66+ return c;
67+ }
68+ return NULL;
69+}
70+
71+static void chunk_push_oversized(chunk * const c, const size_t sz) {
72+ if (chunks_oversized_n < 64 && chunk_buf_sz >= 4096) {
73+ ++chunks_oversized_n;
74+ chunk **co = &chunks_oversized;
75+ while (*co && sz < (*co)->mem->size) co = &(*co)->next;
76+ c->next = *co;
77+ *co = c;
78+ }
79+ else
80+ chunk_free(c);
81+}
82+
83+static buffer * chunk_buffer_acquire_sz(size_t sz) {
84 chunk *c;
85 buffer *b;
86- if (chunks) {
87- c = chunks;
88- chunks = c->next;
89+ if (sz <= chunk_buf_sz) {
90+ if (chunks) {
91+ c = chunks;
92+ chunks = c->next;
93+ }
94+ else
95+ c = chunk_init(chunk_buf_sz);
96+ /* future: might choose to pop from chunks_oversized, if available
97+ * (even if larger than sz) rather than allocating new chunk
98+ * (and if doing so, might replace chunks_oversized_n) */
99 }
100 else {
101- c = chunk_init(chunk_buf_sz);
102+ /*(round up to nearest chunk_buf_sz)*/
103+ sz = (sz + (chunk_buf_sz-1)) & ~(chunk_buf_sz-1);
104+ c = chunk_pop_oversized(sz);
105+ if (NULL == c)
106+ c = chunk_init(sz);
107 }
108 c->next = chunk_buffers;
109 chunk_buffers = c;
110@@ -137,21 +175,47 @@ buffer * chunk_buffer_acquire(void) {
111 return b;
112 }
113
114+buffer * chunk_buffer_acquire(void) {
115+ return chunk_buffer_acquire_sz(chunk_buf_sz);
116+}
117+
118 void chunk_buffer_release(buffer *b) {
119 if (NULL == b) return;
120- if (b->size >= chunk_buf_sz && chunk_buffers) {
121+ if (chunk_buffers) {
122 chunk *c = chunk_buffers;
123 chunk_buffers = c->next;
124 c->mem = b;
125- c->next = chunks;
126- chunks = c;
127 buffer_clear(b);
128+ if (b->size == chunk_buf_sz) {
129+ c->next = chunks;
130+ chunks = c;
131+ }
132+ else if (b->size > chunk_buf_sz)
133+ chunk_push_oversized(c, b->size);
134+ else
135+ chunk_free(c);
136 }
137 else {
138 buffer_free(b);
139 }
140 }
141
142+size_t chunk_buffer_prepare_append(buffer * const b, size_t sz) {
143+ if (sz > chunk_buffer_string_space(b)) {
144+ sz += b->used ? b->used : 1;
145+ buffer * const cb = chunk_buffer_acquire_sz(sz);
146+ /* swap buffer contents and copy original b->ptr into larger b->ptr */
147+ /*(this does more than buffer_move())*/
148+ buffer tb = *b;
149+ *b = *cb;
150+ *cb = tb;
151+ if ((b->used = tb.used))
152+ memcpy(b->ptr, tb.ptr, tb.used);
153+ chunk_buffer_release(cb);
154+ }
155+ return chunk_buffer_string_space(b);
156+}
157+
158 static chunk * chunk_acquire(size_t sz) {
159 if (sz <= chunk_buf_sz) {
160 if (chunks) {
161@@ -162,13 +226,10 @@ static chunk * chunk_acquire(size_t sz) {
162 sz = chunk_buf_sz;
163 }
164 else {
165- sz = (sz + 8191) & ~8191uL;
166- /* future: might have buckets of certain sizes, up to socket buf sizes*/
167- if (chunks_oversized && chunks_oversized->mem->size >= sz) {
168- chunk *c = chunks_oversized;
169- chunks_oversized = c->next;
170- return c;
171- }
172+ /*(round up to nearest chunk_buf_sz)*/
173+ sz = (sz + (chunk_buf_sz-1)) & ~(chunk_buf_sz-1);
174+ chunk *c = chunk_pop_oversized(sz);
175+ if (c) return c;
176 }
177
178 return chunk_init(sz);
179@@ -183,10 +244,7 @@ static void chunk_release(chunk *c) {
180 }
181 else if (sz > chunk_buf_sz) {
182 chunk_reset(c);
183- chunk **co = &chunks_oversized;
184- while (*co && sz < (*co)->mem->size) co = &(*co)->next;
185- c->next = *co;
186- *co = c;
187+ chunk_push_oversized(c, sz);
188 }
189 else {
190 chunk_free(c);
191@@ -205,6 +263,7 @@ void chunkqueue_chunk_pool_clear(void)
192 chunk_free(c);
193 }
194 chunks_oversized = NULL;
195+ chunks_oversized_n = 0;
196 }
197
198 void chunkqueue_chunk_pool_free(void)
199diff --git a/src/chunk.h b/src/chunk.h
200index 4c6b7e4..93f343c 100644
201--- a/src/chunk.h
202+++ b/src/chunk.h
203@@ -50,6 +50,8 @@ typedef struct {
204 buffer * chunk_buffer_acquire(void);
205 void chunk_buffer_release(buffer *b);
206
207+size_t chunk_buffer_prepare_append (buffer *b, size_t sz);
208+
209 void chunkqueue_chunk_pool_clear(void);
210 void chunkqueue_chunk_pool_free(void);
211
212diff --git a/src/http-header-glue.c b/src/http-header-glue.c
213index d54f00c..2231fba 100644
214--- a/src/http-header-glue.c
215+++ b/src/http-header-glue.c
216@@ -1267,7 +1267,7 @@ handler_t http_response_read(server *srv, connection *con, http_response_opts *o
217 if (avail < toread) {
218 /*(add avail+toread to reduce allocations when ioctl EOPNOTSUPP)*/
219 avail = avail ? avail - 1 + toread : toread;
220- buffer_string_prepare_append(b, avail);
221+ avail = chunk_buffer_prepare_append(b, avail);
222 }
223
224 n = read(fd, b->ptr+buffer_string_length(b), avail);