Do not use the python threading module

Threading in python imposes significant overhead.
Instead create the thread using pthreads directly
This commit is contained in:
Kovid Goyal
2017-09-06 18:32:57 +05:30
parent 94c4c00859
commit 7f180ad3d9
3 changed files with 45 additions and 14 deletions

View File

@@ -3,7 +3,6 @@
# License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
from gettext import gettext as _
from threading import Thread
from time import monotonic
from weakref import WeakValueDictionary
@@ -82,12 +81,11 @@ class DumpCommands: # {{{
# }}}
class Boss(Thread):
class Boss:
daemon = True
def __init__(self, glfw_window, opts, args):
Thread.__init__(self, name='ChildMonitor')
self.window_id_map = WeakValueDictionary()
startup_session = create_session(opts, args)
self.cursor_blink_zero_time = monotonic()
@@ -169,8 +167,10 @@ class Boss(Thread):
for window in tab:
self.close_window(window)
def run(self):
self.child_monitor.loop()
def start(self):
if not getattr(self, 'io_thread_started', False):
self.child_monitor.start()
self.io_thread_started = True
def on_window_resize(self, window, w, h):
# debounce resize events
@@ -423,7 +423,7 @@ class Boss(Thread):
self.shutting_down = True
self.child_monitor.shutdown()
wakeup()
self.join()
self.child_monitor.join()
for t in self.tab_manager:
t.destroy()
del self.tab_manager

View File

@@ -5,10 +5,15 @@
* Distributed under terms of the GPL3 license.
*/
#ifndef __APPLE__
// Need _GNU_SOURCE for pthread_setname_np on linux
#define _GNU_SOURCE
#endif
#include <pthread.h>
#undef _GNU_SOURCE
#include "data-types.h"
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>
#include <signal.h>
#include <GLFW/glfw3.h>
@@ -151,6 +156,25 @@ wakeup_(int fd) {
}
}
static void* io_loop(void *data);
static PyObject *
start(ChildMonitor *self) {
#define start_doc "start() -> Start the I/O thread"
int ret = pthread_create(&self->io_thread, NULL, io_loop, self);
if (ret != 0) return PyErr_SetFromErrno(PyExc_OSError);
Py_RETURN_NONE;
}
static PyObject *
join(ChildMonitor *self) {
#define join_doc "join() -> Wait for the I/O thread to finish"
int ret = pthread_join(self->io_thread, NULL);
if (ret != 0) return PyErr_SetFromErrno(PyExc_OSError);
Py_RETURN_NONE;
}
static PyObject *
wakeup(ChildMonitor UNUSED *self) {
#define wakeup_doc "wakeup() -> wakeup the ChildMonitor I/O thread, forcing it to exit from poll() if it is waiting there."
@@ -396,15 +420,21 @@ write_to_child(int fd, Screen *screen) {
screen_mutex(unlock, write);
}
static PyObject *
loop(ChildMonitor *self) {
#define loop_doc "loop() -> The monitor loop."
static void*
io_loop(void *data) {
// The I/O thread loop
size_t i;
int ret;
bool has_more, data_received;
Screen *screen;
ChildMonitor *self = (ChildMonitor*)data;
#ifdef __APPLE__
pthread_setname_np("ChildMonitor");
#else
pthread_setname_np(self->io_thread, "ChildMonitor");
#endif
Py_BEGIN_ALLOW_THREADS;
while (LIKELY(!self->shutting_down)) {
children_mutex(lock);
remove_children(self);
@@ -455,8 +485,7 @@ loop(ChildMonitor *self) {
remove_children(self);
for (i = 0; i < EXTRA_FDS; i++) close(fds[i].fd);
children_mutex(unlock);
Py_END_ALLOW_THREADS;
Py_RETURN_NONE;
return 0;
}
// }}}
@@ -464,7 +493,8 @@ loop(ChildMonitor *self) {
static PyMethodDef methods[] = {
METHOD(add_child, METH_VARARGS)
METHOD(needs_write, METH_VARARGS)
METHOD(loop, METH_NOARGS)
METHOD(start, METH_NOARGS)
METHOD(join, METH_NOARGS)
METHOD(wakeup, METH_NOARGS)
METHOD(shutdown, METH_NOARGS)
METHOD(parse_input, METH_NOARGS)

View File

@@ -284,6 +284,7 @@ typedef struct {
double repaint_delay;
unsigned int count;
bool shutting_down;
pthread_t io_thread;
} ChildMonitor;
PyTypeObject ChildMonitor_Type;