Quartet 9: Allegro | Teaser
Tags: validation, javascript
Published: 2020-03-27 21:33:09

---
title: Quartet 9: Allegro | Teaser
published: true
description: It's astonishing result as for me.
tags: validation, javascript
---

I am going to release new version of [Quartet 9: Allegro](https://www.npmjs.com/package/quartet) data validation library.

I wanted to create library that will have four principles:
- simplicity
- minimalism
- similarity of schema and TypeScript type
- performance

## Evaluation of the results

For this type

```typescript
interface Message {
  type: "subscribeAcknowledgement"
  channel: string // with "channel" inside
  data: {
    id: string
    symbol: string
    price: number
    count: number
    accustic: number
    size: number
    mid: number
    last: number
    lastSize: number
    network: number
    open: number
    high: number
    low: number
    volume: number
    interest: number
    change: number
    percents: number
    someNumber: number
    grade: number
    mark: number
    velocity: number
    length: number
    height: number
    width: number
  }
}
```

We have such validation function:

```typescript 
// validator: (value: any) => value is Message
const validator = v<Message>({
  type: "subscribeAcknowledgement",
  channel: v.and(v.string, v.test(/channel/)),
  data: {
    id: v.string,
    symbol: v.string,
    price: v.number,
    count: v.number,
    accustic: v.number,
    size: v.number,
    mid: v.number,
    last: v.number,
    lastSize: v.number,
    network: v.number,
    open: v.number,
    high: v.number,
    low: v.number,
    volume: v.number,
    interest: v.number,
    change: v.number,
    percents: v.number,
    someNumber: v.number,
    grade: v.number,
    mark: v.number,
    velocity: v.number,
    length: v.number,
    height: v.number,
    width: v.number
  }
})
```
Lets compare it with one of the fastest library `ajv` and with one of the most popular library `joi`.

Ajv Validator:
```javascript
const ajvValidator = ajv.compile({
  type: "object",
  required: ["type", "channel", "data"],
  properties: {
    type: {
      type: "string",
      enum: ["subscribeAcknowledgement"]
    },
    channel: {
      type: "string",
      pattern: "channel"
    },
    data: {
      type: "object",
      required: [
        "id",
        "symbol",
        "price",
        "count",
        "accustic",
        "size",
        "mid",
        "last",
        "lastSize",
        "network",
        "open",
        "high",
        "low",
        "volume",
        "interest",
        "change",
        "percents",
        "someNumber",
        "grade",
        "mark",
        "velocity",
        "length",
        "height",
        "width"
      ],
      properties: {
        id: { type: "string" },
        symbol: { type: "string" },
        price: { type: "number" },
        count: { type: "number" },
        accustic: { type: "number" },
        size: { type: "number" },
        mid: { type: "number" },
        last: { type: "number" },
        lastSize: { type: "number" },
        network: { type: "number" },
        open: { type: "number" },
        high: { type: "number" },
        low: { type: "number" },
        volume: { type: "number" },
        interest: { type: "number" },
        change: { type: "number" },
        percents: { type: "number" },
        someNumber: { type: "number" },
        grade: { type: "number" },
        mark: { type: "number" },
        velocity: { type: "number" },
        length: { type: "number" },
        height: { type: "number" },
        width: { type: "number" }
      }
    }
  }
});
```

Joi Validator:

```javascript
const joiSchema = Joi.object({
  type: Joi.equal("subscribeAcknowledgement").required(),
  channel: Joi.string()
    .pattern(/channel/)
    .required(),
  data: Joi.object({
    id: Joi.string().required(),
    symbol: Joi.string().required(),
    price: Joi.number().required(),
    count: Joi.number().required(),
    accustic: Joi.number().required(),
    size: Joi.number().required(),
    mid: Joi.number().required(),
    last: Joi.number().required(),
    lastSize: Joi.number().required(),
    network: Joi.number().required(),
    open: Joi.number().required(),
    high: Joi.number().required(),
    low: Joi.number().required(),
    volume: Joi.number().required(),
    interest: Joi.number().required(),
    change: Joi.number().required(),
    percents: Joi.number().required(),
    someNumber: Joi.number().required(),
    grade: Joi.number().required(),
    mark: Joi.number().required(),
    velocity: Joi.number().required(),
    length: Joi.number().required(),
    height: Joi.number().required(),
    width: Joi.number().required()
  })
});
```

And now, benchmark for this case:

```
joi                x   1,104 ops/sec ±15.76% (80 runs sampled)
Quartet 8          x   1,438 ops/sec ±9.27% (55 runs sampled)
ajv                x  78,991 ops/sec ±2.81% (83 runs sampled)
Quartet 9: Allegro x 149,552 ops/sec ±5.54% (78 runs sampled)
```

![Benchmark results](https://dev-to-uploads.s3.amazonaws.com/i/mxothx9yevd8pgf2ur6o.png)

Why is it so fast? Let's look at it

```javascript
validator.toString()
```

What we see is an actual result:

```javascript
function validator(value) {
  if (value == null) return false
  if (value.type !== "subscribeAcknowledgement") return false
  if (!validator.custom(value.channel)) return false
  if (value.data == null) return false
  if (typeof value.data.id !== 'string') return false
  if (typeof value.data.symbol !== 'string') return false
  if (typeof value.data.price !== 'number') return false
  if (typeof value.data.count !== 'number') return false
  if (typeof value.data.accustic !== 'number') return false
  if (typeof value.data.size !== 'number') return false
  if (typeof value.data.mid !== 'number') return false
  if (typeof value.data.last !== 'number') return false
  if (typeof value.data.lastSize !== 'number') return false
  if (typeof value.data.open !== 'number') return false
  if (typeof value.data.high !== 'number') return false
  if (typeof value.data.low !== 'number') return false
  if (typeof value.data.volume !== 'number') return false
  if (typeof value.data.interest !== 'number') return false
  if (typeof value.data.change !== 'number') return false
  if (typeof value.data.percents !== 'number') return false
  if (typeof value.data.someNumber !== 'number') return false
  if (typeof value.data.grade !== 'number') return false
  if (typeof value.data.mark !== 'number') return false
  if (typeof value.data.velocity !== 'number') return false
  if (typeof value.data.length !== 'number') return false
  if (typeof value.data.height !== 'number') return false
  if (typeof value.data.width !== 'number') return false

  return true
}
```