summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean Boussier <jean.boussier@gmail.com>2021-08-24 12:32:07 +0200
committerAlan Wu <XrXr@users.noreply.github.com>2021-10-20 18:19:39 -0400
commit0dc3bba6f2b2b1b23e1ec9dd2ec29f932c292db0 (patch)
treec9db52ed439e6cf7fc3f48622718ce418f3b3849
parent2ba090a1f9258035b40374f9ff9da3ff920701cd (diff)
Allow to compile with --yjit-stats support but not the full RUBY_DEBUG
RUBY_DEBUG have a very significant performance overhead. Enough that YJIT with RUBY_DEBUG is noticeably slower than the interpreter without RUBY_DEBUG. This makes it hard to collect yjit-stats in production environments. By allowing to collect JIT statistics without the RUBy_DEBUG overhead, I hope to make such use cases smoother.
-rw-r--r--yjit_codegen.c67
-rw-r--r--yjit_core.c2
-rw-r--r--yjit_iface.c25
-rw-r--r--yjit_iface.h28
4 files changed, 75 insertions, 47 deletions
diff --git a/yjit_codegen.c b/yjit_codegen.c
index 3f9169a74b..a5f39d273b 100644
--- a/yjit_codegen.c
+++ b/yjit_codegen.c
@@ -159,30 +159,7 @@ jit_save_sp(jitstate_t* jit, ctx_t* ctx)
static bool jit_guard_known_klass(jitstate_t *jit, ctx_t* ctx, VALUE known_klass, insn_opnd_t insn_opnd, VALUE sample_instance, const int max_chain_depth, uint8_t *side_exit);
#if RUBY_DEBUG
-
-// Increment a profiling counter with counter_name
-#define GEN_COUNTER_INC(cb, counter_name) _gen_counter_inc(cb, &(yjit_runtime_counters . counter_name))
-static void
-_gen_counter_inc(codeblock_t *cb, int64_t *counter)
-{
- if (!rb_yjit_opts.gen_stats) return;
- mov(cb, REG0, const_ptr_opnd(counter));
- cb_write_lock_prefix(cb); // for ractors.
- add(cb, mem_opnd(64, REG0, 0), imm_opnd(1));
-}
-
-// Increment a counter then take an existing side exit.
-#define COUNTED_EXIT(side_exit, counter_name) _counted_side_exit(side_exit, &(yjit_runtime_counters . counter_name))
-static uint8_t *
-_counted_side_exit(uint8_t *existing_side_exit, int64_t *counter)
-{
- if (!rb_yjit_opts.gen_stats) return existing_side_exit;
-
- uint8_t *start = cb_get_ptr(ocb, ocb->write_pos);
- _gen_counter_inc(ocb, counter);
- jmp_ptr(ocb, existing_side_exit);
- return start;
-}
+# define YJIT_STATS 1
// Add a comment at the current position in the code block
static void
@@ -268,14 +245,50 @@ verify_ctx(jitstate_t *jit, ctx_t *ctx)
}
#else
+#ifndef YJIT_STATS
+#define YJIT_STATS 0
+#endif // ifndef YJIT_STATS
-#define GEN_COUNTER_INC(cb, counter_name) ((void)0)
-#define COUNTED_EXIT(side_exit, counter_name) side_exit
#define ADD_COMMENT(cb, comment) ((void)0)
#define verify_ctx(jit, ctx) ((void)0)
#endif // if RUBY_DEBUG
+#if YJIT_STATS
+
+// Increment a profiling counter with counter_name
+#define GEN_COUNTER_INC(cb, counter_name) _gen_counter_inc(cb, &(yjit_runtime_counters . counter_name))
+static void
+_gen_counter_inc(codeblock_t *cb, int64_t *counter)
+{
+ if (!rb_yjit_opts.gen_stats) return;
+ mov(cb, REG0, const_ptr_opnd(counter));
+ cb_write_lock_prefix(cb); // for ractors.
+ add(cb, mem_opnd(64, REG0, 0), imm_opnd(1));
+}
+
+// Increment a counter then take an existing side exit.
+#define COUNTED_EXIT(side_exit, counter_name) _counted_side_exit(side_exit, &(yjit_runtime_counters . counter_name))
+static uint8_t *
+_counted_side_exit(uint8_t *existing_side_exit, int64_t *counter)
+{
+ if (!rb_yjit_opts.gen_stats) return existing_side_exit;
+
+ uint8_t *start = cb_get_ptr(ocb, ocb->write_pos);
+ _gen_counter_inc(ocb, counter);
+ jmp_ptr(ocb, existing_side_exit);
+ return start;
+}
+
+
+#else
+
+#define GEN_COUNTER_INC(cb, counter_name) ((void)0)
+#define COUNTED_EXIT(side_exit, counter_name) side_exit
+
+#endif // if YJIT_STATS
+
+
// Generate an exit to return to the interpreter
static uint8_t *
yjit_gen_exit(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb)
@@ -302,7 +315,7 @@ yjit_gen_exit(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb)
mov(cb, member_opnd(REG_CFP, rb_control_frame_t, pc), RAX);
// Accumulate stats about interpreter exits
-#if RUBY_DEBUG
+#if YJIT_STATS
if (rb_yjit_opts.gen_stats) {
mov(cb, RDI, const_ptr_opnd(exit_pc));
call_ptr(cb, RSI, (void *)&rb_yjit_count_side_exit_op);
diff --git a/yjit_core.c b/yjit_core.c
index 519da41230..ee3914acc6 100644
--- a/yjit_core.c
+++ b/yjit_core.c
@@ -522,7 +522,7 @@ add_block_version(blockid_t blockid, block_t* block)
rb_bug("allocation failed");
}
-#if RUBY_DEBUG
+#if YJIT_STATS
// First block compiled for this iseq
yjit_runtime_counters.compiled_iseq_count++;
#endif
diff --git a/yjit_iface.c b/yjit_iface.c
index 90b4ed9555..8ad6005bb9 100644
--- a/yjit_iface.c
+++ b/yjit_iface.c
@@ -25,11 +25,18 @@ static VALUE mYjit;
static VALUE cYjitBlock;
#if RUBY_DEBUG
-static int64_t exit_op_count[VM_INSTRUCTION_SIZE] = { 0 };
-struct rb_yjit_runtime_counters yjit_runtime_counters = { 0 };
+# define YJIT_STATS 1
static VALUE cYjitCodeComment;
+#else
+# ifndef YJIT_STATS
+# define YJIT_STATS 0
+# endif
+#endif
+#if YJIT_STATS
extern const int rb_vm_max_insn_name_size;
+static int64_t exit_op_count[VM_INSTRUCTION_SIZE] = { 0 };
+struct rb_yjit_runtime_counters yjit_runtime_counters = { 0 };
#endif
// Machine code blocks (executable memory)
@@ -721,7 +728,7 @@ get_yjit_stats(rb_execution_context_t *ec, VALUE self)
rb_hash_aset(hash, key, value);
}
-#if RUBY_DEBUG
+#if YJIT_STATS
if (rb_yjit_opts.gen_stats) {
// Indicate that the complete set of stats is available
rb_hash_aset(hash, ID2SYM(rb_intern("all_stats")), Qtrue);
@@ -783,16 +790,16 @@ get_yjit_stats(rb_execution_context_t *ec, VALUE self)
static VALUE
reset_stats_bang(rb_execution_context_t *ec, VALUE self)
{
-#if RUBY_DEBUG
+#if YJIT_STATS
memset(&exit_op_count, 0, sizeof(exit_op_count));
memset(&yjit_runtime_counters, 0, sizeof(yjit_runtime_counters));
-#endif // if RUBY_DEBUG
+#endif // if YJIT_STATS
return Qnil;
}
#include "yjit.rbinc"
-#if RUBY_DEBUG
+#if YJIT_STATS
void
rb_yjit_collect_vm_usage_insn(int insn)
{
@@ -1022,9 +1029,9 @@ rb_yjit_init(struct rb_yjit_options *options)
rb_yjit_opts.gen_stats |= !!getenv("YJIT_STATS");
-#if !RUBY_DEBUG
+#if !YJIT_STATS
if(rb_yjit_opts.gen_stats) {
- rb_warning("--yjit-stats requires that Ruby is compiled with CPPFLAGS='-DRUBY_DEBUG=1'");
+ rb_warning("--yjit-stats requires that Ruby is compiled with CPPFLAGS='-DYJIT_STATS=1' or CPPFLAGS='-DRUBY_DEBUG=1'");
}
#endif
@@ -1070,7 +1077,7 @@ rb_yjit_init(struct rb_yjit_options *options)
#endif
#endif
- if (RUBY_DEBUG && rb_yjit_opts.gen_stats) {
+ if (YJIT_STATS && rb_yjit_opts.gen_stats) {
// Setup at_exit callback for printing out counters
rb_block_call(rb_mKernel, rb_intern("at_exit"), 0, NULL, at_exit_print_stats, Qfalse);
}
diff --git a/yjit_iface.h b/yjit_iface.h
index 4b3da00b76..6f7aa69cea 100644
--- a/yjit_iface.h
+++ b/yjit_iface.h
@@ -16,6 +16,23 @@
#endif
#if RUBY_DEBUG
+# define YJIT_STATS 1
+struct yjit_comment {
+ uint32_t offset;
+ const char *comment;
+};
+
+typedef rb_darray(struct yjit_comment) yjit_comment_array_t;
+
+extern yjit_comment_array_t yjit_code_comments;
+#else
+# ifndef YJIT_STATS
+# define YJIT_STATS 0
+# endif // ifndef YJIT_STATS
+#endif // if RUBY_DEBUG
+
+
+#if YJIT_STATS
#define YJIT_DECLARE_COUNTERS(...) struct rb_yjit_runtime_counters { \
int64_t __VA_ARGS__; \
@@ -81,16 +98,7 @@ YJIT_DECLARE_COUNTERS(
#undef YJIT_DECLARE_COUNTERS
-struct yjit_comment {
- uint32_t offset;
- const char *comment;
-};
-
-typedef rb_darray(struct yjit_comment) yjit_comment_array_t;
-
-extern yjit_comment_array_t yjit_code_comments;
-
-#endif // if RUBY_DEBUG
+#endif // YJIT_STATS
RUBY_EXTERN struct rb_yjit_options rb_yjit_opts;
RUBY_EXTERN struct rb_yjit_runtime_counters yjit_runtime_counters;