-
Notifications
You must be signed in to change notification settings - Fork 2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #9506 from jonathanhefner/benchmark-nextjs
Benchmark Next.js
- Loading branch information
Showing
23 changed files
with
1,576 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
*.dockerfile | ||
.dockerignore | ||
node_modules | ||
npm-debug.log | ||
README.md | ||
.next | ||
.git |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
|
||
# dependencies | ||
/node_modules | ||
/.pnp | ||
.pnp.* | ||
.yarn/* | ||
!.yarn/patches | ||
!.yarn/plugins | ||
!.yarn/releases | ||
!.yarn/versions | ||
|
||
# testing | ||
/coverage | ||
|
||
# next.js | ||
/.next/ | ||
/out/ | ||
|
||
# production | ||
/build | ||
|
||
# misc | ||
.DS_Store | ||
*.pem | ||
|
||
# debug | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
.pnpm-debug.log* | ||
|
||
# env files (can opt-in for committing if needed) | ||
.env* | ||
|
||
# vercel | ||
.vercel | ||
|
||
# typescript | ||
*.tsbuildinfo | ||
next-env.d.ts |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
# Next.js Benchmarking Test | ||
|
||
## Test source files and URLs | ||
|
||
| Test | Source Code | URL | | ||
| --- | --- | --- | | ||
| [JSON Serialization][] | [`app/json/route.ts`][] | http://localhost:3000/json | | ||
| [Single Database Query][] | [`app/db/route.ts`][] | http://localhost:3000/db | | ||
| [Multiple Database Queries][] | [`app/queries/route.ts`][] | http://localhost:3000/queries?queries= | | ||
| [Fortunes][] | [`app/fortunes/page.tsx`][] | http://localhost:3000/fortunes | | ||
| [Database Updates][] | [`app/updates/route.ts`][] | http://localhost:3000/updates?queries= | | ||
| [Plaintext][] | [`app/plaintext/route.ts`][] | http://localhost:3000/plaintext | | ||
| [Caching][] | [`app/cached-queries/route.ts`][] | http://localhost:3000/cached-queries?queries= | | ||
|
||
[JSON Serialization]: https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Framework-Tests-Overview#json-serialization | ||
[Single Database Query]: https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Framework-Tests-Overview#single-database-query | ||
[Multiple Database Queries]: https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Framework-Tests-Overview#multiple-database-queries | ||
[Fortunes]: https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Framework-Tests-Overview#fortunes | ||
[Database Updates]: https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Framework-Tests-Overview#database-updates | ||
[Plaintext]: https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Framework-Tests-Overview#plaintext | ||
[Caching]: https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Framework-Tests-Overview#caching | ||
|
||
[`app/json/route.ts`]: ./app/json/route.ts | ||
[`app/db/route.ts`]: ./app/db/route.ts | ||
[`app/queries/route.ts`]: ./app/queries/route.ts | ||
[`app/fortunes/page.tsx`]: ./app/fortunes/page.tsx | ||
[`app/updates/route.ts`]: ./app/updates/route.ts | ||
[`app/plaintext/route.ts`]: ./app/plaintext/route.ts | ||
[`app/cached-queries/route.ts`]: ./app/cached-queries/route.ts | ||
|
||
## TODO | ||
|
||
The Fortunes test is currently disabled because the benchmark expects exact HTML output — see [TechEmpower/FrameworkBenchmarks#9505](https://github.com/TechEmpower/FrameworkBenchmarks/pull/9505). After that issue is resolved, the Fortunes test can be re-enabled by applying the following diff: | ||
|
||
```diff | ||
--- a/frameworks/TypeScript/nextjs/benchmark_config.json | ||
+++ b/frameworks/TypeScript/nextjs/benchmark_config.json | ||
@@ -20,7 +20,7 @@ | ||
"json_url": "/json", | ||
"db_url": "/db", | ||
"query_url": "/queries?queries=", | ||
- "TEMPORARILY DISABLED fortune_url": "/fortunes", | ||
+ "fortune_url": "/fortunes", | ||
"update_url": "/updates?queries=", | ||
"plaintext_url": "/plaintext", | ||
"cached_query_url": "/cached-queries?queries=" | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { findWorld as uncached_findWorld, World } from "@/lib/db" | ||
import { unstable_cache } from "next/cache" | ||
import { NextRequest } from "next/server" | ||
|
||
const findWorld = unstable_cache(uncached_findWorld) | ||
|
||
export async function GET(request: NextRequest) { | ||
const queriesParam = request.nextUrl.searchParams.get("queries") | ||
const queriesCount = Math.min(Math.max(Number(queriesParam) || 1, 1), 500) | ||
const results = Array<World | undefined>(queriesCount) | ||
|
||
for (let i = 0; i < queriesCount; i += 1) { | ||
const id = 1 + Math.floor(Math.random() * 10000) | ||
results[i] = await findWorld(id) | ||
} | ||
|
||
return Response.json(results) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import { findWorld } from "@/lib/db" | ||
|
||
export async function GET() { | ||
const id = 1 + Math.floor(Math.random() * 10000) | ||
return Response.json(await findWorld(id)) | ||
} |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { db } from "@/lib/db" | ||
|
||
// Prevent database queries during build phase. | ||
export const dynamic = "force-dynamic" | ||
|
||
export default async function Page() { | ||
const fortunes = await db.selectFrom("Fortune").selectAll().execute() | ||
fortunes.push({ id: 0, message: "Additional fortune added at request time." }) | ||
fortunes.sort((a, b) => a.message.localeCompare(b.message)) | ||
|
||
return <> | ||
<title>Fortunes</title> | ||
|
||
<table> | ||
<thead> | ||
<tr> | ||
<th>id</th> | ||
<th>message</th> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
{fortunes.map(fortune => | ||
<tr key={fortune.id}> | ||
<td>{fortune.id}</td> | ||
<td>{fortune.message}</td> | ||
</tr> | ||
)} | ||
</tbody> | ||
</table> | ||
</> | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export async function GET() { | ||
return Response.json({ message: "Hello, World!" }) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
export default function RootLayout({ | ||
children, | ||
}: Readonly<{ | ||
children: React.ReactNode; | ||
}>) { | ||
return ( | ||
<html lang="en"> | ||
<body> | ||
{children} | ||
</body> | ||
</html> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export default function Home() { | ||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export function GET() { | ||
return new Response("Hello, World!") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { findWorld, World } from "@/lib/db" | ||
import { NextRequest } from "next/server" | ||
|
||
export async function GET(request: NextRequest) { | ||
const queriesParam = request.nextUrl.searchParams.get("queries") | ||
const queriesCount = Math.min(Math.max(Number(queriesParam) || 1, 1), 500) | ||
const promises = Array<Promise<World | undefined>>(queriesCount) | ||
|
||
for (let i = 0; i < queriesCount; i += 1) { | ||
const id = 1 + Math.floor(Math.random() * 10000) | ||
promises[i] = findWorld(id) | ||
} | ||
|
||
return Response.json(await Promise.all(promises)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { db, findWorld, upsertWorlds, World } from "@/lib/db" | ||
import { NextRequest } from "next/server" | ||
|
||
export async function GET(request: NextRequest) { | ||
const queriesParam = request.nextUrl.searchParams.get("queries") | ||
const queriesCount = Math.min(Math.max(Number(queriesParam) || 1, 1), 500) | ||
|
||
const ids = new Set<number>() | ||
while (ids.size < queriesCount) { | ||
ids.add(1 + Math.floor(Math.random() * 10000)) | ||
} | ||
|
||
const promises = new Array<Promise<World | undefined>>() | ||
for (const id of ids) { | ||
promises.push(findWorld(id)) | ||
} | ||
|
||
const results = await Promise.all(promises) as World[] | ||
for (const result of results) { | ||
result.randomNumber = 1 + Math.floor(Math.random() * 10000) | ||
} | ||
|
||
await upsertWorlds(results) | ||
|
||
return Response.json(results) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
{ | ||
"framework": "nextjs", | ||
"tests": [ | ||
{ | ||
"default": { | ||
"display_name": "Next.js", | ||
"versus": "nodejs", | ||
"classification": "Platform", | ||
"language": "TypeScript", | ||
"platform": "nodejs", | ||
"framework": "nextjs", | ||
"os": "Linux", | ||
"webserver": "None", | ||
"database": "postgres", | ||
"database_os": "Linux", | ||
"orm": "Micro", | ||
"approach": "Realistic", | ||
"notes": "", | ||
"port": 3000, | ||
"json_url": "/json", | ||
"db_url": "/db", | ||
"query_url": "/queries?queries=", | ||
"TEMPORARILY DISABLED fortune_url": "/fortunes", | ||
"update_url": "/updates?queries=", | ||
"plaintext_url": "/plaintext", | ||
"cached_query_url": "/cached-queries?queries=" | ||
} | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { Kysely, PostgresDialect } from "kysely" | ||
import { Pool } from "pg" | ||
import { Database, WorldRow } from "./schema.js" | ||
|
||
export const db = new Kysely<Database>({ | ||
dialect: new PostgresDialect({ | ||
pool: new Pool({ connectionString: process.env.DATABASE_URL }), | ||
}), | ||
}) | ||
|
||
export type World = { | ||
[key in keyof WorldRow as key extends "randomnumber" ? "randomNumber" : key]: WorldRow[key] | ||
} | ||
|
||
export async function findWorld(id: number): Promise<World | undefined> { | ||
return db.selectFrom("World"). | ||
where("id", "=", id). | ||
select(["id", "randomnumber as randomNumber"]). | ||
executeTakeFirst() | ||
} | ||
|
||
export async function upsertWorlds(worlds: World[]) { | ||
const values = worlds.map(world => ({ id: world.id, randomnumber: world.randomNumber })) | ||
return db.insertInto("World").values(values).onConflict(oc => | ||
oc.column("id").doUpdateSet({ randomnumber: eb => eb.ref("excluded.randomnumber") }) | ||
).execute() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { Generated, Insertable, Selectable, Updateable } from "kysely" | ||
|
||
export interface Database { | ||
World: WorldTable | ||
Fortune: FortuneTable | ||
} | ||
|
||
export interface WorldTable { | ||
id: Generated<number> | ||
randomnumber: number | ||
} | ||
|
||
export type WorldRow = Selectable<WorldTable> | ||
export type NewWorld = Insertable<WorldTable> | ||
export type WorldUpdate = Updateable<WorldTable> | ||
|
||
export interface FortuneTable { | ||
id: Generated<number> | ||
message: string | ||
} | ||
|
||
export type Fortune = Selectable<FortuneTable> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import { NextRequest, NextResponse } from "next/server" | ||
|
||
export function middleware(request: NextRequest) { | ||
const response = NextResponse.next() | ||
response.headers.set("Server", "Next.js") | ||
return response | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import type { NextConfig } from "next"; | ||
|
||
const nextConfig: NextConfig = { | ||
output: "standalone", | ||
}; | ||
|
||
export default nextConfig; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
FROM node:22-slim | ||
|
||
ENV NEXT_TELEMETRY_DISABLED="1" | ||
ENV DATABASE_URL="postgres://benchmarkdbuser:benchmarkdbpass@tfb-database/hello_world" | ||
|
||
EXPOSE 3000 | ||
|
||
WORKDIR /nextjs | ||
|
||
COPY package.json package-lock.json ./ | ||
RUN npm ci | ||
|
||
COPY ./ ./ | ||
RUN npm run build \ | ||
&& cp -r public .next/standalone/ \ | ||
&& cp -r .next/static .next/standalone/.next/ | ||
|
||
ENV NODE_ENV="production" | ||
|
||
CMD ["node", ".next/standalone/server.js"] |
Oops, something went wrong.