Nanobenchmarks JavaScript et freins prématurés

Bonjour, je m'appelle Dmitry Karlovsky et avant ... je mesurais ma pipette tous les jours , mais les règles communes n'avaient pas assez de précision pour mesurer de si petites tailles.







J'ai donc décidé qu'il suffisait de l'endurer! ... et j'ai grondé le mien avec des divisions nanométriques, un support pour une mesure froide et chauffée, des tests, des partages et autres libertés. Je vous invite donc à rejoindre cette Olympiade spéciale sur la mesure de la vitesse de votre code JS.







Jetons d'abord un coup d'œil à ce cas:













Cas héréditaire



Ici, nous avons 3 options:







  • monomorphe est lorsque les mêmes types d'arguments sont passés à la même fonction à chaque fois. JIT crée du code optimisé, au début duquel il n'y a qu'une vérification que le type passé est le même.
  • — , ( 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