Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Typia Generates Unused Functions in Validation Code Paths #515

Closed
sinclairzx81 opened this issue Feb 20, 2023 · 1 comment
Closed

Typia Generates Unused Functions in Validation Code Paths #515

sinclairzx81 opened this issue Feb 20, 2023 · 1 comment
Assignees
Labels
bug Something isn't working
Projects

Comments

@sinclairzx81
Copy link
Contributor

Bug Report

Typia seems to be generating unused functions in validation code paths

Repro

import typia from 'typia'

interface Point3D {
  x: number
  y: number
  z: number
}

interface Simple {
  scale: Point3D,
  position: Point3D,
  rotate: Point3D,
  pivot: Point3D
}

const X = typia.is<Simple>({})

Emit

Note the function $io1 is emitted but never used.

"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const typia_1 = __importDefault(require("typia"));
const X = (input => {
    const $io0 = input => "object" === typeof input.scale && null !== input.scale && ("number" === typeof input.scale.x && "number" === typeof input.scale.y && "number" === typeof input.scale.z) && ("object" === typeof input.position && null !== input.position && ("number" === typeof input.position.x && "number" === typeof input.position.y && "number" === typeof input.position.z)) && ("object" === typeof input.rotate && null !== input.rotate && ("number" === typeof input.rotate.x && "number" === typeof input.rotate.y && "number" === typeof input.rotate.z)) && ("object" === typeof input.pivot && null !== input.pivot && ("number" === typeof input.pivot.x && "number" === typeof input.pivot.y && "number" === typeof input.pivot.z));
    const $io1 = input => "number" === typeof input.x && "number" === typeof input.y && "number" === typeof input.z;
     // ^ $io1 function is defined in the validation HOT path, but never used.
    return "object" === typeof input && null !== input && $io0(input);
})({});

Performance

As per #513 (comment), I've followed up and run a few more performance tests on Typia comparing NaN and non-NaN assertions for JIT (which is how I've noticed this issue). The following is the results for the non-NaN checking case for TypeBox.

image

In theory, AOT should perform much faster than JIT here (and in pretty much all cases). In local testing I've run, I usually see around 10-20% performance degrade for using JIT. So in theory, Typia should be seeing upwards 20,000x (estimate)

Micro Benchmark

You can run the following script to test performance degradation for function definitions in hot code paths.

{ // with unused function
    const S = Date.now()
    for(let i = 0; i < 1_000_000_000; i++) {
        const f = () => {} // unused
        const x = typeof 10 === 'number'
    }
    console.log(Date.now() - S) // 1166ms
}
{ // without unused function
    const S = Date.now()
    for(let i = 0; i < 1_000_000_000; i++) {
        const x = typeof 10 === 'number'
    }
    console.log(Date.now() - S) // 360ms
}

Notes

Comparing the validation routines for JIT / AOT, I don't see a lot of difference in terms of assertion logic. I think if you omit the unused $io1 function you're likely going to see an immediate performance boost. Also, you may get a bit more of a performance by inlining the $io0 function as a single conditional expression (this to avoid the function call / new stack frame).

In either case, it's probably going to be good to omit the unused function (if only to reduce JS output)
Anyway, Hope this helps
S

PS: Feel free to keep the AllowNaN = true in the TypeBox benchmarks!

@samchon
Copy link
Owner

samchon commented Feb 20, 2023

You're right. I can't publish #509 because of unused local variables and parameters.

I have to fix it.

@samchon samchon self-assigned this Feb 20, 2023
@samchon samchon added the bug Something isn't working label Feb 20, 2023
@samchon samchon added this to To do in v3.6 Update via automation Feb 20, 2023
samchon added a commit that referenced this issue Feb 21, 2023
Fix #515 - remove unused locals, but not perfect yet
v3.6 Update automation moved this from To do to Done Feb 21, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
No open projects
Development

No branches or pull requests

2 participants