diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 326191f645..813783eb23 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -50,7 +50,7 @@ jobs: node-version: ${{ matrix.node }} - uses: ipfs/aegir/actions/cache-node-modules@master - run: npm run --if-present test:node - - uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b # v2.1.0 + - uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d # v3.1.4 with: flags: node files: .coverage/*,packages/*/.coverage/* @@ -65,7 +65,7 @@ jobs: node-version: lts/* - uses: ipfs/aegir/actions/cache-node-modules@master - run: npm run --if-present test:chrome - - uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b # v2.1.0 + - uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d # v3.1.4 with: flags: chrome files: .coverage/*,packages/*/.coverage/* @@ -80,7 +80,7 @@ jobs: node-version: lts/* - uses: ipfs/aegir/actions/cache-node-modules@master - run: npm run --if-present test:chrome-webworker - - uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b # v2.1.0 + - uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d # v3.1.4 with: flags: chrome-webworker files: .coverage/*,packages/*/.coverage/* @@ -95,7 +95,7 @@ jobs: node-version: lts/* - uses: ipfs/aegir/actions/cache-node-modules@master - run: npm run --if-present test:firefox - - uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b # v2.1.0 + - uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d # v3.1.4 with: flags: firefox files: .coverage/*,packages/*/.coverage/* @@ -110,7 +110,7 @@ jobs: node-version: lts/* - uses: ipfs/aegir/actions/cache-node-modules@master - run: npm run --if-present test:firefox-webworker - - uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b # v2.1.0 + - uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d # v3.1.4 with: flags: firefox-webworker files: .coverage/*,packages/*/.coverage/* @@ -126,7 +126,7 @@ jobs: - uses: ipfs/aegir/actions/cache-node-modules@master - run: npx playwright install-deps - run: npm run --if-present test:webkit - - uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b # v2.1.0 + - uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d # v3.1.4 with: flags: webkit files: .coverage/*,packages/*/.coverage/* @@ -141,7 +141,7 @@ jobs: node-version: lts/* - uses: ipfs/aegir/actions/cache-node-modules@master - run: npx xvfb-maybe npm run --if-present test:electron-main - - uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b # v2.1.0 + - uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d # v3.1.4 with: flags: electron-main files: .coverage/*,packages/*/.coverage/* @@ -156,7 +156,7 @@ jobs: node-version: lts/* - uses: ipfs/aegir/actions/cache-node-modules@master - run: npx xvfb-maybe npm run --if-present test:electron-renderer - - uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b # v2.1.0 + - uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d # v3.1.4 with: flags: electron-renderer files: .coverage/*,packages/*/.coverage/* diff --git a/run-client.ts b/run-client.ts new file mode 100644 index 0000000000..90380ae35a --- /dev/null +++ b/run-client.ts @@ -0,0 +1,61 @@ +/* eslint-disable no-console */ +import { noise } from '@chainsafe/libp2p-noise' +import { yamux } from '@chainsafe/libp2p-yamux' +import { mplex } from '@libp2p/mplex' +import { plaintext } from '@libp2p/plaintext' +import { tcp } from '@libp2p/tcp' +import { multiaddr } from '@multiformats/multiaddr' +import { createLibp2p, type Libp2p } from 'libp2p' +import { perf, type PerfOutput, type Perf } from '../src/index.js' + +const ONE_MEG = 1024 * 1024 +const DOWNLOAD_BYTES = ONE_MEG * 1024 * 5 + +async function createNode (): Promise> { + return createLibp2p({ + transports: [ + tcp() + ], + connectionEncryption: [ + noise(), plaintext() + ], + streamMuxers: [ + yamux(), mplex() + ], + services: { + perf: perf({ + writeBlockSize: 1024 * 1024 + }) + }, + connectionManager: { + minConnections: 0 + } + }) +} + +const libp2p1 = await createNode() + +let last: PerfOutput | undefined + +const ma = multiaddr('/ip4/127.0.0.1/tcp/59032') + +for await (const output of libp2p1.services.perf.measurePerformance(ma, 0, DOWNLOAD_BYTES)) { + last = output + console.info(output) + + console.info((output.downloadBytes / (1024 * 1024)) / output.timeSeconds, 'MB/s') +} + +if (last?.type === 'final') { + console.info((last.downloadBytes / (1024 * 1024)) / last.timeSeconds, 'MB/s') +} + +await libp2p1.stop() + +// plaintext/yamux - 1354 MB/s +// plaintext/mplex - 34478 MB/s +// noise/yamux - 60 MB/s +// noise/mplex - 62 MB/s + +// noise/yamux/native crypto - 282 MB/s +// noise/mplex/native crypto - 420 MB/s diff --git a/run-server.ts b/run-server.ts new file mode 100644 index 0000000000..8d6d569994 --- /dev/null +++ b/run-server.ts @@ -0,0 +1,39 @@ +/* eslint-disable no-console */ +import { noise } from '@chainsafe/libp2p-noise' +import { yamux } from '@chainsafe/libp2p-yamux' +import { mplex } from '@libp2p/mplex' +import { plaintext } from '@libp2p/plaintext' +import { tcp } from '@libp2p/tcp' +import { createLibp2p, type Libp2p } from 'libp2p' +import { perf, type Perf } from '../src/index.js' + +async function createNode (): Promise> { + return createLibp2p({ + addresses: { + listen: [ + '/ip4/0.0.0.0/tcp/59032' + ] + }, + transports: [ + tcp() + ], + connectionEncryption: [ + noise(), plaintext() + ], + streamMuxers: [ + yamux(), mplex() + ], + services: { + perf: perf({ + writeBlockSize: 1024 * 1024 + }) + }, + connectionManager: { + minConnections: 0 + } + }) +} + +const server = await createNode() + +console.info(server.getMultiaddrs()) diff --git a/run.ts b/run.ts new file mode 100644 index 0000000000..37fac789f8 --- /dev/null +++ b/run.ts @@ -0,0 +1,147 @@ +/* eslint-disable no-console */ +import { noise } from '@chainsafe/libp2p-noise' +import { yamux } from '@chainsafe/libp2p-yamux' +import { mplex } from '@libp2p/mplex' +import { plaintext } from '@libp2p/plaintext' +import { tcp } from '@libp2p/tcp' +import last from 'it-last' +import { createLibp2p, type Libp2p } from 'libp2p' +import { perf, type PerfOutput, type Perf } from '../src/index.js' + +const ONE_MEG = 1024 * 1024 +const DOWNLOAD_BYTES = ONE_MEG * 1024 * 5 +const REPEAT = 10 + +// plaintext/yamux - 1354 MB/s +// plaintext/mplex - 34478 MB/s +// noise/yamux - 60 MB/s +// noise/mplex - 62 MB/s + +// noise/yamux/native crypto - 282 MB/s +// noise/mplex/native crypto - 420 MB/s + +const sizes = [ + 64, 128, 256, 384, 512, 640, 768, 896, 1024, 1152, 1280, 1408, 1536 +] + +for (let i = 0; i < sizes.length; i++) { + const size = sizes[i] + + const measurements: PerfOutput[] = [] + + for (let n = 0; n < REPEAT; n++) { + async function createNode (): Promise> { + return createLibp2p({ + addresses: { + listen: [ + '/ip4/0.0.0.0/tcp/0' + ] + }, + transports: [ + tcp() + ], + connectionEncryption: [ + noise(), plaintext() + ], + streamMuxers: [ + yamux(), mplex() + ], + services: { + perf: perf({ + writeBlockSize: size * 1024 + }) + }, + connectionManager: { + minConnections: 0 + } + }) + } + + const libp2p1 = await createNode() + const libp2p2 = await createNode() + + const result = await last( + libp2p1.services.perf.measurePerformance(libp2p2.getMultiaddrs()[0], 0, DOWNLOAD_BYTES) + ) + + if (result != null) { + measurements.push(result) + } + + await libp2p1.stop() + await libp2p2.stop() + } + + const downloadBytes = measurements + .map(m => { + if (m.type === 'final') { + return m.downloadBytes + } + + return 0 + }) + .filter(outliers()) + .reduce((acc, curr) => acc + curr, 0) + + const timeSeconds = measurements + .map(m => { + if (m.type === 'final') { + return m.timeSeconds + } + + return 0 + }) + .filter(outliers()) + .reduce((acc, curr) => acc + curr, 0) + + console.info(size, 'kb', (downloadBytes / (1024 * 1024)) / timeSeconds, 'MB/s') +} + +function outliers() { + let o: number[] + + return function(v: number, i: number, a: number[]) { + if (o == null) { + o = calc(a) + } + + return !~o.indexOf(v); + } +} + +function calc(arr: number[]): number[] { + arr = arr.slice(0); + + arr = arr.sort(function(a, b) { + return a - b; + }); + + var len = arr.length; + var middle = median(arr); + var range = iqr(arr); + var outliers = []; + + for (var i = 0; i < len; i++) { + Math.abs(arr[i] - middle) > range && outliers.push(arr[i]); + } + + return outliers; +} + +function median(arr: number[]): number { + var len = arr.length; + var half = ~~(len / 2); + + return len % 2 + ? arr[half] + : (arr[half - 1] + arr[half]) / 2; +} + +function iqr(arr: number[]): number { + var len = arr.length; + var q1 = median(arr.slice(0, ~~(len / 2))); + var q3 = median(arr.slice(Math.ceil(len / 2))); + var g = 1.5; + + return (q3 - q1) * g; +}