ref: 007ec4e4611e7636a72830b8e927c8d803d69ece
parent: 9ed9fa49fb919ce97cc035bffe42290876b3f999
author: Timothy B. Terriberry <tterribe@xiph.org>
date: Sun Sep 23 04:42:58 EDT 2012
More link enumeration improvements. 1) Remember the granule position of the last page we've seen from the current link and save the first page of the next link as long as we're scanning forward. This knocks almost 10% off the number of seeks for large links. For smaller links the improvement is much larger. 2) Only use pairs of close-by serial numbers to estimate link start locations (assuming they're above our start threshold). This gives a minor (<2%) improvement, which might be in the noise, but as it doesn't appear to hurt and is faster, might as well. 3) Eliminate a redundant check in op_pcm_seek_page_impl().
--- a/src/opusfile.c
+++ b/src/opusfile.c
@@ -934,7 +934,7 @@
}
offset1=_sr[sri].offset;
serialno1=_sr[sri].serialno;
- for(srj=0;srj<sri;srj++){
+ for(srj=sri;srj-->0;){
ogg_int64_t gp2;
opus_int64 offset2;
opus_int64 num;
@@ -956,6 +956,7 @@
offset2-=op_rescale64(gp2,den,num);
if(offset2<_searched)continue;
bisect=OP_MIN(bisect,offset2);
+ break;
}
}
return bisect>=_end_searched?-1:bisect;
@@ -989,12 +990,13 @@
improve the lower bound on the location where the next link starts.*/
nsr=1;
for(;;){
- opus_int64 data_offset;
- opus_int64 end_searched;
- opus_int64 bisect;
- opus_int64 next;
- opus_int64 last;
- int sri;
+ opus_int64 data_offset;
+ opus_int64 end_searched;
+ opus_int64 bisect;
+ opus_int64 next;
+ opus_int64 last;
+ ogg_int64_t end_gp;
+ int sri;
serialnos=*_serialnos;
nserialnos=*_nserialnos;
if(OP_UNLIKELY(nlinks>=clinks)){
@@ -1018,8 +1020,13 @@
if(sri<=0)break;
/*Last page wasn't found.
We have at least one more link.*/
+ last=-1;
end_searched=next=_sr[sri-1].search_start;
- if(sri<nsr)_searched=_sr[sri].offset+_sr[sri].size;
+ end_gp=-1;
+ if(sri<nsr){
+ _searched=_sr[sri].offset+_sr[sri].size;
+ if(_sr[sri].serialno==links[nlinks-1].serialno)end_gp=_sr[sri].gp;
+ }
nsr=sri;
bisect=-1;
/*If we've already found the end of at least one link, try to pick the
@@ -1044,6 +1051,7 @@
while(_searched<end_searched){
if(bisect==-1)bisect=_searched+(end_searched-_searched>>1);
if(OP_UNLIKELY(bisect-_searched<OP_CHUNK_SIZE))bisect=_searched;
+ else end_gp=-1;
ret=op_seek_helper(_of,bisect);
if(OP_UNLIKELY(ret<0))return ret;
last=op_get_next_page(_of,&og,_of->end);
@@ -1051,6 +1059,7 @@
if(OP_UNLIKELY(last<0))return OP_EBADLINK;
OP_ASSERT(nsr<_csr);
_sr[nsr].serialno=ogg_page_serialno(&og);
+ _sr[nsr].gp=ogg_page_granulepos(&og);
if(!op_lookup_serialno(_sr[nsr].serialno,serialnos,nserialnos)){
end_searched=bisect;
next=last;
@@ -1061,11 +1070,13 @@
OP_ASSERT(_of->offset-last>=0);
OP_ASSERT(_of->offset-last<=OP_PAGE_SIZE);
_sr[nsr].size=(opus_int32)(_of->offset-last);
- _sr[nsr].gp=ogg_page_granulepos(&og);
nsr++;
}
}
- else _searched=_of->offset;
+ else{
+ _searched=_of->offset;
+ if(_sr[nsr].serialno==links[nlinks-1].serialno)end_gp=_sr[nsr].gp;
+ }
bisect=op_predict_link_start(_sr,nsr,_searched,end_searched);
}
/*Bisection point found.
@@ -1074,17 +1085,20 @@
empty.*/
if(OP_LIKELY(links[nlinks-1].pcm_end==-1)){
ret=op_find_final_pcm_offset(_of,serialnos,nserialnos,
- links+nlinks-1,next,0,-1,&total_duration);
+ links+nlinks-1,next,links[nlinks-1].serialno,end_gp,&total_duration);
if(OP_UNLIKELY(ret<0))return ret;
+ if(end_gp==-1)last=-1;
}
/*Restore the cursor position after the seek.
This only performs an actual seek if the last page in the link did not
belong to our Opus stream.
TODO: Read forward instead, or let seek implementations do that?*/
- ret=op_seek_helper(_of,next);
- if(OP_UNLIKELY(ret<0))return ret;
+ if(last!=next){
+ ret=op_seek_helper(_of,next);
+ if(OP_UNLIKELY(ret<0))return ret;
+ }
ret=op_fetch_headers(_of,&links[nlinks].head,&links[nlinks].tags,
- _serialnos,_nserialnos,_cserialnos,NULL);
+ _serialnos,_nserialnos,_cserialnos,last!=next?NULL:&og);
if(OP_UNLIKELY(ret<0))return ret;
links[nlinks].offset=next;
links[nlinks].data_offset=_of->offset;
@@ -2027,10 +2041,8 @@
if(bisect<=begin+1)end=begin;
else{
bisect=OP_MAX(bisect-OP_CHUNK_SIZE,begin+1);
- if(bisect!=_of->offset){
- ret=op_seek_helper(_of,bisect);
- if(OP_UNLIKELY(ret<0))return ret;
- }
+ ret=op_seek_helper(_of,bisect);
+ if(OP_UNLIKELY(ret<0))return ret;
}
}
else{