[−][src]Struct pdb::TypeFinder 
pub struct TypeFinder<'t> { /* fields omitted */ }A TypeFinder is a secondary, in-memory data structure that permits efficiently finding types
by TypeIndex. It starts out empty and must be populated by calling update(&TypeIter) while
iterating.
TypeFinder allocates all the memory it needs when it is first created. The footprint is
directly proportional to the total number of types; see TypeInformation.len().
Time/space trade-off
The naïve approach is to store the position of each Type as they are covered in the stream.
The cost is memory: namely one u32 per Type.
Compare this approach to a TypeFinder that stores the position of every Nth type. Memory
requirements would be reduced by a factor of N in exchange for requiring an average of (N-1)/2
iterations per lookup. However, iteration is cheap sequential memory access, and spending less
memory on TypeFinder means more of the data can fit in the cache, so this is likely a good
trade-off for small-ish values of N.
TypeFinder is parameterized by shift which controls this trade-off as powers of two:
- If 
shiftis 0,TypeFinderstores 4 bytes perTypeand always performs direct lookups. - If 
shiftis 1,TypeFinderstores 2 bytes perTypeand averages 0.5 iterations per lookup. - If 
shiftis 2,TypeFinderstores 1 byte perTypeand averages 1.5 iterations per lookup. - If 
shiftis 3,TypeFinderstores 4 bits perTypeand averages 3.5 iterations per lookup. - If 
shiftis 4,TypeFinderstores 2 bits perTypeand averages 7.5 iterations per lookup. - If 
shiftis 5,TypeFinderstores 1 bit perTypeand averages 15.5 iterations per lookup. 
This list can continue but with rapidly diminishing returns. Iteration cost is proportional to type size, which varies, but typical numbers from a large program are:
- 24% of types are 12 bytes
 - 34% of types are <= 16 bytes
 - 84% of types are <= 32 bytes
 
A shift of 2 or 3 is likely appropriate for most workloads. 500K types would require 1 MB or
500 KB of memory respectively, and lookups -- though indirect -- would still usually need only
one or two 64-byte cache lines.
Methods
impl<'t> TypeFinder<'t>[src] 
impl<'t> TypeFinder<'t>pub fn max_indexed_type(&self) -> TypeIndex[src] 
pub fn max_indexed_type(&self) -> TypeIndexReturns the highest TypeIndex which is currently served by this TypeFinder.
In general, you shouldn't need to consider this. Types always refer to types with lower
TypeIndexes, and either:
- You obtained a 
Typeby iterating, in which case you should be callingupdate()as you iterate, and in which case all types it can reference are <=max_indexed_type(), or - You got a 
Typefrom thisTypeFinder, in which case all types it can reference are still <=max_indexed_type(). 
pub fn update(&mut self, iterator: &TypeIter)[src] 
pub fn update(&mut self, iterator: &TypeIter)Update this TypeFinder based on the current position of a TypeIter.
Do this each time you call .next().
pub fn find(&self, type_index: TypeIndex) -> Result<Type<'t>>[src] 
pub fn find(&self, type_index: TypeIndex) -> Result<Type<'t>>Find a type by TypeIndex.
Errors
Error::TypeNotFound(type_index)if you ask for a type that doesn't existError::TypeNotIndexed(type_index, max_indexed_type)if you ask for a type that is known to exist but is not currently known by thisTypeFinder.
Trait Implementations
impl<'t> Debug for TypeFinder<'t>[src] 
impl<'t> Debug for TypeFinder<'t>Auto Trait Implementations
impl<'t> Send for TypeFinder<'t>
impl<'t> Send for TypeFinder<'t>impl<'t> Sync for TypeFinder<'t>
impl<'t> Sync for TypeFinder<'t>