CPAN is a software modules repository famous for the sheer number of solutions it offers free of charge. Not all of them do different things though, and in some cases its pushing TIMTOWTDI to its limits. Sometimes choosing the right module for the job is easy, but when its not you have to compare them in one way or another.
While speed of execution may not be the most important factor in choosing a solution, it can speak for the code quality and feature design. Two programs written in the same language doing exactly the same thing should have quite comparable run times, but feature creep, code bloat or inefficient algorithms could increase that time beyond acceptable level. Some modules can also implement interesting optimization strategies, while others may not or could not due to different design goals.
In this article, I am going to present benchmark results ran on my machine. You should probably try it out yourself on yours too! Source code for these benchmarks can be viewed at https://github.com/bbrtj/perl-validator-benchmark.
Benchmark setup
We're going to see how the following libraries fare against each other in validating a hash reference:
- Data::MuForm
A form framework that was recommended to me on #perl IRC. Even though I haven't used it in any serious project, it seems pretty comprehensive and is capable of more than just validating data (like rendering). It has some maintenance issues, but has seen some activity lately.
- Data::Sah
A very interesting module that lets you compile your rules into a single expression in Perl, JavaScript or human language. It implements a schema language for validating structures called Sah.
- Form::Toolkit
Moose-based, role-heavy framework that can be extended by creating more Moose classes and roles. It focuses on validating the data and doesn't care from where it came from. Was not updated in years, but still passes all tests and noone has reported any issues.
- Form::Tiny
Lightweight data validator inspired by Laravel validation system, Form::Toolkit and Type::Tiny. It does not contain any field validation code, and instead depends on Type::Tiny constraints to deliver them.
- HTML::FormHandler
Very similar to Data::MuForm, but seems to have more rendering and other non-validation capabilities. The most ++'ed module of them all.
- JSON::Schema::Modern
A comprehensive perl implementation of a validator using json schema.
- JSON::Schema::Tiny
A slimmed down version of JSON::Schema::Modern from the same author.
- Type::Tiny
Pure type-based check. Other validators may already use Type::Tiny, but here we just construct a pure Type::Tiny nested structure and validate with that. Yes, that's possible.
- Valiant
Recent addition to CPAN, presented at the last conference. Inspired by Ruby on Rails and meant to be used together with Moo. Marked as early release in the documentation.
- Validate::Tiny
Possibly the smallest validation library on CPAN. May be basic, but thanks to that you have full control over what's going on, and hopefully better performance.
- Validator::LIVR
Perl implementation of Language Independent Validation Rules.
Code for each case and each validator can be viewed in the project's repository.
Case #1: a single field
This will be the most basic hash reference with just a single value:
{
a => 2
}
We don't check for the value here, we just want 'a'
existence in $data
to be ensured.
Results
Rate Speedup vs previous
HtmlFormHandler 1048/s --
JsonSchemaModern 1530/s 45%
DataMuForm 5173/s 238%
JsonSchemaTiny 15576/s 201%
ValidatorLivr 34594/s 122%
FormToolkit 34855/s 0%
Valiant 45882/s 31%
FormTiny 64478/s 40%
TypeTiny 102492/s 58%
ValidateTiny 144608/s 41%
DataSah 479967/s 231%
Case #2: multiple fields
A little more complex case, which involves five fields which are all required and string:
{
a => 'test1',
b => 'test2',
c => 'test3',
d => 'test4',
e => 'test5',
}
Results of this case can be used to determine how efficiently each framework is traversing a flat structure.
Results
Rate Speedup vs previous
HtmlFormHandler 485/s --
JsonSchemaModern 761/s 56%
DataMuForm 1856/s 143%
JsonSchemaTiny 2234/s 20%
ValidatorLivr 10683/s 378%
FormToolkit 15208/s 42%
Valiant 17324/s 13%
ValidateTiny 30450/s 75%
FormTiny 31392/s 3%
TypeTiny 35353/s 12%
DataSah 152641/s 331%
Case #3: array of nested hashes
The last case is an array of 100 hashes:
{
a => [{
b => 5,
c => 'text',
}, {
b => -1,
c => 'another text',
}, {
b => 1000,
c => 'and another',
}, # and 97 hashes more
]
}
This should not only test the framework's ability to validate such structure, but also whether its performance goes down linearly with data amount, or exponentially.
Results
Rate Speedup vs previous
DataMuForm 1.98/s --
HtmlFormHandler 7.74/s 290%
JsonSchemaModern 35.5/s 358%
JsonSchemaTiny 45.2/s 27%
Valiant 167/s 269%
FormToolkit 306/s 83%
ValidateTiny 600/s 96%
FormTiny 756/s 26%
ValidatorLivr 1830/s 142%
DataSah 2434/s 33%
TypeTiny 5986/s 145%
Conclussion
Left as an exercise for the reader. Now that the numbers are out, you can do with them as you please.
This article has been rewritten. The old version can be viewed here
feedback@bbrtj.eu
Published on 2021-10-19