Skip to content

Commit

Permalink
Merge pull request #31 from BME-MIT-IET/non-functional-tests
Browse files Browse the repository at this point in the history
Non functional tests
  • Loading branch information
Posfay authored May 22, 2024
2 parents fd6fd90 + 1afd358 commit 58dbd95
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 6 deletions.
30 changes: 30 additions & 0 deletions doc/Non_functional_tests.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
= Non-Functional Testing Report

== Decision to Use JProfiler

After careful consideration of the application's type — an offline, Java Swing-based, single-player game — we decided to use JProfiler instead of JMeter. While JMeter is excellent for load testing and performance testing of web applications, JProfiler offers more comprehensive capabilities for profiling Java applications. JProfiler's robust feature set makes it an ideal choice for analyzing CPU and memory usage, detecting memory leaks, and optimizing performance.

== Profiling the Application

In this project, we used JProfiler to profile the entire application, focusing on both the menu screen and the in-game state. The primary areas of focus were:

- **Memory Usage**: Monitoring the application's memory consumption and identifying any memory leaks.
- **CPU Usage**: Analyzing CPU utilization to detect performance bottlenecks.

=== Menu Screen Profiling

While profiling the application in the menu screen, we observed a significant amount of continuous object creation. The top objects by instance count and memory consumption were:

- `java.awt.geom.AffineTransform`: 7000 instances/sec
- `sun.java2d.SunGraphics2D`: 4500 instances/sec
- `java.awt.Rectangle`: 3500 instances/sec

These objects were being created at a high rate, leading to increased memory usage and CPU consumption.

=== In-Game Profiling

During in-game profiling, similar patterns of excessive object creation were noted. By analyzing the memory and CPU usage, we were able to identify areas where performance could be optimized.

== Identifying and Optimizing the Window Refresher Method

One of the key findings from the profiling sessions was a small issue with the window refresher method. The `repaint` method was being called more often than needed, leading to unnecessary object creation and higher CPU usage. We implemented a small optimization by reducing the frequency of the `repaint` calls, resulting in a noticeable improvement in performance.
20 changes: 14 additions & 6 deletions src/macaroni/app/App.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,37 @@
import java.util.logging.Level;

public final class App {

private static final Logger logger = Logger.getLogger(App.class.getName());

private final long FPS = 60;
boolean running = false;

private final Window window = new Window();

public void run() {
logger.info("Application started.");
running = true;
window.open();

long fps = 60;
long lastLoopTime = System.currentTimeMillis();
final long OPTIMAL_TIME = 1000 / fps;

while (running) {
long currentLoopTime = System.currentTimeMillis();
long elapsedTime = currentLoopTime - lastLoopTime;

if (window.shouldClose()) {
logger.info("Window should close. Stopping application.");
running = false;
}

if (elapsedTime >= OPTIMAL_TIME) {
window.repaint();
lastLoopTime = currentLoopTime;
}

window.repaint();

long currentLoopTime = System.currentTimeMillis();
long sleepTime = 1000 / FPS - (currentLoopTime - lastLoopTime);
long sleepTime = lastLoopTime - System.currentTimeMillis() + OPTIMAL_TIME;
if (sleepTime >= 0) {
try {
logger.fine("Sleeping for " + sleepTime + " ms.");
Expand All @@ -35,7 +44,6 @@ public void run() {
running = false;
}
}
lastLoopTime = currentLoopTime;
}

window.close();
Expand Down

0 comments on commit 58dbd95

Please sign in to comment.