SpringBoot High CPU භාවිතය විසඳමු | Performance Tuning Sinhala Guide
ආයුබෝවන් යාළුවනේ!
ඔබ Spring Boot එක්ක වැඩ කරන developer කෙනෙක් නම්, සමහර වෙලාවට ඔබගේ application එක සාමාන්යයට වඩා slow වෙනවා දැකලා ඇති, එහෙමත් නැත්නම් server එකේ CPU usage එක ඉහළ යනවා දැකලා ඇති. මේක developer කෙනෙක් විදිහට අපිට නිතරම මුහුණ දෙන්න වෙන පොදු ගැටලුවක්. Application එකක performance එක අඩුවීම කියන්නේ user experience එකට අහිතකර විදිහට බලපාන දෙයක් වගේම, server costs වැඩි වෙන්නත් පුළුවන්.
මේ tutorial එකෙන් අපි Spring Boot application එකක High CPU usage එකක් කියන්නේ මොකක්ද, ඒක හඳුනාගන්නේ කොහොමද, ඒකට හේතු මොනවද, සහ ඒ ගැටලුව නිරාකරණය කරගන්නේ කොහොමද කියලා විස්තරාත්මකව කතා කරනවා. විශේෂයෙන්ම, අපි profiler එකක් භාවිතා කරලා application එකක තියෙන performance bottlenecks හොයාගන්න හැටිත්, ඒවා නිවැරදි කරගන්න හැටිත් practical example එකක් එක්ක බලමු. එහෙනම්, අපි පටන් ගමු!
1. High CPU Usage එකක් කියන්නේ මොකක්ද?
සරලව කිව්වොත්, CPU usage එකක් කියන්නේ, ඔබගේ computer එකේ හෝ server එකේ Central Processing Unit (CPU) එක කොච්චර කාර්යබහුලද කියන එක. මේක සාමාන්යයෙන් percentage එකක් විදිහට තමයි පෙන්නුම් කරන්නේ (උදා: 10%, 80%, 100%).
Spring Boot application එකක් high CPU usage එකක් පෙන්නුම් කරනවා කියන්නේ, ඒ application එක CPU එකෙන් වැඩිපුර resources ප්රමාණයක් භාවිතා කරනවා කියන එකයි. මේක සාමාන්යයෙන් යම්කිසි කාර්යයක් (task) ඉතාමත් කාර්යක්ෂම නොවන විදිහට ක්රියාත්මක වීම නිසා හෝ එකවර වැඩි tasks ප්රමාණයක් execute කරන්න උත්සාහ කිරීම නිසා ඇති වෙන්න පුළුවන්.
High CPU Usage එකක් නරක ඇයි?
- Application එක slow වීම: CPU එක අධික ලෙස කාර්යබහුල වුණාම, අලුත් requests වලට respond කරන්න ගත වෙන කාලය වැඩි වෙනවා. මේක users ලාට නරක අත්දැකීමක් (poor user experience) දෙන්න පුළුවන්.
- Server unresponsive වීම: සමහර වෙලාවට CPU usage එක 100% ට ආසන්න වුණොත්, application එක සම්පූර්ණයෙන්ම unresponsive වෙලා crash වෙන්නත් පුළුවන්.
- වැඩිපුර server costs: Application එකක performance එක අඩුවෙනකොට, ඒක handles කරන්න සිද්ධ වෙන requests ප්රමාණයට අනුව servers වැඩි කරන්න හෝ powerful servers භාවිතා කරන්න අපිට සිදු වෙනවා. මේක Cloud environments වලදී නම් වැඩිපුර මුදල් වැය වීමට හේතුවක්.
Spring Boot Applications වල High CPU Usage එකට පොදු හේතු:
- Inefficient Algorithms: Code එකේ තියෙන Algorithms කාර්යක්ෂම නොවීම. (උදා: nested loops, recursive functions with no memoization for large inputs).
- Excessive Object Creation/Garbage Collection: අනවශ්ය විදිහට objects විශාල ප්රමාණයක් නිර්මාණය කිරීම සහ ඒවා garbage collect කිරීමට ගතවන කාලය වැඩි වීම.
- Concurrency Issues: Thread pool එකක් වැරදි විදිහට manage කිරීම, Deadlocks හෝ Race conditions නිසා threads අවහිර වීම.
- External System Latency: Database calls, API calls වගේ external services වලට කරන requests වල delay එකක් තිබුණත්, ඒක CPU usage එකට බලපාන්න පුළුවන් (blocking I/O operations).
- Large Data Processing: එකවර විශාල දත්ත ප්රමාණයක් process කිරීමට උත්සාහ කිරීම.
2. High CPU Usage එකක් හඳුනාගන්නේ කොහොමද?
ගැටලුව විසඳීමට පෙර, එය නිවැරදිව හඳුනා ගැනීම අත්යවශ්යයි. High CPU usage එකක් සිදුවන බව දැනගැනීමට සහ එයට වගකිවයුතු process එක හඳුනා ගැනීමට විවිධ ක්රම තිබෙනවා.
2.1. System Monitoring Tools භාවිතය
Operating system එකේ built-in tools භාවිතා කරලා අපිට CPU usage එක monitor කරන්න පුළුවන්. මේවායින් Spring Boot application එකේ process ID (PID) එක සහ ඒකෙන් භාවිතා කරන CPU ප්රමාණය දැනගන්න පුළුවන්.
jcmd (Java Command):Java Development Kit (JDK) එකේ එන jcmd utility එකෙන් running Java applications වලට විවිධ commands execute කරන්න පුළුවන්. High CPU usage එකක් තියෙනකොට, thread dump එකක් ගන්න jcmd භාවිතා කරන්න පුළුවන්.
jcmd <your_java_process_PID> Thread.print > thread_dump.txtමේකෙන් process එකේ තියෙන හැම thread එකකම current state එක, call stack එක වගේ තොරතුරු ලබාදෙනවා. මේ thread_dump.txt file එක analyze කරලා, වැඩිපුරම CPU එක භාවිතා කරන thread එක මොකක්ද කියලා identify කරන්න පුළුවන්. Thread dump එකක් analyze කරනකොට, බොහෝ විට RUNNABLE state එකේ තියෙන threads සහ ඒවායේ stack traces බලන්න වෙනවා. යම්කිසි code section එකක් දිගින් දිගටම stack trace එකේ තිබුණොත්, ඒක bottleneck එකක් වෙන්න පුළුවන්. (උදා: ඔබ top -H -p එකෙන් ලබාගත් අධික CPU භාවිතය සහිත thread ID එක hex format එකට convert කරලා thread dump එක ඇතුළත search කරලා බලන්න පුළුවන්).
top (Linux/macOS) / Task Manager (Windows):top command එක Linux/macOS වලදී real-time CPU usage, memory usage, සහ running processes පෙන්වනවා. Task Manager එක Windows වලදී මේ හා සමාන තොරතුරු සපයනවා.ඔබගේ Spring Boot application එකේ process ID එක (PID) දැනගෙන, top command එකෙන් ඒ process එකේ threads වල CPU usage එක බලන්න පුළුවන්. මේ සඳහා -H flag එක භාවිතා කරන්න.
top -H -p <your_java_process_PID>මේ -H flag එකෙන් process එකේ තියෙන තනි තනි threads වල විස්තර බලාගන්න පුළුවන්. PID, USER, PR (priority), NI (nice value), VIRT, RES (resident memory), SHR (shared memory), S (status), %CPU, %MEM සහ TIME+ වගේ තොරතුරු මෙහිදී පෙන්වනු ලබනවා. මේකෙන් වැඩිපුරම CPU එක භාවිතා කරන thread එක මොකක්ද කියලා හඳුනාගන්න පුළුවන්.
2.2. Application Metrics භාවිතය
Spring Boot Actuator වගේ tools, application එකේ internal metrics expose කරනවා. Prometheus වගේ monitoring tools එක්ක මේවා integrate කරලා, කාලයත් එක්ක CPU usage එක, garbage collection details, thread counts වගේ දේවල් visualize කරන්න පුළුවන්.
Spring Boot Actuator:ඔබගේ pom.xml file එකට Actuator dependency එක එකතු කරන්න:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>පස්සේ application.properties එකේ management.endpoints.web.exposure.include=* කියලා දාලා, සියලුම endpoints expose කරන්න පුළුවන්. දැන් ඔබට /actuator/metrics/system.cpu.usage වගේ endpoints වලින් CPU usage එක බලන්න පුළුවන්.
3. ගැටලුවට මුල සොයාගැනීම: Profiling Techniques
System monitoring tools වලින් High CPU usage එකක් තියෙන බව හඳුනාගත්තට පස්සේ, ඊළඟ පියවර තමයි ඒකට හේතුවන නිශ්චිත code section එක හෝ thread එක identify කිරීම. මෙන්න මේ වගේ වෙලාවට තමයි profilers කියන tools අත්යවශ්ය වෙන්නේ. Profiler එකකින් application එකේ run-time behavior එක analyze කරලා, වැඩිපුරම CPU time එක භාවිතා කරන methods මොනවද කියලා බලාගන්න පුළුවන්.
3.1. VisualVM භාවිතය
VisualVM කියන්නේ JDK එකත් එක්ක එන නොමිලේ භාවිතා කළ හැකි powerful monitoring සහ profiling tool එකක්. (සාමාන්යයෙන් JDK_HOME/bin folder එකේ jvisualvm ලෙස තිබේ.) මේකෙන් local සහ remote Java applications වල performance data බලාගන්න පුළුවන්. අපි VisualVM භාවිතා කරලා high CPU usage එකක් identify කරගන්න හැටි practical example එකකින් බලමු.
Practical Example: CPU Intensive Spring Boot Application එකක් Profile කරමු
පියවර 1: CPU Intensive Spring Boot Application එකක් හදමු
මුලින්ම, අපි හිතාමතාම CPU intensive කාර්යයක් කරන Spring Boot REST Controller එකක් හදාගමු. මේක recursive Fibonacci calculation එකක්.
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class CpuIntensiveController {
@GetMapping("/calculate-fibonacci")
public String calculateFibonacci(@RequestParam(defaultValue = "40") int n) {
long startTime = System.nanoTime();
long result = fibonacci(n);
long endTime = System.nanoTime();
long duration = (endTime - startTime) / 1_000_000; // milliseconds
System.out.println("Fibonacci of " + n + " calculated in " + duration + " ms.");
return "Fibonacci of " + n + " is " + result + " (calculated in " + duration + " ms)";
}
// A CPU-intensive recursive Fibonacci function
private long fibonacci(int n) {
if (n <= 1) {
return n;
}
// This causes repeated calculations for the same numbers, leading to high CPU
return fibonacci(n - 1) + fibonacci(n - 2);
}
}
මේ fibonacci(int n) method එක n කියන අගය 40 වගේ වෙනකොට recursive calls ගොඩක් ඇති කරනවා. මේක ඉතාමත් කාර්යක්ෂම නොවන (inefficient) algorithm එකක් නිසා CPU එකට විශාල බරක් (load) දෙනවා.
පියවර 2: Spring Boot Application එක Run කරමු
දැන් මේ Spring Boot application එක run කරන්න. සාමාන්යයෙන් IDE එකකින් (IntelliJ IDEA, Eclipse) හෝ Maven/Gradle command එකකින් run කරන්න පුළුවන්:
mvn spring-boot:runApplication එක port 8080 එකේ run වෙනවා ඇති.
පියවර 3: VisualVM Open කර Application එකට Connect වෙමු
- මුලින්ම
jvisualvmcommand එක run කරලා VisualVM open කරගන්න. (JDK_HOME/binfolder එකේ මේක තියෙනවා.) - VisualVM window එකේ වම් පැත්තේ "Local" කියන එක යටතේ ඔබගේ running Spring Boot application එක (උදා:
CpuIntensiveApplicationවගේ නමකින්) පෙනෙයි. ඒක click කරන්න. - දැන් ඔබට application එකේ CPU, Memory, Threads වගේ දේවල් Overview, Monitor tabs වලින් බලාගන්න පුළුවන්.
පියවර 4: CPU Profiling පටන් ගමු
- application එක select කරලා, "Sampler" tab එකට යන්න.
- "CPU" radio button එක select කරලා, "Start" button එක click කරන්න.
- දැන් browser එක open කරලා,
http://localhost:8080/calculate-fibonacci?n=40කියන URL එකට requests කිහිපයක් යවන්න. (තවත් හොඳයි, මේ request එකට server එකට අඛණ්ඩව requests යවන load testing tool එකක් (උදා: JMeter, k6, Postman Runner) වගේ දෙයක් භාවිතා කලොත්.)
ඔබ requests යවනකොට, VisualVM එකේ CPU usage එක ඉහළ යනවා පෙනෙයි. "Sampler" tab එකේ ඔබට CPU එක වැඩිපුරම භාවිතා කරන methods මොනවද කියලා percent ගණන් වලින් දැකගන්න පුළුවන්. ඔබට පෙනෙයි CpuIntensiveController.fibonacci කියන method එක තමයි වැඩිම CPU time එකක් භාවිතා කරන්නේ කියලා. මේක තමයි අපේ bottleneck එක.
මේ වගේම, "Threads" tab එකට ගියොත්, ඔබට දැනට run වෙන threads වල state එක බලාගන්න පුළුවන්. RUNNABLE state එකේ තියෙන threads වල stack traces බලලා, ඒ threads මොන method එකකද වැඩිපුර කාලයක් ගත කරන්නේ කියලා හඳුනාගන්න පුළුවන්.
පියවර 5: Bottleneck එක විසඳමු
අපි දැන් bottleneck එක හඳුනාගත්තා. fibonacci method එක කාර්යක්ෂම නොවීම තමයි ගැටලුව. මේක විසඳන්න විවිධ ක්රම තියෙනවා. අපි Memoization (Dynamic Programming) භාවිතා කරලා මේක optimize කරමු:
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@RestController
public class OptimizedCpuIntensiveController { // Changed class name for clarity
private final Map<Integer, Long> memo = new HashMap<>(); // To store calculated values
@GetMapping("/calculate-fibonacci-optimized")
public String calculateFibonacciOptimized(@RequestParam(defaultValue = "40") int n) {
long startTime = System.nanoTime();
long result = fibonacciOptimized(n);
long endTime = System.nanoTime();
long duration = (endTime - startTime) / 1_000_000; // milliseconds
System.out.println("Optimized Fibonacci of " + n + " calculated in " + duration + " ms.");
return "Optimized Fibonacci of " + n + " is " + result + " (calculated in " + duration + " ms)";
}
// An optimized Fibonacci function using memoization
private long fibonacciOptimized(int n) {
if (n <= 1) {
return n;
}
if (memo.containsKey(n)) {
return memo.get(n);
}
long result = fibonacciOptimized(n - 1) + fibonacciOptimized(n - 2);
memo.put(n, result); // Store the result
return result;
}
}
මේ optimized code එකෙන්, fibonacciOptimized method එකෙන් දැනටමත් calculate කරපු Fibonacci numbers memo Map එකේ store කරනවා. ඒ නිසා එකම number එක නැවත නැවත calculate කිරීමක් සිදුවෙන්නේ නැහැ. මේක Dynamic Programming වල පොදු ක්රමවේදයක්. දැන් application එක නැවත run කරලා, VisualVM එකෙන් profile කරලා බලන්න. කලින් වගේ High CPU usage එකක් නොපෙන්වන බව ඔබට දැකගන්න පුළුවන්.
4. විසඳුම් සහ Best Practices
High CPU usage ගැටලු විසඳීමට සහ ඒවා වළක්වා ගැනීමට භාවිතා කළ හැකි පොදු විසඳුම් සහ best practices කිහිපයක් මෙන්න:
4.1. Code Optimization
- Algorithm Improvement: වඩාත් කාර්යක්ෂම Algorithms භාවිතා කරන්න (අපේ Fibonacci example එකේ වගේ). data structures නිවැරදිව තෝරාගන්න.
- Reduce Object Creation: Loops ඇතුළත අනවශ්ය විදිහට objects නිර්මාණය කිරීමෙන් වළකින්න. මේක garbage collection එකට විශාල බරක් දෙනවා.
- Lazy Loading: අවශ්ය වන විට පමණක් objects හෝ data load කරන්න.
4.2. Thread Management
- ExecutorService භාවිතය: Threads manually manage කරනවාට වඩා,
java.util.concurrent.ExecutorServiceවගේ thread pool එකක් භාවිතා කරන්න. මේකෙන් threads efficiently manage කරන්න පුළුවන්. - Avoid Over-synchronization:
synchronizedblocks හෝ methods අනවශ්ය විදිහට භාවිතා කිරීමෙන් වළකින්න. මේවා concurrency එක අඩු කරලා, threads block වෙන්න පුළුවන්. - Non-Blocking I/O: Database calls, external API calls වගේ I/O operations වලදී Non-Blocking I/O (NIO) හෝ Asynchronous programming techniques භාවිතා කරන්න. Spring WebFlux වගේ frameworks මේකට උදව් වෙනවා.
4.3. Database Optimization
- Efficient Queries: N+1 query problem වගේ දේවල් වලකින්න. Queries optimize කරන්න.
- Indexing: Database tables වලට නිවැරදිව Indexes එකතු කරන්න.
- Caching: නිතරම භාවිතා කරන දත්ත Caching (උදා: Spring Cache with Redis or Ehcache) මගින් cache කරන්න. මේක database hits අඩු කරලා application performance එක වැඩි කරනවා.
4.4. Garbage Collection Tuning
- JVM එකේ Garbage Collector (GC) එක tuning කිරීමෙන් memory management එක improve කරන්න පුළුවන්.
-Xmx(maximum heap size),-Xms(initial heap size), සහ-XX:+UseG1GC(G1 Garbage Collector භාවිතා කිරීමට) වගේ JVM arguments භාවිතා කරන්න. - VisualVM වගේ profilers වලින් GC activity එක monitor කරන්න පුළුවන්.
4.5. Asynchronous Processing
- යම්කිසි task එකක් user request එකට direct respond කරන්න අවශ්ය නැත්නම්, ඒක Asynchronously execute කරන්න. Spring Framework එකේ
@Asyncannotation එක මේකට භාවිතා කරන්න පුළුවන්. - මේ වගේ tasks වෙනම thread එකක execute වෙන නිසා main request thread එක block වෙන්නේ නැහැ.
@Service
public class MyAsyncTaskService {
@Async
public CompletableFuture<String> doLongRunningTask() {
// Simulate a long-running operation
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return CompletableFuture.completedFuture("Task Completed!");
}
}
4.6. Resource Management
- Database connection pools (HikariCP), HTTP connection pools (Apache HttpClient) වගේ දේවල් නිවැරදිව configure කරලා භාවිතා කරන්න. මේවා resource utilization එක optimize කරනවා.
නිගමනය
Spring Boot application එකක High CPU usage එකක් කියන්නේ performance එකට සහ user experience එකට සෘජුවම බලපාන බැරෑරුම් ගැටලුවක්. නමුත්, System Monitoring Tools, Application Metrics, සහ විශේෂයෙන්ම Profilers වගේ දේවල් නිවැරදිව භාවිතා කරලා මේ ගැටලුව හඳුනාගෙන, එයට effective විසඳුම් ලබාදෙන්න පුළුවන්.
අපගේ Fibonacci example එකෙන් අපි දැක්කා කොහොමද VisualVM එකෙන් bottleneck එකක් identify කරලා, code optimization මගින් ඒක විසඳගන්නේ කියලා. මේ වගේම, Code Optimization, Efficient Thread Management, Database Optimization, GC Tuning, Asynchronous Processing වගේ best practices භාවිතා කිරීමෙන් ඔබට ඔබගේ Spring Boot applications වල කාර්යක්ෂමතාවය ඉහළ නංවා ගන්න පුළුවන්.
මතක තියාගන්න, performance tuning කියන්නේ එකපාරක් කරලා ඉවර කරන වැඩක් නෙවෙයි. නිතරම ඔබගේ application එක monitor කරන්න, profile කරන්න, සහ අවශ්ය පරිදි optimize කරන්න. මේ tutorial එකෙන් ඔබට මේ ගමනට හොඳ අඩිතාලමක් ලැබුණා කියලා මම විශ්වාස කරනවා.
ඔබ මේ ගැන අත්දැකීම් කොහොමද? ඔබ භාවිතා කරන profiling tools මොනවද? පහළ comment section එකේ ඔබගේ අදහස් සහ අත්දැකීම් බෙදාගන්න. ඔබගේ ඊළඟ project එකේදී මේ concepts implement කරලා බලන්න!