bun add mitata
npm install mitata
попробуйте mitata в браузере с помощником AI по адресу https://bolt.new/~/mitata
node --expose-gc ...
)javascript | С++ один заголовок |
---|---|
import { run , bench , boxplot } from 'mitata' ;
function fibonacci ( n ) {
if ( n <= 1 ) return n ;
return fibonacci ( n - 1 ) + fibonacci ( n - 2 ) ;
}
bench ( 'fibonacci(40)' , ( ) => fibonacci ( 40 ) ) ;
boxplot ( ( ) => {
bench ( 'Array.from($size)' , function * ( state ) {
const size = state . get ( 'size' ) ;
yield ( ) => Array . from ( { length : size } ) ;
} ) . range ( 'size' , 1 , 1024 ) ;
} ) ;
await run ( ) ; | # include " src/mitata.hpp "
int fibonacci ( int n) {
if (n <= 1 ) return n;
return fibonacci (n - 1 ) + fibonacci (n - 2 );
}
int main () {
mitata::runner runner;
runner. bench ( " noop " , []() { });
runner. summary ([&]() {
runner. bench ( " empty fn " , []() { });
runner. bench ( " fibonacci " , []() { fibonacci ( 20 ); });
});
auto stats = runner. run ();
} |
import { run } from 'mitata' ;
await run ( { format : 'mitata' , colors : false } ) ; // default format
await run ( { filter : / new Array.* / } ) // only run benchmarks that match regex filter
await run ( { throw : true } ) ; // will immediately throw instead of handling error quietly
// c++
auto stats = runner . run ( { . colors = true , . format = "json" , . filter = std :: regex ( ".*" ) } ) ;
В средах выполнения, которые предоставляют gc (например, Bun, node --expose-gc ...
), mitata будет автоматически запускать сбор мусора перед каждым тестом.
Это поведение можно дополнительно настроить с помощью функции gc
в каждом тесте (вы должны делать это только в случае крайней необходимости — большие всплески gc):
bench ( 'lots of allocations' , ( ) => {
Array . from ( { length : 1024 } , ( ) => Array . from ( { length : 1024 } , ( ) => new Array ( 1024 ) ) ) ;
} )
// false | 'once' (default) | 'inner'
// once runs gc after warmup
// inner runs gc after warmup and before each (batch-)iteration
. gc ( 'inner' ) ;
В готовом виде mitata может определять движок/время выполнения, на котором он работает, и возвращаться к использованию альтернативных нестандартных функций ввода-вывода. Если ваш движок или среда выполнения не поддерживаются, откройте проблему или запросите поддержку.
$ xs bench.mjs
$ quickjs bench.mjs
$ d8 --expose-gc bench.mjs
$ spidermonkey -m bench.mjs
$ graaljs --js.timer-resolution=1 bench.mjs
$ /System/Library/Frameworks/JavaScriptCore.framework/Versions/Current/Helpers/jsc bench.mjs
// bench.mjs
import { print } from './src/lib.mjs' ;
import { run , bench } from './src/main.mjs' ; // git clone
import { run , bench } from './node_modules/mitata/src/main.mjs' ; // npm install
print ( 'hello world' ) ; // works on every engine
С другими библиотеками для тестирования производительности зачастую довольно сложно легко создавать тесты, которые выходят за диапазон или запускают одну и ту же функцию с разными аргументами без написания спагетти-кода, но теперь с mitata преобразование вашего теста для использования аргументов — это всего лишь вызов функции.
import { bench } from 'mitata' ;
bench ( function * look_mom_no_spaghetti ( state ) {
const len = state . get ( 'len' ) ;
const len2 = state . get ( 'len2' ) ;
yield ( ) => new Array ( len * len2 ) ;
} )
. args ( 'len' , [ 1 , 2 , 3 ] )
. range ( 'len' , 1 , 1024 ) // 1, 8, 64, 512...
. dense_range ( 'len' , 1 , 100 ) // 1, 2, 3 ... 99, 100
. args ( { len : [ 1 , 2 , 3 ] , len2 : [ '4' , '5' , '6' ] } ) // every possible combination
В случаях, когда вам нужна уникальная копия значения для каждой итерации, mitata поддерживает создание вычисляемых параметров, которые не учитываются в результатах тестирования (примечание: нет никакой гарантии времени пересчета, порядка или количества вызовов) :
bench ( 'deleting $keys from object' , function * ( state ) {
const keys = state . get ( 'keys' ) ;
const obj = { } ;
for ( let i = 0 ; i < keys ; i ++ ) obj [ i ] = i ;
yield {
[ 0 ] ( ) {
return { ... obj } ;
} ,
bench ( p0 ) {
for ( let i = 0 ; i < keys ; i ++ ) delete p0 [ i ] ;
} ,
} ;
} ) . args ( 'keys' , [ 1 , 10 , 100 ] ) ;
bun add @mitata/counters
npm install @mitata/counters
поддерживается: macos (apple silicon) | linux (amd64, aarch64)
Установив пакет @mitata/counters
вы сможете включить сбор и отображение аппаратных счетчиков для тестов.
------------------------------------------- -------------------------------
new Array ( 1024 ) 332.67 ns/iter 337 . 90 ns █
( 295.63 ns … 507 . 93 ns ) 455 . 66 ns ▂██▇▄▂▂▂▁▂▁▃▃▃▂▂▁▁▁▁▁
2 . 41 ipc ( 48.66 % stalls ) 37 . 89 % L1 data cache
1.11 k cycles 2.69 k instructions 33.09 % retired LD / ST ( 888.96 )
new URL ( google . com ) 246 . 40 ns /iter 245 . 10 ns █▃
( 206.01 ns … 841 . 23 ns ) 302 . 39 ns ▁▁▁▁▂███▇▃▂▂▂▂▂▂▂▁▁▁▁
4 . 12 ipc ( 1.05 % stalls ) 98 . 88 % L1 data cache
856.49 cycles 3.53 k instructions 28.65 % retired LD / ST ( 1.01 k )
Для тех, кто любит проводить микротесты, mitata может автоматически обнаруживать и информировать вас о проходах оптимизации, таких как устранение мертвого кода, не требуя каких-либо специальных флагов движка.
-------------------------------------- -------------------------------
1 + 1 318.63 ps/iter 325 . 37 ps ▇ █ !
( 267.92 ps … 14 . 28 ns ) 382 . 81 ps ▁▁▁▁▁▁▁█▁▁█▁▁▁▁▁▁▁▁▁▁
empty function 319 . 36 ps /iter 325 . 37 ps █ ▅ !
( 248.62 ps … 46 . 61 ns ) 382 . 81 ps ▁▁▁▁▁▁▃▁▁█▁█▇▁▁▁▁▁▁▁▁
! = benchmark was likely optimized out ( dead code elimination )
Благодаря возможностям рендеринга ascii mitata теперь вы можете легко визуализировать образцы в виде гистограмм, коробчатых диаграмм, линейных диаграмм, гистограмм и получать четкие сводные данные без каких-либо дополнительных инструментов или зависимостей.
-------------------------------------- -------------------------------
1 + 1 318.11 ps/iter 325 . 37 ps ▇ █ !
( 267.92 ps … 11 . 14 ns ) 363 . 97 ps ▁▁▁▁▁▁▁▁█▁▁▁█▁▁▁▁▁▁▁▁
Date . now ( ) 27.69 ns/iter 27 . 48 ns █
( 27.17 ns … 44 . 10 ns ) 32 . 74 ns ▃█▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
┌ ┐
1 + 1 ┤■ 318.11 ps
Date . now ( ) ┤■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 27.69 ns
└ ┘
-------------------------------------- -------------------------------
Bubble Sort 2.11 ms/iter 2 . 26 ms █
( 1.78 ms … 6 . 93 ms ) 4 . 77 ms ▃█▃▆▅▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
Quick Sort 159 . 60 µs /iter 154 . 50 µs █
( 133.13 µs … 792 . 21 µs ) 573 . 00 µs ▅█▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
Native Sort 97 . 20 µs /iter 97 . 46 µs ██
( 90.88 µs … 688 . 92 µs ) 105 . 00 µs ▁▁▂▁▁▂▇██▇▃▃▃▃▃▂▂▂▁▁▁
┌ ┐
╷┌─┬─┐ ╷
Bubble Sort ├┤ │ ├───────────────────────┤
╵└─┴─┘ ╵
┬ ╷
Quick Sort │───┤
┴ ╵
┬
Native Sort │
┴
└ ┘
90 . 88 µs 2 . 43 ms 4 . 77 ms
-------------------------------------- -------------------------------
new Array ( 1 ) 3.57 ns/iter 3 . 20 ns 6 . 64 ns ▁█▄▂▁▁▁▁▁▁
new Array ( 8 ) 5 . 21 ns /iter 4 . 31 ns 8 . 85 ns ▁█▄▁▁▁▁▁▁▁
new Array ( 64 ) 17 . 94 ns /iter 13 . 40 ns 171 . 89 ns █▂▁▁▁▁▁▁▁▁
new Array ( 512 ) 188 . 05 ns /iter 246 . 88 ns 441 . 81 ns █▃▃▃▃▂▂▁▁▁
new Array ( 1024 ) 364 . 93 ns /iter 466 . 91 ns 600 . 34 ns █▄▁▁▁▅▅▃▂▁
Array . from ( 1 ) 29 . 73 ns /iter 29 . 24 ns 36 . 88 ns ▁█▄▃▂▁▁▁▁▁
Array . from ( 8 ) 33 . 96 ns /iter 32 . 99 ns 42 . 45 ns ▂█▄▂▂▁▁▁▁▁
Array . from ( 64 ) 146 . 52 ns /iter 143 . 82 ns 310 . 93 ns █▅▁▁▁▁▁▁▁▁
Array . from ( 512 ) 1 . 11 µs /iter 1 . 18 µs 1 . 34 µs ▃▅█▂▆▅▄▂▂▁
Array . from ( 1024 ) 1 . 98 µs /iter 2 . 09 µs 2 . 40 µs ▃█▃▃▇▇▄▂▁▁
summary
new Array ( $len )
5 . 42 … 8 . 33 x faster than Array . from ( $len )
┌ ┐
Array . from ( $size ) ⢠⠊
new Array ( $size ) ⢀⠔⠁
⡠⠃
⢀⠎
⡔⠁
⡠⠊
⢀⠜
⡠⠃
⡔⠁
⢀⠎
⡠⠃
⢀⠜
⢠⠊ ⣀⣀⠤⠤⠒
⡰⠁ ⣀⡠⠤⠔⠒⠊⠉
⣀⣀⣀⠤⠜ ⣀⡠⠤⠒⠊⠉
⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣔⣒⣒⣊⣉⠭⠤⠤⠤⠤⠤⠒⠊⠉
└ ┘
Если вам не нужна вся ерунда, которая поставляется с mitata, или вам просто нужны необработанные результаты, mitata экспортирует свои фундаментальные строительные блоки, чтобы вы могли легко создавать свои собственные инструменты и оболочки, не теряя при этом каких-либо основных преимуществ использования mitata.
# include " src/mitata.hpp "
int main () {
auto stats = mitata::lib::fn ([]() { /* * */ })
}
import { B , measure } from 'mitata' ;
// lowest level for power users
const stats = await measure ( function * ( state ) {
const size = state . get ( 'x' ) ;
yield ( ) => new Array ( size ) ;
} , {
args : { x : 1 } ,
batch_samples : 5 * 1024 ,
min_cpu_time : 1000 * 1e6 ,
} ) ;
// explore how magic happens
console . log ( stats . debug ) // -> jit optimized source code of benchmark
// higher level api that includes mitata's argument and range features
const b = new B ( 'new Array($x)' , state => {
const size = state . get ( 'x' ) ;
for ( const _ of state ) new Array ( size ) ;
} ) . args ( 'x' , [ 1 , 5 , 10 ] ) ;
const trial = await b . run ( ) ;
mitata расширяет возможности JavaScript с помощью циклов измерения с нулевыми издержками, генерируемых jit, для обеспечения таймингов с высоким разрешением. Это позволяет предоставлять такие функции, как тактовая частота процессора и обнаружение мертвого кода, не требуя доступа за пределами песочницы js.
clk : ~ 3 . 13 GHz
cpu : Apple M2 Pro
runtime : node 22 . 8 . 0 ( arm64-darwin )
benchmark avg ( min … max ) p75 p99 ( min … top 1 % )
-------------------------------------- -------------------------------
noop 93 . 09 ps /iter 91 . 55 ps █ !
( 61.04 ps … 20 . 30 ns ) 101 . 81 ps ▁▁▁▁▁▁▁▁▁▁▂▁▁▁▁█▁▁▁▁▂
! = benchmark was likely optimized out ( dead code elimination )
// vs other libraries
16041 . 00 ns /iter - node : perf_hooks ( performance . timerify )
5.30 ns/iter - https : //npmjs . com /benchmark
noop x 188 , 640 , 251 ops/sec ± 5 . 71 % ( 73 runs sampled )
36 . 62 ns /iter - vitest bench / https : //npmjs . com / tinybench
┌─────────┬───────────┬──────────────┬───────────────────┬──────────┬──────────┐
│ ( index ) │ Task Name │ ops/sec │ Average Time ( ns ) │ Margin │ Samples │
├─────────┼───────────┼──────────────┼───────────────────┼──────────┼──────────┤
│ 0 │ ' noop ' │ ' 27 , 308 , 739 ' │ 36 . 61831406333669 │ ' ± 0 . 14 % ' │ 13654370 │
└─────────┴───────────┴──────────────┴───────────────────┴──────────┴──────────┘
156.5685 ns/iter - https : //npmjs . com /cronometro
╔══════════════╤═════════╤═══════════════════╤═══════════╗
║ Slower tests │ Samples │ Result │ Tolerance ║
╟──────────────┼─────────┼───────────────────┼───────────╢
║ Fastest test │ Samples │ Result │ Tolerance ║
╟──────────────┼─────────┼───────────────────┼───────────╢
║ noop │ 10000 │ 6386980 . 78 op /sec │ ± 1 . 85 % ║
╚══════════════╧═════════╧═══════════════════╧═══════════╝