TypedJSON icon indicating copy to clipboard operation
TypedJSON copied to clipboard

Performance?

Open gerleim opened this issue 7 years ago • 3 comments
trafficstars

Nice work! Any measurement of using TypedJSON vs plain JSON (not typed) or other methods of deserialization?

gerleim avatar Jan 31 '18 15:01 gerleim

Thank you, @gerleim

I'm afraid no such thing has been done up until now, as we never experienced performance issues in AudioNodes regarding TypedJSON (and we are serializing/deserializing "rather large" structures).

That said, it should be easy to measure performance for one particular case. What TypedJSON does is nothing more than a simple set of 2-way conversions between these 3 steps:

json <-> untyped object tree <-> typed object tree

JSON.stringify and JSON.parse are used internally with the untyped object tree, so everything else is TypedJSON doing the conversions.

With that in mind, given an object tree o with every single property annotated properly (so that no properties are skipped), the execution time difference between calling JSON.stringify(o) and TypedJSON.stringify(o) should accurately represent the overhead added by TypedJSON.

Similarly for de-serialization, given a JSON string s, the difference between JSON.parse(s) and TypedJSON.parse(s) should accurately represent the overhead added by TypedJSON, given the JSON is an exact representation of an object tree (i.e. no extra objects in JSON).

JohnWeisz avatar Feb 22 '18 17:02 JohnWeisz

@JohnWeisz @gerleim

I've ran a test.

Program 1 : Without TypedJSON

//tslint:disable
const microtime = require('microtime')
const startTime = microtime.now();

const json = '{ "first_name": "John", "last_name": "Doe"}';

class User {
  
  constructor(
    public first_name: string,
    public last_name: string
  ) {
  }
  
  public getFullName = (): string => {
    return this.first_name + ' ' + this.last_name;
  };
  
  public static fromJSON = (json: string): User => {
    const jsonObject = JSON.parse(json);
    return new User(
      jsonObject.first_name,
      jsonObject.last_name
    );
  };
}

const user: User = User.fromJSON(json);

console.log(user.first_name); // Works, prints "John"
console.log(user.last_name); // Works, prints "Doe"
console.log(user.getFullName()); //Error: TypeError: user.getFullName is not a function

const endTime = microtime.now();
console.log(`Took ${endTime - startTime}  microseconds`);


Program 2: With TypedJSON

//tslint:disable
const microtime = require('microtime')
const startTime = microtime.now();

import { JsonMember, JsonObject, TypedJSON } from 'typedjson-npm';

const json = '{ "first_name": "John", "last_name": "Doe"}';

@JsonObject
class User {
  
  @JsonMember({ type: String })
  first_name: string;
  
  @JsonMember({ type: String })
  last_name: string;
  
  public getFullName = (): string => {
    return this.first_name + ' ' + this.last_name;
  };
}


const user: User = TypedJSON.parse(json, User);

console.log(user.first_name);
console.log(user.last_name);
console.log(user.getFullName());

const endTime = microtime.now();
console.log(`Took ${endTime - startTime} microseconds`);

Output : Program 1 : Without TypedJSON

John
Doe
John Doe
Took 1471  microseconds

Output : Program 2 : With TypedJSON

John
Doe
John Doe
Took 5364 microseconds

I am not pro in benchmarking stuff. This is my first time I am comparing performance. Can this test considered as a valid one ?

theapache64 avatar Jun 28 '18 09:06 theapache64

Test with nested object

Without TypedJSON

//tslint:disable
const microtime = require('microtime')
const startTime = microtime.now();

const json = '{ "first_name": "John", "last_name": "Doe","car":{"name":"BMW","series":"2018"}}';

class Car {
    constructor(
      public name : string,
      public series : string
    ){}
    
    public getNameWithSeries(){
      return this.name+' '+this.series
    }
}

class User {
  
  constructor(
    public first_name: string,
    public last_name: string,
    public car : Car
  ) {
  }
  
  public getFullName = (): string => {
    return this.first_name + ' ' + this.last_name;
  };
  
  public static fromJSON = (json: string): User => {
    const jsonObject = JSON.parse(json);
    return new User(
      jsonObject.first_name,
      jsonObject.last_name,
      new Car(
        jsonObject.car.name,
        jsonObject.car.series,
      )
    );
  };
}

const user: User = User.fromJSON(json);

console.log(`First name : ${user.first_name}`);
console.log(`Last name : ${user.last_name}`);
console.log(`Full name : ${user.getFullName()}`);
console.log(`Car with series : ${user.car.getNameWithSeries()}`);

const endTime = microtime.now();
console.log(`Took ${endTime - startTime}  microseconds`);

With TypedJSON

//tslint:disable const microtime = require('microtime') const startTime = microtime.now();

import { JsonMember, JsonObject, TypedJSON } from 'typedjson-npm';

const json = '{ "first_name": "John", "last_name": "Doe","car":{"name":"BMW","series":"2018"}}';

@JsonObject
class Car{
  
  @JsonMember({type : String})
  name : string
  
  @JsonMember({type : String})
  series : string
  
  public getNameWithSeries = () =>{
    return this.name + ' '+  this.series;
  }
}

@JsonObject
class User {
  
  @JsonMember({type : String})
  first_name: string;
  
  @JsonMember({type : String})
  last_name: string;
  
  @JsonMember({type : Car})
  car : Car
  
  public getFullName = (): string => {
    return this.first_name + ' ' + this.last_name;
  };
}

const user: User = TypedJSON.parse(json, User);

console.log(`First name : ${user.first_name}`);
console.log(`Last name : ${user.last_name}`);
console.log(`Full name : ${user.getFullName()}`);
console.log(`Car with series : ${user.car.getNameWithSeries()}`);

const endTime = microtime.now();
console.log(`Took ${endTime - startTime}  microseconds`);

Output : With TypedJSON

First name : John
Last name : Doe
Full name : John Doe
Car with series : BMW 2018
Took 5604  microseconds

Output : Without TypedJSON

First name : John
Last name : Doe
Full name : John Doe
Car with series : BMW 2018
Took 1684  microseconds

theapache64 avatar Jun 28 '18 10:06 theapache64