Nanobenchmarks de JavaScript y frenos prematuros

Hola, mi nombre es Dmitry Karlovsky y antes ... medía mi pipeta todos los días , pero las reglas comunes no tenían la precisión suficiente para medir tamaños tan pequeños.







¡Así que decidí que era suficiente con soportarlo! ... y regañé al mío con divisiones nanométricas, apoyo para una medición fría y acalorada, pruebas, compartir y otras libertades. Así que los invito a unirse a esta Olimpiada especial sobre la medición de la velocidad de su código JS.







Primero, echemos un vistazo a este caso:













Caso hereditario



Aquí tenemos 3 opciones:







  • monomórfico es cuando se pasan los mismos tipos de argumentos a la misma función cada vez. JIT crea código optimizado, al principio del cual solo hay una verificación de que el tipo pasado es el mismo.
  • — , ( 4 Chrome 88, 7 Firefox 85). JIT .
  • — . JIT .


JIT , . , . , . , , , , .







( ), ( ), .







. , 10 , :







class Base {

    p0 = 0
    p1 = 1
    p2 = 2
    p3 = 3
    p4 = 4
    p5 = 5
    p6 = 6
    p7 = 7
    p8 = 8
    p9 = 9

    get s() {
        return (
            + this.p0
            + this.p1
            + this.p2
            + this.p3
            + this.p4
            + this.p5
            + this.p6
            + this.p7
            + this.p8
            + this.p9
        )
    }

}
      
      





:







const Derived = [
    class extends Base { n0 = 0 },
    class extends Base { n1 = 1 },
    class extends Base { n2 = 2 },
    class extends Base { n3 = 3 },
    class extends Base { n4 = 4 },
]
      
      





3 :







const mono = Array.from( {length}, ()=> new Derived[0] )
const poly = Array.from( {length}, (_,i)=> new Derived[i%4] )
const mega = Array.from( {length}, (_,i)=> new Derived[i%5] )
      
      





, — JIT , , . - , 2 . , .







— . , , , , JIT .







— . JIT . , .







, , , . .









. , :







class A {
    p0 = 0
    p1 = 0
    p2 = 0
    p3 = 0
    p4 = 0
    p5 = 0
    p6 = 0
    p7 = 0
    p8 = 0
    p9 = 0
}

class B {
    constructor() {
        this.p0 = 0
        this.p1 = 0
        this.p2 = 0
        this.p3 = 0
        this.p4 = 0
        this.p5 = 0
        this.p6 = 0
        this.p7 = 0
        this.p8 = 0
        this.p9 = 0
    }
}

function C() {
    this.p0 = 0
    this.p1 = 0
    this.p2 = 0
    this.p3 = 0
    this.p4 = 0
    this.p5 = 0
    this.p6 = 0
    this.p7 = 0
    this.p8 = 0
    this.p9 = 0
}
      
      





Chrome 88 :













V8 , , 10 . Firefox 85 :













, , V8 , Firefox , - .









, . , $mol : , , . 3 ..







:







class Dictionary_base {
    constructor( dict ) {
        Object.assign( this , dict )
    }
}
      
      





:







class Initializer_base {
    constructor( init ) {
        if( init ) init( this )
    }
}
      
      





, .







Chrome 88 :













, . Firefox 85 :













. Chrome , Firefox , Firefox, . c .









. . , , . . — . , , . :







const chain = {}
const uid = ()=> Math.random().toString(16).slice(2)

for( let i = 0; i < 100; i++ ){
    chain[ uid() ] = i
}
      
      





. , :







const solid = JSON.parse( JSON.stringify( chain ) )
      
      





, , :







const map = new Map
for( let key in chain ) map.set( key, chain[key] )
      
      





Chrome 88 .













, , — . Firefox 85 — :















, , , :







function fib_sync(n) {
    if( n < 2 ) return 1
    return fib_sync( n - 1 ) + fib_sync( n - 2 )
}

function* fib_gen(n) {
    if( n < 2 ) return 1
    return ( yield* fib_gen( n - 1 ) ) + ( yield* fib_gen( n - 2 ) )
}

async function fib_async(n) {
    if( n < 2 ) return 1
    return ( await fib_async( n - 1 ) ) + ( await fib_async( n - 2 ) )
}
      
      





Chrome 88 :













, — . , . , , . Firefox 85 .









, . - . , . :









. — ISO8601:













, API , dayjs, API, , . dateFns, Date, - , , . .







, — ISO8601:













, JSJoda . dateFns



, Date, .







, , ISO8601 , . :













JSJoda . , $mol_time . .







Firefox 85 JSJoda :













, , , Firefox , JSJoda . , , . , , , .









:

















. , , , . . — , , , .







, .







. {#}



.







, , , , . :







const list = Array.from(
    { length: {#} },
    (_,i)=> new Date( `2015-07-20T07:48:28.${ i % 1000 }Z` ),
})
      
      







. :







  • , .
  • , .


{#}



, , . , - :







res = list[{#}].toString()
      
      







. :







  • , , .
  • , . , .


:







function measure() {

    // common setup code

    // case setup code

    let accum_$qwerty
    const case_$qwerty = iter_$qwerty => {
        // measured code where {#} replaced by iter_$qwerty
        accum_$qwerty = iter_$qwerty
    }
    let time_$qwerty = -performance.now()

    case_$qwerty(0);
    case_$qwerty(1);
    case_$qwerty(2);

    // ...

    time_$qwerty += performance.now()
    // teardown code
    return time_$qwerty
)
      
      





:







function measure() {

    // common setup code

    // case setup code

    let accum_$qwerty
    const case_$qwerty = iter_$qwerty => {
        accum_$qwerty = iter_$qwerty
    }
    let time_$qwerty = -performance.now()

    case_$qwerty(0);
    // measured code where {#} replaced by 0
    case_$qwerty(1);
    // measured code where {#} replaced by 1
    case_$qwerty(2);
    // measured code where {#} replaced by 2

    // ...

    time_$qwerty += performance.now()
    // teardown code
    return time_$qwerty
)
      
      





, . , , , . 20 . .









- , $mol_import, CDN:







const {
    $mol_time_moment: Moment,
    $mol_time_interval: Interval,
    $mol_time_duration: Duration,
} = $mol_import.script('https://unpkg.com/mol_time_all@1.1.12/web.js')
      
      







$mol_assert:







$mol_assert_like( [ 1 ], [ 1 ], [ 2 ] ) // Not like [1] --- [2]
      
      







perf.js.hyoo.ru — , . , . — .







bench.hyoo.ru — , , . : bench.hyoo.ru: JS .







- JS , , , , , .








All Articles