title: Calculating the number of primes in a range RMI version vs concurrent version
body: <p>I have two versions of a program with the same purpose: to calculate how many prime numbers there are between 0 and n. </p>
  
  <p>The first version uses concurrency, a Callable class "does the math" and the results are retrieved though a <code>Future</code> array. There are as many created threads as processors in my computer (4).</p>
  
  <p>The second version is implemented via RMI. All four servers are registered in the local host. The servers are working in paralell as well, obviously.</p>
  
  <p>I would expect the second version to be slower than the first, because I guess the network would involve latency and the other version would just run the program concurrently.</p>
  
  <p>However, the RMI version is around twice faster than the paralel version... Why is this happening?!</p>
  
  <p>I didn't paste any code because it'd be huge, but ask for it in case you need it and I'll see what I can do...</p>
  
  <p><strong>EDIT:</strong> adding the code. I commented the sections where unnecessary code was to be posted.</p>
  
  <p><strong>Paralell version</strong></p>
  
  <pre><code>public class taskPrimes implements Callable
  {
    private final long x;
    private final long y;
    private Long total = new Long(0);
  
    public taskPrimes(long x, long y)
    {
      this.x = x;
      this.y = y;
    }
  
    public static boolean isPrime(long n)
    {
      if (n&lt;=1) return false ;
      for (long i=2; i&lt;=Math.sqrt(n); i++)
        if (n%i == 0) return false;
      return true;
    } 
  
    public Long call()
    {   
      for (long i=linf; i&lt;=lsup;i++)
        if (isPrime(i)) total++;
    return total;
    }
  }
  
  public class paralelPrimes 
  {
    public static void main(String[] args) throws Exception 
    {
      // here some variables...
      int nTasks = Runtime.getRuntime().availableProcessors();
  
      ArrayList&lt;Future&lt;Long&gt;&gt; partial = new ArrayList&lt;Future&lt;Long&gt;&gt;(); 
      ThreadPoolExecutor ept = new ThreadPoolExecutor();
      for(int i=0; i&lt;nTasks; i++)
      {
        partial.add(ept.submit(new taskPrimes(x, y))); // x and y are the limits of the range
        // sliding window here
      }  
      for(Future&lt;Long&gt; iterator:partial)
        try { total +=  iterator.get(); } catch (Exception e) {}
    }   
  }
  </code></pre>
  
  <p><strong>RMI version</strong></p>
  
  <p><strong>Server</strong></p>
  
  <pre><code>public class serverPrimes 
      extends UnicastRemoteObject 
          implements interfacePrimes
  {
      public serverPrimes() throws RemoteException {}
  
      @Override
      public int primes(int x, int y) throws RemoteException
      {
          int total = 0;
          for(int i=x; i&lt;=y; i++)
              if(isPrime(i)) total++;
          return total;
      }
  
      @Override
      public boolean isPrime(int n) throws RemoteException
      {
          if (n&lt;=1) return false;
          for (int i=2; i&lt;=Math.sqrt(n); i++)
              if (n%i == 0) return false ;
          return true;
      }
  
      public static void main(String[] args) throws Exception 
      {
          interfacePrimes RemoteObject1 = new serverPrimes();
          interfacePrimes RemoteObject2 = new serverPrimes();
          interfacePrimes RemoteObject3 = new serverPrimes();
          interfacePrimes RemoteObject4 = new serverPrimes();
  
          Naming.bind("Server1", RemoteObject1);
          Naming.bind("Server2", RemoteObject2);
          Naming.bind("Server3", RemoteObject3);
          Naming.bind("Server4", RemoteObject4);
      }
  }
  </code></pre>
  
  <p><strong>Client</strong></p>
  
  <pre><code>public class clientPrimes implements Runnable
  {
      private int x;
      private int y;
      private interfacePrimes RemoteObjectReference;
      private static AtomicInteger total = new AtomicInteger();
  
      public clientPrimes(int x, int y, interfacePrimes RemoteObjectReference)
      {
          this.x = x;
          this.y = y;
          this.RemoteObjectReference = RemoteObjectReference;
      }
  
      @Override
      public void run()
      {
          try
          {
              total.addAndGet(RemoteObjectReference.primes(x, y));
          }
          catch (RemoteException e) {}
      }
  
      public static void main(String[] args) throws Exception
      {
          // some variables here...
          int nServers = 4;
          ExecutorService e = Executors.newFixedThreadPool(nServers);
  
          double t = System.nanoTime();
          for (int i=1; i&lt;=nServers; i++)
          {
              e.submit(new clientPrimes(xVentana, yVentana, (interfacePrimes)Naming.lookup("//localhost/Server"+i)));
              // sliding window here
          }
          e.shutdown();
          while(!e.isTerminated());
          t = System.nanoTime()-t;
      }
  }
  </code></pre>