From e4dcf1d852931937107d404b04854419219f398f Mon Sep 17 00:00:00 2001 From: Dery Almas Date: Mon, 20 Apr 2026 08:20:40 +0200 Subject: [PATCH] Buildsystem: Simplify `format_buffer` utility method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This method is used to generate headers for embedding files into the binary (think about the new `#embed` feature in C23 and C++26). While the stringification step itself was plenty fast, it then proceeded to wrap everything using the `textwrap` module. `textwrap` is *very* slow, as it's apparently optimized for human text. This patch reimplements the wrapping logic using a simple regex, resulting in a tremendous speed improvement (~6x), and switches to `map` for the stringification itself (thanks Rémi!) It also removes a (practically) unused argument, `initial_indent`. The generated files are pretty much the same, with a tiny difference in line length (for some reason the old logic overshot the requested line length) --- core/core_builders.py | 4 ++-- core/extension/make_interface_dumper.py | 2 +- editor/editor_builders.py | 4 ++-- main/main_builders.py | 6 +++--- methods.py | 11 ++--------- modules/text_server_adv/text_server_adv_builders.py | 2 +- scene/theme/default_theme_builders.py | 2 +- servers/rendering/renderer_rd/effects/SCsub | 4 ++-- 8 files changed, 14 insertions(+), 21 deletions(-) diff --git a/core/core_builders.py b/core/core_builders.py index c9d76eb068..a0f13fa802 100644 --- a/core/core_builders.py +++ b/core/core_builders.py @@ -66,7 +66,7 @@ def encryption_key_builder(target, source, env): #include uint8_t script_encryption_key[32] = {{ - {methods.format_buffer(buffer, 1)} +{methods.format_buffer(buffer, 1)} }};""" ) @@ -87,7 +87,7 @@ def make_certs_header(target, source, env): inline constexpr int _certs_compressed_size = {len(buffer)}; inline constexpr int _certs_uncompressed_size = {decomp_size}; inline constexpr unsigned char _certs_compressed[] = {{ - {methods.format_buffer(buffer, 1)} +{methods.format_buffer(buffer, 1)} }}; """) diff --git a/core/extension/make_interface_dumper.py b/core/extension/make_interface_dumper.py index 024ac712ef..0fdc1cb7eb 100644 --- a/core/extension/make_interface_dumper.py +++ b/core/extension/make_interface_dumper.py @@ -17,7 +17,7 @@ def run(target, source, env): inline constexpr int _gdextension_interface_data_compressed_size = {len(buffer)}; inline constexpr int _gdextension_interface_data_uncompressed_size = {decomp_size}; inline constexpr unsigned char _gdextension_interface_data_compressed[] = {{ - {methods.format_buffer(buffer, 1)} +{methods.format_buffer(buffer, 1)} }}; class GDExtensionInterfaceDump {{ diff --git a/editor/editor_builders.py b/editor/editor_builders.py index 26f871ac6b..d9091f0463 100644 --- a/editor/editor_builders.py +++ b/editor/editor_builders.py @@ -63,7 +63,7 @@ inline constexpr const char *_doc_data_hash = "{hash(buffer)}"; inline constexpr int _doc_data_compressed_size = {len(buffer)}; inline constexpr int _doc_data_uncompressed_size = {decomp_size}; inline constexpr const unsigned char _doc_data_compressed[] = {{ - {methods.format_buffer(buffer, 1)} +{methods.format_buffer(buffer, 1)} }}; """) @@ -114,7 +114,7 @@ def make_translations(target, source, env): file.write(f"""\ inline constexpr const unsigned char _{category}_translation_{name}_compressed[] = {{ - {methods.format_buffer(buffer, 1)} +{methods.format_buffer(buffer, 1)} }}; """) diff --git a/main/main_builders.py b/main/main_builders.py index 78041ce4f1..63d0bb2d0a 100644 --- a/main/main_builders.py +++ b/main/main_builders.py @@ -13,7 +13,7 @@ def make_splash(target, source, env): static const Color boot_splash_bg_color = Color(0.14, 0.14, 0.14); inline constexpr const unsigned char boot_splash_png[] = {{ - {methods.format_buffer(buffer, 1)} +{methods.format_buffer(buffer, 1)} }}; """) @@ -29,7 +29,7 @@ def make_splash_editor(target, source, env): static const Color boot_splash_editor_bg_color = Color(0.125, 0.145, 0.192); inline constexpr const unsigned char boot_splash_editor_png[] = {{ - {methods.format_buffer(buffer, 1)} +{methods.format_buffer(buffer, 1)} }}; """) @@ -41,6 +41,6 @@ def make_app_icon(target, source, env): # Use a neutral gray color to better fit various kinds of projects. file.write(f"""\ inline constexpr const unsigned char app_icon_png[] = {{ - {methods.format_buffer(buffer, 1)} +{methods.format_buffer(buffer, 1)} }}; """) diff --git a/methods.py b/methods.py index 6fe6b2fb7c..e0baf06085 100644 --- a/methods.py +++ b/methods.py @@ -8,7 +8,6 @@ import os import re import subprocess import sys -import textwrap import zlib from collections import OrderedDict from io import StringIO @@ -1596,14 +1595,8 @@ def compress_buffer(buffer: bytes) -> bytes: return zlib.compress(buffer, zlib.Z_BEST_COMPRESSION) -def format_buffer(buffer: bytes, indent: int = 0, width: int = 120, initial_indent: bool = False) -> str: - return textwrap.fill( - ", ".join(str(byte) for byte in buffer), - width=width, - initial_indent="\t" * indent if initial_indent else "", - subsequent_indent="\t" * indent, - tabsize=4, - ) +def format_buffer(buffer: bytes, indent: int = 0, width: int = 120) -> str: + return re.sub(f"(.{{0,{width - indent - 1}}},) ", ("\t" * indent) + "\\g<1>\n", ", ".join(map(str, buffer))) ############################################################ diff --git a/modules/text_server_adv/text_server_adv_builders.py b/modules/text_server_adv/text_server_adv_builders.py index 3040becbea..7e5e3b9579 100644 --- a/modules/text_server_adv/text_server_adv_builders.py +++ b/modules/text_server_adv/text_server_adv_builders.py @@ -16,6 +16,6 @@ def make_icu_data(target, source, env): extern "C" U_EXPORT const size_t U_ICUDATA_SIZE = {len(buffer)}; extern "C" U_EXPORT const unsigned char U_ICUDATA_ENTRY_POINT[] = {{ - {methods.format_buffer(buffer, 1)} +{methods.format_buffer(buffer, 1)} }}; """) diff --git a/scene/theme/default_theme_builders.py b/scene/theme/default_theme_builders.py index fc9f3f9dd0..976112c915 100644 --- a/scene/theme/default_theme_builders.py +++ b/scene/theme/default_theme_builders.py @@ -15,7 +15,7 @@ def make_fonts_header(target, source, env): file.write(f"""\ inline constexpr int _font_{name}_size = {len(buffer)}; inline constexpr unsigned char _font_{name}[] = {{ - {methods.format_buffer(buffer, 1)} +{methods.format_buffer(buffer, 1)} }}; """) diff --git a/servers/rendering/renderer_rd/effects/SCsub b/servers/rendering/renderer_rd/effects/SCsub index e76f258923..e0efb7b1cd 100644 --- a/servers/rendering/renderer_rd/effects/SCsub +++ b/servers/rendering/renderer_rd/effects/SCsub @@ -33,7 +33,7 @@ def areatex_builder(target, source, env): #define AREATEX_SIZE (AREATEX_HEIGHT * AREATEX_PITCH) inline constexpr const unsigned char area_tex_png[] = {{ - {methods.format_buffer(buffer, 1)} +{methods.format_buffer(buffer, 1)} }}; """) @@ -52,7 +52,7 @@ def searchtex_builder(target, source, env): #define SEARCHTEX_SIZE (SEARCHTEX_HEIGHT * SEARCHTEX_PITCH) inline constexpr const unsigned char search_tex_png[] = {{ - {methods.format_buffer(buffer, 1)} +{methods.format_buffer(buffer, 1)} }}; """)