Skip to content

Commit

Permalink
Close #268 - refactored entire benchmark program for TypeBox
Browse files Browse the repository at this point in the history
  • Loading branch information
samchon committed Oct 27, 2022
1 parent f74e018 commit 4725356
Show file tree
Hide file tree
Showing 40 changed files with 1,967 additions and 815 deletions.
233 changes: 137 additions & 96 deletions benchmark/features/benchmark_assert.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import { TSchema, Type } from "@sinclair/typebox";
import { TypeCompiler } from "@sinclair/typebox/compiler";
import * as tr from "class-transformer";
import { ClassConstructor } from "class-transformer";
import * as cv from "class-validator";
import * as t from "io-ts";
import "reflect-metadata";
import { z } from "zod";

import TSON from "../../src";
// PURE TYPESCRIPT TYPES
import { ArrayRecursive } from "../../test/structures/ArrayRecursive";
import { ArrayRecursiveUnionExplicit } from "../../test/structures/ArrayRecursiveUnionExplicit";
import { ArrayRecursiveUnionImplicit } from "../../test/structures/ArrayRecursiveUnionImplicit";
import { ObjectHierarchical } from "../../test/structures/ObjectHierarchical";
import { ObjectRecursive } from "../../test/structures/ObjectRecursive";
import { ObjectUnionExplicit } from "../../test/structures/ObjectUnionExplicit";
import { ObjectUnionImplicit } from "../../test/structures/ObjectUnionImplicit";
import { UltimateUnion } from "../../test/structures/UltimateUnion";
Expand All @@ -19,158 +23,195 @@ import { CvArrayRecursive } from "../structures/class-validator/CvArrayRecursive
import { CvArrayRecursiveUnionExplicit } from "../structures/class-validator/CvArrayRecursiveUnionExplicit";
import { CvArrayRecursiveUnionImplicit } from "../structures/class-validator/CvArrayRecursiveUnionImplicit";
import { CvObjectHierarchical } from "../structures/class-validator/CvObjectHierarchical";
import { CvObjectRecursive } from "../structures/class-validator/CvObjectRecursive";
import { CvObjectUnionExplicit } from "../structures/class-validator/CvObjectUnionExplicit";
import { CvObjectUnionImplicit } from "../structures/class-validator/CvObjectUnionImplicit";
// IO-TS TYPES
import { IoTsArrayRecursive } from "../structures/io-ts/IoTsArrayRecursive";
import { IoTsArrayRecursiveUnionExplicit } from "../structures/io-ts/IoTsArrayRecursiveUnionExplicit";
import { IoTsArrayRecursiveUnionImplicit } from "../structures/io-ts/IoTsArrayRecursiveUnionImplicit";
import { IoTsObjectHierarchical } from "../structures/io-ts/IoTsObjectHierarchical";
import { IoTsObjectRecursive } from "../structures/io-ts/IoTsObjectRecursive";
import { IoTsObjectUnionExplicit } from "../structures/io-ts/IoTsObjectUnionExplicit";
import { IoTsObjectUnionImplicit } from "../structures/io-ts/IoTsObjectUnionImplicit";
import { IoTsUltimateUnion } from "../structures/io-ts/IoTsUltimateUnion";
import { IoTsUtils } from "../structures/io-ts/IoTsUtils";
// TYPEBOX TYPES
import { TypeBoxArrayRecursive } from "../structures/typebox/TypeBoxArrayRecursive";
import { TypeBoxArrayRecursiveUnionExplicit } from "../structures/typebox/TypeBoxArrayRecursiveUnionExplicit";
import { TypeBoxArrayRecursiveUnionImplicit } from "../structures/typebox/TypeBoxArrayRecursiveUnionImplicit";
import { TypeBoxObjectHierarchical } from "../structures/typebox/TypeBoxObjectHierarchical";
import { TypeBoxObjectRecursive } from "../structures/typebox/TypeBoxObjectRecursive";
import { TypeBoxObjectUnionExplicit } from "../structures/typebox/TypeBoxObjectUnionExplicit";
import { TypeBoxObjectUnionImplicit } from "../structures/typebox/TypeBoxObjectUnionImplicit";
import { TypeBoxUltimateUnion } from "../structures/typebox/TypeBoxUltimateUnion";
import { __TypeBoxArrayRecursive } from "../structures/typebox/TypeBoxArrayRecursive";
import { __TypeBoxArrayRecursiveUnionExplicit } from "../structures/typebox/TypeBoxArrayRecursiveUnionExplicit";
import { __TypeBoxArrayRecursiveUnionImplicit } from "../structures/typebox/TypeBoxArrayRecursiveUnionImplicit";
import { __TypeBoxObjectHierarchical } from "../structures/typebox/TypeBoxObjectHierarchical";
import { __TypeBoxObjectUnionExplicit } from "../structures/typebox/TypeBoxObjectUnionExplicit";
import { __TypeBoxObjectUnionImplicit } from "../structures/typebox/TypeBoxObjectUnionImplicit";
import { __TypeBoxUltimateUnion } from "../structures/typebox/TypeBoxUltimateUnion";
// ZOD TYPES
import { ZodArrayRecursive } from "../structures/zod/ZodArrayRecursive";
import { ZodArrayRecursiveUnionExplicit } from "../structures/zod/ZodArrayRecursiveUnionExplicit";
import { ZodArrayRecursiveUnionImplicit } from "../structures/zod/ZodArrayRecursiveUnionImplicit";
import { ZodObjectHierarchical } from "../structures/zod/ZodObjectHierarchical";
import { ZodObjectRecursive } from "../structures/zod/ZodObjectRecursive";
import { ZodObjectUnionExplicit } from "../structures/zod/ZodObjectUnionExplicit";
import { ZodObjectUnionImplicit } from "../structures/zod/ZodObjectUnionImplicit";
import { ZodUltimateUnion } from "../structures/zod/ZodUltimateUnion";

const assert = () => [
AssertBenchmarker.prepare(
/* -----------------------------------------------------------
PREPARE ASSETS
----------------------------------------------------------- */
class CustomError extends Error {
public constructor(public readonly instance: object) {
super();

const proto = new.target.prototype;
if (Object.setPrototypeOf) Object.setPrototypeOf(this, proto);
else (this as any).__proto__ = proto;
}
}

const assertTypeBox =
<S extends TSchema>(schema: S) =>
<T>(input: T[]) => {
const program = TypeCompiler.Compile(Type.Array(schema));
if (program.Check(input)) return input;

const iterator = program.Errors(input);
throw new CustomError(iterator.next().value);
};
const assertIoTs =
<S extends t.Mixed>(type: S) =>
<T>(input: T[]) => {
const validation = t.array(type).decode(input);
const paths: string[] = IoTsUtils.getPaths(validation);

if (paths.length) throw new CustomError(paths);
return input;
};
const assertZod =
<S extends z.ZodTypeAny>(type: S) =>
<T>(input: T[]) => {
const res = z.array(type).safeParse(input);
if (res.success) return input;
throw new CustomError(res.error);
};
const assertClassValidator =
<S extends object>(schema: ClassConstructor<S>) =>
<T>(input: T[]) => {
const result = input.map((elem) =>
cv.validateSync(tr.plainToInstance(schema, elem)),
);
if (result.length) throw new CustomError(result);
return input;
};

const prepare = AssertBenchmarker.prepare([
"typescript-json",
"typebox",
"io-ts",
"zod",
"class-validator",
]);

/* -----------------------------------------------------------
DO BENCHMARK
----------------------------------------------------------- */
const assertType = () => [
prepare(
"object (hierarchical)",
() => ObjectHierarchical.generate(),
() => ObjectHierarchical.trail(),
{
"typescript-json": (input) => TSON.assertType(input),
"io-ts": (input) => IoTsObjectHierarchical.decode(input),
"class-validator": (input) => {
const cla = tr.plainToInstance(CvObjectHierarchical, input);
return cv.validateSync(cla);
},
zod: (input) => ZodObjectHierarchical.safeParse(input),
typebox: (input) =>
TypeBoxObjectHierarchical.Errors(input).next().value,
"typescript-json": TSON.createAssertType<ObjectHierarchical[]>(),
"io-ts": assertIoTs(IoTsObjectHierarchical),
"class-validator": assertClassValidator(CvObjectHierarchical),
zod: assertZod(ZodObjectHierarchical),
typebox: assertTypeBox(__TypeBoxObjectHierarchical),
},
),
AssertBenchmarker.prepare(
prepare(
"object (recursive)",
() => ObjectRecursive.generate(),
() => ObjectUnionImplicit.generate(),
() => ObjectUnionImplicit.trail(),
{
"typescript-json": (input) => TSON.assertType(input),
"io-ts": (input) => IoTsObjectRecursive.decode(input),
"class-validator": (input) => {
const cla = tr.plainToInstance(CvObjectRecursive, input);
return cv.validateSync(cla);
},
zod: (input) => ZodObjectRecursive.safeParse(input),
typebox: (input) =>
TypeBoxObjectRecursive.Errors(input).next().value,
"typescript-json": TSON.createAssertType<ObjectUnionImplicit[]>(),
"io-ts": assertIoTs(IoTsObjectUnionImplicit),
"class-validator": assertClassValidator(CvObjectUnionImplicit),
zod: assertZod(ZodObjectUnionImplicit),
typebox: assertTypeBox(__TypeBoxObjectUnionImplicit),
},
),
AssertBenchmarker.prepare(
prepare(
"object (union, explicit)",
() => ObjectUnionExplicit.generate(),
() => ObjectUnionExplicit.trail(),
{
"typescript-json": (input) => TSON.assertType(input),
"io-ts": (input) => IoTsObjectUnionExplicit.decode(input),
"class-validator": (input) => {
const classes = input.map((elem) =>
tr.plainToClass(CvObjectUnionExplicit, elem),
);
return classes.map((clas) => cv.validateSync(clas));
},
zod: (input) => ZodObjectUnionExplicit.safeParse(input),
typebox: (input) =>
TypeBoxObjectUnionExplicit.Errors(input).next().value,
"typescript-json": TSON.createAssertType<ObjectUnionExplicit[]>(),
"io-ts": assertIoTs(IoTsObjectUnionExplicit),
"class-validator": assertClassValidator(CvObjectUnionExplicit),
zod: assertZod(ZodObjectUnionExplicit),
typebox: assertTypeBox(__TypeBoxObjectUnionExplicit),
},
),
AssertBenchmarker.prepare(
prepare(
"object (union, implicit)",
() => ObjectUnionImplicit.generate(),
() => ObjectUnionImplicit.trail(),
{
"typescript-json": (input) => TSON.assertType(input),
"io-ts": null,
"class-validator": (input) => {
const classes = input.map((elem) =>
tr.plainToClass(CvObjectUnionImplicit, elem),
);
return classes.map((clas) => cv.validateSync(clas));
},
zod: (input) => ZodObjectUnionImplicit.safeParse(input),
typebox: null,
"typescript-json": TSON.createAssertType<ObjectUnionImplicit[]>(),
"io-ts": assertIoTs(IoTsObjectUnionImplicit),
"class-validator": assertClassValidator(CvObjectUnionImplicit),
zod: assertZod(ZodObjectUnionImplicit),
typebox: assertTypeBox(__TypeBoxObjectUnionImplicit),
},
),
AssertBenchmarker.prepare(
prepare(
"array (recursive)",
() => ArrayRecursive.generate(),
() => ArrayRecursive.trail(),
{
"typescript-json": (input) => TSON.assertType(input),
"io-ts": (input) => IoTsArrayRecursive.decode(input),
"class-validator": (input) => {
const cla = tr.plainToInstance(CvArrayRecursive, input);
return cv.validateSync(cla);
},
zod: (input) => ZodArrayRecursive.safeParse(input),
typebox: (input) =>
TypeBoxArrayRecursive.Errors(input).next().value,
"typescript-json": TSON.createAssertType<ArrayRecursive[]>(),
"io-ts": assertIoTs(IoTsArrayRecursive),
"class-validator": assertClassValidator(CvArrayRecursive),
zod: assertZod(ZodArrayRecursive),
typebox: assertTypeBox(__TypeBoxArrayRecursive),
},
),
AssertBenchmarker.prepare(
prepare(
"array (union, explicit)",
() => ArrayRecursiveUnionExplicit.generate(),
() => ArrayRecursiveUnionExplicit.trail(),
{
"typescript-json": (input) => TSON.assertType(input),
"io-ts": (input) => IoTsArrayRecursiveUnionExplicit.decode(input),
"class-validator": (input) => {
const classes = input.map((elem) =>
tr.plainToClass(CvArrayRecursiveUnionExplicit, elem),
);
return classes.map((clas) => cv.validateSync(clas));
},
zod: (input) => ZodArrayRecursiveUnionExplicit.safeParse(input),
typebox: (input) =>
TypeBoxArrayRecursiveUnionExplicit.Errors(input).next().value,
"typescript-json":
TSON.createAssertType<ArrayRecursiveUnionExplicit[]>(),
"io-ts": assertIoTs(IoTsArrayRecursiveUnionExplicit),
"class-validator": assertClassValidator(
CvArrayRecursiveUnionExplicit,
),
zod: assertZod(ZodArrayRecursiveUnionExplicit),
typebox: assertTypeBox(__TypeBoxArrayRecursiveUnionExplicit),
},
),
AssertBenchmarker.prepare(
prepare(
"array (union, implicit)",
() => ArrayRecursiveUnionImplicit.generate(),
() => ArrayRecursiveUnionImplicit.trail(),
{
"typescript-json": (input) => TSON.assertType(input),
"io-ts": null,
"class-validator": (input) => {
const classes = input.map((elem) =>
tr.plainToClass(CvArrayRecursiveUnionImplicit, elem),
);
return classes.map((clas) => cv.validateSync(clas));
},
zod: (input) => ZodArrayRecursiveUnionImplicit.safeParse(input),
typebox: null,
"typescript-json":
TSON.createAssertType<ArrayRecursiveUnionImplicit[]>(),
"io-ts": assertIoTs(IoTsArrayRecursiveUnionImplicit),
"class-validator": assertClassValidator(
CvArrayRecursiveUnionImplicit,
),
zod: assertZod(ZodArrayRecursiveUnionImplicit),
typebox: assertTypeBox(__TypeBoxArrayRecursiveUnionImplicit),
},
),
AssertBenchmarker.prepare(
prepare(
"ultimate union",
() => UltimateUnion.generate(),
() => UltimateUnion.trail(),
{
"typescript-json": (input) => TSON.assertType(input),
"io-ts": null,
"typescript-json": TSON.createAssertType<UltimateUnion[]>(),
"io-ts": assertIoTs(IoTsUltimateUnion),
"class-validator": null,
zod: (input) => ZodUltimateUnion.safeParse(input),
typebox: null,
zod: assertZod(ZodUltimateUnion),
typebox: assertTypeBox(__TypeBoxUltimateUnion),
},
),
];
export { assert as benchmark_assert };
export { assertType as benchmark_assert };
Loading

0 comments on commit 4725356

Please sign in to comment.