diff --git a/CLAUDE.md b/CLAUDE.md
index a410410..e2712d6 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -30,7 +30,7 @@ java -jar target/cloudsimplus-benchmarks-8.5.1-uber.jar -l
Alternative entry points (run from the IDE or with `exec`/`java -cp`):
- `org.cloudsimplus.benchmarks.Run` runs every JMH benchmark matching `org.cloudsimplus.` with preset options (1 fork, 5 warmup, 25 measurement iterations, ms, 1 thread).
- `org.cloudsimplus.benchmarks.SimulationTimeBenchmark` is a plain `main` (not JMH): it runs a full simulation several times, growing Hosts/VMs/Cloudlets each run, and prints execution time.
-- `org.cloudsimplus.listeners.ListenersMemoryBenchmark` is a plain `main` (not JMH): it prints the heap retained by each VM and Host (run it with `-XX:+UseSerialGC`). To compare with CloudSim Plus 8.5.1 (before issue #586), build with `./mvnw clean package -Pcloudsimplus-8`, run it, then build without the profile and run it again (see its Javadoc).
+- `org.cloudsimplus.benchmarks.MemoryFootprintBenchmark` is a plain `main` (not JMH): it prints the heap retained by each VM, Host and Cloudlet, i.e., their memory footprint (run it with `-XX:+UseSerialGC`). To compare with CloudSim Plus 8.5.1 (before issues #586 and #587), build with `./mvnw clean package -Pcloudsimplus-8`, run it, then build without the profile and run it again (see its Javadoc).
There are no unit tests in this project.
diff --git a/src/main/java/org/cloudsimplus/listeners/ListenersMemoryBenchmark.java b/src/main/java/org/cloudsimplus/benchmarks/MemoryFootprintBenchmark.java
similarity index 74%
rename from src/main/java/org/cloudsimplus/listeners/ListenersMemoryBenchmark.java
rename to src/main/java/org/cloudsimplus/benchmarks/MemoryFootprintBenchmark.java
index 560ab48..2595b3e 100644
--- a/src/main/java/org/cloudsimplus/listeners/ListenersMemoryBenchmark.java
+++ b/src/main/java/org/cloudsimplus/benchmarks/MemoryFootprintBenchmark.java
@@ -21,8 +21,9 @@
* You should have received a copy of the GNU General Public License
* along with CloudSim Plus. If not, see .
*/
-package org.cloudsimplus.listeners;
+package org.cloudsimplus.benchmarks;
+import org.cloudsimplus.cloudlets.CloudletSimple;
import org.cloudsimplus.hosts.HostSimple;
import org.cloudsimplus.resources.PeSimple;
import org.cloudsimplus.vms.VmSimple;
@@ -34,10 +35,16 @@
import java.util.List;
import java.util.function.IntFunction;
-/// Measures the heap retained by each VM and Host, to compare the memory used
-/// before and after the listener lists became the shared `List.of()` (issue #586).
-/// Before that, each VM created 6 empty `ArrayList`s and each Host created
-/// 2 empty `ArrayList`s and 1 empty `HashSet`, even when no listener was added.
+/// Measures the heap retained by each VM, Host and Cloudlet (their memory footprint),
+/// to compare CloudSim Plus versions. Since it measures the whole object (with everything it references),
+/// it includes all changes that affect the footprint, such as:
+/// - [#586](https://github.com/cloudsimplus/cloudsimplus/issues/586): listener lists start as the shared `List.of()`.
+/// Before that, each VM created 6 empty `ArrayList`s and each Host created
+/// 2 empty `ArrayList`s and 1 empty `HashSet`, even when no listener was added.
+/// - [#587](https://github.com/cloudsimplus/cloudsimplus/issues/587): reduces the Cloudlet footprint.
+/// Before that, each Cloudlet created 3 empty listener `HashSet`s, an empty `requiredFiles` `LinkedList`
+/// and a new `UtilizationModelFull` for its CPU. Now, the listener and `requiredFiles` lists start as the shared `List.of()`,
+/// and the CPU uses the shared `UtilizationModel.FULL`.
///
/// It's a plain `main` (not JMH), since JMH measures time and allocation rate,
/// but here we need the memory that stays in the heap after the objects are created.
@@ -48,20 +55,19 @@
/// The results are only accurate with a stop-the-world GC, where [System#gc()]
/// does a full collection, so run it with `-XX:+UseSerialGC`.
///
-/// To compare CloudSim Plus 8.5.1 (before #586) with the current version, build and run it once for each version:
+/// To compare CloudSim Plus 8.5.1 (before #586 and #587) with the current version, build and run it once for each version:
///
/// ```bash
/// ./mvnw clean package -Pcloudsimplus-8 # CloudSim Plus 8.5.1
-/// java -XX:+UseSerialGC -cp target/cloudsimplus-benchmarks-*-uber.jar org.cloudsimplus.listeners.ListenersMemoryBenchmark 8.5.1
+/// java -XX:+UseSerialGC -cp target/cloudsimplus-benchmarks-*-uber.jar org.cloudsimplus.benchmarks.MemoryFootprintBenchmark 8.5.1
///
/// ./mvnw clean package # current CloudSim Plus version
-/// java -XX:+UseSerialGC -cp target/cloudsimplus-benchmarks-*-uber.jar org.cloudsimplus.listeners.ListenersMemoryBenchmark current
+/// java -XX:+UseSerialGC -cp target/cloudsimplus-benchmarks-*-uber.jar org.cloudsimplus.benchmarks.MemoryFootprintBenchmark current
/// ```
///
/// @author Manoel Campos da Silva Filho
-/// @see CloudSim Plus issue #586
/// @see CloudSim Plus issue #523
-public final class ListenersMemoryBenchmark {
+public final class MemoryFootprintBenchmark {
/// Number of objects of each type created in each round.
private static final int OBJECTS = 100_000;
@@ -80,20 +86,24 @@ public final class ListenersMemoryBenchmark {
private static final long HOST_BW = 10_000;
private static final long HOST_STORAGE = 100_000;
+ private static final long CLOUDLET_LENGTH = 10_000;
+ private static final int CLOUDLET_PES = 1;
+
private static final MemoryMXBean MEMORY = ManagementFactory.getMemoryMXBean();
/// A private constructor to avoid class instantiation.
- private ListenersMemoryBenchmark(){}
+ private MemoryFootprintBenchmark(){}
/// Runs the benchmark.
/// @param args an optional label to identify the CloudSim Plus version being measured (e.g., "before" or "after")
public static void main(final String[] args) {
final String label = args.length > 0 ? args[0] : "current";
System.out.printf("%s (%s): %,d objects per round, median of %d rounds%n",
- ListenersMemoryBenchmark.class.getSimpleName(), label, OBJECTS, ROUNDS);
+ MemoryFootprintBenchmark.class.getSimpleName(), label, OBJECTS, ROUNDS);
- printResult("VmSimple", measure(ListenersMemoryBenchmark::newVm));
- printResult("HostSimple", measure(ListenersMemoryBenchmark::newHost));
+ printResult("VmSimple", measure(MemoryFootprintBenchmark::newVm));
+ printResult("HostSimple", measure(MemoryFootprintBenchmark::newHost));
+ printResult("CloudletSimple", measure(MemoryFootprintBenchmark::newCloudlet));
}
private static VmSimple newVm(final int index) {
@@ -106,6 +116,11 @@ private static HostSimple newHost(final int index) {
return new HostSimple(HOST_RAM, HOST_BW, HOST_STORAGE, List.of(new PeSimple(PE_MIPS)));
}
+ /// Creates a Cloudlet with the default utilization models.
+ private static CloudletSimple newCloudlet(final int index) {
+ return new CloudletSimple(CLOUDLET_LENGTH, CLOUDLET_PES);
+ }
+
/// {@return the median heap (in bytes) retained by each object created by a given function}
/// @param factory a function that creates an object for a given index
private static double measure(final IntFunction