我让 Express 比 Fastify 更快(JSON 速度快 100 倍,NestJS 也一样)

2025-05-27

我让 Express 比 Fastify 更快(JSON 速度快 100 倍,NestJS 也一样)

大纲

你好,我是typia的开发人员,fastify目前正在学习。

在学习过程中,我理解了为什么fastify比 更快。此外,我还做了一个实验,typia 更快的 JSON stringify 函数来模拟express的秘密fastifyexpress

从实验(基准测试)中,我得到了有趣的结果,它express比 更快fastify。所以我想和大家分享一下。

服务器级别的 JSON 字符串化基准测试

速度expressfastify


什么typia



// RUNTIME VALIDATORS
export function is<T>(input: unknown | T): input is T; // returns boolean
export function assert<T>(input: unknown | T): T; // throws TypeGuardError
export function validate<T>(input: unknown | T): IValidation<T>; // detailed
export const customValidators: CustomValidatorMap; // can add custom validators

// STRICT VALIDATORS
export function equals<T>(input: unknown | T): input is T;
export function assertEquals<T>(input: unknown | T): T;
export function validateEquals<T>(input: unknown | T): IValidation<T>;

// JSON
export function application<T>(): IJsonApplication; // JSON schema
export function assertParse<T>(input: string): T; // type safe parser
export function assertStringify<T>(input: T): string; // safe and faster
    // +) isParse, validateParse 
    // +) stringify, isStringify, validateStringify

// MISC
export function random<T>(): Primitive<T>; // generate random data
export function clone<T>(input: T): Primitive<T>; // deep clone
export function prune<T extends object>(input: T): void; // erase extra props
    // +) isClone, assertClone, validateClone
    // +) isPrune, assertPrune, validatePrune


Enter fullscreen mode Exit fullscreen mode

在讲述详细的故事之前,我先简单介绍一下typia 。

它是一个 TypeScript 的运行时验证器库,仅需一行代码,即可使用纯 TypeScript 类型实现上述功能。而其他所有替代库都需要额外且重复的模式定义,这与 TypeScript 类型不同。

此外, typia的验证速度比其他工具快得多。就验证速度而言,typia最多比 快 15,000 倍class-validator。在 JSON 字符串化函数方面,typia最多比 快 100 倍class-transformer,甚至是类型安全的。


秘密fastify

fastify是一个竞技库express,以更快的速度作为武器。

而之所以比isfastify更快的原因之一是fast-json-stringify这是团队开发的另一个库,它通过分析 JSON 模式定义来提高 JSON 转换速度。expressfast-json-stringifyfastify

通过使用该fast-json-stringify库,fastify可以比 更快地序列化 JSON 字符串express,并且这种差异使得fastify比 更快express



const fastJson = require('fast-json-stringify')

// REQUIRES JSON SCHEMA DEFINITION
const stringify = fastJson({
    title: 'Example Schema',
    type: 'object',
    properties: {
        firstName: {
            type: 'string'
        },
        lastName: {
            type: 'string'
        },
        age: {
            description: 'Age in years',
            type: 'integer'
        },
        reg: {
            type: 'string'
        }
    }
});

// MAKES JSON SERIALIZATION FASTER
console.log(stringify({
    firstName: 'Matteo',
    lastName: 'Collina',
    age: 32,
    reg: /"([^"]|\\")*"/
}));


Enter fullscreen mode Exit fullscreen mode

Stringify 基准测试

fast-json-stringifyJSON.stringify()比本机函数更快


fastify模仿的秘密express



import typia from "typia";

// PURE TYPESCRIPT TYPE
interface IPerson {
    firstName: string;
    lastName: string;
    age: number; // Age in years
    reg: RegExp;
}

// EASIER THAN ANY OTHER LIBRARIES
typia.stringify<IPerson>({
    firstName: 'Matteo',
    lastName: 'Collina',
    age: 32,
    reg: /"([^"]|\\")*"/
});


Enter fullscreen mode Exit fullscreen mode

研究的源代码fastify,我明白了为什么fastify更快。

顺便说一下,typia 的功能和 一样fast-json-stringify。因此,模仿 的秘密fastify也很容易。



//----
// EXPRESS + TYPIA
//----
import express from "express";
import typia from "typia";

const server: express.Express = express();
const reply =
    <T>(stringify: (input: T) => string | null) =>
    (data: T) =>
    (_req: express.Request, res: express.Response) =>
        res
            .status(200)
            .header("Content-Type", "application/json")
            .send(stringify(data));

// VERY EASY TO IMPLEMENT
server.get(
    "/ObjectSimple",
    reply(typia.createIsStringify<ObjectSimple[]>())
         (storage.ObjectSimple),
);


Enter fullscreen mode Exit fullscreen mode

这是使用typiafastify模仿库的代码express

我认为我的解决方案比 容易得多fastify,因为typia不需要复杂的 JSON 模式定义,它只需要纯 TypeScript 类型。

你同意?



//----
// FASTIFY
//----
import fastify, { FastifyReply, FastifyRequest } from "fastify";
import typia from "typia";

const server = fastify();
const schema = (app: typia.IJsonApplication) => {
    const definitions: Record<string, typia.IJsonSchema> = {};
    for (const [key, value] of Object.entries(app.components.schemas))
        definitions[key.replace("#/definitions/", "")] = value;

    return {
        schema: {
            response: {
                200: {
                    ...app.schemas[0]!,
                    definitions,
                },
            },
        },
    };
};
const reply = (data: object) => (_i: FastifyRequest, o: FastifyReply) =>
    o.send(data);

// DEFINING JSON SCHEMA IS A TERRIBLE WORK
// THEREFORE, I JUST USED typia.application() FUNCTION
server.get(
    "/ObjectSimple",
    schema(typia.application<[ObjectSimple[]], "ajv", "#/definitions">()),
    reply(storage.ObjectSimple),
);


Enter fullscreen mode Exit fullscreen mode

另外,为了进行实验(基准测试)fastify,我还编写了服务器代码fastify。顺便说一句,由于定义 JSON 模式对我来说是一项非常繁琐的工作,所以我直接通过typia.application()函数生成了 JSON 模式数据。

通过autocannon(团队构建的另一个库)测量这些服务器的基准fastify,我得到了非常棒的结果。在某些情况下,仅仅通过利用函数,express速度就变得更快。fastifytypia.stringify()

服务器上的 JSON 字符串化基准测试

expressfastify变得比某些情况下更快


提升 NestJS 服务器速度

验证基准

class-validator而且class-transformer速度非常慢

你知道吗?NestJS 正在使用class-validatorclass-transformer。你还记得吗?在上述基准测试中,这些库比任何其他库都慢。

如果您将它们替换为nestia ( typia为 NestJS 提供的包装器)支持的装饰器,则可以提升您使用 NestJS 开发的后端服务器的速度。只需替换一些如下所示的装饰器函数,您的服务器程序就会运行得更快。



import { Controller } from "@nestjs/common";
import { TypedBody, TypedRoute } from "@nestia/core";

import type { IBbsArticle } from "@bbs-api/structures/IBbsArticle";

@Controller("bbs/articles")
export class BbsArticlesController {
    /** 
     * Store a new content.
     * 
     * @param inupt Content to store
     * @returns Newly archived article
     */
    @TypedRoute.Post() // 100x faster and safer JSON.stringify()
    public async store(
        // 15,000x faster validator
        @TypedBody() input: IBbsArticle.IStore 
    ): Promise<IBbsArticle>; 
        // do not need DTO class definition, 
        // just fine with interface
}


Enter fullscreen mode Exit fullscreen mode

此外,使用nestia,您可以构建比 Swagger 更先进的 Swagger。此外,您还可以构建 SDK 库(例如 tRPC),因此客户端开发人员可以更轻松、更安全地使用您的 API,如下所示。

SDK 使用代码

前端开发人员会很高兴


fastify仍然很快

回顾上面的基准测试结果,当响应数据较少时, 比fastify的组合更快。如果响应数据变得更小,总是比+更快expresstypiafastifyexpresstypia

我只是假设它对fastify标头解析有特殊的优化逻辑,可以减少每次 API 调用的等待时间,但我不知道具体原因。我需要fastify进一步研究,也需要学习express

我会fastify继续,并且会带着原因再次回来。

感谢您阅读我的文章,希望您喜欢我的文章。


链接

文章来源:https://dev.to/samchon/i-made-express-faster-than-fastify-4h8g
PREV
30 次面试中的技术职业建议
NEXT
如何在 JavaScript 中检查对象是否为空