Le lun. 4 janv. 2021 à 15:04, Mark Thomas <ma...@apache.org> a écrit :
> On 04/01/2021 11:54, Romain Manni-Bucau wrote: > > <snip/> > > > Well it also depends the classpath. I fully agree with a plain tomcat not > > customized you don't get much - just have a more consistent usage of > > resources but it is about being purist so not that interesting to me > here. > > Now make your classpath bloated - yes some people do ;) but I guess > having > > ~100jars is not that rare too these days - and this is really slower, in > > particular with a custom security manager getResource check even if it > got > > optimized. > > If an app is that bloated then I'd be surprised if the changes proposed > had any noticeable effect. > Startup is still very slow but this helps a little bit - but agree order or magnitude is not critical. > > > Another interesting case is the tomee one or more exactly: the embedded > > one. Let's assume somebody uses tomcat embeded (not rare these days) and > > its dependency resolution comes with a servlet-api which is not tomcat > one > > (not rare too), then it can miss the resources because it is a pure API > or > > the project it comes from grab them from elsewhere. Why would he get > > warnings if he does not use the validation. > > Any valid API JAR needs to include the resources as passing the TCK > requires validation to be enabled - and that requires the schemas to be > available. The current consensus of the Jakarta Servlet team is that the > Servlet API JAR must include all the schema required for validation. > > Error messages where the root cause is an invalid API JAR are not > something that concerns me. > Still it is allowed to provide the resource outside servlet jar I think. TCK require signature validation and runtime validation, packaging is up to the vendor. > > (As an aside, due to the dependencies between the schema it means that > the Servlet API JAR has to include all the schema for the JSP API as > well - they can't be decoupled into the JSP API JAR). > > > So to summarize I see two benefits to update a bit the impl: > > > > 1. Makes it smoother for embedded case (where validation is rare) > > 2. Makes is a bit faster for highly customized standalone instances > > (enterprise prebundled server/layer) > > > > Indeed I don't expect - can be done technically but hope it is never > true - > > both to be true at the same time :s. > > 1 assumes an invalid API JAR so I don't consider that to be a valid use > case. > Not really, it would be invalid if tomcat would always validate it, it is valid to consider it as a tomcat bug to log a kind of false positive warning. Typically the corrupted case I got shouldn't warn the user by default since it is not used but I get dozens of warning lines which is very misleading for end users. > > 2 looks to be the most likely (only?) use case where there is potential > benefit to performing this optimisation > > >> The Maps are public but they aren't part of what we consider to be > >> Tomcat's public API so while this would technically be an API change, I > >> don't think that is a reason not to do this (or limit it to 10.1.x) > > > > Not sure I got this, it is just about chaging the internals of the map so > > API does not break (like overriding get to be lazy but not changing the > > generics). > > Ah. I was thinking of a simpler implementation that switched the > Map<String,String> to Map<String,Supplier<String>) or whatever results > in the simplest code. > > That brings us back to the complexity vs performance benefit question. > To be concrete I had that in mind: use supplier in the not exposed map then expose as read only this: public class LazyMap<A, B> extends ConcurrentHashMap<A, B> { private final Map<A, Supplier<B>> delegate = new HashMap<>(); @Override public B get(final Object key) { final B b = super.get(key); if (b == null) { final Supplier<B> supplier = delegate.remove(key); if (supplier != null) { final B value = supplier.get(); final B existing = putIfAbsent((A) key, value); return existing != null ? existing : value; } } return b; } @Override public boolean containsKey(Object key) { return super.containsKey(key) || delegate.containsKey(key); } @Override public boolean containsValue(Object value) { ensurePopulated(); return super.containsValue(value); } @Override public Set<Entry<A, B>> entrySet() { ensurePopulated(); return super.entrySet(); } @Override public KeySetView<A, B> keySet() { ensurePopulated(); return super.keySet(); } @Override public Collection<B> values() { ensurePopulated(); return super.values(); } private void ensurePopulated() { delegate.forEach((a, b) -> super.putIfAbsent(a, b.get())); } } Don't think it is crazy but if you judge it is not worth no worries too. Don't want to make you loose too much time on this, just thought it was worth some review cause I was surprised to have it eagerly coded. > > Mark > > --------------------------------------------------------------------- > To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org > For additional commands, e-mail: dev-h...@tomcat.apache.org > >