[PATCH] D88281: [clangd] Use Decision Forest to score code compeltions.

2020-09-28 Thread Adam Czachorowski via Phabricator via cfe-commits
adamcz added a comment.

Just noticed: typo in commit description - compeltions


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D88281/new/

https://reviews.llvm.org/D88281

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D88281: [clangd] Use Decision Forest to score code compeltions.

2020-09-28 Thread Utkarsh Saxena via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 294711.
usaxena95 marked an inline comment as done.
usaxena95 added a comment.

Added fixme for renaming evaluate() and fixed typo.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D88281/new/

https://reviews.llvm.org/D88281

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/CodeComplete.h
  clang-tools-extra/clangd/Quality.cpp
  clang-tools-extra/clangd/Quality.h
  clang-tools-extra/clangd/tool/ClangdMain.cpp
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp

Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -10,7 +10,6 @@
 #include "ClangdServer.h"
 #include "CodeComplete.h"
 #include "Compiler.h"
-#include "CompletionModel.h"
 #include "Matchers.h"
 #include "Protocol.h"
 #include "Quality.h"
@@ -163,14 +162,38 @@
   return S;
 }
 
-TEST(DecisionForestRuntime, SanityTest) {
-  using Example = clangd::Example;
-  using clangd::Evaluate;
-  Example E1;
-  E1.setContextKind(ContextKind::CCC_ArrowMemberAccess);
-  Example E2;
-  E2.setContextKind(ContextKind::CCC_SymbolOrNewName);
-  EXPECT_GT(Evaluate(E1), Evaluate(E2));
+TEST(DecisionForestRankingModel, NameMatchSanityTest) {
+  clangd::CodeCompleteOptions Opts;
+  Opts.RankingModel = CodeCompleteOptions::DecisionForest;
+  auto Results = completions(
+  R"cpp(
+struct MemberAccess {
+  int ABG();
+  int AlphaBetaGamma();
+};
+int func() { MemberAccess().ABG^ }
+)cpp",
+  /*IndexSymbols=*/{}, Opts);
+  EXPECT_THAT(Results.Completions,
+  ElementsAre(Named("ABG"), Named("AlphaBetaGamma")));
+}
+
+TEST(DecisionForestRankingModel, ReferencesAffectRanking) {
+  clangd::CodeCompleteOptions Opts;
+  Opts.RankingModel = CodeCompleteOptions::DecisionForest;
+  constexpr int NumReferences = 10;
+  EXPECT_THAT(
+  completions("int main() { clang^ }",
+  {ns("clangA"), withReferences(NumReferences, func("clangD"))},
+  Opts)
+  .Completions,
+  ElementsAre(Named("clangD"), Named("clangA")));
+  EXPECT_THAT(
+  completions("int main() { clang^ }",
+  {withReferences(NumReferences, ns("clangA")), func("clangD")},
+  Opts)
+  .Completions,
+  ElementsAre(Named("clangA"), Named("clangD")));
 }
 
 TEST(CompletionTest, Limit) {
Index: clang-tools-extra/clangd/tool/ClangdMain.cpp
===
--- clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ clang-tools-extra/clangd/tool/ClangdMain.cpp
@@ -167,6 +167,26 @@
 Hidden,
 };
 
+opt RankingModel{
+"ranking-model",
+cat(Features),
+desc("Model to use to rank code-completion items"),
+values(clEnumValN(CodeCompleteOptions::Heuristics, "heuristics",
+  "Use hueristics to rank code completion items"),
+   clEnumValN(CodeCompleteOptions::DecisionForest, "decision_forest",
+  "Use Decision Forest model to rank completion items")),
+init(CodeCompleteOptions().RankingModel),
+Hidden,
+};
+
+opt DecisionForestBase{
+"decision-forest-base",
+cat(Features),
+desc("Base for exponentiating the prediction from DecisionForest."),
+init(CodeCompleteOptions().DecisionForestBase),
+Hidden,
+};
+
 // FIXME: also support "plain" style where signatures are always omitted.
 enum CompletionStyleFlag { Detailed, Bundled };
 opt CompletionStyle{
@@ -739,6 +759,8 @@
   CCOpts.EnableFunctionArgSnippets = EnableFunctionArgSnippets;
   CCOpts.AllScopes = AllScopesCompletion;
   CCOpts.RunParser = CodeCompletionParse;
+  CCOpts.RankingModel = RankingModel;
+  CCOpts.DecisionForestBase = DecisionForestBase;
 
   RealThreadsafeFS TFS;
   std::vector> ProviderStack;
Index: clang-tools-extra/clangd/Quality.h
===
--- clang-tools-extra/clangd/Quality.h
+++ clang-tools-extra/clangd/Quality.h
@@ -77,6 +77,7 @@
   void merge(const CodeCompletionResult &SemaCCResult);
   void merge(const Symbol &IndexResult);
 
+  // FIXME(usx): Rename to evaluateHeuristics().
   // Condense these signals down to a single number, higher is better.
   float evaluate() const;
 };
@@ -136,6 +137,10 @@
   // Whether the item matches the type expected in the completion context.
   bool TypeMatchesPreferred = false;
 
+  /// Length of the unqualified partial name of Symbol typed in
+  /// CompletionPrefix.
+  unsigned FilterLength = 0;
+
   /// Set of derived signals computed by calculateDerivedSignals(). Must not be
   /// set explicitly.
   struct DerivedSignals {
@@ -161,6 +166,8 @@
 /// Combine symbol quality and relevance into a single score.
 float evaluateSymbolAndRelevance(float SymbolQuality, float SymbolRelevance);
 
+float ev

[PATCH] D88281: [clangd] Use Decision Forest to score code compeltions.

2020-09-28 Thread Adam Czachorowski via Phabricator via cfe-commits
adamcz accepted this revision.
adamcz added inline comments.



Comment at: clang-tools-extra/clangd/CodeComplete.cpp:1635
+case RM::Heuristics:
+  Scores.Quality = Quality.evaluate();
+  Scores.Relevance = Relevance.evaluate();

usaxena95 wrote:
> adamcz wrote:
> > Ideally we'd rename the evaluate() here, since SymbolQualitySignals is used 
> > for both heuristic and DecisionForest version, but evaluate is 
> > heuristic-specific. I think in pefect world this would be out of 
> > SymbolQualitySignals class (which would become just storage), but at least 
> > it should be renamed to evaluateUsingHeuristic().
> Right. I plan to do this but the changes for a rename would include unrelated 
> files. So I planed to do this another patch keeping this one tractable and 
> clean.
> Let me know if you want me to do it in this one itself.
Separate change sounds good.



Comment at: clang-tools-extra/clangd/tool/ClangdMain.cpp:185
+cat(Features),
+desc("Base for exponentiating the prediction from DecsionForest."),
+init(CodeCompleteOptions().DecisionForestBase),

typo: Decsion


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D88281/new/

https://reviews.llvm.org/D88281

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D88281: [clangd] Use Decision Forest to score code compeltions.

2020-09-28 Thread Utkarsh Saxena via Phabricator via cfe-commits
usaxena95 added a comment.

If we just consider ranking, there are not many code paths. Most of the code 
paths are for gathering and creating code completion items.
In the end all the code paths end up in the `addCandidate` method to get 
`scored` either by heuristics or by decision forest.
So I have added 2 tests for checking sanity and exercising the code path.




Comment at: clang-tools-extra/clangd/CodeComplete.cpp:1635
+case RM::Heuristics:
+  Scores.Quality = Quality.evaluate();
+  Scores.Relevance = Relevance.evaluate();

adamcz wrote:
> Ideally we'd rename the evaluate() here, since SymbolQualitySignals is used 
> for both heuristic and DecisionForest version, but evaluate is 
> heuristic-specific. I think in pefect world this would be out of 
> SymbolQualitySignals class (which would become just storage), but at least it 
> should be renamed to evaluateUsingHeuristic().
Right. I plan to do this but the changes for a rename would include unrelated 
files. So I planed to do this another patch keeping this one tractable and 
clean.
Let me know if you want me to do it in this one itself.



Comment at: clang-tools-extra/clangd/CodeComplete.cpp:1655
+  // NameMatch should be a multiplier on total score to support rescoring.
+  Scores.Total = Relevance.NameMatch * Scores.ExcludingName;
+  return Scores;

adamcz wrote:
> Could we make the weight of Relevance.NameMatch configurable, maybe through 
> CodeCompletionOptions or such? I'm worried it may dominate the score too much 
> and being able to configure this would allow us to run experiments easily.
Since this is multiplicative, I don't think it is possible to weigh NameMatch.
Although we can weigh the contribution of DF prediction.
Did some maths and realised that the `base` in `pow(base, Evaluate(E))` can 
effectively represent the weightage given to DF Model.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D88281/new/

https://reviews.llvm.org/D88281

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D88281: [clangd] Use Decision Forest to score code compeltions.

2020-09-28 Thread Utkarsh Saxena via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 294684.
usaxena95 marked 2 inline comments as done.
usaxena95 added a comment.

Addressed comments.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D88281/new/

https://reviews.llvm.org/D88281

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/CodeComplete.h
  clang-tools-extra/clangd/Quality.cpp
  clang-tools-extra/clangd/Quality.h
  clang-tools-extra/clangd/tool/ClangdMain.cpp
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp

Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -10,7 +10,6 @@
 #include "ClangdServer.h"
 #include "CodeComplete.h"
 #include "Compiler.h"
-#include "CompletionModel.h"
 #include "Matchers.h"
 #include "Protocol.h"
 #include "Quality.h"
@@ -163,14 +162,38 @@
   return S;
 }
 
-TEST(DecisionForestRuntime, SanityTest) {
-  using Example = clangd::Example;
-  using clangd::Evaluate;
-  Example E1;
-  E1.setContextKind(ContextKind::CCC_ArrowMemberAccess);
-  Example E2;
-  E2.setContextKind(ContextKind::CCC_SymbolOrNewName);
-  EXPECT_GT(Evaluate(E1), Evaluate(E2));
+TEST(DecisionForestRankingModel, NameMatchSanityTest) {
+  clangd::CodeCompleteOptions Opts;
+  Opts.RankingModel = CodeCompleteOptions::DecisionForest;
+  auto Results = completions(
+  R"cpp(
+struct MemberAccess {
+  int ABG();
+  int AlphaBetaGamma();
+};
+int func() { MemberAccess().ABG^ }
+)cpp",
+  /*IndexSymbols=*/{}, Opts);
+  EXPECT_THAT(Results.Completions,
+  ElementsAre(Named("ABG"), Named("AlphaBetaGamma")));
+}
+
+TEST(DecisionForestRankingModel, ReferencesAffectRanking) {
+  clangd::CodeCompleteOptions Opts;
+  Opts.RankingModel = CodeCompleteOptions::DecisionForest;
+  constexpr int NumReferences = 10;
+  EXPECT_THAT(
+  completions("int main() { clang^ }",
+  {ns("clangA"), withReferences(NumReferences, func("clangD"))},
+  Opts)
+  .Completions,
+  ElementsAre(Named("clangD"), Named("clangA")));
+  EXPECT_THAT(
+  completions("int main() { clang^ }",
+  {withReferences(NumReferences, ns("clangA")), func("clangD")},
+  Opts)
+  .Completions,
+  ElementsAre(Named("clangA"), Named("clangD")));
 }
 
 TEST(CompletionTest, Limit) {
Index: clang-tools-extra/clangd/tool/ClangdMain.cpp
===
--- clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ clang-tools-extra/clangd/tool/ClangdMain.cpp
@@ -167,6 +167,26 @@
 Hidden,
 };
 
+opt RankingModel{
+"ranking-model",
+cat(Features),
+desc("Model to use to rank code-completion items"),
+values(clEnumValN(CodeCompleteOptions::Heuristics, "heuristics",
+  "Use hueristics to rank code completion items"),
+   clEnumValN(CodeCompleteOptions::DecisionForest, "decision_forest",
+  "Use Decision Forest model to rank completion items")),
+init(CodeCompleteOptions().RankingModel),
+Hidden,
+};
+
+opt DecisionForestBase{
+"decision-forest-base",
+cat(Features),
+desc("Base for exponentiating the prediction from DecsionForest."),
+init(CodeCompleteOptions().DecisionForestBase),
+Hidden,
+};
+
 // FIXME: also support "plain" style where signatures are always omitted.
 enum CompletionStyleFlag { Detailed, Bundled };
 opt CompletionStyle{
@@ -739,6 +759,8 @@
   CCOpts.EnableFunctionArgSnippets = EnableFunctionArgSnippets;
   CCOpts.AllScopes = AllScopesCompletion;
   CCOpts.RunParser = CodeCompletionParse;
+  CCOpts.RankingModel = RankingModel;
+  CCOpts.DecisionForestBase = DecisionForestBase;
 
   RealThreadsafeFS TFS;
   std::vector> ProviderStack;
Index: clang-tools-extra/clangd/Quality.h
===
--- clang-tools-extra/clangd/Quality.h
+++ clang-tools-extra/clangd/Quality.h
@@ -136,6 +136,10 @@
   // Whether the item matches the type expected in the completion context.
   bool TypeMatchesPreferred = false;
 
+  /// Length of the unqualified partial name of Symbol typed in
+  /// CompletionPrefix.
+  unsigned FilterLength = 0;
+
   /// Set of derived signals computed by calculateDerivedSignals(). Must not be
   /// set explicitly.
   struct DerivedSignals {
@@ -161,6 +165,8 @@
 /// Combine symbol quality and relevance into a single score.
 float evaluateSymbolAndRelevance(float SymbolQuality, float SymbolRelevance);
 
+float evaluateDecisionForest(const SymbolQualitySignals &Quality,
+ const SymbolRelevanceSignals &Relevance);
 /// TopN is a lossy container that preserves only the "best" N elements.
 template > class TopN {
 public:
Index: clang-tools-extra/clangd/Quality.cpp
===

[PATCH] D88281: [clangd] Use Decision Forest to score code compeltions.

2020-09-25 Thread Adam Czachorowski via Phabricator via cfe-commits
adamcz accepted this revision.
adamcz added a comment.
This revision is now accepted and ready to land.

Could you add a test that sets this flag? Perhaps we can run 
CodeCompletionTests.cpp twice, once with this flag, once without? Just to 
exercise these code paths, I think most expectations there are unordered, so it 
should work?




Comment at: clang-tools-extra/clangd/CodeComplete.cpp:1635
+case RM::Heuristics:
+  Scores.Quality = Quality.evaluate();
+  Scores.Relevance = Relevance.evaluate();

Ideally we'd rename the evaluate() here, since SymbolQualitySignals is used for 
both heuristic and DecisionForest version, but evaluate is heuristic-specific. 
I think in pefect world this would be out of SymbolQualitySignals class (which 
would become just storage), but at least it should be renamed to 
evaluateUsingHeuristic().



Comment at: clang-tools-extra/clangd/CodeComplete.cpp:1655
+  // NameMatch should be a multiplier on total score to support rescoring.
+  Scores.Total = Relevance.NameMatch * Scores.ExcludingName;
+  return Scores;

Could we make the weight of Relevance.NameMatch configurable, maybe through 
CodeCompletionOptions or such? I'm worried it may dominate the score too much 
and being able to configure this would allow us to run experiments easily.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D88281/new/

https://reviews.llvm.org/D88281

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D88281: [clangd] Use Decision Forest to score code compeltions.

2020-09-25 Thread Utkarsh Saxena via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 294281.
usaxena95 added a comment.

Moved DF evaluation to Quality.cpp


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D88281/new/

https://reviews.llvm.org/D88281

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/CodeComplete.h
  clang-tools-extra/clangd/Quality.cpp
  clang-tools-extra/clangd/Quality.h
  clang-tools-extra/clangd/tool/ClangdMain.cpp

Index: clang-tools-extra/clangd/tool/ClangdMain.cpp
===
--- clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ clang-tools-extra/clangd/tool/ClangdMain.cpp
@@ -167,6 +167,18 @@
 Hidden,
 };
 
+opt RankingModel{
+"ranking-model",
+cat(Features),
+desc("Model to use to rank code-completion items"),
+values(clEnumValN(CodeCompleteOptions::Heuristics, "heuristic",
+  "Use hueristics to rank code completion items"),
+   clEnumValN(CodeCompleteOptions::DecisionForest, "df",
+  "Use Decision Forest model to rank completion items")),
+init(CodeCompleteOptions().RankingModel),
+Hidden,
+};
+
 // FIXME: also support "plain" style where signatures are always omitted.
 enum CompletionStyleFlag { Detailed, Bundled };
 opt CompletionStyle{
@@ -739,6 +751,7 @@
   CCOpts.EnableFunctionArgSnippets = EnableFunctionArgSnippets;
   CCOpts.AllScopes = AllScopesCompletion;
   CCOpts.RunParser = CodeCompletionParse;
+  CCOpts.RankingModel = RankingModel;
 
   RealThreadsafeFS TFS;
   std::vector> ProviderStack;
Index: clang-tools-extra/clangd/Quality.h
===
--- clang-tools-extra/clangd/Quality.h
+++ clang-tools-extra/clangd/Quality.h
@@ -136,6 +136,10 @@
   // Whether the item matches the type expected in the completion context.
   bool TypeMatchesPreferred = false;
 
+  /// Length of the unqualified partial name of Symbol typed in
+  /// CompletionPrefix.
+  unsigned FilterLength = 0;
+
   /// Set of derived signals computed by calculateDerivedSignals(). Must not be
   /// set explicitly.
   struct DerivedSignals {
@@ -161,6 +165,8 @@
 /// Combine symbol quality and relevance into a single score.
 float evaluateSymbolAndRelevance(float SymbolQuality, float SymbolRelevance);
 
+float evaluateDecisionForest(const SymbolQualitySignals &Quality,
+ const SymbolRelevanceSignals &Relevance);
 /// TopN is a lossy container that preserves only the "best" N elements.
 template > class TopN {
 public:
Index: clang-tools-extra/clangd/Quality.cpp
===
--- clang-tools-extra/clangd/Quality.cpp
+++ clang-tools-extra/clangd/Quality.cpp
@@ -8,6 +8,7 @@
 
 #include "Quality.h"
 #include "AST.h"
+#include "CompletionModel.h"
 #include "FileDistance.h"
 #include "SourceCode.h"
 #include "URI.h"
@@ -486,6 +487,33 @@
   return SymbolQuality * SymbolRelevance;
 }
 
+float evaluateDecisionForest(const SymbolQualitySignals &Quality,
+ const SymbolRelevanceSignals &Relevance) {
+  Example E;
+  E.setIsDeprecated(Quality.Deprecated);
+  E.setIsReservedName(Quality.ReservedName);
+  E.setIsImplementationDetail(Quality.ImplementationDetail);
+  E.setNumReferences(Quality.References);
+  E.setSymbolCategory(Quality.Category);
+
+  SymbolRelevanceSignals::DerivedSignals Derived =
+  Relevance.calculateDerivedSignals();
+  E.setIsNameInContext(Derived.NameMatchesContext);
+  E.setIsForbidden(Relevance.Forbidden);
+  E.setIsInBaseClass(Relevance.InBaseClass);
+  E.setFileProximityDistance(Derived.FileProximityDistance);
+  E.setSemaFileProximityScore(Relevance.SemaFileProximityScore);
+  E.setSymbolScopeDistance(Derived.ScopeProximityDistance);
+  E.setSemaSaysInScope(Relevance.SemaSaysInScope);
+  E.setScope(Relevance.Scope);
+  E.setContextKind(Relevance.Context);
+  E.setIsInstanceMember(Relevance.IsInstanceMember);
+  E.setHadContextType(Relevance.HadContextType);
+  E.setHadSymbolType(Relevance.HadSymbolType);
+  E.setTypeMatchesPreferred(Relevance.TypeMatchesPreferred);
+  E.setFilterLength(Relevance.FilterLength);
+  return Evaluate(E);
+}
 // Produces an integer that sorts in the same order as F.
 // That is: a < b <==> encodeFloat(a) < encodeFloat(b).
 static uint32_t encodeFloat(float F) {
Index: clang-tools-extra/clangd/CodeComplete.h
===
--- clang-tools-extra/clangd/CodeComplete.h
+++ clang-tools-extra/clangd/CodeComplete.h
@@ -147,6 +147,12 @@
   std::function
   RecordCCResult;
+
+  /// Model to use for ranking code completion candidates.
+  enum CodeCompletionRankingModel {
+Heuristics,
+DecisionForest,
+  } RankingModel = Heuristics;
 };
 
 // Semi-structured representation of a code-complete suggestion for our C++ API.
Index: clang-tools-extra/clangd/CodeComplete.cpp
==

[PATCH] D88281: [clangd] Use Decision Forest to score code compeltions.

2020-09-25 Thread Utkarsh Saxena via Phabricator via cfe-commits
usaxena95 created this revision.
Herald added subscribers: cfe-commits, kadircet, arphaman, mgrang.
Herald added a project: clang.
usaxena95 requested review of this revision.
Herald added subscribers: MaskRay, ilya-biryukov.

By default clangd scores a code completion item using heuristic model.
Scoring can be done by Decision Forest by passing --ranking_model=df to
clangd.

TODO:

- Explain and backup the heuristic for combining NameMatch and DF prediction.
- Maybe add tests for sanity.
- Add end-to-end latency metrics.
- Add extra debug logging for the DF model.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D88281

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/CodeComplete.h
  clang-tools-extra/clangd/tool/ClangdMain.cpp
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp

Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -26,6 +26,8 @@
 #include "clang/Tooling/CompilationDatabase.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/Path.h"
+#include "llvm/Support/Timer.h"
+#include "llvm/Support/raw_ostream.h"
 #include "llvm/Testing/Support/Annotations.h"
 #include "llvm/Testing/Support/Error.h"
 #include "gmock/gmock.h"
@@ -33,6 +35,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 namespace clang {
@@ -648,6 +651,76 @@
 Has("bar", CompletionItemKind::Function)));
 }
 
+/*
+TEST(CompletionTest, DO_NOT_SUBMIT_SpeedTestForReviewOnly) {
+
+  auto randFunction = []() {
+std::stringstream ss;
+ss << "void ";
+for (int i = 0; i < 10; ++i)
+  ss << char(rand() % 3 == 0 ? 'a' + rand() % 3 : 'A' + rand() % 3);
+ss << "();\n";
+return ss.str();
+  };
+  int Trials = 1;
+  std::vector IndexedResults;
+  IndexedResults.push_back(cls({"ns::ABCDabc"}));
+  IndexedResults.push_back(cls({"ns::abcABC"}));
+
+  std::string code = R"cpp(
+  namespace ns {
+void abc();
+)cpp";
+  for (int i = 0; i < 50; ++i)
+code += randFunction();
+  code += "namepsace ns2 {\n";
+  for (int i = 0; i < 50; ++i)
+code += randFunction();
+  code += "} //namespace ns2\n";
+  code += R"cpp(} // namespace ns
+  void f() { abc^ }
+   )cpp";
+  llvm::errs() << code << "\n";
+
+  CodeCompleteOptions Opts;
+  Opts.AllScopes = true;
+
+  llvm::Timer DF("DF", "Decision Forest");
+  llvm::Timer Heuristic("Heuristic", "Heuristic ranking.");
+
+  Opts.RankingModel = CodeCompleteOptions::DecisionForest;
+  DF.startTimer();
+  auto DFCompletions = completions(code, IndexedResults, Opts);
+  for (int i = 0; i < Trials; ++i)
+completions(code, IndexedResults, Opts);
+  DF.stopTimer();
+
+  Opts.RankingModel = CodeCompleteOptions::Heuristic;
+  Heuristic.startTimer();
+  auto HeuristicCompletions = completions(code, IndexedResults, Opts);
+  for (int i = 0; i < Trials; ++i)
+completions(code, IndexedResults, Opts);
+  Heuristic.stopTimer();
+
+  for (const auto &M : {DFCompletions, HeuristicCompletions}) {
+auto S = M.Completions;
+std::sort(S.begin(), S.end(),
+  [&](const CodeCompletion &a, const CodeCompletion &b) {
+return a.Score.Total > b.Score.Total ||
+   (a.Score.Total == b.Score.Total && a.Name < b.Name);
+  });
+int r = 0;
+for (const auto &C : S) {
+  llvm::errs() << r++ << ".\t" << C.Scope << " " << C.Name << " "
+   << C.Score.Total << " / " << C.Score.ExcludingName
+   << "\t\tNameMatch = "
+   << C.Score.Total / C.Score.ExcludingName << "\n";
+}
+llvm::errs() << "\n\n";
+  }
+  EXPECT_LT(int(DFCompletions.Completions.size()), 0LL);
+}
+*/
 TEST(CompletionTest, SemaIndexMerge) {
   auto Results = completions(
   R"cpp(
Index: clang-tools-extra/clangd/tool/ClangdMain.cpp
===
--- clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ clang-tools-extra/clangd/tool/ClangdMain.cpp
@@ -167,6 +167,18 @@
 Hidden,
 };
 
+opt RankingModel{
+"ranking-model",
+cat(Features),
+desc("Model to use to rank code-completion items"),
+values(clEnumValN(CodeCompleteOptions::Heuristic, "heuristic",
+  "Use hueristics to rank code completion items"),
+   clEnumValN(CodeCompleteOptions::DecisionForest, "df",
+  "Use Decision Forest model to rank completion items")),
+init(CodeCompleteOptions().RankingModel),
+Hidden,
+};
+
 // FIXME: also support "plain" style where signatures are always omitted.
 enum CompletionStyleFlag { Detailed, Bundled };
 opt CompletionStyle{
@@ -739,6 +751,7 @@
   CCOpts.EnableFunctionArgSnippets = EnableFunctionArgSnippets;
   CCOpts.AllScopes = AllScopesCompletion;
   CCOpts.RunParser = CodeCompletionParse;