Skip to content

Commit

Permalink
Use the stock qsort implementation from libc
Browse files Browse the repository at this point in the history
to save the code and stack space

Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
Change-Id: Ifb00e71e97cf2b4045845ed4ed92c7d21f87db67
  • Loading branch information
xiaoxiang781216 committed Apr 21, 2021
1 parent 2830065 commit deabbe8
Show file tree
Hide file tree
Showing 2 changed files with 5 additions and 249 deletions.
237 changes: 5 additions & 232 deletions dmalloc_tab.c
Original file line number Diff line number Diff line change
Expand Up @@ -225,235 +225,7 @@ static int entry_cmp(const void *entry1_p, const void *entry2_p)
}

/*
* static void swap_bytes
*
* Swap the values between two items of a specified size.
*
* ARGUMENTS:
*
* item1_p -> Pointer to the first item.
*
* item2_p -> Pointer to the first item.
*
* ele_size -> Size of the two items.
*/
static void swap_bytes(unsigned char *item1_p, unsigned char *item2_p,
int ele_size)
{
unsigned char char_temp;

for (; ele_size > 0; ele_size--) {
char_temp = *item1_p;
*item1_p = *item2_p;
*item2_p = char_temp;
item1_p++;
item2_p++;
}
}

/*
* static void insert_sort
*
* Do an insertion sort which is faster for small numbers of items and
* better if the items are already sorted.
*
* ARGUMENTS:
*
* first_p <-> Start of the list that we are splitting.
*
* last_p <-> Last entry in the list that we are splitting.
*
* holder_p <-> Location of hold area we can store an entry.
*
* ele_size -> Size of the each element in the list.
*/
static void insert_sort(unsigned char *first_p, unsigned char *last_p,
unsigned char *holder_p,
const unsigned int ele_size)
{
unsigned char *inner_p, *outer_p;

for (outer_p = first_p + ele_size; outer_p <= last_p; ) {

/* look for the place to insert the entry */
for (inner_p = outer_p - ele_size;
inner_p >= first_p && entry_cmp(outer_p, inner_p) < 0;
inner_p -= ele_size) {
}
inner_p += ele_size;

/* do we need to insert the entry in? */
if (outer_p != inner_p) {
/*
* Now we shift the entry down into its place in the already
* sorted list.
*/
memcpy(holder_p, outer_p, ele_size);
memmove(inner_p + ele_size, inner_p, outer_p - inner_p);
memcpy(inner_p, holder_p, ele_size);
}

outer_p += ele_size;
}
}

/*
* static void split
*
* This sorts an array of longs via the quick sort algorithm (it's pretty quick)
*
* ARGUMENTS:
*
* first_p -> Start of the list that we are splitting.
*
* last_p -> Last entry in the list that we are splitting.
*
* ele_size -> Size of the each element in the list.
*/
static void split(unsigned char *first_p, unsigned char *last_p,
const unsigned int ele_size)
{
unsigned char *left_p, *right_p, *pivot_p, *left_last_p, *right_first_p;
unsigned char *firsts[MAX_QSORT_SPLITS], *lasts[MAX_QSORT_SPLITS];
mem_table_t pivot;
unsigned int width, split_c = 0, min_qsort_size, size1, size2;

min_qsort_size = MAX_QSORT_PARTITION * ele_size;

while (1) {

/* find the left, right, and mid point */
left_p = first_p;
right_p = last_p;
/* is there a faster way to find this? */
width = (last_p - first_p) / ele_size;
pivot_p = first_p + ele_size * (width >> 1);

/*
* Find which of the left, middle, and right elements is the
* median (Knuth vol3 p123).
*/
if (entry_cmp(first_p, pivot_p) > 0) {
swap_bytes(first_p, pivot_p, ele_size);
}
if (entry_cmp(pivot_p, last_p) > 0) {
swap_bytes(pivot_p, last_p, ele_size);
if (entry_cmp(first_p, pivot_p) > 0) {
swap_bytes(first_p, pivot_p, ele_size);
}
}

/*
* save our pivot so we don't have to worry about hitting and
* swapping it elsewhere while we iterate across the list below.
*/
memcpy(&pivot, pivot_p, ele_size);

do {

/* shift the left side up until we reach the pivot value */
while (entry_cmp(left_p, &pivot) < 0) {
left_p += ele_size;
}
/* shift the right side down until we reach the pivot value */
while (entry_cmp(&pivot, right_p) < 0) {
right_p -= ele_size;
}

/* if we met in the middle then we are done */
if (left_p == right_p) {
left_p += ele_size;
right_p -= ele_size;
break;
}
else if (left_p < right_p) {
/*
* swap the left and right since they both were on the wrong
* size of the pivot and continue
*/
swap_bytes(left_p, right_p, ele_size);
left_p += ele_size;
right_p -= ele_size;
}
} while (left_p <= right_p);

/* Rename variables to make more sense. This will get optimized out. */
right_first_p = left_p;
left_last_p = right_p;

/* determine the size of the left and right hand parts */
size1 = left_last_p - first_p;
size2 = last_p - right_first_p;

/* is the 1st half small enough to just insert-sort? */
if (size1 < min_qsort_size) {

/* use the pivot as our temporary space */
insert_sort(first_p, left_last_p, (unsigned char *)&pivot, ele_size);

/* is the 2nd part small as well? */
if (size2 < min_qsort_size) {

/* use the pivot as our temporary space */
insert_sort(right_first_p, last_p, (unsigned char *)&pivot, ele_size);

/* pop a partition off our stack */
if (split_c == 0) {
/* we are done */
return;
}
split_c--;
first_p = firsts[split_c];
last_p = lasts[split_c];
}
else {
/* we can just handle the right side immediately */
first_p = right_first_p;
/* last_p = last_p */
}
}
else if (size2 < min_qsort_size) {

/* use the pivot as our temporary space */
insert_sort(right_first_p, last_p, (unsigned char *)&pivot, ele_size);

/* we can just handle the left side immediately */
/* first_p = first_p */
last_p = left_last_p;
}
else {
/*
* neither partition is small, we'll have to push the larger one
* of them on the stack
*/
if (split_c >= MAX_QSORT_SPLITS) {
/* sanity check here -- we should never get here */
abort();
}
if (size1 > size2) {
/* push the left partition on the stack */
firsts[split_c] = first_p;
lasts[split_c] = left_last_p;
split_c++;
/* continue handling the right side */
first_p = right_first_p;
/* last_p = last_p */
}
else {
/* push the right partition on the stack */
firsts[split_c] = right_first_p;
lasts[split_c] = last_p;
split_c++;
/* continue handling the left side */
/* first_p = first_p */
last_p = left_last_p;
}
}
}
}

/*
* static void log_slot
* static void log_entry
*
* Log the information from the memory slot to the logfile.
*
Expand Down Expand Up @@ -672,9 +444,10 @@ void _dmalloc_table_log_info(mem_table_t *mem_table, const int log_n,
}

/* sort the entries by their total-size */
split((unsigned char *)mem_table->mt_entries,
(unsigned char *)(mem_table->mt_bounds_p - 1),
sizeof(*mem_table->mt_entries));
qsort(mem_table->mt_entries,
mem_table->mt_entry_n,
sizeof(*mem_table->mt_entries),
entry_cmp);

/* display the column headers */
if (in_use_column_b) {
Expand Down
17 changes: 0 additions & 17 deletions dmalloc_tab_loc.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,6 @@

#include "conf.h"

/*
* Maximum number of splits. This should mean that these routines can
* handle at least 2^128 different values (that's _quite_ a few). And
* then you can always increase the value.
*/
#define MAX_QSORT_SPLITS 128

/*
* Maximum number of entries that must be in list for it to be
* partitioned. If there are fewer elements then just do our
* insertion sort.
*/
#define MAX_QSORT_PARTITION 8

/* comparison function */
typedef int (*compare_t)(const void *element1_p, const void *element2_p);

/*
* void HASH_MIX
*
Expand Down

0 comments on commit deabbe8

Please sign in to comment.