Commit Graph

64832 Commits

Author SHA1 Message Date
Benjamin Otte
3cd9908b43 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 03:21:41 +02:00
Benjamin Otte
7d95bc4dc6 testsuite: Support different models
In particular, add a GtkTreeModel of GtkDirectoryList that enumerates
the full tree of everything below G_TEST_SRCDIR.

You can set it to ~ or / to get lots of files.

Use this to test numeric sorting, string sorting, the treelistrow
sorter and the multisorter.
And while doing all of that, try to use something that is still
realistic.
2020-07-22 03:21:41 +02:00
Benjamin Otte
cf0f0956a9 testsuite: Support incremental and non-incremental sorting 2020-07-22 03:21:41 +02:00
Benjamin Otte
ceaa0e3962 testsuite: Collect more statistics on models
* "max time"
   Reports the max time taken for all main loop iterations + initial
   set.
   This is useful to judge the performance of incremental search models.
 * "changes"
   Reports the sum of all changes during items-changed signal emissions.
   Uses MAX(added, removed) as the number to not double-count items that
   were moved.
   This is useful to judge the accuracy of the models by comparing the
   number among them.
2020-07-22 03:21:41 +02:00
Benjamin Otte
7dcde5620f testsuite: Add more sorting tests 2020-07-22 03:21:41 +02:00
Benjamin Otte
693a459b43 testsuite: Add some sorting performance tests 2020-07-22 03:21:41 +02:00
Matthias Clasen
33656fe588 sor3listmodel: Add an incremental property
This lets us easily compare incremental and non-incremental
sorting.
2020-07-22 03:21:41 +02:00
Matthias Clasen
8ae3529bb3 sor3listmodel: Do time-based batching
Stop a sorting step if it has run for more than 1.5ms.
This is an attempt to improve interactivity during
incremental sorting.
2020-07-22 03:21:41 +02:00
Matthias Clasen
3bdd9fe50f sor3listmodel: Count the number of steps 2020-07-22 03:21:41 +02:00
Matthias Clasen
c6e6d682dc gtksor3listmodel: Track changed items precisely
Keep track of what items we swap, and emit
minimal items-changed signals based on that.
2020-07-22 03:21:41 +02:00
Matthias Clasen
a82f6d06ba sor3listmodel: Add profiler marks 2020-07-22 03:21:41 +02:00
Matthias Clasen
863c7e1a0a sor3listmodel: Add a :sorting boolean
This is convenient for quitting a test run
when the sorting is done.
2020-07-22 03:21:41 +02:00
Matthias Clasen
99a6c230f3 Add a custom model using quicksort 2020-07-22 03:21:41 +02:00
Matthias Clasen
e65dc063a8 Add another incremental sort model
This one uses a very simple iterative mergesort.
2020-07-22 03:21:41 +02:00
Benjamin Otte
5a058bf375 REMOVE: Copy current sort model to Tim4SortModel
This allows judging the impact of sort keys.
2020-07-22 03:21:41 +02:00
Benjamin Otte
6458305723 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 03:21:41 +02:00
Benjamin Otte
3326976669 multisorter: Implement GtkSortKeys 2020-07-22 03:21:41 +02:00
Benjamin Otte
26e7a0d050 treelistrowsorter: Implement GtkSortKeys 2020-07-22 03:21:41 +02:00
Benjamin Otte
20a6c2a2bd numericsorter: Implement GtkSortKeys 2020-07-22 03:21:41 +02:00
Benjamin Otte
61cdbebf6a stringsorter: Implement GtkSortKeys 2020-07-22 03:21:41 +02:00
Benjamin Otte
4aa811cde7 sortkeys: Add an equal sort keys
Compares every element as equal.
This is useful when sorters are in an invalid configuration.
2020-07-22 03:21:41 +02:00
Benjamin Otte
1544c90813 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 03:21:41 +02:00
Benjamin Otte
0941d39126 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 03:21:41 +02:00
Benjamin Otte
2da5a3600a REMOVE: Copy current sort model to Tim3SortModel
This is to compare with Tim2SortModel, which uses the different array
structure.
2020-07-22 03:21:41 +02:00
Benjamin Otte
5b406b07c6 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 03:21:41 +02:00
Benjamin Otte
76df9adfdc REMOVE: Copy current sort model to Tim2SortModel
This is the state of the model with incremental sorting support, before
doing some surgery that might slow down operations.
2020-07-22 03:21:41 +02:00
Benjamin Otte
da35f00405 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 03:21:41 +02:00
Benjamin Otte
1edd8a5d49 testsuite: Add exhaustive sortlistmodel test
This is basically a copy/paste from the filterlistmodel test, but
adapted for sorting.
2020-07-21 16:16:34 +02:00
Benjamin Otte
22295e1585 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-21 16:16:34 +02:00
Benjamin Otte
18545870e2 timsort: Add change tracking to gtk_tim_sort_step() 2020-07-21 16:16:34 +02:00
Benjamin Otte
ee6a5c9c02 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-21 16:16:34 +02:00
Benjamin Otte
5d35fb7f17 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-21 16:16:34 +02:00
Benjamin Otte
cc02085952 sortlistmodel: Make sorting incremental
This is just an experiment so far to see how long it takes to sort.
2020-07-21 16:16:34 +02:00
Benjamin Otte
25b8222db7 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-21 16:16:34 +02:00
Benjamin Otte
adc8728de0 REMOVE: Copy initial timsort model to Tim1SortModel
This allows a good comparison with Sor4ListModel, because all that
changes is the sort function.
2020-07-21 16:16:34 +02:00
Benjamin Otte
153c671d8a 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-21 16:16:34 +02:00
Benjamin Otte
8657930c64 Add a timsort() implementation 2020-07-21 16:16:34 +02:00
Benjamin Otte
30953269ee REMOVE: Copy current sort model to Sor4ListModel
More benchmarking.
2020-07-20 22:28:01 +02:00
Benjamin Otte
7007655d49 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-20 22:28:01 +02:00
Benjamin Otte
de69a3ffe9 REMOVE: Copy dumb sort model to Sor2ListModel
More benchmarking.
2020-07-20 22:28:01 +02:00
Benjamin Otte
35daf93ac0 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-20 22:28:01 +02:00
Benjamin Otte
2b987d03a3 REMOVE: Copy the old sortmodel to GtkGSeqSortModel
This allows benchmarking against it.
2020-07-20 22:28:01 +02:00
Benjamin Otte
9e525e06da demo: Add faster sorters
This is just the existing sorters, but without the overhead of GObject
properties.
2020-07-20 22:28:01 +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