Backbone.validateAll

JavaScript performance comparison

Revision 4 of this test case created by Greg Franko

Info

To determine the performance benefits from using the Backbone.validateAll plugin to validate only the Model attributes that are set/saved instead of all Model attributes.

Preparation code

<script src='http://code.jquery.com/jquery.js'></script>
<script src='http://underscorejs.org/underscore.js'></script>
<script src='http://backbonejs.org/backbone.js'></script>
<script src='http://gregfranko.com/javascripts/Backbone.validateAll.js'></script>
<script>
Benchmark.prototype.setup = function() {
          var User = Backbone.Model.extend({
              // RegEx Patterns
              // ==============
              patterns: {
   
                  specialCharacters: "[^a-zA-Z 0-9]+",
   
                  digits: "[0-9]",
   
                  email: "^[a-zA-Z0-9._-]+@[a-zA-Z0-9][a-zA-Z0-9.-]*[.]{1}[a-zA-Z]{2,6}$",
   
                  phone: "^([0-9]{3})?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$"
   
              },
   
              // Validators
              // ==========
              validators: {
   
                  minLength: function(value, minLength) {
   
                      return value.length >= minLength;
   
                  },
   
                  maxLength: function(value, maxLength) {
   
                      return value.length <= maxLength;
   
                  },
   
                  pattern: function(value, pattern) {
   
                      return new RegExp(pattern, "gi").test(value) ? true : false;
   
                  },
   
                  isEmail: function(value) {
     
                    return User.prototype.validators.pattern(value, User.prototype.patterns.email);
   
                  },
   
                  isPhone: function(value) {
   
                      return User.prototype.validators.pattern(value, User.prototype.patterns.phone);
   
                  },
   
                  hasSpecialCharacter: function(value) {
     
                    return User.prototype.validators.pattern(value, User.prototype.patterns.specialCharacters);
   
                  },
   
                  hasDigit: function(value) {
                     
                    return User.prototype.validators.pattern(value, User.prototype.patterns.digits);
   
                  }
   
              },        
              validate: function(attrs) {
               
                  var errors = this.errors = {};
             
                  if(attrs.firstname != null) {
                      if (!attrs.firstname) errors.firstname = 'firstname is required';
                      else if(!this.validators.minLength(attrs.firstname, 2)) errors.firstname = 'firstname is too short';
                      else if(!this.validators.maxLength(attrs.firstname, 15)) errors.firstname = 'firstname is too large';
                      else if(this.validators.hasSpecialCharacter(attrs.firstname)) errors.firstname = 'firstname cannot contain special characters';
                  }
   
                  if(attrs.lastname != null) {
   
                      if (!attrs.lastname) errors.lastname = 'lastname is required';
                      else if(!this.validators.minLength(attrs.lastname, 2)) errors.lastname = 'lastname is too short';
                      else if(!this.validators.maxLength(attrs.lastname, 15)) errors.lastname = 'lastname is too large';
                      else if(this.validators.hasSpecialCharacter(attrs.lastname)) errors.lastname = 'lastname cannot contain special characters';  
   
                  }
   
                  if(attrs.password != null) {
   
                      if(!attrs.password) errors.password = 'password is required';
                      else if(!this.validators.minLength(attrs.password, 6)) errors.password = 'password is too short';
                      else if(!this.validators.maxLength(attrs.password, 15)) errors.password = 'password is too big';
                      else if(!this.validators.hasSpecialCharacter(attrs.password)) errors.password = 'password must contain a special character';
                      else if(!this.validators.hasDigit(attrs.password)) errors.password = 'password must contain a digit';
   
                  }          
                 
                  if(attrs.email != null) {
   
                      if (!attrs.email) errors.email = 'email is required';
                      else if(!this.validators.isEmail(attrs.email)) errors.email = 'email is not valid';
   
                  }
               
                  if(attrs.phone != null) {
   
                      if(!attrs.phone) errors.phone = 'phone is required';
                      else if(!this.validators.isPhone(attrs.phone)) errors.phone = 'phone number is invalid';
   
                  }
             
                  if (!_.isEmpty(errors)) return errors;
              }
          });
    var user = new User;
};
</script>

Preparation code output

Test runner

Warning! For accurate results, please disable Firebug before running the tests. (Why?)

Java applet disabled.

Testing in unknown unknown
Test Ops/sec
Default Backbone Validate
user.set({firstname: ""}, { validate: true });
user.set({lastname: ""}, { validate: true });
user.set({password: ""}, { validate: true });
user.set({email: ""}, { validate: true });
user.set({phone: ""}, { validate: true });
pending…
Backbone.validateAll Validate
user.set({firstname: ""}, {validate: true, validateAll: false});
user.set({lastname: ""}, {validate: true, validateAll: false});
user.set({password: ""}, {validate: true, validateAll: false});
user.set({email: ""}, {validate: true, validateAll: false});
user.set({phone: ""}, {validate: true, validateAll: false});
pending…

Compare results of other browsers

Revisions

You can edit these tests or add even more tests to this page by appending /edit to the URL. Here’s a list of current revisions for this page:

0 comments

Add a comment