Approach to solving performance problems with spring-vaadin

I’ve got a spring-based vaadin 23 application that exhibits significant slowness in initial UI component navigation. I’ve so far been unable to diagnose the issues - service singletons should already be constructed and I’ve whitelisted the appropriate packages, but it is still far slower than expected. Strategies for figuring out the issue(s) would be most welcome.

Can you please explain more what is slow? Can you show the code?

“the code” is a largish existing flow application that’s been ported from vaadin7->10->14->23: I haven’t any idea how to show anything that would be useful here, which is why I’m looking for strategies. General instrumentation wasn’t terribly helpful - nothing stuck out anyway. Spring component instrumentation was a little more helpful in that I could see some substantial delays, but never in the actual scope of the easily traceable methods. I wonder about the time it takes to ship javascript blobs to the web browser, but I don’t see where to instrument that on the server side, as I don’t see a lot of transfer time on the client side, only idleness. The basic observation is that each navigation to a new application endpoint takes longer than I expect with the loading indicator visible for multiple seconds. Different endpoints take different amounts of time to become active, which implicates Spring, but there are certainly other possible explanations with database or JS network transfer as the obvious alternatives.

First I would have a look at the network activity from the browser developer tools

If the database is a suspect then turn on SQL logging and check if there are many SQL statements executed

You could also use Spring AOP to log the execution time of Java methods

Minor follow up: I’ so far my most effective technique has been to get stack dumps during slowdowns. For the most part it has been due to some sort of conflict between the vaadin spring beanloader and the baseline spring bean provisioning API which we were using directly to provision some deep business logic beans that weren’t really UI elements… this appears to be a mistake since it looks like the vaadin spring and base spring don’t seem to be sharing a cache - even worse, they seem to be using different classloaders, which makes scanning extra awful when you deploy as an unexploded executable WAR.

Simon is definitely right about this. If you’re trying to debug performance, you need to either have robust logging, or some kind of an understanding of what’s happening behind the scenes.

Even though I have the same issue we also have updated the app from 7->14->23
But after updating to 23 i see slowness in internal navigation between tabs
I think because of DB app may be slow so I have added a chaching mechanism in hibernate and spring repo, it helps but is not up to the mark, I’m also faded with the time taken by loading the indicator while navigating to another endpoint
can anyone from vaadin team share the strategies to improve the performance of the app or
something that will help us !

It’s hard to share “always valid points that works on every app” - but some things to keep in mind:

  • less is sometimes more
  • lazy loading of data is key
  • if something needs time to load, add a loading indicator

This guide includes some tips on handling long-running tasks: https://vaadin.com/docs/latest/advanced/long-running-tasks.

That could certainly be true and worth looking into. I know we could be doing better with hibernate caching ourselves, but my initial successes have been to simplify our use of spring to make certain that beans are loaded and wired by the vaadin layer exclusively.

yes, but we’re not talking about long-running tasks here - these are major Vaadin Spring components that are taking excessively long to instantiate and wire, and the time is spent in the guts of Vaadin, Spring, and Java, not in application code. Furthermore, the slowness has happened in the V14->V23 transition: I’m not sure what changed, but something clearly has that wasn’t, as far as I can tell, in the release notes.

yeah - refactoring is always a good thing for the first two points, and I’m slowly making progress there. As far as point three goes, since the slowness is in component construction, adding a loading indicator isn’t terribly satisfying since the router tends to leave you looking at a blank screen while building up the components to populate it.

What component is affected? Can you pin point it to some special components, add-ons, lit templates or anything else?

well, it was a bunch of different components, like around 20 of them with very different compositions so I knew I couldn’t pin the blame to any one component. This is why I was asking about strategies to identify the problems since I wasn’t having much luck finding anyplace in our code to put metrics collection. Anyway, things are getting substantially better since discovering the conflicts between Spring Vaadin and plain-old-spring bean/classloader caching. Basically, I’m going through and retiring all the latter and that’s making a substantial difference.

:thinking: interesting - how did you instantiate all your components that this way was used? Personally never had problems injecting Vaadin components directly or using Vaadin’s Instantiator::createComponent

All the primary components are standard vaadin spring beans, so they’re okay. The problem is that sometimes we had them using plain old java constructors somewhere deeper and then using annotation autowiring of their data members through a static spring ApplicationContext (obviously only for singleton services). A dramatically cut down pseudo-example:
public class ContextProvider { public static void autowire(Object thing) { beanFactory.autowireBeanProperties(thing, ...); } } @Route(...) @UIScope public class SomeTool extends Div { public SomeTool() { add(new DeepThing()); } } public class DeepThing extends Div { @Autowired private SomeService someService; public DeepThing() { ... ContextProvider.autowire(this); ... } }
An awful hack, I know, but I inherited that awful hack, so… Anyway, that static autowire seems not to share state with whatever is loading the main components, and might not even share the same classloader.

That really looks like an old school hack that isn’t needed anymore thanks to the instantiator mentioned above, that could probably help and can be used instead of new (close to) anywhere

“old school hack” is painfully accurate. FWIW, if I cannot use direct annotation-based injection, I’ve been using BeanFactoryAware - perhaps Instantiator::createComponent would be a better alternative, at least for beans that live only in the UI - thanks.