From b53d91a4c40b69ec1d7e95e44863c8c921ed2f11 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 16 Sep 2024 14:15:43 +0200 Subject: [PATCH] InputText: optimization for large text: using memchr() instead of strchr() shaves 0.2 ms on 865k multi-line text case. Approximately 20%. (#7925) --- docs/CHANGELOG.txt | 2 +- imgui_widgets.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index b91d55530..069b60388 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -68,7 +68,7 @@ Other changes: - InputText: internal refactoring to simplify and optimize the code. The ImWchar buffer has been removed. Simplifications allowed to implement new optimizations for handling very large text buffers (e.g. in our testing, handling of a 1 MB text buffer is now 3 times faster in VS2022 Debug build). - This is the first step toward more refactorig. (#7925) [@alektron, @ocornut] + This is the first step toward more refactoring. (#7925) [@alektron, @ocornut] - InputText: added CJK double-width punctuation to list of separators considered for CTRL+Arrow. - Misc: Made it accepted to call SetMouseCursor() with any out-of-bound value, as a way to allow hacking in custom cursors if desirable. diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 3576d31fa..64156b40d 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -5095,6 +5095,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ // We are attempting to do most of that in **one main pass** to minimize the computation cost (non-negligible for large amount of text) + 2nd pass for selection rendering (we could merge them by an extra refactoring effort) // FIXME: This should occur on buf_display but we'd need to maintain cursor/select_start/select_end for UTF-8. const char* text_begin = state->TextA.Data; + const char* text_end = text_begin + state->CurLenA; ImVec2 cursor_offset, select_start_offset; { @@ -5119,7 +5120,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ // In multi-line mode, we never exit the loop until all lines are counted, so add one extra to the searches_remaining counter. searches_remaining += is_multiline ? 1 : 0; int line_count = 0; - for (const char* s = text_begin; (s = strchr(s, '\n')) != NULL; s++) // FIXME-OPT: memchr() would be faster? + for (const char* s = text_begin; (s = (const char*)memchr(s, '\n', (size_t)(text_end - s))) != NULL; s++) { line_count++; if (searches_result_line_no[0] == -1 && s >= searches_input_ptr[0]) { searches_result_line_no[0] = line_count; if (--searches_remaining <= 0) break; }