title: Array sum ForkJoin implementation slower than the serial implementation
body: <p>So I am trying to understand how Java ForkJoin framework works. The simplest thing I could think of implementing was an array sum. However my parallel implementation is 3-4 times slower than the serial implementation. I must obviously be doing something wrong, but I am not sure what.</p>
  <p>To measure the performance, I created a set of classes and interfaces (I used Lombok annotations for generating boilerplate code).</p>
  <pre class="lang-java prettyprint-override"><code>interface Result&lt;T&gt; {
      T getValue();
  }
  
  @AllArgsConstructor(staticName = &quot;of&quot;)
  @Value
  class MeasuredResult&lt;T&gt; implements Result&lt;T&gt; {
      T value;
      long elapsedTimeMillis;
  }
  
  @AllArgsConstructor(staticName = &quot;of&quot;)
  class CombinedResult&lt;T&gt; implements Result&lt;T&gt; {
      private final MeasuredResult&lt;T&gt; parallelResult;
      private final MeasuredResult&lt;T&gt; serialResult;
  
      public double getParallelizationFactor() {
          return (double) serialResult.getElapsedTimeMillis() / parallelResult.getElapsedTimeMillis();
      }
  
      public T getParallelValue() {
          return parallelResult.getValue();
      }
  
      public T getSerialValue() {
          return parallelResult.getValue();
      }
  
      @Override
      public T getValue() {
          return getSerialValue();
      }
  
      public boolean isDifferent() {
          return !isSame();
      }
  
      public boolean isSame() {
          return parallelResult.getValue().equals(serialResult.getValue());
      }
  }
  
  interface Parallelizable&lt;T&gt; {
      T processParallelly();
  
      T processSerially();
  
      default CombinedResult&lt;T&gt; getResult() {
          MeasuredResult&lt;T&gt; parallelResult = measureParallel();
          MeasuredResult&lt;T&gt; serialResult = measureSerial();
  
          return CombinedResult.of(parallelResult, serialResult);
      }
  
      default MeasuredResult&lt;T&gt; measure(Supplier&lt;T&gt; supplier) {
          long startTime = System.currentTimeMillis();
          T value = supplier.get();
          long endTime = System.currentTimeMillis();
  
          return MeasuredResult.of(value, endTime - startTime);
      }
  
      default MeasuredResult&lt;T&gt; measureParallel() {
          return measure(this::processParallelly);
      }
  
      default MeasuredResult&lt;T&gt; measureSerial() {
          return measure(this::processSerially);
      }
  }
  </code></pre>
  <p>The idea was that by implementing the <code>Parallelizable</code> interface, I'd define the serial and parallel versions of the code and use the <code>getResult()</code> function to get a <code>CombinedResult</code> object with the values and time measurement to unit test with. Here's my implementation of the array sum.</p>
  <pre class="lang-java prettyprint-override"><code>@AllArgsConstructor
  public class ArraySum implements Parallelizable&lt;Integer&gt; {
      private final int[] nums;
  
      @Override
      public Integer processParallelly() {
          return new ParallelForkJoinImpl(0, nums.length).compute();
      }
  
      @Override
      public Integer processSerially() {
          int sum = 0;
          for (int num : nums) {
              sum += num;
          }
          return sum;
      }
  
      @AllArgsConstructor()
      private class ParallelForkJoinImpl extends RecursiveTask&lt;Integer&gt; {
          private static final int THRESHOLD = 1_000;
  
          private final int start;
          private final int end;
  
          @Override
          protected Integer compute() {
              if (end - start &lt;= THRESHOLD) {
                  int sum = 0;
                  for (int i = start; i &lt; end; i++) {
                      sum += nums[i];
                  }
                  return sum;
              }
              int mid = (start + end) / 2;
              ForkJoinTask&lt;Integer&gt; left = new ParallelForkJoinImpl(start, mid).fork();
              ForkJoinTask&lt;Integer&gt; right = new ParallelForkJoinImpl(mid, end).fork();
  
              return left.join() + right.join();
          }
      }
  }
  </code></pre>
  <p>From what I understand, calling <code>fork()</code> on the <code>RecursiveTask</code> implementation should give me a <code>Future</code> object as response which will block on computation when the <code>join()</code> function is called on it. Also use the common <code>ForkJoinPool</code> will automatically be used when <code>fork()</code> is called.</p>
  <p>But like I said, the value for <code>elapsedTimeMillis</code> for the parallel implementation is 3-4 times larger than the serial implementation, and I don't know why. What did I do wrong here?</p>