On 05.09.2015 02:53, Branko Čibej wrote: > On 04.09.2015 21:17, stef...@apache.org wrote: >> Author: stefan2 >> Date: Fri Sep 4 19:17:44 2015 >> New Revision: 1701317 >> >> URL: http://svn.apache.org/r1701317 >> Log: >> Finally, make svn_ra_svn__list_t actually a fully typed, ra_svn-specific >> object. Update the creation functions; everything else already "just fits". > How is this code different from using APR arrays, except that the latter > needs a typecast on array item access? As far as I can see, you've > completely duplicated the APR array allocation strategy, including using > two allocations to create the array. > > The only significant difference is that capacity is being tracked > outside the svn_ra_svn__list_t structure during the construction of the > list. > > Call me dense ... but can you please explain how exactly is this > better/faster than using APR arrays? (I'm not going to mention 'safer' > because it clearly isn't.) Code like this that is apparently meant be an > optimisation of something(?) really should have a bit of an explanatory > comment, IMO.
I played around with the apr_array_make implementation a bit and did some performance measurements with small array allocation and usage, with the following pattern: * in 60% of cases, the array does not get resized * in 30% it gets resized once * in 10% it gets resized twice If I change apr_array_make to allocate the initial number of elements in the same block as the array header, I get a 15% speedup on this test case, compared to the default implementation. If I change it further to never set the element values to 0 in apr_array_make, I get an additional 10% speedup, for a total of 23%. So I'm guessing this is the number you were actually seeing. We can certainly change APR to get that extra 15% in, but we can't remove the memset(0) because it's part of the existing API semantics. However we can add (in apr-1.6 and 2.0) a new constructor, e.g. apr_array_make_uninitialized, that would not clear the element values. This wouldn't help with apr_array_push, but note that there's already a private function called apr_array_push_noclear that's used with apr_table_t Obviously I'd much rather make these enhancements in APR than have yet another custom allocation hack in Subversion. -- Brane
#include <stdlib.h> #include "apr_pools.h" #include "apr_tables.h" static void test_array_alloc(apr_pool_t *pool) { int i, j, k; for (i = 0; i < 50000; ++i) { apr_pool_clear(pool); for (j = 0; j < 10000; ++j) { const int nelts = ((j % 10 == 0) ? 11 : (j % 10 < 7) ? 3 : 7); apr_array_header_t *a = apr_array_make(pool, 4, 1); for (k = 0; k < nelts; ++k) APR_ARRAY_PUSH(a, char) = '\0'; } } } int main(void) { apr_pool_t *pool = NULL; if (apr_initialize()) exit(1); atexit(apr_terminate); apr_pool_create(&pool, NULL); test_array_alloc(pool); return 0; }