2
\$\begingroup\$

I would like to optimize the way that I save file.

Actually, each seconds I save lot of string in different files. So, I made lot of IO at the same time, instead of making a little during more time.

So, I want to write file but without asking too many IO at same time and so don't put the disk at 100% of I/O used (specially for someone who are on Raspberry/HDD).

Currently, I made this code :

public class FileSaverTimer implements Runnable {

    public static final int MAX_RUNNING = 10, SKIP_WHEN_ALREADY = 2;
    private static List<FileSaverAction> allActions = new ArrayList<>();
    public static void addAction(FileSaverAction action) {
        allActions.add(action);
    }
    
    private int actionRunning = 0;
    
    @Override
    public void run() {
        if(actionRunning > SKIP_WHEN_ALREADY)
            return; // too many already running, skipping...
        for(int i = actionRunning; i < Math.min(MAX_RUNNING, allActions.size()); i++) {
            FileSaverAction action = allActions.remove(0); // removing first item
            actionRunning++; // adding a running task
            action.save(() -> actionRunning--); // save, and when it's finished removing running task
        }
    }

    public static interface FileSaverAction {
        
        /**
         * Technically save the save sync with the thread which run this
         * 
         * @param finished the action to run when it's finished
         */
        void save(FileSaverFinished finished);
    }

    public static interface FileSaverFinished {
        
        /**
         * The action that will be called when the action is finished.
         */
        void finish();
    }
}

Then, to use:

FileSaverTimer.addAction((finished) -> {
    try {
        Files.write(file, content.getBytes(), StandardOpenOption.APPEND);
    } catch (IOException e) {
        e.printStackTrace();
    }
    finished.finish();
});

Also, there is only ONE instance of the timer which run asyncally each seconds, and it's called like that:

Bukkit.getScheduler().runTaskTimerAsynchronously(this, new FileSaverTimer(), 20, 20);
// 20 ticks = 1 second

The objective is to add file in a queue, and wait until previous tasks have been done. But I don't know how I have to define limits SKIP_WHEN_ALREADY and MAX_RUNNING, and if it's really relevant.

Some informations :

  • Now, this code works (I'm sure I can do better)
  • Some files can be back quickly in the queue with other informations (I can know which are more possible to come back)
  • Not necessary to save it as soon as possible (everything stay in RAM)

So, can you help me to do better? Specially to works better according to user hardware?

Is it better to make lot of little file save (few line), or only one big save ?

Also, I agree if you have another structure to do it. I just proposed my code to know what I can upgrade, but change everything can also upgrade the result!

\$\endgroup\$
6
  • 1
    \$\begingroup\$ You're using a static, non thread safe collection across all instances of your saver class, however the actionsRunning is non-static. Are you expecting access from multiple threads/instances? How are instances of the timer being created/what is invoking the run method? \$\endgroup\$
    – forsvarir
    Oct 20 at 19:24
  • \$\begingroup\$ There is only one instance of the timer that is running, it's static to make is faster to register file to save. They all will be used only by one instance of this thread \$\endgroup\$
    – Elikill58
    Oct 20 at 19:33
  • 1
    \$\begingroup\$ Can you share a bit more details about what kind of optimization are you looking for? Have you identified problems with your current approach, for example bottlenecks, or low throughput, or others. How would you measure the success of optimizations? \$\endgroup\$
    – janos
    Oct 21 at 14:56
  • 1
    \$\begingroup\$ Welcome to Code Review! "without making the disk at 100%" - is that 100% used space? or something else? \$\endgroup\$ Oct 21 at 16:48
  • 1
    \$\begingroup\$ No, 100% of used performance, not space. Not taking all power of disk and so impact other files/apps. But thanks :) \$\endgroup\$
    – Elikill58
    Oct 21 at 16:51

Your Answer

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

Browse other questions tagged or ask your own question.