1

I need people opinions on how to improve a code I've written. Let's assume we have an application cataloging movies (~3500 of them) and actors (~1000, but I need to double-check this).

Both actors and movies are POJOs. An actor has a picture, stored on disk and its path in a database, along with the person others attributes. A movie has a set of actors and other POJOs attributes.

Given a movie, I need to be able to select the actors playing in it. I've therefore built a jlist with a scaled down buffered image of actors image. This jlist is heavily used through out the app. And the problems are with the performances of populating this jlist. It takes quite some time to create all the person objects and load their images (~2 mins) and this destroys usability. The bottleneck currently is the disk IO on the image reading. I have been through several iterations, but the latest is as follow:

  • On start-up, loop through the person table, and create all the person objects with attributes accessible directly in the DB.
  • Loop through the above collection of person objects, and for each one, go get its image and its buffered images (which are used in different contexts, the buffered image being used a lot more often) and add them as attributes. The images are on disk.
  • Return the above synchronized arraylist to the application layer, and use it as a cache.

There is little differences between getting the attributes and the images in the same loop (in terms of performances at least). With this approach, I have to wait for the full 2 mins to create all the objects before starting to use the app. But using the jlist is super fast as I just need access to the cache. But I'd like to reduce the waiting time to load the app. I understand there is not much that can be done to improve the disk access, but maybe a better approach is possible.

This is a java application with swing and sqlite. I can share some part of the code if it helps clarify the question.

  • You should rethink loading so many images in Java at once. It will keep killing performance. I don't know how you store the images in memory? As their compressed size or in a full "image" object with a bitmap? Especially having so many images as bitmap will kill performance. – Pieter B May 31 '17 at 16:49
  • Have you considered pre-creating the scaled down images and loading the full images only when requested? I.e. when selecting a movie or actor, then load the full version from disk, otherwise use a thumbnail. Loading 5k full-size 10MB images is very different from loading 5k 64x64 thumbs. – Ordous May 31 '17 at 16:52
  • 1
    How many images or thumbnails can be viewed at once, and how long does it take to load just that many? – Dan Pichelman May 31 '17 at 17:42
  • 2
    "I need people opinions on how to improve a code I've written. " - consider presenting parts of it on codereview.stackexchange.com – Timothy Truckle May 31 '17 at 18:26
  • 1
    Would Lazy loading (the idea to only create the POJOs that you need immediately) be helpful here? – Dan Pichelman May 31 '17 at 21:36
2

You can use a ListModel to return placeholder values until things get loaded. On startup you only load and cache the first few dozen. then when the value is requested to fire off a task using SwingWorker running in a background thread.

public class BackgroundLoader extends SwingWorker<Void, Person>{

    private LinkedBlockingQueue<ID> queue = new LinkedBlockingQueue<>();
    private MyListModel list;

    //runs in background -> not safe to access ListModel
    public Void doInBackground(){

        while(true){
            ID id = queue.take();
            Person person = PersonDB.load(id);
            publish(person);
        }
    }

    //runs in swing event thread -> safe to access ListModel
    public void process(List<V> chunks){
        list.addPersons(chunks);
    }

    public void startLoad(ID id){
        queue.put(id);
    }

}

In the same vein don't load images upfront. When you need an image return a placeholder and dispatch a SwingWorker to load the actual image.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.