You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-07 12:30:27 +00:00
Array performance improvements to reduce copying/copy_on_write calls
- Avoid temporary copy of p_array in Array::append_array when types match - Call ptrw() once before looping in methods that return new Arrays, to avoid copy_on_write call for each item (recursive_duplicate, slice, filter, map)
This commit is contained in:
@@ -287,9 +287,15 @@ void Array::push_back(const Variant &p_value) {
|
|||||||
void Array::append_array(const Array &p_array) {
|
void Array::append_array(const Array &p_array) {
|
||||||
ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
|
ERR_FAIL_COND_MSG(_p->read_only, "Array is in read-only state.");
|
||||||
|
|
||||||
|
if (!is_typed() || _p->typed.can_reference(p_array._p->typed)) {
|
||||||
|
_p->array.append_array(p_array._p->array);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Vector<Variant> validated_array = p_array._p->array;
|
Vector<Variant> validated_array = p_array._p->array;
|
||||||
|
Variant *write = validated_array.ptrw();
|
||||||
for (int i = 0; i < validated_array.size(); ++i) {
|
for (int i = 0; i < validated_array.size(); ++i) {
|
||||||
ERR_FAIL_COND(!_p->typed.validate(validated_array.write[i], "append_array"));
|
ERR_FAIL_COND(!_p->typed.validate(write[i], "append_array"));
|
||||||
}
|
}
|
||||||
|
|
||||||
_p->array.append_array(validated_array);
|
_p->array.append_array(validated_array);
|
||||||
@@ -529,8 +535,9 @@ Array Array::recursive_duplicate(bool p_deep, int recursion_count) const {
|
|||||||
recursion_count++;
|
recursion_count++;
|
||||||
int element_count = size();
|
int element_count = size();
|
||||||
new_arr.resize(element_count);
|
new_arr.resize(element_count);
|
||||||
|
Variant *write = new_arr._p->array.ptrw();
|
||||||
for (int i = 0; i < element_count; i++) {
|
for (int i = 0; i < element_count; i++) {
|
||||||
new_arr[i] = get(i).recursive_duplicate(true, recursion_count);
|
write[i] = get(i).recursive_duplicate(true, recursion_count);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
new_arr._p->array = _p->array;
|
new_arr._p->array = _p->array;
|
||||||
@@ -566,8 +573,9 @@ Array Array::slice(int p_begin, int p_end, int p_step, bool p_deep) const {
|
|||||||
int result_size = (end - begin) / p_step + (((end - begin) % p_step != 0) ? 1 : 0);
|
int result_size = (end - begin) / p_step + (((end - begin) % p_step != 0) ? 1 : 0);
|
||||||
result.resize(result_size);
|
result.resize(result_size);
|
||||||
|
|
||||||
|
Variant *write = result._p->array.ptrw();
|
||||||
for (int src_idx = begin, dest_idx = 0; dest_idx < result_size; ++dest_idx) {
|
for (int src_idx = begin, dest_idx = 0; dest_idx < result_size; ++dest_idx) {
|
||||||
result[dest_idx] = p_deep ? get(src_idx).duplicate(true) : get(src_idx);
|
write[dest_idx] = p_deep ? get(src_idx).duplicate(true) : get(src_idx);
|
||||||
src_idx += p_step;
|
src_idx += p_step;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -581,6 +589,7 @@ Array Array::filter(const Callable &p_callable) const {
|
|||||||
int accepted_count = 0;
|
int accepted_count = 0;
|
||||||
|
|
||||||
const Variant *argptrs[1];
|
const Variant *argptrs[1];
|
||||||
|
Variant *write = new_arr._p->array.ptrw();
|
||||||
for (int i = 0; i < size(); i++) {
|
for (int i = 0; i < size(); i++) {
|
||||||
argptrs[0] = &get(i);
|
argptrs[0] = &get(i);
|
||||||
|
|
||||||
@@ -592,7 +601,7 @@ Array Array::filter(const Callable &p_callable) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (result.operator bool()) {
|
if (result.operator bool()) {
|
||||||
new_arr[accepted_count] = get(i);
|
write[accepted_count] = get(i);
|
||||||
accepted_count++;
|
accepted_count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -607,17 +616,15 @@ Array Array::map(const Callable &p_callable) const {
|
|||||||
new_arr.resize(size());
|
new_arr.resize(size());
|
||||||
|
|
||||||
const Variant *argptrs[1];
|
const Variant *argptrs[1];
|
||||||
|
Variant *write = new_arr._p->array.ptrw();
|
||||||
for (int i = 0; i < size(); i++) {
|
for (int i = 0; i < size(); i++) {
|
||||||
argptrs[0] = &get(i);
|
argptrs[0] = &get(i);
|
||||||
|
|
||||||
Variant result;
|
|
||||||
Callable::CallError ce;
|
Callable::CallError ce;
|
||||||
p_callable.callp(argptrs, 1, result, ce);
|
p_callable.callp(argptrs, 1, write[i], ce);
|
||||||
if (ce.error != Callable::CallError::CALL_OK) {
|
if (ce.error != Callable::CallError::CALL_OK) {
|
||||||
ERR_FAIL_V_MSG(Array(), vformat("Error calling method from 'map': %s.", Variant::get_callable_error_text(p_callable, argptrs, 1, ce)));
|
ERR_FAIL_V_MSG(Array(), vformat("Error calling method from 'map': %s.", Variant::get_callable_error_text(p_callable, argptrs, 1, ce)));
|
||||||
}
|
}
|
||||||
|
|
||||||
new_arr[i] = result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new_arr;
|
return new_arr;
|
||||||
|
|||||||
Reference in New Issue
Block a user