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

Add more powerful benchmarks #54

Merged
merged 11 commits into from
Dec 2, 2021
Merged

Add more powerful benchmarks #54

merged 11 commits into from
Dec 2, 2021

Conversation

kibertoad
Copy link
Member

No description provided.

@kibertoad
Copy link
Member Author

@Uzlopak There is definitely something wrong with how our benchmarks are written, I don't think we were actually awaiting anything to finish processing originally and were counting who knows what. Now it seems to be fixed, but for some reason nothing gets returned as a result of the operation. Could you take a look? Wonder if we are using wrong header.

You can see it in action by running benchmarks/package.json -> benchmark-busboy

@Uzlopak
Copy link
Contributor

Uzlopak commented Dec 1, 2021

@kibertoad

Does this help?

@Uzlopak
Copy link
Contributor

Uzlopak commented Dec 1, 2021

allowUnsafe does not really generate data :/

@kibertoad
Copy link
Member Author

@Uzlopak Version that is currently pushed returns immediately, promise is not resolved properly for some reason. I'm trying to produce much simpler example based on our usage of Busboy in types-multipart.spec.js, but it isn't returning any content either. This makes me wonder if our results are even correct 😂

@Uzlopak
Copy link
Contributor

Uzlopak commented Dec 1, 2021

pushed now.

If i make some low rounds, like 10 warmup and 10 benchmark cycles it will get results.

@Uzlopak
Copy link
Contributor

Uzlopak commented Dec 1, 2021

@kibertoad

[email protected] benchmark-all /home/aras/Workspace/fastify/direct/busboy/benchmarks
npm run benchmark-busboy && npm run benchmark-fastify -p high

[email protected] benchmark-busboy /home/aras/Workspace/fastify/direct/busboy/benchmarks
node busboy/executioner.js -c 0

second
Mean time for busboy is 1945927.3472222222 nanoseconds
all done

[email protected] benchmark-fastify /home/aras/Workspace/fastify/direct/busboy/benchmarks
node busboy/executioner.js -c 1 "high"

second
Mean time for @fastify/busboy is 1765178.5027777778 nanoseconds
Something went wrong: ENOENT: no such file or directory, open '/home/aras/Workspace/fastify/direct/busboy/benchmarks/_results/Busboy_comparison-@fastify/busboy-Node_12.json'

@Uzlopak
Copy link
Contributor

Uzlopak commented Dec 2, 2021

Also it seems that the preset command line parameter is not passed to executioner.js

@kibertoad
Copy link
Member Author

@Uzlopak Much better now, thank you! Still trying to figure out what can we listen to to ensure that we actually read the expected parts of the payload in expected way; knowing that we fired the finish event is not enough, we may as well read nothing before doing so.

I am very concerned that if I add this:

        busboy.on('part', function (p) {
            callbacks.partBegin++;
            p.on('header', function (header) {
                for (var h in header)
                console.log('Part header: k: ' + inspect(h) + ', v: ' + inspect(header[h]));
            });
            p.on('data', function (data) {
                //callbacks.partData++;
                console.log('Part data: ' + inspect(data.toString()));
            });
            p.on('end', function () {
                console.log('End of part\n');
                //callbacks.partEnd++;
            });
        });

then none of the part listeners log anything. It feels like we are not doing anything.

@kibertoad
Copy link
Member Author

Also it seems that the preset command line parameter is not passed to executioner.js

commonBuilder.js is supposed to read it on its own, is that not working?

@Uzlopak
Copy link
Contributor

Uzlopak commented Dec 2, 2021

I think the actual mistake was that i took the dicer benchmarks. part is not a busboy event but a dicer event.
First of all: sorry about that.

What we can do is to listen to the file event, as we have only one file, and accumulate the size of the provided chunk(s) (=> bytesRead). in finish we could then return the bytesRead.

The thing is we dont pipe anything through the file system or so. So it makes actually sense to just listen to the file event and pipe the data into the nirvana.

So we should actually also handle the file stream:
busboy.on('file', (fieldname, file, filename, encoding, mimetype) => {
console.log(File [${fieldname}]: filename: ${filename}, encoding: ${encoding}, mimetype: ${mimetype});
file.on('data', data => {
console.log(File [${fieldname}] got ${data.length} bytes);
});
file.on('end', () => {
console.log(File [${fieldname}] Finished);
});
});

@kibertoad
Copy link
Member Author

Ah, that part actually comes from Dicer, which explains why it wouldn't work for Busboy which I don't think is passing through all the events it gets from Dicer. But events that Busboy emits are not documented, ant the one used by fastify-multipart (file) is not hit either.

@kibertoad
Copy link
Member Author

The thing is we dont pipe anything through the file system or so. So it makes actually sense to just listen to the file event and pipe the data into the nirvana.

Great point!

@kibertoad
Copy link
Member Author

@Uzlopak Pushed the change, it's still not firing any file events. Do we still miss something?

@Uzlopak
Copy link
Contributor

Uzlopak commented Dec 2, 2021

It is really strange. Even legacy busboy behaves the same :/ So it is not even something were I could blame that we maybe broke something...

@Uzlopak
Copy link
Contributor

Uzlopak commented Dec 2, 2021

It ignores the parts in this line.
So this means, the payload is wrong?

if (this._isPreamble && this._events.preamble) { this.emit('preamble', this._part) } else if (this._isPreamble !== true && this._events.part) { this.emit('part', this._part) } else { this._ignore() }

@kibertoad
Copy link
Member Author

Yes, looks like it.

@Uzlopak
Copy link
Contributor

Uzlopak commented Dec 2, 2021

The payload seems valid. I really dont get it... What is the issue?

@Uzlopak
Copy link
Contributor

Uzlopak commented Dec 2, 2021

At this point it is easier to setup a fastify instance and run the autocannon against it than writing a benchmark... WTF

@Uzlopak
Copy link
Contributor

Uzlopak commented Dec 2, 2021

Ok.. the most stupidest thing

@Uzlopak
Copy link
Contributor

Uzlopak commented Dec 2, 2021

I go to sleep now, knowing I solved this ridiculously issue...

npm run benchmark-all

> [email protected] benchmark-all /home/aras/Workspace/fastify/direct/busboy/benchmarks
> npm run benchmark-busboy && npm run benchmark-fastify -p high


> [email protected] benchmark-busboy /home/aras/Workspace/fastify/direct/busboy/benchmarks
> node busboy/executioner.js -c 0

second
Mean time for busboy is 305643.6620498615 nanoseconds
all done

> [email protected] benchmark-fastify /home/aras/Workspace/fastify/direct/busboy/benchmarks
> node busboy/executioner.js -c 1 "high"

second
Mean time for @fastify/busboy is 165044.7206085754 nanoseconds

Something went wrong: ENOENT: no such file or directory, open '/home/aras/Workspace/fastify/direct/busboy/benchmarks/_results/Busboy_comparison-@fastify/busboy-Node_12.json'

@kibertoad
Copy link
Member Author

@Uzlopak Woooohooo! Awesome, great job!

@kibertoad
Copy link
Member Author

I'll wrap up remaining loose ends and prepare it for review.

@kibertoad
Copy link
Member Author

kibertoad commented Dec 2, 2021

@Uzlopak I've added real validators to ensure our results are consistent, and they are sometimes passing, and sometimes failing. Do you have any ideas what could make them randomly fail sometimes? Could be that we actually have a bug in there that makes both implementations sometimes swallow some data or generate some in excess.
Reproduction: just run either "benchmark-fastify" or "benchmark-busboy" several times in the row. It will fail more times than it will pass.
Considering that we do buffer.toString() both when processing and when asserting, should be identical?..

@Uzlopak
Copy link
Contributor

Uzlopak commented Dec 2, 2021

Actually... I think this is because of generating Buffer data. I assume that it fails, e.g. when \r\n is created randomly. What happens if you give a specific string like consecutive 'AAAAAA...'? Does it still fail?

@kibertoad
Copy link
Member Author

@Uzlopak You were right, replacing data with deterministic set resolved the issue. This is now ready for review :)

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.

first review, will test now

.gitignore Show resolved Hide resolved
benchmarks/common/commonBuilder.js Show resolved Hide resolved
benchmarks/package.json Outdated Show resolved Hide resolved
"benchmark-busboy": "node busboy/executioner.js -c 0",
"benchmark-fastify": "node busboy/executioner.js -c 1",
"benchmark-all": "npm run benchmark-busboy && npm run benchmark-fastify -p high",
"benchmark-all-medium": "npm run benchmark-busboy && npm run benchmark-fastify -p medium",

This comment was marked as outdated.

Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
"benchmark-all-medium": "npm run benchmark-busboy && npm run benchmark-fastify -p medium",
"benchmark-all-medium": "npm run benchmark-busboy -- -p medium && npm run benchmark-fastify -- -p medium",

benchmarks/package.json Outdated Show resolved Hide resolved
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.

good job.

@kibertoad kibertoad merged commit fc62b60 into master Dec 2, 2021
@kibertoad kibertoad deleted the feat/better-benchmark branch December 2, 2021 15:26
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

Successfully merging this pull request may close these issues.

2 participants