summaryrefslogtreecommitdiffhomepage
path: root/src/ruby
diff options
context:
space:
mode:
authorMax Romanov <max.romanov@nginx.com>2020-11-05 12:45:08 +0300
committerMax Romanov <max.romanov@nginx.com>2020-11-05 12:45:08 +0300
commit9f8b746e776031e6eef6dea84c8dafbb8c24c725 (patch)
tree137ddadcef40b387bfa0eda9815f4eec611ce407 /src/ruby
parent28f1eb55e7c5d60ab4f705eb27e67d31f3fc4ad0 (diff)
downloadunit-9f8b746e776031e6eef6dea84c8dafbb8c24c725.tar.gz
unit-9f8b746e776031e6eef6dea84c8dafbb8c24c725.tar.bz2
Ruby: reusing static constant references to string objects.
This shall save a couple of CPU cycles in request processing.
Diffstat (limited to 'src/ruby')
-rw-r--r--src/ruby/nxt_ruby.c158
1 files changed, 115 insertions, 43 deletions
diff --git a/src/ruby/nxt_ruby.c b/src/ruby/nxt_ruby.c
index 743bf646..7b383557 100644
--- a/src/ruby/nxt_ruby.c
+++ b/src/ruby/nxt_ruby.c
@@ -14,14 +14,6 @@
#define NXT_RUBY_RACK_API_VERSION_MAJOR 1
#define NXT_RUBY_RACK_API_VERSION_MINOR 3
-#define NXT_RUBY_STRINGIZE_HELPER(x) #x
-#define NXT_RUBY_STRINGIZE(x) NXT_RUBY_STRINGIZE_HELPER(x)
-
-#define NXT_RUBY_LIB_VERSION \
- NXT_RUBY_STRINGIZE(RUBY_API_VERSION_MAJOR) \
- "." NXT_RUBY_STRINGIZE(RUBY_API_VERSION_MINOR) \
- "." NXT_RUBY_STRINGIZE(RUBY_API_VERSION_TEENY)
-
typedef struct {
nxt_task_t *task;
@@ -45,10 +37,8 @@ static void nxt_ruby_request_handler(nxt_unit_request_info_t *req);
static VALUE nxt_ruby_rack_app_run(VALUE arg);
static int nxt_ruby_read_request(VALUE hash_env);
-nxt_inline void nxt_ruby_add_sptr(VALUE hash_env,
- const char *name, uint32_t name_len, nxt_unit_sptr_t *sptr, uint32_t len);
-nxt_inline void nxt_ruby_add_str(VALUE hash_env,
- const char *name, uint32_t name_len, const char *str, uint32_t len);
+nxt_inline void nxt_ruby_add_sptr(VALUE hash_env, VALUE name,
+ nxt_unit_sptr_t *sptr, uint32_t len);
static nxt_int_t nxt_ruby_rack_result_status(VALUE result);
static int nxt_ruby_rack_result_headers(VALUE result, nxt_int_t status);
static int nxt_ruby_hash_info(VALUE r_key, VALUE r_value, VALUE arg);
@@ -86,6 +76,93 @@ NXT_EXPORT nxt_app_module_t nxt_app_module = {
nxt_ruby_start,
};
+typedef struct {
+ nxt_str_t string;
+ VALUE *v;
+} nxt_ruby_string_t;
+
+static VALUE nxt_rb_80_str;
+static VALUE nxt_rb_content_length_str;
+static VALUE nxt_rb_content_type_str;
+static VALUE nxt_rb_http_str;
+static VALUE nxt_rb_https_str;
+static VALUE nxt_rb_path_info_str;
+static VALUE nxt_rb_query_string_str;
+static VALUE nxt_rb_rack_url_scheme_str;
+static VALUE nxt_rb_remote_addr_str;
+static VALUE nxt_rb_request_method_str;
+static VALUE nxt_rb_request_uri_str;
+static VALUE nxt_rb_server_addr_str;
+static VALUE nxt_rb_server_name_str;
+static VALUE nxt_rb_server_port_str;
+static VALUE nxt_rb_server_protocol_str;
+
+static nxt_ruby_string_t nxt_rb_strings[] = {
+ { nxt_string("80"), &nxt_rb_80_str },
+ { nxt_string("CONTENT_LENGTH"), &nxt_rb_content_length_str },
+ { nxt_string("CONTENT_TYPE"), &nxt_rb_content_type_str },
+ { nxt_string("http"), &nxt_rb_http_str },
+ { nxt_string("https"), &nxt_rb_https_str },
+ { nxt_string("PATH_INFO"), &nxt_rb_path_info_str },
+ { nxt_string("QUERY_STRING"), &nxt_rb_query_string_str },
+ { nxt_string("rack.url_scheme"), &nxt_rb_rack_url_scheme_str },
+ { nxt_string("REMOTE_ADDR"), &nxt_rb_remote_addr_str },
+ { nxt_string("REQUEST_METHOD"), &nxt_rb_request_method_str },
+ { nxt_string("REQUEST_URI"), &nxt_rb_request_uri_str },
+ { nxt_string("SERVER_ADDR"), &nxt_rb_server_addr_str },
+ { nxt_string("SERVER_NAME"), &nxt_rb_server_name_str },
+ { nxt_string("SERVER_PORT"), &nxt_rb_server_port_str },
+ { nxt_string("SERVER_PROTOCOL"), &nxt_rb_server_protocol_str },
+ { nxt_null_string, NULL },
+};
+
+
+static int
+nxt_ruby_init_strings(void)
+{
+ VALUE v;
+ nxt_ruby_string_t *pstr;
+
+ pstr = nxt_rb_strings;
+
+ while (pstr->string.start != NULL) {
+ v = rb_str_new_static((char *) pstr->string.start, pstr->string.length);
+
+ if (nxt_slow_path(v == Qnil)) {
+ nxt_unit_alert(NULL, "Ruby: failed to create const string '%.*s'",
+ (int) pstr->string.length,
+ (char *) pstr->string.start);
+
+ return NXT_UNIT_ERROR;
+ }
+
+ *pstr->v = v;
+
+ rb_gc_register_address(pstr->v);
+
+ pstr++;
+ }
+
+ return NXT_UNIT_OK;
+}
+
+
+static void
+nxt_ruby_done_strings(void)
+{
+ nxt_ruby_string_t *pstr;
+
+ pstr = nxt_rb_strings;
+
+ while (pstr->string.start != NULL) {
+ rb_gc_unregister_address(pstr->v);
+
+ *pstr->v = Qnil;
+
+ pstr++;
+ }
+}
+
static nxt_int_t
nxt_ruby_start(nxt_task_t *task, nxt_process_data_t *data)
@@ -109,6 +186,8 @@ nxt_ruby_start(nxt_task_t *task, nxt_process_data_t *data)
rack_init.task = task;
rack_init.script = &conf->u.ruby.script;
+ nxt_ruby_init_strings();
+
res = rb_protect(nxt_ruby_init_basic,
(VALUE) (uintptr_t) &rack_init, &state);
if (nxt_slow_path(res == Qnil || state != 0)) {
@@ -440,78 +519,69 @@ fail:
static int
nxt_ruby_read_request(VALUE hash_env)
{
+ VALUE name;
uint32_t i;
nxt_unit_field_t *f;
nxt_unit_request_t *r;
r = nxt_ruby_run_ctx.req->request;
-#define NL(S) (S), sizeof(S)-1
-
- nxt_ruby_add_sptr(hash_env, NL("REQUEST_METHOD"), &r->method,
+ nxt_ruby_add_sptr(hash_env, nxt_rb_request_method_str, &r->method,
r->method_length);
- nxt_ruby_add_sptr(hash_env, NL("REQUEST_URI"), &r->target,
+ nxt_ruby_add_sptr(hash_env, nxt_rb_request_uri_str, &r->target,
r->target_length);
- nxt_ruby_add_sptr(hash_env, NL("PATH_INFO"), &r->path, r->path_length);
- nxt_ruby_add_sptr(hash_env, NL("QUERY_STRING"), &r->query,
+ nxt_ruby_add_sptr(hash_env, nxt_rb_path_info_str, &r->path, r->path_length);
+ nxt_ruby_add_sptr(hash_env, nxt_rb_query_string_str, &r->query,
r->query_length);
- nxt_ruby_add_sptr(hash_env, NL("SERVER_PROTOCOL"), &r->version,
+ nxt_ruby_add_sptr(hash_env, nxt_rb_server_protocol_str, &r->version,
r->version_length);
- nxt_ruby_add_sptr(hash_env, NL("REMOTE_ADDR"), &r->remote,
+ nxt_ruby_add_sptr(hash_env, nxt_rb_remote_addr_str, &r->remote,
r->remote_length);
- nxt_ruby_add_sptr(hash_env, NL("SERVER_ADDR"), &r->local, r->local_length);
-
- nxt_ruby_add_sptr(hash_env, NL("SERVER_NAME"), &r->server_name,
+ nxt_ruby_add_sptr(hash_env, nxt_rb_server_addr_str, &r->local,
+ r->local_length);
+ nxt_ruby_add_sptr(hash_env, nxt_rb_server_name_str, &r->server_name,
r->server_name_length);
- nxt_ruby_add_str(hash_env, NL("SERVER_PORT"), "80", 2);
- rb_hash_aset(hash_env, rb_str_new2("rack.url_scheme"),
- r->tls ? rb_str_new2("https") : rb_str_new2("http"));
+ rb_hash_aset(hash_env, nxt_rb_server_port_str, nxt_rb_80_str);
+
+ rb_hash_aset(hash_env, nxt_rb_rack_url_scheme_str,
+ r->tls ? nxt_rb_https_str : nxt_rb_http_str);
for (i = 0; i < r->fields_count; i++) {
f = r->fields + i;
- nxt_ruby_add_sptr(hash_env, nxt_unit_sptr_get(&f->name), f->name_length,
- &f->value, f->value_length);
+ name = rb_str_new(nxt_unit_sptr_get(&f->name), f->name_length);
+
+ nxt_ruby_add_sptr(hash_env, name, &f->value, f->value_length);
}
if (r->content_length_field != NXT_UNIT_NONE_FIELD) {
f = r->fields + r->content_length_field;
- nxt_ruby_add_sptr(hash_env, NL("CONTENT_LENGTH"),
+ nxt_ruby_add_sptr(hash_env, nxt_rb_content_length_str,
&f->value, f->value_length);
}
if (r->content_type_field != NXT_UNIT_NONE_FIELD) {
f = r->fields + r->content_type_field;
- nxt_ruby_add_sptr(hash_env, NL("CONTENT_TYPE"),
+ nxt_ruby_add_sptr(hash_env, nxt_rb_content_type_str,
&f->value, f->value_length);
}
-#undef NL
-
return NXT_UNIT_OK;
}
nxt_inline void
-nxt_ruby_add_sptr(VALUE hash_env,
- const char *name, uint32_t name_len, nxt_unit_sptr_t *sptr, uint32_t len)
+nxt_ruby_add_sptr(VALUE hash_env, VALUE name,
+ nxt_unit_sptr_t *sptr, uint32_t len)
{
char *str;
str = nxt_unit_sptr_get(sptr);
- rb_hash_aset(hash_env, rb_str_new(name, name_len), rb_str_new(str, len));
-}
-
-
-nxt_inline void
-nxt_ruby_add_str(VALUE hash_env,
- const char *name, uint32_t name_len, const char *str, uint32_t len)
-{
- rb_hash_aset(hash_env, rb_str_new(name, name_len), rb_str_new(str, len));
+ rb_hash_aset(hash_env, name, rb_str_new(str, len));
}
@@ -901,5 +971,7 @@ nxt_ruby_atexit(void)
rb_gc_unregister_address(&nxt_ruby_call);
rb_gc_unregister_address(&nxt_ruby_env);
+ nxt_ruby_done_strings();
+
ruby_cleanup(0);
}