diff options
author | Keith Packard <keithp@keithp.com> | 2016-11-16 14:00:38 -0800 |
---|---|---|
committer | Keith Packard <keithp@keithp.com> | 2016-11-17 22:18:39 -0800 |
commit | d68d89a2b8d2c1ebde355171f99e5205dbd0ea43 (patch) | |
tree | 4215744176db590fb2e4de60e37155daf79e5cee | |
parent | 6e4264b6dba38e83d265a175f0f5cc8573dcfb26 (diff) |
altos/lisp: binary search for chunk in collect
Speeds up collect a bit
Signed-off-by: Keith Packard <keithp@keithp.com>
-rw-r--r-- | src/lisp/ao_lisp_mem.c | 69 |
1 files changed, 44 insertions, 25 deletions
diff --git a/src/lisp/ao_lisp_mem.c b/src/lisp/ao_lisp_mem.c index b681dbd5..53ebf757 100644 --- a/src/lisp/ao_lisp_mem.c +++ b/src/lisp/ao_lisp_mem.c @@ -314,36 +314,55 @@ static int chunk_busy; static void note_chunk(uint16_t addr, uint16_t size) { - int i; + int l, r; - if (addr < chunk_low || chunk_high < addr) + if (addr < chunk_low || chunk_high <= addr) return; - for (i = 0; i < chunk_busy; i++) { - if (ao_lisp_chunk[i].size && ao_lisp_chunk[i].old_addr == addr) { -#if DBG_MEM - if (ao_lisp_chunk[i].size != size) - ao_lisp_abort(); -#endif - return; - } - if (ao_lisp_chunk[i].old_addr > addr) { - int end = min(AO_LISP_NCHUNK, chunk_busy + 1); - memmove(&ao_lisp_chunk[i+1], - &ao_lisp_chunk[i], - (end - (i+1)) * sizeof (struct ao_lisp_chunk)); - break; - } - } - if (i < AO_LISP_NCHUNK) { - ao_lisp_chunk[i].old_addr = addr; - ao_lisp_chunk[i].size = size; - if (chunk_busy < AO_LISP_NCHUNK) - chunk_busy++; + /* Binary search for the location */ + l = 0; + r = chunk_busy - 1; + while (l <= r) { + int m = (l + r) >> 1; + if (ao_lisp_chunk[m].old_addr < addr) + l = m + 1; else - chunk_high = ao_lisp_chunk[AO_LISP_NCHUNK-1].old_addr + - ao_lisp_chunk[AO_LISP_NCHUNK-1].size; + r = m - 1; } + /* + * The correct location is always in 'l', with r = l-1 being + * the entry before the right one + */ + +#if DBG_MEM + /* Off the right side */ + if (l >= AO_LISP_NCHUNK) + ao_lisp_abort(); + + /* Off the left side */ + if (l == 0 && chunk_busy && addr > ao_lisp_chunk[0].old_addr) + ao_lisp_abort(); +#endif + + /* Shuffle existing entries right */ + int end = min(AO_LISP_NCHUNK, chunk_busy + 1); + + memmove(&ao_lisp_chunk[l+1], + &ao_lisp_chunk[l], + (end - (l+1)) * sizeof (struct ao_lisp_chunk)); + + /* Add new entry */ + ao_lisp_chunk[l].old_addr = addr; + ao_lisp_chunk[l].size = size; + + /* Increment the number of elements up to the size of the array */ + if (chunk_busy < AO_LISP_NCHUNK) + chunk_busy++; + + /* Set the top address if the array is full */ + if (chunk_busy == AO_LISP_NCHUNK) + chunk_high = ao_lisp_chunk[AO_LISP_NCHUNK-1].old_addr + + ao_lisp_chunk[AO_LISP_NCHUNK-1].size; } static void |