Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[NARS1] [estess] Improve performance of quicksort (and in turn string… #86

Merged
merged 2 commits into from
Nov 10, 2017

Conversation

nars1
Copy link
Collaborator

@nars1 nars1 commented Nov 9, 2017

…pool garbage collection in YottaDB) by choosing a better pivot #85

The primary enhancement is to stpg_sort.c. Previously, the pivot was chosen as the median of the left, right and (left+right)/2 indices in the array. This is the normally recommended pivot rule for quicksort. But it was observed to give us a pivot that ended up almost in one corner of the array (i.e. too close to left or too close to right). This in turn caused quicksort to degenerate into an O(n^2) algorithm which showed its colors when a garbage collection had to run with thousands of items. The pivot is now chosen as the median of 9 equally-spaced numbers in the array spanning [left,right] indices. And this was observed to give us a pivot that ended up almost in the midpoint of the array (45% most of the time) thus enabling quicksort to run in O(nlogn). With these changes, a garbage collection that used to take 83 seconds took 0.5 seconds.

In addition the following changes were done.

a) Enhance the stringpool to contain > 4Gi items ("stp_array_size" variable)
b) stp_expand_array.c : Expand the "stp_array" array (that holds the items for garbage collection) exponentially instead of linearly.
c) lv_getslot.c : And handle an edge case (numElems == MAXINT4) introduced in a prior commit for #80

…pool garbage collection in YottaDB) by choosing a better pivot YottaDB#85

The primary enhancement is to stpg_sort.c. Previously, the pivot was chosen as the median of the left, right and (left+right)/2 indices in the array. This is the normally recommended pivot rule for quicksort. But it was observed to give us a pivot that ended up almost in one corner of the array (i.e. too close to left or too close to right). This in turn caused quicksort to degenerate into an O(n^2) algorithm which showed its colors when a garbage collection had to run with thousands of items. The pivot is now chosen as the median of 9 equally-spaced numbers in the array spanning [left,right] indices. And this was observed to give us a pivot that ended up almost in the midpoint of the array (45% most of the time) thus enabling quicksort to run in O(nlogn). With these changes, a garbage collection that used to take 83 seconds took 0.5 seconds.

In addition the following changes were done.

a) Enhance the stringpool to contain > 4Gi items ("stp_array_size" variable)
b) stp_expand_array.c : Expand the "stp_array" array (that holds the items for garbage collection) exponentially instead of linearly.
c) lv_getslot.c : And handle an edge case (numElems == MAXINT4) introduced in a prior commit for YottaDB#80
@nars1 nars1 self-assigned this Nov 9, 2017
@nars1 nars1 requested a review from estess November 9, 2017 22:10
@@ -141,7 +141,7 @@ lvTreeNode *lvtreenode_getslot(symval *sym)
numElems = p->numAlloc;
else
numElems = LV_NEWBLOCK_INIT_ALLOC;
lvtreenode_newblock(sym, (numElems > MAXINT4) ? MAXINT4 : (numElems * 2));
lvtreenode_newblock(sym, (numElems < MAXINT4) ? (numElems * 2) : MAXINT4);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to have an edge case problem. As soon as numElems is > (MAXINT4 / 2) but is < MAXINT4, this expression is either going to pass a negative value to lvtreenode_newblock() or a wrapped (too small) positive value. Not sure exactly which but think it is the former because numElems is unsigned which I think forces unsigned arithmetic. Yet the second parm to lvtreenode_newblock() is defined as being an int so I'm puzzled by the lack of a type sign conflict warning. Were the parm unsigned, there would still be an issue because again, values of numElems where (MAXINT4 / 2) < numElems < MAXINT4, the value of that expression will be larger than when numElems >= MAXINT4.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the catch. Now fixed.

a = stp_array;
stp_array = (mstr **) malloc(stp_array_size * SIZEOF(mstr *));
stp_array = (mstr **)malloc(stp_array_size * SIZEOF(mstr *));
longcpy((uchar_ptr_t)stp_array, (uchar_ptr_t)a, n * SIZEOF(mstr *));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Opportunity for longcopy->memcpy (optional)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done here and all other remaining usages.

…in lv_getslot YottaDB#80

These changes address review comments

1) All longcpy usages need to be replaced with memcpy. Since there were only a few remaining in the codebase, I replaced all of them.
2) lv_getslot.c : In function lvtreenode_getslot(), as soon as numElems is > (MAXINT4 / 2) but is < MAXINT4, we would end up passing a number that is > MAXINT4 but < MAXUINT4 to lvtreenode_newblock(). The latter expects a signed int though and so is going to see this as a negative number. Fix it so we never pass more than MAXINT4 to lvtreenode_newblock(). While in this module, fix a few assignments to be DEBUG_ONLY and move them to their proper scope and add a few missing asserts in lv_getslot() similar to the other two (lvtree_getslot() and lvtreenode_getslot()).
Copy link
Contributor

@estess estess left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@nars1 nars1 merged commit 49f59d9 into YottaDB:master Nov 10, 2017
@nars1 nars1 deleted the stpg_sort branch November 10, 2017 17:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants