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

Hanlde multi-parametric route (issue #17) #27

Merged
merged 1 commit into from
Sep 27, 2017
Merged

Hanlde multi-parametric route (issue #17) #27

merged 1 commit into from
Sep 27, 2017

Conversation

brunoscopelliti
Copy link
Contributor

Detect multi parametric path (new nodeType=4)

Handle lookup for multi parametric path

Unit test issue #17

@coveralls
Copy link

coveralls commented Sep 23, 2017

Coverage Status

Coverage increased (+0.1%) to 98.341% when pulling c4b5515 on brunoscopelliti:issue-17 into ddc113a on delvedor:master.

@mcollina
Copy link
Collaborator

Can you verify if it impacts the current benchmarks anyhow?

@mcollina
Copy link
Collaborator

@gajus can you please check if this would work for you?

@mcollina
Copy link
Collaborator

This would fix the last part of fastify/fastify#122 (comment).

index.js Outdated
@@ -34,6 +34,8 @@ function Router (opts) {
this.tree = new Node()
}

const forbiddenCharactersInParameterName = ['-']
Copy link

Choose a reason for hiding this comment

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

This is a bit naive implementation. Rather it should accept regex for each parameter.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you make (probably again) some examples of regexps that we should support?

How would you implement the check?

Copy link

Choose a reason for hiding this comment

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

There is already a complete implementation https://www.npmjs.com/package/path-to-regexp

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Rather it should accept regex for each parameter.

Ops, I didn't thought about that. I'll try to extend the current solution in the next days.

@brunoscopelliti
Copy link
Contributor Author

Hi @mcollina ,
these are the results of npm run bench

master
---

lookup static route x 18,014,399 ops/sec ±1.07% (89 runs sampled)
lookup dynamic route x 1,142,987 ops/sec ±1.08% (87 runs sampled)
lookup long static route x 4,309,751 ops/sec ±0.84% (91 runs sampled)
find static route x 25,174,052 ops/sec ±0.87% (87 runs sampled)
find dynamic route x 1,238,040 ops/sec ±0.84% (93 runs sampled)
find long static route x 6,032,821 ops/sec ±1.32% (91 runs sampled)
issue-17
---

lookup static route x 18,550,126 ops/sec ±0.81% (91 runs sampled)
lookup dynamic route x 1,166,002 ops/sec ±0.91% (88 runs sampled)
lookup long static route x 4,408,449 ops/sec ±0.61% (93 runs sampled)
find static route x 24,968,881 ops/sec ±0.83% (95 runs sampled)
find dynamic route x 1,225,983 ops/sec ±1.03% (87 runs sampled)
find long static route x 6,820,027 ops/sec ±0.70% (92 runs sampled)

@coveralls
Copy link

coveralls commented Sep 25, 2017

Coverage Status

Coverage increased (+0.2%) to 98.416% when pulling 5dc2845 on brunoscopelliti:issue-17 into ddc113a on delvedor:master.

1 similar comment
@coveralls
Copy link

Coverage Status

Coverage increased (+0.2%) to 98.416% when pulling 5dc2845 on brunoscopelliti:issue-17 into ddc113a on delvedor:master.

@brunoscopelliti
Copy link
Contributor Author

The latest commits should extend the support to multi parametric route.
However it's far from being comparable to path-to-regexp.
Is having results consistent with expressjs a goal for this router?

@brunoscopelliti
Copy link
Contributor Author

I added also a couple of cases to bench.js.
Performance gets worse for multi parametric route (up to 50% for multi-parametric route with regexp).

lookup static route x 16,930,736 ops/sec ±2.12% (85 runs sampled)
lookup dynamic route x 1,008,912 ops/sec ±0.87% (90 runs sampled)
lookup dynamic multi-parametric route x 724,158 ops/sec ±0.73% (89 runs sampled)
lookup dynamic multi-parametric route with regex x 556,579 ops/sec ±2.40% (83 runs sampled)
lookup long static route x 3,174,227 ops/sec ±1.25% (86 runs sampled)
find static route x 23,057,566 ops/sec ±3.15% (83 runs sampled)
find dynamic route x 1,158,078 ops/sec ±1.30% (86 runs sampled)
find dynamic multi-parametric route x 737,519 ops/sec ±3.10% (86 runs sampled)
find dynamic multi-parametric route with regex x 642,025 ops/sec ±0.80% (90 runs sampled)
find long static route x 4,754,253 ops/sec ±0.76% (93 runs sampled)

@mcollina
Copy link
Collaborator

It seems there is a regression also on the basic ones (static, dynamic), can you check again?

The goal is for the "multi-parametric" to not slow things down for the rest. It's still a valid usecase, and we need to support it - it would be very hard to make it fast.

I know that the Express router offers way more features, however it is up to 2 order of magnitude slower than this one. As long as the port from path-to-regexp to this one can be done, I'm ok.

@brunoscopelliti
Copy link
Contributor Author

brunoscopelliti commented Sep 25, 2017

I've repeated the run a couple of times... Results are at the bottom.
Also note that the only edit I've done that might impact the benchmark is adding the following condition in the find method:

if (kind === 4) {
  ...
}

Benchmark results.

MBP-di-Bruno:find-my-way brunoscopelliti$ npm run bench

> find-my-way@1.5.0 bench /Users/brunoscopelliti/Desktop/github/find-my-way
> node bench.js

lookup static route x 18,109,687 ops/sec ±0.83% (91 runs sampled)
lookup dynamic route x 1,158,082 ops/sec ±0.94% (88 runs sampled)
lookup dynamic multi-parametric route x 740,031 ops/sec ±0.82% (89 runs sampled)
lookup dynamic multi-parametric route with regex x 622,698 ops/sec ±0.59% (89 runs sampled)
lookup long static route x 3,465,129 ops/sec ±0.73% (93 runs sampled)
find static route x 25,453,476 ops/sec ±0.77% (88 runs sampled)
find dynamic route x 1,252,262 ops/sec ±0.65% (91 runs sampled)
find dynamic multi-parametric route x 780,137 ops/sec ±0.90% (91 runs sampled)
find dynamic multi-parametric route with regex x 643,324 ops/sec ±0.84% (93 runs sampled)
find long static route x 4,809,736 ops/sec ±0.89% (89 runs sampled)
MBP-di-Bruno:find-my-way brunoscopelliti$ npm run bench

> find-my-way@1.5.0 bench /Users/brunoscopelliti/Desktop/github/find-my-way
> node bench.js

lookup static route x 17,867,160 ops/sec ±0.75% (88 runs sampled)
lookup dynamic route x 1,172,580 ops/sec ±0.98% (91 runs sampled)
lookup dynamic multi-parametric route x 743,542 ops/sec ±0.85% (93 runs sampled)
lookup dynamic multi-parametric route with regex x 623,682 ops/sec ±0.45% (88 runs sampled)
lookup long static route x 3,449,537 ops/sec ±0.73% (86 runs sampled)
find static route x 24,059,221 ops/sec ±4.42% (88 runs sampled)
find dynamic route x 1,176,371 ops/sec ±1.44% (85 runs sampled)
find dynamic multi-parametric route x 744,186 ops/sec ±1.25% (88 runs sampled)
find dynamic multi-parametric route with regex x 608,528 ops/sec ±1.17% (86 runs sampled)
find long static route x 4,353,530 ops/sec ±2.88% (87 runs sampled)
MBP-di-Bruno:find-my-way brunoscopelliti$ npm run bench

> find-my-way@1.5.0 bench /Users/brunoscopelliti/Desktop/github/find-my-way
> node bench.js

lookup static route x 17,940,631 ops/sec ±0.93% (90 runs sampled)
lookup dynamic route x 1,184,742 ops/sec ±0.98% (92 runs sampled)
lookup dynamic multi-parametric route x 758,835 ops/sec ±0.83% (93 runs sampled)
lookup dynamic multi-parametric route with regex x 619,055 ops/sec ±0.84% (93 runs sampled)
lookup long static route x 3,505,525 ops/sec ±0.82% (92 runs sampled)
find static route x 25,224,421 ops/sec ±1.07% (90 runs sampled)
find dynamic route x 1,250,157 ops/sec ±1.06% (92 runs sampled)
find dynamic multi-parametric route x 791,601 ops/sec ±1.06% (93 runs sampled)
find dynamic multi-parametric route with regex x 642,348 ops/sec ±0.81% (91 runs sampled)
find long static route x 4,774,825 ops/sec ±1.00% (91 runs sampled)
MBP-di-Bruno:find-my-way brunoscopelliti$ npm run bench

> find-my-way@1.5.0 bench /Users/brunoscopelliti/Desktop/github/find-my-way
> node bench.js

lookup static route x 18,058,915 ops/sec ±1.46% (87 runs sampled)
lookup dynamic route x 1,152,634 ops/sec ±0.91% (90 runs sampled)
lookup dynamic multi-parametric route x 740,654 ops/sec ±0.88% (92 runs sampled)
lookup dynamic multi-parametric route with regex x 614,405 ops/sec ±0.77% (83 runs sampled)
lookup long static route x 3,434,878 ops/sec ±0.89% (92 runs sampled)
find static route x 25,266,066 ops/sec ±1.09% (95 runs sampled)
find dynamic route x 1,232,198 ops/sec ±1.48% (91 runs sampled)
find dynamic multi-parametric route x 756,447 ops/sec ±0.94% (88 runs sampled)
find dynamic multi-parametric route with regex x 640,800 ops/sec ±0.73% (86 runs sampled)
find long static route x 4,688,079 ops/sec ±1.20% (88 runs sampled)

Copy link
Collaborator

@mcollina mcollina 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
Owner

@delvedor delvedor left a comment

Choose a reason for hiding this comment

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

Awesome work, thanks!!
Could you also update the docs?

@brunoscopelliti
Copy link
Contributor Author

Could you also update the docs?

Sure!

@coveralls
Copy link

coveralls commented Sep 26, 2017

Coverage Status

Coverage increased (+0.2%) to 98.416% when pulling 63aef07 on brunoscopelliti:issue-17 into ddc113a on delvedor:master.

Copy link
Owner

@delvedor delvedor left a comment

Choose a reason for hiding this comment

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

Very well! Just few minor notes :)

README.md Outdated
<a name="supported-path-formats"></a>
##### Supported path formats
To register a **parametric** path, use the *colon* before the parameter name. For **wildcard** use the *star*.
*Remember that static routes should always be inserted before parametric and wildcard.*
Copy link
Owner

Choose a reason for hiding this comment

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

This is not correct, static route should not be inserted before parametric and wildcard, they are.
We do that internally :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh, sorry for that, you're right...
I haven't done to much attention to that part before (https://github.com/delvedor/find-my-way/blob/master/node.js#L22-L30).

README.md Outdated
// the store can be updated
assert.equal(store, { hello: 'world' })
}, { hello: 'world' })
#### on(methods[], path, handler, [store])
Copy link
Owner

Choose a reason for hiding this comment

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

Since this is the same api I'll add another # before the section title.

README.md Outdated
// your code
})
```
Last argument, `store` is used to pass an object that you can access later inside the handler function.
Copy link
Owner

Choose a reason for hiding this comment

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

... the handler function. If needed, store can be updated.

Hanlde multi-parametric route (issue #17)

Detect multi parametric path (new nodeType=4)

Handle lookup for multi parametric path

Unit test issue #17

Extend comments for new node type

Detect multi parametric part with regex

Hanlde lookup for multi parametric path with regex

Add unit tests

Extended benchmark

Added another testcase

Update documentation: Added info for multiparametric routes

Fix documentation
@coveralls
Copy link

Coverage Status

Coverage increased (+0.2%) to 98.416% when pulling 003b37d on brunoscopelliti:issue-17 into ddc113a on delvedor:master.

4 similar comments
@coveralls
Copy link

Coverage Status

Coverage increased (+0.2%) to 98.416% when pulling 003b37d on brunoscopelliti:issue-17 into ddc113a on delvedor:master.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.2%) to 98.416% when pulling 003b37d on brunoscopelliti:issue-17 into ddc113a on delvedor:master.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.2%) to 98.416% when pulling 003b37d on brunoscopelliti:issue-17 into ddc113a on delvedor:master.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.2%) to 98.416% when pulling 003b37d on brunoscopelliti:issue-17 into ddc113a on delvedor:master.

Copy link
Owner

@delvedor delvedor left a comment

Choose a reason for hiding this comment

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

Awesome, thank you for contributing! :)

@delvedor delvedor merged commit 99f4934 into delvedor:master Sep 27, 2017
@delvedor
Copy link
Owner

Landed in v1.6.0 :)

@brunoscopelliti brunoscopelliti deleted the issue-17 branch September 27, 2017 18:40
@AVVS
Copy link

AVVS commented Sep 30, 2017

This created a problem with routes, where a param is, for example a uuid v4:

/some/:uuid/extra - before that /some/0000-0000-0000-0000/extra would match just fine, now it treats such a string as a multi-parametric route and doesn't resolve at all

to do this now I have to use route /some/*and then do smth like

pseudo code:

const segments = params['*'].split('/')
assert.ok(segments.length === 2)
assert.ok(segments[1] === 'extra')
const uuid = segments[0];

Maybe I'm doing something wrong, but it does seem like a breaking change

Edit:

/some/:uuid(.+)/embedded - this seem to work as well, but it still doesnt change the fact that it is a breaking change :(

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.

6 participants