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