marcs@SLC.COM (Marc San Soucie) (12/12/90)
OSF Problem Report
=================================
Submitter Information (Include Email address at miminum)
---------------------
Submitter Name: Marc San Soucie
Organization: Servio Corporation - Beaverton, Oregon
Email Address: marcs@slc.com
Phone: 503-690-3526
OSF License Number: Could be 287
Hardware/Software Configuration
-------------------------------
Offering and Version: Motif 1.1.0
Component (Module): VirtKeys.c
Client Hardware: Sun SPARCStation 1, 16Meg memory
Client Software: SunOS 4.0.3, X11R4 (MIT)
Server Hardware: SAME
Server Software: SAME
Compiler: ?
Problem Description
-------------------
Severity Level: Severe
Because I find this kind of thing hard to swallow...
Date of First Occurrence:
12/10/90
One Line Description:
FindVirtKey is excessively slow, and is called too many times.
Full Description:
I was running 'prof' against a bunch of MOTIF applications built with prof
version of libXm.a, libXt.a, and libX11.a, in order to see where all the
time was going. In this particular case, I was running a complex multi-pane
EMACS-like editor thing which included a pair of multi-line text widgets. I
created widget hierarchies, created text buffers, moved the focus around,
pulled down some menus, and typed about 140 keystrokes. Here are the top
few lines of the 'prof' output, which YES, I KNOW is not overwhelmingly
accurate, but it does give some idea of the problem.
First, it is simply unfathomable that FindVirtKey should need to be called
47000 times to handle 140 keystrokes. Not having studied the
interrelationship between XtTranslateKeycode and XmTranslateKey in detail,
I can only surmise that someone has written a blunt and clumsy loop when a
modicum of smarts would have been more effective.
Second, FindVirtKey itself is written in such a way as to insure its place
high on the list of costly calls. I have supplied a suggestion for its
improvement below. The improved version is unfortunately only 20-30%
faster, since the bulk of the problem is that MOTIF is walking through a
longish virtual bindings list a gobule of times for easy lousy keystroke.
Add up all the costs due to virtual keysym lookup and you've got one heck
of a CPU-expensive widget set there.
%time cumsecs #call ms/call name
30.9 3.61 47063 0.08 _FindVirtKey
11.0 4.89 mcount
2.7 5.21 47063 0.01 _XtTranslateKey
2.4 5.49 9682 0.03 _XrmStringToQuark
2.2 5.75 46644 0.01 __XtConvertCase
2.0 5.98 91405 0.00 multiply.o
1.8 6.19 9295 0.02 __XtMatchUsingDontCareMods
1.7 6.39 304 0.66 _RefigureLines
1.7 6.59 1013 0.20 _read
1.6 6.78 47063 0.00 _XtTranslateKeycode
1.5 6.96 3662 0.05 _ComputeLateBindings
1.5 7.14 192 0.94 _XStringToKeysym
1.5 7.31 679 0.25 select.o
1.4 7.47 292 0.55 write.o
1.3 7.62 50350 0.00 _XFindContext
1.1 7.75 680 0.19 _FindWidth
1.1 7.88 _HPfree
1.1 8.01 47063 0.00 __XmTranslateKey
1.0 8.13 hpalloc.o
1.0 8.25 157 0.76 writev.o
0.9 8.36 iss2
0.9 8.46 33 3.03 _access
0.9 8.56 2000 0.05 ioctl.o
0.8 8.65 703 0.13 SetValues.o
0.7 8.73 7777 0.01 _MeasureLine
0.7 8.81 13699 0.01 __XmGetClassExtensionPtr
0.7 8.89 11765 0.01 __XmIsSlowSubclass
0.6 8.96 1120 0.06 _Scan
0.6 9.03 w4cp
0.5 9.09 2873 0.02 _CallSetValues
0.5 9.15 1524 0.04 gettimeofday.o
0.4 9.20 512 0.10 _MatchEvent
0.4 9.25 155 0.32 __XmTextInvalidate
0.4 9.30 w4cp
0.3 9.34 60 0.67 _BindActions
0.3 9.38 15138 0.00 _EqualEvents
0.3 9.42 47326 0.00 _GetVirtualBindingsData
0.3 9.46 1135 0.04 _ScanAlphanumeric
0.3 9.50 845 0.05 _XNextEvent
0.3 9.54 846 0.05 _XtAppNextEvent
Repeat By:
Build a 'prof' version of anything with a multi-line text widget in it. Or
any widget, for that matter, that accepts keystrokes.
Proposed Solution:
static void FindVirtKey (virtData, keycode, modifiers,
modifiers_return, keysym_return)
XmVirtualBindingsData virtData;
KeyCode keycode;
Modifiers modifiers;
Modifiers *modifiers_return;
KeySym *keysym_return;
{
XmKeyBinding keyBindings = virtData->bindings;
Cardinal i;
XmKeyBinding currBinding;
Modifiers eventMods;
KeySym keysym;
/*
* get the modifiers from the actual event
*/
eventMods = (Modifiers)(virtData->lastKeyEvent->state) & modifiers;
keysym = *keysym_return;
currBinding = keyBindings;
for (i = 0; i < XtNumber(virtualKeysyms); i++)
{
/*
* the null binding should not be interpreted as a match
* keysym is zero (e.g. pre-edit terminator)
*/
if (currBinding->keysym == keysym &&
currBinding->modifiers == eventMods &&
currBinding->keysym)
{
*keysym_return = virtualKeysyms[i].keysym;
break;
}
currBinding++;
}
*modifiers_return |= ControlMask | Mod1Mask;
}
New numbers for approximately the same activity...
Better, but not great. Solve the real problem, and throw this in for the fun of
it.
%time cumsecs #call ms/call name
20.6 2.20 47419 0.05 _FindVirtKey
14.1 3.71 mcount
3.5 4.08 3694 0.10 _ComputeLateBindings
2.8 4.38 47419 0.01 _XtTranslateKey
2.5 4.65 1011 0.27 select.o
2.2 4.89 9773 0.02 _XrmStringToQuark
2.2 5.12 311 0.74 _RefigureLines
2.2 5.35 9366 0.02 __XtMatchUsingDontCareMods
2.0 5.56 192 1.09 _XStringToKeysym
2.0 5.77 1184 0.18 _read
1.9 5.97 47419 0.00 _XtTranslateKeycode
1.7 6.15 47000 0.00 __XtConvertCase
1.7 6.33 384 0.47 write.o
1.6 6.50 50863 0.00 _XFindContext
1.6 6.67 hpalloc.o
1.5 6.83 160 1.00 writev.o
1.3 6.97 47419 0.00 __XmTranslateKey
1.2 7.10 _HPfree
1.1 7.22 92234 0.00 multiply.o
0.9 7.32 690 0.14 _FindWidth
0.8 7.41 321 0.28 _GetResources
0.8 7.50 47684 0.00 _GetVirtualBindingsData
0.8 7.59 33 2.73 _access
0.7 7.67 7873 0.01 _MeasureLine
0.7 7.75 14482 0.01 __XmGetClassExtensionPtr
0.7 7.83 2148 0.04 gettimeofday.o
0.7 7.91 w4cp
0.7 7.98 774 0.09 _ImportArgs
0.7 8.05 603 0.12 _MatchEvent
0.7 8.12 2787 0.03 ioctl.o
0.6 8.18 1140 0.05 _Scan
0.5 8.23 733 0.07 SetValues.o
0.5 8.28 7732 0.01 _AddRedraw
0.5 8.33 1829 0.03 _CallGetValuesHook
0.5 8.38 2964 0.02 _CallSetValues
0.5 8.43 12504 0.00 __XmIsSlowSubclass