Skip to content

perf(url): mark host with port : safehost#320

Merged
yusukebe merged 2 commits intov2from
perf/url-port-url-as-safe-host
Mar 12, 2026
Merged

perf(url): mark host with port : safehost#320
yusukebe merged 2 commits intov2from
perf/url-port-url-as-safe-host

Conversation

@yusukebe
Copy link
Member

@yusukebe yusukebe commented Mar 12, 2026

Making a host with a port like :3000 a safe host. This improves the benchmark's performance when you use something like localhost:3000.

@usualoma
Copy link
Member

Hi @yusukebe

Optimization is definitely needed!

Normalization via new URL()

Sorry for not adding sufficient tests. Since new URL() performs normalization like this (to match the behavior), it requires verification including the scheme, which is costly, so I omitted it.

http://localhost:080 => http://localhost
http://localhost:08080 => http://localhost:8080
http://localhost:80 => http://localhost
http://localhost:443 => http://localhost:443
https://localhost:443 => https://localhost

Narrowing the range of ports to optimize

In most cases, four-digit port numbers are used. Since explicitly specifying 1-999 or 60000-65535 is rare,
how about designating port numbers in the 1000-59999 range as the fast path?

PR: #322

For ports in the range 1000-59999, this benchmark script showed an improvement of about 30%.

  • url-1 : perf/url-port-url-as-safe-host
  • url-2 : perf/url-port-url-as-safe-host-narrow
Preset: ports-1000-59999
Versions: url-1, url-2

localhost ports 1000-59999
  url-2: 13969303.03 ops/sec (35.79 ms avg)
  url-1: 10771996.69 ops/sec (46.42 ms avg)

ipv4 ports 1000-59999
  url-2: 11448480.85 ops/sec (43.67 ms avg)
  url-1: 8290749.97 ops/sec (60.31 ms avg)

domain ports 1000-59999
  url-2: 9154128.03 ops/sec (54.62 ms avg)
  url-1: 7135953.11 ops/sec (70.07 ms avg)

sink=0
build-url-port.mts
// Run:
// node_modules/.bin/esbuild benchmarks/build-url-port.mts --bundle --platform=node --format=esm --outfile=/tmp/build-url-port.mjs
// node /tmp/build-url-port.mjs [preset] [versions]
//
// Presets:
// - ports-all
// - ports-4-digit
// - ports-1000-59999
//
// Versions:
// - url-1,url-2

import { performance } from 'node:perf_hooks'

import { buildUrl as buildUrl1 } from '../src/url-1.ts'
import { buildUrl as buildUrl2 } from '../src/url-2.ts'

type BuildUrl = (scheme: string, host: string, incomingUrl: string) => string

type BenchmarkCase = {
  name: string
  scheme: string
  host: string
  incomingUrl: string
}

type BenchmarkSuite = {
  name: string
  cases: BenchmarkCase[]
}

type BenchmarkVersion = {
  label: string
  fn: BuildUrl
}

const versionMap: Record<string, BuildUrl> = {
  'url-1': buildUrl1,
  'url-2': buildUrl2,
}

const suitePresets: Record<string, BenchmarkSuite[]> = {
  'ports-all': [
    {
      name: 'localhost ports',
      cases: [
        {
          name: 'simple path',
          scheme: 'http',
          host: 'localhost:3000',
          incomingUrl: '/foo',
        },
        {
          name: 'query string',
          scheme: 'http',
          host: 'localhost:8080',
          incomingUrl: '/foo/bar?x=1&y=two',
        },
        {
          name: 'hash fragment',
          scheme: 'http',
          host: 'localhost:4321',
          incomingUrl: '/deep/path?q=bench#hash',
        },
        {
          name: 'empty path',
          scheme: 'https',
          host: 'localhost:65535',
          incomingUrl: '',
        },
      ],
    },
    {
      name: 'ipv4 ports',
      cases: [
        {
          name: '127 loopback',
          scheme: 'http',
          host: '127.0.0.1:8787',
          incomingUrl: '/alpha',
        },
        {
          name: 'private network',
          scheme: 'http',
          host: '192.168.0.1:3001',
          incomingUrl: '/beta/gamma?value=123',
        },
        {
          name: 'docker bridge',
          scheme: 'https',
          host: '172.17.0.2:9443',
          incomingUrl: '/delta/epsilon#section',
        },
        {
          name: 'link local',
          scheme: 'http',
          host: '169.254.10.20:65535',
          incomingUrl: '/zeta/theta?ok=1&mode=bench',
        },
      ],
    },
    {
      name: 'domain ports',
      cases: [
        {
          name: 'example',
          scheme: 'https',
          host: 'example.com:444',
          incomingUrl: '/alpha/beta',
        },
        {
          name: 'subdomain',
          scheme: 'https',
          host: 'api.example.com:8443',
          incomingUrl: '/v1/items?limit=10',
        },
        {
          name: 'long path',
          scheme: 'https',
          host: 'static.example.com:12345',
          incomingUrl: '/assets/app/chunk.js?v=20260312',
        },
        {
          name: 'maximum port',
          scheme: 'https',
          host: 'download.example.com:65535',
          incomingUrl: '/release/archive.tar.gz',
        },
      ],
    },
  ],
  'ports-4-digit': [
    {
      name: 'localhost 4-digit ports',
      cases: [
        {
          name: 'simple path',
          scheme: 'http',
          host: 'localhost:3000',
          incomingUrl: '/foo',
        },
        {
          name: 'query string',
          scheme: 'http',
          host: 'localhost:4321',
          incomingUrl: '/foo/bar?x=1',
        },
        {
          name: 'hash fragment',
          scheme: 'https',
          host: 'localhost:8080',
          incomingUrl: '/deep/path#hash',
        },
        {
          name: 'empty path',
          scheme: 'https',
          host: 'localhost:9443',
          incomingUrl: '',
        },
      ],
    },
    {
      name: 'ipv4 4-digit ports',
      cases: [
        {
          name: '127 loopback',
          scheme: 'http',
          host: '127.0.0.1:8787',
          incomingUrl: '/alpha',
        },
        {
          name: 'private network',
          scheme: 'http',
          host: '192.168.0.1:3001',
          incomingUrl: '/beta/gamma?value=123',
        },
        {
          name: 'docker bridge',
          scheme: 'https',
          host: '172.17.0.2:9443',
          incomingUrl: '/delta/epsilon#section',
        },
        {
          name: 'k8s service',
          scheme: 'http',
          host: '10.0.0.8:5555',
          incomingUrl: '/zeta/theta?ok=1',
        },
      ],
    },
    {
      name: 'domain 4-digit ports',
      cases: [
        {
          name: 'example',
          scheme: 'https',
          host: 'example.com:4444',
          incomingUrl: '/alpha/beta',
        },
        {
          name: 'subdomain',
          scheme: 'https',
          host: 'api.example.com:8443',
          incomingUrl: '/v1/items?limit=10',
        },
        {
          name: 'static assets',
          scheme: 'https',
          host: 'static.example.com:1234',
          incomingUrl: '/assets/app.js?v=1',
        },
        {
          name: 'download',
          scheme: 'http',
          host: 'download.example.com:5000',
          incomingUrl: '/release/archive.tar.gz',
        },
      ],
    },
  ],
  'ports-1000-59999': [
    {
      name: 'localhost ports 1000-59999',
      cases: [
        {
          name: 'minimum fast path',
          scheme: 'http',
          host: 'localhost:1000',
          incomingUrl: '/foo',
        },
        {
          name: 'common dev port',
          scheme: 'http',
          host: 'localhost:3000',
          incomingUrl: '/foo/bar?x=1',
        },
        {
          name: 'alt http',
          scheme: 'https',
          host: 'localhost:8080',
          incomingUrl: '/deep/path#hash',
        },
        {
          name: 'high valid port',
          scheme: 'https',
          host: 'localhost:54321',
          incomingUrl: '',
        },
      ],
    },
    {
      name: 'ipv4 ports 1000-59999',
      cases: [
        {
          name: '127 loopback',
          scheme: 'http',
          host: '127.0.0.1:8787',
          incomingUrl: '/alpha',
        },
        {
          name: 'private network',
          scheme: 'http',
          host: '192.168.0.1:3001',
          incomingUrl: '/beta/gamma?value=123',
        },
        {
          name: 'docker bridge',
          scheme: 'https',
          host: '172.17.0.2:9443',
          incomingUrl: '/delta/epsilon#section',
        },
        {
          name: 'upper bound',
          scheme: 'http',
          host: '10.0.0.8:59999',
          incomingUrl: '/zeta/theta?ok=1',
        },
      ],
    },
    {
      name: 'domain ports 1000-59999',
      cases: [
        {
          name: 'example',
          scheme: 'https',
          host: 'example.com:4444',
          incomingUrl: '/alpha/beta',
        },
        {
          name: 'api',
          scheme: 'https',
          host: 'api.example.com:12345',
          incomingUrl: '/v1/items?limit=10',
        },
        {
          name: 'static assets',
          scheme: 'https',
          host: 'static.example.com:54321',
          incomingUrl: '/assets/app.js?v=1',
        },
        {
          name: 'download',
          scheme: 'http',
          host: 'download.example.com:5000',
          incomingUrl: '/release/archive.tar.gz',
        },
      ],
    },
  ],
}

const presetName = process.argv[2] ?? 'ports-all'
const requestedVersions = (process.argv[3] ?? 'url-1,url-2')
  .split(',')
  .map((label) => label.trim())
  .filter(Boolean)

const benchmarkSuites = suitePresets[presetName]
if (!benchmarkSuites) {
  throw new Error(`Unknown preset: ${presetName}`)
}

const versions: BenchmarkVersion[] = requestedVersions.map((label) => {
  const fn = versionMap[label]
  if (!fn) {
    throw new Error(`Unknown version: ${label}`)
  }
  return { label, fn }
})

if (versions.length < 2) {
  throw new Error('Select at least two versions')
}

const warmupIterations = 200_000
const iterationsPerSample = 500_000
const sampleCount = 5

let sink = 0

const assertSameResult = (suite: BenchmarkSuite) => {
  for (const testCase of suite.cases) {
    const expected = versions[0].fn(testCase.scheme, testCase.host, testCase.incomingUrl)
    for (let i = 1; i < versions.length; i++) {
      const version = versions[i]
      const actual = version.fn(testCase.scheme, testCase.host, testCase.incomingUrl)
      if (actual !== expected) {
        throw new Error(
          `Mismatched result for "${suite.name}" / "${testCase.name}":\n${versions[0].label}=${expected}\n${version.label}=${actual}`
        )
      }
    }
  }
}

const runLoop = (fn: BuildUrl, suite: BenchmarkSuite, iterations: number): number => {
  const startedAt = performance.now()
  const cases = suite.cases
  const caseCount = cases.length

  for (let i = 0; i < iterations; i++) {
    const testCase = cases[i % caseCount]
    sink ^= fn(testCase.scheme, testCase.host, testCase.incomingUrl).length
  }

  return performance.now() - startedAt
}

const benchmark = (fn: BuildUrl, suite: BenchmarkSuite) => {
  runLoop(fn, suite, warmupIterations)

  const samples: number[] = []
  for (let i = 0; i < sampleCount; i++) {
    samples.push(runLoop(fn, suite, iterationsPerSample))
  }

  const averageMs = samples.reduce((sum, value) => sum + value, 0) / samples.length
  const opsPerSec = (iterationsPerSample * 1000) / averageMs

  return {
    averageMs,
    opsPerSec,
  }
}

const rotateVersions = (offset: number): BenchmarkVersion[] => {
  const normalizedOffset = offset % versions.length
  return versions.slice(normalizedOffset).concat(versions.slice(0, normalizedOffset))
}

console.log(`Preset: ${presetName}`)
console.log(`Versions: ${versions.map((version) => version.label).join(', ')}`)

for (const [suiteIndex, suite] of benchmarkSuites.entries()) {
  assertSameResult(suite)

  const resultsByLabel: Record<string, ReturnType<typeof benchmark>> = {}
  for (const version of rotateVersions(suiteIndex)) {
    resultsByLabel[version.label] = benchmark(version.fn, suite)
  }

  const results = versions
    .map((version) => ({
      label: version.label,
      ...resultsByLabel[version.label],
    }))
    .sort((a, b) => b.opsPerSec - a.opsPerSec)

  console.log(`\n${suite.name}`)
  for (const result of results) {
    console.log(
      `  ${result.label}: ${result.opsPerSec.toFixed(2)} ops/sec (${result.averageMs.toFixed(2)} ms avg)`
    )
  }
}

console.log(`\nsink=${sink}`)

…99 (#322)

* perf: added fast path handling for port numbers in the range 1000-59999

* test: fix test description
@yusukebe
Copy link
Member Author

@usualoma

Cutting the rare case and narrowing the range are good ideas! I've merged #322. Thank you!

@yusukebe yusukebe merged commit f1744ce into v2 Mar 12, 2026
4 checks passed
@yusukebe yusukebe deleted the perf/url-port-url-as-safe-host branch March 12, 2026 22:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants