npmmirror v.s tencent mirror ,坐标湖北武汉, 结果:
=== Final Result (sorted by tarball avg) ===
npmmirror
metadata avg: 229.4 ms
metadata p50: 253.9 ms
metadata p90: 409.2 ms
tarball avg: 435.1 ms
tarball p50: 266.1 ms
tarball p90: 906.1 ms
tencent
metadata avg: 777.0 ms
metadata p50: 700.7 ms
metadata p90: 1336.7 ms
tarball avg: 508.6 ms
tarball p50: 440.9 ms
tarball p90: 938.3 ms
脚本 via ChatGPT
```js
#!/usr/bin/env node
import { performance } from 'node:perf_hooks'
const registries = [
{
name: 'npmmirror',
base: '
https://registry.npmmirror.com',
},
{
name: 'tencent',
base: '
http://mirrors.tencent.com/npm',
},
]
// 👉 多包(覆盖不同大小 & 热门程度)
const PACKAGES = [
{ name: 'react', version: '18.2.0' },
{ name: 'lodash', version: '4.17.21' },
{ name: 'typescript', version: '5.4.5' },
{ name: 'axios', version: '1.6.7' },
]
// 👉 多轮(建议 ≥10 )
const RUNS = 10
// 👉 并发数(模拟 npm )
const CONCURRENCY = 4
async function fetchWithTiming(url) {
const start = performance.now()
const res = await fetch(url)
await res.arrayBuffer()
return performance.now() - start
}
// 简单并发控制
async function runPool(tasks, limit) {
const results = []
let i = 0
async function worker() {
while (i < tasks.length) {
const idx = i++
results[idx] = await tasks[idx]()
}
}
await Promise.all(Array.from({ length: limit }, worker))
return results
}
async function testRegistry(registry) {
const metadataTimes = []
const tarballTimes = []
for (let run = 0; run < RUNS; run++) {
const tasks = []
for (const pkg of PACKAGES) {
const metadataUrl = `${registry.base}/${
pkg.name}`
const tarballUrl = `${registry.base}/${
pkg.name}/-/${
pkg.name}-${pkg.version}.tgz`
tasks.push(async () => {
const t = await fetchWithTiming(metadataUrl)
metadataTimes.push(t)
})
tasks.push(async () => {
const t = await fetchWithTiming(tarballUrl)
tarballTimes.push(t)
})
}
await runPool(tasks, CONCURRENCY)
console.log(`[${
registry.name}] run ${run + 1}/${RUNS} done`)
}
function stats(arr) {
const sorted = [...arr].sort((a, b) => a - b)
const avg = arr.reduce((a, b) => a + b, 0) / arr.length
const p50 = sorted[Math.floor(sorted.length * 0.5)]
const p90 = sorted[Math.floor(sorted.length * 0.9)]
return { avg, p50, p90 }
}
return {
name:
registry.name,
metadata: stats(metadataTimes),
tarball: stats(tarballTimes),
}
}
async function main() {
const results = []
for (const r of registries) {
console.log(`\nTesting ${
r.name}...`)
const res = await testRegistry(r)
results.push(res)
}
console.log('\n=== Final Result (sorted by tarball avg) ===')
results.sort((a, b) => a.tarball.avg - b.tarball.avg)
for (const r of results) {
console.log(`
${
r.name}
metadata avg: ${r.metadata.avg.toFixed(1)} ms
metadata p50: ${r.metadata.p50.toFixed(1)} ms
metadata p90: ${r.metadata.p90.toFixed(1)} ms
tarball avg: ${r.tarball.avg.toFixed(1)} ms
tarball p50: ${r.tarball.p50.toFixed(1)} ms
tarball p90: ${r.tarball.p90.toFixed(1)} ms
`)
}
}
main()
```