Why is this Java application running slowly on a Mac and not on a PC?

I created an application using Java and it runs smoothly on the Windows platform. However, when it was tested on my Macbook Pro Retina 15 'with the 4960HQ, the displayed frame rate was significantly lower.

I encoded a program to run animations at a constant frequency of 60 frames per second, and the console shows that 60 frames per second are retrieved on both Mac and Windows. However, the program on a Mac looks like it is running at a speed of 6-8 frames per second.

Is there a custom coding methodology developed for the Mac? Or is Java just not optimized for Mac OSX?

Minimum working code example:

    long framerate = 1000 / 60;
    // time the frame began
    long frameStart;
    // number of frames counted this second
    long frameCount = 0;
    // time elapsed during one frame
    long elapsedTime;
    // accumulates elapsed time over multiple frames
    long totalElapsedTime = 0;
    // the actual calculated framerate reported

    while(true){
        frameStart = System.currentTimeMillis();

        world.moveBG(3);

        // calculate the time it took to render the frame
            elapsedTime = System.currentTimeMillis() - frameStart;
            // sync the framerate
            try {
                // make sure framerate milliseconds have passed this frame
                if (elapsedTime < framerate) {
                    Thread.sleep(framerate - elapsedTime);
                } else {
                    // don't starve the garbage collector
                    Thread.sleep(5);
                }
            } catch (InterruptedException e) {
                break;
            }
            ++frameCount;
            totalElapsedTime += (System.currentTimeMillis() - frameStart);
            if (totalElapsedTime > 1000) {
                reportedFramerate = (long) ((double) frameCount
                        / (double) totalElapsedTime * 1000.0);
                // show the framerate in the applet status window
                System.out.println("fps: " + reportedFramerate);
                // repaint();
                frameCount = 0;
                totalElapsedTime = 0;
            }
    }

fps, 60fps . world.moveBG(3) 3 ( , ). Mac 10fps 60. 60 .

, , Mac, Windows, , Mac

+4
1

. Windows 3 , 179 , 60 , .

, :

package com.nosolojava.test;

import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.logging.Logger;

public class FrameRateExecutor {

private final Logger logger = Logger.getLogger(this.getClass().getCanonicalName());

final static long framerate = 1000 / 60;

// number of frames counted this second
AtomicInteger frameCount = new AtomicInteger(0);

ScheduledExecutorService executor;
private volatile AtomicBoolean running = new AtomicBoolean(false);

class Task implements Runnable {
    private final long lastTaskTimeStamp;

    public Task() {
        super();
        //get creation time so we can calculate delay after
        this.lastTaskTimeStamp = System.currentTimeMillis();
    }

    public void run() {
        // TODO implement logic
        logger.log(
                Level.INFO,
                String.format("Do something, framecount: %02d %d", frameCount.addAndGet(1),
                        System.currentTimeMillis()));

        //calculate when to execute next task and submit
        long currentTime = System.currentTimeMillis();
        long elapsed = currentTime - lastTaskTimeStamp;
        long delay = (framerate - elapsed) +framerate;

        logger.log(Level.INFO, String.format("elapsed %04d delay %04d", elapsed, delay));

        //check finish condition 
        if (running.get()) {
            executor.schedule(new Task(), delay, TimeUnit.MILLISECONDS);
        }
    }
};

public void stop() {
    running.set(false);
    executor.shutdown();

    try {
        executor.awaitTermination(3, TimeUnit.SECONDS);
    } catch (InterruptedException e) {
        logger.log(Level.SEVERE, "Error stopping executor", e);
    }

}

public void start() {

    //check if is already up
    if (this.running.compareAndSet(false, true)) {
        //init scheduled executor
        executor = new ScheduledThreadPoolExecutor(1);

        //start first task 
        executor.execute(new Task());
    }
}

public static void main(String[] args) throws InterruptedException {
    FrameRateExecutor frameExecutor = new FrameRateExecutor();

    frameExecutor.start();

    Thread.sleep(3000);
    frameExecutor.stop();

}

}

+1

Source: https://habr.com/ru/post/1535075/


All Articles