[前][次][番号順一覧][スレッド一覧]

ruby-changes:70941

From: Kevin <ko1@a...>
Date: Sat, 22 Jan 2022 07:35:12 +0900 (JST)
Subject: [ruby-changes:70941] fc6fd4c31e (master): Accurately report VM memsize

https://git.ruby-lang.org/ruby.git/commit/?id=fc6fd4c31e

From fc6fd4c31e957a4b15ba2c03cbd1cea0a8af6513 Mon Sep 17 00:00:00 2001
From: Kevin Newton <kddnewton@g...>
Date: Tue, 11 Jan 2022 12:47:22 -0500
Subject: Accurately report VM memsize

Currently the calculation only counts the size of the struct. This commit adds the size of the associated st tables, id tables, and linked lists.

Still missing is the size of the ractors and (potentially) the size of the object space.
---
 process.c  | 15 +++++++++++++++
 thread.c   | 15 +++++++++++++++
 vm.c       | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
 vm_trace.c | 23 +++++++++++++++++++++++
 4 files changed, 105 insertions(+), 4 deletions(-)

diff --git a/process.c b/process.c
index 83c44fdd489..8eee6f772a7 100644
--- a/process.c
+++ b/process.c
@@ -1090,6 +1090,21 @@ waitpid_signal(struct waitpid_state *w) https://github.com/ruby/ruby/blob/trunk/process.c#L1090
     return FALSE;
 }
 
+// Used for VM memsize reporting. Returns the size of a list of waitpid_state
+// structs. Defined here because the struct definition lives here as well.
+size_t
+rb_vm_memsize_waiting_list(struct list_head *waiting_list)
+{
+    struct waitpid_state *waitpid = 0;
+    size_t size = 0;
+
+    list_for_each(waiting_list, waitpid, wnode) {
+        size += sizeof(struct waitpid_state);
+    }
+
+    return size;
+}
+
 /*
  * When a thread is done using sigwait_fd and there are other threads
  * sleeping on waitpid, we must kick one of the threads out of
diff --git a/thread.c b/thread.c
index 95daed66684..46ae21b5893 100644
--- a/thread.c
+++ b/thread.c
@@ -5575,6 +5575,21 @@ rb_check_deadlock(rb_ractor_t *r) https://github.com/ruby/ruby/blob/trunk/thread.c#L5575
     }
 }
 
+// Used for VM memsize reporting. Returns the size of a list of waiting_fd
+// structs. Defined here because the struct definition lives here as well.
+size_t
+rb_vm_memsize_waiting_fds(struct list_head *waiting_fds)
+{
+    struct waiting_fd *waitfd = 0;
+    size_t size = 0;
+
+    list_for_each(waiting_fds, waitfd, wfd_node) {
+        size += sizeof(struct waiting_fd);
+    }
+
+    return size;
+}
+
 static void
 update_line_coverage(VALUE data, const rb_trace_arg_t *trace_arg)
 {
diff --git a/vm.c b/vm.c
index 634ed158847..cb7007ac133 100644
--- a/vm.c
+++ b/vm.c
@@ -2731,17 +2731,65 @@ ruby_vm_destruct(rb_vm_t *vm) https://github.com/ruby/ruby/blob/trunk/vm.c#L2731
     return 0;
 }
 
+size_t rb_vm_memsize_waiting_list(struct list_head *waiting_list); // process.c
+size_t rb_vm_memsize_waiting_fds(struct list_head *waiting_fds); // thread.c
+size_t rb_vm_memsize_postponed_job_buffer(); // vm_trace.c
+size_t rb_vm_memsize_workqueue(struct list_head *workqueue); // vm_trace.c
+
+// Used for VM memsize reporting. Returns the size of the at_exit list by
+// looping through the linked list and adding up the size of the structs.
 static size_t
-vm_memsize(const void *ptr)
+vm_memsize_at_exit_list(rb_at_exit_list *at_exit)
 {
-    size_t size = sizeof(rb_vm_t);
+    size_t size = 0;
 
-    // TODO
-    // size += vmobj->ractor_num * sizeof(rb_ractor_t);
+    while (at_exit) {
+        size += sizeof(rb_at_exit_list);
+        at_exit = at_exit->next;
+    }
 
     return size;
 }
 
+// Used for VM memsize reporting. Returns the size of the builtin function
+// table if it has been defined.
+static size_t
+vm_memsize_builtin_function_table(const struct rb_builtin_function *builtin_function_table)
+{
+    return builtin_function_table == NULL ? 0 : sizeof(struct rb_builtin_function);
+}
+
+// Reports the memsize of the VM struct object and the structs that are
+// associated with it.
+static size_t
+vm_memsize(const void *ptr)
+{
+    rb_vm_t *vm = GET_VM();
+
+    return (
+        sizeof(rb_vm_t) +
+        rb_vm_memsize_waiting_list(&vm->waiting_pids) +
+        rb_vm_memsize_waiting_list(&vm->waiting_grps) +
+        rb_vm_memsize_waiting_fds(&vm->waiting_fds) +
+        rb_st_memsize(vm->loaded_features_index) +
+        rb_st_memsize(vm->loading_table) +
+        rb_st_memsize(vm->ensure_rollback_table) +
+        rb_vm_memsize_postponed_job_buffer() +
+        rb_vm_memsize_workqueue(&vm->workqueue) +
+        rb_st_memsize(vm->defined_module_hash) +
+        vm_memsize_at_exit_list(vm->at_exit) +
+        rb_st_memsize(vm->frozen_strings) +
+        vm_memsize_builtin_function_table(vm->builtin_function_table) +
+        rb_id_table_memsize(vm->negative_cme_table) +
+        rb_st_memsize(vm->overloaded_cme_table)
+    );
+
+    // TODO
+    // struct { struct list_head set; } ractor;
+    // void *main_altstack; #ifdef USE_SIGALTSTACK
+    // struct rb_objspace *objspace;
+}
+
 static const rb_data_type_t vm_data_type = {
     "VM",
     {0, 0, vm_memsize,},
diff --git a/vm_trace.c b/vm_trace.c
index 466856341d0..7f6a60b0cbe 100644
--- a/vm_trace.c
+++ b/vm_trace.c
@@ -1578,6 +1578,29 @@ struct rb_workqueue_job { https://github.com/ruby/ruby/blob/trunk/vm_trace.c#L1578
     rb_postponed_job_t job;
 };
 
+// Used for VM memsize reporting. Returns the size of a list of rb_workqueue_job
+// structs. Defined here because the struct definition lives here as well.
+size_t
+rb_vm_memsize_workqueue(struct list_head *workqueue)
+{
+    struct rb_workqueue_job *work = 0;
+    size_t size = 0;
+
+    list_for_each(workqueue, work, jnode) {
+        size += sizeof(struct rb_workqueue_job);
+    }
+
+    return size;
+}
+
+// Used for VM memsize reporting. Returns the total size of the postponed job
+// buffer that was allocated at initialization.
+size_t
+rb_vm_memsize_postponed_job_buffer()
+{
+    return sizeof(rb_postponed_job_t) * MAX_POSTPONED_JOB;
+}
+
 void
 Init_vm_postponed_job(void)
 {
-- 
cgit v1.2.1


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]