الرباعية 9: اليجرو أداء

عندما تم إنشاء مكتبة التحقق من صحة البيانات الرباعية ، تم تعيين المعالم التالية:



في هذه المقالة ، أود أن أعتبر الأداء quartetوأسبابه.


مقال عن الإيجاز والبساطة سيكون في 4 أبريل.


سنستكشف هذا الجانب بالمقارنة quartetمع ajv آخر أكثر شعبية .


مرحبا بالعالم


سنكتب أبسط اختبار - ما إذا كانت القيمة هي سلسلة "Hello World!".


لمقارنة مكتبات التحقق من الصحة ، هناك حاجة إلى البيانات التي سنقوم بالتحقق منها. وفقًا لذلك ، لهذه المهمة لدينا هذه المجموعات من البيانات الصالحة وغير الصالحة.


const valids = ["Hello World!"];
const invalids = [null, false, undefined, "", 1, Infinity, "Hello World"];

ajv


كما هو الحال دائمًا ، يبدأ كل شيء بالاستيراد:


const Ajv = require("ajv");

إنشاء مثيل "المترجم":


const ajv = new Ajv();

يقبل إدخال Ajv وصفًا تم التحقق منه في شكل مخطط JSON .


لنقم بإنشاء مخطط مناسب لمهمتنا.


const helloWorldSchema = {
  type: "string",
  enum: ["Hello World!"]
};

بعد ذلك ، من الضروري "تجميع" وظيفة التحقق من الصحة ، أي من الدائرة ، الحصول على وظيفة تنتظر إدخال البيانات ، والعودة عند الإخراج true، إذا نجحت عملية التحقق ، وإلا فستعود false.


const ajvValidator = ajv.compile(helloWorldSchema);

منجز!


benchmark.


, :


Ajv Build
661,639 ops/sec
354,725 ops/sec
628,443 ops/sec
659,900 ops/sec
557,037 ops/sec

: 572,349 ops/sec

:


for (let i = 0; i < valids.length; i++) {
  ajvValidator(valids[i]);
}
for (let i = 0; i < invalids.length; i++) {
  ajvValidator(invalids[i]);
}

:


Ajv Validation

21,452,228 ops/sec
 3,066,770 ops/sec
 4,522,850 ops/sec
 2,522,777 ops/sec
 2,741,310 ops/sec

: 6,861,187 ops/sec

— , .


quartet


є «»:


const { v } = require("quartet");

:


const quartetValidator = v("Hello World!");

:


Quartet 9: Allegro Build

6,019,078 ops/sec
3,893,780 ops/sec
2,712,363 ops/sec
5,926,415 ops/sec
2,729,369 ops/sec

: 4,256,201 ops/sec

:


for (let i = 0; i < valids.length; i++) {
  quartetValidator(valids[i]);
}
for (let i = 0; i < invalids.length; i++) {
  quartetValidator(invalids[i]);
}

:


Quartet 9: Allegro Validation

15,073,432 ops/sec
13,711,573 ops/sec
13,123,812 ops/sec
25,617,225 ops/sec
17,588,846 ops/sec

: 17,022,977 ops/sec

:


صورة


صورة



:


console.log("Function");
console.log(quartetValidator.toString());

:


function (value) { return value === c; }

c — , .



. , , .



. API. , :


interface Person {
  id: number; //   
  name: string; //  
  phone: string | null; // null  12  
  phoneBook: {
    [name: string]: string; // 12  
  };
  gender: "male" | "female";
}


const valids = [
  {
    id: 1,
    name: "andrew",
    phone: "380975003434",
    phoneBook: {
      andrew: "380975003434",
      bohdan: "380975003434",
      vasilina: "380975003434"
    },
    gender: "male"
  },
  {
    id: 2,
    name: "bohdan",
    phone: null,
    phoneBook: {},
    gender: "male"
  },
  {
    id: 3,
    name: "Elena",
    phone: null,
    phoneBook: {
      siroja: "380975003434"
    },
    gender: "female"
  }
];

const invalids = [
  null, //  
  false, //  
  undefined, //  
  "", //  
  1, //  
  Infinity, //  
  "Hello World", //  
  {
    id: 0, //   
    name: "andrew",
    phone: "380975003434",
    phoneBook: {
      andrew: "380975003434",
      bohdan: "380975003434",
      vasilina: "380975003434"
    },
    gender: "male"
  },
  {
    //  id
    name: "andrew",
    phone: "380975003434",
    phoneBook: {
      andrew: "380975003434",
      bohdan: "380975003434",
      vasilina: "380975003434"
    },
    gender: "male"
  },
  {
    id: 1.5, //  
    name: "andrew",
    phone: "380975003434",
    phoneBook: {
      andrew: "380975003434",
      bohdan: "380975003434",
      vasilina: "380975003434"
    },
    gender: "male"
  },
  {
    id: 1,
    name: "", //  
    phone: "380975003434",
    phoneBook: {
      andrew: "380975003434",
      bohdan: "380975003434",
      vasilina: "380975003434"
    },
    gender: "male"
  },
  {
    id: 1,
    //  name
    phone: "380975003434",
    phoneBook: {
      andrew: "380975003434",
      bohdan: "380975003434",
      vasilina: "380975003434"
    },
    gender: "male"
  },
  {
    id: 1,
    name: "andrew",
    phone: "38097500434", // 11 
    phoneBook: {
      andrew: "380975003434",
      bohdan: "380975003434",
      vasilina: "380975003434"
    },
    gender: "male"
  },
  {
    id: 1,
    name: "andrew",
    //  phone
    phoneBook: {
      andrew: "380975003434",
      bohdan: "380975003434",
      vasilina: "380975003434"
    },
    gender: "male"
  },
  {
    id: 1,
    name: "andrew",
    phone: "380975003434",
    phoneBook: {
      andrew: "380975003434",
      bohdan: "380975003434",
      vasilina: "38097503434" // 11 
    },
    gender: "male"
  },
  {
    id: 1,
    name: "andrew",
    phone: "380975003434",
    // phoneBook 
    gender: "male"
  },
  {
    id: 1,
    name: "andrew",
    phone: "380975003434",
    phoneBook: {
      andrew: "380975003434",
      bohdan: "380975003434",
      vasilina: "380975003434"
    },
    gender: "Male" // 'male'
  },
  {
    id: 1,
    name: "andrew",
    phone: "380975003434",
    phoneBook: {
      andrew: "380975003434",
      bohdan: "380975003434",
      vasilina: "380975003434"
    }
  }
];

ajv


:


const personSchema = {
  type: "object",
  required: ["id", "name", "phone", "phoneBook", "gender"],
  properties: {
    id: {
      type: "integer",
      exclusiveMinimum: 0
    },
    name: {
      type: "string",
      minLength: 1
    },
    phone: {
      anyOf: [
        { type: "null" },
        {
          type: "string",
          pattern: "^\\d{12}$"
        }
      ]
    },
    phoneBook: {
      type: "object",
      additionalProperties: {
        type: "string",
        pattern: "^\\d{12}$"
      }
    },
    gender: {
      type: "string",
      enum: ["male", "female"]
    }
  }
};

:


const ajvCheckPerson = ajv.compile(personSchema);

:


Ajv Build

79,476 ops/sec
78,334 ops/sec
61,752 ops/sec
77,395 ops/sec
78,539 ops/sec
51,922 ops/sec
80,031 ops/sec
77,687 ops/sec
65,439 ops/sec
79,805 ops/sec

: 73,038 ops/sec

:


for (let i = 0; i < valids.length; i++) {
  ajvCheckPerson(valids[i]);
}
for (let i = 0; i < invalids.length; i++) {
  ajvCheckPerson(invalids[i]);
}

:


Ajv Validation

227,640 ops/sec
301,134 ops/sec
190,450 ops/sec
195,595 ops/sec
384,380 ops/sec
193,358 ops/sec
385,280 ops/sec
239,009 ops/sec
193,832 ops/sec
392,808 ops/sec

: 270,349 ops/sec

quartet


:


const quartetCheckPerson = v({
  id: v.and(v.safeInteger, v.positive),
  name: v.and(v.string, v.minLength(1)),
  phone: [null, v.test(/^\d{12}$/)],
  phoneBook: {
    [v.rest]: v.test(/^\d{12}$/)
  },
  gender: ["male", "female"]
});

:


Quartet 9: Allegro Build

35,564 ops/sec
14,401 ops/sec
15,438 ops/sec
26,852 ops/sec
33,935 ops/sec
16,010 ops/sec
34,550 ops/sec
33,148 ops/sec
16,037 ops/sec
36,828 ops/sec

: 26,276 ops/sec

:


for (let i = 0; i < valids.length; i++) {
  quartetCheckPerson(valids[i]);
}
for (let i = 0; i < invalids.length; i++) {
  quartetCheckPerson(invalids[i]);
}

, :


Quartet 9: Allegro Validation

237,059 ops/sec
435,844 ops/sec
248,021 ops/sec
238,931 ops/sec
416,993 ops/sec
281,904 ops/sec
439,975 ops/sec
242,074 ops/sec
330,487 ops/sec
421,704 ops/sec

: 329,299 ops/sec

:


صورة
صورة



, , quartetCheckPerson .


console.log(quartetCheckPerson.toString());
console.log({ ...quartetCheckPerson });


function validator(value) {
  if (value == null) return false
  if (!Number.isSafeInteger(value.id)) return false
  if (value.id <= 0) return false
  if (typeof value.name !== 'string') return false
  if (value.name == null || value.name.length < 1) return false
  if (!validator["value.phone"](value.phone)) return false
  if (value.phoneBook == null) return false
  validator.keys = Object.keys(value.phoneBook)
  for (let i = 0; i < validator.keys.length; i++) {
    validator.elem = value.phoneBook[validator.keys[i]]
    if (!validator["tester-1"].test(validator.elem)) return false
  }

  if (!validator["value.gender"](value.gender)) return false
  return true
};

// Check person properties
{
  'value.phone': function validator(value) {
    if (value === null) return true;
    if (validator.tester.test(value)) return true;
    return false
  }
  ['value.phone']['tester']: /^\d{12}$/,
  'tester-1': /^\d{12}$/,
  'value.gender': function validator(value) {
    if (validator.__validValuesDict[value] === true) return true
    return false
  },
  ['value.gender']['__validValuesDict']: {
    male: true,
    female: true
  }
}

— , — .


:


ajv


— ajv , errors.


quartet


quartet - .


:


1) v.custom. — , explanations , . — —


:


const checkId = v(v.and(v.safeInteger, v.positive));
const checkName = v(v.and(v.string, v.minLength(1)));
const checkPhone = v([null, v.test(/^\d{12}$/)]);
const checkPhoneBookItem = v(v.test(/^\d{12}$/));
const checkGender = v(["male", "female"]);

const quartetCheckPerson = v({
    id: v.custom(checkId, "id"),
    name: v.custom(checkName, "name"),
    phone: v.custom(checkPhone, "phone"),
    phoneBook: {
      [v.rest]: v.custom(checkPhoneBookItem, "phoneBook")
    },
    gender: v.custom(checkGender, "gender")
  }); 

// quartetCheckPerson({}) // false
// quartetCheckPerson.explanations // ['id']

إجراء القياسات:
صورة
صورة


2) الطريقة الثانية هي أكثر أيديولوجية - باستخدام التفسيرات المخصصة بشكل افتراضي. سيتم استدعاء دالة errorBoundary بمجرد أن يقوم أحد المراجعين بإرجاع false.


import { quartet } from 'quartet'
const v = quartet({
  errorBoundary(explanations, { value, id, schema, innerExplanations }) {
    explanations.push(...innerExplanations, { value, id, schema })
  }
})

const checkPerson = v({
  id: v.and(v.safeInteger, v.positive),
  name: v.and(v.string, v.minLength(1)),
  phone: [null, v.test(/^\d{12}$/)],
  phoneBook: {
    [v.rest]: v.test(/^\d{12}$/)
  },
  gender: ["male", "female"]
});

// checkPerson(null) // false
// checkPerson.explanations // [{ value: null, id: 'value', schema: { id: ... }]

إجراء القياسات:


صورة
صورة


ملخص


أعطت المقارنة نتائج مختلطة. بالنسبة لأولئك الذين يحتاجون إلى الأداء والشرح - اختر ajv. بالنسبة لأولئك الذين لا يحتاجون إلى تفسيرات للإعاقات - خذوا الرباعية - وحصلوا على أداء أكثر مع مخطط أكثر قابلية للقراءة والتعبير.
لقد شجعتني هذه النتيجة. آمل أن يرغب القارئ في التجربة quartet@9عمليًا.


شكرا للقراءة ، من الممتع قراءة التعليقات.


All Articles