-
-
Notifications
You must be signed in to change notification settings - Fork 574
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(types): replace intersection with union to get better perf #3443
perf(types): replace intersection with union to get better perf #3443
Conversation
06610f8
to
60bffbb
Compare
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #3443 +/- ##
=======================================
Coverage 95.58% 95.58%
=======================================
Files 155 155
Lines 9357 9357
Branches 2746 2784 +38
=======================================
Hits 8944 8944
Misses 413 413 ☔ View full report in Codecov by Sentry. |
Hi @m-shaka
Awesome!
I've been thinking about this for a while: We can care less about changing the type definitions of handlers. A few users customize them, but we don't have to care about them though we have to take care of actual runtime behaviors. These are at risk own. So, it's okay to go with this. Plus, regarding the types, we must care about the performance, most importantly. Shall we go ahead with this PR? |
Found that replacing intersections with unions will break chaning like new Hono()
.get('/bar/:id', c => c.text('foo'))
.post(c => {
const id = c.req.param('id') // Woops! `string | undefined`
return c.text(id)
}) It's likely there're pitfalls we don't notice so far 🤔 Instead, I'm wondering if we can change the intersection in Line 215 in f87c221
apps added through |
60bffbb
to
b44b0c5
Compare
I replaced intersection in I prepared new another script to generate a suitable test case (it's not commited) import { writeFile } from 'node:fs'
import * as path from 'node:path'
const count = 10
const countSubRoutes = 20
const generateRoutes = (count: number) => {
let routes = `import { Hono } from '../../../src'
export const app = new Hono()`
for (let i = 1; i <= count; i++) {
routes += `
.route('', new Hono()`
// each sub app has 20 routes
for (let j = 1; j <= countSubRoutes; j++) {
routes += `
.get('/route${i}-${j}/:id', (c) => {
return c.json({ ok: true })
})`
}
routes += `
)`
}
return routes
}
const routes = generateRoutes(count)
writeFile(path.join(import.meta.dirname, '../generated/app.ts'), routes, (err) => {
if (err) { throw err }
console.log(`${count} routes have been written to app.ts`)
}) Put this into
|
This is awesome! I also tried it; I could feel it became faster with
Regarding measuring performance, we can measure two patterns:
We can choose only the latter to measure it, but in my opinion, it's better to know both performances because there are cases if a user uses If so, the script and CI process will be a bit complicated. But, for measuring const count = 5
const generateRoutes = (count: number) => {
let routes = `import { Hono } from '../../../src'
import { app as subApp } from './app'
export const app = new Hono()`
for (let i = 1; i <= count; i++) {
routes += `
.route('/${i}', subApp)`
}
return routes
}
const routes = generateRoutes(count)
// ... And create two files:
Then measure this |
@yusukebe Apologies for my long absence. Regarding the script for the performance measure, how about doing it in another PR?
#3491 is amazing! After merging it and this PR, I'll improve the display of the result |
Agree!
I'm also thinking about this.
Yes! It looks good for me. Can I merge it? |
Go! |
Okay! I just released |
…js#3443) * perf(types): replace intersection with union to get better perf * revert intersection * format * refactor: move ExcludeEmptyObject to utils/type.ts
I'm developing a tool that generates Open API documentation based on schema types. However, this change of the schema types has broken my generator. Please treat major changes to schema types as breaking changes or highlight these chages in the release notes. |
Hi @miyaji255
This PR is for performance improvement. We should not change the APIs with this PR. If this change breaks existing applications, it's not intended and may be a bug. Can you create a new issue to report it? |
My tool relies solely on type information and is independent of runtime behavior. In future updates, I would appreciate careful consideration when making changes of types as well. |
@miyaji255 Okay! |
The author should do the following, if applicable
bun run format:fix && bun run lint:fix
to format the codedetails
This leads a breaking change
I found that massive amount of intersection increase type instantiation.
So, I've tried replacing intersections to union and as a result, this has decreased type instantiation drastically, that is, by about 70%.
However, union here is not intuitive and this may be a breaking change for users manipulating type of Hono somehow. I'm not certain how they do that, though
@yusukebe What's your thought on that? Do you think we should go for it this way?