commit 5ccc65eba1807c12e603c4bdf6590d91cc52499a Author: Steve Grubb Date: Sat Sep 2 09:58:46 2023 -0400 Speed up aureport --summary reports diff --git a/src/ausearch-string.c b/src/ausearch-string.c index 8dbec53..484c232 100644 --- a/src/ausearch-string.c +++ b/src/ausearch-string.c @@ -1,27 +1,28 @@ /* -* ausearch-string.c - Minimal linked list library for strings -* Copyright (c) 2005,2008,2014 Red Hat Inc., Durham, North Carolina. -* All Rights Reserved. -* -* This software may be freely redistributed and/or modified under the -* terms of the GNU General Public License as published by the Free -* Software Foundation; either version 2, or (at your option) any -* later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; see the file COPYING. If not, write to the -* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor -* Boston, MA 02110-1335, USA. -* -* Authors: -* Steve Grubb -*/ - + * ausearch-string.c - Minimal linked list library for strings + * Copyright (c) 2005,2008,2014,2023 Red Hat Inc. + * All Rights Reserved. + * + * This software may be freely redistributed and/or modified under the + * terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1335, USA. + * + * Authors: + * Steve Grubb + */ + +#pragma GCC optimize("O3,inline") #include "ausearch-string.h" #include #include @@ -31,28 +32,10 @@ void slist_create(slist *l) { l->head = NULL; l->cur = NULL; + l->last = NULL; l->cnt = 0; } -void slist_last(slist *l) -{ - register snode* cur; - - if (l->head == NULL) - return; - - // Try using cur so that we don't have to start at beginnning - if (l->cur) - cur = l->cur; - else - cur = l->head; - - // Loop until no next value - while (cur->next) - cur = cur->next; - l->cur = cur; -} - snode *slist_next(slist *l) { if (l->cur == NULL) @@ -80,14 +63,14 @@ void slist_append(slist *l, snode *node) newnode->hits = node->hits; newnode->next = NULL; - // Make sure cursor is at the end - slist_last(l); - - // if we are at top, fix this up - if (l->head == NULL) + // if the top is empty, add it there + if (l->head == NULL) { l->head = newnode; - else // Otherwise add pointer to newnode - l->cur->next = newnode; + l->last = newnode; + } else { // Otherwise put at the end + l->last->next = newnode; + l->last = newnode; + } // make newnode current l->cur = newnode; @@ -109,25 +92,25 @@ void slist_clear(slist* l) } l->head = NULL; l->cur = NULL; + l->last = NULL; l->cnt = 0; } -/* This function dominates the timing of aureport. Needs to be more efficient */ int slist_add_if_uniq(slist *l, const char *str) { snode sn; - register snode *cur; + register snode *cur; if (str == NULL) return -1; - cur = l->head; + cur = l->head; while (cur) { if (strcmp(str, cur->str) == 0) { cur->hits++; l->cur = cur; return 0; - } else + } else cur = cur->next; } @@ -140,7 +123,7 @@ int slist_add_if_uniq(slist *l, const char *str) } // If lprev would be NULL, use l->head -static void swap_nodes(snode *lprev, snode *left, snode *right) +static inline void swap_nodes(snode *lprev, snode *left, snode *right) { snode *t = right->next; if (lprev) @@ -150,17 +133,13 @@ static void swap_nodes(snode *lprev, snode *left, snode *right) } // This will sort the list from most hits to least -void slist_sort_by_hits(slist *l) +static void old_sort_by_hits(slist *l) { register snode* cur, *prev; - - if (l->cnt <= 1) - return; - prev = cur = l->head; while (cur && cur->next) { - /* If the next node is bigger */ + // If the next node is bigger if (cur->hits < cur->next->hits) { if (cur == l->head) { // Update the actual list head @@ -180,3 +159,82 @@ void slist_sort_by_hits(slist *l) l->cur = l->head; } +// Merge two sorted lists +static snode* slist_merge_sorted_lists(snode *a, snode *b) +{ + snode dummy; + snode *tail = &dummy; + dummy.next = NULL; + + while (a && b) { + if (a->hits >= b->hits) { + tail->next = a; + a = a->next; + } else { + tail->next = b; + b = b->next; + } + tail = tail->next; + } + tail->next = a ? a : b; + return dummy.next; +} + +// Split the list into two halves +static void slist_split_list(snode *head, snode **front, snode **back) +{ + snode *fast, *slow; + slow = head; + fast = head->next; + + while (fast) { + fast = fast->next; + if (fast) { + slow = slow->next; + fast = fast->next; + } + } + + *front = head; + *back = slow->next; + slow->next = NULL; +} + +// Merge sort for linked list +static void slist_merge_sort(snode **head_ref) +{ + snode *head = *head_ref; + snode *a, *b; + + if (!head || !head->next) + return; + + slist_split_list(head, &a, &b); + + slist_merge_sort(&a); + slist_merge_sort(&b); + + *head_ref = slist_merge_sorted_lists(a, b); +} + +// This function dominates aureport --summary --kind output +void slist_sort_by_hits(slist *l) +{ + if (l->cnt <= 1) + return; + + // If the list is small, use old algorithm because + // the new one has some overhead that makes it slower + // until the list is big enough that the inefficiencies + // of the old algorithm cause slowness. The value chosen + // below is just a guess. At 100, the old algorithm is + // faster. At 1000, the new one is 5x faster. + if (l->cnt < 200) + return old_sort_by_hits(l); + + slist_merge_sort(&l->head); + + // End with cur pointing at first record + l->cur = l->head; +} + diff --git a/src/ausearch-string.h b/src/ausearch-string.h index 1cfc4a6..5fcf1ee 100644 --- a/src/ausearch-string.h +++ b/src/ausearch-string.h @@ -1,6 +1,6 @@ /* * ausearch-string.h - Header file for ausearch-string.c -* Copyright (c) 2005,2008 Red Hat Inc., Durham, North Carolina. +* Copyright (c) 2005,2008,2023 Red Hat Inc. * All Rights Reserved. * * This software may be freely redistributed and/or modified under the @@ -15,7 +15,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; see the file COPYING. If not, write to the -* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor +* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor * Boston, MA 02110-1335, USA. * * Authors: @@ -41,6 +41,7 @@ typedef struct _snode{ typedef struct { snode *head; // List head snode *cur; // Pointer to current node + snode *last; // Pointer to current node unsigned int cnt; // How many items in this list } slist;