X Tutup
Skip to content

Avoid extra copy in Vector/CowData push_back/insert#112630

Merged
Repiteo merged 1 commit intogodotengine:masterfrom
aaronp64:push_back_move
Nov 11, 2025
Merged

Avoid extra copy in Vector/CowData push_back/insert#112630
Repiteo merged 1 commit intogodotengine:masterfrom
aaronp64:push_back_move

Conversation

@aaronp64
Copy link
Contributor

@aaronp64 aaronp64 commented Nov 11, 2025

Update push_back/insert methods to move new item into CowData instead of copying.

This mainly helps with String/RefCounted types, making Array.push_back around 20% faster for these types, and similar improvement for String.split, compared with gdscript below:

func _ready():
	run_test("array_push_back_int")
	run_test("array_push_back_str")
	run_test("array_push_back_refcounted")
	run_test("string_split")
	run_test("array_insert_str")

func run_test(test_name: String):
	var start := Time.get_ticks_msec()
	call(test_name)
	var end := Time.get_ticks_msec()
	print("%s: %dms" % [test_name.rpad(27), end - start])

func array_push_back_int():
	var a := []
	for i in 3000000:
		a.push_back(i)
		
func array_push_back_str():
	var a := []
	for i in 3000000:
		a.push_back("test")
		
func array_push_back_refcounted():
	var a := []
	var regex := RegEx.new()
	for i in 3000000:
		a.push_back(regex)

func string_split():
	var s := "1,2,3,4,5,6,7,8,9"
	for i in 500000:
		s.split()

func array_insert_str():
	var a := []
	for i in 3000000:
		a.insert(a.size(), "test")

old:

array_push_back_int        : 119ms
array_push_back_str        : 218ms
array_push_back_refcounted : 198ms
string_split               : 555ms
array_insert_str           : 218ms

new:

array_push_back_int        : 104ms
array_push_back_str        : 163ms
array_push_back_refcounted : 160ms
string_split               : 460ms
array_insert_str           : 181ms

Copy link
Member

@Ivorforce Ivorforce left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've been unhappy with this section for a while, partially due to the requirement of needing to solve the "copy from inside to inside" problem (#31736).

Anyway, this is a safe improvement, so I definitely think we should merge it!

However, there are a few other spots where we're making explicit copies. Please address those as well. They can be identified by the GH-31736 comment.

@aaronp64 aaronp64 changed the title Avoid extra copy in Vector/CowData push_back Avoid extra copy in Vector/CowData push_back/insert Nov 11, 2025
@aaronp64
Copy link
Contributor Author

Updated with a similar change for insert. append goes through push_back, so that should already be covered by the push_back change.

Copy link
Member

@Ivorforce Ivorforce left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me, thanks!

@Ivorforce Ivorforce modified the milestones: 4.x, 4.6 Nov 11, 2025
Update push_back/insert methods to move new item into CowData instead of copying
@Repiteo Repiteo merged commit 18a17de into godotengine:master Nov 11, 2025
20 checks passed
@Repiteo
Copy link
Contributor

Repiteo commented Nov 11, 2025

Thanks!

@aaronp64 aaronp64 deleted the push_back_move branch November 17, 2025 19:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

X Tutup