From b67e213b1609289d0d3c514becac70f0fdcc941e Mon Sep 17 00:00:00 2001 From: Lukas Tenbrink Date: Sat, 15 Mar 2025 18:06:28 +0100 Subject: [PATCH] Optimize `FileAccessCompressed::get_buffer` by using `memcpy`. --- core/io/file_access_compressed.cpp | 57 ++++++++++++++++++------------ 1 file changed, 35 insertions(+), 22 deletions(-) diff --git a/core/io/file_access_compressed.cpp b/core/io/file_access_compressed.cpp index 5fe30ff42c9..30fe310b33c 100644 --- a/core/io/file_access_compressed.cpp +++ b/core/io/file_access_compressed.cpp @@ -247,7 +247,11 @@ bool FileAccessCompressed::eof_reached() const { } uint64_t FileAccessCompressed::get_buffer(uint8_t *p_dst, uint64_t p_length) const { - ERR_FAIL_COND_V(!p_dst && p_length > 0, -1); + if (p_length == 0) { + return 0; + } + + ERR_FAIL_NULL_V(p_dst, -1); ERR_FAIL_COND_V_MSG(f.is_null(), -1, "File must be opened before use."); ERR_FAIL_COND_V_MSG(writing, -1, "File has not been opened in read mode."); @@ -256,29 +260,38 @@ uint64_t FileAccessCompressed::get_buffer(uint8_t *p_dst, uint64_t p_length) con return 0; } - for (uint64_t i = 0; i < p_length; i++) { - p_dst[i] = read_ptr[read_pos]; - read_pos++; - if (read_pos >= read_block_size) { - read_block++; + uint64_t dst_idx = 0; + while (true) { + // Copy over as much of our current block as possible. + const uint32_t copied_bytes_count = MIN(p_length - dst_idx, read_block_size - read_pos); + memcpy(p_dst + dst_idx, read_ptr + read_pos, copied_bytes_count); + dst_idx += copied_bytes_count; + read_pos += copied_bytes_count; - if (read_block < read_block_count) { - //read another block of compressed data - f->get_buffer(comp_buffer.ptrw(), read_blocks[read_block].csize); - int ret = Compression::decompress(buffer.ptrw(), read_blocks.size() == 1 ? read_total : block_size, comp_buffer.ptr(), read_blocks[read_block].csize, cmode); - ERR_FAIL_COND_V_MSG(ret == -1, -1, "Compressed file is corrupt."); - read_block_size = read_block == read_block_count - 1 ? read_total % block_size : block_size; - read_pos = 0; - - } else { - read_block--; - at_end = true; - if (i + 1 < p_length) { - read_eof = true; - } - return i + 1; - } + if (dst_idx == p_length) { + // We're done! We read back all that was requested. + return p_length; } + + // We're not done yet; try reading the next block. + read_block++; + + if (read_block >= read_block_count) { + // We're done! We read back the whole file. + read_block--; + at_end = true; + if (dst_idx + 1 < p_length) { + read_eof = true; + } + return dst_idx + 1; + } + + // Read the next block of compressed data. + f->get_buffer(comp_buffer.ptrw(), read_blocks[read_block].csize); + int ret = Compression::decompress(buffer.ptrw(), read_blocks.size() == 1 ? read_total : block_size, comp_buffer.ptr(), read_blocks[read_block].csize, cmode); + ERR_FAIL_COND_V_MSG(ret == -1, -1, "Compressed file is corrupt."); + read_block_size = read_block == read_block_count - 1 ? read_total % block_size : block_size; + read_pos = 0; } return p_length;