Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

improve startup perf#1030

Open
tandraschko wants to merge 1 commit into
apache:mainapache/tomcat:mainfrom
tandraschko:startupperftandraschko/tomcat:startupperfCopy head branch name to clipboard
Open

improve startup perf#1030
tandraschko wants to merge 1 commit into
apache:mainapache/tomcat:mainfrom
tandraschko:startupperftandraschko/tomcat:startupperfCopy head branch name to clipboard

Conversation

@tandraschko

Copy link
Copy Markdown
Member

What

A set of internal, behavior-preserving optimizations that reduce web application
deployment/startup time. There are no changes to defaults, configuration,
public API, parsing output, or threading model
— outputs are identical; only
redundant work and allocations are removed.

Changes

Annotation / JAR scanning (ContextConfig)

  • Index the @HandlesTypes types by name (class-file descriptor form for
    annotations, binary name for classes) so matching a scanned class is an O(1)
    lookup instead of a linear scan of all handled types plus a per-annotation
    string conversion.
  • Record whether a fragment JAR contains META-INF/resources/ during the
    annotation scan (which already iterates every entry), so processResourceJARs
    no longer re-opens and re-scans each JAR.
  • Check the cached default web.xml freshness with File.lastModified() for
    file: URIs instead of opening a URLConnection.
  • Use Collections.singleton for the per-fragment annotation merge.

Mapper (Mapper / batch registration)

  • Register a context's servlet mappings into the copy-on-write wrapper arrays in
    a single merge per mapping category instead of reallocating the array once per
    mapping (previously O(n²)). Verified equivalent to the old sequential
    insertMap behaviour (sorted order, existing-wins dedup, wildcard nesting)
    over 300k randomized cases.

Web resources

  • JarWarResourceSet: build the META-INF bloom filter once when the entries
    are read rather than rebuilding it on every resource lookup.
  • AbstractSingleArchiveResourceSet: pre-size the entry map from the JAR entry
    count.
  • StandardRoot: hoist a loop invariant in listResources; Collections.addAll
    instead of Arrays.asList wrapper.

Misc internal

  • StandardJarScanner: hoist loop-invariant getJarFileURL()/toURI() out of the
    manifest Class-Path loop; Collections.addAll for the class-path URLs.
  • Digester.updateAttributes: resolve the class loader once per call.
  • FragmentJarScannerCallback: single map lookup for duplicate detection.
  • StandardContext.mergeParameters: iterate entrySet() directly.
  • LifecycleBase.fireLifecycleEvent: skip allocating the event when there are no
    listeners.
  • AbstractProtocol.init: compute the (built/quoted) name once.
  • MbeansDescriptorsIntrospectionSource: Set membership test instead of a
    linear array scan.

Correctness

All changes preserve observable behaviour. The Mapper change was fuzz-checked
against the original sequential implementation (identical arrays and nesting).
TestContextConfigAnnotation is updated to build the new derived index (mirroring
the normal processClasses flow). Please run at least TestMapper*,
TestContextConfig*, and the webresources tests.

Performance

Measured on a build from source (JDK 25), median of 8 start/stop cycles, same
webapp set both sides. The gains scale with application size:

  • Mapping-heavy app (~8000 classes, 20000 servlet mappings): server startup
    ~560 ms → ~483 ms (~14%).
  • Small/typical apps: low single-digit %, near run-to-run noise.

Changelog entries are included.

Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

Morty Proxy This is a proxified and sanitized view of the page, visit original site.