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 629129 - gtk_text_iter_forward_visible_cursor_position is VERY slow
gtk_text_iter_forward_visible_cursor_position is VERY slow
Status: RESOLVED OBSOLETE
Product: gtk+
Classification: Platform
Component: Widget: GtkTextView
unspecified
Other Linux
: Normal normal
: ---
Assigned To: gtk-bugs
gtk-bugs
Depends on:
Blocks:
 
 
Reported: 2010-09-09 02:19 UTC by José Aliste
Modified: 2018-04-15 00:17 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
textiter: remove recursivity for find_by_log_attrs() (3.26 KB, patch)
2014-04-10 22:12 UTC, Sébastien Wilmet
committed Details | Review
textiter: small optimization for find_by_log_attrs() (1.93 KB, patch)
2014-04-11 12:00 UTC, Sébastien Wilmet
committed Details | Review
textiter: simplify find_by_log_attrs() (5.51 KB, patch)
2014-04-11 12:37 UTC, Sébastien Wilmet
committed Details | Review
Test performances (1.32 KB, text/plain)
2014-04-14 12:38 UTC, Sébastien Wilmet
  Details

Description José Aliste 2010-09-09 02:19:52 UTC
The title says it all ;). Actually on the code there is a fixme where it says the code is "gratiously" slow, so I am adding this in the hope of giving this bug more exposition. 

The slowness is noticeable on big unwrapped lines (length depends on your cpu)  when calling the function when the cursor is near the end of the line.
Comment 1 Sébastien Wilmet 2014-04-10 22:12:36 UTC
Created attachment 274046 [details] [review]
textiter: remove recursivity for find_by_log_attrs()

find_by_log_attrs() was a recursive function. It is replaced by an
iteration.

There is still a part to optimize for a later commit.
Comment 2 Sébastien Wilmet 2014-04-10 22:15:22 UTC
find_visible_by_log_attrs() should also be optimized, and is probably the main source of the bad performances. The function should skip directly all the invisible region.
Comment 3 Sébastien Wilmet 2014-04-11 12:00:54 UTC
Created attachment 274079 [details] [review]
textiter: small optimization for find_by_log_attrs()

Use gtk_text_iter_set_line_offset (&tmp_iter, 0) instead of
gtk_text_iter_get_line(). The difference should not be big. In the first
case the line doesn't need to be traversed thanks to the offset 0. For
get_line(), the btree must be traversed.

A temporary iter is needed to not break the behavior. But the behavior
is quite strange, the function works directly on the iter passed as an
argument to the function, even if the function returns FALSE (not
found). So maybe a later commit will fix this strange behavior.
Comment 4 Sébastien Wilmet 2014-04-11 12:37:14 UTC
Created attachment 274088 [details] [review]
textiter: simplify find_by_log_attrs()

And find_visible_by_log_attrs().

The already_moved_initially parameter was always FALSE.

There is also a small cleanup of the find_visible_by_log_attrs()
(remove trailing spaces, fix indentation).
Comment 5 Sébastien Wilmet 2014-04-11 13:26:03 UTC
It seems there is no easy way to skip an invisible region.

A solution:
- create a list of GtkTextTags having the 'invisible' property to TRUE (and 'invisible-set' too), by looking at all the tags present in the tag table.
- call gtk_text_iter_forward_to_tag_toggle() or backward_to_tag_toggle() on each tags.
- take the nearest iter.
Comment 6 Sébastien Wilmet 2014-04-11 14:28:34 UTC
(In reply to comment #5)
> - take the nearest iter.

This won't work if the invisible tags overlap, unfortunately.

A GtkTextRegion would be useful to solve this problem I think:
https://git.gnome.org/browse/gtksourceview/tree/gtksourceview/gtktextregion.h

We add all the nearest invisible regions in the GtkTextRegion, GtkTextRegion will merge the regions if they overlap, and then we use the iterator functions to find the nearest visible region.
Comment 7 Matthias Clasen 2014-04-14 05:23:55 UTC
Do you have any performance tests for this ? It would be really nice to have tests that prove the claimed performance improvements.
Comment 8 Sébastien Wilmet 2014-04-14 12:38:43 UTC
Created attachment 274262 [details]
Test performances

The first patch is not only for performances reasons, an iteration is better in C than recursivity.

The second patch is a micro-optimization which was based on common sense. The attached file test.c measures this micro-optimization. The results:
$ ./test
Before patch: 0.196737 seconds.
After patch: 0.192029 seconds.

It tests the difference between:
> gtk_text_iter_set_line_offset (&iter, 0);
and:
> gtk_text_iter_get_line (&iter) > 0

So I was right.

And the third patch is just a cleanup.

But the main problem still exists in find_visible_by_log_attrs() (based on common sense).
Comment 9 Sébastien Wilmet 2014-04-15 11:01:48 UTC
So the fixme comment "this function is very, very gratuitously slow" was probably no longer valid. Or am I missing something?
Comment 10 Sébastien Wilmet 2014-05-12 13:51:33 UTC
The slower thing in find_by_log_attrs() is the call to find_line_log_attrs(), which call _gtk_text_buffer_get_line_log_attrs(). Getting the log attrs for the whole line is needed because some attributes need some context to work properly.

The other things in find_by_log_attrs() is just navigation through the buffer. It can not be really optimized (and doing so is useless, as the micro-optimization above shows).

So I think it is right to remove the fixme comment about the slowness of find_by_log_attrs().
Comment 11 Paolo Borelli 2014-07-13 14:40:35 UTC
Review of attachment 274079 [details] [review]:

This one looks obviously correct to me. And I agree that the usage of the iter is suspicious
Comment 12 Paolo Borelli 2014-07-13 14:44:36 UTC
Review of attachment 274046 [details] [review]:

I am not sure that the comment about being slow is outdated or if instead there is some logical optimization we are missing (as opposed to playing games with recursivity and microoptimizations)
It is also true that keeping that comment without anyone knowing what it means is not very useful eiter

That said, I think that the non recursive version is actually easier to read, so I think the patch should go in

::: gtk/gtktextiter.c
@@ +3113,3 @@
+      gboolean found;
+
+      found = find_line_log_attrs (iter, func, &offset, already_moved_initially);

if you want to shorten the code a bit here you could do

if (!find_line_log_attrs())
   ...
   return

and save a local var
Comment 13 Paolo Borelli 2014-07-13 14:47:23 UTC
Review of attachment 274088 [details] [review]:

This is strange... the patch itself looks ok, but it would be interesting to dig into the git log when that param started to be false for every call
Comment 14 Paolo Borelli 2014-07-13 14:54:52 UTC
Review of attachment 274088 [details] [review]:

Actually, the bool param was used in the recursion. So I think it is more clear to squash this patch with the first one
Comment 15 Sébastien Wilmet 2014-07-13 15:12:34 UTC
Comment on attachment 274088 [details] [review]
textiter: simplify find_by_log_attrs()

This commit has been squashed with the commit that removes the recursivity.
Comment 16 Sébastien Wilmet 2014-12-20 15:25:51 UTC
(In reply to comment #5)
> It seems there is no easy way to skip an invisible region.

Bug #321548 contains an interesting solution, that can probably be applied here.

Though the solution described in Comment #5 and Comment #6 could be generalized so it is useful for other properties, which would be useful for bug #719978.
Comment 17 Matthias Clasen 2018-02-10 05:18:58 UTC
We're moving to gitlab! As part of this move, we are moving bugs to NEEDINFO if they haven't seen activity in more than a year. If this issue is still important to you and still relevant with GTK+ 3.22 or master, please reopen it and we will migrate it to gitlab.
Comment 18 Matthias Clasen 2018-04-15 00:17:36 UTC
As announced a while ago, we are migrating to gitlab, and bugs that haven't seen activity in the last year or so will be not be migrated, but closed out in bugzilla.

If this bug is still relevant to you, you can open a new issue describing the symptoms and how to reproduce it with gtk 3.22.x or master in gitlab:

https://gitlab.gnome.org/GNOME/gtk/issues/new