Expand GDType to cover GDExtension types as well#106016
Expand GDType to cover GDExtension types as well#106016Repiteo merged 1 commit intogodotengine:masterfrom
GDType to cover GDExtension types as well#106016Conversation
6b3487a to
da4e7f1
Compare
da4e7f1 to
bf9104f
Compare
|
I can confirm that this PR increased type-checking performance using The duplication of data and relationships irks me a bit, but I imagine it's out of scope of this PR to look at changing these. Looking forward to the ClassDB cleanup! :) I don't understand the purpose of clearing I feel like it should be set during the Object constructor, instead of during initialization? This would allow us to get rid of the check in This is the first time I saw the GDType changes! Looks like a solid start! :D Would it be worthwhile changing these to static variables and using static constructors for in-built classes? That way we don't have to dynamically allocate memory for them, and only have to initialize the properties. PR looks good overall! Only major issue is the possible memory leak concern. Maybe some confusion/concern around The ClassDB changes look good! I'm really excited for the future of this! :D |
|
Thanks a lot for the review!
The singular branch is unlikely to be a bottleneck, especially when compared to some of the other logic slowing these functions down. So I wouldn't expect any observable performance improvements just from this change, especially on hot execution.
It's part of the It's possible we can change this eventually, but now is not the time.
Built-in classes are already created statically, the only classes that are created dynamically are those created from GDExtension (which this PR focuses on). |
dsnopek
left a comment
There was a problem hiding this comment.
Thanks!
For the most part this looks great :-)
However, I tested it with hot reload, and it seems to work, but I get 3 errors printed when it reloads:
ERROR: core/object/object.cpp:234 - Condition "gdtype" is true.
ERROR: core/object/object.cpp:234 - Condition "gdtype" is true.
ERROR: core/object/object.cpp:234 - Condition "gdtype" is true.
I think we might be missing some place where we should be disposing of the gdtype in preparation for reload? Perhaps it should be deleted in GDExtension::_clear_extension()?
bf9104f to
0e7168f
Compare
|
@dsnopek Thanks a lot for testing! I had another look, and it seems like I failed to realize that |
0e7168f to
9b54928
Compare
|
Thanks, however, in the latest version of this PR, I'm still getting those errors on reload. I suspect the right thing to do is to have Patchdiff --git a/core/extension/gdextension.cpp b/core/extension/gdextension.cpp
index ad5b6a8442f..8c38ae0be48 100644
--- a/core/extension/gdextension.cpp
+++ b/core/extension/gdextension.cpp
@@ -976,6 +976,8 @@ void GDExtension::_clear_extension(Extension *p_extension) {
obj->clear_internal_extension();
}
+
+ p_extension->gdextension.destroy_gdtype();
}
void GDExtension::track_instance_binding(Object *p_object) {
diff --git a/core/object/object.cpp b/core/object/object.cpp
index 2ffea4aefa3..10bd258b707 100644
--- a/core/object/object.cpp
+++ b/core/object/object.cpp
@@ -236,6 +236,19 @@ void ObjectGDExtension::create_gdtype() {
gdtype = memnew(GDType(ClassDB::get_gdtype(parent_class_name), class_name));
}
+void ObjectGDExtension::destroy_gdtype() {
+ ERR_FAIL_COND(!gdtype);
+
+ memdelete(const_cast<GDType *>(gdtype));
+ gdtype = nullptr;
+}
+
+ObjectGDExtension::~ObjectGDExtension() {
+ if (gdtype) {
+ memdelete(const_cast<GDType *>(gdtype));
+ }
+}
+
bool Object::Connection::operator<(const Connection &p_conn) const {
if (signal == p_conn.signal) {
return callable < p_conn.callable;
diff --git a/core/object/object.h b/core/object/object.h
index 11cb9095855..3438e5ece56 100644
--- a/core/object/object.h
+++ b/core/object/object.h
@@ -374,6 +374,9 @@ struct ObjectGDExtension {
/// This is not exposed through the GDExtension API (yet) so it is inferred from above parameters.
const GDType *gdtype;
void create_gdtype();
+ void destroy_gdtype();
+
+ ~ObjectGDExtension();
};
#define GDVIRTUAL_CALL(m_name, ...) _gdvirtual_##m_name##_call(__VA_ARGS__)When I use that, I don't get the errors anymore! Also, it appears the reload isn't full working with the latest version of this PR (whereas before there were the errors, but it still worked), at least using the same test as I used last time (I've got a |
This turned out to be a godot-cpp issue godotengine/godot-cpp#1876 |
9b54928 to
1646b32
Compare
Sorry about that! Somehow, I managed to patch the wrong part of the PR with the fix. I've corrected this now. With the latest version, I can hot reload without any error messages (macOS).
Unfortunately, this is not an option. The |
The reload process goes through all instances and resets the But assuming nothing is getting missed, if you look at my patch above, in the first chunk where it's calling |
Oh that's interesting! That totally explains your suggestion. |
It doesn't - at the moment, reload is unsafe with regard to multithreading. This was one of the "let's get this out now, and fix it later" things. :-) That said, I don't think multithreading issues affect very many users - maybe more often with editor plugins that spawn threads? And they could maybe handle it manually by stopping their threads on The solution is probably some variation of protecting access to |
1646b32 to
dbf3ba8
Compare
|
Alright, thanks for clearing that up. I'm totally happy to go with your suggestion then! The hot reload seems to work for me with your suggestions applied, without any errors printed1.
An idea i had was to synchronize threads when a reload is scheduled, and only start exchanging extension pointers when they're all paused. That would make hot reload compatibility completely free, but if there's any long running threads, it would take a while to reload. Footnotes
|
Co-authored-by: David Snopek <dsnopek@gmail.com>
dbf3ba8 to
aa33b53
Compare
dsnopek
left a comment
There was a problem hiding this comment.
Thanks!
I re-ran this through some manual hot-reload tests and everything seems to be working fine :-)
|
Thanks! |
Objecttypes. Optimizeis_class#105793.GDTypeis explained in the corresponding proposal: godotengine/godot-proposals#12323.This PR expands
GDTypeto cover GDExtension added classes as well, by swapping the pointer when a GDExtension subtype is assigned to theObject. This eliminates branching and separate computation in typing functions such asis_class.This should be merged relatively soon after, or even together with #105793, to eliminate the possibility of
GDTypebeing used in contexts assuming internal types only.Explanation
Objectinstances can get assigned a GDExtension 'subtype'. According to Godot's typing logic, this makes theObject's new type the GDExtension's supplied type, i.e. a subtype of the builtin type. You can read more about this general idea here: godotengine/godot-proposals#12155Note: Instances are usually assigned a GDExtension instance exactly once, right after the
Objectis created. When this happens, all we have to do is use the GDExtension'sGDTypeinstead of the builtin one.