From 225face055bc266c570ed07ef6604e10b17de0ea Mon Sep 17 00:00:00 2001 From: Jason Lu Date: Thu, 1 May 2025 01:40:28 +0800 Subject: [PATCH] add compare code for python. see run time diff with python --- src/main/java/jvm/Calculation.java | 68 ++++++++++++ src/main/java/jvm/Calculation2.java | 166 ++++++++++++++++++++++++++++ src/main/java/jvm/SpeedTest.java | 36 ++++++ 3 files changed, 270 insertions(+) create mode 100644 src/main/java/jvm/Calculation.java create mode 100644 src/main/java/jvm/Calculation2.java create mode 100644 src/main/java/jvm/SpeedTest.java diff --git a/src/main/java/jvm/Calculation.java b/src/main/java/jvm/Calculation.java new file mode 100644 index 0000000..16cd446 --- /dev/null +++ b/src/main/java/jvm/Calculation.java @@ -0,0 +1,68 @@ +package jvm; +import java.lang.System; // Import System for nanoTime and printf + +/** + * A Java class to replicate the calculation performed by the Python script. + */ +public class Calculation { + + /** + * Performs the iterative calculation. + * + * @param iterations The number of iterations for the loop. + * @param param1 The first parameter used in the calculation. + * @param param2 The second parameter used in the calculation. + * @return The result of the calculation. + */ + public static double calculate(int iterations, int param1, int param2) { + // Initialize the result as a double + double result = 1.0; + + // Loop from 1 to iterations (inclusive) + for (int i = 1; i <= iterations; i++) { + // Calculate the first value of j + // Use double for j to ensure floating-point arithmetic + double jMinus = (double)i * param1 - param2; + // Subtract 1.0 / jMinus from the result (use 1.0 for double division) + result -= (1.0 / jMinus); + + // Calculate the second value of j + double jPlus = (double)i * param1 + param2; + // Add 1.0 / jPlus to the result + result += (1.0 / jPlus); + } + // Return the final calculated result + return result; + } + + /** + * The main entry point of the program. + * + * @param args Command line arguments (not used). + */ + public static void main(String[] args) { + // Define the parameters for the calculation + final int ITERATIONS = 100_000_000; // Use underscore for readability (Java 7+) + final int PARAM1 = 4; + final int PARAM2 = 1; + + // Record the start time using System.nanoTime() for higher precision + long startTime = System.nanoTime(); + + // Perform the calculation and multiply the result by 4.0 + double finalResult = calculate(ITERATIONS, PARAM1, PARAM2) * 4.0; + + // Record the end time + long endTime = System.nanoTime(); + + // Calculate the duration in nanoseconds + long durationNanos = endTime - startTime; + // Convert the duration to seconds (as a double) + double durationSeconds = durationNanos / 1_000_000_000.0; + + // Print the final result, formatted to 12 decimal places + System.out.printf("Result: %.12f%n", finalResult); + // Print the execution time, formatted to 6 decimal places + System.out.printf("Execution Time: %.6f seconds%n", durationSeconds); + } +} diff --git a/src/main/java/jvm/Calculation2.java b/src/main/java/jvm/Calculation2.java new file mode 100644 index 0000000..845db7e --- /dev/null +++ b/src/main/java/jvm/Calculation2.java @@ -0,0 +1,166 @@ +package jvm; +import java.lang.System; // Import System for nanoTime and printf +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +/** + * A Java class to replicate the calculation performed by the Python script, + * optimized using multithreading. + */ +public class Calculation2 { + + /** + * Represents a task that calculates a partial sum for a given range of iterations. + * Implements Callable so it can be executed by an ExecutorService and return a result. + */ + private static class PartialCalculator implements Callable { + private final int startIteration; + private final int endIteration; + private final int param1; + private final int param2; + + /** + * Constructor for the partial calculator task. + * @param startIteration The starting iteration (inclusive). + * @param endIteration The ending iteration (exclusive). + * @param param1 The first parameter for calculation. + * @param param2 The second parameter for calculation. + */ + public PartialCalculator(int startIteration, int endIteration, int param1, int param2) { + this.startIteration = startIteration; + this.endIteration = endIteration; + this.param1 = param1; + this.param2 = param2; + } + + /** + * The computation performed by this task. Calculates the sum for the assigned range. + * @return The partial sum for the range. + */ + @Override + public Double call() { + double partialSum = 0.0; + // Loop through the assigned range of iterations + // Note: loop goes up to < endIteration + for (int i = startIteration; i < endIteration; i++) { + // Calculate the first value of j + double jMinus = (double)i * param1 - param2; + // Subtract 1.0 / jMinus from the partial sum + partialSum -= (1.0 / jMinus); + + // Calculate the second value of j + double jPlus = (double)i * param1 + param2; + // Add 1.0 / jPlus to the partial sum + partialSum += (1.0 / jPlus); + } + return partialSum; + } + } + + /** + * Performs the iterative calculation using multiple threads. + * + * @param iterations The total number of iterations for the loop. + * @param param1 The first parameter used in the calculation. + * @param param2 The second parameter used in the calculation. + * @param numThreads The number of threads to use for the calculation. + * @return The result of the calculation. + * @throws InterruptedException If thread execution is interrupted. + * @throws ExecutionException If computation threw an exception. + */ + public static double calculateParallel(int iterations, int param1, int param2, int numThreads) + throws InterruptedException, ExecutionException { + + // Create a fixed-size thread pool + ExecutorService executor = Executors.newFixedThreadPool(numThreads); + // List to hold the Future objects representing the results of each task + List> futureResults = new ArrayList<>(); + + // Calculate the approximate number of iterations per thread + int iterationsPerThread = iterations / numThreads; + int start = 1; // Start iteration from 1 + + // Divide the work and submit tasks to the executor + for (int i = 0; i < numThreads; i++) { + int end = start + iterationsPerThread; + // For the last thread, ensure it covers all remaining iterations + if (i == numThreads - 1) { + end = iterations + 1; // Go up to iterations (inclusive) + } + // Ensure end doesn't exceed the total iterations + 1 boundary + if (end > iterations + 1) { + end = iterations + 1; + } + + // Create and submit the task for the calculated range + // The loop inside PartialCalculator runs from start (inclusive) to end (exclusive) + Callable task = new PartialCalculator(start, end, param1, param2); + futureResults.add(executor.submit(task)); + + // Set the start for the next chunk + start = end; + } + + // Initialize the total result (starting from the base 1.0) + double totalResult = 1.0; + // Retrieve results from each Future and add to the total result + for (Future future : futureResults) { + // future.get() blocks until the result is available + totalResult += future.get(); + } + + // Shut down the executor service gracefully + executor.shutdown(); + + // Return the final combined result + return totalResult; + } + + /** + * The main entry point of the program. + * + * @param args Command line arguments (not used). + */ + public static void main(String[] args) { + // Define the parameters for the calculation + final int ITERATIONS = 100_000_000; + final int PARAM1 = 4; + final int PARAM2 = 1; + // Determine the number of threads based on available processors + final int NUM_THREADS = Runtime.getRuntime().availableProcessors(); + + System.out.println("Using " + NUM_THREADS + " threads."); + + // Record the start time + long startTime = System.nanoTime(); + + double finalResult = 0; + try { + // Perform the parallel calculation and multiply the result by 4.0 + finalResult = calculateParallel(ITERATIONS, PARAM1, PARAM2, NUM_THREADS) * 4.0; + + // Record the end time + long endTime = System.nanoTime(); + + // Calculate the duration + long durationNanos = endTime - startTime; + double durationSeconds = durationNanos / 1_000_000_000.0; + + // Print the final result and execution time + System.out.printf("Result: %.12f%n", finalResult); + System.out.printf("Execution Time: %.6f seconds%n", durationSeconds); + + } catch (InterruptedException | ExecutionException e) { + // Handle potential exceptions during parallel execution + System.err.println("Calculation failed: " + e.getMessage()); + e.printStackTrace(); + // Ensure System.exit is not used in production code without careful consideration + // System.exit(1); + } + } +} diff --git a/src/main/java/jvm/SpeedTest.java b/src/main/java/jvm/SpeedTest.java new file mode 100644 index 0000000..7edf248 --- /dev/null +++ b/src/main/java/jvm/SpeedTest.java @@ -0,0 +1,36 @@ +package jvm; + +/** + * it converts from python code + * just check performance differences between python and java + */ +public class SpeedTest { + + public double calculate(int iter, int param1, int param2) { + double result = 1.0; + + for (int i = 1; i <= iter; i++) { + double jMinus = (double)i * param1 - param2; + // Subtract 1.0 / jMinus from the result (use 1.0 for double division) + result -= (1.0 / jMinus); + + // Calculate the second value of j + double jPlus = (double)i * param1 + param2; + // Add 1.0 / jPlus to the result + result += (1.0 / jPlus); + } + + return result; + } + + public static void main(String[] args) { + SpeedTest speedTest = new SpeedTest(); + long start = System.nanoTime(); + double result = speedTest.calculate(100_000_000, 4, 1) * 4.0; + System.out.println(result); + long end = System.nanoTime(); + long durationNanos = end - start; + double durationSeconds = durationNanos / 1_000_000_000.0; + System.out.println( durationSeconds ); + } +}