Skip to content

Commit 2193de0

Browse files
committed
Faster sorting algo
1 parent ade7a41 commit 2193de0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+757
-437
lines changed

UPGRADING

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ PHP X.Y UPGRADE NOTES
5656
output buffer is created in an output buffer handler.
5757
. Added zend_memnstr_ex, which is based on string matching sunday algo.
5858
. Added zend_memnrstr, zend_memnrstr_ex.
59+
. Added hybrid sorting algo zend_sort for better performance.
60+
. Added stable sorting algo zend_insert_sort.
5961

6062
- DBA
6163
. dba_delete() now returns false if the key was not found for the inifile

Zend/Makefile.am

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ libZend_la_SOURCES=\
1313
zend_vm_opcodes.c zend_opcode.c zend_operators.c zend_ptr_stack.c zend_stack.c \
1414
zend_variables.c zend.c zend_API.c zend_extensions.c zend_hash.c \
1515
zend_list.c zend_indent.c zend_builtin_functions.c zend_sprintf.c \
16-
zend_ini.c zend_qsort.c zend_objects.c zend_object_handlers.c \
16+
zend_ini.c zend_sort.c zend_objects.c zend_object_handlers.c \
1717
zend_objects_API.c zend_ts_hash.c zend_stream.c \
1818
zend_default_classes.c \
1919
zend_iterators.c zend_interfaces.c zend_exceptions.c \

Zend/tests/methods-on-non-objects-usort.phpt

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,21 +23,16 @@ int(4096)
2323
string(43) "Call to a member function compare() on null"
2424
int(4096)
2525
string(43) "Call to a member function compare() on null"
26-
int(4096)
27-
string(43) "Call to a member function compare() on null"
28-
int(4096)
29-
string(43) "Call to a member function compare() on null"
3026
array(5) {
3127
[0]=>
32-
int(-1)
28+
int(1)
3329
[1]=>
34-
int(3)
30+
int(4)
3531
[2]=>
3632
int(2)
3733
[3]=>
38-
int(4)
34+
int(3)
3935
[4]=>
40-
int(1)
36+
int(-1)
4137
}
4238
Alive
43-

Zend/zend_API.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1715,7 +1715,7 @@ static int zend_startup_module_zval(zval *zv) /* {{{ */
17151715
}
17161716
/* }}} */
17171717

1718-
static void zend_sort_modules(void *base, size_t count, size_t siz, compare_func_t compare) /* {{{ */
1718+
static void zend_sort_modules(void *base, size_t count, size_t siz, compare_func_t compare, swap_func_t swp) /* {{{ */
17191719
{
17201720
Bucket *b1 = base;
17211721
Bucket *b2;
@@ -1821,7 +1821,7 @@ ZEND_API void zend_collect_module_handlers(void) /* {{{ */
18211821

18221822
ZEND_API int zend_startup_modules(void) /* {{{ */
18231823
{
1824-
zend_hash_sort(&module_registry, zend_sort_modules, NULL, 0);
1824+
zend_hash_sort_ex(&module_registry, zend_sort_modules, NULL, 0);
18251825
zend_hash_apply(&module_registry, zend_startup_module_zval);
18261826
return SUCCESS;
18271827
}

Zend/zend_hash.c

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1663,8 +1663,47 @@ ZEND_API zval *zend_hash_get_current_data_ex(HashTable *ht, HashPosition *pos)
16631663
}
16641664
}
16651665

1666-
ZEND_API int zend_hash_sort(HashTable *ht, sort_func_t sort_func,
1667-
compare_func_t compar, zend_bool renumber)
1666+
ZEND_API void zend_hash_bucket_swap(Bucket *p, Bucket *q) {
1667+
zval val;
1668+
zend_ulong h;
1669+
zend_string *key;
1670+
1671+
ZVAL_COPY_VALUE(&val, &p->val);
1672+
h = p->h;
1673+
key = p->key;
1674+
1675+
ZVAL_COPY_VALUE(&p->val, &q->val);
1676+
p->h = q->h;
1677+
p->key = q->key;
1678+
1679+
ZVAL_COPY_VALUE(&q->val, &val);
1680+
q->h = h;
1681+
q->key = key;
1682+
}
1683+
1684+
ZEND_API void zend_hash_bucket_renum_swap(Bucket *p, Bucket *q) {
1685+
zval val;
1686+
1687+
ZVAL_COPY_VALUE(&val, &p->val);
1688+
ZVAL_COPY_VALUE(&p->val, &q->val);
1689+
ZVAL_COPY_VALUE(&q->val, &val);
1690+
}
1691+
1692+
ZEND_API void zend_hash_bucket_packed_swap(Bucket *p, Bucket *q) {
1693+
zval val;
1694+
zend_ulong h;
1695+
1696+
ZVAL_COPY_VALUE(&val, &p->val);
1697+
h = p->h;
1698+
1699+
ZVAL_COPY_VALUE(&p->val, &q->val);
1700+
p->h = q->h;
1701+
1702+
ZVAL_COPY_VALUE(&q->val, &val);
1703+
q->h = h;
1704+
}
1705+
1706+
ZEND_API int zend_hash_sort_ex(HashTable *ht, sort_func_t sort, compare_func_t compar, zend_bool renumber)
16681707
{
16691708
Bucket *p;
16701709
uint32_t i, j;
@@ -1688,7 +1727,9 @@ ZEND_API int zend_hash_sort(HashTable *ht, sort_func_t sort_func,
16881727
}
16891728
}
16901729

1691-
(*sort_func)((void *) ht->arData, i, sizeof(Bucket), compar);
1730+
sort((void *)ht->arData, i, sizeof(Bucket), compar,
1731+
(swap_func_t)(renumber? zend_hash_bucket_renum_swap :
1732+
((ht->u.flags & HASH_FLAG_PACKED) ? zend_hash_bucket_packed_swap : zend_hash_bucket_swap)));
16921733

16931734
HANDLE_BLOCK_INTERRUPTIONS();
16941735
ht->nNumUsed = i;

Zend/zend_hash.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,13 +201,19 @@ typedef struct _HashPointer {
201201
ZEND_API void zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor);
202202
ZEND_API void _zend_hash_merge(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, zend_bool overwrite ZEND_FILE_LINE_DC);
203203
ZEND_API void zend_hash_merge_ex(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, merge_checker_func_t pMergeSource, void *pParam);
204-
ZEND_API int zend_hash_sort(HashTable *ht, sort_func_t sort_func, compare_func_t compare_func, zend_bool renumber);
204+
ZEND_API void zend_hash_bucket_swap(Bucket *p, Bucket *q);
205+
ZEND_API void zend_hash_bucket_renum_swap(Bucket *p, Bucket *q);
206+
ZEND_API void zend_hash_bucket_packed_swap(Bucket *p, Bucket *q);
207+
ZEND_API int zend_hash_sort_ex(HashTable *ht, sort_func_t sort_func, compare_func_t compare_func, zend_bool renumber);
205208
ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t compar, zend_bool ordered);
206209
ZEND_API zval *zend_hash_minmax(const HashTable *ht, compare_func_t compar, uint32_t flag);
207210

208211
#define zend_hash_merge(target, source, pCopyConstructor, overwrite) \
209212
_zend_hash_merge(target, source, pCopyConstructor, overwrite ZEND_FILE_LINE_CC)
210213

214+
#define zend_hash_sort(ht, compare_func, renumber) \
215+
zend_hash_sort_ex(ht, zend_sort, compare_func, renumber)
216+
211217
#define zend_hash_num_elements(ht) \
212218
(ht)->nNumOfElements
213219

Zend/zend_ini.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
/* $Id$ */
2020

2121
#include "zend.h"
22-
#include "zend_qsort.h"
22+
#include "zend_sort.h"
2323
#include "zend_API.h"
2424
#include "zend_ini.h"
2525
#include "zend_alloc.h"
@@ -202,7 +202,7 @@ static int ini_key_compare(const void *a, const void *b) /* {{{ */
202202

203203
ZEND_API void zend_ini_sort_entries(void) /* {{{ */
204204
{
205-
zend_hash_sort(EG(ini_directives), zend_qsort, ini_key_compare, 0);
205+
zend_hash_sort(EG(ini_directives), ini_key_compare, 0);
206206
}
207207
/* }}} */
208208

Zend/zend_llist.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222
#include "zend.h"
2323
#include "zend_llist.h"
24-
#include "zend_qsort.h"
24+
#include "zend_sort.h"
2525

2626
ZEND_API void zend_llist_init(zend_llist *l, size_t size, llist_dtor_func_t dtor, unsigned char persistent)
2727
{
@@ -33,7 +33,6 @@ ZEND_API void zend_llist_init(zend_llist *l, size_t size, llist_dtor_func_t dtor
3333
l->persistent = persistent;
3434
}
3535

36-
3736
ZEND_API void zend_llist_add_element(zend_llist *l, void *element)
3837
{
3938
zend_llist_element *tmp = pemalloc(sizeof(zend_llist_element)+l->size-1, l->persistent);
@@ -186,6 +185,14 @@ ZEND_API void zend_llist_apply(zend_llist *l, llist_apply_func_t func)
186185
}
187186
}
188187

188+
static void zend_llist_swap(zend_llist_element **p, zend_llist_element **q)
189+
{
190+
zend_llist_element *t;
191+
t = *p;
192+
*p = *q;
193+
*q = t;
194+
}
195+
189196
ZEND_API void zend_llist_sort(zend_llist *l, llist_compare_func_t comp_func)
190197
{
191198
size_t i;
@@ -205,7 +212,8 @@ ZEND_API void zend_llist_sort(zend_llist *l, llist_compare_func_t comp_func)
205212
*ptr++ = element;
206213
}
207214

208-
zend_qsort(elements, l->count, sizeof(zend_llist_element *), (compare_func_t) comp_func);
215+
zend_sort(elements, l->count, sizeof(zend_llist_element *),
216+
(compare_func_t) comp_func, (swap_func_t) zend_llist_swap);
209217

210218
l->head = elements[0];
211219
elements[0]->prev = NULL;

Zend/zend_qsort.c

Lines changed: 0 additions & 133 deletions
This file was deleted.

0 commit comments

Comments
 (0)