Hi,

If it’s optional but still enabled, I think it’s a good idea to speedup 
bootstrapping.

Just my $0.01 ;)

Regards
JB

> Le 27 déc. 2020 à 16:15, Romain Manni-Bucau <rmannibu...@gmail.com> a écrit :
> 
> Hi everyone,
> 
> wonder if there is some work planned in tomcat 10 to 1. makes it start
> faster and 2. make jmx optional.
> 
> I did some tests and locally a tomcat start is about 400ms.
> I was surprised to see that Registry.disableRegistry() was taking already
> 65ms whereas it should be almost nothing so refactored the code, added a
> RegistryFactory and really noop impl (not even a mock) and went down to
> 1ms, way better right? except the remaining 64ms went to the next line (new
> StandardHost()). After some investigation time is mainly classloading time
> (in all senses).
> 
> So I wonder if it wouldnt make sense to optimize tomcat startup time +
> finally make JMX optional since it is no more used by users in most cases -
> gues we must keep it as an optional plugin since it is used "historically".
> 
> The proposal would be to:
> 
> 1. reduce classloading tree as much as possible for default case - here
> having jmx optional will help a lot
> 2. probably generate resource bundle as .java at build time to avoid all
> the classloading resource bundle implies (it is like 74 loadClass + as much
> getResource for a simple startup and all loadclass are misses)
> 2.bis. probably add a mode where StringManager uses the default bundle
> without passing through the resource bundle layer
> 3. cut dead code when we know it is inactive (typically the case for jmx)
> 4. open point: bypassing Context: in "main" mode (as the code shared
> after), you just want to bind some logic in a servlet/filter/valve, you
> don't always care about handling contexts (or a single one) so wonder if we
> shouldnt evaluate the fact to add the user logic in a valve for this kind
> of bench and maybe document this case (spring boot could inherit from it
> since it almost never use anything else that default spring servlet and
> binds everything in it).
> 
> Here is the kind of case I'd like to see insanely fast (<100ms - and it is
> possible regarding what it does):
> 
> public class Main {
>    public static void main(String[] args) throws LifecycleException,
> InterruptedException {
>        final long start = System.nanoTime();
>        Registry.disableRegistry();
>        final long startDisableRegistry = System.nanoTime();
> 
>        final Host host = new StandardHost();
>        host.setName("localhost");
>        final long startHost = System.nanoTime();
> 
>        final Engine engine = new StandardEngine();
>        engine.setName("Tomcat");
>        engine.setDefaultHost("localhost");
>        engine.setRealm(new NullRealm());
>        engine.addChild(host);
>        final long startEngine = System.nanoTime();
> 
>        final var protocolHandler = new Http11Nio2Protocol();
>        protocolHandler.setPort(8080);
>        final long startHttp11Nio2Protocol = System.nanoTime();
> 
>        final Service service = new StandardService();
>        service.setName("Tomcat");
>        service.setContainer(engine);
>        service.addConnector(new Connector(protocolHandler));
>        final long startService = System.nanoTime();
> 
>        final StandardServer server = new StandardServer();
>        server.setPort(-1);
>        server.addService(service);
>        final long startServer = System.nanoTime();
> 
>        final StandardContext context = new StandardContext();
>        context.setUseNaming(false);
>        context.setClearReferencesStopThreads(false);
>        context.setClearReferencesStopTimerThreads(false);
>        context.setClearReferencesHttpClientKeepAliveThread(false);
>        context.setClearReferencesRmiTargets(false);
>        context.setClearReferencesThreadLocals(false);
>        context.setClearReferencesObjectStreamClassCaches(false);
>        context.setWorkDir(System.getProperty("java.io.tmpdir"));
>        context.setName("");
>        context.setPath("");
>        context.setDocBase(null);
>        context.addLifecycleListener(event -> {
>            if (event.getType().equals(Lifecycle.CONFIGURE_START_EVENT)) {
>                context.setConfigured(true);
>                if (context.getLoginConfig() == null) {
>                    context.setLoginConfig(new LoginConfig("NONE", null,
> null, null));
>                    context.getPipeline().addValve(new
> NonLoginAuthenticator());
>                }
>            }
>        });
>        context.addServletContainerInitializer((classes, ctx) -> {
>            ctx.addServlet("default", new DefaultServlet())
>                    .addMapping("/");
>        }, Set.of());
>        final long startContext = System.nanoTime();
> 
>        host.addChild(context);
> 
>        server.init();
>        final long inited = System.nanoTime();
>        server.start();
>        final long started = System.nanoTime();
>        // new CountDownLatch(1).await();
> 
>        final var contextClassLoader =
> Thread.currentThread().getContextClassLoader();
> 
>        server.stop();
>        server.destroy();
>        final long stopped = System.nanoTime();
> 
>        System.out.println(TimeUnit.NANOSECONDS.toMillis(started - start) +
> "ms");
>        System.out.println(TimeUnit.NANOSECONDS.toMillis(stopped - started)
> + "ms");
>        System.out.println();
>        System.out.println("startDisableRegistry:    " +
> TimeUnit.NANOSECONDS.toMillis(startDisableRegistry - start) + "ms");
>        System.out.println("startHost:               " +
> TimeUnit.NANOSECONDS.toMillis(startHost - startDisableRegistry) + "ms");
>        System.out.println("startEngine:             " +
> TimeUnit.NANOSECONDS.toMillis(startEngine - startHost) + "ms");
>        System.out.println("startHttp11Nio2Protocol: " +
> TimeUnit.NANOSECONDS.toMillis(startHttp11Nio2Protocol - startEngine) +
> "ms");
>        System.out.println("startService:            " +
> TimeUnit.NANOSECONDS.toMillis(startService - startEngine) + "ms");
>        System.out.println("startServer:             " +
> TimeUnit.NANOSECONDS.toMillis(startServer - startService) + "ms");
>        System.out.println("startContext:            " +
> TimeUnit.NANOSECONDS.toMillis(startContext - startServer) + "ms");
>        System.out.println("actualInit:              " +
> TimeUnit.NANOSECONDS.toMillis(inited - startContext) + "ms");
>        System.out.println("actualStart:             " +
> TimeUnit.NANOSECONDS.toMillis(started - inited) + "ms");
>    }
> }
> 
> 
> Current reference output (medium values) is - on java 11:
> 
> 364ms
> 22ms
> 
> startDisableRegistry:    58ms
> startHost:               19ms
> startEngine:             7ms
> startHttp11Nio2Protocol: 25ms
> startService:            39ms
> startServer:             12ms
> startContext:            26ms
> actualStart:             200ms
> 
> Wdyt? Anyone had a look before?
> 
> 
> PS: if curious the registry patch i did was:
> https://gist.github.com/rmannibucau/e7cb9674fa4a21ccfe9eb956b509fad1 -
> indeed since it does not help overall I don't ask to integrate it at all,
> just a FYI
> 
> Romain Manni-Bucau
> @rmannibucau <https://twitter.com/rmannibucau> |  Blog
> <https://rmannibucau.metawerx.net/> | Old Blog
> <http://rmannibucau.wordpress.com> | Github <https://github.com/rmannibucau> |
> LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book
> <https://www.packtpub.com/application-development/java-ee-8-high-performance>


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to