-
Notifications
You must be signed in to change notification settings - Fork 84
Conversation
public string EncodingName => "br"; | ||
|
||
/// <inheritdoc /> | ||
public bool SupportsFlush => false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you verify this? We would like flush support.
It appears to be supported:
https://github.com/dotnet/corefx/blob/master/src/System.IO.Compression.Brotli/src/System/IO/Compression/enc/BrotliStream.Compress.cs#L110
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I tried to find it in the source, but looked at a different file (without .Compress)🤦🏻♂️
// Copyright (c) .NET Foundation. All rights reserved. | ||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
||
#if NETCOREAPP2_1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The public types should be NETSTANDARD, let's keep the NETCOREAPP regions as constrained as possible. You should be able to limit them to ResponseCompressionProvider.ctor and BrotliCompressionProvider.CreateStream
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But what will they do on non-netcoreapp2.1? Throw?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CreateStream is the only place that would need to throw (NotImplementedException, NotSupportedException?). And that exception will be avoided by having ResponseCompressionProvider skip adding the provider. It would only throw if someone added it manually.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would only throw if someone added it manually.
Good point 👍🏻
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm assuming that also means that you're fine with adding Brotli as a default provider?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's fine, as long as it's second on the list.
new CompressionProviderFactory(typeof(GzipCompressionProvider)), | ||
#if NETCOREAPP2_1 | ||
new CompressionProviderFactory(typeof(BrotliCompressionProvider)) | ||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
List all TFMs and include the else and error cases so we know if these need updating.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed on the error case, but what should the other TFMs do?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The other TFMs can be empty.
920f84f
to
f89a2be
Compare
public Stream CreateStream(Stream outputStream) | ||
{ | ||
#if NET461 | ||
throw new PlatformNotSupportedException(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do these require a message?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not worried about it. I don't expect people to hit this.
You can combine net461 and netstandard2_0.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if that would work. I think you need to check NETCOREAPP2_1 first, then check NETSTANDARD2_0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nvrm, I didn't realize ifdefs are not inherited.
c51e066
to
170b08a
Compare
Any pointers on tests you'd like to see? |
Can you recycle some of the existing Flush tests? |
Is the intention that gzip will be preferred over Brotli and that you have to explicitly configure it if you want it the other way around? |
Right |
31062f8
to
48a2160
Compare
I guess this will also fix #216, as I had to take the "registration" order into account when selecting a compression provider when you have multiple matching providers with the same (or missing) quality value. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking really good. I wonder about the repetitive complexity and if we need fast paths or caching for the common case.
@shirhatti is doing some analysis of other implementations to see if the priority system needs to be more flexible. We'll follow up with you.
var encodingName = encoding.Value; | ||
var quality = encoding.Quality.GetValueOrDefault(1); | ||
|
||
if (Math.Abs(quality) < double.Epsilon) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why the Abs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Uh, I blame R# 🤣
{ | ||
return provider; | ||
candidates.Add(new ProviderCandidate(provider.EncodingName, quality, i, provider)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is starting to become a lot of work on every response, and you'd get the same results most of the time, no? e.g. gzip, deflate, br
or gzip, deflate
are always going to evaluate to the same provider. Is it worth caching a few results based on the raw header string to avoid this redundant processing? Or at least having a fast path for headers that do not contain quality, then you can do a Contains for each available provider and be done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it's much more work, it's just doing it the other way around by matching first and ordering after, but we can certainly try to be smarter to avoid some work 👍🏻
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be worth checking/considering making _providers a Dictionary? Besides that, I don't see much you can do.
} | ||
} | ||
|
||
if (candidates.Count == 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could be combine with ElementAtOrDefault(0)
|
||
public double Quality { get; } | ||
|
||
public int Order { get; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Priority?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LOL, I had Priority and changed it to Order last minute 😂
[Theory] | ||
[InlineData("gzip", "br")] | ||
[InlineData("br", "gzip")] | ||
public async Task Request_AcceptMixed_CompressedGzip(string encoding1, string encoding2) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see the opposite test where you configure the providers in the other order and ensure br is selected. (NETCOREAPP2_2 only)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that's still missing. I'm reluctant to copy-pasting the setup code more, but I'm not sure if there there's a good way to reuse the setup as there are quite a few permutations.
@Tratcher I added some benchmarks and ran them on the dev branch (before) and this branch (after) and they look pretty similar: BeforeBenchmarkDotNet=v0.10.14, OS=macOS High Sierra 10.13.4 (17E202) [Darwin 17.5.0]
Intel Core i7-4870HQ CPU 2.50GHz (Haswell), 1 CPU, 8 logical and 4 physical cores
.NET Core SDK=2.1.300
[Host] : .NET Core 2.1.1 (CoreCLR 4.6.26606.02, CoreFX 4.6.26606.05), 64bit RyuJIT
Job-BPKSVL : .NET Core 2.1.1 (CoreCLR 4.6.26606.02, CoreFX 4.6.26606.05), 64bit RyuJIT
Runtime=Core Server=True Toolchain=.NET Core 2.1
RunStrategy=Throughput
AfterBenchmarkDotNet=v0.10.14, OS=macOS High Sierra 10.13.4 (17E202) [Darwin 17.5.0]
Intel Core i7-4870HQ CPU 2.50GHz (Haswell), 1 CPU, 8 logical and 4 physical cores
.NET Core SDK=2.1.300
[Host] : .NET Core 2.1.1 (CoreCLR 4.6.26606.02, CoreFX 4.6.26606.05), 64bit RyuJIT
Job-YFUDVB : .NET Core 2.1.1 (CoreCLR 4.6.26606.02, CoreFX 4.6.26606.05), 64bit RyuJIT
Runtime=Core Server=True Toolchain=.NET Core 2.1
RunStrategy=Throughput
|
1c8f224
to
026932b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking clean.
#if NETCOREAPP2_1 | ||
return new BrotliStream(outputStream, Options.Level, leaveOpen: true); | ||
#elif NET461 || NETSTANDARD2_0 | ||
throw new PlatformNotSupportedException(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's add a comment to the exception.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A comment explaining why we throw, or an exception message?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exception message 😄
namespace Microsoft.AspNetCore.ResponseCompression | ||
{ | ||
/// <summary> | ||
/// Options for the <see cref="BrotliCompressionProvider"/> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Relating to options, can you add a comment to ResponseCompressionOptions saying the Providers's priority is based on their ordering in the list?
{ | ||
// No compression | ||
return null; | ||
candidates.Add(new ProviderCandidate(encodingName.Value, quality, int.MaxValue, null)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should add a comment here about what each of these values mean.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The arguments?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah for the arguments. Or add named params.
{ | ||
return provider; | ||
candidates.Add(new ProviderCandidate(provider.EncodingName, quality, i, provider)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be worth checking/considering making _providers a Dictionary? Besides that, I don't see much you can do.
@@ -0,0 +1,54 @@ | |||
using System.Collections.Generic; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: copyright header.
@@ -0,0 +1 @@ | |||
[assembly: BenchmarkDotNet.Attributes.AspNetCoreBenchmark] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: copyright header.
3474e3e
to
af8bec1
Compare
Anything more I can do to get this over the finish line 🏁? 👼 |
Just waiting on a feature sign-off from @shirhatti. He'll be back Monday. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please rebase.
{ | ||
new CompressionProviderFactory(typeof(GzipCompressionProvider)), | ||
#if NETCOREAPP2_1 | ||
new CompressionProviderFactory(typeof(BrotliCompressionProvider)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We decided to make Brotli higher priority than Gzip. We'll have time to evaluate the impact in the preview releases. Please switch the order and then we can get this merged.
af8bec1
to
17ec376
Compare
Rebased and swapped defaults 👌🏻 |
Sorry, I just realized we'd swapped the branches under you and this was targeting 3.0 (master). I changed the base branch back to 2.2 since we want this sooner than later 😁, but unfortunately that requires one more rebase. I can get to it later today if you don't. |
66d9783
to
cb26243
Compare
cb26243
to
91068a5
Compare
Rebased. Hopfully it went OK 🙏 |
Great, thanks. |
Wee! Thank you 😄 |
By adding brotli as the default we might have broken anyone running on full Fx. Whoops |
We do not add brotli on net461. |
Probably needs a few more tests, like for ordering. Should the Brotli provider be added by default?
Closes #217