[gjs: 1/2] object: Use std::vector to hold Objects GClosure's
- From: Philip Chimento <pchimento src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs: 1/2] object: Use std::vector to hold Objects GClosure's
- Date: Mon, 25 Jul 2022 04:16:52 +0000 (UTC)
commit 203ff94d4797121a1ac96d04e5bb766f06207e83
Author: Marco Trevisan (TreviƱo) <mail 3v1n0 net>
Date: Fri Jun 10 03:11:00 2022 +0200
object: Use std::vector to hold Objects GClosure's
We used a std::forward list to hold closure pointers in Object's to
avoid adding a vector when not needed, but these structures are terribly
slow as already pointed out in [1], and demonstrated even way poorer
performances when testing signal connections (see [2], #485 and !758), so get
rid of them and just use vectors everywhere which can boost performances
up to 95% in our tests.
This implies some more memory usage for each object, as we can't use a
std::vector without the size member since C++11, but I think it's still
better, given that size of std::forward_list is still bigger when with
only two closures/vfuncs added (as each element requires two pointers).
Fixes: #485
[1] https://github.com/3v1n0/stl-containers-benchmarks
[2] https://gitlab.gnome.org/3v1n0/gjs/-/snippets/3608
gi/object.cpp | 24 ++++++++++++------------
gi/object.h | 5 ++---
gjs/gjs_pch.hh | 1 -
3 files changed, 14 insertions(+), 16 deletions(-)
---
diff --git a/gi/object.cpp b/gi/object.cpp
index 6c85631c9..a9e39fd27 100644
--- a/gi/object.cpp
+++ b/gi/object.cpp
@@ -78,7 +78,7 @@ class JSTracer;
#if defined(__x86_64__) && defined(__clang__)
/* This isn't meant to be comprehensive, but should trip on at least one CI job
* if sizeof(ObjectInstance) is increased. */
-static_assert(sizeof(ObjectInstance) <= 48,
+static_assert(sizeof(ObjectInstance) <= 64,
"Think very hard before increasing the size of ObjectInstance. "
"There can be tens of thousands of them alive in a typical "
"gnome-shell run.");
@@ -1697,19 +1697,18 @@ bool ObjectInstance::ensure_uses_toggle_ref(JSContext* cx) {
return true;
}
-static void invalidate_closure_list(std::forward_list<GClosure*>* closures,
- void* data, GClosureNotify notify_func) {
+static void invalidate_closure_vector(std::vector<GClosure*>* closures,
+ void* data, GClosureNotify notify_func) {
g_assert(closures);
g_assert(notify_func);
- auto before = closures->before_begin();
for (auto it = closures->begin(); it != closures->end();) {
// This will also free the closure data, through the closure
// invalidation mechanism, but adding a temporary reference to
// ensure that the closure is still valid when calling invalidation
// notify callbacks
- GjsAutoGClosure closure(closures->front(), GjsAutoTakeOwnership());
- it = closures->erase_after(before);
+ GjsAutoGClosure closure(*it, GjsAutoTakeOwnership());
+ it = closures->erase(it);
// Only call the invalidate notifiers that won't touch this vector
g_closure_remove_invalidate_notifier(closure, data, notify_func);
@@ -1967,7 +1966,7 @@ ObjectInstance::~ObjectInstance() {
}
ObjectPrototype::~ObjectPrototype() {
- invalidate_closure_list(&m_vfuncs, this, &vfunc_invalidated_notify);
+ invalidate_closure_vector(&m_vfuncs, this, &vfunc_invalidated_notify);
g_type_class_unref(g_type_class_peek(m_gtype));
@@ -2104,7 +2103,7 @@ bool ObjectInstance::associate_closure(JSContext* cx, GClosure* closure) {
/* This is a weak reference, and will be cleared when the closure is
* invalidated */
- m_closures.push_front(closure);
+ m_closures.push_back(closure);
g_closure_add_invalidate_notifier(
closure, this, &ObjectInstance::closure_invalidated_notify);
@@ -2114,11 +2113,12 @@ bool ObjectInstance::associate_closure(JSContext* cx, GClosure* closure) {
void ObjectInstance::closure_invalidated_notify(void* data, GClosure* closure) {
// This callback should *only* touch m_closures
auto* priv = static_cast<ObjectInstance*>(data);
- priv->m_closures.remove(closure);
+ Gjs::remove_one_from_unsorted_vector(&priv->m_closures, closure);
}
void ObjectInstance::invalidate_closures() {
- invalidate_closure_list(&m_closures, this, &closure_invalidated_notify);
+ invalidate_closure_vector(&m_closures, this, &closure_invalidated_notify);
+ m_closures.shrink_to_fit();
}
bool ObjectBase::connect(JSContext* cx, unsigned argc, JS::Value* vp) {
@@ -3024,7 +3024,7 @@ bool ObjectPrototype::hook_up_vfunc_impl(JSContext* cx,
g_assert(std::find(m_vfuncs.begin(), m_vfuncs.end(), trampoline) ==
m_vfuncs.end() &&
"This vfunc was already associated with this class");
- m_vfuncs.push_front(trampoline);
+ m_vfuncs.push_back(trampoline);
g_closure_add_invalidate_notifier(
trampoline, this, &ObjectPrototype::vfunc_invalidated_notify);
g_closure_add_invalidate_notifier(
@@ -3040,7 +3040,7 @@ bool ObjectPrototype::hook_up_vfunc_impl(JSContext* cx,
void ObjectPrototype::vfunc_invalidated_notify(void* data, GClosure* closure) {
// This callback should *only* touch m_vfuncs
auto* priv = static_cast<ObjectPrototype*>(data);
- priv->m_vfuncs.remove(closure);
+ Gjs::remove_one_from_unsorted_vector(&priv->m_vfuncs, closure);
}
bool
diff --git a/gi/object.h b/gi/object.h
index 886f13eaf..f73e73585 100644
--- a/gi/object.h
+++ b/gi/object.h
@@ -10,7 +10,6 @@
#include <stddef.h> // for size_t
#include <stdint.h> // for uint32_t
-#include <forward_list>
#include <functional>
#include <vector>
@@ -197,7 +196,7 @@ class ObjectPrototype
FieldCache m_field_cache;
NegativeLookupCache m_unresolvable_cache;
// a list of vfunc GClosures installed on this prototype, used when tracing
- std::forward_list<GClosure*> m_vfuncs;
+ std::vector<GClosure*> m_vfuncs;
// a list of interface types explicitly associated with this prototype,
// by gjs_add_interface
std::vector<GType> m_interface_gtypes;
@@ -295,7 +294,7 @@ class ObjectInstance : public GIWrapperInstance<ObjectBase, ObjectPrototype,
GjsMaybeOwned<JSObject*> m_wrapper;
// a list of all GClosures installed on this object (from signal connections
// and scope-notify callbacks passed to methods), used when tracing
- std::forward_list<GClosure*> m_closures;
+ std::vector<GClosure*> m_closures;
bool m_wrapper_finalized : 1;
bool m_gobj_disposed : 1;
diff --git a/gjs/gjs_pch.hh b/gjs/gjs_pch.hh
index 6f1b0b4fb..337e585f5 100644
--- a/gjs/gjs_pch.hh
+++ b/gjs/gjs_pch.hh
@@ -10,7 +10,6 @@
#include <cmath>
#include <cstddef>
#include <deque>
-#include <forward_list>
#include <functional>
#include <limits>
#include <memory>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]