Advanced

Compute-intensive functions

Which PAC functions trigger blocking DNS lookups, and how to avoid unnecessary ones.

PAC evaluation is synchronous and blocking โ€” the browser freezes the request until FindProxyForURL returns. Functions that perform DNS resolution amplify this effect: every DNS round-trip adds tens to hundreds of milliseconds to every request.

dnsResolve()
โ— High cost
Always triggers a live DNS lookup. Cache the result in a variable โ€” never call twice for the same host.
isResolvable()
โ— High cost
Performs a DNS lookup on every call. Replace with dnsDomainIs() or shExpMatch() wherever possible.
isInNet() + hostname
โ— High cost
If the first argument is a hostname (not an IP), isInNet() internally calls dnsResolve(). Always pre-resolve.
isInNet() + IP
โ— No cost
If you pass a pre-resolved IP (from dnsResolve), no additional DNS lookup occurs. This is the correct pattern.
dnsDomainIs()
โ— No cost
Pure string suffix match. Zero DNS overhead. Always prefer this over isResolvable() for domain checks.
shExpMatch()
โ— No cost
Pure string glob match. Zero DNS overhead. Good for URL and host pattern matching.

The golden rule:

DNS optimisation pattern
function FindProxyForURL(url, host) {

  // โœ“ FAST: domain checks first โ€” zero DNS cost
  if ( isPlainHostName(host)
    || dnsDomainIs(host, ".corp.com")
    || shExpMatch(host, "*.local")) {
    return "DIRECT";
  }

  // โœ“ ONE DNS call โ€” stored and reused below
  var ip = dnsResolve(host);
  if (!ip) { return "DIRECT"; } // โœ“ guard failure case

  // โœ“ FAST: isInNet receives an IP โ€” no extra DNS
  if ( isInNet(ip, "10.0.0.0",    "255.0.0.0")
    || isInNet(ip, "192.168.0.0", "255.255.0.0")) {
    return "DIRECT";
  }

  // โœ— WRONG โ€” triggers a second DNS lookup for the same host:
  // if (isInNet(dnsResolve(host), "10.0.0.0", "255.0.0.0")) { ... }

  return "PROXY proxy.corp.com:8080";
}