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:
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--;