nano

nano with my custom patches
git clone git://bsandro.tech/nano
Log | Files | Refs | README | LICENSE

commit 3922b531a8e4f1076dcabee77b6c87f72af0bf37
parent 0d1438a73126460a562ed43893397cc3776dcfe3
Author: Benno Schulenberg <bensberg@telfort.nl>
Date:   Sun, 25 Sep 2022 09:22:29 +0200

input: allocate a small keystroke buffer, and never free it

Instead of allocating and freeing a tiny fragment of memory for every
keystroke, reserve a small piece in the beginning and then retain it,
because it will be needed again and again and again.  Increase the size
when needed (for a large paste, probably), but don't bother to shrink
it afterward.

This addresses the first part of https://savannah.gnu.org/bugs/?63086.

Diffstat:
Msrc/prototypes.h | 1+
Msrc/winio.c | 32+++++++++++++++++++++++---------
2 files changed, 24 insertions(+), 9 deletions(-)

diff --git a/src/prototypes.h b/src/prototypes.h @@ -581,6 +581,7 @@ linestruct *line_from_number(ssize_t number); /* Most functions in winio.c. */ void record_macro(void); void run_macro(void); +void reserve_space_for(size_t newsize); size_t waiting_keycodes(void); #ifdef ENABLE_NANORC void implant(const char *string); diff --git a/src/winio.c b/src/winio.c @@ -46,6 +46,8 @@ static int *key_buffer = NULL; /* A buffer for the keystrokes that haven't been handled yet. */ static int *nextcodes = NULL; /* A pointer pointing at the next keycode in the keystroke buffer. */ +static size_t capacity = 32; + /* The size of the keystroke buffer; gets doubled whenever needed. */ static size_t waiting_codes = 0; /* The number of key codes waiting in the keystroke buffer. */ #ifdef ENABLE_NANORC @@ -126,7 +128,8 @@ void run_macro(void) return; } - key_buffer = nrealloc(key_buffer, macro_length * sizeof(int)); + if (macro_length > capacity) + reserve_space_for(macro_length); for (size_t i = 0; i < macro_length; i++) key_buffer[i] = macro_buffer[i]; @@ -137,6 +140,14 @@ void run_macro(void) } #endif /* !NANO_TINY */ +/* Allocate the requested space for the keystroke buffer. */ +void reserve_space_for(size_t newsize) +{ + key_buffer = nrealloc(key_buffer, newsize * sizeof(int)); + nextcodes = key_buffer; + capacity = newsize; +} + /* Control character compatibility: * * - Ctrl-H is Backspace under ASCII, ANSI, VT100, and VT220. @@ -246,8 +257,10 @@ void read_keys_from(WINDOW *frame) curs_set(0); - /* Initiate the keystroke buffer, and save the keycode in it. */ - key_buffer = nrealloc(key_buffer, sizeof(int)); + /* When there is no keystroke buffer yet, allocate one. */ + if (!key_buffer) + reserve_space_for(capacity); + key_buffer[0] = input; nextcodes = key_buffer; @@ -284,10 +297,11 @@ void read_keys_from(WINDOW *frame) if (input == ERR) break; - /* Extend the keystroke buffer, and save the keycode at its end. */ - key_buffer = nrealloc(key_buffer, ++waiting_codes * sizeof(int)); - key_buffer[waiting_codes - 1] = input; - nextcodes = key_buffer; + /* When the keystroke buffer is full, extend it. */ + if (waiting_codes == capacity) + reserve_space_for(2 * capacity); + + key_buffer[waiting_codes++] = input; } /* Restore blocking-input mode. */ @@ -316,9 +330,9 @@ void put_back(int keycode) /* If there is no room at the head of the keystroke buffer, make room. */ if (nextcodes == key_buffer) { - key_buffer = nrealloc(key_buffer, (waiting_codes + 1) * sizeof(int)); + if (waiting_codes == capacity) + reserve_space_for(2 * capacity); memmove(key_buffer + 1, key_buffer, waiting_codes * sizeof(int)); - nextcodes = key_buffer; } else nextcodes--;