Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Possible performance impact due com.vaadin.mpr.MprServlet detection #12572

Closed
rPraml opened this issue Jan 11, 2023 · 4 comments
Closed

Possible performance impact due com.vaadin.mpr.MprServlet detection #12572

rPraml opened this issue Jan 11, 2023 · 4 comments

Comments

@rPraml
Copy link

rPraml commented Jan 11, 2023

Affected version: Vaadin Framework 8.19.0

Hello, I compared the vaadin-server source changes 8.18.0 <-> 8.19.0 and noticed, that there are mostly changes, that look like this:

    private boolean assertConnector(ClientConnector connector) {
        try {
            Class.forName("com.vaadin.mpr.MprServlet", false,
                    getClass().getClassLoader());
            return true;
        } catch (ClassNotFoundException e) {
            return connectorIdToConnector
                    .get(connector.getConnectorId()) == connector;
        }
    }

I'm afraid, that this could cause a massive performance impact, if the MprServlet is not on the classpath, as every time an exception is generated and thrown.
I see that this code may be executed multiple times per request. I see also that most code paths are only executed, if assertions are enabled, but disabling assertions is not really an option.

I would suggest to cache the result, if MprServlet is present or not.

Please see this test about performance results and a possible fix

public class TestPerformance {

	private boolean isMprPresent() {
		try {
			Class.forName("com.vaadin.mpr.MprServlet", false, getClass().getClassLoader());
			return true;
		} catch (ClassNotFoundException e) {
			return false;
		}
	}

	private boolean isUiPresent() {
		try {
			Class.forName("com.vaadin.ui.UI", false, getClass().getClassLoader());
			return true;
		} catch (ClassNotFoundException e) {
			return false;
		}
	}

	/**
	 * The com.vaadin.ui is present. This test runs in about 200ms.
	 */
	@Test
	void testUiPresent() {
		for (int i = 0; i < 1_000_000; i++) {
			assertThat(isUiPresent()).isTrue();
		}
	}

	/**
	 * The com.vaadin.mpr.MprServlet is not present, so we have to generate a ClassNotFound exception every time. 
	 * This test runs in about 27 seconds. This is more than 100 times slower.
	 */
	@Test
	void testMprPresent() {
		for (int i = 0; i < 1_000_000; i++) {
			assertThat(isMprPresent()).isFalse();
		}
	}

	/**
	 * This is an better way I suggest to cache, if MprServlet is present. This test runs in about 150ms.
	 */
	@Test
	void testMprPresentFast() {
		for (int i = 0; i < 1_000_000; i++) {
			assertThat(MprCheck.isPresent()).isFalse();
		}
	}

	private static class MprCheck {
		private static boolean present;

		static {
			try {
				Class.forName("com.vaadin.mpr.MprServlet", false, MprCheck.class.getClassLoader());
				present = true;
			} catch (ClassNotFoundException e) {
				present = false;
			}
		}

		public static boolean isPresent() {
			return present;
		}
	}
}

cheers
Roland

@TatuLund
Copy link
Contributor

I am pleased to see that our are able to detect details like this. This check is done only assertions (as we are doing many other checkings that can have performance impact), so this should not be a concern.

@TatuLund
Copy link
Contributor

, if assertions are enabled, but disabling assertions is not really an option.

Do you mean that you run assertions enabled in production?

@rPraml
Copy link
Author

rPraml commented Jan 12, 2023

Hello Tatu,
currently, we have enabled assertions in production. (and that's good - we are still investigating why #12565 happens).
I know that enabling assertions may affect performance.
We do not have vaadin 8.19 productive, yet. So I cannot say how the overall performance is affected by this particular code change.
I only did a quick review what's changed between 8.18 and 8.19 and noticed, that there is a possible performance bottleneck, which can be easily fixed.

@TatuLund
Copy link
Contributor

Improvement will be included in Vaadin 8.19.1

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

No branches or pull requests

2 participants