Lucene - Core
  1. Lucene - Core
  2. LUCENE-6218

don't decode freqs or enumerate all positions, when scores are not needed

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 5.1, 6.0
    • Component/s: None
    • Labels:
      None
    • Lucene Fields:
      New

      Description

      Today if you don't call score() some things are faster, we won't invoke similarity or read the norm for the document or other things.

      On the other hand, its sad in this case that we are decompressing twice as many packed integers as we need (freqs can be skipped over, and our postings lists supports that) and walking all positions in phrase matching to determine the number of times the phrase matched (1 is enough, then we can stop).

      When scoring is not needed, things can be optimized in other cases too (e.g. thats the whole concept of filters).

      1. LUCENE-6218.patch
        116 kB
        Robert Muir
      2. LUCENE-6218.patch
        108 kB
        Robert Muir
      3. LUCENE-6218.patch
        95 kB
        Robert Muir

        Activity

        Hide
        Robert Muir added a comment -

        Here is a prototype patch: we pass a boolean to Weight.scorer(). Its initial value is set by IndexSearcher, based on the collector. E.g. you are sorting by price, or just counting the number of this, then its false.

        We also pass false from QueryWrapperFilter, ConstantScoreQuery, and MUST_NOT clauses in BooleanQuery.

        Show
        Robert Muir added a comment - Here is a prototype patch: we pass a boolean to Weight.scorer(). Its initial value is set by IndexSearcher, based on the collector. E.g. you are sorting by price, or just counting the number of this, then its false. We also pass false from QueryWrapperFilter, ConstantScoreQuery, and MUST_NOT clauses in BooleanQuery.
        Hide
        Alan Woodward added a comment -

        This is part of what I was trying to do in LUCENE-2878: Weight.scorer() has an extra flag that describes what postings should be decoded. So you can say if you just want docs only, or freqs, or positions, or whatever.

        Show
        Alan Woodward added a comment - This is part of what I was trying to do in LUCENE-2878 : Weight.scorer() has an extra flag that describes what postings should be decoded. So you can say if you just want docs only, or freqs, or positions, or whatever.
        Hide
        Adrien Grand added a comment -

        +1 This has the potential to simplify/improve lots of things, eg. remove TermFilter which does not being any improvement anymore compared to TermQuery, or run prohibited clauses through BooleanScorer.

        Show
        Adrien Grand added a comment - +1 This has the potential to simplify/improve lots of things, eg. remove TermFilter which does not being any improvement anymore compared to TermQuery, or run prohibited clauses through BooleanScorer.
        Hide
        Alan Woodward added a comment -

        Which is to say that I think this is a great idea, but it would be nice if the extra value passed to scorer() is an int, rather than a boolean, as that allows for more extensibility. But that might need LUCENE-4524 to be committed first, as that unifies the flags on DocsEnum and DocsAndPositionsEnum, without which the simple integer flag doesn't make sense.

        Show
        Alan Woodward added a comment - Which is to say that I think this is a great idea, but it would be nice if the extra value passed to scorer() is an int, rather than a boolean, as that allows for more extensibility. But that might need LUCENE-4524 to be committed first, as that unifies the flags on DocsEnum and DocsAndPositionsEnum, without which the simple integer flag doesn't make sense.
        Hide
        Robert Muir added a comment -

        Alan, yes i saw that.

        But I think we should design for today, I dont think we should make elaborate apis extensible to the future. If we want it to be an integer flag later, we can just change it.

        Show
        Robert Muir added a comment - Alan, yes i saw that. But I think we should design for today, I dont think we should make elaborate apis extensible to the future. If we want it to be an integer flag later, we can just change it.
        Hide
        Alan Woodward added a comment -

        Oh, sure. I'm sort of hoping that the future in this case means this week, though . Just want to make sure we're not stepping on each other's toes.

        Show
        Alan Woodward added a comment - Oh, sure. I'm sort of hoping that the future in this case means this week, though . Just want to make sure we're not stepping on each other's toes.
        Hide
        Michael McCandless added a comment -

        +1, awesome

        Show
        Michael McCandless added a comment - +1, awesome
        Hide
        Robert Muir added a comment -

        Well, i'm not sure merging docsenum and docsandpositionsenum is related. The scoring api still has no concept of positions with that change, and there is no optimization to implement in any of the scorers (yet), so I think we can defer whether the boolean needs to be upgraded to an int, in other issues, when we have real use cases to use it?

        In this case we are just saying up-front that we don't need the score to speed up queries we have today.

        And we have a few use cases right now that can be sped up by the change, e.g. sorting by something other than score, boolean MUST_NOT, constant score queries, filters, etc. I only implemented the optimization for terms and exact phrases, but we could do it for sloppy phrases, spans, etc too.

        Show
        Robert Muir added a comment - Well, i'm not sure merging docsenum and docsandpositionsenum is related. The scoring api still has no concept of positions with that change, and there is no optimization to implement in any of the scorers (yet), so I think we can defer whether the boolean needs to be upgraded to an int, in other issues, when we have real use cases to use it? In this case we are just saying up-front that we don't need the score to speed up queries we have today. And we have a few use cases right now that can be sped up by the change, e.g. sorting by something other than score, boolean MUST_NOT, constant score queries, filters, etc. I only implemented the optimization for terms and exact phrases, but we could do it for sloppy phrases, spans, etc too.
        Hide
        Alan Woodward added a comment -

        yeah, that'll be in later issues. +1 to commit this one then.

        Show
        Alan Woodward added a comment - yeah, that'll be in later issues. +1 to commit this one then.
        Hide
        Robert Muir added a comment -

        Here is the standard benchmark. You can see the optimization happening for the MUST_NOT clauses:

                            Task   QPS trunk      StdDev   QPS patch      StdDev                Pct diff
                    OrHighNotLow      108.19      (4.1%)      105.11      (6.7%)   -2.8% ( -13% -    8%)
                    OrHighNotMed       89.28      (3.7%)       87.15      (6.3%)   -2.4% ( -11% -    7%)
                        HighTerm      120.82      (5.1%)      118.25      (6.1%)   -2.1% ( -12% -    9%)
                         MedTerm      177.26      (4.8%)      173.98      (5.8%)   -1.9% ( -11% -    9%)
                         LowTerm      950.16      (4.4%)      934.26      (4.6%)   -1.7% ( -10% -    7%)
                   OrHighNotHigh       29.55      (3.2%)       29.14      (5.7%)   -1.4% (  -9% -    7%)
                     MedSpanNear      144.83      (3.7%)      143.30      (4.5%)   -1.1% (  -8% -    7%)
                        Wildcard       45.54      (5.3%)       45.17      (6.1%)   -0.8% ( -11% -   11%)
                         Prefix3      214.45      (5.5%)      213.06      (7.6%)   -0.6% ( -13% -   13%)
                     LowSpanNear       28.04      (2.7%)       27.86      (3.3%)   -0.6% (  -6% -    5%)
                      AndHighLow     1171.37      (2.4%)     1165.20      (3.0%)   -0.5% (  -5% -    5%)
                    HighSpanNear      144.44      (3.9%)      143.73      (5.0%)   -0.5% (  -9% -    8%)
                   OrNotHighHigh       49.49      (3.2%)       49.25      (5.8%)   -0.5% (  -9% -    8%)
                          IntNRQ        8.45      (7.7%)        8.41     (10.3%)   -0.5% ( -17% -   19%)
                     AndHighHigh       88.18      (1.6%)       87.78      (1.9%)   -0.5% (  -3% -    3%)
                      AndHighMed      123.35      (1.7%)      123.11      (1.8%)   -0.2% (  -3% -    3%)
                         Respell       89.47      (1.9%)       89.44      (1.4%)   -0.0% (  -3% -    3%)
                          Fuzzy1      109.20      (1.8%)      109.63      (1.3%)    0.4% (  -2% -    3%)
                          Fuzzy2       67.56      (2.1%)       67.85      (1.5%)    0.4% (  -3% -    4%)
                       LowPhrase       34.54      (2.0%)       34.76      (1.9%)    0.6% (  -3% -    4%)
                 LowSloppyPhrase      119.91      (2.6%)      120.75      (2.4%)    0.7% (  -4% -    5%)
                      OrHighHigh       27.37      (9.3%)       27.71      (8.6%)    1.2% ( -15% -   21%)
                       OrHighMed       58.23      (8.7%)       58.97      (8.0%)    1.3% ( -14% -   19%)
                       OrHighLow       56.42      (8.7%)       57.23      (7.9%)    1.4% ( -13% -   19%)
                 MedSloppyPhrase       15.92      (4.0%)       16.19      (4.3%)    1.7% (  -6% -   10%)
                HighSloppyPhrase       13.52     (12.1%)       13.77      (8.6%)    1.9% ( -16% -   25%)
                      HighPhrase       17.50      (4.5%)       17.99      (4.2%)    2.8% (  -5% -   12%)
                       MedPhrase      253.02      (5.7%)      261.32      (6.1%)    3.3% (  -8% -   15%)
                    OrNotHighMed      185.01      (1.9%)      205.45      (3.6%)   11.0% (   5% -   16%)
                    OrNotHighLow      959.96      (2.2%)     1144.49      (3.5%)   19.2% (  13% -   25%)
        
        Show
        Robert Muir added a comment - Here is the standard benchmark. You can see the optimization happening for the MUST_NOT clauses: Task QPS trunk StdDev QPS patch StdDev Pct diff OrHighNotLow 108.19 (4.1%) 105.11 (6.7%) -2.8% ( -13% - 8%) OrHighNotMed 89.28 (3.7%) 87.15 (6.3%) -2.4% ( -11% - 7%) HighTerm 120.82 (5.1%) 118.25 (6.1%) -2.1% ( -12% - 9%) MedTerm 177.26 (4.8%) 173.98 (5.8%) -1.9% ( -11% - 9%) LowTerm 950.16 (4.4%) 934.26 (4.6%) -1.7% ( -10% - 7%) OrHighNotHigh 29.55 (3.2%) 29.14 (5.7%) -1.4% ( -9% - 7%) MedSpanNear 144.83 (3.7%) 143.30 (4.5%) -1.1% ( -8% - 7%) Wildcard 45.54 (5.3%) 45.17 (6.1%) -0.8% ( -11% - 11%) Prefix3 214.45 (5.5%) 213.06 (7.6%) -0.6% ( -13% - 13%) LowSpanNear 28.04 (2.7%) 27.86 (3.3%) -0.6% ( -6% - 5%) AndHighLow 1171.37 (2.4%) 1165.20 (3.0%) -0.5% ( -5% - 5%) HighSpanNear 144.44 (3.9%) 143.73 (5.0%) -0.5% ( -9% - 8%) OrNotHighHigh 49.49 (3.2%) 49.25 (5.8%) -0.5% ( -9% - 8%) IntNRQ 8.45 (7.7%) 8.41 (10.3%) -0.5% ( -17% - 19%) AndHighHigh 88.18 (1.6%) 87.78 (1.9%) -0.5% ( -3% - 3%) AndHighMed 123.35 (1.7%) 123.11 (1.8%) -0.2% ( -3% - 3%) Respell 89.47 (1.9%) 89.44 (1.4%) -0.0% ( -3% - 3%) Fuzzy1 109.20 (1.8%) 109.63 (1.3%) 0.4% ( -2% - 3%) Fuzzy2 67.56 (2.1%) 67.85 (1.5%) 0.4% ( -3% - 4%) LowPhrase 34.54 (2.0%) 34.76 (1.9%) 0.6% ( -3% - 4%) LowSloppyPhrase 119.91 (2.6%) 120.75 (2.4%) 0.7% ( -4% - 5%) OrHighHigh 27.37 (9.3%) 27.71 (8.6%) 1.2% ( -15% - 21%) OrHighMed 58.23 (8.7%) 58.97 (8.0%) 1.3% ( -14% - 19%) OrHighLow 56.42 (8.7%) 57.23 (7.9%) 1.4% ( -13% - 19%) MedSloppyPhrase 15.92 (4.0%) 16.19 (4.3%) 1.7% ( -6% - 10%) HighSloppyPhrase 13.52 (12.1%) 13.77 (8.6%) 1.9% ( -16% - 25%) HighPhrase 17.50 (4.5%) 17.99 (4.2%) 2.8% ( -5% - 12%) MedPhrase 253.02 (5.7%) 261.32 (6.1%) 3.3% ( -8% - 15%) OrNotHighMed 185.01 (1.9%) 205.45 (3.6%) 11.0% ( 5% - 16%) OrNotHighLow 959.96 (2.2%) 1144.49 (3.5%) 19.2% ( 13% - 25%)
        Hide
        Robert Muir added a comment -

        complete patch. I also added simple tests.

        Show
        Robert Muir added a comment - complete patch. I also added simple tests.
        Hide
        Robert Muir added a comment -

        Hooked into more tests so we can be sure docids are correct with flag on/off.

        BooleanQuery discards optional clauses when MSM=0 and scoring isn't required. Added early-exit logic to SloppyPhraseScorer, like ExactPhraseScorer. Fixed a case where Lucene50PF would return 0 here (since things already rely on it returning 1).

        I think its ready.

        Show
        Robert Muir added a comment - Hooked into more tests so we can be sure docids are correct with flag on/off. BooleanQuery discards optional clauses when MSM=0 and scoring isn't required. Added early-exit logic to SloppyPhraseScorer, like ExactPhraseScorer. Fixed a case where Lucene50PF would return 0 here (since things already rely on it returning 1). I think its ready.
        Hide
        Michael McCandless added a comment -

        +1

        Show
        Michael McCandless added a comment - +1
        Hide
        Ryan Ernst added a comment -

        +1

        Show
        Ryan Ernst added a comment - +1
        Hide
        Adrien Grand added a comment -

        +1

        Show
        Adrien Grand added a comment - +1
        Hide
        ASF subversion and git services added a comment -

        Commit 1657554 from Robert Muir in branch 'dev/trunk'
        [ https://svn.apache.org/r1657554 ]

        LUCENE-6218: don't decode freqs or enumerate all positions when scoring is not needed

        Show
        ASF subversion and git services added a comment - Commit 1657554 from Robert Muir in branch 'dev/trunk' [ https://svn.apache.org/r1657554 ] LUCENE-6218 : don't decode freqs or enumerate all positions when scoring is not needed
        Hide
        ASF subversion and git services added a comment -

        Commit 1657571 from Robert Muir in branch 'dev/branches/branch_5x'
        [ https://svn.apache.org/r1657571 ]

        LUCENE-6218: don't decode freqs or enumerate all positions when scoring is not needed

        Show
        ASF subversion and git services added a comment - Commit 1657571 from Robert Muir in branch 'dev/branches/branch_5x' [ https://svn.apache.org/r1657571 ] LUCENE-6218 : don't decode freqs or enumerate all positions when scoring is not needed
        Hide
        Timothy Potter added a comment -

        Bulk close after 5.1 release

        Show
        Timothy Potter added a comment - Bulk close after 5.1 release

          People

          • Assignee:
            Unassigned
            Reporter:
            Robert Muir
          • Votes:
            0 Vote for this issue
            Watchers:
            7 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development