Details
- Reviewers
dberris dblaikie - Commits
- rGb5600b58a0d8: [XRay][graph] Disambiguate name of type from member name
rG6c97b3acda3e: [XRay] A graph Class for the llvm-xray graph
rG2957c25a5ebf: [XRay] A graph Class for the llvm-xray graph
rL294722: [XRay][graph] Disambiguate name of type from member name
rL294717: [XRay] A graph Class for the llvm-xray graph
rL294713: [XRay] A graph Class for the llvm-xray graph
Diff Detail
- Repository
- rL LLVM
Event Timeline
include/llvm/XRay/Graph.h | ||
---|---|---|
402–405 ↗ | (On Diff #86541) | Does two lookups (count and insert). Avoid that if you can (usually by using "insert" and checking the bool element of the pair returned) |
414–417 ↗ | (On Diff #86541) | Similar double lookup |
496–514 ↗ | (On Diff #86541) | Could use the unified assignment operator if you like, maybe (pass by value, then swap) |
528–529 ↗ | (On Diff #86541) | calling insert might be more obvious. Explicitly calling operator overloads is generally a bit 'weird'. |
Aside from addressing @dblaikie's comments, please also make sure that the documentation questions raised earlier are addressed too.
Marking this with "Requested Changes" to remove from my "needs review" list.
include/llvm/XRay/Graph.h | ||
---|---|---|
366 ↗ | (On Diff #86541) | Please do not use names that start with _. |
369 ↗ | (On Diff #86541) | This section s already public, why the repetition here? |
tools/llvm-xray/xray-graph.cc | ||
476 ↗ | (On Diff #86541) | Why the empty line? |
- Address Reviewer comments
- reply to comments
- rebase on top of D29610 and simplify implementation.
include/llvm/XRay/Graph.h | ||
---|---|---|
87 ↗ | (On Diff #86541) | Please see the new Comments to explain this class class. |
165–171 ↗ | (On Diff #86541) | In this case I cannot define this as a converting ctor, as I need to access a protected member of my parent, which I cannot do in a converting ctor :(=. |
316–318 ↗ | (On Diff #86541) | Well actually in this case yes, it is defined symetrically due to the Boolean template behavior of this class. however this does expose a problem in iterator_facade_base which I have to work around. |
While thinking about this more, it's going to be really hard to start understanding what the semantics we're optimising for are without unit tests. This class is sufficiently complex in implementation that I think we really ought to spend as much time as we can writing up unit tests that will exercise the parts of the code that are really important (in this case that the graph we're building is representing the graph we intend to build) and that we're able to implement the basic graph algorithms like breadth-first-search or depth-first-search on top of the interface of this graph type. The risk right now of not implementing unit tests is that any changes we make to this type's implementation will introduce subtle bugs that will break the basic use-cases while serving only the ones that the llvm-xray graph/graph-diff tools need.
I understand that there's some urgency here, I'd be really happy with covering basic tests covering the most basic of features of this type.
include/llvm/XRay/Graph.h | ||
---|---|---|
41–44 ↗ | (On Diff #87347) | This seems like it's leaking implementation details. Why should the user of the type need to know about DenseMapInfo? |
49–61 ↗ | (On Diff #87347) | Some well-placed empty lines here would help readability. /// Usage: /// /// Graph<int, int, int> G; /// G[1] = 0; /// G[2] = 1; /// G[{1, 2}] = 2; /// /// for (const auto& V : G.vertices()) { /// // V will be an int, do something with it here. /// } /// /// for (const auto &E : G.edges()) { /// // E will be a std::pair<int, int>, do something with it here. /// } /// /// // show an example on what to do with the third int? |
62 ↗ | (On Diff #87347) | While you do provide documentation for the views and for some of the member operations, please provide documentation about things like:
|
71–73 ↗ | (On Diff #87347) | I don't know whether saying that this is derived from std::pair<...> is important to document. This seems like an implementation detail that doesn't help the user of this class at all. Probably say what this type is useful for -- probably important to say that this represents the vertex and the attributes associated with it. |
77–79 ↗ | (On Diff #87347) | Likewise here, I don't see why it's important to tell the reader that you should treat this type as a pair. |
80–88 ↗ | (On Diff #87347) | Why is this documentation on this internal class, as opposed to documentation on the operations on the graph type? i.e. why is it important to mention that this is a child of std::pair<...> -- as opposed to saying why this is derived from std::pair<...> instead? |
90–95 ↗ | (On Diff #87347) | All this documentation seems like implementation detail documentation. This will not be helpful when the doxygen docs are generated and read by users of this type. Remember this is getting into the set of LLVM libraries, and can be used on its own as opposed to just serving the purposes of llvm-xray graph or similar requirements. |
98–112 ↗ | (On Diff #87347) | We still don't have documentation as to "why" these member functions exist, and why we're not just using a DenseMap<pair<VertexIdentifier, VertexIdentifier>, EdgeAttribute>. This still isn't clear from the documentation that's been so far mentioned here. Also it's not clear why the adjacency list being stored isn't just an unordered_map<VertexIdentifier, pair<VertexIdentifier, EdgeAttribute>>, and lookup for all the adjacent vertices (or even out-edges) will be given by equal_range(VertexIdentifier). Since we're already adapting iterators anyway, I'm sure you can turn an iterator that yields a pair<VertexIdentifier, pair<VertexIdentifier, EdgeAddtribute>> into something that yields a tuple<VertexIdentifier&, VertexIdentifier&, EdgeAttribute&> with appropriate const-ness of members. For in-edge and out-edge and attribute storage, you could have done it this way: using EdgeAttributeContainer = std::list<EdgeAttribute>; std::list<EdgeAttribute> EdgeAttributes; unordered_multimap<VertexIdentifier, pair<VertexIdentifier, EdgeAttributeContainer::iterator>> OutEdges; unordered_multimap<VertexIdentifier, pair<VertexIdentifier, EdgeAttributeContainer::iterator>> InEdges; unordered_multimap<pair<VertexIdentifier, VertexIdentifier>, EdgeAttributeContainer::iterator>> EdgeLookup; Since you're already defining your own iterators, they could have been simpler lookup, and still have the consistent interface. I'm not saying this is how you should do it, I'm asking why this isn't what's being done, and the documentation (either internal for the implementer/reader or external generated from this type) isn't answering this question. |
139–140 ↗ | (On Diff #87347) | Consider moving this and all public declarations together for easier reading. |
351–353 ↗ | (On Diff #87347) | Why can't this be defined as a non-member like so: friend template <bool IsConstL, bool IsConstR> bool operator==(const EdgeListIterator<IsConstL>&L, const EdgeListIterator<IsConstR>&R) { return ...; } This way it's defined with the class and it's also accessible only through ADL? |
355 ↗ | (On Diff #87347) | If you defined this as a non-member, it would look like: friend bool operator!=(...) { return !(L == R); } |
557 ↗ | (On Diff #87347) | LLVM Style wants local identifiers starting with capital letters. |
tools/llvm-xray/xray-graph.cc | ||
300 ↗ | (On Diff #87347) | Pro-tip: when asserting, provide some human-readable explanation for what the expectation is. As in: assert((/* complicated conditional */) && "We want a pony, but got a unicorn!"); |
Few more drive-by comments.
include/llvm/XRay/Graph.h | ||
---|---|---|
538–539 ↗ | (On Diff #87327) | two lookups (count + find) - avoid that by using find and then checking end, etc. |
563 ↗ | (On Diff #87327) | Extra semicolon (there are a whole bunch in this class/generally - remove them all) |
571 ↗ | (On Diff #87327) | Missing spaces (run this all through clang-format?) |
578 ↗ | (On Diff #87327) | Extra semicolon |
581 ↗ | (On Diff #87327) | Extra semicolon |
87 ↗ | (On Diff #86541) | Sorry, it's still unclear to me what this class provides over using std::pair directly. (but it sounds like Dean's in on the discussion and has some higher-level feedback/ideas/etc that might motivate a different direction or help sure up this one) |
tools/llvm-xray/xray-graph.cc | ||
497–499 ↗ | (On Diff #87327) | LLVM code usually skips {} on single line statements. |
include/llvm/XRay/Graph.h | ||
---|---|---|
41–44 ↗ | (On Diff #87347) | DenseSet and other Derived classes seem to do this too. |
98–112 ↗ | (On Diff #87347) | I cannot quite do this, however something simmilar probably could be done. (The problem with unordered_multimap is the cost of edge-deletion :(. The code complexity of this would increase slightly. If we were to go this way I would probably implement it more like: DenseMap<VertexIdentifier, Set<VertexIdentifier>> OutEdges; DenseMap<VertexIdentifier, Set<VertexIdentifier>> InEdges; DenseMap<pair<VertexIdentifier, VertexIdentifier>, EdgeAttribute>> EdgeLookup; Which would increase the size somewhat, but would probably work fine. If you want I can go ahead with that? |
Please address all comments.
include/llvm/XRay/Graph.h | ||
---|---|---|
41–44 ↗ | (On Diff #87347) | I'm a little uneasy with the requirements being imposed on VI here. Let me ask a different question: can we just remove this? Why is this essential if we're not relying on DenseMap requirements anymore in the implementation? And if we are using DenseMap, can we get away with just not even mentioning this type in the interface of Graph? I'm trying to further simplify this type because it's currently really hard to explain why VI is there just by looking at what this type is supposed to do. |
49–61 ↗ | (On Diff #87347) | I don't see it done. |
212–213 ↗ | (On Diff #87595) | Empty line in between? |
220–221 ↗ | (On Diff #87595) | Empty line in between? |
230 ↗ | (On Diff #87595) | You're doing two lookups here. Consider just doing one lookup using iterators. |
315 ↗ | (On Diff #87595) | I'd remove this comment. |
364 ↗ | (On Diff #87595) | LLVM Style uses capital letters for local variable names. |
tools/llvm-xray/xray-graph.h | ||
125 ↗ | (On Diff #87595) | Probably not for now, but it would be great if we can construct a graph with a terse interface. Something like: Graph<int, int, int> G( {1, 2, 3, 4, 5}, {{1, 2}, {2, 3}, {3, 4}}); Maybe write as a TODO on the Graph type? |
unittests/XRay/GraphTest.cpp | ||
1 ↗ | (On Diff #87595) | Please have more basic tests (construction, copy-construction, assignment, move construction, etc.), smaller and more focused test cases for more interface and semantics-related tests. |
19 ↗ | (On Diff #87595) | This comment seems nothing to do with the graph. Sets? Hashing? This seems to be leaking implementation details, so let's avoid that by only keeping this about the graph. |
24 ↗ | (On Diff #87595) | This comment seems out of place. |
46–47 ↗ | (On Diff #87595) | Probably needs to be ASSERT_EQ because if this isn't true it doesn't make sense to proceed with the test case. |
50–51 ↗ | (On Diff #87595) | Spurious whitespace. |
52–53 ↗ | (On Diff #87595) | Use consumeError(...) instead? |
60–83 ↗ | (On Diff #87595) | Break out into a different test case, please, give it a name that describes what the case is actually testing. |
66 ↗ | (On Diff #87595) | Consider EXPECT_TRUE(bool{T}) instead. |
- Address Review Commits
include/llvm/XRay/Graph.h | ||
---|---|---|
41–44 ↗ | (On Diff #87347) | We are still using DenseMap, and so the question. VI needs to be there, because the type is int for Graph and StrRef for Graph Diff. |
315 ↗ | (On Diff #87595) | It was not a problem anymore anyway. |
432–435 ↗ | (On Diff #85528) | Oh, in the new version it does work. That is why there is no constructors non-default anymore :) |
Almost ready to land. One thing that needs to be addressed are the spurious semicolons (will cause the buildbots that build with -pedantic to complain loudly).
The tests could be better, but those could be improved post-commit.