Giter Club home page Giter Club logo

pooledstringcontent's Introduction

PooledStringContent

What is it?

If you're writing a .NET library/app that sends HTTP requests, then you may have used the StringContent class to translate strings to an HttpContent, which you can PUT/POST with. PooledStringContent is a drop-in replacement for StringContent you can use to cut down on memory usage in your library/app.

Installation

You can get it via NuGet:

Install-Package Pooling.Net.Http

How do I use it?

Simply replace the lines where you use StringContent:

using (var content = new StringContent("..."))
{
    return await httpClient.PostAsync(uri, content).ConfigureAwait(false);
}

with PooledStringContent:

using (var content = new PooledStringContent("..."))
{
    return await httpClient.PostAsync(uri, content).ConfigureAwait(false);
}

Encodings other than UTF-8 are also supported, e.g. you can write new PooledStringContent("foobar", Encoding.Unicode).

What benefits does it offer?

Performance. If your application/library is using a lot of memory when making HTTP requests, then this may help as it uses buffer pooling for the encoded bytes. It rents these buffers using the new ArrayPool APIs added to .NET Core.

If you're interested more in how it works, take a look at the source code here.

Is this only compatible with .NET Core?

No, it should be compatible with the .NET Framework/other environments as well, because it targets the .NET Platform Standard.

Pitfalls

#1: Not disposing the content

It is very important that you make sure to dispose the PooledStringContent after using it. This is because unlike StringContent, it actually does important work when disposing by returning its rented array to the buffer pool. If you don't dispose it, it will end up eventually depleting the buffer pool and creating new arrays each time, which could result in less performance for your app.

In short, change any code like this:

var content = new StringContent("...");
return await httpClient.PostAsync(uri, content).ConfigureAwait(false);

to use a using statement, like the example above:

using (var content = new PooledStringContent("..."))
{
    return await httpClient.PostAsync(uri, content).ConfigureAwait(false);
}

Note that this may lead to our next pitfall, which is...

#2: Disposing before you finish the request

An optimization you can make with Task-returning methods is, if all you do is some synchronous work then await another async action at the end, i.e.

public async Task<HttpResponseMessage> Foo()
{
    var content = new StringContent("...");
    return await _httpClient.PostAsync(_uri, content).ConfigureAwait(false);
}

you can instead return the Task directly like so:

public Task<HttpResponseMessage> Foo() // note: no async
{
    var content = new StringContent("...");
    return _httpClient.PostAsync(_uri, content); // note: no await
}

Now, if you made the change I noted above, your code may now look like this:

public Task<HttpResponseMessage> Foo()
{
    using (var content = new PooledStringContent("..."))
    {
        return _httpClient.PostAsync(_uri, content);
    }
}

But wait! PostAsync is no longer the last operation in the method, since after it's returned content.Dispose is called in a finally block. (using expands to a try-finally block when compiled.) This means that if the HttpClient attempts to read from the content after performing an asynchronous operation, the content will already have been disposed and will no longer be valid.

The fix for this is to switch back to using async/await:

public async Task<HttpResponseMessage> Foo()
{
    using (var content = new PooledStringContent("..."))
    {
        return await _httpClient.PostAsync(_uri, content).ConfigureAwait(false);
    }
}

See this StackOverflow question for more on this.

Building

Interested in building the repo? Please make sure you have the .NET Core RTM tooling installed.

To build the source:

cd src
dotnet restore
dotnet build

To run tests:

cd test
dotnet restore
dotnet test

License

MIT

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.