Mostly avoid an expensive multi-map iteration pattern
authorSimon McVittie <simon.mcvittie@collabora.co.uk>
Fri, 8 Mar 2013 13:55:29 +0000 (13:55 +0000)
committerSimon McVittie <simon.mcvittie@collabora.co.uk>
Fri, 8 Mar 2013 13:56:05 +0000 (13:56 +0000)
commit3ead592946f3b9e9b41196c193228047af9b0834
treee88fda25e9db44bc5d6db43647ab4d56ac227ee0
parent1e758bd6f27e260aa43cf7001d595f5f36e5bb93
Mostly avoid an expensive multi-map iteration pattern

If you have a MultiMap with, say, 100 keys each with 1 value, and you
iterate over it like this (pseudocode):

    for key in keys():
        values = get(key)
        for value in values:
            do something(key, value)

then you have constructed one GObject for the result of keys(), and
100 GObjects for the results of get() (because it returns a read-only
view). If you iterate it like this:

    iter = map_iterator()
    while iter.next():
        do something(iter.key(), iter.value())

there's only one extraneous GObject, the iterator itself.

When there are thousands of contacts, as in add-contacts-stress-test,
this really starts to matter.

This patch doesn't fix every use of get_keys() - some of them do
non-trivial work per key as well as per value, making it awkward to
convert to map_iterator() - but it's a start. It cuts 'user' CPU time
for IndividualAggregator quiescence for an e-d-s Google account with
2049 contacts (reading from cache) by around 3%.

Bug: https://bugzilla.gnome.org/show_bug.cgi?id=682903
Reviewed-by: Philip Withnall <philip@tecnocode.co.uk>
[note added to HACKING as per Philip's review]
Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
HACKING
backends/eds/lib/edsf-persona.vala
backends/key-file/kf-persona.vala
backends/telepathy/lib/tpf-persona-store-cache.vala
backends/telepathy/lib/tpf-persona-store.vala
folks/abstract-field-details.vala
folks/individual-aggregator.vala
folks/individual.vala