godot icon indicating copy to clipboard operation
godot copied to clipboard

Many properties in _get_property_list() slows down instantiate() by 2-8x.

Open chairfull opened this issue 1 year ago • 2 comments

Tested versions

  • Reproducible in: v4.4.dev2.official [97ef3c837], v4.3.stable.official [77dcf97d8]

System information

Godot v4.3.stable - Ubuntu 24.04.1 LTS 24.04 - X11 - GLES3 (Compatibility) - AMD Radeon R9 200 Series (radeonsi, pitcairn, LLVM 17.0.6, DRM 3.57, 6.8.0-45-generic) - AMD FX(tm)-6300 Six-Core Processor (6 Threads)

Issue description

When a script has a _get_property_list() method with many properties, then calling load().instantiate() is much slower (2-8x in my case) while testing from the editor.

But when the project is built, the lag is gone. So it's only in editor.

I feel the obvious solution is below, but it doesn't work.

func _get_property_list():
	if not Engine.is_editor_hint():
		return []
	# Properties here...

Steps to reproduce

  • Create "res://test_scene.tscn" with this script on a node:
@tool
extends Node

var a := 0.0
var b := "b"
var c := [1, 2, 3, 4]
var d := false
var e := { x=false }
var f := Vector2.ZERO

var bool_a := false
var bool_b := true
var bool_c := true
var bool_d := false
var bool_e := false
var bool_f := true

var str_a := "a"
var str_b := "bb"
var str_c := "ccc"
var str_d := "dddd"
var str_e := "eeeee"
var str_f := "ffffff"

var arr_a := []
var arr_b := [1]
var arr_c := [false, true]
var arr_d := [[], [], [], []]
var arr_e := [{}, {}, {}, {}, {}]
var arr_f := ["f", "ff", "fff", "ffff", "fffff"]

var dict_a := {}
var dict_b := {x=1}
var dict_c := {a=1, b=2}
var dict_d := {a=true, b=true, c=true}
var dict_e := {x=[], y=false, c=true, e=Vector2.ZERO}
var dict_f := {a="a", b="b", c="c", d="d", e="e"}

var np_a := ^"../property_list"
var np_b := ^"../property_list"
var np_c := ^"../property_list"
var np_d := ^"../property_list"
var np_e := ^"../property_list"
var np_f := ^"../property_list"

func _get_property_list() -> Array[Dictionary]:
	var props: Array[Dictionary]
	
	if not Engine.is_editor_hint():
		return props
	
	props.append({ name="a", type=TYPE_FLOAT })
	props.append({ name="b", type=TYPE_STRING })
	props.append({ name="c", type=TYPE_ARRAY })
	props.append({ name="e", type=TYPE_DICTIONARY })
	props.append({ name="f", type=TYPE_VECTOR2 })
	
	props.append({ name="Bool", type=TYPE_NIL, usage=PROPERTY_USAGE_GROUP, hint_string="bool_" })
	props.append({ name="bool_a", type=TYPE_BOOL })
	props.append({ name="bool_b", type=TYPE_BOOL })
	props.append({ name="bool_c", type=TYPE_BOOL })
	props.append({ name="bool_d", type=TYPE_BOOL })
	props.append({ name="bool_e", type=TYPE_BOOL })
	props.append({ name="bool_f", type=TYPE_BOOL })
	
	props.append({ name="String", type=TYPE_NIL, usage=PROPERTY_USAGE_GROUP, hint_string="str_" })
	props.append({ name="str_a", type=TYPE_STRING })
	props.append({ name="str_b", type=TYPE_STRING })
	props.append({ name="str_c", type=TYPE_STRING })
	props.append({ name="str_d", type=TYPE_STRING })
	props.append({ name="str_e", type=TYPE_STRING })
	props.append({ name="str_f", type=TYPE_STRING })
	
	props.append({ name="Array", type=TYPE_NIL, usage=PROPERTY_USAGE_GROUP, hint_string="arr_" })
	props.append({ name="arr_a", type=TYPE_ARRAY })
	props.append({ name="arr_b", type=TYPE_ARRAY })
	props.append({ name="arr_c", type=TYPE_ARRAY })
	props.append({ name="arr_d", type=TYPE_ARRAY })
	props.append({ name="arr_e", type=TYPE_ARRAY })
	props.append({ name="arr_f", type=TYPE_ARRAY })
	
	props.append({ name="Dict", type=TYPE_NIL, usage=PROPERTY_USAGE_GROUP, hint_string="dict_" })
	props.append({ name="dict_a", type=TYPE_DICTIONARY })
	props.append({ name="dict_b", type=TYPE_DICTIONARY })
	props.append({ name="dict_c", type=TYPE_DICTIONARY })
	props.append({ name="dict_d", type=TYPE_DICTIONARY })
	props.append({ name="dict_e", type=TYPE_DICTIONARY })
	props.append({ name="dict_f", type=TYPE_DICTIONARY })
	
	props.append({ name="NodePath", type=TYPE_NIL, usage=PROPERTY_USAGE_GROUP, hint_string="np_" })
	props.append({ name="np_a", type=TYPE_NODE_PATH })
	props.append({ name="np_b", type=TYPE_NODE_PATH })
	props.append({ name="np_c", type=TYPE_NODE_PATH })
	props.append({ name="np_d", type=TYPE_NODE_PATH })
	props.append({ name="np_e", type=TYPE_NODE_PATH })
	props.append({ name="np_f", type=TYPE_NODE_PATH })
	
	return props
  • From another scene, run this script.
func _ready():
	var t1 := Time.get_ticks_msec()
	for i in 1000:
		var _node: Node = load("res://test_scene.tscn").instantiate()
	var tt1 := Time.get_ticks_msec() - t1
	prints("non: ", tt1)
  • Now comment out the _get_property_list() and run again, it will be 2x faster.

Minimal reproduction project (MRP)

test_property_list.zip

chairfull avatar Oct 04 '24 21:10 chairfull

Duplicate of #1502

KRTirtho avatar Oct 13 '24 05:10 KRTirtho

Is there an existing issue for this?

  • [X] I have searched the existing issues

image

KRTirtho avatar Oct 13 '24 05:10 KRTirtho