Skip to content

Optimizing memory usage even further. #824

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

Merged
merged 5 commits into from
May 19, 2020

Conversation

stebet
Copy link
Contributor

@stebet stebet commented May 4, 2020

Proposed Changes

After writing a blog on the allocation fixes and publishing last weekend, I got a few pointers from @davidfowl on saving even more allocations by using ArrayPool instead of MemoryPool. I also cleaned up some related code while I was at it.

Types of Changes

  • Bug fix (non-breaking change which fixes issue #NNNN)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause an observable behavior change in existing systems)
  • Documentation improvements (corrections, new content, etc)
  • Cosmetic change (whitespace, formatting, etc)

Checklist

  • I have read the CONTRIBUTING.md document
  • I have signed the CA (see https://cla.pivotal.io/sign/rabbitmq)
  • All tests pass locally with my changes
  • I have added tests that prove my fix is effective or that my feature works
  • I have added necessary documentation (if appropriate)
  • Any dependent changes have been merged and published in related repositories

@stebet
Copy link
Contributor Author

stebet commented May 4, 2020

Example of allocation reductions (using my benchmark app, sending and reciving 50.000 events with 512 byte payloads).

Before:
512AllocsAfter

After:
512Optimized

@stebet
Copy link
Contributor Author

stebet commented May 4, 2020

I didn't notice #816 which makes the same change to the contract. I'll make changes to accomodate. I do think adding a method to the contracts should not require a major change as additions are normally not considered breaking, unless they might affect certain overloads, so we could add the ReadOnlyMemory overload to the batch publishing interface and still keep the byte[] version as well. What do you think @bording?

@davidfowl
Copy link

I see a bunch of low hanging fruit:

  • What’s allocating the Task? That should be cached as there’s only 2 values.
  • Why is that Func being allocated?

@@ -259,6 +259,7 @@ namespace RabbitMQ.Client
public interface IBasicPublishBatch
{
void Add(string exchange, string routingKey, bool mandatory, RabbitMQ.Client.IBasicProperties properties, byte[] body);
void Add(string exchange, string routingKey, bool mandatory, RabbitMQ.Client.IBasicProperties properties, System.ReadOnlyMemory<byte> body);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately since this is a change to an interface, this means this is a breaking change. If you're wanting to get this in to a release before 7.0, you can't do this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should go into 7.0 which we can release fairly soon. @lukebakken WDYT?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I know there are quite a few things that have been discussed for 7.0, one of which is a fully-async client. I think @stebet has done some work on that.

If "fairly soon" means within 6 months... maybe???

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I've done some research and experiments. It'd probably require quite a lot of changes to the public interface, all of which are good i.m.o, like departing from Event based notifications (can be replaced with a pluggable interface), but I'll write up a proposal soon for that. Reverting any interface changes for now :)

@lukebakken lukebakken self-assigned this May 4, 2020
@bording
Copy link
Collaborator

bording commented May 4, 2020

I do think adding a method to the contracts should not require a major change as additions are normally not considered breaking, unless they might affect certain overloads,

That is only true when you're talking about a class. Any changes to an interface are breaking because any existing implementations of that interface break. That's why default interface methods were added to C# 8.

@stebet
Copy link
Contributor Author

stebet commented May 4, 2020

I'll take a closer look and follow up later tonight. Thanks for this @davidfowl and @bording. It makes sense to skip the interface change as most of this is very applicable to 6.X.

@lukebakken
Copy link
Collaborator

@stebet I'm going to test and review this today. Since there are no interface changes, I assume this is OK for 6.1.0

@lukebakken lukebakken force-pushed the arrayPoolOptimizations branch from 28082c8 to f67908b Compare May 19, 2020 21:25
@lukebakken lukebakken merged commit 98299f8 into rabbitmq:master May 19, 2020
@stebet stebet deleted the arrayPoolOptimizations branch May 20, 2020 00:03
@bollhals bollhals mentioned this pull request May 20, 2020
11 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants