注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

断尘居

温柔的男人像海洋。

 
 
 
 
 

日志

 
 

Lucene索引过程分析(3)  

2011-12-22 16:51:31|  分类: Lucene |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

5、DocumentsWriter对CharBlockPool,ByteBlockPool,IntBlockPool的缓存管理

  • 在索引的过程中,DocumentsWriter将词信息(term)存储在CharBlockPool中,将文档号(doc ID),词频(freq)和位置(prox)信息存储在ByteBlockPool中。
  • 在ByteBlockPool中,缓存是分块(slice)分配的,块(slice)是分层次的,层次越高,此层的块越大,每一层的块大小事相同的。
    • nextLevelArray表示的是当前层的下一层是第几层,可见第9层的下一层还是第9层,也就是说最高有9层。
    • levelSizeArray表示每一层的块大小,第一层是5个byte,第二层是14个byte以此类推。

ByteBlockPool类中有以下静态变量:

final static int[] nextLevelArray = {1, 2, 3, 4, 5, 6, 7, 8, 9, 9};
final static int[] levelSizeArray = {5, 14, 20, 30, 40, 40, 80, 80, 120, 200};

  • 在ByteBlockPool中分配一个块的代码如下:

 

//此函数仅仅在upto已经是当前块的结尾的时候方才调用来分配新块。

public int allocSlice(final byte[] slice, final int upto) {

  //可根据块的结束符来得到块所在的层次。从而我们可以推断,每个层次的块都有不同的结束符,第1层为16,第2层位17,第3层18,依次类推。

  final int level = slice[upto] & 15;

  //从数组总得到下一个层次及下一层块的大小。

  final int newLevel = nextLevelArray[level];

  final int newSize = levelSizeArray[newLevel];

  // 如果当前缓存总量不够大,则从DocumentsWriter的freeByteBlocks中分配。

  if (byteUpto > DocumentsWriter.BYTE_BLOCK_SIZE-newSize)

    nextBuffer();

  final int newUpto = byteUpto;

  final int offset = newUpto + byteOffset;

  byteUpto += newSize;

  //当分配了新的块的时候,需要有一个指针从本块指向下一个块,使得读取此信息的时候,能够在此块读取结束后,到下一个块继续读取。

  //这个指针需要4个byte,在本块中,除了结束符所占用的一个byte之外,之前的三个byte的数据都应该移到新的块中,从而四个byte连起来形成一个指针。

  buffer[newUpto] = slice[upto-3];

  buffer[newUpto+1] = slice[upto-2];

  buffer[newUpto+2] = slice[upto-1];

  // 将偏移量(也即指针)写入到连同结束符在内的四个byte

  slice[upto-3] = (byte) (offset >>> 24);

  slice[upto-2] = (byte) (offset >>> 16);

  slice[upto-1] = (byte) (offset >>> 8);

  slice[upto] = (byte) offset;

  // 在新的块的结尾写入新的结束符,结束符和层次的关系就是(endbyte = 16 | level)

  buffer[byteUpto-1] = (byte) (16|newLevel);

  return newUpto+3;

}

  • 在ByteBlockPool中,文档号和词频(freq)信息是应用或然跟随原则写到一个块中去的,而位置信息(prox)是写入到另一个块中去的,对于同一个词,这两块的偏移量保存在IntBlockPool中。因而在IntBlockPool中,每一个词都有两个int,第0个表示docid + freq在ByteBlockPool中的偏移量,第1个表示prox在ByteBlockPool中的偏移量。
  • 在写入docid + freq信息的时候,调用termsHashPerField.writeVInt(0, p.lastDocCode),第一个参数表示向此词的第0个偏移量写入;在写入prox信息的时候,调用termsHashPerField.writeVInt(1, (proxCode<<1)|1),第一个参数表示向此词的第1个偏移量写入。
  • CharBlockPool是按照出现的先后顺序保存词(term)
  • 在TermsHashPerField中,有一个成员变量RawPostingList[] postingsHash,为每一个term分配了一个RawPostingList,将上述三个缓存关联起来。

 

abstract class RawPostingList {

  final static int BYTES_SIZE = DocumentsWriter.OBJECT_HEADER_BYTES + 3*DocumentsWriter.INT_NUM_BYTE;

  int textStart; //此词在CharBlockPool中的偏移量,由此可以知道是哪个词。

  int intStart; //此词在IntBlockPool中的偏移量,在指向的位置有两个int,一个是docid + freq信息的偏移量,一个是prox信息的偏移量。

  int byteStart; //此词在ByteBlockPool中的起始偏移量

}

static final class PostingList extends RawPostingList {

  int docFreq;                                    // 此词在此文档中出现的次数

  int lastDocID;                                  // 上次处理完的包含此词的文档号。

  int lastDocCode;                                // 文档号和词频按照或然跟随原则形成的编码

  int lastPosition;                               // 上次处理完的此词的位置

}

这里需要说明的是,在IntBlockPool中保存了两个在ByteBlockPool中的偏移量,而在RawPostingList的byteStart又保存了在ByteBlockPool中的偏移量,这两者有什么区别呢?

在IntBlockPool中保存的分别指向docid+freq及prox信息在ByteBlockPool中的偏移量是主要用来写入信息的,它记录的偏移量是下一个要写入的docid+freq或者prox在ByteBlockPool中的位置,随着信息的不断写入,IntBlockPool中的两个偏移量是不断改变的,始终指向下一个可以写入的位置。

RawPostingList中byteStart主要是用来读取docid及prox信息的,当索引过程基本结束,所有的信息都写入在缓存中了,那么如何找到此词对应的文档号偏移量及位置信息,然后写到索引文件中去呢?自然是通过RawPostingList找到byteStart,然后根据byteStart在ByteBlockPool中找到docid+freq及prox信息的起始位置,从起始位置开始的两个大小为5的块,第一个就是docid+freq信息的源头,第二个就是prox信息的源头,如果源头的块中包含了所有的信息,读出来就可以了,如果源头的块中有指针,则沿着指针寻找到下一个块,从而可以找到所有的信息。

  • 下面举一个实例来表明如果进行缓存管理的:

此例子中,准备添加三个文件:

file01: common common common common common term

file02: common common common common common term term

file03: term term term common common common common common

file04: term

(1) 添加第一篇文档第一个common

  • 在CharBlockPool中分配6个char来存放"common"字符串
  • 在ByteBlockPool中分配两个块,每个块大小为5,以16结束,第一个块用来存放docid+freq信息,第二个块用来存放prox信息。此时docid+freq信息没有写入,docid+freq信息总是在下一篇文档的处理过程出现了"common"的时候方才写入,因为当一篇文档没有处理完毕的时候,freq也即词频是无法知道的。而prox信息存放0,是因为第一个common的位置为0,但是此0应该左移一位,最后一位置0表示没有payload存储,因而0<<1 + 0 = 0。
  • 在IntBlockPool中分配两个int,一个指向第0个位置,是因为当前没有docid+freq信息写入,第二个指向第6个位置,是因为第5个位置写入了prox信息。所以IntBlockPool中存放的是下一个要写入的位置。

 

 

(2) 添加第四个common

  • 在ByteBlockPool中,prox信息已经存放了4个,第一个0是代表第一个位置为0,后面不跟随payload。第二个2表示,位置增量(差值原则)为1,后面不跟随payload(或然跟随原则),1<<1 + 0 =2。第三个第四个同第二个。

 

 

(3) 添加第五个common

  • ByteBlockPool中,存放prox信息的块已经全部填满,必须重新分配新的块。
  • 新的块层次为2,大小为14,在缓存的最后追加分配。
  • 原块中连同结束位在内的四个byte作为指针(绿色部分),指向新的块的其实地址,在此为10.
  • 被指针占用的结束位之前的三位移到新的块中,也即6, 7, 8移到10, 11, 12处,13处是第五个common的prox信息。
  • 指针的值并不都是四个byte的最后一位,当缓存很大的时候,指针的值也会很大。比如指针出现[0, 0, 0, -56],最后一位为负,并不表示指向的负位置,而是最后一个byte的第一位为1,显示为有符号数为负,-56的二进制是11001000,和前三个byte拼称int,大小为200也即指向第200个位置。比如指针出现[0, 0, 1, 2],其转换为二进制的int为100000010,大小为258,也即指向第258个位置。比如指针出现
    [0, 0, 1, -98],转换为二进制的int为110011110,大小为414,也即指向第414个位置。

 

 

(4) 添加第一篇文档,第一个term

  • CharBlockPool中分配了5个char来存放"term"
  • ByteBlockPool中分配了两个块来分别存放docid+freq信息和prox信息。第一个块没有信息写入,第二个块写入了"term"的位置信息,即出现在第5个位置,并且后面没有payload,5<<1 + 0 = 10。
  • IntBlockPool中分配了两个int来指向"term"的两个块中下一个写入的位置。

 

 

(5) 添加第二篇文档第一个common

  • 第一篇文档的common的docid+freq信息写入。在第一篇文档中,"common"出现了5次,文档号为0,按照或然跟随原则,存放的信息为[docid<<1 + 0, 5] = [0, 5],docid左移一位,最后一位为0表示freq大于1。
  • 第二篇文档第一个common的位置信息也写入了,位置为0,0<<1 + 0 = 0。

 

 

(6) 添加第二篇文档第一个term

  • 第一篇文档中的term的docid+freq信息写入,在第一篇文档中,"term"出现了1次,文档号为0,所以存储信息为[docid<<1 + 1] = [1],文档号左移一位,最后一位为1表示freq为1。
  • 第二篇文档第一个term的prox信息也写入了,在第5个位置,5<<1 + 0 = 10。
  • 第二篇文档中的5个common的prox信息也写入了,分别为从14到18的[0, 2, 2, 2, 2]

 

 

(7) 添加第三篇文档的第一个term

  • 第二篇文档的term的docid+freq信息写入,在第二篇文档中,文档号为1,"term"出现了2次,所以存储为[docid<<1 + 0, freq] = [2, 2],存储在25, 26两个位置。
  • 第二篇文档中两个term的位置信息也写入了,为30, 31的[10, 2],也即出现在第5个,第6个位置,后面不跟随payload。
  • 第三篇文档的第一个term的位置信息也写入了,在第0个位置,不跟payload,为32保存的[0]

 

 

(8) 添加第三篇文档第二个term

  • term的位置信息已经填满了,必须分配新的块,层次为2,大小为14,结束符为17,也即图中34到47的位置。
  • 30到33的四个byte组成一个int指针,指向第34个位置
  • 原来30到32的三个prox信息移到34到36的位置。
  • 在37处保存第三篇文档第二个term的位置信息,位置为1,不跟随payload,1<<1 + 0 = 2。

 

 

(9) 添加第三篇文档第四个common

  • 第二篇文档中"common"的docid+freq信息写入,文档号为1,出现了5次,存储为[docid << 1 + 0, freq],docid取差值为1,因而存储为 [2, 5],即2,3的位置。
  • 第三篇文档中前四个common的位置信息写入,即从19到22的[6, 2, 2, 2],即出现在第3个,第4个,第5个,第6个位置。
  • 第三篇文档中的第三个"term"的位置信息也写入,为38处的[2]。

 

 

(10) 添加第三篇文档的第五个common

  • 虽然common已经分配了层次为2,大小为14的第二个块(从10到23),不过还是用完了,需要在缓存的最后分配新的块,层次为3, 7, 8移44个
    虽染伤痕 - 断,需要在缓存的最后番层纯椋4恢"jximgwi瞬愦挝7uon

    file04: term<-f10到2mon62e10'目椋愦挝3, 7, 8移44i.pg" > <紧跟上,分别为>

  • 0 = 10。 <0, 2,层次为e索引过程分析(3) - 断尘伤痕 - 断尘居" alt="" src="http://dl.iteye.com/upload/attachment/202783/a64c7e25-7f03-3e3e-b54b-029b1ddc2e13.fpg"d07-9483-634da5a20cb7

     

    (9) 添加第三篇文档第四个com1mon

    <四>
  • 第二篇文档的term的docid+fr> <3le="Lucen3, 7,然恢谩 桓鎝篇文档中,"com分配新的为2,矗愦挝3, 7, 8倚连. 很大的时鑫恢
  • <3l"Lucene索引过程分析(3) - 断尘伤痕 - 断尘居" alt="" src="http://dl.iteye.com/upload/attachment/202779/66f0dabd-e799-3fbd-831e85cd979ae3cba38pg"d96idt8pg1dr="739d536="472" >

     

    <6>&nbrel="nofollow"> 

    (6) 添加第二篇文档第一个ter1l> 最终tingList {<, ar来存放"term, t来指向"termool的缓存管理

    (7) 添加第三el="nofollow"> 治(3) - 断点击查看原始位置图片&nbye.com/upload/attachment/202769/45c4b9be-03c5-36e5-885891/f4b2721>

    " h 

    pac&nbrel="i>下面举一个实例来 nbw-blog zta ss="bct fc
    div> Andnbw-bclearfi由觮"> (function(){ van clwumiiRell_2dItem0">
    pe n ight fcn0-919"> e an>
     &nbsnbc-0g>5c-0-40 pe mt pe mt-个纹缆壅庹舠tag">
    titleft;margin-left:12-bkicons"pe n ight fcn0-919"> e an>
    &nbsnbc-0g>5c-0-40 pe min>
    <
    &nbsnbc-0g>5c-0-40 pe mass转发至ibo stag">
    ight fcn0-919"> e an>
    &nbsnbc-0g>5c-0-40 pe min>
    <
    &nbsnbc-0g>5c-0-40 pe mtss转发至ibo stag">

    赶%="0" scrol1杏>
    t"m-e">

    : ="h

    &nbsogse">阅读(eibo2" title=paniReadCou/spa572 an ideUpan idcn0-919">&nbsspae">port" cl

B"ogp""0 >

"中""0; slocid萷; sl槔捶直鸫娣興op>final static int[]cid/p; slocid萷; sltends List exli> 3, 4, 5, 6, 7, 8, 9, 9};
final static int[] lecid萣r; sltends ay = {5, 14, 20, 30, 40, 40, 80, 80, 120, 200};

B"ogp""0 >

"中2""0; slocid萷; sl从数譶bsplcid/p; slocid萷; sl前块的结尾的时候方才调用来分配新块。

public int allocSlcid/p; slocid萷; sll byte[] slice, final int upto) {

  //可根据块礳id/p; slocid萷; sl从数譶bspl

  final int lcid/p; slocid萷; sl从数譶bspler[byt最篺set >&//从数%E5;樽艿cid/p; slocid萷; sl从数譶bspl<前炕层块的大小。

  final int ncid/p; slocid萷; sl从数譶bsplereturn n最

  final int ncid/p; slocid萷; sl从数譶bspleretevel];

  // 如果当前cid/p; slocid萷; sl从数譶bspl<嬖覦ocumentsWriter的freeByteBlocks中分配。

  if (byteUptcid/p; slocid萷; sl从数譶bspl

   cid/p; slocid萷; sl从数譶bspl从数譶bspl从数譶bsplsp; final int ncid/p; slocid萷; sl从数譶bspl>  //縟>最篵每/tr>礳id/p; slocid萷; sl从数譶bspleset;

  byteUpto +=cid/p; slocid萷; sl从数譶bspl>b每/tr>; //当分配了衏id/p; slocid萷; sl从数譶bspl>要有一个指针从本块指向下一个块,使得读取此信息的时候,能够在此块读取结束后,到下一个块继续读取。

  //这个指针cid/p; slocid萷; sl从数譶bspl>

  buffer[newUcid/p; slocid萷; sl从数譶bspl>upto-2];

<个位fset >&newUcid/p; slocid萷; sl从数譶bspl>upto-2];

  buffer[newUcid/p; slocid萷; sl从数譶bspl>upto-2];

  // 将偏移量cid/p; slocid萷; sl从数譶bspl>嬖崾谀诘乃母鯾yte

  slice[upto-cid/p; slocid萷; sl从数譶bspl>fset >&new鑫; 8);

&nb%E5; sl从数 slc%E5; slopto-cid/p; slocid萷; sl从数譶bspl>fset >&nt;> 16);

&n%E5; sl从数 slc%E5; slopto-cid/p; slocid萷; sl从数譶bspl>fset >&n

 >

&n%E5; sl从数 slc%E5; sloto]cid/p; slocid萷; sl从数譶bspl>fset >&  // 在新的块cid/p; slocid萷; sl从数譶bspl>嬖崾筒愦蔚墓叵稻褪(endbyte = 16 | level)

  buffer[bytecid/p; slocid萷; sl从数譶bspl>) (16|newLevel);

  return newUcid/p; slocid萷; sl从数譶bspl>

  • CharBlockPool是癱id/li; slocid萳i; slar来存放"term(term)
  • 在TermsHashPerFicid/li; slocid萳i; sl在T诘 p.lastDocCo2次st[] postingsHash,为每一个term分配了一个RawPostingList,将上述三个缓存关联起来。
  • B"ogp""0 >

    "中9""0; slocid萷; sl从数譶bsplcid/p; slocid萷; slist {

      final staticid/p; slocid萷; sl从数譶bsplstends List exli>ter.OBJECT_HEADER_BYTES + 3*DocumentsWriter.INT_NUM_BYTE;

      int textStacid/p; slocid萷; sl从数譶bsplsli>eckPool中的偏移量,由此可以知道是哪个词。

      int intStarcid/p; slocid萷; sl从数譶bsplsli>eli>ol中的起始偏移罥赶虻奈恢糜辛礁鰅nt,一个是docid + freq信息的偏移量,一个是prox信息的偏移量。

      int byteStacid/p; slocid萷; sl从数譶bsplsli>eb每竜l中的起始偏移灵来分别存放do贐ytestatic ficid/p; slocid萷; sl}cid/p; slocid萷; slList extends RawPostingList {

      int docFreqcid/p; slocid萷; sl从数譶bsplsli>e篇蜦6两萩%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbspl

    p>

      int lastDoccid/p; slocid萷; sl从数譶bsplsli>ep; &nb%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsp萩%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbspl

    }

    ep; 问萩%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbspl从数譶bspl从数譶bspl从数譶bspl从数譶bspl从数譶bspl从数譶bspl从数譶bspl从数譶bspl从数譶bspl从数譶bspl从数譶bspl从数譶bspl从数譶bspl从数譶bspl从数譶bspl从数譶bspl从数譶bspl从数譶bspl从数譶bspl从数譶bspl从数譶bspl从数譶bspl从数譶bspl从数譶bspl

    为[doc跟随原息为[docid<&lp; bastPoscid/p; slocid萷; sl从数譶bsplsli>ep;&n; &nb%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbsp萩%E5;nbsplc%E5;nbsplc%E5;nbsplc%E5;nbspl

    }

    这里需要薱id/p; slocid萷; sl}cid/p; slocid萷; slckPool中保存了两个在ByteBlockPool中的偏移量,而在RawPostingList的byteStart又保存了在ByteBlockPool中的偏移量,这两者有什么区别呢?

    在IntBlockPool中保cid/p; slocid萷; sl指向docid+freq及prox信息在ByteBlockPool中的偏移量是主要用来写入信息的,它记录的偏移量是下一个要写入的docid+freq或者prox在ByteBlockPool中的位置,随着信息的不断写入,IntBlockPool中的两个偏移量是不断改变的,始终指向下一个可以写入的位置。

    RawPostingList中。cid/p; slocid萷; slt,然后根据bytocid及prox信息的,当索引过程基本结束,所有的信息都写入在缓存中了,那么如何找到此词对应的文档号偏移量及位置信息,然后写到索引文件中去呢?自然是通过RawPostingList找到byteStart,然后根据byteStart在ByteBlockPool中找到docid+freq及prox信息的起始位置,从起始位置开2比目椋谝1 0的块,第一个就是docid+freq信息的源头,第二个就是prox信息的源头,如果源头的块中包含了所有的信息,读出来就可以了,如果源头的块中有指针,则沿着指针寻找到下一个块,从而可以找到所有的信息。

    B"ogp""0 >

    "中9""0; slocid萷; sl:

    file01: common comcid/p; slocid萷; slon common common term

    file02: common comcid/p; slocid萷; slon common common term term

    file03: term term cid/p; slocid萷; slon coommon common common common

    file04: term

    • 在CharBlockPcid/p; slocid萿l; slocid萳i; sl纱丝梢灾朗悄膃10椤 >ByteBlock"笮∥1"ckPool謈id/li; slocid萳i; slri槔捶直鸫娣興o贐e10
    • 谝桓隹橛美创娣興ocid+freq信息,第二个块用来存放prox信息。此时docid+freq信息没有写入,docid+freq信息总是在下一篇文档的处理过程出现了"common"的时候方才写入,因"笮∥1"比如指有处理完毕的时候,freq也即词频是无法知道的。而prox信息存放0,是因为第一个common的位置为0,但是此0应该左移一位,最后一位置0表示没有payload存储,因而0<<1 + 0 = 0。 %E5;id萩%E5;id仁BlockPoo中分cid/li; slocid萳i; slriI赶虻奈恢糜辛絜10 /li芾韇yte2保存的[0]息写入,第二个指向第6个位置,是因为第5个位置写入了prox信息。所以IntBlockPool中存放的是下一个要写入的位置。

     

    "nb; slcid/p; slocid萷; sl从数譶bsplcid/p; slocid萷; sl磇d;

    "nofollow"; slcid/a; slc%E5;nbsplcid/p; slocid萷; slul>
  • 在ByteBlockPcid/p; slocid萿l; slocid萳i; sl槔捶直鸫娣興o贐谝桓0是代表第一个位置为0,后面不跟随payload。第二个2表示,位置增量(差值原则)为1,后面不跟随payload(或然跟随原则),1<<1 + 0 =2。第三个第%E5;id萩%E5;id仁BlockPo
  •  

    "nb; slcid/p; slocid萷; sl从数譶bsplcid/p; slocid萷; sl磇d;

    "nofollow"; slcid/a; slc%E5;nbsplcid/p; slocid萷; slul>
  • ByteBlockPoocid/p; slocid萿l; slocid萳i; sl槔捶直鸫娣興o贐谝满,必须重新分配新的块。
  • 新的块层次为2,碿id/li; sl謈id萳i; sl诨捍娴淖詈笞芳臃峙洹
  • 原块中连同结束位cid/li; sl謈id萳i; slbyte作为指针(绿色部分),指向新的块的其实地址,在此为10.
  • 被指针占用的结束cid/li; sl謈id萳i; sl位移到新的块中,也即6, 7, 8移到10, 11, 12处,13处是第五个common的prox信息。
  • 指针的值并不都是cid/li; sl謈id萳i; sl出现[0, ,当缓存很大的时候,指针的值也会很大。比如指针出现[0, 0, 0, -56],最后一位为负,并不表示指向的负位置,而是最后一个byte的第一位为1,显示为有符号数为负,-56的二进制是11001000,和前三个byte拼称int,大小为200也即指向第200个位置。比如指针出现[0, 0, 1, 2],其转惑一位为负Dint为100000010,大小为258,也即指向第258个位置。比如指针出现
    [0, 0, 1, -98],转换蝐id萣r; sl频膇nt为110011110,大小为414,也即指向第414个位置。
  •  

    "nb; slcid/p; slocid萷; sl从数譶bsplcid/p; slocid萷; sl磇d;

    "nofollow"; slcid/a; slc%E5;nbsplcid/p; slocid萷; sluerm

    • CharBlockPoocid/p; slocid萿l; slocid萳i; slar来存放"term"字符>
    • ByteBlock"桓"ncid/li; sl謈id萳i; sl槔捶直鸫娣興o贐e10 q信息和prox信息。第一个块没有信息写入,第二个块写入了"term"的位置信息,即出现在"桓"的[6, 2, 25个,第6个位訧ntBlo猯t;1 + 0 = 10。
    • %E5;id萩%E5;id仁BlockPo 械5竎id/li; sl謈id萳i; slI赶虻奈恢糜辛絜10 q信息li>个写入"桓"的

     

    "n_BLOCcid/p; slocid萷; sl%E5;nbsplcid/p; slocid萷; slcid;

    "nofollow"; slcid/a; slc%E5;nbsplcid/p; slocid萷; slumon

    • 第一篇文档的cid/p; slocid萿l; slocid萳i; slfreq信息写的分别为从篇文档中,"com>
    • 第二篇文档第一个cid/li; sl謈id萳i; sld+freq信息二篇文分别为从]。
    0 = 0。

    "

    "n_sp;

    "

    "n_; slcid/p; slocid萷; sl%E5;nbsplcid/p; slocid萷; slcid;

    "nofollow"; slcid/a; slc%E5;nbsplcid/p; slocid萷; slum

    • 第一篇文档中cid/p; slocid萿l; slocid萳i; slfreq信息写贐yt桓鎝篇文档中,"com>
    • 第二篇文档第一个cid/li; sl謈id萳i; sld+freq信息二篇文桓鎝
    • %E5;id萩%E5;id仁B牡抵械5竎id/li; sl謈id萳i; sld+freq信息贐yt耍直鹞14到18的[0, 2, 2, 2, 2]

    "nofollow"; slcid/a; slc%E5;nbsplcid/p; slocid萷; sluerm

    • 第二篇文档的cid/p; slocid萿l; slocid萳i; slfrrm"出现羪t桓鎝篇文档中,"com>
    • 第二篇文档中两个cid/li; sl謈id萳i; sld+freq信息了,为30, 31的[10, 2],也即出现在第5个,第6个位置,后面不跟随payload。
    • 第三篇文档的第一cid/li; sl謈id萳i; sld+位置信息还是i芾砘跟随p]。
    0 = 为32保存的[0]

     

    "n_; slcid/p; slocid萷; sl%E5;nbsplcid/p; slocid萷; slcid;

    "nofollow"; slcid/a; slc%E5;nbsplcid/p; slocid萷; slum

    : ="h在LOFTER的更多文章< 0 1">< 5>

    "赶%="0" scrol12c&nallowt.loan men nallowtransparename" cellph&naloam/js/yadjingxuan_201501re笮∥

    b.do?email=zhaohe162@163769/> / tih tittle= 巳et= k b-bleft;margin-left:12;>

    < 0 5> titleft;mapx;padd4">< 0 15>< 0;" cel:1>< solid #d5d5d5;backgrou/d:#ffffe1aget=">

    : ="h an i

    < 16>< 1">< 0;cospr:#d7854e;curspr:poli>eraa>关闭 an id=" ht< tibleft;ma> 玩LOFTER阝费冲印20张照片,人人有奖!llow">llow">llow">llow">llow">评论第四 tit用易信&zta><<有> ockPool,ByteBlockPool,IntBlockPool的缓存管理
    • 在 atrong\> riter将词信息(term)存储在CharBlockPool中,将文档号(doc ID),词频(freq)和位置(prox)信息存储在ByteBlockPool中。
    • 在ByteBlockPool ri槔捶直鸫娣興o贐(slice)是分层次的,层次越高,此层的块越大,每一层的块大小事相同的。
      • nextLevelArray表

          fin二篇

      • levelSizeArray表

         二篇鯾yte,第二层是14个byte以此类推。

    e索襖>e索襖>',
    Cou/s:0,
    引atus:'none',
    _single:'

    第四'

    < noulid=//www.lofter.cosplefoolsBytru2ss0ref="http://b.do.163769/4${x.visitorName}/ss
    id=//www.lofter.cosref="http://b.do.163769/4services/wapb.do.html?frompersonalb.dohomesscan i<3) - ="来自网易手机博客"b用易信&p;第四 {elsesWrx.moveFrom=='iphone'} id=//www.lofter.cscan i<3) - ="来自iPhone客户端"b用易信&p;第四 {elsesWrx.moveFrom=='android'} id=//www.lofter.cscan i<3) - ="来自Android客户端"b用易信&p;第四 {elsesWrx.moveFrom=='mobile'} id=//www.lofter.c"0ref="http://b.do.163769/4services/em0b.do.html?frompersonalb.dohomesscan i<3) - ="来自网易短信写博"b用易信&p;第四 { w} < m2a-bd=//www.lofter.cosplefoolsBytru2ss0ref="http://b.do.163769/4${x.visitorName}/ss
    蟚t=//eaa idonerrorBythis.ploa.dcl_ .f60"blloam${fn1(a.userName)}"/>第四 < m2a-b0ref="http://b.do.163769/4${a.userName}/ss${fn(a.nickname,8)|escape}第四 < tib用易信&li>roe"><5ss${a.selfI赶ro|escape}{sWrg/eat260}${suspa6e5}{ w}<
    llow">< t=/> m2a-b0ref="#ss=//www.lofter.c>第四 蟚t=//eaa < m2a-b0ref="${furl()}${x.per> 蟚t=//eaa <6">推荐过这篇日志的人ommon
    < noulid=//www.lofter.cosplefoolsBytru2ss0ref="http://b.do.163769/4${x.re笮∥

    erName}/ss

    erNickname|escape}" onerrorBythis.ploa.dcl_ .f40"b用易信&cwd bdwa bdc0幸lloam${fn1(x.re笮∥

    erName)}"/>

    < m2a-b=//www.lofter.cosplefoolsBytru2s"0ref="http://b.do.163769/4${x.re笮∥

    erName}/ss

    erNickname,6)|escape}
    0} <6">他们还推荐0 =

    l#183l第an i>礱s用易信&">< m2a-b=//www.lofter.cosref="http://b.do.163769/4${y.re笮∥

    B.doP跟> B.doTitle|escape}第四

    蟚t=//eaa 转载记录=
    &nbsspan p;l#183l第an i>
    <7 m2a-b0ref="${x.referB.doUrl}ss${x.referB.doTitle|escape}第四第 ti
    <7 m2a-b0ref="${x.referHomePage}ss${x.referUserName|escape}第四第 ti
    蟚t=//eaa < m2a-b0ref="http://b.do.163769/4${x.userName}/${x.per> B.dos 3) - ="${x.3) - |lefault:""|escape}ss${x.3) - |lefault:""|escape}第四 蟚t=//eaa < m2a-b0ref="http://b.do.163769/4${x.userName}/${x.per> 蟚t=//eaa < m2a-b=//www.lofter.cosref="${x.b.doUrl|lefault:""|escape}?re笮∥

    R berid=itleam${x.b.doTile|lefault:""|escape}ss${x.b.doTile|lefault:""|escape}第四 蟚t=//eaa

    4}{b/eak}{ w}
    ${fn2(x.l bytshTime,'yyyy-MM-dd HH:mm:ss')}
    蟚t=//eaa < m2a-b0ref="${furl()}${x.per> 蟚t=//eaa &nbsilft p;llow">
    &nbsirgt p;llow">
    < noulid=//www.lofter.cosplefoolsBytru2ss0ref="http://b.do.163769/4${x.l bytsherUsername}/ss
    < m2a-b"=//www.lofter.cosplefoolsBytru2s"0ref="http://b.do.163769/4${x.l bytsherUsername}/ss
    蟚t=//eaa
    <6 bdwb bdc0 bds/n>网易新闻< ti
    ht/an i> 第四 祏l> {sWrlef0} 7}{b/eak}{ w} <5sscn0-919">&nbsib.dcke篇5i摹さ赼n i>${x.3) - |escape}第四 {/list} < tib用易信&downloal163 <有s=//www.lofter.cosplefoolsBytru2s"0ref="http://jing163769/4 蟚t=//eaa epsple-rsideb被推荐日志 bl配ssc/ul> epsple-rsideb最新日志 bl配ssc/ul> epsple-rsideb该作者比匿他文章 bl配ssc/ul> epsple-rsideb博主推荐 bl配ssc/ul> epsple-rsideb随机阅读 bl配ssc/ul> epsple-rsideb首页推荐 bl配ssc/ul> < m2a-b0ref="http://b.dog163769/">更多; slc sl第四礲r/> < tibtle=yodab9b_ridleft;margin-lefnonel_zoom:1="h < tibtle=b.doPublicAccou/鋝sc/ ti> i>蟚t=//eaa bdwt bds2 bdc0i < tib用易信&casessc/ ti> < tib用易信&iv c/ ti> c/ ti> i>蟚t=//eaa &nbszta> p;llow">
    < tib用易信&zta> class=sc/ ti> i>蟚t=//eaa ${x.nickName|escape}第四llow">llow">投票给
    llow">“${b[voteToOp_ _index]}”llow">llow">
    llow">{/ w} llow">llow">llow">cn0-919">&nbs">llow">llow">llow">llow">${fn1(x.voteTime)}
    蟚t=//eaa c/ ti> ecype="蟚t=/javascrip>ss vm-ewumiiP跟>Ls ecype="蟚t=/javascrip>s(lloamhttp:// >s < tib用易信&l 用 h赶">llow"> < tib用易信&r cr h赶">llow"> c/ ti> < tib用易信&n5-mb lcr bh an ceis
    llow"> < tib用易信&r br bh">llow"> < tib用易信&c bc bh lcr">llow"> c/ ti> c/ ti> < tib用易信&l wl g lg h赶">llow"> < tib用易信&l wl t lt">llow"> < tib用易信&l wl b lbssllow"> < tib用易信&-ewr g rg h赶">llow"> < tib用易信&-ewr t rt">llow"> < tib用易信&-ewr b rbssllow"> < tib用易信&n5-ac tib用易信&r hssllow">c tib用易信&c hssllow">c/ ti> c tib用易信&n5-a页脚 "nofollow"b用易信&m2ae"><8衧=//www.lofter.cosref="http://yxpg163769/">我的照片书第四 10">-第an i>
    "nofollow"b用易信&m2ae"><8衧=//www.lofter.cosref="http://b.dog163769//l bytc/tha6/ss博客风格第四 10">-第an i>
    "nofollow"b用易信&m2ae"><8衧=//www.lofter.cosref="http://b.dog163769//services/wapb.do.html">手机博客第四 10">-第an i>
    "nofollow"b用易信&m2ae"><8衧=//www.lofter.cosref="http://jingxuan_20150/app?
     e">10">-第an i>cn0-919">&nbs"><8衧tle=$_foot_subscribesscan i<用易信&p;llow"><8>订阅此博客第四第an i> <8">网易公司版权所有llow">lcopy;1997- if]--a if]--a i tib用易信&n5-tpl n5-inisn "nofollow"b用易信&prid=//wet="_bla k="0ref="http://helpg163769//anecial/007525FT/b.do.html?b13aze/a>帮助第四 can i<用易信&fr p;蟚t=//eaa ss <0':'"><3','"><1':'"><4','"><2':'"><5','"><3':'"><6','"><4':'"><7','"><5':'"><9'}}; By.jpgx?paePo'http://b.st .126.=de/笮on/empty?png'; /",= er:'他' s ecype="蟚t=/javascrip>s(lloamhttp://b1.st .126.=de/ c/scrip>s ecype="蟚t=/javascrip>s(lloamhttp://b1.st .126.=de/ c/scrip>s elloamhttp://analyticsg163769//i>es.jssecype="蟚t=/javascrip>ssc/scrip>s ecype="蟚t=/javascrip>ss _i>es_nacc='b.do';neteaseTrs s window.sepTimeout(fun/pion(){ ','//jinggoogle-analyticsg笮/analyticsgjs','ga'); ', 's cscrip>ecype="蟚t=/javascrip>ss window.sepTimeout(fun/pion(){ J.loalScrip>('http://music.ph.126.=de/ph.js?0<1'); J.l峙銬l_aByDWR(.dcl_ .dwr,'MusicBeanNew','se5CopyrightMusicSessionToken',false); },p000); c/scrip>s cscrip>s window.sepTimeout(fun/pion(){ rnallip>e=e篇蝩6e5.c/eateEpa6e5('scrip>'); allip>.asynce=e1; allip>.ploePo'http://b1.st .126.=de/ Child(allip>); },300); c/scrip>s ecype="蟚t=/javascrip>s(lloam/ c/scrip>s easync(lloamhttps://nos.=deease769/4udc-web/v1/.do.jss>c/scrip>s