GNOME Bugzilla – Bug 93775
highlite is very slow and sometimes crashes the terminal
Last modified: 2004-12-22 21:47:04 UTC
When I run VTE built into gnome-terminal highlighting text is amazingly slow (the highlight happens 5-10 seconds after the mouse events have completed) and often crashes the terminal. For some strange reason the problem only seems to happen after there is some data in the scrollback buffer. In other words highlighting will work okay if you highlight immediately after gnome-terminal is started. But if you type in a command that fills the screen with data and then start highlighting the problem can be seen. Using Sun's Forte Performance Analyzer Tool it seems to be spending over 98% of its time in a call to regexec in libc called from vte_terminal_match_check_internal, called from vte_terminal_match_hilite. For some reason I don't see things running so slowly when I run the src/vte demo program in the vte module. The slowdown only happens when running VTE with gnome-terminal. Not sure if this is a Solaris-specific problem. Has anyone on Linux seen such behavior?
Do you have a stack dump from the crash on Solaris? Hiliting works quickly on my Linux system.
I rebuilt VTE and gnome-terminal with VTE from CVS head. I am still seeing the slowdown. gnome-terminal seems to eat up 60-80% of the CPU on Solaris. It is still spending most of its time in regexec() called from vte_terminal_match_check_internal() called from vte_terminal_match_hilite(). Since you are not seeing this on Solaris, it sounds like a Solaris-specific bug. :) However I can't seem to make it crash anymore. It is just really slow. I notice that it when I build VTE into gnome-terminal it is using pango rendering (it ignores VTE_USE_PANGO=0 and VTE_USE_PANGOX=0). Is there any way to use VTE in gnome-terminal but not use pango for rendering? If possible, perhaps testing this combination may reveal something.
I have seen the same behavior (on Solaris 9). I think the problem is just that Solaris's internal regexp routines can't handle the gnome-terminal regular expressions efficiently. If there's very little text in the gnome-terminal window, then the regexec() call finishes quickly anyway. Here is a better reproduction recipe: * Fire up gnome-terminal on Solaris. * Fill the screen with some text (e.g. "ls -l"). * Move the mouse cursor around in the window, making sure to pass the cursor over a glyph. * Notice that the cursor stops blinking for a while and keypresses take a long time to appear. The longer you moved the mouse, the longer gnome-terminal takes to recover. Some possible solutions, none of them easy: * Link against a third-party regular expression library when building on Solaris. GNU regex and rx appear to crash on the relevant regular expressions, but pcreposix works great. This is the solution I'm going with locally. Unfortunately, it may be hard to arrange on a distribution level because gettext's libintl has a -lc library dependency, so it's a little tough to get pcre linked in before libc. * Cache the results of the regexec() calls in vte_terminal_match_check_internal(). Things would still be a little slow the first time you moved the mouse around after new text appears, but not nearly as bad. (The combination of continuously scrolling text and mouse movement might still be painful.) * Use simpler regular expressions in gnome-terminal. * Write a hand-coded URL recognizer and punt the vte_terminal_match_add() API. * Solaris could get a better regular expression implementation. (I wouldn't hold my breath.) As a complete side point, I don't understand why vte_terminal_match_check_internal() bothers to iterate over all of the matches returned by regexec(). It seems lik only matches[0] is of interest.
A brief addendum: using pcre should be fine if the normal pcre interfaces get used (and then libintl's -lc ceases to be a problem); using pcreposix would be dangerous since any other library which uses regcomp() and regexec() wouldn't be using matching structures. Of course, pcre's regular expression syntax is a little different from POSIX's, so pcre isn't a terribly satisfying solution anyway.
Oh, and, of course, rx and regex dumped core because I didn't rebuild the source files with the appropriate headers. pcre merely happened to use structures which were mostly (but not completely) compatible with the system ones. So rx or regex might work as alternatives to pcre if used correctly. (Sorry for the trickle of information.)
Created attachment 18185 [details] Workaround for this problem.
I think I have a simple workaround for this problem. The problem is caused by the vte_terminal_match_check_internal() routine in vte.c continually calling regexec() as you move the mouse around in the terminal window. Now the regular expression string that is being passed to regexec() is zero length, and regexec is always returning REG_NOMATCH. It's a simple workaround to not call regexec if the regular expression string length is zero, and instead just set the return value directly to REG_NOMATCH. With this changes, vte seems to be quite zippy on my Ultra 60 running Solaris 9 Update 3. Note that it'll make the Linux version go even faster too. I've attached a patch for this.
The reg member of the regex struct is not a string but a regex_t, so passing it to strlen() makes no sense to me.
Doh! I missed that. Thanks. Let me investigate further and see if I can check the re_len field in the regex_t struct for zero length, to provide a similar workaround. Probably tomorrow.
Well one thing I thought to check against was the match variable being passed to the regcomp() call, but that is initially set to "abcdefg" at line 631 in vteapp.c. Umm, why is that? It seems rather arbitary to me.
Narin, can you comment on this please to make sure I'm on the right track? I've been looking at this a bit further and thinking of a slightly different approach to try to work around the regexec slowness on Solaris. There is a routine called vte_terminal_match_add() that adds regular expressions to be checked as you do things in vte. In vteapp.c there are three (potential) calls to add expressions (at about line 631). Now two of these are only done if dingus is set. The other seeds a regular expression of "abcdefg" which seems to be pretty bogus. I'm guessing that's there to prevent other code that uses these regular expression from breaking (i.e. if there was just a null regex string). Correct assumption, or is there something I'm totally missing here? I'm thinking that perhaps a workaround here (for the case where dingus isn't set), is to remove the call to vte_terminal_match_add() for "abcdefg", and add in some checks to not do the regular expressiom checking if there isn't any other regular expressions set (i.e. dingus is not set). Does this seem a reasonable approach? If yes, I'll start trying to generate another patch. In conjunction with this, we will try to convince the Solaris libc folks to fix their slow regexec. Thanks.
On the assumption that the call to vte_terminal_match_add() for "abcdefg" was bogus, I just removed it. Now (assuming that dingus is not set - i.e. the user didn't supply a -D command line option), then this means that there are no regular expressions to be checked against, and terminal->pvt->match_regexes->len at line 1623 in vte.c is zero, so the if clause with the regexec calls in never gets called. vte is zippy once more on Solaris again (sans dingus). I'll attach another (much simpler) patch.
Created attachment 18198 [details] Second attempt at a workaround.
What exactly are you trying to work around here? The slowness comes from perfectly legitimate regexp executions. You can't optimize them away without breaking URL matching. vteapp.c is a vte test program; it isn't used by gnome-terminal or other callers of vte.
I'm trying to work around the slowness of the Solaris regexec. Your (several) suggestions on how to do this are tackling the problem from the regexec perspective. I was trying to see if there is a simple fix to just turn off the use of regular expressions in vte, which would circumvent the problem for us. I realize that they are a nice feature, but if turning them off generated a workaround, then that would have been nice. I'll go poke the Solaris libc folk and see if I can get them to fix their problem. The trouble there is that Solaris development moves at glacier speeds. If there was a way of getting around the problem in the vte code, we would have a solution much quicker.
Greg is right. The vte sample app adds arbitrary strings for matching so that I can test the matching code. Turning off use dingus matching in the sample app isn't going to affect gnome-terminal, which also makes use of the feature. I should point out that regex_t is an opaque type, and doesn't have an re_len field on some platforms.
I've created a small self-contained example program which I've attached to the Solaris libc/regexec bug (4858911) that Brian submitted. It shows that Solaris lib regexec is over five times slower the Gnu libc regexec. We had a useable workaround for our Solaris GNOME 2.[3,4] builds - namely building gnome-terminal against a libregex.so made up of the Gnu libc regex code. This really isn't a vte bug. Brian, if you are agreeable, I think this should be closed as NOTABUG.
yes, this bug can be closed, since it is not a bug with any part of GNOME.
I dunno; vte effectively doesn't work under Solaris, because of this performance issue. The fault may lie with Solaris for having a lousy regular expression matcher, but isn't it normally the responsibility of applications to work around OS bugs, at least until the OS bugs have been fixed in the current release. (I'm not saying someone has to rush out and fix this problem right now, especially because there's no obvious fix. But leaving it open in the bug-tracking db seems reasonable.)
Here's a workaround that can be used on Solaris. For the official Sun RE builds I presume they will probably create a Gnu regex library that'll be statically linked with vte, but the instructions here will get vte going on Solaris with minimal pain. Adjust accordingly for your Solaris machine and build environment: * Downloaded the Gnu regex-0.12 distribution from: ftp://ftp.gnu.org/gnu/libc/glibc-1.09.1.tar.gz * Unpacked into /net/stard.sfbay/spare/gnome-2.2/regex-0.12 * Built with: % cd /net/stard.sfbay/spare/gnome-2.2/regex-0.12 % cc -g -DSTDC_HEADERS=1 -DHAVE_STRING_H=1 -DHAVE_ALLOCA_H=1 -I. -I. -c regex.c % cc -G -h libregex.so.1 -o libregex.so.1 regex.o % ln -s libregex.so.1 libregex.so * Ran with: % setenv LD_PRELOAD /net/stard.sfbay/spare/gnome-2.2/regex-0.12/libregex.so % /net/stard.sfbay/opt/gnome-2.2/bin/vte
If you do this, please be absolutely certain that you build with the right regex.h so that regex_t structures used by the library are the correct size for passing to functions which read and modify them.
gnome-terminal 2.3.2 crashes on solaris 2.6 with this workaround after half way thru '/bin/ls -R /usr/lib'. vte performance is really bad on solaris. Anybody has a clue where the bottleneck is? any more workarounds?
Created attachment 22271 [details] [review] Workaround which avoids regexps but violates vte interface
I first worked around this problem by linking in an alternate regexp library, but that was dissatisfying because it could adversely affect other applications using vte. Also, one of my users still experienced bad performance using pcre, and I didn't really want to play the regexp library lottery again. So, I have substituted a custom URL matcher which matches according to the regexps passed by gnome-terminal to vte. This violates the vte interface specification, but is effective as a local patch if your problem is "gnome-terminal doesn't work for me."
This is fixed in Solaris 10 and Solaris 9 Update 6. I sugtgets that this bug be closed.
Greg, what version of vte is your patch against? I tried to apply it to 0.11.10, and it failed to apply cleanly.
It's against vte 0.10.27.
Any chance you could make it work with 0.11.x? Recent versions of gnome-terminal require >0.11.0 vte.
Sorry, no plans to do that any time soon.
Created attachment 24823 [details] [review] Greg's workaround patch to vte.c, applied against vte-0.11.10
For fellow Solaris 8 sufferers, I applied Greg's patch to 0.11.10. It works for me. For the first time in at least a year, gnome-terminal works on my machine (goodbye, CDE dtterm!).
*** Bug 124874 has been marked as a duplicate of this bug. ***
Will there be some notation in release notes somewhere, that a patched Solaris 9 is required for Gnome (at least, gnome-terminal)? Possibly referring to this bug? Otherwise, unfortunate end-users like myself spend a lot of time spinning their wheels.
The last patch seems (finally) work for me on Sol9/SPARC with GNOME 2.6 beta. Will definitely test in final 2.6.0 as soon I patch the Garnome's version numbers, and report here then.
On solaris 8, I experience the same highlight slowness problem with gnome-terminal 2.4.0.1, but not for vte, even when there's a lot of text in the buffer. Any idea on how to track this down further?
The problem occurs because gnome-terminal passes complicated regexps to vte for hilight matching.