After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 499954 - [ARITH] Key repeat is delayed
[ARITH] Key repeat is delayed
Status: RESOLVED FIXED
Product: gnome-calculator
Classification: Core
Component: general
5.21.x
Other Linux
: Normal major
: ---
Assigned To: gcalctool maintainers
gcalctool maintainers
Depends on:
Blocks: 500994
 
 
Reported: 2007-11-27 12:22 UTC by Robert Ancell
Modified: 2008-04-12 08:23 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Gprof results (60.22 KB, text/plain)
2007-12-12 22:57 UTC, Rich Burridge
  Details
Faster implementation for creating binary numbers (3.21 KB, patch)
2007-12-23 09:13 UTC, Sami Pietilä
committed Details | Review

Description Robert Ancell 2007-11-27 12:22:01 UTC
Holding down a key in calculator stalls the display and uses up 100% CPU.

Steps to reproduce:
1. Open Calculator
2. Hold down 1 key

Expected result:
1s are continuously and smoothly appended to the display

Actual result:
The first few are added then the display stalls and 100% CPU is used. After ~1s many more numbers are shown (i.e. they were delayed)

This doesn't occur in 2.20.2, occurs slightly in 2.22.1 and occurs in 2.22.0 and 2.22.2.

Doing a ltrace of calctool shows many expensive repetitive operations (e.g. repeated strlen() of a 199 character 0.000000... string) but I can't see a major difference between this and the 2.20 series.
Comment 1 Robert Ancell 2007-11-27 12:24:39 UTC
I tried reimplementing the make minimal changes to display routine to see if this was causing it but it made no difference (as I would expect since GTK+ is probably faster at just replacing the display).
Comment 2 Rich Burridge 2007-11-27 16:11:02 UTC
Note that this is only a problem (for me at least) in arithmetic 
precedence mode, which suggests that the problem is going to be 
specific to a "case EXPRS:" clause somewhere.
Comment 3 Rich Burridge 2007-12-12 22:57:39 UTC
Created attachment 100854 [details]
Gprof results 

I recompiled gcalctool with the -p option to allow us to
run gprof on it. I then did the following test:

1/ Start gcalctool
   Make sure you are in arithmetic precedence mode.
2/ Held the "3" down for about five seconds.
3/ Selected File->Quit from the menu bar.

I then generated these results with:

% gprof gcalctool gmon.out

From a quick perusal of the results, I'd say that we are doing
*way* too much validation of what the user is typing in as s/he
is typing it in.

Sami/Robert, perhaps you can pin-point how best to improve this.

One possible "quick fix" is to make sure that we synchronously 
update the display area after processing each input character, 
that may make the problem look less obvious.
Comment 4 Robert Ancell 2007-12-15 01:17:27 UTC
Found the problem. It's the bit panel that is causing the problem.

Each key that gets pressed causes the display to be updated which means the bit panel needs to be updated. This occurs in gtk.c through set_bit_panel() in do_button(). As the display gets more complicated the calculation gets slower and slower. This occurs in all modes but the bit panel is only visible in scientific mode.

The facts:

1. We have to update the bit panel when the number in the display is changed. There should be an optimisation that the bit panel is greyed out unless the display is an appropriately sized integer (i.e. if it has a fractional component ('1.123') or is a calculation('123+456'))

2. The arithmetic solver is too slow. The above example of entering a single repeating digit is a simple case and should not cause this much delay.

3. The bit panel should not be set from the UI. It currently gets updated when a button is pressed but should be updated when the display changes (which can be caused by other events like mode changes).

Sami, can you look at the parser/solver and see why it is so slow solving simple integers?
Comment 5 Robert Ancell 2007-12-15 01:18:11 UTC
(to prove it is the bit panel quote out the set_bit_panel() call and recompile)
Comment 6 Sami Pietilä 2007-12-15 08:15:16 UTC
>2. The arithmetic solver is too slow. The above example of entering a single
>repeating digit is a simple case and should not cause this much delay.

Can you give some details? 

I left "int ret = usable_num(MP);" into set_bit_panel() and commented the whole "switch" section out. After that, the slowness was gone.
Comment 7 Robert Ancell 2007-12-16 12:55:29 UTC
Yes, but you've deleted the bin_str() call which is only in the EXPRS branch of set_bit_panel()...
Comment 8 Sami Pietilä 2007-12-16 17:07:24 UTC
Expanding the scope beyond the parser. The bin_str() uses mp lib which might be slow.

I suggest using the same method in expression mode than is used in non-expression mode. That is, replacing EXPRS branch with:

----- code in EXPR case -------

            if (ret || !is_integer(MP)) {
                gtk_widget_set_sensitive(X->bit_panel, FALSE);
                return;
            }
            
            {
                char *bit_str, label[3], tmp[MAXLINE];
                bit_str = make_fixed(MP, tmp, BIN, MAXLINE, FALSE);
                bit_str_len = strlen(bit_str);
                if (bit_str_len <= MAXBITS) {
                    gtk_widget_set_sensitive(X->bit_panel, TRUE);
                    
                    STRCPY(label, " 0");
                    for (i = 0; i < MAXBITS; i++) {
                        label[1] = (i < bit_str_len) ? bit_str[bit_str_len-i-1] : '0';
                        gtk_label_set_text(GTK_LABEL(X->bits[MAXBITS - i - 1]), label);
                    }
                    
                    return;
                }

            }

--- end of code ---

This seems to make it fast. I'll add this to my TODO list and write a real patch when I get a moment for that.

Comment 9 Sami Pietilä 2007-12-23 09:13:33 UTC
Created attachment 101491 [details] [review]
Faster implementation for creating binary numbers
Comment 10 Sami Pietilä 2007-12-23 09:20:36 UTC
Please note that there still is a bug, which is caused by the is_integer() call. is_integer() is not able to detect, for example, 2^8 as an integer.
Comment 11 Rich Burridge 2008-01-02 18:01:09 UTC
Patch committed. Thanks.

> Please note that there still is a bug, which is caused by the is_integer()
> call. is_integer() is not able to detect, for example, 2^8 as an integer.

Can you provide a set of steps that I can do with gcalctool that
reproduces this problem?

Comment 12 Robert Ancell 2008-04-12 08:23:07 UTC
Problem doesn't seem to occur in 2.22.1, closing.