Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GDscipt bad perfomance dictionary #94786

Closed
vali-dexer opened this issue Jul 26, 2024 · 13 comments
Closed

GDscipt bad perfomance dictionary #94786

vali-dexer opened this issue Jul 26, 2024 · 13 comments

Comments

@vali-dexer
Copy link

vali-dexer commented Jul 26, 2024

Tested versions

4.2.2 stable

System information

Linux Vulkan API 1.3.277 Forward Mobile, Cpu Ryzen 4800

Issue description

Hello
operation with Dictionary and maybe Array unexpectedly takes a long time

in other languages (python), the same code gives better performance
this behavior can be considered a mistake because the difference is in other languages for python, time - 0.31-0.32 (Dictionary). 0.22 (List)

need to be tested

extends Node

var vec_dict : Dictionary = {"x":0.0, "y":0.0}
var vec_arr: Array[float] = [0.0, 0.0] #NOTE typed array give better perfomance
var vec_f1 : float = 0.0
var vec_f2 : float = 0.0
var vec : Vector2 = Vector2(0.0,0.0)

var iter : int = 1_000_000
var time : float = 0.0
	
func _ready() -> void:
	for d:int in range(5):
		time = Time.get_unix_time_from_system()
		for  i:int in range(iter):
			vec+=Vector2(0.5,0.5)
		print(Time.get_unix_time_from_system() - time, " =1= ",vec)
		time = Time.get_unix_time_from_system()
		for i:int in range(iter):
			vec_arr[0]+=0.5
			vec_arr[1]+=0.5
		print(Time.get_unix_time_from_system() - time, " =2= ",vec_arr)
		time = Time.get_unix_time_from_system()
		for i:int in range(iter):
			vec_dict.x += 0.5
			vec_dict.y += 0.5
		print(Time.get_unix_time_from_system() - time, " =3= ",vec_dict)

output
0.08130407333374 =1= (500000, 500000)
0.23810791969299 =2= [500000, 500000]
0.46027398109436 =3= { "x": 500000, "y": 500000 }
0.08708500862122 =1= (1000000, 1000000)
0.23752689361572 =2= [1000000, 1000000]
0.46500897407532 =3= { "x": 1000000, "y": 1000000 }
0.08664584159851 =1= (1500000, 1500000)
0.23779892921448 =2= [1500000, 1500000]
0.46151900291443 =3= { "x": 1500000, "y": 1500000 }

Steps to reproduce

  1. Create empty project with 1 node and 1 script
  2. paste code
  3. run

Minimal reproduction project (MRP)

N/A

@huwpascoe
Copy link

When performance matters, best use the packed arrays:
PackedByteArray
PackedColorArray
PackedFloat32Array
PackedFloat64Array
PackedInt32Array
PackedInt64Array
PackedStringArray
PackedVector2Array
PackedVector3Array

@AThousandShips
Copy link
Member

You can't really compare python to GDScript for performance, they're two very different environments, the difference in performance isn't an indicator of an error necessarily

@vali-dexer
Copy link
Author

When performance matters, best use the packed arrays: PackedByteArray PackedColorArray PackedFloat32Array PackedFloat64Array PackedInt32Array PackedInt64Array PackedStringArray PackedVector2Array PackedVector3Array

the main problem with Dictionary, Array gave performance +- at python level, but considering that gdscript is better optimized here may be a problem with Arrya, PackedFloat64Array showed even better result (0.16)

@vali-dexer
Copy link
Author

vali-dexer commented Jul 26, 2024

You can't really compare python to GDScript for performance, they're two very different environments, the difference in performance isn't an indicator of an error necessarily

The comparison of 2 languages is not exactly accurate, but if the difference in python language is 30% between operations and gdscipt 50%, and gdscipt is more optimized, then the chance that this is a bad implementation is high

same code, only instead of Dictionary or Array, 2 float varible is used, shows 0.10-0.11 (in gdscipt), 0.23-0.24 (in python) (quite strange result)

@AThousandShips
Copy link
Member

Where are you getting that GDScript is more optimized? Python is often compiled for performance and has a lot of optimizations

@vali-dexer
Copy link
Author

in basic operations sometimes gdscipt wins, but not always (in tests without project build or python build file, possibly when python build with optimization the results will change ratio), like gdscript works in multithread mode while python not

@AThousandShips
Copy link
Member

The primary goal of GDScript AFAIK isn't necessarily raw performance but stability and ease of use, there is some work being done on improving the performance, see godotengine/godot-proposals#6031 for more details

But GDScript performs essentially no structural optimizations, it largely compiles the input into straight operations to a VM, it does no analysis like improving loops etc.

If you can identify some areas where GDScript is broken for performance that'd be great, but that would need analyzing the actual source code, comparing with other, unrelated languages doesn't really tell you anything except that GDScript works differently

@vali-dexer
Copy link
Author

vali-dexer commented Jul 26, 2024

Good that the work on optimization gdscipt, the goal gdscipt is clear, understandable and logical, code should be seen (not clear where are outlined types, maybe in modules/gdscript/gdscipt.cpp), but the data work strangely Vector compared to any analogues faster than them by 20% (2 float), 200% (packedFloat64Array), 300% (Float Array),575% (Dictionary ), python without assembly also does not use cycle optimization but nevertheless gives a better time. Although hearing about VM was unexpected, and may be that the vector suddenly feels good in VM

@AThousandShips
Copy link
Member

AThousandShips commented Jul 26, 2024

A virtual machine would be required unless it's compiled to some machine code to be run on the CPU

The code is in modules/gdscript, in different areas for different parts

But it's obvious that a Vector2 is faster than an array, it would be the same in C++, because you are accessing by index in a dynamic way, not directly on the data, that's not surprising (with optimization it could be faster)

@monxa
Copy link

monxa commented Jul 26, 2024

As much as I want to agree with @AThousandShips, GDScript should be as performant as possible. Yes, it's made for ease of use, but performance cannot be secondary in a real-time engine. That said, I do think the api is largly performant. We do have beautiful optimizations everywhere.
For example:

  • StringNames: Makes operations such as comparisons and lookups on strings very easy, especially important because the api operates largly with strings for interops.
  • HashMaps: Using in many cases linear data structures instead of HashMaps for the bucks such as done in c++ std::map/unordered_map

Exactly because of the latter, because we already attempt to avoid cache misses, I would have thought that Dictionary lookup would be fast, even in gdscript.

I am wondering: Is gdscript not further optimized on exports? Didn't we have a middlelayer gdscript runtime for that?

@AThousandShips
Copy link
Member

It is not further optimized, nor was, it's interpreted into a virtual binary format which used to be partially exported and compressed in 3.x, but it was never optimized with any compiler optimizations

@vali-dexer
Copy link
Author

vali-dexer commented Jul 26, 2024

Undoubtedly, the simplicity of language is the main advantage, but why if the language is weaker in a number of problems with performance, it is not a problem. gdscipt is a good advantage over other engines, but if in basic tasks it loses to other languages (python or lua) with almost the same syntax or logic, then its use is useless

#add var for store Dictionary
var dict_opt_v2_0: PackedFloat64Array = [0.0,0.0]
var dict_opt_v2_1: PackedStringArray = ["x","y"]

...

#paste analog Dictionary
		time = Time.get_unix_time_from_system()
		for i:int in range(iter): 
			dict_opt_v2_0[dict_opt_v2_1.find("x")]+=0.5
			dict_opt_v2_0[dict_opt_v2_1.find("y")]+=0.5
		print(Time.get_unix_time_from_system() - time, " =5= ",dict_opt_v2_0)

output
0.35146999359131 =5= [500000, 500000]
0.34716081619263 =5= [1000000, 1000000]
0.34942197799683 =5= [1500000, 1500000]

faster then Dictionary

there are some assumptions in this code

@AThousandShips
Copy link
Member

Can we focus on the question of:
Are there any actual performance issues, any actual bugs

For improvements in general please see the linked proposal

Otherwise I don't think there's any bug here, unless someone can find some actual errors in the code this is simply a difference in performance between two completely unrelated and fundamentally different languages and can't be used as an induction of anything

If there isn't anything actionable, something that can be identified as a bug, then this should be closed and focus should be on ideas for performance elsewhere

@vali-dexer vali-dexer closed this as not planned Won't fix, can't repro, duplicate, stale Jul 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants