[gjs: 5/7] object: Use smaller data structure for closures
- From: Cosimo Cecchi <cosimoc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs: 5/7] object: Use smaller data structure for closures
- Date: Sun, 1 Jul 2018 17:09:20 +0000 (UTC)
commit 93cf31db41b4a533f8e264da2213c15d0501f4e7
Author: Philip Chimento <philip chimento gmail com>
Date: Wed Jun 20 00:36:44 2018 -0700
object: Use smaller data structure for closures
Some time ago, we switched from GList* to std::set to store the list of
GClosures associated with an object. std::set was the most time-efficient
container, but we need to optimize for space here. std::forward_list is
comparable to GSList.
This reduces ObjectInstance to 96 bytes and ObjectPrototype to 192 bytes.
gi/object.cpp | 14 +++++++++++---
gi/object.h | 8 +++-----
2 files changed, 14 insertions(+), 8 deletions(-)
---
diff --git a/gi/object.cpp b/gi/object.cpp
index 322c586c..ed10722b 100644
--- a/gi/object.cpp
+++ b/gi/object.cpp
@@ -63,7 +63,7 @@
#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) <= 112,
+static_assert(sizeof(ObjectInstance) <= 96,
"Think very hard before increasing the size of ObjectInstance. "
"There can be tens of thousands of them alive in a typical "
"gnome-shell run.");
@@ -1395,7 +1395,7 @@ void ObjectBase::invalidate_all_closures(void) {
GClosure *closure = *m_closures.begin();
g_closure_invalidate(closure);
/* Erase element if not already erased */
- m_closures.erase(closure);
+ m_closures.remove(closure);
}
}
@@ -1695,11 +1695,19 @@ void ObjectBase::associate_closure(JSContext* cx, GClosure* closure) {
/* This is a weak reference, and will be cleared when the closure is
* invalidated */
- m_closures.insert(closure);
+ auto already_has = std::find(m_closures.begin(), m_closures.end(), closure);
+ g_assert(already_has == m_closures.end() &&
+ "This closure was already associated with this object");
+ m_closures.push_front(closure);
g_closure_add_invalidate_notifier(closure, this,
&ObjectBase::closure_invalidated_notify);
}
+void ObjectBase::closure_invalidated_notify(void* data, GClosure* closure) {
+ auto* priv = static_cast<ObjectBase*>(data);
+ priv->m_closures.remove(closure);
+}
+
bool ObjectBase::connect(JSContext* cx, unsigned argc, JS::Value* vp) {
GJS_GET_PRIV(cx, argc, vp, args, obj, ObjectBase, priv);
if (!priv)
diff --git a/gi/object.h b/gi/object.h
index 7c4327c7..4c6cd59f 100644
--- a/gi/object.h
+++ b/gi/object.h
@@ -27,8 +27,8 @@
#include <glib-object.h>
#include <girepository.h>
+#include <forward_list>
#include <functional>
-#include <set>
#include <stack>
#include <vector>
@@ -89,7 +89,7 @@ class ObjectBase {
/* a list of all GClosures installed on this object (from
* signals, trampolines, explicit GClosures, and vfuncs on prototypes),
* used when tracing */
- std::set<GClosure*> m_closures;
+ std::forward_list<GClosure*> m_closures;
explicit ObjectBase(ObjectPrototype* proto = nullptr) : m_proto(proto) {}
@@ -200,9 +200,7 @@ class ObjectBase {
public:
void associate_closure(JSContext* cx, GClosure* closure);
- static void closure_invalidated_notify(void* data, GClosure* closure) {
- static_cast<ObjectBase*>(data)->m_closures.erase(closure);
- }
+ static void closure_invalidated_notify(void* data, GClosure* closure);
/* JSClass operations */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]