Skip to content

Commit 8f5762c

Browse files
committed
Keep Timer for compatibility
1 parent 82a6a7b commit 8f5762c

2 files changed

Lines changed: 255 additions & 8 deletions

File tree

src/main/java/pascal/taie/util/Monitor.java

Lines changed: 109 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,48 @@
3939
import java.util.concurrent.TimeoutException;
4040
import java.util.function.Supplier;
4141

42+
/**
43+
* A comprehensive monitoring utility for tracking task execution metrics including
44+
* elapsed time, CPU usage, and memory consumption.
45+
*
46+
* <p>This class provides both instance-based and static methods for monitoring tasks.
47+
* It tracks the following metrics:
48+
* <ul>
49+
* <li><b>Elapsed Time:</b> Total execution time in seconds</li>
50+
* <li><b>CPU Usage:</b> Process CPU load at start, peak, and end of execution</li>
51+
* <li><b>Memory Usage:</b> Heap and non-heap memory consumption at start, peak, and end</li>
52+
* </ul>
53+
*
54+
* <p>The monitor uses a scheduled executor to periodically sample CPU and memory usage
55+
* (every {@value #INTERVAL} second) to capture peak values during task execution.
56+
*
57+
* <p><b>Example usage (instance-based):</b>
58+
* <pre>{@code
59+
* Monitor monitor = new Monitor("MyTask");
60+
* monitor.start();
61+
* // ... perform task ...
62+
* monitor.stop();
63+
* System.out.println(monitor); // Prints all metrics
64+
* }</pre>
65+
*
66+
* <p><b>Example usage (static convenience method):</b>
67+
* <pre>{@code
68+
* Monitor.runAndCount(() -> {
69+
* // ... perform task ...
70+
* }, "MyTask");
71+
* }</pre>
72+
*
73+
* <p>This class replaces the deprecated {@link Timer} class and provides enhanced
74+
* monitoring capabilities beyond simple time tracking.
75+
*
76+
* @see Timer
77+
*/
4278
public class Monitor {
4379

4480
private static final Logger logger = LogManager.getLogger(Monitor.class);
4581

4682
/**
47-
* Monitoring interval in seconds
83+
* Monitoring interval in seconds for periodic CPU and memory sampling.
4884
*/
4985
private static final int INTERVAL = 1;
5086

@@ -68,6 +104,11 @@ public class Monitor {
68104

69105
private boolean inCounting = false;
70106

107+
/**
108+
* Creates a new Monitor with the given name.
109+
*
110+
* @param name the name of this monitor, used in output messages
111+
*/
71112
public Monitor(String name) {
72113
this.name = name;
73114
this.osBean = (OperatingSystemMXBean) ManagementFactory
@@ -80,6 +121,13 @@ public Monitor(String name) {
80121
});
81122
}
82123

124+
/**
125+
* Starts the monitoring process.
126+
*
127+
* <p>Records the start time and initial CPU/memory metrics, and begins
128+
* periodic sampling of CPU and memory usage to track peak values.
129+
* If the monitor is already running, this call has no effect.
130+
*/
83131
public void start() {
84132
if (!inCounting) {
85133
inCounting = true;
@@ -92,6 +140,13 @@ public void start() {
92140
}
93141
}
94142

143+
/**
144+
* Stops the monitoring process.
145+
*
146+
* <p>Records the final elapsed time and end CPU/memory metrics, then
147+
* shuts down the periodic sampling scheduler. If the monitor is not
148+
* currently running, this call has no effect.
149+
*/
95150
public void stop() {
96151
if (inCounting) {
97152
inCounting = false;
@@ -111,15 +166,34 @@ public void stop() {
111166
}
112167
}
113168

169+
/**
170+
* Returns the total elapsed time in seconds.
171+
*
172+
* @return the elapsed time in seconds as a floating-point number
173+
*/
114174
public float inSecond() {
115175
return elapsedTime / 1000F;
116176
}
117177

178+
/**
179+
* Clears all monitoring data and resets the counting state.
180+
*
181+
* <p>This resets the elapsed time to zero and marks the monitor as not counting.
182+
*/
118183
public void clear() {
119184
elapsedTime = 0;
120185
inCounting = false;
121186
}
122187

188+
/**
189+
* Returns a string representation of the monitoring results.
190+
*
191+
* <p>The output includes the monitor name, elapsed time, CPU usage statistics
192+
* (start, peak, and end percentages), and memory usage statistics (start, peak,
193+
* and end in megabytes).
194+
*
195+
* @return a formatted string containing all monitoring metrics
196+
*/
123197
@Override
124198
public String toString() {
125199
StringBuilder sb = new StringBuilder();
@@ -157,10 +231,16 @@ private long getMemoryUsedMB() {
157231
}
158232

159233
/**
160-
* Runs a task, log the elapsed time, and return the result.
234+
* Runs a task, monitors its execution, logs the results, and returns the task's result.
235+
*
236+
* <p>This is a convenience method that creates a Monitor, starts it, executes the task,
237+
* stops monitoring, and logs the results at the specified logging level.
161238
*
162-
* @param task task to be executed
163-
* @param taskName name of the task
239+
* @param <T> the type of result returned by the task
240+
* @param task the task to be executed
241+
* @param taskName the name of the task for logging purposes
242+
* @param level the logging level for the monitoring results
243+
* @return the result of the task execution
164244
*/
165245
public static <T> T runAndCount(Supplier<T> task, String taskName, Level level) {
166246
logger.info("[{}] starts ...", taskName);
@@ -173,15 +253,28 @@ public static <T> T runAndCount(Supplier<T> task, String taskName, Level level)
173253
}
174254

175255
/**
176-
* Runs a task and log the elapsed time.
256+
* Runs a task, monitors its execution, and logs the results at INFO level.
177257
*
178-
* @param task task to be executed
179-
* @param taskName taskName of the task
258+
* <p>This is a convenience method that creates a Monitor, starts it, executes the task,
259+
* stops monitoring, and logs the results at INFO level.
260+
*
261+
* @param task the task to be executed
262+
* @param taskName the name of the task for logging purposes
180263
*/
181264
public static void runAndCount(Runnable task, String taskName) {
182265
runAndCount(task, taskName, Level.INFO);
183266
}
184267

268+
/**
269+
* Runs a task, monitors its execution, and logs the results at the specified level.
270+
*
271+
* <p>This is a convenience method that creates a Monitor, starts it, executes the task,
272+
* stops monitoring, and logs the results at the specified logging level.
273+
*
274+
* @param task the task to be executed
275+
* @param taskName the name of the task for logging purposes
276+
* @param level the logging level for the monitoring results
277+
*/
185278
public static void runAndCount(Runnable task, String taskName, Level level) {
186279
runAndCount(() -> {
187280
task.run();
@@ -190,7 +283,14 @@ public static void runAndCount(Runnable task, String taskName, Level level) {
190283
}
191284

192285
/**
193-
* Runs a task with given time budget.
286+
* Runs a task with a given time budget.
287+
*
288+
* <p>Executes the task in a separate thread with a timeout. If the task does not
289+
* complete within the specified time limit, the execution is terminated and the
290+
* program exits with status code 1.
291+
*
292+
* @param task the task to be executed
293+
* @param seconds the time budget in seconds
194294
*/
195295
public static void runWithTimeout(Runnable task, long seconds) {
196296
Duration timeout = Duration.ofSeconds(seconds);
@@ -207,4 +307,5 @@ public static void runWithTimeout(Runnable task, long seconds) {
207307
executor.shutdown();
208308
}
209309
}
310+
210311
}
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
/*
2+
* Tai-e: A Static Analysis Framework for Java
3+
*
4+
* Copyright (C) 2022 Tian Tan <tiantan@nju.edu.cn>
5+
* Copyright (C) 2022 Yue Li <yueli@nju.edu.cn>
6+
*
7+
* This file is part of Tai-e.
8+
*
9+
* Tai-e is free software: you can redistribute it and/or modify
10+
* it under the terms of the GNU Lesser General Public License
11+
* as published by the Free Software Foundation, either version 3
12+
* of the License, or (at your option) any later version.
13+
*
14+
* Tai-e is distributed in the hope that it will be useful,but WITHOUT
15+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16+
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
17+
* Public License for more details.
18+
*
19+
* You should have received a copy of the GNU Lesser General Public
20+
* License along with Tai-e. If not, see <https://www.gnu.org/licenses/>.
21+
*/
22+
23+
package pascal.taie.util;
24+
25+
import org.apache.logging.log4j.Level;
26+
import org.apache.logging.log4j.LogManager;
27+
import org.apache.logging.log4j.Logger;
28+
29+
import java.time.Duration;
30+
import java.util.concurrent.ExecutionException;
31+
import java.util.concurrent.ExecutorService;
32+
import java.util.concurrent.Executors;
33+
import java.util.concurrent.Future;
34+
import java.util.concurrent.TimeUnit;
35+
import java.util.concurrent.TimeoutException;
36+
import java.util.function.Supplier;
37+
38+
/**
39+
* A utility class for timing tasks and logging elapsed time.
40+
*
41+
* <p><b>Note:</b> This class is deprecated and will be removed in a future version.
42+
* Please use {@link Monitor} instead, which provides enhanced monitoring capabilities
43+
* including CPU and memory usage tracking in addition to elapsed time.
44+
*
45+
* @deprecated Use {@link Monitor} instead for improved monitoring with CPU and memory tracking.
46+
* @see Monitor
47+
*/
48+
@Deprecated(forRemoval = true)
49+
public class Timer {
50+
51+
private static final Logger logger = LogManager.getLogger(Timer.class);
52+
53+
private final String name;
54+
55+
private long elapsedTime = 0;
56+
57+
private long startTime;
58+
59+
private boolean inCounting = false;
60+
61+
public Timer(String name) {
62+
this.name = name;
63+
}
64+
65+
public void start() {
66+
if (!inCounting) {
67+
inCounting = true;
68+
startTime = System.currentTimeMillis();
69+
}
70+
}
71+
72+
public void stop() {
73+
if (inCounting) {
74+
elapsedTime += System.currentTimeMillis() - startTime;
75+
inCounting = false;
76+
}
77+
}
78+
79+
public float inSecond() {
80+
return elapsedTime / 1000F;
81+
}
82+
83+
public void clear() {
84+
elapsedTime = 0;
85+
inCounting = false;
86+
}
87+
88+
@Override
89+
public String toString() {
90+
return String.format("[%s] elapsed time: %.2fs",
91+
name, inSecond());
92+
}
93+
94+
/**
95+
* Runs a task, log the elapsed time, and return the result.
96+
*
97+
* @param task task to be executed
98+
* @param taskName name of the task
99+
*/
100+
public static <T> T runAndCount(Supplier<T> task, String taskName, Level level) {
101+
logger.info("{} starts ...", taskName);
102+
Timer timer = new Timer(taskName);
103+
timer.start();
104+
T result = task.get();
105+
timer.stop();
106+
logger.log(level, "{} finishes, elapsed time: {}", taskName,
107+
String.format("%.2fs", timer.inSecond()));
108+
return result;
109+
}
110+
111+
/**
112+
* Runs a task and log the elapsed time.
113+
*
114+
* @param task task to be executed
115+
* @param taskName taskName of the task
116+
*/
117+
public static void runAndCount(Runnable task, String taskName) {
118+
runAndCount(task, taskName, Level.INFO);
119+
}
120+
121+
public static void runAndCount(Runnable task, String taskName, Level level) {
122+
runAndCount(() -> {
123+
task.run();
124+
return null;
125+
}, taskName, level);
126+
}
127+
128+
/**
129+
* Runs a task with given time budget.
130+
*/
131+
public static void runWithTimeout(Runnable task, long seconds) {
132+
Duration timeout = Duration.ofSeconds(seconds);
133+
ExecutorService executor = Executors.newSingleThreadExecutor();
134+
Future<?> handler = executor.submit(task);
135+
try {
136+
handler.get(timeout.getSeconds(), TimeUnit.SECONDS);
137+
} catch (TimeoutException e) {
138+
e.printStackTrace();
139+
System.exit(1);
140+
} catch (InterruptedException | ExecutionException e) {
141+
e.printStackTrace();
142+
} finally {
143+
executor.shutdown();
144+
}
145+
}
146+
}

0 commit comments

Comments
 (0)