Speed un reading from child process

Do the reading into a pre-allocated buffer to avoid mallocs in the inner
loop.
This commit is contained in:
Kovid Goyal 2016-11-19 16:59:12 +05:30
parent 6e7f537850
commit d87e4eeb95
4 changed files with 43 additions and 12 deletions

View File

@ -21,7 +21,7 @@ from .char_grid import CharGrid
from .keys import interpret_text_event, interpret_key_event
from .utils import resize_pty, create_pty, sanitize_title
from .fast_data_types import (
BRACKETED_PASTE_START, BRACKETED_PASTE_END, Screen, parse_bytes_dump, parse_bytes
BRACKETED_PASTE_START, BRACKETED_PASTE_END, Screen, read_bytes_dump, read_bytes
)
@ -56,7 +56,7 @@ class Boss(Thread):
self.window, self.opts = window, opts
self.screen = Screen(self)
self.char_grid = CharGrid(self.screen, opts, window_width, window_height)
self.parse_bytes = partial(parse_bytes_dump, print) if args.dump_commands else parse_bytes
self.read_bytes = partial(read_bytes_dump, print) if args.dump_commands else read_bytes
self.write_buf = memoryview(b'')
glfw.glfwSetCharModsCallback(window, self.on_text_input)
glfw.glfwSetKeyCallback(window, self.on_key)
@ -201,16 +201,8 @@ class Boss(Thread):
def read_ready(self):
if self.shutting_down:
return
try:
data = os.read(self.child_fd, 100 * io.DEFAULT_BUFFER_SIZE)
except BlockingIOError:
return
except EnvironmentError:
data = b''
if data:
self.parse_bytes(self.screen, data)
else: # EOF
self.shutdown()
if self.read_bytes(self.screen, self.child_fd) is False:
self.shutdown() # EOF
def write_ready(self):
if not self.shutting_down:

View File

@ -13,6 +13,8 @@ static PyMethodDef module_methods[] = {
GL_METHODS
{"parse_bytes", (PyCFunction)parse_bytes, METH_VARARGS, ""},
{"parse_bytes_dump", (PyCFunction)parse_bytes_dump, METH_VARARGS, ""},
{"read_bytes", (PyCFunction)read_bytes, METH_VARARGS, ""},
{"read_bytes_dump", (PyCFunction)read_bytes_dump, METH_VARARGS, ""},
{NULL, NULL, 0, NULL} /* Sentinel */
};

View File

@ -231,6 +231,7 @@ typedef struct {
} SavepointBuffer;
#define PARSER_BUF_SZ 8192
#define READ_BUF_SZ (1024*1024)
typedef struct {
PyObject_HEAD
@ -250,6 +251,7 @@ typedef struct {
uint8_t parser_buf[PARSER_BUF_SZ];
unsigned int parser_state, parser_text_start, parser_buf_pos;
bool parser_has_pending_text;
uint8_t read_buf[READ_BUF_SZ];
} Screen;
PyTypeObject Screen_Type;
@ -275,6 +277,8 @@ int init_SpriteMap(PyObject *);
int init_ChangeTracker(PyObject *);
int init_Screen(PyObject *);
PyObject* create_256_color_table();
PyObject* read_bytes_dump(PyObject UNUSED *, PyObject *);
PyObject* read_bytes(PyObject UNUSED *, PyObject *);
PyObject* parse_bytes_dump(PyObject UNUSED *, PyObject *);
PyObject* parse_bytes(PyObject UNUSED *, PyObject *);
uint16_t* translation_table(char);

View File

@ -7,6 +7,8 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include "data-types.h"
#include "control-codes.h"
@ -554,3 +556,34 @@ parse_bytes(PyObject UNUSED *self, PyObject *args) {
_parse_bytes(screen, pybuf.buf, pybuf.len, dump_callback);
Py_RETURN_NONE;
}
PyObject*
#ifdef DUMP_COMMANDS
read_bytes_dump(PyObject UNUSED *self, PyObject *args) {
#else
read_bytes(PyObject UNUSED *self, PyObject *args) {
#endif
PyObject *dump_callback = NULL;
Py_ssize_t len;
Screen *screen;
int fd;
#ifdef DUMP_COMMANDS
if (!PyArg_ParseTuple(args, "OOi", &dump_callback, &screen, &fd)) return NULL;
#else
if (!PyArg_ParseTuple(args, "Oi", &screen, &fd)) return NULL;
#endif
while(true) {
len = read(fd, screen->read_buf, READ_BUF_SZ);
if (len == -1) {
if (errno == EINTR) continue;
if (errno == EIO) { Py_RETURN_FALSE; }
return PyErr_SetFromErrno(PyExc_OSError);
}
break;
}
_parse_bytes(screen, screen->read_buf, len, dump_callback);
if(len > 0) { Py_RETURN_TRUE; }
Py_RETURN_FALSE;
}