Open pattontim opened 2 years ago
Okay so I've been able to narrow the scope of the problem down considerably
It's not the loading from _create_background or OSDWindow.show(). For me these averaged out to 37 and 20ms each to run.
I then thought it may be the drawing, however a few observations don't support this. Removing the code from on_draw still makes the background take long to draw, almost no effect. It's not window size (# pixels), since if I resize the window down to 1/4 the size it still takes long.
However. opening the menu display is fast. What differs between menu and keyboard window? My guess is the portion of the code responsible for locking and/or creating the input device
This is the culprit for me, 250-300ms runtime on my hardware
# Get All defines from linux headers
if os.path.exists('/usr/include/linux/input-event-codes.h'):
CHEAD = defines('/usr/include', 'linux/input-event-codes.h')
elif os.path.exists(os.path.split(__file__)[0] + '/input-event-codes.h'):
CHEAD = defines(os.path.split(__file__)[0], 'input-event-codes.h')
else:
CHEAD = defines('/usr/include', 'linux/input.h')
MAX_FEEDBACK_EFFECTS = 4
# Keys enum contains all keys and button from linux/uinput.h (KEY_* BTN_*)
Keys = IntEnum('Keys', {i: CHEAD[i] for i in CHEAD.keys() if (i.startswith('KEY_') or
i.startswith('BTN_'))})
# Keys enum contains all keys and button from linux/uinput.h (KEY_* BTN_*)
KeysOnly = IntEnum('KeysOnly', {i: CHEAD[i] for i in CHEAD.keys() if i.startswith('KEY_')})
# Axes enum contains all axes from linux/uinput.h (ABS_*)
Axes = IntEnum('Axes', {i: CHEAD[i] for i in CHEAD.keys() if i.startswith('ABS_')})
# Rels enum contains all rels from linux/uinput.h (REL_*)
Rels = IntEnum('Rels', {i: CHEAD[i] for i in CHEAD.keys() if i.startswith('REL_')})
The enums are slow.
This is my replacement, saving 200ms.
class EnumDict(dict):
"""dot.notation access to dictionary attributes"""
#__getattr__ = dict.get
def __getattr__(self, name):
return dict.get(self, name)
__setattr__ = dict.__setitem__
__delattr__ = dict.__delitem__
PROFILE_KEYS = ""
name = ""
class KeysDict(EnumDict):
name = "Keys"
class KeysOnlyDict(EnumDict):
name = "KeysOnly"
class RelsDict(EnumDict):
name = "Rels"
class AxesDict(EnumDict):
name = "Axes"
It's more complicated since calling str on the attribute is different, I'd have to return a custom object for each with str overridden so that Keys['KEY_END'] for example returns Keys.KEY_END rather than 107. If there is a more elegant solution.
That's interesting and looks like good improvement, but I don't understand why is this code called every time when keyboard is shown in the first place.
If you are starting scc-osd-keyboard
executable every time, then it's okay and understandable. But if you have scc-osd-daemon
running and keyboard is shown after selecting "show keyboard" item from menu, keyboard should be shown from same process without loading and parsing everything every time. Especially uinput module should not be executed more times than once, when scc-osd-daemon
is started.
It was a consequence of starting scc-osd-keyboard
executable every time after making a shell script which passes mouse location args. With the goal of having the keyboard follow the mouse. The same can be achieved with this, I'll try to add some config opts when I get the chance
mx, my = X.get_mouse_pos(self.dpy)
OSDWindow.show(self, *a)
self.move(mx, my)
Suggest adding --use-daemon option when executing external utilities which can write to the daemon socket things like OSD: keyboard *args
to reuse daemon
On my hardware, by my estimates it takes about 500-700ms to display the keyboard.
As far as I can tell, much of the delay probably has to do with loading the file from the keyboard and building the keyboard or it's possible that the loading of a Gtk window is that slow.
research direction:
1) Build and load a finished keyboard directly from file or temporary cache / communicate with daemon to load Keyboard instance
2) If the source is gtk, look into where it may be possible to use HW acceleration or caching to improve performance
I will perform some benchmarks in the meantime to identify where the bottleneck currently is. The OSD menu by contrast takes 50 to 100ms to appear by comparison.