Skip to content

Commit 855aa4c

Browse files
committed
Modules: removed extra VM creation per server.
Previously, when js_import was declared in http or stream blocks, an extra copy of the VM instance was created for each server block. This was not needed and consumed a lot of memory for configurations with many server blocks. This issue was introduced in 9b67441 (0.8.6) and was partially fixed for location blocks only in 685b64f (0.8.7).
1 parent 4fb1c0c commit 855aa4c

File tree

5 files changed

+194
-2
lines changed

5 files changed

+194
-2
lines changed

nginx/ngx_js.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3343,6 +3343,16 @@ ngx_js_merge_vm(ngx_conf_t *cf, ngx_js_loc_conf_t *conf,
33433343
ngx_array_t *imports, *preload_objects, *paths;
33443344
ngx_js_named_path_t *import, *pi, *pij, *preload;
33453345

3346+
if (prev->imports != NGX_CONF_UNSET_PTR && prev->engine == NULL) {
3347+
/*
3348+
* special handling to preserve conf->engine
3349+
* in the "http" or "stream" section to inherit it to all servers
3350+
*/
3351+
if (init_vm(cf, (ngx_js_loc_conf_t *) prev) != NGX_OK) {
3352+
return NGX_ERROR;
3353+
}
3354+
}
3355+
33463356
if (conf->imports == NGX_CONF_UNSET_PTR
33473357
&& conf->type == prev->type
33483358
&& conf->paths == NGX_CONF_UNSET_PTR
@@ -3851,6 +3861,9 @@ ngx_js_init_conf_vm(ngx_conf_t *cf, ngx_js_loc_conf_t *conf,
38513861
return NGX_ERROR;
38523862
}
38533863

3864+
ngx_log_error(NGX_LOG_NOTICE, cf->log, 0, "js vm init %s: %p",
3865+
conf->engine->name, conf->engine);
3866+
38543867
cln = ngx_pool_cleanup_add(cf->pool, 0);
38553868
if (cln == NULL) {
38563869
return NGX_ERROR;
@@ -4039,6 +4052,10 @@ ngx_js_merge_conf(ngx_conf_t *cf, void *parent, void *child,
40394052
ngx_js_loc_conf_t *conf = child;
40404053

40414054
ngx_conf_merge_uint_value(conf->type, prev->type, NGX_ENGINE_NJS);
4055+
if (prev->type == NGX_CONF_UNSET_UINT) {
4056+
prev->type = NGX_ENGINE_NJS;
4057+
}
4058+
40424059
ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 60000);
40434060
ngx_conf_merge_size_value(conf->reuse, prev->reuse, 128);
40444061
ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size, 16384);

nginx/t/js_import2.t

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ http {
4141
4242
js_set $test foo.bar.p;
4343
44+
# context 1
4445
js_import foo from main.js;
4546
4647
location /njs {
@@ -52,11 +53,13 @@ http {
5253
}
5354
5455
location /test_lib {
56+
# context 2
5557
js_import lib.js;
5658
js_content lib.test;
5759
}
5860
5961
location /test_fun {
62+
# context 3
6063
js_import fun.js;
6164
js_content fun;
6265
}
@@ -75,6 +78,7 @@ http {
7578
server_name localhost;
7679
7780
location /test_fun {
81+
# context 4
7882
js_import fun.js;
7983
js_content fun;
8084
}
@@ -114,7 +118,7 @@ $t->write_file('main.js', <<EOF);
114118
115119
EOF
116120

117-
$t->try_run('no njs available')->plan(5);
121+
$t->try_run('no njs available')->plan(6);
118122

119123
###############################################################################
120124

@@ -124,4 +128,10 @@ like(http_get('/test_fun'), qr/FUN-TEST/s, 'fun');
124128
like(http_get('/proxy/test_fun'), qr/FUN-TEST/s, 'proxy fun');
125129
like(http_get('/test_var'), qr/P-TEST/s, 'foo.bar.p');
126130

131+
$t->stop();
132+
133+
my $content = $t->read_file('error.log');
134+
my $count = () = $content =~ m/js vm init/g;
135+
ok($count == 4, 'uniq js vm contexts');
136+
127137
###############################################################################

nginx/t/js_merge_location_blocks.t

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
#!/usr/bin/perl
2+
3+
# (C) Dmitry Volyntsev
4+
# (c) Nginx, Inc.
5+
6+
# Tests for http njs module, check for proper location blocks merging.
7+
8+
###############################################################################
9+
10+
use warnings;
11+
use strict;
12+
13+
use Test::More;
14+
15+
BEGIN { use FindBin; chdir($FindBin::Bin); }
16+
17+
use lib 'lib';
18+
use Test::Nginx;
19+
20+
###############################################################################
21+
22+
select STDERR; $| = 1;
23+
select STDOUT; $| = 1;
24+
25+
my $t = Test::Nginx->new()->has(qw/http/)
26+
->write_file_expand('nginx.conf', <<'EOF');
27+
28+
%%TEST_GLOBALS%%
29+
30+
daemon off;
31+
32+
events {
33+
}
34+
35+
http {
36+
%%TEST_GLOBALS_HTTP%%
37+
38+
js_import main.js;
39+
40+
server {
41+
listen 127.0.0.1:8080;
42+
server_name localhost;
43+
44+
location /a {
45+
js_content main.version;
46+
}
47+
48+
location /b {
49+
js_content main.version;
50+
}
51+
52+
location /c {
53+
js_content main.version;
54+
}
55+
56+
location /d {
57+
js_content main.version;
58+
}
59+
}
60+
}
61+
62+
EOF
63+
64+
$t->write_file('main.js', <<EOF);
65+
function version(r) {
66+
r.return(200, njs.version);
67+
}
68+
69+
export default {version};
70+
71+
EOF
72+
73+
$t->try_run('no njs available')->plan(1);
74+
75+
###############################################################################
76+
77+
$t->stop();
78+
79+
my $content = $t->read_file('error.log');
80+
my $count = () = $content =~ m/ js vm init/g;
81+
ok($count == 1, 'http js block imported once');
82+
83+
###############################################################################

nginx/t/js_merge_server_blocks.t

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#!/usr/bin/perl
2+
3+
# (C) Dmitry Volyntsev
4+
# (c) Nginx, Inc.
5+
6+
# Tests for http njs module, check for proper server blocks merging.
7+
8+
###############################################################################
9+
10+
use warnings;
11+
use strict;
12+
13+
use Test::More;
14+
15+
BEGIN { use FindBin; chdir($FindBin::Bin); }
16+
17+
use lib 'lib';
18+
use Test::Nginx;
19+
20+
###############################################################################
21+
22+
select STDERR; $| = 1;
23+
select STDOUT; $| = 1;
24+
25+
my $t = Test::Nginx->new()->has(qw/http/)
26+
->write_file_expand('nginx.conf', <<'EOF');
27+
28+
%%TEST_GLOBALS%%
29+
30+
daemon off;
31+
32+
events {
33+
}
34+
35+
http {
36+
%%TEST_GLOBALS_HTTP%%
37+
38+
js_import main.js;
39+
40+
server {
41+
listen 127.0.0.1:8080;
42+
}
43+
44+
server {
45+
listen 127.0.0.1:8081;
46+
}
47+
48+
server {
49+
listen 127.0.0.1:8082;
50+
}
51+
52+
server {
53+
listen 127.0.0.1:8083;
54+
}
55+
}
56+
57+
EOF
58+
59+
$t->write_file('main.js', <<EOF);
60+
function version(r) {
61+
r.return(200, njs.version);
62+
}
63+
64+
export default {version};
65+
66+
EOF
67+
68+
$t->try_run('no njs available')->plan(1);
69+
70+
###############################################################################
71+
72+
$t->stop();
73+
74+
my $content = $t->read_file('error.log');
75+
my $count = () = $content =~ m/ js vm init/g;
76+
ok($count == 1, 'http js block imported once');
77+
78+
###############################################################################

nginx/t/stream_js.t

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ $t->write_file('test.js', <<EOF);
394394
EOF
395395

396396
$t->run_daemon(\&stream_daemon, port(8090));
397-
$t->try_run('no stream njs available')->plan(24);
397+
$t->try_run('no stream njs available')->plan(25);
398398
$t->waitforsocket('127.0.0.1:' . port(8090));
399399

400400
###############################################################################
@@ -450,6 +450,10 @@ like($t->read_file('status.log'), qr/$p[0]:200/, 'status undecided');
450450
like($t->read_file('status.log'), qr/$p[1]:200/, 'status allow');
451451
like($t->read_file('status.log'), qr/$p[2]:403/, 'status deny');
452452

453+
my $content = $t->read_file('error.log');
454+
my $count = () = $content =~ m/ js vm init/g;
455+
ok($count == 2, 'http and stream js blocks imported once each');
456+
453457
###############################################################################
454458

455459
sub has_version {

0 commit comments

Comments
 (0)