Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8.0 proposal: LazyBasicProperties / IReadonlyBasicProperties #965

Open
JanEggers opened this issue Oct 29, 2020 · 9 comments
Open

8.0 proposal: LazyBasicProperties / IReadonlyBasicProperties #965

JanEggers opened this issue Oct 29, 2020 · 9 comments
Milestone

Comments

@JanEggers
Copy link
Contributor

https://user-images.githubusercontent.com/661658/96521641-37aacc00-1261-11eb-89d9-abe85fbc2dec.png

shows that currently there are large allocations of BasicProperties and subsequent strings contained in the BasicProperties

My proposal is to either split IBasicProperties or create IReadonlyBasicProperties with only get accessors.

(i didnt do the research yet maybe IBasicProperties can remain and just remove all the setters)

That way we can provide a new Implementation for incoming messages that just deserializes the properties that are actually accessed resulting in much lower computational and memory overhead.

@michaelklishin
Copy link
Member

We cannot use such a read-only interface on the publisher side but we should indeed be able to on the consumer/delivery side. Makes sense.

@stebet
Copy link
Collaborator

stebet commented Oct 29, 2020

I was thinking the exact same thing yesterday. My thought was that requires the BasicProperties to by IDisposable though, since we'd want to keep a copy of the bytes ready, but only deserialize on access, possibly incurring just a memory-copy cost (which can be pooled) but possibly avoiding the deserialization overhead. But lazily deserializing them seems like the correct approach i.m.o if we can easily take care of the disposal.

@JanEggers
Copy link
Contributor Author

from my pov no dispose / copy is needed.

we just need to add to the docs that BasicProperties are only valid until the handler returns just like for the body bytes.

@stebet
Copy link
Collaborator

stebet commented Oct 29, 2020

It's created out of a header frame so we could take over the payload just like we do with body frames, which will require disposing of it when done. I'll do a little test and report back.

@bollhals
Copy link
Contributor

Question is, would it be possible to implement it as a "readonly struct" (We'd have to investigate whether we could even make it ref, to prevent storing it anywhere.) We'd also have to adapt all the passing of the type to use "in" to prevent copying.
Or do we have to implement it as class? (E.g. should the public API use an interface or a struct)

@JanEggers
Copy link
Contributor Author

JanEggers commented Oct 30, 2020

I think the public api is and should be an interface.

And I think it should be implemented as a class to avoid boxing and copiing. Also the instance itself is not the problem, the real problems are the many properties. If we only store one property of type memory and introduce the lazy getters it should get much smaller. Im still thinking about if its better to have one memory property that contains all the data or one slice of memory per property and just dont create the strings.

/// <summary>Autogenerated type. AMQP specification content header properties for content class "basic"</summary>

says its auto generated can someone please point me to the generator of it because its not obvious to me.

@stebet
Copy link
Collaborator

stebet commented Oct 30, 2020

I think the public api is and should be an interface.

And I think it should be implemented as a class to avoid boxing and copiing. Also the instance itself is not the problem, the real problems are the many properties. If we only store one property of type memory and introduce the lazy getters it should get much smaller. Im still thinking about if its better to have one memory property that contains all the data or one slice of memory per property and just dont create the strings.

I agree with this and I've implemented it this way (see my PR). This can contain lot of data (custom headers, publisher app information, timestamps etc.) so a class only makes sense. But treating this the same way as the payload (only safe to use within the consumer scope) etc., makes it possible to save CPU cycles and string allocations by deferring deserialization of the buffer data to when the data is accesses. The class itself becomes a little bit bigger (adds a reference to the buffer) but allocations and CPU should in most cases should go down.

@bollhals
Copy link
Contributor

bollhals commented Oct 30, 2020

I think the public api is and should be an interface.

What are the benefits of using an interface/class here?
Benefits of a ref readonly struct I see as follows:

  • Doesn't allocate
  • Readonly enforces readonly and makes it clear to everyone
  • Ref enforces that the user of this can not store this instance => impossible to access it after method returned, doesn't rely on the user implementing it correctly
  • Still allows implementation of an interface to ensure the ReadOnly and not Readonly types are equal
  • Performance (no allocations required, no virtual method calls, inlineing)
  • "In" can be used to avoid copying overhead

Also the instance itself is not the problem, the real problems are the many properties.

True, but even if we trim the size down, it's one of the most created instances we have. So even if it is small, it will be on the top of the allocation chart.

/// <summary>Autogenerated type. AMQP specification content header properties for content class "basic"</summary>

says its auto generated can someone please point me to the generator of it because its not obvious to me.

It used to be generated until early v6 I think. Comment weren't updated yet it seems.

@michaelklishin
Copy link
Member

Sounds like we can drop the interface here for 8.0.

@michaelklishin michaelklishin changed the title Proposal: LazyBasicProperties / IReadonlyBasicProperties 8.0 proposal: LazyBasicProperties / IReadonlyBasicProperties Nov 6, 2020
@lukebakken lukebakken added this to the 8.0.0 milestone Dec 29, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants