University of Illinois at Urbana-Champaign, [email protected] of Illinois at Urbana-Champaign, [email protected] \CopyrightDan Plyukhin and Gul Agha {CCSXML} <ccs2012> <concept> <concept_id>10010147.10011777.10011778</concept_id> <concept_desc>Computing methodologies Concurrent algorithms</concept_desc> <concept_significance>500</concept_significance> </concept> <concept> <concept_id>10011007.10010940.10010941.10010949.10010950.10010954</concept_id> <concept_desc>Software and its engineering Garbage collection</concept_desc> <concept_significance>500</concept_significance> </concept> </ccs2012> \ccsdesc[500]Computing methodologies Concurrent algorithms \ccsdesc[500]Software and its engineering Garbage collection \supplement\fundingThis work was supported in part by the National Science Foundation under Grant No. SHF 1617401, and in part by the Laboratory Directed Research and Development program at Sandia National Laboratories, a multi-mission laboratory managed and operated by National Technology and Engineering Solutions of Sandia, LLC, a wholly owned subsidiary of Honeywell International, Inc., for the U.S. Department of Energy’s National Nuclear Security Administration under contract DE-NA0003525.
Acknowledgements.
We would like to thank Dipayan Mukherjee, Atul Sandur, Charles Kuch, Jerry Wu, and the anonymous referees for providing valuable feedback in earlier versions of this work. \EventEditorsIgor Konnov and Laura Kovács \EventNoEds2 \EventLongTitle31st International Conference on Concurrency Theory (CONCUR 2020) \EventShortTitleCONCUR 2020 \EventAcronymCONCUR \EventYear2020 \EventDateSeptember 1–4, 2020 \EventLocationVienna, Austria \EventLogo \SeriesVolume2017 \ArticleNo44Scalable Termination Detection for Distributed Actor Systems
Abstract
Automatic garbage collection (GC) prevents certain kinds of bugs and reduces programming overhead. GC techniques for sequential programs are based on reachability analysis. However, testing reachability from a root set is inadequate for determining whether an actor is garbage because an unreachable actor may send a message to a reachable actor. Instead, it is sufficient to check termination (sometimes also called quiescence): an actor is terminated if it is not currently processing a message and cannot receive a message in the future. Moreover, many actor frameworks provide all actors with access to file I/O or external storage; without inspecting an actor’s internal code, it is necessary to check that the actor has terminated to ensure that it may be garbage collected in these frameworks. Previous algorithms to detect actor garbage require coordination mechanisms such as causal message delivery or nonlocal monitoring of actors for mutation. Such coordination mechanisms adversely affect concurrency and are therefore expensive in distributed systems. We present a low-overhead reference listing technique (called DRL) for termination detection in actor systems. DRL is based on asynchronous local snapshots and message-passing between actors. This enables a decentralized implementation and transient network partition tolerance. The paper provides a formal description of DRL, shows that all actors identified as garbage have indeed terminated (safety), and that all terminated actors–under certain reasonable assumptions–will eventually be identified (liveness).
keywords:
actors, concurrency, termination detection, quiescence detection, garbage collection, distributed systemscategory:
\relatedversion1 Introduction
The actor model [1, 2] is a foundational model of concurrency that has been widely adopted for its scalability: for example, actor languages have been used to implement services at PayPal [19], Discord [27], and in the United Kingdom’s National Health Service database [18]. In the actor model, stateful processes known as actors execute concurrently and communicate by sending asynchronous messages to other actors, provided they have a reference (also called a mail address or address in the literature) to the recipient. Actors can also spawn new actors. An actor is said to be garbage if it can be destroyed without affecting the system’s observable behavior.
Although a number of algorithms for automatic actor GC have been proposed [10, 13, 24, 25, 28, 30], actor languages and frameworks currently popular in industry (such as Akka [4], Erlang [5], and Orleans [8]) require that programmers garbage collect actors manually. We believe this is because the algorithms proposed thus far are too expensive to implement in distributed systems. In order to find applicability in real-world actor runtimes, we argue that a GC algorithm should satisfy the following properties:
-
1.
(Low latency) GC should not restrict concurrency in the application.
-
2.
(High throughput) GC should not impose significant space or message overhead.
-
3.
(Scalability) GC should scale with the number of actors and nodes in the system.
To the best of our knowledge, no previous algorithm satisfies all three constraints. The first requirement precludes any global synchronization between actors, a “stop-the-world” step, or a requirement for causal order delivery of all messages. The second requirement means that the number of additional “control” messages imposed by the algorithm should be minimal. The third requirement precludes algorithms based on global snapshots, since taking a global snapshot of a system with a large number of nodes is infeasible.
To address these goals, we have developed a garbage collection technique called DRL for Deferred Reference Listing. The primary advantage of DRL is that it is decentralized and incremental: local garbage can be collected at one node without communicating with other nodes. Garbage collection can be performed concurrently with the application and imposes no message ordering constraints. We also expect DRL to be reasonably efficient in practice, since it does not require many additional messages or significant actor-local computation.
DRL works as follows. The communication protocol (Section 4) tracks information, such as references and message counts, and stores it in each actor’s state. Actors periodically send out copies of their local state (called snapshots) to be stored at one or more designated snapshot aggregator actors. Each aggregator periodically searches its local store to find a subset of snapshots representing terminated actors (Section 6). Once an actor is determined to have terminated, it can be garbage collected by, for example, sending it a self-destruct message. Note that our termination detection algorithm itself is location transparent.
Since DRL is defined on top of the actor model, it is oblivious to details of a particular implementation (such as how sequential computations are represented). Our technique is therefore applicable to any actor framework and can be implemented as a library. Moreover, it can also be applied to open systems, allowing a garbage-collected actor subsystem to interoperate with an external actor system.
The outline of the paper is as follows. We provide a characterization of actor garbage in Section 2 and discuss related work in Section 3. We then provide a specification of the DRL protocol in Section 4. In Section 5, we describe a key property of DRL called the Chain Lemma. This lemma allows us to prove the safety and liveness properties, which are stated in Section 6. We then conclude in Section 7 with some discussion of future work and how DRL may be used in practice. To conserve space, all proofs have been relegated to the Appendix.
2 Preliminaries
An actor can only receive a message when it is idle. Upon receiving a message, it becomes busy. A busy actor can perform an unbounded sequence of actions before becoming idle. In [3], an action may be to spawn an actor, send a message, or perform a (local) computation. We will also assume that actors can perform effects, such as file I/O. The actions an actor performs in response to a message are dictated by its application-level code, called a behavior.
Actors can also receive messages from external actors (such as the user) by becoming receptionists. An actor becomes a receptionist when its address is exposed to an external actor. Subsequently, any external actor can potentially obtain ’s address and send it a message. It is not possible for an actor system to determine when all external actors have “forgotten” a receptionist’s address. We will therefore assume that an actor can never cease to be a receptionist once its address has been exposed.
An actor is said to be garbage if it can be destroyed without affecting the system’s observable behavior. However, without analyzing an actor’s code, it is not possible to know whether it will have an effect when it receives a message. We will therefore restrict our attention to actors that can be guaranteed to be garbage without inspecting their behavior. According to this more conservative definition, any actor that might receive a message in the future should not be garbage collected because it could, for instance, write to a log file when it becomes busy. Conversely, any actor that is guaranteed to remain idle indefinitely can safely be garbage collected because it will never have any effects; such an actor is said to be terminated. Hence, garbage actors coincide with terminated actors in our model.
Terminated actors can be detected by looking at the global state of the system. We say that an actor is a potential acquaintance of (and is a potential inverse acquaintance of ) if has a reference to or if there is an undelivered message to that contains a reference to . We define potential reachability to be the reflexive transitive closure of the potential acquaintance relation. If an actor is idle and has no undelivered messages, then it is blocked; otherwise it is unblocked. We then observe that an actor is terminated when it is only potentially reachable by blocked actors: Such an actor is idle, blocked, and can only potentially be sent a message by other idle blocked actors. Conversely, without analyzing actor code we cannot safely conclude that an actor is terminated if it is potentially reachable by an unblocked actor. Hence, we say that an actor is terminated if and only if it is blocked and all of its potential inverse acquaintances are terminated.
3 Related Work
Global Termination
Global termination detection (GTD) is used to determine when all processes have terminated [17, 16]. For GTD, it suffices to obtain global message send and receive counts. Most GTD algorithms also assume a fixed process topology. However, Lai gives an algorithm in [14] that supports dynamic topologies such as in the actor model. Lai’s algorithm performs termination detection in “waves”, disseminating control messages along a spanning tree (such as an actor supervisor hierarchy) so as to obtain consistent global message send and receive counts. Venkatasubramanian et al. take a similar approach to obtain a consistent global snapshot of actor states in a distributed system [25]. However, such an approach does not scale well because it is not incremental: garbage cannot be detected until all nodes in the system have responded. In contrast, DRL does not require a global snapshot, does not require actors to coordinate their local snapshots, and does not require waiting for all nodes before detecting local terminated actors.
Reference Tracking
We say that an idle actor is simple garbage if it has no undelivered messages and no other actor has a reference to it. Such actors can be detected with distributed reference counting [31, 6, 20] or with reference listing [21, 30] techniques. In reference listing algorithms, each actor maintains a partial list of actors that may have references to it. Whenever sends a reference to , it also sends an message informing about ’s reference. Once no longer needs a reference to , it informs by sending a message; this message should not be processed by until all preceding messages from to have been delivered. Thus an actor is simple garbage when its reference listing is empty.
Our technique uses a form of deferred reference listing, in which may also defer sending messages to until it releases its references to . This allows and messages to be batched together, reducing communication overhead.
Cyclic Garbage
Actors that are transitively acquainted with one another are said to form cycles. Cycles of terminated actors are called cyclic garbage and cannot be detected with reference listing alone. Since actors are hosted on nodes and cycles may span across multiple nodes, detecting cyclic garbage requires sharing information between nodes to obtain a consistent view of the global topology. One approach is to compute a global snapshot of the distributed system [13] using the Chandy-Lamport algorithm [9]; but this requires pausing execution of all actors on a node to compute its local snapshot.
Another approach is to add edges to the actor reference graph so that actor garbage coincides with passive object garbage [24, 29]. This is convenient because it allows existing algorithms for distributed passive object GC, such as [23], to be reused in actor systems. However, such transformations require that actors know when they have undelivered messages, which requires some form of synchronization.
To avoid pausing executions, Wang and Varela proposed a reference listing based technique called the pseudo-root algorithm. The algorithm computes approximate global snapshots and is implemented in the SALSA runtime [30, 28]. The pseudo-root algorithm requires a high number of additional control messages and requires actors to write to shared memory if they migrate or release references during snapshot collection. Our protocol requires fewer control messages and no additional actions between local actor snapshots. Wang and Varela also explicitly address migration of actors, a concern orthogonal to our algorithm.
Our technique is inspired by MAC, a termination detection algorithm implemented in the Pony runtime [10]. In MAC, actors send a local snapshot to a designated cycle detector whenever their message queue becomes empty, and send another notification whenever it becomes non-empty. Clebsch and Drossopoulou prove that for systems with causal message delivery, a simple request-reply protocol is sufficient to confirm that the cycle detector’s view of the topology is consistent. However, enforcing causal delivery in a distributed system imposes additional space and networking costs [11, 7]. DRL is similar to MAC, but does not require causal message delivery, supports decentralized termination detection, and actors need not take snapshots each time their message queues become empty. The key insight is that these limitations can be removed by tracking additional information at the actor level.
An earlier version of DRL appeared in [22]. In this paper, we formalize the description of the algorithm and prove its safety and liveness. In the process, we discovered that release acknowledgment messages are unnecessary and that termination detection is more flexible than we first thought: it is not necessary for GC to be performed in distinct “phases” where every actor takes a snapshot in each phase. In particular, once an idle actor takes a snapshot, it need not take another snapshot until it receives a fresh message.
4 A Two-Level Semantic Model
Our computation model is based on the two level approach to actor semantics [26], in which a lower system-level transition system interprets the operations performed by a higher, user-facing application-level transition system. In this section, we define the DRL communication protocol at the system level. We do not provide a transition system for the application level computation model, since it is not relevant to garbage collection (see [3] for how it can be done). What is relevant to us is that corresponding to each application-level action is a system-level transition that tracks references. We will therefore define system-level configurations and transitions on system-level configurations. We will refer to these, respectively, as configurations and transitions in the rest of the paper.
4.1 Overview
Actors in DRL use reference objects (abbreviated refobs) to send messages, instead of using plain actor addresses. Refobs are similar to unidirectional channels and can only be used by their designated owner to send messages to their target; thus in order for to give a reference to , it must explicitly create a new refob owned by . Once a refob is no longer needed, it should be deactivated by its owner and removed from local state.
The DRL communication protocol enriches each actor’s state with a list of refobs that it currently owns and associated message counts representing the number of messages sent using each refob. Each actor also maintains a subset of the refobs of which it is the target, together with associated message receive counts. Lastly, actors perform a form of “contact tracing” by maintaining a subset of the refobs that they have created for other actors; we provide details about the bookkeeping later in this section.
The additional information above allows us to detect termination by inspecting actor snapshots. If a set of snapshots is consistent (in the sense of [9]) then we can use the “contact tracing” information to determine whether the set is closed under the potential inverse acquaintance relation (see Section 5). Then, given a consistent and closed set of snapshots, we can use the message counts to determine whether an actor is blocked. We can therefore find all the terminated actors within a consistent set of snapshots.
In fact, DRL satisfies a stronger property: any set of snapshots that “appears terminated” in the sense above is guaranteed to be consistent. Hence, given an arbitrary closed set of snapshots, it is possible to determine which of the corresponding actors have terminated. This allows a great deal of freedom in how snapshots are aggregated. For instance, actors could place their snapshots in a global eventually consistent store, with a garbage collection thread at each node periodically inspecting the store for local terminated actors.
Reference Objects
A refob is a triple , where is the owner actor’s address, is the target actor’s address, and is a globally unique token. An actor can cheaply generate such a token by combining its address with a local sequence number, since actor systems already guarantee that each address is unique. We will stylize a triple as . We will also sometimes refer to such a refob as simply , since tokens act as unique identifiers.
When an actor spawns an actor (Fig. 2 (1, 2)) the DRL protocol creates a new refob that is stored in both and ’s system-level state, and a refob in ’s state. The refob allows to send application-level messages to . These messages are denoted , where is the sett of refobs contained in the message that has created for . The refob corresponds to the self variable present in some actor languages.
If has active refobs and , then it can create a new refob by generating a token . In addition to being sent to , this refob must also temporarily be stored in ’s system-level state and marked as “created using ” (Fig. 2 (3)). Once receives , it must add the refob to its system-level state and mark it as “active” (Fig. 2 (4)). Note that can have multiple distinct refobs that reference the same actor in its state; this can be the result of, for example, several actors concurrently sending refobs to . Transition rules for spawning actors and sending messages are given in Section 4.3.
Actor may remove from its state once it has sent a (system-level) message informing about (Fig. 2 (4)). Similarly, when no longer needs its refob for , it can “deactivate” by removing it from local state and sending a (system-level) message (Fig. 2 (5)). Note that if already has a refob and then receives another , then it can be more efficient to defer deactivating the extraneous until is also no longer needed; this way, the messages can be batched together.
When receives an message, it records that the refob has been created, and when receives a message, it records that the refob has been released (Fig. 2 (6)). Note that these messages may arrive in any order. Once has received both, it is permitted to remove all facts about the refob from its local state. Transition rules for these reference listing actions are given in Section 4.4.
Once a refob has been created, it cycles through four states: pending, active, inactive, or released. A refob is said to be pending until it is received by its owner . Once received, the refob is active until it is deactivated by its owner, at which point it becomes inactive. Finally, once learns that has been deactivated, the refob is said to be released. A refob that has not yet been released is unreleased.
Slightly amending the definition we gave in Section 2, we say that is a potential acquaintance of (and is a potential inverse acquaintance of ) when there exists an unreleased refob . Thus, becomes a potential acquaintance of as soon as is created, and only ceases to be an acquaintance once it has received a message for every refob that has been created so far.
Message Counts and Snapshots
For each refob , the owner counts the number of and messages sent along ; this count can be deleted when deactivates . Each message is annotated with the refob used to send it. Whenever receives an or message along , it correspondingly increments a receive count for ; this count can be deleted once has been released. Thus the memory overhead of message counts is linear in the number of unreleased refobs.
A snapshot is a copy of all the facts in an actor’s system-level state at some point in time. We will assume throughout the paper that in every set of snapshots , each snapshot was taken by a different actor. Such a set is also said to form a cut. Recall that a cut is consistent if no snapshot in the cut causally precedes any other [9]. Let us also say that is a set of mutually quiescent snapshots if there are no undelivered messages between actors in the cut. That is, if sent a message to before taking a snapshot, then the message must have been delivered before took its snapshot. Notice that if all snapshots in are mutually quiescent, then is consistent.
Notice also that in Fig. 3, the snapshots of and are mutually quiescent when their send and receive counts agree. This is ensured in part because each refob has a unique token: If actors associated message counts with actor names instead of tokens, then ’s snapshots at and would both contain . Thus, ’s snapshot at and ’s snapshot at would appear mutually quiescent, despite having undelivered messages in the cut.
We would like to conclude that snapshots from two actors are mutually quiescent if and only if their send and receive counts are agreed for every refob or . Unfortunately, this fails to hold in general for systems with unordered message delivery. It also fails to hold when, for instance, the owner actor takes a snapshot before the refob is activated and the target actor takes a snapshot after the refob is released. In such a case, neither knowledge set includes a message count for the refob and they therefore appear to agree. However, we show that the message counts can nevertheless be used to bound the number of undelivered messages for purposes of our algorithm (Lemma A.5).
Definitions
We use the capital letters to denote actor addresses. Tokens are denoted , with a special reserved token for messages from external actors.
A fact is a value that takes one of the following forms: , , , , , , or for some refobs and natural number . Each actor’s state holds a set of facts about refobs and message counts called its knowledge set. We use to denote facts and to denote finite sets of facts. Each fact may be interpreted as a predicate that indicates the occurrence of some past event. Interpreting a set of facts as a set of axioms, we write when is derivable by first-order logic from with the following additional rules:
-
•
If then
-
•
If then
-
•
If then
-
•
If then
For convenience, we define a pair of functions for incrementing message send/receive counts, as follows: If for some , then ; otherwise, . Likewise for incRecv and .
Recall that an actor is either busy (processing a message) or idle (waiting for a message). An actor with knowledge set is denoted if it is busy and if it is idle.
Our specification includes both system messages (also called control messages) and application messages. The former are automatically generated by the DRL protocol and handled at the system level, whereas the latter are explicitly created and consumed by user-defined behaviors. Application-level messages are denoted . The argument is the refob used to send the message. The second argument is a set of refobs created by the sender to be used by the destination actor. Any remaining application-specific data in the message is omitted in our notation.
The DRL communication protocol uses two kinds of system messages. is a message sent from an actor to an actor , informing it that a new refob was created using . is a message sent from an actor to an actor , informing it that the refob has been deactivated and should be released.
A configuration is a quadruple where: is a mapping from actor addresses to knowledge sets; is a mapping from actor addresses to multisets of messages; and are sets of actor addresses. Actors in are internal actors and actors in are external actors; the two sets may not intersect. The mapping associates each actor with undelivered messages to that actor. Actors in are receptionists. We will ensure remains valid in any configuration that is derived from a configuration where the property holds (referred to as the locality laws in [12]).
Configurations are denoted by , , , etc. If an actor address (resp. a token ), does not occur in , then the address (resp. the token) is said to be fresh. We assume a facility for generating fresh addresses and tokens.
In order to express our transition rules in a pattern-matching style, we will employ the following shorthand. Let refer to a mapping where and . Similarly, let refer to a mapping where and . Informally, the expression refers to a set of actors containing both and the busy actor (with knowledge set ); the expression refers to the set of messages containing both and the message (sent to actor ).
The rules of our transition system define atomic transitions from one configuration to another. Each transition rule has a label , parameterized by some variables that occur in the left- and right-hand configurations. Given a configuration , these parameters functionally determine the next configuration . Given arguments , we write to denote a semantic step from to using rule .
We refer to a label with arguments as an event, denoted . A sequence of events is denoted . If then we write when . If there exists such that , then is derivable from . An execution is a sequence of events such that , where is the initial configuration (Section 4.2). We say that a property holds at time if it holds in .
4.2 Initial Configuration
The initial configuration consists of a single actor in a busy state:
where . The actor’s knowledge set includes a refob to itself and a refob to an external actor . can become a receptionist by sending a refob to itself. Henceforth, we will only consider configurations that are derivable from an initial configuration.
4.3 Standard Actor Operations
where | fresh |
and |
where | and fresh and |
---|---|
and | and |
and | and |
where |
Fig. 4 gives transition rules for standard actor operations, such as spawning actors and sending messages. Each of these rules corresponds a rule in the standard operational semantics of actors [3]. Note that each rule is atomic, but can just as well be implemented as a sequence of several smaller steps without loss of generality because actors do not share state – see [3] for a formal proof.
The Spawn event allows a busy actor to spawn a new actor and creates two refobs . is initialized with knowledge about and via the facts . The facts allow and to immediately begin sending messages to . Note that implementing Spawn does not require a synchronization protocol between and to construct . The parent can pass both its address and the freshly generated token to the constructor for . Since actors typically know their own addresses, this allows to construct the triple . Since the spawn call typically returns the address of the spawned actor, can also create the same triple.
The Send event allows a busy actor to send an application-level message to containing a set of refobs to actors – it is possible that or for some . For each new refob , we say that the message contains . Any other data in the message besides these refobs is irrelevant to termination detection and therefore omitted. To send the message, must have active refobs to both the target actor and to every actor referenced in the message. For each target , adds a fact to its knowledge set; we say that created using . Finally, must increment its count for the refob used to send the message; we say that the message is sent along .
The Receive event allows an idle actor to become busy by consuming an application message sent to . Before performing subsequent actions, increments the receive count for and adds all refobs in the message to its knowledge set.
Finally, the Idle event puts a busy actor into the idle state, enabling it to consume another message.
4.4 Release Protocol
where |
where |
where | |
---|---|
and |
only if |
where | for some |
---|---|
or | and |
Whenever an actor creates or receives a refob, it adds facts to its knowledge set. To remove these facts when they are no longer needed, actors can perform the release protocol defined in Fig. 5. All of these rules are not present in the standard operational semantics of actors.
The SendInfo event allows a busy actor to inform about a refob that it created using ; we say that the message is sent along and contains . This event allows to remove the fact from its knowledge set. It is crucial that also increments its count for to indicate an undelivered message sent to : it allows the snapshot aggregator to detect when there are undelivered messages, which contain refobs. This message is delivered with the Info event, which adds the fact to ’s knowledge set and correspondingly increments ’s count for .
When an actor no longer needs for sending messages, can deactivate with the SendRelease event; we say that the is sent along . A precondition of this event is that has already sent messages to inform about all the refobs it has created using . In practice, an implementation may defer sending any or messages to a target until all ’s refobs to are deactivated. This introduces a trade-off between the number of control messages and the rate of simple garbage detection (Section 5).
Each message for a refob includes a count of the number of messages sent using . This ensures that is only delivered after all the preceding messages sent along have been delivered. Once the Release event can be executed, it adds the fact that has been released to ’s knowledge set. Once has received both an and message for a refob , it may remove facts about from its knowledge set using the Compaction event.
Finally, the Snapshot event captures an idle actor’s knowledge set. For simplicity, we have omitted the process of disseminating snapshots to an aggregator. Although this event does not change the configuration, it allows us to prove properties about snapshot events at different points in time.
4.5 Composition and Effects
where | and and fresh |
---|---|
and | and |
where and and |
We give rules to dictate how internal actors interact with external actors in Fig. 6. The In and Out rules correspond to similar rules in the standard operational semantics of actors.
Since internal garbage collection protocols are not exposed to the outside world, all and messages sent to external actors are simply dropped by the ReleaseOut and InfoOut events. Likewise, only messages can enter the system. Since we cannot statically determine when a receptionist’s address has been forgotten by all external actors, we assume that receptionists are never terminated. The resulting “black box” behavior of our system is the same as the actor systems in [3]. Hence, in principle DRL can be gradually integrated into a codebase by creating a subsystem for garbage-collected actors.
The In event allows an external actor to send an application-level message to a receptionist containing a set of refobs , all owned by . Since external actors do not use refobs, the message is sent using the special token. All targets in that are not internal actors are added to the set of external actors.
The Out event delivers an application-level message to an external actor with a set of refobs . All internal actors referenced in become receptionists because their addresses have been exposed to the outside world.
4.6 Garbage
We can now operationally characterize actor garbage in our model. An actor can potentially receive a message in if there is a sequence of events (possibly of length zero) leading from to a configuration in which has an undelivered message. We say that an actor is terminated if it is idle and cannot potentially receive a message.
An actor is blocked if it satisfies three conditions: (1) it is idle, (2) it is not a receptionist, and (3) it has no undelivered messages; otherwise, it is unblocked. We define potential reachability as the reflexive transitive closure of the potential acquaintance relation. That is, can potentially reach if and only if there is a sequence of unreleased refobs ; recall that a refob is unreleased if its target has not yet received a message for .
Notice that an actor can potentially receive a message if and only if it is potentially reachable from an unblocked actor. Hence an actor is terminated if and only if it is only potentially reachable by blocked actors. A special case of this is simple garbage, in which an actor is blocked and has no potential inverse acquaintances besides itself.
We say that a set of actors is closed (with respect to the potential inverse acquaintance relation) if, whenever and there is an unreleased refob , then also . Notice that the closure of a set of terminated actors is also a set of terminated actors.
5 Chain Lemma
To determine if an actor has terminated, one must show that all of its potential inverse acquaintances have terminated. This appears to pose a problem for termination detection, since actors cannot have a complete listing of all their potential inverse acquaintances without some synchronization: actors would need to consult their acquaintances before creating new references to them. In this section, we show that the DRL protocol provides a weaker guarantee that will nevertheless prove sufficient: knowledge about an actor’s refobs is distributed across the system and there is always a “path” from the actor to any of its potential inverse acquaintances.
Let us construct a concrete example of such a path, depicted by Fig. 7. Suppose that spawns , gaining a refob . Then may use to create , which may receive and then use to create .
At this point, there are unreleased refobs owned by and that are not included in ’s knowledge set. However, Fig. 7 shows that the distributed knowledge of creates a “path” to all of ’s potential inverse acquaintances. Since spawned , knows the fact . Then when created , it added the fact to its knowledge set, and likewise added the fact ; each fact points to another actor that owns an unreleased refob to (Fig. 7 (1)).
Since actors can remove facts by sending messages, we also consider (Fig. 7 (2)) to be a “path” from to . But notice that, once receives the message, the fact will be added to its knowledge set and so there will be a “direct path” from to . We formalize this intuition with the notion of a chain in a given configuration :
Definition 5.1.
A chain to is a sequence of unreleased refobs such that:
-
•
;
-
•
For all , either or the message is in transit; and
-
•
and .
We say that an actor is in the root set if it is a receptionist or if there is an application message in transit to an external actor with . Since external actors never release refobs, actors in the root set must never terminate.
Lemma 5.2 (Chain Lemma).
Let be an internal actor in . If is not in the root set, then there is a chain to every unreleased refob . Otherwise, there is a chain to some refob where is an external actor.
When is in the root set, not all of its unreleased refobs are guaranteed to have chains. This is because an external actor may send ’s address to other receptionists without sending an message to .
An immediate application of the Chain Lemma is to allow actors to detect when they are simple garbage. If any actor besides owns an unreleased refob to , then must have a fact in its knowledge set where . Hence, if has no such facts, then it must have no nontrivial potential inverse acquaintances. Moreover, since actors can only have undelivered messages along unreleased refobs, also has no undelivered messages from any other actor; it can only have undelivered messages that it sent to itself. This gives us the following result:
Theorem 5.3.
Suppose is idle with knowledge set , such that:
-
•
does not contain any facts of the form where ; and
-
•
for all facts , also for some .
Then is simple garbage.
6 Termination Detection
In order to detect non-simple terminated garbage, actors periodically sends a snapshot of their knowledge set to a snapshot aggregator actor. An aggregator in turn may disseminate snapshots it has to other aggregators. Each aggregator maintains a map data structure, associating an actor’s address to its most recent snapshot; in effect, snapshot aggregators maintain an eventually consistent key-value store with addresses as keys and snapshots as values. At any time, an aggregator can scan its local store to find terminated actors and send them a request to self-destruct.
Given an arbitrary set of snapshots , we characterize the finalized subsets of in this section. We show that the actors that took these finalized snapshots must be terminated. Conversely, the snapshots of any closed set of terminated actors are guaranteed to be finalized. (Recall that the closure of a set of terminated actors is also a terminated set of actors.) Thus, snapshot aggregators can eventually detect all terminated actors by periodically searching their local stores for finalized subsets. Finally, we give an algorithm for obtaining the maximum finalized subset of a set by “pruning away” the snapshots of actors that appear not to have terminated.
Recall that when we speak of a set of snapshots , we assume each snapshot was taken by a different actor. We will write to denote ’s snapshot in ; we will also write if has a snapshot in . We will also write if for some .
Definition 6.1.
A set of snapshots is closed if, whenever and , then also and .
Definition 6.2.
An actor appears blocked if, for every , then and and for some .
Definition 6.3.
A set of snapshots is finalized if it is closed and every actor in appears blocked.
This definition corresponds to our characterization in Section 4.6: An actor is terminated precisely when it is in a closed set of blocked actors.
Theorem 6.4 (Safety).
If is a finalized set of snapshots at time then the actors in are all terminated at .
We say that the final action of a terminated actor is the last non-snapshot event it performs before becoming terminated. Notice that an actor’s final action can only be an Idle, Info, or Release event. Note also that the final action may come strictly before an actor becomes terminated, since a blocked actor may only terminate after all of its potential inverse acquaintances become blocked.
The following lemma allows us to prove that DRL is eventually live. It also shows that an non-finalized set of snapshots must have an unblocked actor.
Lemma 6.5.
Let be a closed set of terminated actors at time . If every actor in took a snapshot sometime after its final action, then the resulting set of snapshots is finalized.
Theorem 6.6 (Liveness).
If every actor eventually takes a snapshot after performing an Idle, Info, or Release event, then every terminated actor is eventually part of a finalized set of snapshots.
Proof 6.7.
If an actor is terminated, then the closure of is a terminated set of actors. Since every actor eventually takes a snapshot after taking its final action, Lemma 6.5 implies that the resulting snapshots of are finalized.
We say that a refob is unreleased in if . Such a refob is said to be relevant when implies and and and for some ; intuitively, this indicates that has no undelivered messages along . Notice that a set is finalized if and only if all unreleased refobs in are relevant.
Observe that if is unreleased and irrelevant in , then cannot be in any finalized subset of . We can therefore employ a simple iterative algorithm to find the maximum finalized subset of : for each irrelevant unreleased refob in , remove the target from . Since this can make another unreleased refob irrelevant, we must repeat this process until a fixed point is reached. In the resulting subset , all unreleased refobs are relevant. Since all actors in are not members of any finalized subset of , it must be that is the maximum finalized subset of .
7 Conclusion and Future Work
We have shown how deferred reference listing and message counts can be used to detect termination in actor systems. The technique is provably safe (Theorem 6.4) and eventually live (Theorem 6.6). An implementation in Akka is presently underway.
We believe that DRL satisfies our three initial goals:
-
1.
Termination detection does not restrict concurrency in the application. Actors do not need to coordinate their snapshots or pause execution during garbage collection.
-
2.
Termination detection does not impose high overhead. The amortized memory overhead of our technique is linear in the number of unreleased refobs. Besides application messages, the only additional control messages required by the DRL communication protocol are and messages. These control messages can be batched together and deferred, at the cost of worse termination detection time.
-
3.
Termination detection scales with the number of nodes in the system. Our algorithm is incremental, decentralized, and does not require synchronization between nodes.
Since it does not matter what order snapshots are collected in, DRL can be used as a “building block” for more sophisticated garbage collection algorithms. One promising direction is to take a generational approach [15], in which long-lived actors take snapshots less frequently than short-lived actors. Different types of actors could also take snapshots at different rates. In another approach, snapshot aggregators could request snapshots instead of waiting to receive them.
In the presence of faults, DRL remains safe but its liveness properties are affected. If an actor crashes and its state cannot be recovered, then none of its refobs can be released and the aggregator will never receive its snapshot. Consequently, all actors potentially reachable from can no longer be garbage collected. However, ’s failure does not affect the garbage collection of actors it cannot reach. In particular, network partitions between nodes will not delay node-local garbage collection.
Choosing an adequate fault-recovery protocol will likely vary depending on the target actor framework. One option is to use checkpointing or event-sourcing to persist GC state; the resulting overhead may be acceptable in applications that do not frequently spawn actors or create refobs. Another option is to monitor actors for failure and infer which refobs are no longer active; this is a subject for future work.
Another issue that can affect liveness is message loss: If any messages along a refob are dropped, then can never be garbage collected because it will always appear unblocked. This is, in fact, the desired behavior if one cannot guarantee that the message will not be delivered at some later point. In practice, this problem might be addressed with watermarking.
References
- [1] Gul Agha. ACTORS - a Model of Concurrent Computation in Distributed Systems. MIT Press Series in Artificial Intelligence. MIT Press, 1990.
- [2] Gul Agha. Concurrent object-oriented programming. Communications of the ACM, 33(9):125–141, September 1990.
- [3] Gul A. Agha, Ian A. Mason, Scott F. Smith, and Carolyn L. Talcott. A foundation for actor computation. Journal of Functional Programming, 7(1):1–72, January 1997. doi:10.1017/S095679689700261X.
- [4] Akka. https://akka.io/.
- [5] Joe Armstrong, Robert Virding, Claes Wikström, and Mike Williams. Concurrent Programming in ERLANG. Prentice Hall, Englewood Cliffs, New Jersey, second edition, 1996.
- [6] Di Bevan. Distributed garbage collection using reference counting. In G. Goos, J. Hartmanis, D. Barstow, W. Brauer, P. Brinch Hansen, D. Gries, D. Luckham, C. Moler, A. Pnueli, G. Seegmüller, J. Stoer, N. Wirth, J. W. Bakker, A. J. Nijman, and P. C. Treleaven, editors, PARLE Parallel Architectures and Languages Europe, volume 259, pages 176–187. Springer Berlin Heidelberg, Berlin, Heidelberg, 1987. doi:10.1007/3-540-17945-3_10.
- [7] Sebastian Blessing, Sylvan Clebsch, and Sophia Drossopoulou. Tree topologies for causal message delivery. In Proceedings of the 7th ACM SIGPLAN International Workshop on Programming Based on Actors, Agents, and Decentralized Control - AGERE 2017, pages 1–10, Vancouver, BC, Canada, 2017. ACM Press. doi:10.1145/3141834.3141835.
- [8] Sergey Bykov, Alan Geller, Gabriel Kliot, James R. Larus, Ravi Pandya, and Jorgen Thelin. Orleans: Cloud computing for everyone. In Proceedings of the 2nd ACM Symposium on Cloud Computing - SOCC ’11, pages 1–14, Cascais, Portugal, 2011. ACM Press. doi:10.1145/2038916.2038932.
- [9] K. Mani Chandy and Leslie Lamport. Distributed snapshots: Determining global states of distributed systems. ACM Transactions on Computer Systems, 3(1):63–75, February 1985. doi:10.1145/214451.214456.
- [10] Sylvan Clebsch and Sophia Drossopoulou. Fully concurrent garbage collection of actors on many-core machines. In Proceedings of the 2013 ACM SIGPLAN International Conference on Object Oriented Programming Systems Languages & Applications - OOPSLA ’13, pages 553–570, Indianapolis, Indiana, USA, 2013. ACM Press. doi:10.1145/2509136.2509557.
- [11] Colin J Fidge. Timestamps in message-passing systems that preserve the partial ordering. Australian Computer Science Communications, 10(1):56–66, February 1988.
- [12] Carl Hewitt and Henry G. Baker. Laws for communicating parallel processes. In Bruce Gilchrist, editor, Information Processing, Proceedings of the 7th IFIP Congress 1977, Toronto, Canada, August 8-12, 1977, pages 987–992. North-Holland, 1977.
- [13] D. Kafura, M. Mukherji, and D.M. Washabaugh. Concurrent and distributed garbage collection of active objects. IEEE Transactions on Parallel and Distributed Systems, 6(4):337–350, April 1995. doi:10.1109/71.372788.
- [14] Ten-Hwang Lai. Termination detection for dynamically distributed systems with non-first-in-first-out communication. Journal of Parallel and Distributed Computing, 3(4):577–599, December 1986. doi:10.1016/0743-7315(86)90015-8.
- [15] Henry Lieberman and Carl Hewitt. A real-time garbage collector based on the lifetimes of objects. Commun. ACM, 26(6):419–429, 1983. doi:10.1145/358141.358147.
- [16] Jeff Matocha and Tracy Camp. A taxonomy of distributed termination detection algorithms. Journal of Systems and Software, 43(3):207–221, November 1998. doi:10.1016/S0164-1212(98)10034-1.
- [17] Friedemann Mattern. Algorithms for distributed termination detection. Distributed Computing, 2(3):161–175, September 1987. doi:10.1007/BF01782776.
- [18] NHS to Deploy Riak for New IT Backbone With Quality of Care Improvements in Sight. https://riak.com/nhs-to-deploy-riak-for-new-it-backbone-with-quality-of-care-improvements-in-sight.html, October 2013.
- [19] PayPal Blows Past 1 Billion Transactions Per Day Using Just 8 VMs With Akka, Scala, Kafka and Akka Streams. https://www.lightbend.com/case-studies/paypal-blows-past-1-billion-transactions-per-day-using-just-8-vms-and-akka-scala-kafka-and-akka-streams.
- [20] José M. Piquer. Indirect Reference Counting: A Distributed Garbage Collection Algorithm. In Emile H. L. Aarts, Jan van Leeuwen, and Martin Rem, editors, Parle ’91 Parallel Architectures and Languages Europe, volume 505, pages 150–165. Springer Berlin Heidelberg, Berlin, Heidelberg, 1991. doi:10.1007/978-3-662-25209-3_11.
- [21] David Plainfossé and Marc Shapiro. A survey of distributed garbage collection techniques. In Memory Management, International Workshop IWMM 95, Kinross, UK, September 27-29, 1995, Proceedings, pages 211–249, 1995. doi:10.1007/3-540-60368-9\\_26.
- [22] Dan Plyukhin and Gul Agha. Concurrent garbage collection in the actor model. In Proceedings of the 8th ACM SIGPLAN International Workshop on Programming Based on Actors, Agents, and Decentralized Control - AGERE 2018, pages 44–53, Boston, MA, USA, 2018. ACM Press. doi:10.1145/3281366.3281368.
- [23] M. Schelvis. Incremental distribution of timestamp packets: A new approach to distributed garbage collection. In Conference Proceedings on Object-Oriented Programming Systems, Languages and Applications - OOPSLA ’89, pages 37–48, New Orleans, Louisiana, United States, 1989. ACM Press. doi:10.1145/74877.74883.
- [24] Abhay Vardhan and Gul Agha. Using passive object garbage collection algorithms for garbage collection of active objects. ACM SIGPLAN Notices, 38(2 supplement):106, February 2003. doi:10.1145/773039.512443.
- [25] Nalini Venkatasubramanian, Gul Agha, and Carolyn Talcott. Scalable distributed garbage collection for systems of active objects. In Yves Bekkers and Jacques Cohen, editors, Memory Management, volume 637, pages 134–147. Springer-Verlag, Berlin/Heidelberg, 1992. doi:10.1007/BFb0017187.
- [26] Nalini Venkatasubramanian and Carolyn Talcott. Reasoning about meta level activities in open distributed systems. In Proceedings of the Fourteenth Annual ACM Symposium on Principles of Distributed Computing - PODC ’95, pages 144–152, Ottowa, Ontario, Canada, 1995. ACM Press. doi:10.1145/224964.224981.
- [27] Stanislav Vishnevskiy. How Discord Scaled Elixir to 5,000,000 Concurrent Users. https://blog.discord.com/scaling-elixir-f9b8e1e7c29b, July 2017.
- [28] Wei-Jen Wang. Conservative snapshot-based actor garbage collection for distributed mobile actor systems. Telecommunication Systems, June 2011. doi:10.1007/s11235-011-9509-1.
- [29] Wei-Jen Wang, Carlos Varela, Fu-Hau Hsu, and Cheng-Hsien Tang. Actor Garbage Collection Using Vertex-Preserving Actor-to-Object Graph Transformations. In David Hutchison, Takeo Kanade, Josef Kittler, Jon M. Kleinberg, Friedemann Mattern, John C. Mitchell, Moni Naor, Oscar Nierstrasz, C. Pandu Rangan, Bernhard Steffen, Madhu Sudan, Demetri Terzopoulos, Doug Tygar, Moshe Y. Vardi, Gerhard Weikum, Paolo Bellavista, Ruay-Shiung Chang, Han-Chieh Chao, Shin-Feng Lin, and Peter M. A. Sloot, editors, Advances in Grid and Pervasive Computing, volume 6104, pages 244–255. Springer Berlin Heidelberg, Berlin, Heidelberg, 2010. doi:10.1007/978-3-642-13067-0_28.
- [30] Wei-Jen Wang and Carlos A. Varela. Distributed Garbage Collection for Mobile Actor Systems: The Pseudo Root Approach. In Yeh-Ching Chung and José E. Moreira, editors, Advances in Grid and Pervasive Computing, volume 3947, pages 360–372. Springer Berlin Heidelberg, Berlin, Heidelberg, 2006. doi:10.1007/11745693_36.
- [31] Paul Watson and Ian Watson. An efficient garbage collection scheme for parallel computer architectures. In G. Goos, J. Hartmanis, D. Barstow, W. Brauer, P. Brinch Hansen, D. Gries, D. Luckham, C. Moler, A. Pnueli, G. Seegmüller, J. Stoer, N. Wirth, J. W. Bakker, A. J. Nijman, and P. C. Treleaven, editors, PARLE Parallel Architectures and Languages Europe, volume 259, pages 432–443. Springer Berlin Heidelberg, Berlin, Heidelberg, 1987. doi:10.1007/3-540-17945-3_25.
Appendix A Appendix
A.1 Basic Properties
Lemma A.1.
If has undelivered messages along , then is an unreleased refob.
Proof A.2.
There are three types of messages: and . All three messages can only be sent when is active. Moreover, the Release rule ensures that they must all be delivered before can be released.
Lemma A.3.
-
•
Once is added to ’s knowledge set, it will not be removed until after has sent an message containing to .
-
•
Once is added to ’s knowledge set, it will not be removed until after has received the (unique) message along .
-
•
Once is added to ’s knowledge set, it will not be removed until after has received the (unique) message containing .
Proof A.4.
Immediate from the transition rules.
Lemma A.5.
Consider a refob . Let be times such that has not yet been deactivated at and has not yet been released at . In particular, and may be before the creation time of .
Suppose that and and, if , that does not send any messages along during the interval . Then the difference is the number of messages sent along before that were not received before .
Proof A.6.
Since is not deactivated at time and unreleased at time , the message counts were never reset by the SendRelease or Compaction rules. Hence is the number of messages sent along before and is the number of messages received along before . Hence is the number of messages sent before and not received before .
A.2 Chain Lemma
See 5.2
Proof A.7.
We prove that the invariant holds in the initial configuration and at all subsequent times by induction on events , omitting events that do not affect chains. Let and .
In the initial configuration, the only refob to an internal actor is . Since knows , the invariant is satisfied.
In the cases below, let be free variables, not referencing the variables used in the statement of the lemma.
-
•
creates a new unreleased refob , which satisfies the invariant because .
-
•
creates a set of refobs . Let , created using .
If is already in the root set, then the invariant is trivially preserved. Otherwise, there must be a chain where and . Then is a chain in , since .
If is an internal actor, then this shows that every unreleased refob to has a chain in . Otherwise, is in the root set in . To see that the invariant still holds, notice that is a witness of the desired chain.
-
•
removes the fact but also sends , so chains are unaffected.
-
•
delivers to and adds to its knowledge set.
Suppose is part of a chain , i.e. and and for some . Since , we still have a chain in .
-
•
releases the refob . Since external actors never release their refobs, both and must be internal actors.
Suppose the released refob was part of a chain , i.e. and for some . We will show that is a chain in .
-
•
adds a message from an external actor to the internal actor . This event can only create new refobs that point to receptionists, so it preserves the invariant.
-
•
emits a message to the external actor . Since all targets in are already in the root set, the invariant is preserved.
A.3 Termination Detection
Given a set of snapshots taken before some time , we write to denote those snapshots in that were taken before time . If , we denote the time of ’s snapshot as .
See 6.5 Call this set of snapshots . First, we prove the following lemma.
Lemma A.8.
If and , then is unreleased at .
Proof A.9.
By definition, only if . Since , we must also have . For , there are two cases.
Case 1: . Since , Lemma A.3 implies that is unreleased at time .
Case 2: For some and some , . Since performed its final action before taking its snapshot, this implies that will never send the message containing to .
Suppose then for a contradiction that is released at time . Since , Lemma A.3 implies that received an message containing before its snapshot. But this is impossible because never sends this message.
Proof A.10 (Proof (Lemma 6.5)).
By strong induction on time , we show that is closed and that every actor appears blocked.
Induction hypothesis: For all times , if and , then , , and and for some .
Since , the induction hypothesis holds trivially in the initial configuration.
Now assume the induction hypothesis. Suppose that takes its snapshot at time with , which implies .
implies that was created before . Lemma A.8 implies that is also unreleased at time , since cannot perform a Release event after its final action. Hence is in the closure of at time , so .
Now suppose . Then either will be activated after or was deactivated before . The former is impossible because would need to become unblocked to receive . Since is unreleased at time and , the latter implies that there is an undelivered message for at time . But this is impossible as well, since is blocked at .
Finally, let such that ; we must show that . By the above arguments, is active at time and unreleased at time . Since both actors performed their final action before their snapshots, all messages sent before must have been delivered before . By Lemma A.5, this implies .
We now prove the safety theorem, which states that if is a finalized set of snapshots, then the corresponding actors of are terminated. We do this by showing that at each time , all actors in are blocked and all of their potential inverse acquaintances are in .
Consider the first actor in to take a snapshot. We show, using the Chain Lemma, that the closure of this actor is in . Then, since all potential inverse acquaintances of take snapshots strictly after , it is impossible for to have any undelivered messages without appearing unblocked.
For every subsequent actor to take a snapshot, we make a similar argument with an additional step: If has any potential inverse acquaintances in , then they could not have sent a message without first becoming unblocked.
See 6.4
Proof A.11.
Proof by induction on events. The induction hypothesis consists of two clauses that must both be satisfied at all times .
-
•
IH 1: If and is unreleased, then .
-
•
IH 2: The actors of are all blocked.
Initial configuration
Since , the invariant trivially holds.
Suppose takes a snapshot at time . We show that if is unreleased at time , then and there are no undelivered messages along from to . We do this with the help of two lemmas.
Lemma A.12.
If , then is unreleased at time and there are no undelivered messages along at time . Moreover, if , then there are no undelivered messages along throughout the interval .
Proof A.13 (Proof (Lemma)).
Since is closed, we have and . Since appears blocked, we must have and for some .
Suppose . Since , is not deactivated and not released at or . Hence, by Lemma A.5, every message sent along before was received before . Since message sends precede receipts, each of those messages was sent before . Hence there are no undelivered messages along throughout .
Now suppose . Since , is not deactivated and not released at . By IH 2, was blocked throughout the interval , so it could not have sent a message. Hence is not released at . By Lemma A.5, all messages sent along before must have been delivered before . Hence, there are no undelivered messages along at time .
Lemma A.14.
Let be a chain to at time . Then .
Proof A.15 (Proof (Lemma)).
Since all refobs in a chain are unreleased, we know and so . It therefore suffices to prove, by induction on the length of the chain, that .
Base case: By the definition of a chain, , so .
Induction step: Assume , which implies . Let be the time of ’s snapshot.
By the definition of a chain, either the message is in transit at time , or . But the first case is impossible by Lemma A.12, so we only need to consider the latter.
Suppose . Lemma A.12 implies that cannot perform the event during . Hence , so .
Now suppose . By IH 2, must have been blocked throughout the interval . Hence could not have created any refobs during this interval, so must have been created before . This implies and therefore .
Lemma A.14 implies that cannot be in the root set. If it were, then by the Chain Lemma there would be a refob with a chain where is an external actor. Since , there would need to be a snapshot from in – but external actors do not take snapshots, so this is impossible.
In order to maintain IH 2, we must show that if then this event cannot occur. So suppose . By IH 1, we must have , so . By IH 2, we moreover have – otherwise would be blocked and unable to send this message. Since appears blocked in , we must have and for some . Since is not deactivated at and unreleased at , Lemma A.5 implies that every message sent before is received before . Hence cannot send this message to because .
In order to maintain IH 1, suppose that one of the refobs sent to in this step is , where . Then in the next configuration, occurs in ’s knowledge set. By the same argument as above, and and for some . Hence cannot perform the event before , so and .
SendInfo(y,z,A,B,C)
By the same argument as above, cannot send an message to without violating message counts, so IH 2 is preserved.
Suppose that and . By IH 1, is unreleased at time . Since is finalized, . Hence cannot deactivate and IH 2 is preserved.
Since every potential inverse acquaintance of an actor in is also in , none of the actors in is a receptionist. Hence this rule does not affect the invariants.
Suppose where . Then is unreleased and and . But this is impossible because external actors do not take snapshots.