@@ -43,53 +43,42 @@ type measurement struct {
4343}
4444
4545// TODO: refactor to verifyBundle(), use bcmills concurrency pattern
46- func verifyMatches (query string , files ranking.ResultPaths ) (filesSearched int , matches int , _ error ) {
46+ func verifyMatches (query string , files ranking.ResultPaths , possible [] fileMatches ) (filesSearched int , matches int , _ error ) {
4747 rqb := []byte (query )
4848 // matchFile, err := os.Create("/tmp/matchfile.pos.txt")
4949 // if err != nil {
5050 // return m, err
5151 // }
5252 // defer matchFile.Close()
53- work := make (chan [] ranking.ResultPath )
53+ work := make (chan ranking.ResultPath )
5454 go func () {
55- var last string
56- var bundle []ranking.ResultPath
57- for _ , fn := range files {
58- if fn .Path != last {
59- if len (bundle ) > 0 {
60- work <- bundle
61- bundle = nil
62- }
63- last = fn .Path
64- filesSearched ++
65- }
66- bundle = append (bundle , fn )
67- }
68- if len (bundle ) > 0 {
69- work <- bundle
55+ for _ , file := range files {
56+ work <- file
7057 }
7158 close (work )
7259 }()
73- numWorkers := min (len (files ), 1000 )
60+ filesSearched = len (files )
61+ numWorkers := min (len (files ), 100 )
7462 var matchesMu sync.Mutex
7563 var wg sync.WaitGroup
7664 wg .Add (numWorkers )
7765 for range numWorkers {
7866 go func () {
7967 defer wg .Done ()
8068 buf := make ([]byte , 0 , 64 * 1024 )
81- for bundle := range work {
69+ for file := range work {
70+ bundle := possible [file .MatchIdx ].matches
8271 // Turns out open+read+close is significantly faster than
8372 // mmap'ing a whole bunch of small files (most of our files are
8473 // << 64 KB).
8574 // https://eklausmeier.wordpress.com/2016/02/03/performance-comparison-mmap-versus-read-versus-fread/
86- f , err := os .Open (bundle [ 0 ] .Path )
75+ f , err := os .Open (file .Path )
8776 if err != nil {
8877 log .Fatal (err ) // TODO
8978 }
9079 // Assumption: bundle is ordered from low to high (if not, we
9180 // need to traverse bundle).
92- max := bundle [len (bundle )- 1 ].Position + len (rqb )
81+ max := int ( bundle [len (bundle )- 1 ].Position ) + len (rqb )
9382 if max > cap (buf ) {
9483 buf = make ([]byte , 0 , max )
9584 }
@@ -104,16 +93,17 @@ func verifyMatches(query string, files ranking.ResultPaths) (filesSearched int,
10493 b := buf [:n ]
10594
10695 lastPos := - 1
107- for _ , fn := range bundle {
108- if fn .Position + len (rqb ) < len (b ) && bytes .Equal (b [fn .Position :fn .Position + len (rqb )], rqb ) {
109- if lastPos > - 1 && ! bytes .ContainsRune (b [lastPos :fn .Position ], '\n' ) {
96+ for _ , m := range bundle {
97+ pos := int (m .Position )
98+ if pos + len (rqb ) < len (b ) && bytes .Equal (b [pos :pos + len (rqb )], rqb ) {
99+ if lastPos > - 1 && ! bytes .ContainsRune (b [lastPos :pos ], '\n' ) {
110100 continue // cap to one match per line, like grep()
111101 }
112102 matchesMu .Lock ()
113103 matches ++
114104 matchesMu .Unlock ()
115- //fmt.Fprintf(matchFile, "%s:%d\n", fn.Path, fn.Position )
116- lastPos = fn . Position
105+ //fmt.Fprintf(matchFile, "%s:%d\n", fn.Path, pos )
106+ lastPos = pos
117107 }
118108 }
119109 }
@@ -261,16 +251,16 @@ func (si *shardedIndex) doPostingQuery(query *index.Query) []string {
261251 return possible
262252}
263253
264- type entry struct {
265- fn string
266- pos uint32
254+ type fileMatches struct {
255+ fn string
256+ matches []index. Match
267257}
268258
269- func (si * shardedIndex ) doPostingQueryPos (query string ) []entry {
259+ func (si * shardedIndex ) doPostingQueryPos (query string ) []fileMatches {
270260 log .Printf ("doPostingQueryPos(%q)" , query )
271261 var (
272262 wg sync.WaitGroup
273- prefixed = make ([][]entry , len (si .shards ))
263+ prefixed = make ([][]fileMatches , len (si .shards ))
274264 )
275265 for i := range si .shards {
276266 wg .Add (1 )
@@ -281,16 +271,24 @@ func (si *shardedIndex) doPostingQueryPos(query string) []entry {
281271 if err != nil {
282272 log .Fatalf ("QueryPositional(%q): %v" , query , err )
283273 }
284- possible := make ([]entry , len (matches ))
285- for idx , match := range matches {
286- fn , err := ix .DocidMap .Lookup (match .Docid )
287- if err != nil {
288- log .Fatalf ("DocidMap.Lookup(%v): %v" , match .Docid , err )
274+ var possible []fileMatches
275+ for len (matches ) > 0 {
276+ docid := matches [0 ].Docid
277+ n := 1
278+ // Find all matches within this document (source file).
279+ for n < len (matches ) && matches [n ].Docid == docid {
280+ n ++
289281 }
290- possible [idx ] = entry {
291- fn : fn ,
292- pos : match .Position ,
282+
283+ fn , err := ix .DocidMap .Lookup (docid )
284+ if err != nil {
285+ log .Fatalf ("DocidMap.Lookup(%v): %v" , docid , err )
293286 }
287+ possible = append (possible , fileMatches {
288+ fn : fn ,
289+ matches : matches [:n ],
290+ })
291+ matches = matches [n :]
294292 }
295293 prefixed [i ] = possible
296294 }(i )
@@ -300,7 +298,7 @@ func (si *shardedIndex) doPostingQueryPos(query string) []entry {
300298 for _ , p := range prefixed {
301299 l += len (p )
302300 }
303- possible := make ([]entry , 0 , l )
301+ possible := make ([]fileMatches , 0 , l )
304302 for i := range si .shards {
305303 possible = append (possible , prefixed [i ]... )
306304 }
@@ -336,10 +334,10 @@ func (si *shardedIndex) measure(idx int, query string, pos, skipFile, skipGrep b
336334 if queryPos {
337335 possible := si .doPostingQueryPos (string (s .Rune ))
338336 files := make (ranking.ResultPaths , 0 , len (possible ))
339- for _ , entry := range possible {
337+ for idx , entry := range possible {
340338 result := ranking.ResultPath {
341339 Path : entry .fn ,
342- Position : int ( entry . pos ) ,
340+ MatchIdx : idx ,
343341 }
344342 result .Rank (si .rankingMap , & rankingopts )
345343 if result .Ranking > - 1 {
@@ -349,7 +347,7 @@ func (si *shardedIndex) measure(idx int, query string, pos, skipFile, skipGrep b
349347 files = sourcebackend .FilterByKeywords (& rewritten , files )
350348 m .PostingNano = int64 (time .Since (start ))
351349 if ! skipFile {
352- filesSearched , matches , err := verifyMatches (string (s .Rune ), files )
350+ filesSearched , matches , err := verifyMatches (string (s .Rune ), files , possible )
353351 if err != nil {
354352 return m , err
355353 }
0 commit comments