Commit Graph

64812 Commits

Author SHA1 Message Date
Benjamin Otte
e8c4e1205a gtk-demo: Make colors demo do incremental sorting 2020-07-22 14:30:49 +02:00
Benjamin Otte
bf5c540357 sortlistmodel: Properly compute runs
When updating a (partially) sorted model, take the known runs for the
existing sort and apply them to the new sort. That way, we don't have to
check the whole model again.

Benchmarks:

      appending half the items to a model of strings
                        old      new
      512,000 items   437ms    389ms
    1,024,000 items  1006ms    914ms

      appending 10% of the items to a model of strings
                        old      new
      512,000 items   206ms    132ms
    1,024,000 items   438ms    301ms

      appending 1 item to a model of strings
                        old      new
       64,000 items   1.8ms   0.00ms
      512,000 items     ---   0.01ms
2020-07-22 14:30:49 +02:00
Benjamin Otte
c03383d3e5 sortlistmodel: Make sort stable again
Previously, the sort was not stable when items were added/removed while
sorting or the sort algorithm was changed.

Now the sort looks at the item position (via the key's location in the
keys array) to make sure each comparison stays stable with respect to
this position.
2020-07-22 14:30:49 +02:00
Benjamin Otte
eaaa287078 multisorter: Implement GtkSortKeys 2020-07-22 14:30:49 +02:00
Benjamin Otte
554defaf1a treelistrowsorter: Implement GtkSortKeys 2020-07-22 14:30:49 +02:00
Benjamin Otte
659fe52b7b numericsorter: Implement GtkSortKeys 2020-07-22 14:30:49 +02:00
Benjamin Otte
0970077af9 stringsorter: Implement GtkSortKeys 2020-07-22 14:30:49 +02:00
Benjamin Otte
814c88fbc1 sortkeys: Add an equal sort keys
Compares every element as equal.
This is useful when sorters are in an invalid configuration.
2020-07-22 14:30:49 +02:00
Benjamin Otte
3b24c8a0a4 sortlistmodel: Use GtkSortKeys
This massively speeds up sorting with expensive sort functions that it's
the most worthwhile optimization of this whole branch.
It's slower for simple sort functions though.

It's also quite a lot slower when the model doesn't support sort keys
(like GtkCustomSorter), but all the other sorters do support keys.

Of course, this depends on the number of items in the model - the number
of comparisons scales O(N * log N) while the overhead for key handling
scales O(N).
So as the log N part grows, generating keys gets more and more
beneficial.

Benchmarks:

       initial sort of a GFileInfo model with display-name keys
                       items     keys
         8,000 items   715ms     50ms
        64,000 items     ---    554ms

       initial sort of a GFileInfo model with complex keys
                       items     keys
        64,000 items   340ms    295ms
       128,000 items   641ms    605ms

       removing half a GFileInfo model with display-name keys
       (no comparisons, just key freeing overhead of a complex sorter)
                       items     keys
       512,000 items    14ms     21ms
     2,048,000 items    40ms     62ms

       removing half a GFileInfo model with complex keys
       (no comparisons, just key freeing overhead of a complex sorter)
                       items     keys
       512,000 items    90ms    237ms
     2,048,000 items   247ms    601ms
2020-07-22 14:30:49 +02:00
Benjamin Otte
e34c7e6796 sorter: Introduce GtkSortKeys
GtkSortKeys is an immutable struct that can be used to manage "sort
keys" for items.

Sort keys are memory that is created specifically for sorting. Because
sorting involves lots of comparisons, it's a good idea to prepare the
data relevant for sorting in advance and sort on that data.

In measurements with a PropertyExpression on a string sorter, it's about
??? faster
2020-07-22 14:30:49 +02:00
Benjamin Otte
8c608e9c1c sortlistmodel: Split the SortItem into 2 arrays
Instead of one item keeping the item + its position and sorting that
list, keep the items in 1 array and put the positions into a 2nd array.

This is generally slower while sorting, but allows multiple improvements:

1. We can replace items with keys
   This allows avoiding multiple slow lookups when using complex
   comparisons

2. We can keep multiple position arrays
   This allows doing a sorting in the background without actually
   emitting items-changed() until the array is completely sorted.

3. The main list tracks the items in the original model
   So only a single memmove() is necessary there, while the old version
   had to upgrade the position in every item.
Benchmarks:

        sorting a model of simple strings
                          old      new
        256,000 items   256ms    268ms
        512,000 items   569ms    638ms

        sorting a model of file trees, directories first, by size
                          old      new
         64,000 items   350ms    364ms
        128,000 items   667ms    691ms

        removing half the model
                          old      new
        512,000 items    24ms     15ms
      1,024,000 items    49ms     25ms
2020-07-22 14:30:49 +02:00
Benjamin Otte
283c3b70dd sortlistmodel: Add an incremental property
Also refactor a large part of the sortmodel to make this convenient.

A large amount of time has been spent on getting items-changed regions
minimized.
2020-07-22 14:30:49 +02:00
Benjamin Otte
93599c2c48 testsuite: Add exhaustive sortlistmodel test
This is basically a copy/paste from the filterlistmodel test, but
adapted for sorting.
2020-07-22 14:04:40 +02:00
Benjamin Otte
080e625090 sortlistmodel: Make the sort callback useful
1. Run step() for a while to avoid very short steps
   This way, we batch items-changed() emissions.

2. Track the change region accurately
   This way, we can avoid invalidating the whole list if our step just
   touched a small part of a huge list.
   As this is a merge sort, this is a common occurence when we're buys
   merging chunks: The rest of the model outside those chunks isn't
   changed.

Note that the tracking is accurate: It determines the minimum change
region in the model.

This will be important, because the testsuite is going to test this.
2020-07-22 14:04:40 +02:00
Benjamin Otte
26696a741e timsort: Add change tracking to gtk_tim_sort_step() 2020-07-22 14:04:40 +02:00
Benjamin Otte
a209e54b8f timsort: Add gtk_tim_sort_set_max_merge_size()
Makes the SOrtListModel responsive when incrementally sorting.

By making it configurable we can avoid losting performance in the
non-incremental case.
2020-07-22 14:04:40 +02:00
Benjamin Otte
8921dadaa1 timsort: Make sure merges don't take too long
Limit the size of the merged areas and thereby chunk larger merges into
smaller ones.
2020-07-22 14:04:40 +02:00
Benjamin Otte
47232acbd8 sortlistmodel: Make sorting incremental
This is just an experiment so far to see how long it takes to sort.
2020-07-22 14:04:40 +02:00
Benjamin Otte
cbad8ec2e4 timsort: Add gtk_tim_sort_set_runs()
... and use it in the SortListModel

Setting runs allows declaring already sorted regions so the sort does
not attempt to sort them again.

This massively speeds up partial inserts where we can reuse the sorted
model as a run and only resort the newly inserted parts.

Benchmarks:

    appending half the model
                    qsort  timsort
    128,000 items    94ms     69ms
    256,000 items   202ms    143ms
    512,000 items   488ms    328ms

    appending 1 item
                    qsort  timsort
      8,000 items   1.5ms    0.0ms
     16,000 items   3.1ms    0.0ms
              ...
    512,000 items     ---    1.8ms
2020-07-22 14:04:40 +02:00
Benjamin Otte
800170b47d sortlistmodel: Use timsort
Simply replace the old qsort() call with a timsort() call.

This is ultimately relevant because timsort is a LOT faster in merging
to already sorted lists (think items-chaged adding some items) or
reversing an existing list (think columnview sort order changes).

Benchmarks:

    initially sorting the model
                    qsort  timsort
    128,000 items   124ms    111ms
    256,000 items   264ms    250ms
2020-07-22 14:04:40 +02:00
Benjamin Otte
97c5cb3514 Add a timsort() implementation 2020-07-22 14:04:40 +02:00
Benjamin Otte
081afc0477 sortlistmodel: Track item positions
The model now tracks the original positions on top of just the items so that
it can remove items in an items-changed emission.

It now takes twice as much memory but removes items much faster.

Benchmarks:

Removing 50% of a model:
                   before    after
   250,000 items    135ms     10ms
   500,000 items    300ms     25ms

Removing 1 item:
     4,000 items    2.2ms      0ms
     8,000 items    4.6ms      0ms
   500,000 items      ---   0.01ms
2020-07-22 14:04:40 +02:00
Benjamin Otte
e807fc3be0 sortlistmodel: Replace with an array-based model
This is the dumbest possible sortmodel using an array:
Just grab all the items, put them in the array, qsort() the array.

Some benchmarks (setting a new model):

  125,000 items - old: 549ms
                  new: 115ms
  250,000 items - new: 250ms

This performance can not be kept for simple additions and removals
though.
2020-07-22 14:04:40 +02:00
Benjamin Otte
b67ffe9650 sortlistmodel: Test that the model is stable
Stability is measured relative to the child model, not relative to the
previous sorter.
2020-07-20 22:28:01 +02:00
Benjamin Otte
2c519b006d testsuite: Fix a leak 2020-07-20 22:28:01 +02:00
Matthias Clasen
852429d163 Merge branch 'barthalion/asan-runner' into 'master'
ci: Switch ASAN tests to runners tagged so

See merge request GNOME/gtk!2267
2020-07-20 16:17:49 +00:00
Matthias Clasen
ee9c6bbf75 Merge branch 'action-muxer-speedup' into 'master'
Action muxer speedup

See merge request GNOME/gtk!1754
2020-07-20 16:17:17 +00:00
Bartłomiej Piotrowski
d9ece94377 ci: Switch ASAN tests to runners tagged so 2020-07-20 16:41:46 +02:00
Matthias Clasen
486fbce42b actionmuxer: Update docs and clean up headers
Update the doc comment at the top to describe the
current  functionality of GtkActionMuxer.
2020-07-20 08:24:54 -04:00
Matthias Clasen
ed92026632 actionmuxer: Use an array for accels
We have a lot of accels across all the muxers, but the vast
majority has just one or two, so an array is going to be
smaller and faster for this.
2020-07-20 08:24:54 -04:00
Matthias Clasen
05e614feb7 actionmuxer: Create observed_actions and groups on demand
The vast majority of action muxers don't have observers or
groups, so we can avoid the overhead of carrying all these
empty hash tables.
2020-07-20 08:24:54 -04:00
Matthias Clasen
14059afdf1 inspector: Make the actions tab work again
Bring back the actions tab; we don't receive
changes anymore, since GtkActionMuxer lost
the GActionGroup signals for this, and the
action observer machinery has no way to listen
for all changes.
2020-07-20 08:24:54 -04:00
Matthias Clasen
9b294eb94e Add gtk_action_muxer_list_actions
This is needed to reinstate the actions support
in the inspector.
2020-07-20 08:24:53 -04:00
Matthias Clasen
96d42cf1cc actionmuxer: Stop implementing GActionGroup
Instead of implementing the GActionGroup interface
and using its signals for propagating changes up
and down the muxer hierarchy, use the GtkActionObserver
mechanism. This cuts down on the signal emission
overhead.
2020-07-20 08:24:53 -04:00
Matthias Clasen
4786a16696 actionmuxer: Port internal users
Port all internal users of the action muxer
from the GActionGroup interface to the new
action muxer apis.
2020-07-20 08:24:52 -04:00
Matthias Clasen
14bb12125f actionmuxer: Add some more api
We want to drop the GActionGroup interface from
GtkActionMuxer, so add the necessary api directly
to GtkActionMuxer itself.
2020-07-20 08:24:14 -04:00
Matthias Clasen
07e8dafcea inspector: Remove action support temporarily
This is using the action muxer as a GActionGroup,
and we want to remove that interface from GtkActionMuxer.

The support will come back later.
2020-07-20 08:24:14 -04:00
Matthias Clasen
ab67a81f11 Speed up action muxer setup more
Don't emit signals for group insertion/removal
if nobody is listening.
2020-07-20 08:24:14 -04:00
Matthias Clasen
aa76f7e210 Speed up action muxer setup
We don't need to duplicate all these action names and
emit all these signals if nobody is listening.
2020-07-20 08:24:14 -04:00
Matthias Clasen
0c15463e41 Merge branch 'matthiasc/for-master' into 'master'
Matthiasc/for master

See merge request GNOME/gtk!2266
2020-07-20 12:23:12 +00:00
Matthias Clasen
5df1356295 gsk: Remove an unused debug flag
GSK_DEBUG_DIFF was not used anywhere, so remove it.
2020-07-20 07:03:08 -04:00
Matthias Clasen
95fc81c565 inspector: Add a few more debug flags
Add check buttons for GTK_DEBUG=constraints and
GTK_DEBUG=layout in the logs page.
2020-07-20 07:03:08 -04:00
Matthias Clasen
378e594f75 Tweak the GTK_DEBUG=help output
I got the layout flag wrong when I added the
improved help output. It is about layout managers,
not about showing layout borders.
2020-07-20 07:03:08 -04:00
Matthias Clasen
86c7fceb09 Merge branch 'list-model-docs' into 'master'
List model docs

See merge request GNOME/gtk!2182
2020-07-19 23:50:09 +00:00
Matthias Clasen
b5e20a3e37 Merge branch 'matthiasc/for-master' into 'master'
Matthiasc/for master

See merge request GNOME/gtk!2265
2020-07-19 19:14:04 +00:00
Matthias Clasen
75a30b1f98 windowhandle: Don't use an action muxer needlessly
The api that is meant to be used here is
gtk_widget_activate_action.
2020-07-19 13:50:23 -04:00
Matthias Clasen
c64a021af4 NEWS: Updates 2020-07-18 18:28:51 -04:00
Matthias Clasen
9b64635925 Merge branch 'matthiasc/for-master' into 'master'
Matthiasc/for master

See merge request GNOME/gtk!2264
2020-07-18 17:31:31 +00:00
Matthias Clasen
7b76be5360 button: Add explicit key bindings for activation
We should not rely on GtkWindow to have global
"activate-default" key bindings that happen to
fall back to activating the focus widget. This is
unreliable, since the bubbling up from the button
to the toplevel may run across other widgets that
may want to use Enter for their own purpose, and
then the button loses out. By adding our own
key bindings, the button gets to handle it before
its ancestors.

This fixes check buttons in the inspector property
list not reacting to Enter despite having focus.
2020-07-18 12:53:10 -04:00
Matthias Clasen
2e2336ffce text: Claim clicks when grabbing focus
If we don't, an ancestor (such a GtkListItemWidget)
may interpret the click as "I should grab focus!",
and still our focus away. This was causing hard-to-focus
entries in the property list in the inspector.
2020-07-18 12:47:47 -04:00