Over a million developers have joined DZone.

True Art of Functional Cloud Recursion With GridGain 3.0

· Cloud Zone

Build fast, scale big with MongoDB Atlas, a hosted service for the leading NoSQL database on AWS. Try it now! Brought to you in partnership with MongoDB.

As I mentioned in my previous blog, GridGain 3.0 practically changed the way we think about cloud programming. GridGain has always been simple and natural to use, but after the last 2.1 release this just was not enough anymore. We kept thinking on how to make our product even more natural and more powerful. Well, the addition of Data Grid component in GridGain 3.0 definitely helped, but I think the biggest and most powerful change for us was a significant paradigm shift towards Functional Programming (FP) with rich and powerful APIs. The functional approach for APIs just fits so naturally, I am surprised we have not thought about it before (well... reading books on Scala definitely helped :). In GridGain 3.0 the API's got rich, and the code got terse.

Take a look for example at how you can *recursively* calculate Fibonacci sequence for number 10 in GridGain 3.0 (this is not the most effective implementation, but bare with me for now):

   1. final Grid g = G.start(); // Start grid.  
3. int fib = g.call(UNICAST, new GridClosureX<Integer, Integer>() {
4. @Override public Integer applyx(Integer n) throws GridException {
5. return n == 0 ? 0 : n <= 2 ? 1 :
6. g.call(UNICAST, this, n - 1) + g.call(UNICAST, this, n - 2);
7. }
8. }, 10);

Things to notice in the above coding snippet:
  1. GridClosureX is just a function which will be executed on the remote grid or cloud (suffix 'X' means that it throws GridException).
  2. There is no deployment step - GridGain auto-deploys your code on participating nodes on-demand (pretty cool).
  3. We are reusing the same grid variable "g" in local and remote code (even cooler, but it gets better).
  4. Note how we are re-executing the same closure from remote nodes *recursively* by passing "this" into "g.call(..)" method!!!
I hope you are already intrigued, but the above example, as pretty as it is, is not very useful or effective. Nodes may recursively calculate Fibonacci for the same number more than once throughout the same execution. Also, the method returns an integer which is not very practical as Fibonacci numbers grow very large very quickly.

Let's get a little fancier and introduce caching of calculated Fibonacci numbers on remote nodes. Also let's switch to using BigInteger so we can handle really large numbers:

   1. BigInteger fib = g.call(UNICAST, new GridClosureX<Long, BigInteger>() {  
2. @Override public BigInteger applyx(Long n) throws GridException {
3. System.out.println("Starting fibonacci execution for number: " + n);
5. // Make sure n is not negative.
6. n = Math.abs(n);
8. if (n == 0) {
9. return BigInteger.ZERO;
10. }
12. if (n <= 2) {
13. return BigInteger.ONE;
14. }
16. // Node-local storage is provided by Grid.nodeLocal() method.
17. GridNodeLocal<Long, BigInteger> nodeLocal = g.nodeLocal();
19. // Check if value is cached in node-local store first.
20. BigInteger n1 = nodeLocal.get(n - 1);
22. // If value is not cached in node-local store, then
23. // compute it and cache it.
24. if (n1 == null) {
25. // Nested recursive distributed execution on the grid.
26. nodeLocal.putIfAbsent(n - 1, n1 = g.call(UNICAST, this, n - 1, p));
27. }
29. // Check if value is cached in node-local store first.
30. BigInteger n2 = nodeLocal.get(n - 2);
32. // If value is not cached in node-local store, then
33. // compute it and cache it.
34. if (n2 == null) {
35. // Nested recursive distributed execution on the grid.
36. nodeLocal.putIfAbsent(n - 2, n2 = g.call(UNICAST, this, n - 2, p));
37. }
39. return n1.add(n2);
40. }
41. }, 100);

This code snippet is pretty similar to the first one, except that it caches already calculated values directly on remote nodes, so it gets smarter as it progresses. If you run it twice for the same value, no recursion will happen the second time at all, and you will get result immediately from node-local store. All we need to do now is just startup a few grid nodes and give it a go. The result for Fibonacci(100) is '354224848179261915075' by the way.

Now I want you to stop for a second and think about what we have been able to achieve just in a few lines of code above.

This example, along with many others, is shipped with GridGain. I invite you to download it and see it for yourself.

Now it's easier than ever to get started with MongoDB, the database that allows startups and enterprises alike to rapidly build planet-scale apps. Introducing MongoDB Atlas, the official hosted service for the database on AWS. Try it now! Brought to you in partnership with MongoDB.


Published at DZone with permission of Dmitriy Setrakyan, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}