1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-13 13:31:48 +00:00

Optimize Object::get_class_name

* Run the static function once per class instead of one per instance.
* Saves some memory in Object derived classes.
This commit is contained in:
Juan Linietsky
2023-04-07 23:32:37 +02:00
parent 61630d4e1e
commit 8950943356
4 changed files with 28 additions and 17 deletions

View File

@@ -195,14 +195,15 @@ bool Object::_predelete() {
_predelete_ok = 1; _predelete_ok = 1;
notification(NOTIFICATION_PREDELETE, true); notification(NOTIFICATION_PREDELETE, true);
if (_predelete_ok) { if (_predelete_ok) {
_class_ptr = nullptr; //must restore so destructors can access class ptr correctly _class_name_ptr = nullptr; // Must restore, so constructors/destructors have proper class name access at each stage.
} }
return _predelete_ok; return _predelete_ok;
} }
void Object::_postinitialize() { void Object::_postinitialize() {
_class_ptr = _get_class_namev(); _class_name_ptr = _get_class_namev(); // Set the direct pointer, which is much faster to obtain, but can only happen after postinitialize.
_initialize_classv(); _initialize_classv();
_class_name_ptr = nullptr; // May have been called from a constructor.
notification(NOTIFICATION_POSTINITIALIZE); notification(NOTIFICATION_POSTINITIALIZE);
} }

View File

@@ -376,7 +376,6 @@ private:
#define GDCLASS(m_class, m_inherits) \ #define GDCLASS(m_class, m_inherits) \
private: \ private: \
void operator=(const m_class &p_rval) {} \ void operator=(const m_class &p_rval) {} \
mutable StringName _class_name; \
friend class ::ClassDB; \ friend class ::ClassDB; \
\ \
public: \ public: \
@@ -388,13 +387,11 @@ public:
return String(#m_class); \ return String(#m_class); \
} \ } \
virtual const StringName *_get_class_namev() const override { \ virtual const StringName *_get_class_namev() const override { \
if (_get_extension()) { \ static StringName _class_name_static; \
return &_get_extension()->class_name; \ if (unlikely(!_class_name_static)) { \
StringName::assign_static_unique_class_name(&_class_name_static, #m_class); \
} \ } \
if (!_class_name) { \ return &_class_name_static; \
_class_name = get_class_static(); \
} \
return &_class_name; \
} \ } \
static _FORCE_INLINE_ void *get_class_ptr_static() { \ static _FORCE_INLINE_ void *get_class_ptr_static() { \
static int ptr; \ static int ptr; \
@@ -614,8 +611,7 @@ private:
Variant script; // Reference does not exist yet, store it in a Variant. Variant script; // Reference does not exist yet, store it in a Variant.
HashMap<StringName, Variant> metadata; HashMap<StringName, Variant> metadata;
HashMap<StringName, Variant *> metadata_properties; HashMap<StringName, Variant *> metadata_properties;
mutable StringName _class_name; mutable const StringName *_class_name_ptr = nullptr;
mutable const StringName *_class_ptr = nullptr;
void _add_user_signal(const String &p_name, const Array &p_args = Array()); void _add_user_signal(const String &p_name, const Array &p_args = Array());
bool _has_user_signal(const StringName &p_name) const; bool _has_user_signal(const StringName &p_name) const;
@@ -714,10 +710,11 @@ protected:
Variant _call_deferred_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error); Variant _call_deferred_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
virtual const StringName *_get_class_namev() const { virtual const StringName *_get_class_namev() const {
if (!_class_name) { static StringName _class_name_static;
_class_name = get_class_static(); if (unlikely(!_class_name_static)) {
StringName::assign_static_unique_class_name(&_class_name_static, "Object");
} }
return &_class_name; return &_class_name_static;
} }
Vector<StringName> _get_meta_list_bind() const; Vector<StringName> _get_meta_list_bind() const;
@@ -788,13 +785,16 @@ public:
_FORCE_INLINE_ const StringName &get_class_name() const { _FORCE_INLINE_ const StringName &get_class_name() const {
if (_extension) { if (_extension) {
// Can't put inside the unlikely as constructor can run it
return _extension->class_name; return _extension->class_name;
} }
if (!_class_ptr) {
if (unlikely(!_class_name_ptr)) {
// While class is initializing / deinitializing, constructors and destructurs
// need access to the proper class at the proper stage.
return *_get_class_namev(); return *_get_class_namev();
} else {
return *_class_ptr;
} }
return *_class_name_ptr;
} }
/* IAPI */ /* IAPI */

View File

@@ -201,6 +201,14 @@ StringName::StringName(const StringName &p_name) {
} }
} }
void StringName::assign_static_unique_class_name(StringName *ptr, const char *p_name) {
mutex.lock();
if (*ptr == StringName()) {
*ptr = StringName(p_name, true);
}
mutex.unlock();
}
StringName::StringName(const char *p_name, bool p_static) { StringName::StringName(const char *p_name, bool p_static) {
_data = nullptr; _data = nullptr;

View File

@@ -177,6 +177,8 @@ public:
StringName(const String &p_name, bool p_static = false); StringName(const String &p_name, bool p_static = false);
StringName(const StaticCString &p_static_string, bool p_static = false); StringName(const StaticCString &p_static_string, bool p_static = false);
StringName() {} StringName() {}
static void assign_static_unique_class_name(StringName *ptr, const char *p_name);
_FORCE_INLINE_ ~StringName() { _FORCE_INLINE_ ~StringName() {
if (likely(configured) && _data) { //only free if configured if (likely(configured) && _data) { //only free if configured
unref(); unref();