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

perf!: reduce default brotli compression factor to 4, was before 11 (maximum) #278

Merged
merged 2 commits into from
Jan 29, 2024

Conversation

kahlstrm
Copy link
Contributor

@kahlstrm kahlstrm commented Jan 28, 2024

BREAKING CHANGE: The default brotli quality value currently is 11, which is not meant to be used in an on the fly compression context. Change this to a more reasonable default value of 4.

Checklist

index.js Outdated Show resolved Hide resolved
@gurgunday
Copy link
Member

This looks like a pretty good change

Choosing anything higher than 6 has significant impact on the performance for little benefit

Ref: dotnet/runtime#26097 (comment)

@kahlstrm kahlstrm force-pushed the perf/use-sensible-brotli-value branch 2 times, most recently from 6beb4b6 to 6278077 Compare January 28, 2024 13:33
@kahlstrm kahlstrm requested a review from Uzlopak January 28, 2024 13:33
@kahlstrm
Copy link
Contributor Author

This looks like a pretty good change

Choosing anything higher than 6 has significant impact on the performance for little benefit

Ref: dotnet/runtime#26097 (comment)

In this case 4 was chosen as it's apparently a default used by Cloudflare. Related. Here level 5 provides some advantages at files above 64KB so that would also be an alternative.

@Uzlopak
Copy link
Contributor

Uzlopak commented Jan 28, 2024

Yeah, makes sense. I also was avoiding brotli for the same reason, and preferred gzip as it has higher throughput. But maybe with brotli compression factor of 4 this drawback does not exist anymore.

@Uzlopak
Copy link
Contributor

Uzlopak commented Jan 28, 2024

what does the title mean? sensible brotli value? Maybe some more distinctive title is good, so that reading the release notes it can be determined what changed.

perf: reduce default brotli compression factor to 4, was before 11 (maximum)

Copy link
Member

@gurgunday gurgunday left a comment

Choose a reason for hiding this comment

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

Will lgtm after the title change :)

@kahlstrm kahlstrm force-pushed the perf/use-sensible-brotli-value branch from 6278077 to c9bb734 Compare January 28, 2024 13:50
@kahlstrm kahlstrm changed the title perf(index): use sensible brotli value as default perf: reduce default brotli compression factor to 4, was before 11 (maximum) Jan 28, 2024
Copy link
Contributor

@Uzlopak Uzlopak left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Member

@Fdawgs Fdawgs left a comment

Choose a reason for hiding this comment

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

Maybe put an inline comment referencing why we've set the default to 4?

@kahlstrm kahlstrm force-pushed the perf/use-sensible-brotli-value branch 2 times, most recently from fddece4 to 707ddc4 Compare January 29, 2024 00:35
@kahlstrm kahlstrm requested a review from Fdawgs January 29, 2024 00:36
index.js Outdated
@@ -117,7 +117,9 @@ function processCompressParams (opts) {
}

const params = {
global: (typeof opts.global === 'boolean') ? opts.global : true
global: (typeof opts.global === 'boolean') ? opts.global : true,
// Default of zlib is 11 which is way too heavy for on-the-fly, instead default to 4 as it's used by Cloudflare for on-the-fly compression https://blog.cloudflare.com/this-is-brotli-from-origin#testing
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// Default of zlib is 11 which is way too heavy for on-the-fly, instead default to 4 as it's used by Cloudflare for on-the-fly compression https://blog.cloudflare.com/this-is-brotli-from-origin#testing
/**
* Default of 4 as 11 has a heavy impact on performance.
* @see {@link https://blog.cloudflare.com/this-is-brotli-from-origin#testing}
*/

@kahlstrm kahlstrm force-pushed the perf/use-sensible-brotli-value branch from 707ddc4 to d476623 Compare January 29, 2024 08:09
@kahlstrm kahlstrm requested a review from Fdawgs January 29, 2024 08:10
@SimenB
Copy link
Member

SimenB commented Jan 29, 2024

I'd argue changing the default is a breaking change, and not a "performance improvement". I agree it's a better default, but the behaviour shouldn't change without the consumer having the chance to decide if they value throughput over compression

@climba03003
Copy link
Member

climba03003 commented Jan 29, 2024

I'd argue changing the default is a breaking change

Yes, it is.

the behaviour shouldn't change without the consumer having the chance to decide if they value throughput over compression

@SimenB Maybe you overlook the code, it still allow to change the value in brotliOptions. The predefined one is before the spread operator which means it is not non-configurable.

@Uzlopak
Copy link
Contributor

Uzlopak commented Jan 29, 2024

As it is breaking the api contract i also concur , that it is a semver-major.

@mcollina
Copy link
Member

I'd argue changing the default is a breaking change, and not a "performance improvement".

I'm ok in bumping a major for this.


I agree it's a better default, but the behaviour shouldn't change without the consumer having the chance to decide if they value throughput over compression

Is this implemented already? https://github.com/fastify/fastify-compress?tab=readme-ov-file#brotlioptions-and-zliboptions

@Uzlopak
Copy link
Contributor

Uzlopak commented Jan 29, 2024

@mcollina

Yes:

br: () => ((opts.zlib || zlib).createBrotliCompress || zlib.createBrotliCompress)(params.brotliOptions),

@SimenB
Copy link
Member

SimenB commented Jan 29, 2024

Yes, the user can set it (IIRC we did lower it at my previous workplace) - I'm just pointing out changing the default (even if configurable) is breaking 🙂 When I said "user should have the chance to decide" I merely meant a major version will "force" the user to make a conscious choice (as it'll be out of semver ranges for people setting that (most, if not all)), rather than a perf version, which is usually a patch release which I assume most people don't comb through changelogs for

@Uzlopak
Copy link
Contributor

Uzlopak commented Jan 29, 2024

@SimenB
And to what value did you reduce it?

@SimenB
Copy link
Member

SimenB commented Jan 29, 2024

I haven't worked there for 5 months, but I asked a former colleague, and he sent this snippet

// fastify-compress by default uses brotli quality at 11 (max), which is really
// slow. This sets it at 5 instead which is better for on-the-fly compression,
// based on https://blog.cloudflare.com/results-experimenting-brotli/
// Based on the same blog post, it sets zlib quality to 8.
// It also sets the operation to flush to work with streaming responses.
// Otherwise it will buffer everything (i.e. streaming won't work) which will
// impact TTFB.
const compressPlugin: FastifyPluginAsync = async instance => {
  instance.register(fastifyCompress, {
    zlibOptions: {
      flush: zlib.constants.Z_SYNC_FLUSH,
      level: 8,
    },
    brotliOptions: {
      flush: zlib.constants.BROTLI_OPERATION_FLUSH,
      params: {
        [zlib.constants.BROTLI_PARAM_QUALITY]: 5,
      },
    },
  });
};

(credit to @hzr)

@kahlstrm
Copy link
Contributor Author

kahlstrm commented Jan 29, 2024

I haven't worked there for 5 months, but I asked a former colleague, and he sent this snippet

// fastify-compress by default uses brotli quality at 11 (max), which is really
// slow. This sets it at 5 instead which is better for on-the-fly compression,
// based on https://blog.cloudflare.com/results-experimenting-brotli/
// Based on the same blog post, it sets zlib quality to 8.
// It also sets the operation to flush to work with streaming responses.
// Otherwise it will buffer everything (i.e. streaming won't work) which will
// impact TTFB.
const compressPlugin: FastifyPluginAsync = async instance => {
  instance.register(fastifyCompress, {
    zlibOptions: {
      flush: zlib.constants.Z_SYNC_FLUSH,
      level: 8,
    },
    brotliOptions: {
      flush: zlib.constants.BROTLI_OPERATION_FLUSH,
      params: {
        [zlib.constants.BROTLI_PARAM_QUALITY]: 5,
      },
    },
  });
};

(credit to @hzr)

I've set mine to 5 as well in the project I'm using this in, so for me that's fine as well 👍 . The improvement of quality level 5 over 4 is seemingly more signifant with filesizes above 64 KB according to the Cloudflare article posted previously. Here is some analysis from 2015

@gurgunday
Copy link
Member

8 seems too much 😅, but I fully get that it is much better than the current default

64kb is significant for text data, I don't believe the average size of an HTML page or a CSS file is up there

I think 4 is a good default

@kahlstrm
Copy link
Contributor Author

8 seems too much 😅, but I fully get that it is much better than the current default

64kb is significant for text data, I don't believe the average size of an HTML page or a CSS file is up there

I think 4 is a good default

Note that in the snippet zlib is set at 8, which is comparable to brotli quality 4 IIRC. The brotli level inthe snippet is below to level 5.

@Fdawgs Fdawgs changed the title perf: reduce default brotli compression factor to 4, was before 11 (maximum) perf!: reduce default brotli compression factor to 4, was before 11 (maximum) Jan 29, 2024
@mcollina mcollina merged commit aa3079a into fastify:master Jan 29, 2024
19 checks passed
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.

7 participants