Changeset 5c90890


Ignore:
Timestamp:
2018-07-12T08:54:12Z (5 months ago)
Author:
dequis <dx@…>
Branches:
master
Children:
c82e4ca
Parents:
b9d1fdc
git-author:
dequis <dx@…> (03-07-18 06:17:17)
git-committer:
dequis <dx@…> (12-07-18 08:54:12)
Message:

Stop using the irc->users linked list, use the hash table instead

irc_user_new() mentions that the reason this list is kept is for easy
iteration. Luckily, this is the future, and GHashTableIter exists now.

The main point of this is to get rid of the g_slist_insert_sorted() in
irc_user_set_nick() which is a particularly slow part of loading large
user lists, and scales poorly

In a test with discord, the GUILD_SYNC event is now 4 times faster, on
top of the improvements of the other bee_user hash tables patch.
Combining both patches it went from 136 to 6 seconds for 50k members.

Files:
7 edited

Legend:

Unmodified
Added
Removed
  • irc.c

    rb9d1fdc r5c90890  
    242242{
    243243        GSList *l;
     244        GHashTableIter iter;
     245        gpointer itervalue;
    244246
    245247        irc->status |= USTATUS_SHUTDOWN;
     
    271273        bee_free(irc->b);
    272274
    273         while (irc->users) {
    274                 irc_user_free(irc, (irc_user_t *) irc->users->data);
     275        g_hash_table_iter_init(&iter, irc->nick_user_hash);
     276
     277        while (g_hash_table_iter_next(&iter, NULL, &itervalue)) {
     278                g_hash_table_iter_remove(&iter);
     279                irc_user_free(irc, (irc_user_t *) itervalue);
    275280        }
    276281
     
    292297        irc->fd = -1;
    293298
    294         g_hash_table_foreach_remove(irc->nick_user_hash, irc_free_hashkey, NULL);
    295299        g_hash_table_destroy(irc->nick_user_hash);
    296300
  • irc.h

    rb9d1fdc r5c90890  
    102102        GSList *file_transfers;
    103103
    104         GSList *users, *channels;
     104        GSList *users G_GNUC_DEPRECATED;
     105        GSList *channels;
    105106        struct irc_channel *default_channel;
    106107        GHashTable *nick_user_hash;
  • irc_channel.c

    rb9d1fdc r5c90890  
    121121{
    122122        irc_t *irc;
    123         GSList *l;
     123        GHashTableIter iter;
     124        gpointer itervalue;
    124125
    125126        if (ic == NULL) {
     
    146147        }
    147148
    148         for (l = irc->users; l; l = l->next) {
    149                 irc_user_t *iu = l->data;
     149        g_hash_table_iter_init(&iter, irc->nick_user_hash);
     150
     151        while (g_hash_table_iter_next(&iter, NULL, &itervalue)) {
     152                irc_user_t *iu = itervalue;
    150153
    151154                if (iu->last_channel == ic) {
     
    729732                }
    730733        } else if (g_strcasecmp(set_getstr(&irc->b->set, "default_target"), "last") == 0 &&
    731                    ic->last_target && g_slist_find(irc->users, ic->last_target)) {
     734                   ic->last_target && g_hash_table_contains(irc->nick_user_hash, ic->last_target->key)) {
    732735                iu = ic->last_target;
    733736        } else {
  • irc_commands.c

    rb9d1fdc r5c90890  
    449449
    450450        if (!channel || *channel == '0' || *channel == '*' || !*channel) {
    451                 irc_send_who(irc, irc->users, "**");
     451                GList *all_users = g_hash_table_get_values(irc->nick_user_hash);
     452                irc_send_who(irc, (GSList *) all_users, "**");
     453                g_list_free(all_users);
    452454        } else if ((ic = irc_channel_by_name(irc, channel))) {
    453455                irc_send_who(irc, ic->users, channel);
  • irc_im.c

    rb9d1fdc r5c90890  
    181181        }
    182182        if (iu == NULL) {
    183                 for (l = irc->users; l; l = l->next) {
    184                         iu = l->data;
     183                GHashTableIter iter;
     184                gpointer itervalue;
     185                g_hash_table_iter_init(&iter, irc->nick_user_hash);
     186
     187                while (g_hash_table_iter_next(&iter, NULL, &itervalue)) {
     188                        iu = itervalue;
    185189                        if (iu->bu) {
    186                                 bee_irc_channel_update(irc, ic, l->data);
     190                                bee_irc_channel_update(irc, ic, iu);
    187191                        }
    188192                }
  • irc_user.c

    rb9d1fdc r5c90890  
    3737        iu->key = g_strdup(nick);
    3838        nick_lc(irc, iu->key);
    39         /* Using the hash table for speed and irc->users for easy iteration
    40            through the list (since the GLib API doesn't have anything sane
    41            for that.) */
    4239        g_hash_table_insert(irc->nick_user_hash, iu->key, iu);
    43         irc->users = g_slist_insert_sorted(irc->users, iu, irc_user_cmp);
    4440
    4541        return iu;
     
    8783        irc_user_quit(iu, msg);
    8884
    89         irc->users = g_slist_remove(irc->users, iu);
    9085        g_hash_table_remove(irc->nick_user_hash, iu->key);
    9186
     
    148143        }
    149144
    150         irc->users = g_slist_remove(irc->users, iu);
    151145        g_hash_table_remove(irc->nick_user_hash, iu->key);
    152146
     
    175169        iu->key = g_strdup(key);
    176170        g_hash_table_insert(irc->nick_user_hash, iu->key, iu);
    177         irc->users = g_slist_insert_sorted(irc->users, iu, irc_user_cmp);
    178171
    179172        if (iu == irc->user) {
  • root_commands.c

    rb9d1fdc r5c90890  
    773773        bu->ic->acc->prpl->remove_buddy(bu->ic, bu->handle, NULL);
    774774        nick_del(bu);
    775         if (g_slist_find(irc->users, iu)) {
     775        if (g_hash_table_contains(irc->nick_user_hash, iu->key)) {
    776776                bee_user_free(irc->b, bu);
    777777        }
     
    10331033{
    10341034        int online = 0, away = 0, offline = 0, ismatch = 0;
    1035         GSList *l;
     1035        GList *l, *users;
    10361036        GRegex *regex = NULL;
    10371037        GError *error = NULL;
     
    10741074        }
    10751075
    1076         for (l = irc->users; l; l = l->next) {
     1076        users = g_hash_table_get_values(irc->nick_user_hash);
     1077        users = g_list_sort(users, irc_user_cmp);
     1078
     1079        for (l = users; l; l = l->next) {
    10771080                irc_user_t *iu = l->data;
    10781081                bee_user_t *bu = iu->bu;
     
    11191122                }
    11201123        }
     1124
     1125        g_list_free(users);
    11211126
    11221127        irc_rootmsg(irc, "%d buddies (%d available, %d away, %d offline)", n_online + n_away + n_offline, n_online,
Note: See TracChangeset for help on using the changeset viewer.