[subset] Optimize set iteration by caching the last found page map index.
Reuse it if possible on consecutive calls to next(). Will signifcantly speed up cases where the entire set is iterated. In local testing iterating a very large set was 10x faster.
This commit is contained in:
parent
1bb00cd54b
commit
2c137045dc
@ -220,6 +220,7 @@ struct hb_set_t
|
||||
hb_object_header_t header;
|
||||
bool successful; /* Allocations successful */
|
||||
mutable unsigned int population;
|
||||
mutable unsigned int last_page_lookup;
|
||||
hb_sorted_vector_t<page_map_t> page_map;
|
||||
hb_vector_t<page_t> pages;
|
||||
|
||||
@ -227,6 +228,7 @@ struct hb_set_t
|
||||
{
|
||||
successful = true;
|
||||
population = 0;
|
||||
last_page_lookup = 0;
|
||||
page_map.init ();
|
||||
pages.init ();
|
||||
}
|
||||
@ -238,6 +240,7 @@ struct hb_set_t
|
||||
void fini_shallow ()
|
||||
{
|
||||
population = 0;
|
||||
last_page_lookup = 0;
|
||||
page_map.fini ();
|
||||
pages.fini ();
|
||||
}
|
||||
@ -742,27 +745,43 @@ struct hb_set_t
|
||||
return *codepoint != INVALID;
|
||||
}
|
||||
|
||||
page_map_t map = {get_major (*codepoint), 0};
|
||||
unsigned int i;
|
||||
page_map.bfind (map, &i, HB_BFIND_NOT_FOUND_STORE_CLOSEST);
|
||||
if (i < page_map.length && page_map[i].major == map.major)
|
||||
unsigned int major = get_major (*codepoint);
|
||||
unsigned int i = last_page_lookup;
|
||||
|
||||
if (unlikely (i >= page_map.length || (page_map.arrayZ[i]).major != major))
|
||||
{
|
||||
if (pages[page_map[i].index].next (codepoint))
|
||||
page_map_t map = {major, 0};
|
||||
page_map.bfind (map, &i, HB_BFIND_NOT_FOUND_STORE_CLOSEST);
|
||||
if (i >= page_map.length) {
|
||||
*codepoint = INVALID;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
page_map_t ¤t = page_map.arrayZ[i];
|
||||
if (likely (current.major == major))
|
||||
{
|
||||
if (pages.arrayZ[current.index].next (codepoint))
|
||||
{
|
||||
*codepoint += page_map[i].major * page_t::PAGE_BITS;
|
||||
return true;
|
||||
*codepoint += current.major * page_t::PAGE_BITS;
|
||||
last_page_lookup = i;
|
||||
return true;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
for (; i < page_map.length; i++)
|
||||
{
|
||||
hb_codepoint_t m = pages[page_map[i].index].get_min ();
|
||||
const page_map_t ¤t = page_map.arrayZ[i];
|
||||
hb_codepoint_t m = pages.arrayZ[current.index].get_min ();
|
||||
if (m != INVALID)
|
||||
{
|
||||
*codepoint = page_map[i].major * page_t::PAGE_BITS + m;
|
||||
*codepoint = current.major * page_t::PAGE_BITS + m;
|
||||
last_page_lookup = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
last_page_lookup = 0;
|
||||
*codepoint = INVALID;
|
||||
return false;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user