tandraschko opened a new pull request, #1030:
URL: https://github.com/apache/tomcat/pull/1030
## 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 <[email protected]>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]