{"action":"created","comment":{"url":"https://api.github.com/repos/akka/akka-meta/pulls/comments/29526287","id":29526287,"diff_hunk":"@@ -0,0 +1,203 @@\n+# Orleans and Akka Actors: A Comparison\n+\n+## Step-By-Step Review\n+\n+This overview walks along the Technical Report [MSR-TR-2014-41](http://research.microsoft.com/apps/pubs/default.aspx?id=210931) by *Philip A. Bernstein, Sergey Bykov, Allan Geller, Cabriel Kliot, Jorgen Thelin (Microsoft Research)*, for another comparison focusing on Erlang and Riak see [Christopher Meiklejohn’s excellent article](http://christophermeiklejohn.com/orleans.html).\n+\n+### Introduction\n+\n+Different focus:\n+\n+  * Akka as a toolkit for building distributed systems, offering the full power but also exposing the inherent essential complexity.\n+  \n+  * Orleans restricts applicability in order to allow seamless use without understanding distributed computing.\n+  \n+#### Lifecycle\n+\n+  * Orleans Grains do not have a lifecycle, can neither be started nor stopped. Consequently they also cannot fail and be restarted, therefore Orleans does not offer tools for software failure handling—the failure handling aspects concentrate on recovering from hardware crashes.\n+  \n+  * Akka Actors implement the full model including defined lifecycle beginning and end, these are explicit operations. Persistent Actors support extending the lifecycle of a logical unit of computation beyond the lifecycle of the running process instance. Restarting an Actor provides powerful means for automatic service recovery.\n+  \n+#### Automatic Creation\n+\n+  * Orleans Grains are created automatically whenever needed, which implies that initialization activities cannot have persistent effects—otherwise these would be uncontrollable. OTOH this frees the user from having to consider the need for Grain creation. It also means that asking for a Grain you don’t know which implementation you will get.\n+  \n+  * Akka actors are explicitly created by their parent, implementing mandatory parental supervision. This allows precise control over when initialization actions are performed and which exact actor class is being created.\n+  \n+#### Virtual Actor Space\n+\n+  * In Orleans each type of Grain corresponds to a practically infinite space of Grain instances that conceptually all exist from the beginning of the universe to its end. The relation to the physical Actors that implement the Grains is explained similar to virtual and physical memory, but this comparison is misleading since the virtual address space of a process is explicitly populated with the desired contents instead of containing the whole system’s information by default.\n+  \n+  * Akka’s explicit lifecycle management requires that all currently running Actors must have been explicitly started in the past and will have to be explicitly stopped in the future. Higher-level abstractions like ClusterSharding provide the ability to opt into an Orleans-like model where instances can be addressed by their logical name instead of a concrete ActorRef, but the API for accessing them is provided by other Actors that perform the necessary lookups and initialization on behalf of the user.\n+\n+#### Automatic Actor Placement and Load Balancing\n+\n+  * Orleans Grains are deployed on silos that can span multiple cluster nodes and the user has no influence on their precise placement or load-dependent movement. This means that making use of elastically provisioned resources is fully automatic and built into the model.\n+  \n+  * Elastic deployment and load balancing are features that Akka users opt into by using ClusterSharding or cluster-aware routers with remote deployment. Otherwise Actors are created explicitly on a given node (this can be influenced using the configuration file in order to allow deployment decisions to be taken by the operations personnel and not the programmer).\n+  \n+### Programming Model\n+\n+#### Virtual Actors\n+\n+  * Orleans Grains are identified by their nominal type and a 128-bit GUID.\n+  \n+  * Akka Actors are identified by their ActorRef, which consists of the ActorPath (including physical network location and the names of all its ancestors) and its UID (a 32-bit integer that disambiguates different incarnations on the same ActorPath).\n+\n+Actors as well as Grains do not share memory with their peers, both only communicate via message-passing.\n+\n+##### Perpetual Existence\n+\n+discussed above\n+\n+##### Automatic Instantiation\n+\n+  * An Orleans Grain may at any given time have one or more activations (active instances) depending on deployment mode. This implies that stateful Grains will have to consider that there may be copies running outside of their control that are responsible for the same piece of data or functionality if automatic scale-out is enabled (see below).\n+  \n+  * An Akka ActorRef refers to an Actor that must have been previously instantiated (otherwise there would not be an ActorRef but only an ActorPath available) and that may have already terminated. There will never be two Actors running with the same ActorRef. When using ClusterSharding there can be exactly zero or one instances currently running for each logical Actor name at any given point in time (unless the user explicitly configures the cluster to tolerate operation under split-brain scenarios).\n+\n+see also above\n+\n+##### Location Transparency\n+\n+  * An Orleans Grain does not have knowledge of its physical location which can also transparently change during the runtime of the system. Users of a Grain’s function do not need to know the location of the Grain activation they are talking to. If my understanding is right then Grain handles can also be sent as part of messages.\n+  \n+  * In Akka the central abstraction for Location Transparency is the ActorRef: it is a self-contained serializable representation of an Actor location that enables other Actors to send messages to it. ActorRefs can also be sent as part of messages to introduce Actors to one another.\n+  \n+##### Automatic Scale-Out\n+\n+  * Orleans Grains can be configured as *stateless worker* which allows multiple activations to be active at any given time. The runtime manages the scaling factor in response to the workload.\n+  \n+  * In Akka cluster-aware routers offer the same functionality as the stateless worker mode of Orleans with the difference that here the provided abstraction exposes available resources to the program as the cluster grows but Akka itself does not contain the logic or ability to spin up additional nodes in response to increased load. This is left to other tools that manage server fleets.\n+  \n+#### Actor Interfaces\n+\n+  * The API provided by Orleans uses code generation in order to present Actor interactions exactly like normal method invocations—with the only difference that all methods are required to return their result asynchronously. Composition of results is performed using the async–await language features of C# and friends.\n+  \n+  * Akka distinguishes Actor interactions from normal method invocations by requiring the use of the ActorRef’s `!` or `tell` methods in order to send messages. These method return no result value, receiving a reply from the Actor entails providing an ActorRef where the response is sent to.\n+\n+In this area the differences between Akka and Orleans are very pronounced and mirror the different intent stated up-front: while Orleans aims for convenience and uses syntax that is familiar to OOP practitioners, Akka makes messaging very explicit and requires the user to define message classes. There is one instance of providing a similar model as async–await, namely the interaction between a PersistentActor and its Journal using the `persist` and `persistAsync` methods, but this API leads to a stronger coupling of the two components than would otherwise be the case. For a PersistentActor this is intended since it cannot function without the Journal, but for Grain interactions users now have to choose between blocking the grain in an `await` call (in a logical sense, but still!) or permitting other invocations to be processed concurrently “during” the `await` call—which leads to much of the same race conditions and problems that shared-state concurrency has. In Akka the interaction of multiple Actors is clearly demarcated by sending messages, and if and Actor ignores all incoming requests until a certain reply has been received then that is an explicit choice that the programmer makes.","path":"ComparisonWithOrleans.md","position":79,"original_position":79,"commit_id":"245ea5eeb53172756740ce7b959d6b6a63ad68b5","original_commit_id":"245ea5eeb53172756740ce7b959d6b6a63ad68b5","user":{"login":"gabikliot","id":10171207,"avatar_url":"https://avatars.githubusercontent.com/u/10171207?v=3","gravatar_id":"","url":"https://api.github.com/users/gabikliot","html_url":"https://github.com/gabikliot","followers_url":"https://api.github.com/users/gabikliot/followers","following_url":"https://api.github.com/users/gabikliot/following{/other_user}","gists_url":"https://api.github.com/users/gabikliot/gists{/gist_id}","starred_url":"https://api.github.com/users/gabikliot/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gabikliot/subscriptions","organizations_url":"https://api.github.com/users/gabikliot/orgs","repos_url":"https://api.github.com/users/gabikliot/repos","events_url":"https://api.github.com/users/gabikliot/events{/privacy}","received_events_url":"https://api.github.com/users/gabikliot/received_events","type":"User","site_admin":false},"body":"Vertical vs. horizontal error propagation is a great analogy!\r\n\r\nAnother reason we believe in horizontal is that you handle the error in the scope of the request, so you know the request details, you know better how to recover. \r\nAlso, a question: does  it mean in Akka that if the actor throws an exception it automatically dies (let it crash) and the supervisor needs to re-create? It means that if the actor serves multiple clients, and it has thrown due to one client request, you are now effectively \"punishing\" other clients as well, since the actor is dead for all of them now (they mean to re-lookup in the supervisor for the new actor that was re-created, their in memory state may have been lost, ...)\r\n","created_at":"2015-05-01T19:17:18Z","updated_at":"2015-05-01T19:17:18Z","html_url":"https://github.com/akka/akka-meta/pull/8#discussion_r29526287","pull_request_url":"https://api.github.com/repos/akka/akka-meta/pulls/8","_links":{"self":{"href":"https://api.github.com/repos/akka/akka-meta/pulls/comments/29526287"},"html":{"href":"https://github.com/akka/akka-meta/pull/8#discussion_r29526287"},"pull_request":{"href":"https://api.github.com/repos/akka/akka-meta/pulls/8"}}},"pull_request":{"url":"https://api.github.com/repos/akka/akka-meta/pulls/8","id":34488606,"html_url":"https://github.com/akka/akka-meta/pull/8","diff_url":"https://github.com/akka/akka-meta/pull/8.diff","patch_url":"https://github.com/akka/akka-meta/pull/8.patch","issue_url":"https://api.github.com/repos/akka/akka-meta/issues/8","number":8,"state":"open","locked":false,"title":"add comparison with Orleans","user":{"login":"rkuhn","id":470469,"avatar_url":"https://avatars.githubusercontent.com/u/470469?v=3","gravatar_id":"","url":"https://api.github.com/users/rkuhn","html_url":"https://github.com/rkuhn","followers_url":"https://api.github.com/users/rkuhn/followers","following_url":"https://api.github.com/users/rkuhn/following{/other_user}","gists_url":"https://api.github.com/users/rkuhn/gists{/gist_id}","starred_url":"https://api.github.com/users/rkuhn/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rkuhn/subscriptions","organizations_url":"https://api.github.com/users/rkuhn/orgs","repos_url":"https://api.github.com/users/rkuhn/repos","events_url":"https://api.github.com/users/rkuhn/events{/privacy}","received_events_url":"https://api.github.com/users/rkuhn/received_events","type":"User","site_admin":false},"body":"","created_at":"2015-04-30T18:40:46Z","updated_at":"2015-05-01T19:17:18Z","closed_at":null,"merged_at":null,"merge_commit_sha":"7308e6e59a78592e2f3d862ea3c5d403ee6916e4","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/akka/akka-meta/pulls/8/commits","review_comments_url":"https://api.github.com/repos/akka/akka-meta/pulls/8/comments","review_comment_url":"https://api.github.com/repos/akka/akka-meta/pulls/comments{/number}","comments_url":"https://api.github.com/repos/akka/akka-meta/issues/8/comments","statuses_url":"https://api.github.com/repos/akka/akka-meta/statuses/245ea5eeb53172756740ce7b959d6b6a63ad68b5","head":{"label":"akka:wip-Orleans","ref":"wip-Orleans","sha":"245ea5eeb53172756740ce7b959d6b6a63ad68b5","user":{"login":"akka","id":1496237,"avatar_url":"https://avatars.githubusercontent.com/u/1496237?v=3","gravatar_id":"","url":"https://api.github.com/users/akka","html_url":"https://github.com/akka","followers_url":"https://api.github.com/users/akka/followers","following_url":"https://api.github.com/users/akka/following{/other_user}","gists_url":"https://api.github.com/users/akka/gists{/gist_id}","starred_url":"https://api.github.com/users/akka/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/akka/subscriptions","organizations_url":"https://api.github.com/users/akka/orgs","repos_url":"https://api.github.com/users/akka/repos","events_url":"https://api.github.com/users/akka/events{/privacy}","received_events_url":"https://api.github.com/users/akka/received_events","type":"Organization","site_admin":false},"repo":{"id":33617252,"name":"akka-meta","full_name":"akka/akka-meta","owner":{"login":"akka","id":1496237,"avatar_url":"https://avatars.githubusercontent.com/u/1496237?v=3","gravatar_id":"","url":"https://api.github.com/users/akka","html_url":"https://github.com/akka","followers_url":"https://api.github.com/users/akka/followers","following_url":"https://api.github.com/users/akka/following{/other_user}","gists_url":"https://api.github.com/users/akka/gists{/gist_id}","starred_url":"https://api.github.com/users/akka/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/akka/subscriptions","organizations_url":"https://api.github.com/users/akka/orgs","repos_url":"https://api.github.com/users/akka/repos","events_url":"https://api.github.com/users/akka/events{/privacy}","received_events_url":"https://api.github.com/users/akka/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/akka/akka-meta","description":"This repository is dedicated to high-level feature discussions and for persisting design decisions.","fork":false,"url":"https://api.github.com/repos/akka/akka-meta","forks_url":"https://api.github.com/repos/akka/akka-meta/forks","keys_url":"https://api.github.com/repos/akka/akka-meta/keys{/key_id}","collaborators_url":"https://api.github.com/repos/akka/akka-meta/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/akka/akka-meta/teams","hooks_url":"https://api.github.com/repos/akka/akka-meta/hooks","issue_events_url":"https://api.github.com/repos/akka/akka-meta/issues/events{/number}","events_url":"https://api.github.com/repos/akka/akka-meta/events","assignees_url":"https://api.github.com/repos/akka/akka-meta/assignees{/user}","branches_url":"https://api.github.com/repos/akka/akka-meta/branches{/branch}","tags_url":"https://api.github.com/repos/akka/akka-meta/tags","blobs_url":"https://api.github.com/repos/akka/akka-meta/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/akka/akka-meta/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/akka/akka-meta/git/refs{/sha}","trees_url":"https://api.github.com/repos/akka/akka-meta/git/trees{/sha}","statuses_url":"https://api.github.com/repos/akka/akka-meta/statuses/{sha}","languages_url":"https://api.github.com/repos/akka/akka-meta/languages","stargazers_url":"https://api.github.com/repos/akka/akka-meta/stargazers","contributors_url":"https://api.github.com/repos/akka/akka-meta/contributors","subscribers_url":"https://api.github.com/repos/akka/akka-meta/subscribers","subscription_url":"https://api.github.com/repos/akka/akka-meta/subscription","commits_url":"https://api.github.com/repos/akka/akka-meta/commits{/sha}","git_commits_url":"https://api.github.com/repos/akka/akka-meta/git/commits{/sha}","comments_url":"https://api.github.com/repos/akka/akka-meta/comments{/number}","issue_comment_url":"https://api.github.com/repos/akka/akka-meta/issues/comments{/number}","contents_url":"https://api.github.com/repos/akka/akka-meta/contents/{+path}","compare_url":"https://api.github.com/repos/akka/akka-meta/compare/{base}...{head}","merges_url":"https://api.github.com/repos/akka/akka-meta/merges","archive_url":"https://api.github.com/repos/akka/akka-meta/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/akka/akka-meta/downloads","issues_url":"https://api.github.com/repos/akka/akka-meta/issues{/number}","pulls_url":"https://api.github.com/repos/akka/akka-meta/pulls{/number}","milestones_url":"https://api.github.com/repos/akka/akka-meta/milestones{/number}","notifications_url":"https://api.github.com/repos/akka/akka-meta/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/akka/akka-meta/labels{/name}","releases_url":"https://api.github.com/repos/akka/akka-meta/releases{/id}","created_at":"2015-04-08T16:01:42Z","updated_at":"2015-04-30T22:11:12Z","pushed_at":"2015-04-30T18:40:46Z","git_url":"git://github.com/akka/akka-meta.git","ssh_url":"git@github.com:akka/akka-meta.git","clone_url":"https://github.com/akka/akka-meta.git","svn_url":"https://github.com/akka/akka-meta","homepage":null,"size":172,"stargazers_count":7,"watchers_count":7,"language":null,"has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":4,"forks":1,"open_issues":4,"watchers":7,"default_branch":"master"}},"base":{"label":"akka:master","ref":"master","sha":"4b68a9e518f78fb3d881295ce72ce14b2414ad62","user":{"login":"akka","id":1496237,"avatar_url":"https://avatars.githubusercontent.com/u/1496237?v=3","gravatar_id":"","url":"https://api.github.com/users/akka","html_url":"https://github.com/akka","followers_url":"https://api.github.com/users/akka/followers","following_url":"https://api.github.com/users/akka/following{/other_user}","gists_url":"https://api.github.com/users/akka/gists{/gist_id}","starred_url":"https://api.github.com/users/akka/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/akka/subscriptions","organizations_url":"https://api.github.com/users/akka/orgs","repos_url":"https://api.github.com/users/akka/repos","events_url":"https://api.github.com/users/akka/events{/privacy}","received_events_url":"https://api.github.com/users/akka/received_events","type":"Organization","site_admin":false},"repo":{"id":33617252,"name":"akka-meta","full_name":"akka/akka-meta","owner":{"login":"akka","id":1496237,"avatar_url":"https://avatars.githubusercontent.com/u/1496237?v=3","gravatar_id":"","url":"https://api.github.com/users/akka","html_url":"https://github.com/akka","followers_url":"https://api.github.com/users/akka/followers","following_url":"https://api.github.com/users/akka/following{/other_user}","gists_url":"https://api.github.com/users/akka/gists{/gist_id}","starred_url":"https://api.github.com/users/akka/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/akka/subscriptions","organizations_url":"https://api.github.com/users/akka/orgs","repos_url":"https://api.github.com/users/akka/repos","events_url":"https://api.github.com/users/akka/events{/privacy}","received_events_url":"https://api.github.com/users/akka/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/akka/akka-meta","description":"This repository is dedicated to high-level feature discussions and for persisting design decisions.","fork":false,"url":"https://api.github.com/repos/akka/akka-meta","forks_url":"https://api.github.com/repos/akka/akka-meta/forks","keys_url":"https://api.github.com/repos/akka/akka-meta/keys{/key_id}","collaborators_url":"https://api.github.com/repos/akka/akka-meta/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/akka/akka-meta/teams","hooks_url":"https://api.github.com/repos/akka/akka-meta/hooks","issue_events_url":"https://api.github.com/repos/akka/akka-meta/issues/events{/number}","events_url":"https://api.github.com/repos/akka/akka-meta/events","assignees_url":"https://api.github.com/repos/akka/akka-meta/assignees{/user}","branches_url":"https://api.github.com/repos/akka/akka-meta/branches{/branch}","tags_url":"https://api.github.com/repos/akka/akka-meta/tags","blobs_url":"https://api.github.com/repos/akka/akka-meta/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/akka/akka-meta/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/akka/akka-meta/git/refs{/sha}","trees_url":"https://api.github.com/repos/akka/akka-meta/git/trees{/sha}","statuses_url":"https://api.github.com/repos/akka/akka-meta/statuses/{sha}","languages_url":"https://api.github.com/repos/akka/akka-meta/languages","stargazers_url":"https://api.github.com/repos/akka/akka-meta/stargazers","contributors_url":"https://api.github.com/repos/akka/akka-meta/contributors","subscribers_url":"https://api.github.com/repos/akka/akka-meta/subscribers","subscription_url":"https://api.github.com/repos/akka/akka-meta/subscription","commits_url":"https://api.github.com/repos/akka/akka-meta/commits{/sha}","git_commits_url":"https://api.github.com/repos/akka/akka-meta/git/commits{/sha}","comments_url":"https://api.github.com/repos/akka/akka-meta/comments{/number}","issue_comment_url":"https://api.github.com/repos/akka/akka-meta/issues/comments{/number}","contents_url":"https://api.github.com/repos/akka/akka-meta/contents/{+path}","compare_url":"https://api.github.com/repos/akka/akka-meta/compare/{base}...{head}","merges_url":"https://api.github.com/repos/akka/akka-meta/merges","archive_url":"https://api.github.com/repos/akka/akka-meta/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/akka/akka-meta/downloads","issues_url":"https://api.github.com/repos/akka/akka-meta/issues{/number}","pulls_url":"https://api.github.com/repos/akka/akka-meta/pulls{/number}","milestones_url":"https://api.github.com/repos/akka/akka-meta/milestones{/number}","notifications_url":"https://api.github.com/repos/akka/akka-meta/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/akka/akka-meta/labels{/name}","releases_url":"https://api.github.com/repos/akka/akka-meta/releases{/id}","created_at":"2015-04-08T16:01:42Z","updated_at":"2015-04-30T22:11:12Z","pushed_at":"2015-04-30T18:40:46Z","git_url":"git://github.com/akka/akka-meta.git","ssh_url":"git@github.com:akka/akka-meta.git","clone_url":"https://github.com/akka/akka-meta.git","svn_url":"https://github.com/akka/akka-meta","homepage":null,"size":172,"stargazers_count":7,"watchers_count":7,"language":null,"has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":4,"forks":1,"open_issues":4,"watchers":7,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/akka/akka-meta/pulls/8"},"html":{"href":"https://github.com/akka/akka-meta/pull/8"},"issue":{"href":"https://api.github.com/repos/akka/akka-meta/issues/8"},"comments":{"href":"https://api.github.com/repos/akka/akka-meta/issues/8/comments"},"review_comments":{"href":"https://api.github.com/repos/akka/akka-meta/pulls/8/comments"},"review_comment":{"href":"https://api.github.com/repos/akka/akka-meta/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/akka/akka-meta/pulls/8/commits"},"statuses":{"href":"https://api.github.com/repos/akka/akka-meta/statuses/245ea5eeb53172756740ce7b959d6b6a63ad68b5"}}}}