sammccall added a comment.

Thanks for the changes. I don't think `TypedValueMap`/`ContextBuilder` pull 
their weight, but let's get another opinion on this.



================
Comment at: clangd/Context.h:65
+  Context *Parent;
+  TypedValueMap Data;
+};
----------------
ilya-biryukov wrote:
> sammccall wrote:
> > ilya-biryukov wrote:
> > > sammccall wrote:
> > > > We add complexity here (implementation and conceptual) to allow 
> > > > multiple properties to be set at the same level (vs having a key and an 
> > > > AnyStorage and making Context a linked list).
> > > > Is this for performance? I'm not convinced it'll actually be faster for 
> > > > our workloads, or that it matters.
> > > Conceptually, a `Context` is more convenient to use when it stores 
> > > multiple values. This allows to put a bunch of things and assign meaning 
> > > to `Context` (i.e., a `Context` for processing a single LSP request, 
> > > global context). If `Context`s were a linked list, the intermediate 
> > > `Context`s would be hard to assign the meaning to.
> > > 
> > > That being said, storage strategy for `Context`s is an implementation 
> > > detail and could be changed anytime. I don't have big preferences here, 
> > > but I think that storing a linked list of maps has, in general, a better 
> > > performance than storing a linked list.
> > > And given that it's already there, I'd leave it this way.
> > With the new shared_ptr semantics:
> > 
> >      Context D = move(C).derive(K1, V1).derive(K2, V2);
> > 
> > Is just as meaningful as
> > 
> >     Context D = move(C).derive().add(K1, V1).add(K2, V2);
> > 
> > Yeah, the list of maps in an implementation detail. It's one that comes 
> > with a bunch of complexity (`ContextBuilder` and most of `TypedValueMap`). 
> > It really doesn't seem to buy us anything (the performance is both 
> > uninteresting and seems likely to be worse in this specific case with very 
> > few entries). 
> The thing I like about it is that the `Context`s are layered properly in a 
> sense that there's a Context corresponding to the request, a Context 
> corresponding to the forked subrequests, etc.
> If we change the interface, we'll be creating a bunch of temporary Contexts 
> that don't correspond to a nice meaningful abstraction (like request) in my 
> head, even though we don't give those contexts any names.
> 
> I do agree we currently pay with some complexity for that. Though I'd argue 
> it's all hidden from the users of the interface, as building and consuming 
> contexts is still super-easy and you don't need to mention ContextBuilder or 
> TypedValueMap. And the implementation complexity is totally manageable from 
> my point of view, but I am the one who implemented it in the first place, so 
> there's certainly a bias there.
I don't see temporary unnamed `Context`s being any different from temporary 
unnamed `ContextBuilder`s.

But we've gone around on this point a bit, and this really seems to be a 
question of taste. @klimek, can we have a third opinion?

The options we're looking at are:
  - `Context` stores a map and a parent pointer. `derive()` returns a 
`ContextBuilder` used to create new contexts containing 0 or more new KV pairs. 
`TypedValueMap` stores the payloads.
  - `Context` stores a single KV pair and a parent pointer. `derive(K, V)` is 
used to create a new context with one new KV pair. A Key-pointer and AnyStorage 
in `Context` store the payloads, the rest of `TypedValueMap` goes away.


================
Comment at: clangd/Context.h:142
+/// Creates a ContextBuilder with a null parent.
+ContextBuilder buildCtx();
+
----------------
ilya-biryukov wrote:
> sammccall wrote:
> > I think we should spell this `emptyCtx().derive()`.
> > It should be pretty rare to derive from the empty context in production 
> > code - and conceptually it's no different than any other use of the empty 
> > context, I think.
> I'd argue the separate function is more readable and saves us an extra lookup 
> in the empty context for missing keys.
> Given that `emptyCtx` is now `Context::empty`, maybe we should also change 
> `buildCtx`  to `Context::build`?
I think this isn't a path we want to make smooth or obvious - usually what you 
want is to accept a context, derive from it, and use the result.

Embedders will need to create root contexts - we discussed `LSPServer` offline, 
and there it seems natural to own a background context and derive from it per 
handled call.


================
Comment at: clangd/Context.h:92
+  ContextBuilder derive() const &;
+  ContextBuilder derive() const &&;
+
----------------
`&&`, not `const&&` :-)

Maybe add a trailing `//takes ownership`


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D40485



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

Reply via email to