MarshallOfSound

#51599: perf: reduce per-call overhead in gin converters

Merged
Created: May 13, 2026, 1:06:44 AM
Merged: May 13, 2026, 1:57:06 PM
7 comments
Target: main

Description of Change

Removes a handful of avoidable allocations, copies, and V8 boundary crossings from the gin converters and gin_helper paths used by webRequest, sendInputEvent, certificate/auth events, and a number of options-dictionary parsers.

  • net_converter.{h,cc}, content_converter.cc — switch the plain-data ToV8 converters (AuthChallengeInfo, X509Certificate, CertPrincipal, HttpRequestHeaders, HttpVersion, RedirectInfo, IPEndPoint, ResourceRequest, VerifyRequestParams, Referrer) from gin::Dictionary + N×Set() to gin::DataObjectBuilder, which internalizes property keys and uses CreateDataProperty(). HttpResponseHeaders::ToV8 and HttpRequestHeaders::FromV8 build from / read the V8 object directly instead of round-tripping through base::DictValue + content::V8ValueConverter.
  • std_converter.hset/map FromV8 move the converted element/key into the container; set/span ToV8 use CreateDataProperty(); hoist keys->Length() out of loops.
  • net_converter.hvector<pair<K,V>>::FromV8 hoists Length() and reserve()s.
  • blink_converter.ccWebKeyboardEvent::ToV8 caches GetModifiers() once; ModifiersToArray reserve()s.
  • gfx_converter.ccColorSpace::ToV8 uses string_view for the enum-name literals.
  • guid_converter.hUuid::FromV8 uses ParseCaseInsensitive(); Uuid::ToV8 takes by const& and passes AsLowercaseString() through directly (drops two heap-allocated string copies).
  • login_item_settings_converter.{h,cc}LaunchItem/LoginItemSettings ToV8 take by const&.
  • gin_helper/dictionary.hSetHidden/SetReadOnlyNonConfigurable take T by const&; SetGetter accessor avoids copying the value.

A behavior-equivalence fuzz across 31 input shapes (plain objects, getters, throwing getters, non-string values, numeric/symbol keys, frozen/null-proto, proxies, arrays, functions, primitives, unicode, invalid header names/values) confirms the touched converters produce byte-identical output for the same inputs, with one deliberate change: webRequest's requestHeaders are now applied in the JS object's insertion order rather than alphabetically (the previous order was an artifact of base::DictValue being a sorted map).

Benchmarks

Linux x86-64 testing build, microbenchmark medians:

path before after Δ
Converter<base::Uuid>::ToV8 320 ns 92 ns −71%
Converter<net::AuthChallengeInfo>::ToV8 5974 ns 2228 ns −63%
Converter<net::HttpRequestHeaders>::ToV8 (10 headers) 12557 ns 4885 ns −61%
Converter<net::CertPrincipal>::ToV8 9009 ns 4090 ns −55%
Converter<net::HttpRequestHeaders>::FromV8 (10 headers) 17255 ns 8511 ns −51%
Converter<net::HttpResponseHeaders*>::ToV8 (16 lines) 31539 ns 18938 ns −40%
Converter<base::Uuid>::FromV8 561 ns 425 ns −24%
Converter<std::set<string>>::FromV8 (long strings) 7422 ns 6056 ns −18%
Dictionary::SetHidden/SetReadOnlyNonConfigurable 3147 ns 2627 ns −17%
Converter<std::span<int>>::ToV8 12027 ns 10311 ns −14%
Converter<std::map<string,string>>::FromV8 (long strings) 13050 ns 11621 ns −11%
Converter<std::set<string>>::ToV8 3857 ns 3485 ns −10%
Converter<blink::WebKeyboardEvent>::ToV8 15883 ns 15428 ns −3%

Checklist

Release Notes

Notes: Improved performance of webRequest header conversions and several other gin converter hot paths.

Backports

41-x-y
Pending
Waiting for a manual backport
42-x-y
In-flight
PR Number
#51607
Waiting to be merged
43-x-y
In-flight
PR Number
#51608
Waiting to be merged

Semver Impact

Major
Breaking changes
Minor
New features
Patch
Bug fixes
None
Docs, tests, etc.

Semantic Versioning helps users understand the impact of updates:

  • Major (X.y.z): Breaking changes that may require code modifications
  • Minor (x.Y.z): New features that maintain backward compatibility
  • Patch (x.y.Z): Bug fixes that don't change the API
  • None: Changes that don't affect using facing parts of Electron