Change memory allocation strategy for pending buf
Now it is allocated on demand. This prevents it from blowing up to READ_BUF_SZ * 2 (2MB) if a small pending update is followed by a large non pending section in the read buffer, which is commonly triggered for instance by the transfer kitten which uses pending updates for its screen drawing mixed with non-pending data transmission. This is a slight performance penalty since there is a branch when writing every char to the pending buffer, but the branch will be almost always one sided so should be well predicted. In any case, filling the pending buffer is not a performance bottleneck, compared to actually dispatching parsed escape codes.
This commit is contained in:
parent
fcd4649642
commit
aa9855516f
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
extern PyTypeObject Screen_Type;
|
extern PyTypeObject Screen_Type;
|
||||||
#define EXTENDED_OSC_SENTINEL 0x1bu
|
#define EXTENDED_OSC_SENTINEL 0x1bu
|
||||||
|
#define PENDING_BUF_INCREMENT (16u * 1024u)
|
||||||
|
|
||||||
// utils {{{
|
// utils {{{
|
||||||
static const uint64_t pow_10_array[] = {
|
static const uint64_t pow_10_array[] = {
|
||||||
@ -1359,6 +1360,13 @@ FLUSH_DRAW;
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
write_pending_char(Screen *screen, uint32_t ch) {
|
write_pending_char(Screen *screen, uint32_t ch) {
|
||||||
|
if (screen->pending_mode.capacity < screen->pending_mode.used + 8) {
|
||||||
|
if (screen->pending_mode.capacity) {
|
||||||
|
screen->pending_mode.capacity += screen->pending_mode.capacity >= READ_BUF_SZ ? PENDING_BUF_INCREMENT : screen->pending_mode.capacity;
|
||||||
|
} else screen->pending_mode.capacity = PENDING_BUF_INCREMENT;
|
||||||
|
screen->pending_mode.buf = realloc(screen->pending_mode.buf, screen->pending_mode.capacity);
|
||||||
|
if (!screen->pending_mode.buf) fatal("Out of memory");
|
||||||
|
}
|
||||||
screen->pending_mode.used += encode_utf8(ch, (char*)screen->pending_mode.buf + screen->pending_mode.used);
|
screen->pending_mode.used += encode_utf8(ch, (char*)screen->pending_mode.buf + screen->pending_mode.used);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1466,19 +1474,9 @@ end:
|
|||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
create_pending_space(Screen *screen, size_t needed_space) {
|
|
||||||
screen->pending_mode.capacity = MAX(screen->pending_mode.capacity * 2, screen->pending_mode.used + needed_space);
|
|
||||||
if (screen->pending_mode.capacity > READ_BUF_SZ) screen->pending_mode.capacity = screen->pending_mode.used + needed_space;
|
|
||||||
screen->pending_mode.buf = realloc(screen->pending_mode.buf, screen->pending_mode.capacity);
|
|
||||||
if (!screen->pending_mode.buf) fatal("Out of memory");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dump_partial_escape_code_to_pending(Screen *screen) {
|
dump_partial_escape_code_to_pending(Screen *screen) {
|
||||||
if (screen->parser_buf_pos) {
|
if (screen->parser_buf_pos) {
|
||||||
const size_t needed_space = 4 * screen->parser_buf_pos + 8;
|
|
||||||
if (screen->pending_mode.used + needed_space >= screen->pending_mode.capacity) create_pending_space(screen, needed_space);
|
|
||||||
write_pending_char(screen, screen->parser_state);
|
write_pending_char(screen, screen->parser_state);
|
||||||
for (unsigned i = 0; i < screen->parser_buf_pos; i++) write_pending_char(screen, screen->parser_buf[i]);
|
for (unsigned i = 0; i < screen->parser_buf_pos; i++) write_pending_char(screen, screen->parser_buf[i]);
|
||||||
}
|
}
|
||||||
@ -1511,6 +1509,11 @@ do_parse_bytes(Screen *screen, const uint8_t *read_buf, const size_t read_buf_sz
|
|||||||
_parse_bytes(screen, screen->pending_mode.buf, screen->pending_mode.used, dump_callback);
|
_parse_bytes(screen, screen->pending_mode.buf, screen->pending_mode.used, dump_callback);
|
||||||
screen->pending_mode.used = 0;
|
screen->pending_mode.used = 0;
|
||||||
screen->pending_mode.activated_at = 0; // ignore any pending starts in the pending bytes
|
screen->pending_mode.activated_at = 0; // ignore any pending starts in the pending bytes
|
||||||
|
if (screen->pending_mode.capacity > READ_BUF_SZ + PENDING_BUF_INCREMENT) {
|
||||||
|
screen->pending_mode.capacity = READ_BUF_SZ;
|
||||||
|
screen->pending_mode.buf = realloc(screen->pending_mode.buf, screen->pending_mode.capacity);
|
||||||
|
if (!screen->pending_mode.buf) fatal("Out of memory");
|
||||||
|
}
|
||||||
if (screen->pending_mode.stop_escape_code_type) {
|
if (screen->pending_mode.stop_escape_code_type) {
|
||||||
if (screen->pending_mode.stop_escape_code_type == DCS) { REPORT_COMMAND(screen_stop_pending_mode); }
|
if (screen->pending_mode.stop_escape_code_type == DCS) { REPORT_COMMAND(screen_stop_pending_mode); }
|
||||||
else if (screen->pending_mode.stop_escape_code_type == CSI) { REPORT_COMMAND(screen_reset_mode, 2026, 1); }
|
else if (screen->pending_mode.stop_escape_code_type == CSI) { REPORT_COMMAND(screen_reset_mode, 2026, 1); }
|
||||||
@ -1526,17 +1529,13 @@ do_parse_bytes(Screen *screen, const uint8_t *read_buf, const size_t read_buf_sz
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case QUEUE_PENDING: {
|
case QUEUE_PENDING: {
|
||||||
const size_t needed_space = read_buf_sz * 2;
|
|
||||||
screen->pending_mode.stop_escape_code_type = 0;
|
screen->pending_mode.stop_escape_code_type = 0;
|
||||||
if (screen->pending_mode.capacity - screen->pending_mode.used < needed_space) {
|
if (screen->pending_mode.used >= READ_BUF_SZ) {
|
||||||
if (screen->pending_mode.capacity > READ_BUF_SZ * 2) {
|
|
||||||
dump_partial_escape_code_to_pending(screen);
|
dump_partial_escape_code_to_pending(screen);
|
||||||
screen->pending_mode.activated_at = 0;
|
screen->pending_mode.activated_at = 0;
|
||||||
state = START;
|
state = START;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
create_pending_space(screen, needed_space);
|
|
||||||
}
|
|
||||||
if (!screen->pending_mode.used) parser_state_at_start_of_pending = screen->parser_state;
|
if (!screen->pending_mode.used) parser_state_at_start_of_pending = screen->parser_state;
|
||||||
read_buf_pos += queue_pending_bytes(screen, read_buf + read_buf_pos, read_buf_sz - read_buf_pos, dump_callback);
|
read_buf_pos += queue_pending_bytes(screen, read_buf + read_buf_pos, read_buf_sz - read_buf_pos, dump_callback);
|
||||||
state = START;
|
state = START;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user