[PATCH] D49546: [clangd] Implement query iterators for Dex symbol index

Sam McCall via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Mon Jul 23 03:32:17 PDT 2018


sammccall added a comment.

A few more comments about the bits I understand, but waiting mostly on the documentation.



================
Comment at: clang-tools-extra/clangd/index/dex/QueryIterator.cpp:155
+  llvm::raw_ostream &dump(llvm::raw_ostream &OS) const override {
+    OS << "(&& ";
+    for (size_t Index = 0; Index < Children.size(); ++Index) {
----------------
nit: `&` should be enough?


================
Comment at: clang-tools-extra/clangd/index/dex/QueryIterator.cpp:175
+// FIXME(kbobyrev): This compares IDs of two iterators...
+auto CompareIterators = [](std::unique_ptr<QueryIterator> &Left,
+                           std::unique_ptr<QueryIterator> &Right) -> bool {
----------------
can this just be a static function?


================
Comment at: clang-tools-extra/clangd/index/dex/QueryIterator.cpp:196
+        });
+    std::make_heap(begin(Children), end(Children), CompareIterators);
+  }
----------------
can we start with the simple/obvious implementation, and add heap later if it actually improves performance?


================
Comment at: clang-tools-extra/clangd/index/dex/QueryIterator.cpp:257
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+                              const QueryIterator &Iterator) {
----------------
you can just inline this.

If you don't, you have to provide a declaration in the header, outside the class definition. (In addition to the friend declaration). GCC errors on this, clang ignores it (GCC is right).


================
Comment at: clang-tools-extra/clangd/index/dex/QueryIterator.h:28
+
+using DocID = size_t;
+using PostingList = std::vector<DocID>;
----------------
`uint32_t` should be plenty. These will be a large fraction of the index's memory usage. (Especially if we push actual payloads onto disk later)


================
Comment at: clang-tools-extra/clangd/index/dex/QueryIterator.h:41
+// FIXME(kbobyrev): Document this one properly.
+// FIXME(kbobyrev): Don't expose all the classes in the header, move classes to
+// header and only have constructors here.
----------------
this is done I think.


================
Comment at: clang-tools-extra/clangd/index/dex/QueryIterator.h:43
+// header and only have constructors here.
+class QueryIterator {
+public:
----------------
I'm not sure `Query` actually adds much to this class name. `Iterator`, `AndIterator`, etc would read more smoothly.


================
Comment at: clang-tools-extra/clangd/index/dex/QueryIterator.h:47
+  // instead?
+  virtual bool reachedEnd() const = 0;
+  virtual bool advance() = 0;
----------------
nit: this seems non-orthogonal, could we either:
 - have `advance()` and `advanceTo()` return void
 - or remove `reachedEnd()` and have owners that need to keep the state (and/or iterators) maintain it separately?


================
Comment at: clang-tools-extra/clangd/index/dex/QueryIterator.h:52
+  virtual DocID peek() const = 0;
+  virtual size_t cost() const = 0;
+
----------------
As discussed offline, please leave this out of the initial patch.
It requires quite some explanation and understanding, and seems likely to delay the review.


================
Comment at: clang-tools-extra/clangd/index/dex/QueryIterator.h:54
+
+  virtual llvm::raw_ostream &dump(llvm::raw_ostream &OS) const = 0;
+
----------------
private?


================
Comment at: clang-tools-extra/clangd/index/dex/QueryIterator.h:68
+std::unique_ptr<QueryIterator>
+constructAndIterator(std::vector<std::unique_ptr<QueryIterator>> &&Children);
+
----------------
nit: `newAndIterator` or just `andIterator`? brevity is the soul of wit and all that

Or even better, what about:

```
Iterator::createAnd(...)
Iterator::createOr(...)
Iterator::create(PostingList*)
```


================
Comment at: clang-tools-extra/clangd/index/dex/QueryIterator.h:68
+std::unique_ptr<QueryIterator>
+constructAndIterator(std::vector<std::unique_ptr<QueryIterator>> &&Children);
+
----------------
sammccall wrote:
> nit: `newAndIterator` or just `andIterator`? brevity is the soul of wit and all that
> 
> Or even better, what about:
> 
> ```
> Iterator::createAnd(...)
> Iterator::createOr(...)
> Iterator::create(PostingList*)
> ```
nit: pass by value rather than by rvalue-reference unless there's a strong reason.

Here, vector<u_p> isn't copyable, and there are no overloads, and this isn't performance-critical, so it should be fine.


================
Comment at: clang-tools-extra/unittests/clangd/DexIndexTests.cpp:19
+
+using std::make_shared;
+using std::max;
----------------
please spell these out (local style)


================
Comment at: clang-tools-extra/unittests/clangd/DexIndexTests.cpp:27
+
+using llvm::raw_string_ostream;
+
----------------
using namespace llvm


================
Comment at: clang-tools-extra/unittests/clangd/DexIndexTests.cpp:67
+
+  vector<unique_ptr<QueryIterator>> Children;
+
----------------
nit: just `auto And = constructAndIterator({constructDocumentIterator(EmptyList)})`

(and below in various places).
This actually seems nicer - the expression hierarchy reflects the iterator hierarchy.


================
Comment at: clang-tools-extra/unittests/clangd/DexIndexTests.cpp:75
+
+  string Dump;
+  raw_string_ostream OS(Dump);
----------------
just `EXPECT_EQ(to_string(*And), "(&& [])")`

You may need to `#include "llvm/Support/ScopedPrinters.h"`


================
Comment at: clang-tools-extra/unittests/clangd/DexIndexTests.cpp:98
+
+  EXPECT_EQ(And->reachedEnd(), false);
+  EXPECT_EQ(And->peek(), 0U);
----------------
add a helper function `vector<DocID> consume(Iterator&)`
(Maybe even to the main file rather than the tests).

Then this section (and some others) can just be `EXPECT_THAT(consume(*And), ElementsAre(0u,7u,10u,...))`


================
Comment at: clang-tools-extra/unittests/clangd/DexIndexTests.cpp:140
+
+  // More complicated example: nested And iterators.
+  //
----------------
Hmm, I'm not sure this approach scales - there shouldn't be anything special about composing and/and, compared to and/or, or/not, boost/and, etc.

I'd suggest testing each iterator directly, and then having one test that uses a more complex tree, and dropping this case.


================
Comment at: clang-tools-extra/unittests/clangd/DexIndexTests.cpp:324
+TEST(DexIndexIterators, QueryTree) {
+  // An example of more complicated query
+  //
----------------
This is too complicated. Try to use each iterator once or twice.
(We'll need to extend this when we add new iterator types)


https://reviews.llvm.org/D49546





More information about the cfe-commits mailing list