diff options
Diffstat (limited to 'chapter')
| -rw-r--r-- | chapter/1/rpc.md | 244 | ||||
| -rw-r--r-- | chapter/2/1.png | bin | 14176 -> 0 bytes | |||
| -rw-r--r-- | chapter/2/10.png | bin | 9834 -> 0 bytes | |||
| -rw-r--r-- | chapter/2/11.png | bin | 12134 -> 0 bytes | |||
| -rw-r--r-- | chapter/2/12.png | bin | 17071 -> 0 bytes | |||
| -rw-r--r-- | chapter/2/13.png | bin | 21547 -> 0 bytes | |||
| -rw-r--r-- | chapter/2/14.png | bin | 11405 -> 0 bytes | |||
| -rw-r--r-- | chapter/2/15.png | bin | 15262 -> 0 bytes | |||
| -rw-r--r-- | chapter/2/2.png | bin | 6152 -> 0 bytes | |||
| -rw-r--r-- | chapter/2/3.png | bin | 13719 -> 0 bytes | |||
| -rw-r--r-- | chapter/2/4.png | bin | 25404 -> 0 bytes | |||
| -rw-r--r-- | chapter/2/futures.md | 530 | ||||
| -rw-r--r-- | chapter/2/images/1.png | bin | 0 -> 41235 bytes | |||
| -rw-r--r-- | chapter/2/images/15.png | bin | 0 -> 48459 bytes | |||
| -rw-r--r-- | chapter/2/images/5.png (renamed from chapter/2/5.png) | bin | 20821 -> 20821 bytes | |||
| -rw-r--r-- | chapter/2/images/6.png (renamed from chapter/2/6.png) | bin | 19123 -> 19123 bytes | |||
| -rw-r--r-- | chapter/2/images/7.png (renamed from chapter/2/7.png) | bin | 30068 -> 30068 bytes | |||
| -rw-r--r-- | chapter/2/images/8.png (renamed from chapter/2/8.png) | bin | 13899 -> 13899 bytes | |||
| -rw-r--r-- | chapter/2/images/9.png (renamed from chapter/2/9.png) | bin | 6463 -> 6463 bytes | |||
| -rw-r--r-- | chapter/2/images/p-1.png | bin | 0 -> 39600 bytes | |||
| -rw-r--r-- | chapter/2/images/p-1.svg | 4 | ||||
| -rw-r--r-- | chapter/2/images/p-2.png | bin | 0 -> 40084 bytes | |||
| -rw-r--r-- | chapter/2/images/p-2.svg | 4 | ||||
| -rw-r--r-- | chapter/8/big-data.md | 4 |
24 files changed, 616 insertions, 170 deletions
diff --git a/chapter/1/rpc.md b/chapter/1/rpc.md index 7688455..ccc9739 100644 --- a/chapter/1/rpc.md +++ b/chapter/1/rpc.md @@ -6,40 +6,47 @@ by: "Muzammil Abdul Rehman and Paul Grosu" ## Introduction: -*Remote Procedure Call* (RPC) is a design *paradigm* that allow two entities to communicate over a communication channel in a general request-response mechanism. It was initially built as a tool for outsourcing computation to a server in a distributed system, however, it has evolved over the years to build modular, scalable, distributed, language-agnostic ecosystem of applications. This RPC *paradigm* has been part of the driving force in creating truly revolutionizing distributed systems and giving rise to various communication schemes and protocols between diverse systems. +*Remote Procedure Call* (RPC) is a design *paradigm* that allow two entities to communicate over a communication channel in a general request-response mechanism. The definition of RPC has mutated and evolved significantly over the past three decades, and therefore RPC *paradigm* is a generic, broadly classifying term to refer to all RPC-esque systems that have arisen over the past four decades. The *definition* of RPC has evolved over the decades. It has moved on from a simple *client-server* design to a group of inter-connected *services*. While the initial RPC *implementations* were designed as tools for outsourcing computation to a server in a distributed system, however, RPC has evolved over the years to build language-agnostic ecosystem of applications. This RPC *paradigm* has been part of the driving force in creating truly revolutionizing distributed systems and giving rise to various communication schemes and protocols between diverse systems. -RPC *paradigm* has been implemented in various forms in our every-day systems. From lower level applications like Network File Systems{% cite sunnfs --file rpc %} and Remote Direct Memory Access{% cite rpcoverrdma --file rpc %} to access protocols to developing an ecosystem of microservices, RPC has been used everywhere. Some of the major examples of RPC include SunNFS{% cite sunnfs --file rpc %}, Twitter's Finagle{% cite finagle --file rpc %}, Apache Thrift{% cite thrift --file rpc %}, Java RMI{% cite rmipaper --file rpc %}, SOAP, CORBA{% cite corba --file rpc %}, Google's gRPC{% cite grpc --file rpc %}. +RPC *paradigm* has been used to implement our every-day systems. From lower level applications like Network File Systems{% cite sunnfs --file rpc %} and Remote Direct Memory Access{% cite rpcoverrdma --file rpc %} to access protocols to developing an ecosystem of microservices, RPC has been used everywhere. RPC has a diverse variety of applications -- SunNFS{% cite sunnfs --file rpc %}, Twitter's Finagle{% cite finagle --file rpc %}, Apache Thrift{% cite thrift --file rpc %}, Java RMI{% cite rmipaper --file rpc %}, SOAP, CORBA{% cite corba --file rpc %} and Google's gRPC{% cite grpc --file rpc %} to name a few. -RPC has evolved over the years. Starting off as a synchronous, insecure, request-response system, RPC has evolved into a secure, asynchronous, resilient *paradigm* that has influenced protocols and programming designs, like, HTTP, REST, and just about anything with a request-response system. It has transitioned to an asynchronous bidirectional communication for connecting services and devices across the internet. RPC has influenced various design paradigms and communication protocols. +RPC has evolved over the years. Starting off as a synchronous, insecure, request-response system, RPC has evolved into a secure, asynchronous, resilient *paradigm* that has influenced protocols and programming designs, like, HTTP, REST, and just about anything with a request-response system. It has transitioned to an asynchronous, bidirectional, communication mechanism for connecting services and devices across the internet. While the initial RPC implementations mainly focused on a local, private network with multiple clients communicating with a server and synchronously waiting for the response from the server, modern RPC systems have *endpoints* communicating with each other, asynchronously passing arguments and processing responses, as well having two-way request-response streams(from client to server, and also from server to client). RPC has influenced various design paradigms and communication protocols. ## Remote Procedure Calls: -*Remote Procedure Call paradigm* can be defined, at a high level, as a set of two language-agnostic communication *endpoints* connected over a network with one endpoint sending a request and the other endpoint generating a response based on that request. In the simplest terms, it's a request-response paradigm where the two *endpoints*/hosts have different *address space*. The host that requests a remote procedure can be referred to as *caller* and the host that responds to this can be referred to as *callee*. +The *Remote Procedure Call paradigm* can be defined, at a high level, as a set of two communication *endpoints* connected over a network with one endpoint sending a request and the other endpoint generating a response based on that request. In the simplest terms, it's a request-response paradigm where the two *endpoints*/hosts have different *address space*. The host that requests a remote procedure can be referred to as *caller* and the host that responds to this can be referred to as *callee*. The *endpoints* in the RPC can either be a client and a server, two nodes in a peer-to-peer network, two hosts in a grid computation system, or even two microservices. The RPC communication is not limited to two hosts, rather could have multiple hosts or *endpoints* involved {% cite anycastrpc --file rpc %}. +<p align="center"> +[ Image Source: {% cite rpcimage --file rpc %}] +</p> <figure> <img src="{{ site.baseurl }}/resources/img/rpc_chapter_1_ycog_10_steps.png" alt="RPC in 10 Steps." /> -<p>Fig1. - Remote Procedure Call{% cite rpcimage --file rpc %}.</p> +<p>Fig1. - Remote Procedure Call.</p> </figure> -The simplest RPC implementation looks like Fig1. In this case, the *client*(or *caller*) and the *server*(or *callee*) are separated by a physical network. The main components of the system are the client routine/program, the client stub, the server routine/program, the server stub, and the network routines. The client program can only interact with the client stub that provides the interface of the remote server to the client. This stub also provides marshalling/pickling/serialization of the input arguments sent to the stub by the client routine. Similarly, the server stub provides a client interface to the server routines. Whenever a client routine has to perform a *remote procedure*, it calls the client stub, which serializes the input argument. This serialized data is sent to the server using OS network routines (TCP/IP). The data is serialized by the server stub, present to the server routines for the given arguments. The return value from the server routines is serialized again and sent over the network back to the client where it's deserialized by the client stub and presented to the client routine. This *remote procedure* is generally hidden from the client routine and it appears as a *local procedure* to the client. RPC services also require a discovery service/host-resolution mechanism to bootstrap the communication between the client and the server. +The simplest RPC implementation looks like Fig1. In this case, the *client*(or *caller*) and the *server*(or *callee*) are separated by a physical network. The main components of the system are the client routine/program, the client stub, the server routine/program, the server stub, and the network routines. A *stub* is a small program that is generally used as a stand-in(or an interface) for a larger program{% cite stubrpc --file rpc %}. A *client stub* exposes the functionality provided by the server routine to the client routine while the server stub provides a client-like program to the server routine{% cite rpcimage --file rpc %}. The client stub takes the input arguments from the client program and returns the result, while the server stub provides input arguments to the server program and gets the results. The client program can only interact with the client stub that provides the interface of the remote server to the client. This stub also provides marshalling/pickling/serialization of the input arguments sent to the stub by the client routine. Similarly, the server stub provides a client interface to the server routines as well as the marshalling services. + +When a client routine performs a *remote procedure*, it calls the client stub, which serializes the input argument. This serialized data is sent to the server using OS network routines (TCP/IP){% cite rpcimage --file rpc %}. The data is serialized by the server stub, present to the server routines for the given arguments. The return value from the server routines is serialized again and sent over the network back to the client where it's deserialized by the client stub and presented to the client routine. This *remote procedure* is generally hidden from the client routine and it appears as a *local procedure* to the client. RPC services also require a discovery service/host-resolution mechanism to bootstrap the communication between the client and the server. One important feature of RPC is different *address space* {% cite implementingrpc --file rpc %} for all the endpoints, however, passing the locations to a global storage(Amazon S3, Microsoft Azure, Google Cloud Store) is not impossible. In RPC, all the hosts have separate *address spaces*. They can't share pointers or references to a memory location in one host. This *address space* isolation means that all the information is passed in the messages between the host communicating as a value (objects or variables) but not by reference. Since RPC is a *remote* procedure call, the values sent to the *remote* host cannot be pointers or references to a *local* memory. However, passing links to a global shared memory location is not impossible but rather dependent on the type of system (see *Applications* section for detail). -Originally, RPC was developed as a synchronous, language-specific marshalling service with a custom network protocol to outsource computation {% cite implementingrpc --file rpc %}. It had registry-system to register all the servers. One of the earliest RPC-based system {% cite implementingrpc --file rpc %} was implemented in the Cedar programming language in early 1980's. The goal of this system was to provide similar programming semantics as local procedure calls. Developed for a LAN network with an inefficient network protocol and a *serialization* scheme to transfer information using the said network protocol, this system aimed at executing a *procedure*(also referred as *method* or a *function*) in a remote *address space*. The single-thread synchronous client and the server were written in an old *Cedar* programming language with a registry system used by the servers to *bind*(or register) their procedures. The clients used this registry system to find a specific server to execute their *remote* procedures. +Originally, RPC was developed as a synchronous request-response mechanism, tied to a specific programming language implementation, with a custom network protocol to outsource computation {% cite implementingrpc --file rpc %}. It had registry system to register all the servers. One of the earliest RPC-based system {% cite implementingrpc --file rpc %} was implemented in the Cedar programming language in early 1980's. The goal of this system was to provide similar programming semantics as local procedure calls. Developed for a LAN network with an inefficient network protocol and a *serialization* scheme to transfer information using the said network protocol, this system aimed at executing a *procedure*(also referred as *method* or a *function*) in a remote *address space*. The single-thread synchronous client and the server were written in an old *Cedar* programming language with a registry system used by the servers to *bind*(or register) their procedures. The clients used this registry system to find a specific server to execute their *remote* procedures. This RPC implementation {% cite implementingrpc --file rpc %} had a very specific use-case. It was built specifically for outsourcing computation between a "Xerox research internetwork", a small, closed, ethernet network with 16-bit addresses{% cite implementingrpc --file rpc %}. -Modern RPC-based systems are language-agnostic, asynchronous, load-balanced systems. Authentication and authorization to these systems have been added as needed along with other security features. Most of these systems have fault-handling built into them as modules. +Modern RPC-based systems are language-agnostic, asynchronous, load-balanced systems. Authentication and authorization to these systems have been added as needed along with other security features. Most of these systems have fault-handling built into them as modules and the systems are generally spread all across the internet. RPC programs have a network (or a communication channel), therefore, they need to handle remote errors and be able to communication information successfully. Error handling generally varies and is categorized as *remote-host* or *network* failure handling. Depending on the type of the system, and the error, the caller (or the callee) return an error and these errors can be handled accordingly. For asynchronous RPC calls, it's possible to specify events to ensure progress. RPC implementations use a *serialization*(also referred to as *marshalling* or *pickling*) scheme on top of an underlying communication protocol (traditionally TCP over IP). These *serialization* schemes allow both the caller *caller* and *callee* to become language agnostic allowing both these systems to be developed in parallel without any language restrictions. Some examples of serialization schemes are JSON, XML, or Protocol Buffers {% cite grpc --file rpc %}. -RPC allows different components of a larger system to be developed independently of one another. The language-agnostic nature combined with a decoupling of some parts of the system allows the two components (caller and callee) to scale separately and add new functionalities. This independent scaling of the system might lead to a mesh of interconnected RPC *services* facilitating one another. +Modern RPC systems allow different components of a larger system to be developed independently of one another. The language-agnostic nature combined with a decoupling of some parts of the system allows the two components (caller and callee) to scale separately and add new functionalities. This independent scaling of the system might lead to a mesh of interconnected RPC *services* facilitating one another. ### Examples of RPC -RPC has become very predominant in modern systems. In the simplest RPC systems, a client connects to a server over a network connection and performs a *procedure*. This procedure could be as simple as `return "Hello World"` in your favorite programming language. However, the complexity of the of this remote procedure has no upper bound. +RPC has become very predominant in modern systems. Google even performs orders of 10^10^ RPC calls per second {% cite grpcpersec --file rpc %}. That's *tens of trillions* of RPC calls *every second*. It's more than the *annual GDP of United States* {%cite usgdp --file rpc%}. + +In the simplest RPC systems, a client connects to a server over a network connection and performs a *procedure*. This procedure could be as simple as `return "Hello World"` in your favorite programming language. However, the complexity of the of this remote procedure has no upper bound. Here's the code of this simple RPC server, written in Python3. ```python @@ -70,69 +77,200 @@ One can even view the *three-way handshake* as an example of RPC paradigm. The ## Evolution of RPC: -RPC paradigm was first proposed in 1980’s and still continues as a relevant model of performing distributed computation, which initially was developed for a LAN and now can be globally implemented. It has had a long and arduous journey to its current state. Here are the three main(overlapping) stages that RPC went through. +RPC paradigm was first proposed in 1980’s and still continues as a relevant model of performing distributed computation, which initially was developed for a LAN and now can be implemented on open networks, as web services across the internet. It has had a long and arduous journey to its current state. Here are the three main(overlapping) stages that RPC went through. ### The Rise: All Hail RPC(Early 1970's - Mid 1980's) -RPC started off strong. With RFCs{% cite rfc674 rfc707 --file rpc %} coming out and specifying the design of Remote Procedure Calls, followed by Nelson et. al{% cite implementingrpc --file rpc %} coming up with a first implementation for the Cedar programming language, RPC revolutionized systems in general and gave rise to one of the earliest distributed systems(apart from the internet, of course). +RPC started off strong. With RFC 674{% cite rfc674 --file rpc %} and RFC 707{% cite rfc674 rfc707 --file rpc %} coming out and specifying the design of Remote Procedure Calls, followed by Nelson et. al{% cite implementingrpc --file rpc %} coming up with a first RPC implementation for the Cedar programming language, RPC revolutionized systems in general and gave rise to one of the earliest distributed systems(apart from the internet, of course). With these early achievements, people started using RPC as the defacto design choice. It became a Holy Grail in the systems community for a few years after the first implementation. -### The Fall: RPC is Dead(Late 1970's - Late 1980's) +### The Fall: RPC is Dead(Late 1970's - Late 1990's) + +RPC, despite being an initial success, wasn't without flaws. Within a year of its inception, the limitation of the RPC started to catch up with it. RFC 684 criticized RPC for latency, failures, and the cost. It also focussed on message-passing systems as an alternative to RPC design. Similarly, a few years down the road, in 1988, Tenenbaum et.~al presented similar concerns against RPC {%cite critiqueofrpc --file rpc %}. It talked about problems heterogeneous devices, message passing as an alternative, packet loss, network failure, RPC's synchronous nature, and highlighted that RPC is not a one-size-fits-all model. + +In 1994, *A Note on Distributed Computing* was published. This paper claimed RPC to be "fundamentally flawed" {%cite notedistributed --file rpc %}. It talked about a unified object view and cited four main problems with dividing these objects for distributed computing in RPC: communication latency, address space separation, partial failures and concurrency issues(resulting from accessing same remote object by two concurrent client requests). Although most of these problems(except partial failures) were inherently associated with distributed computing itself but partial failures for RPC systems meant that progress might not always be possible in an RPC system. + +This era wasn't a dead end for RPC, though. Some of the preliminary designs for modern RPC systems were introduced in this era. Perhaps, the earliest system in this era was SunRPC {% cite sunnfs --file rpc %} used for the Sun Network File System(NFS). Soon to follow SunRPC was CORBA{% cite corba --file rpc %} which was followed by Java RMI{% cite rmipaper --file rpc %}. -RPC, despite being an initial success, wasn't without flaws. Within a year of its inception, the limitation of the RPC started to catch up with it. RFC 684 criticized RPC for latency, failures, and the cost. It also focussed on message-passing systems as an alternative to RPC design. Similarly, a few years down the road, in 1988, Tenenbaum et. al presented similar concerns against RPC {%cite critiqueofrpc --file rpc %}. It talked about problems heterogeneous devices, message passing as an alternative, packet loss, network failure, RPC's synchronous nature, and highlighted that RPC is not a one-size-fits-all model. +However, the initial implementations of these systems were riddled with various issues and design flaws. For instance, Java RMI didn't handle network failures and assumed a reliable network with zero-latency{% cite rmipaper --file rpc %}. -### The Rise, Again: Long Live RPC(Early 1990's - Today) +### The Rise, Again: Long Live RPC(Late 1990's - Today) -Despite facing problems in its early days, RPC withstood the test of time. Researchers realized the limitations of RPC and focussed on rectifying and instead of enforcing RPC, they started to use RPC in applications where it was needed. The designer started adding exception-handling, async, network failure handling and heterogenity between different languages/devices to RPC. +Despite facing problems in its early days, RPC withstood the test of time. Researchers realized the limitations of RPC and focussed on rectifying and instead of enforcing RPC, they started to use RPC in applications where it was needed. The designer started adding exception-handling, async, network failure handling and heterogeneity between different languages/devices to RPC. -Perhaps, the earliest system in this era was SunRPC {% cite sunnfs --file rpc %} used for the Sun Network File System(NFS). This SunRPC has gone under various additions and is now referred to as Open Network Computing RPC(ONC RPC). +In this era, SunRPC went through various additions and became came to be known as Open Network Computing RPC(ONC RPC). CORBA and RMI have also undergone various modifications as internet standards were set. -Soon to follow SunRPC was the language-agnostic CORBA{% cite corba --file rpc %} which was followed by Java RMI{% cite rmipaper --file rpc %}. CORBA and RMI have also undergone various modifications as internet standards were set and TCP/IP became the norm. +A new breed of RPC also started in this era, Async(asynchronous) RPC, giving rise to systems that use *futures* and *promises*, like Finagle{% cite finagle --file rpc %} and Cap'n Proto(post-2010). -A new breed of RPC also started in this era(early 2000's), Async RPC, giving rise to systems that use *futures* and *promises*, like Finagle{% cite finagle --file rpc %} and Cap'n Proto(post-2010). -In the post-2000 era, MAUI{% cite maui --file rpc %}, Cap'n Proto{% cite capnproto --file rpc %}, gRPC{% cite grpc --file rpc %}, Thrift{% cite thrift --file rpc %} and Finagle{% cite finagle --file rpc %} have been released, which have significantly boosted the widespread use of RPC. A level overview of some of the most important RPC implementation is as follows. +<p align="center"> +[ Image Source: {% cite norman --file rpc %}] +</p> +<figure> + <img src="{{ site.baseurl }}/resources/img/rpc_chapter_1_syncrpc.jpg" alt="RPC in 10 Steps." /> +<p>Fig2. - Synchronous RPC.</p> +</figure> + + +<p align="center"> +[ Image Source: {% cite norman --file rpc %}] +</p> +<figure> + <img src="{{ site.baseurl }}/resources/img/rpc_chapter_1_asyncrpc.jpg" alt="RPC in 10 Steps." /> +<p>Fig3. - Asynchronous RPC.</p> +</figure> + + +A traditional, synchronous RPC is a *blocking* operation while an asynchronous RPC is a *non-blocking* operation{%cite dewan --file rpc %}. Fig2. shows a synchronous RPC call while Fig3. shows an asynchronous RPC call. In synchronous RPC, the client sends a request to the server and blocks and waits for the server to perform its computation and return the result. Only after getting the result from the server, the client proceeds onwards. In an asynchronous RPC, the client performs a request to the server and waits only for the acknowledgment of the delivery of input parameters/arguments. After this, the client proceeds onwards and when the server is finished processing, it sends an interrupt to the client. The client receives this message from the server, receives the results, and continues. + +Asynchronous RPC makes it possible to separate the remote call from the return value making it possible to write a single-threaded client to handle multiple RPC calls at the specific intervals it needs to process{%cite async --file rpc%}. It also allows easier handling of slow clients/servers as well as transferring large data easily(due to their incremental nature){%cite async --file rpc%}. + +In the post-2000 era, MAUI{% cite maui --file rpc %}, Cap'n Proto{% cite capnprotosecure --file rpc %}, gRPC{% cite grpc --file rpc %}, Thrift{% cite thrift --file rpc %} and Finagle{% cite finagle --file rpc %} have been released, which have significantly boosted the widespread use of RPC. + +Most of these newer systems came up with their Interface Description Languages(IDLs). These IDLs specified the common protocols and interfacing language that could be used to transfer information clients and servers written in different programming languages, making these RPC implementations language-agnostic. Some of the most common IDLs are JSON, XML, and ProtoBufs. + +A high-level overview of some of the most important RPC implementation is as follows. #### Java Remote Method Invocation -Java RMI (Java Remote Method Invocation){% cite rmibook --file rpc %} is a Java implementation for performing RPC (Remote Procedure Calls) between a client and a server. The client using a stub passes via a socket connection the information over the network to the server. The Remote Object Registry (ROR){% cite rmipaper --file rpc %} on the server contains the references to objects that can be accessed remotely and through which the client will connect to. The client then can request of the invocation of methods on the server for processing the requested call and then responds with the answer. RMI provides some security by being encoded but not encrypted, though that can be augmented by tunneling over a secure connection or other methods. +Java RMI (Java Remote Method Invocation){% cite rmibook --file rpc %} is a Java implementation for performing RPC (Remote Procedure Calls) between a client and a server. The client using a stub passes via a socket connection the information over the network to the server that contains remote objects. The Remote Object Registry (ROR){% cite rmipaper --file rpc %} on the server contains the references to objects that can be accessed remotely and through which the client will connect to. The client then can request the invocation of methods on the server for processing the requested call and then responds with the answer. + +RMI provides some security by being encoded but not encrypted, though that can be augmented by tunneling over a secure connection or other methods. Moreover, RMI is very specific to Java. It cannot be used to take advantage of the language-independence feature that is inherent to most RPC implementations. Perhaps the main problem with RMI is that it doesn't provide *access transparency*. This means that a programmer(not the client program) cannot distinguish between the local objects or the remote objects making it relatively difficult handle partial failures in the network{%cite roi --file rpc %}. #### CORBA -CORBA (Common Object Request Broker Architecture){% cite corba --file rpc %} was created by the Object Management Group {% cite corbasite --file rpc %} to allow for language-agnostic communication among multiple computers. It is an object-oriented model defined via an Interface Definition Language (IDL) and the communication is managed through an Object Request Broker (ORB). Each client and server have an ORB by which they communicate. The benefits of CORBA is that it allows for multi-language implementations that can communicate with each other, but much of the criticism around CORBA relates to poor consistency among implementations. +CORBA (Common Object Request Broker Architecture){% cite corba --file rpc %} was created by the Object Management Group {% cite corbasite --file rpc %} to allow for language-agnostic communication among multiple computers. It is an object-oriented model defined via an Interface Definition Language (IDL) and the communication is managed through an Object Request Broker (ORB). This ORB acts as a broker for objects. CORBA can be viewed as a language-independent RMI system where each client and server have an ORB by which they communicate. The benefits of CORBA is that it allows for multi-language implementations that can communicate with each other, but much of the criticism around CORBA relates to poor consistency among implementations and it's relatively outdated by now. Moreover, CORBA suffers from same access transparency issues as Java RMI. #### XML-RPC and SOAP -SOAP (Simple Object Access Protocol) is a successor of XML-RPC as a web-services protocol for communicating between a client and server. It was initially designed by a group at Microsoft {% cite soaparticle1 --file rpc %}. The SOAP message is an XML-formatted message composed of an envelope inside which a header and a body are provided. The body of the message contains the request and response of the message, which is transmitted over HTTP or SMTP. The benefit of such a protocol is that it provides the flexibility for transmission over multiple transport protocol, though parsing such messages could become a bottleneck. +The XML-RPC specifications {% cite Wiener --file rpc%} performs an HTTP Post request to a server formatted as XML composed of a *header* and *payload* that calls only one method. It was originally released in the late 1990's and unlike RMI, it provides transparency by using HTTP as a transparent mechanism. + +The header has to provide the basic information, like user agent and the size of the payload. The payload has to initiate a `methodCall` structure by specifying the name via `methodName` and associated parameter values. Parameters for the method can be scalar, structures or (recursive) arrays. The types of scalar can be one of `i4`, `int`, `boolean`, `string`, `double`, `dateTime.iso8601` or `base64`. The scalars are used to create more complex structures and arrays. + +Below is an example as provided by the XML-RPC documentation{% cite Wiener --file rpc%}: + +```XML + +POST /RPC2 HTTP/1.0 +User-Agent: Frontier/5.1.2 (WinNT) +Host: betty.userland.com +Content-Type: text/xml +Content-length: 181 + +<?xml version="1.0"?> +<methodCall> + <methodName>examples.getStateName</methodName> + <params> + <param> + <value><i4>41</i4></value> + </param> + </params> + </methodCall> +``` + +The response to a request will have the `methodResponse` with `params` and values, or a `fault` with the associated `faultCode` in case of an error {% cite Wiener --file rpc %}: + +```XML +HTTP/1.1 200 OK +Connection: close +Content-Length: 158 +Content-Type: text/xml +Date: Fri, 17 Jul 1998 19:55:08 GMT +Server: UserLand Frontier/5.1.2-WinNT + +<?xml version="1.0"?> +<methodResponse> + <params> + <param> + <value><string>South Dakota</string></value> + </param> + </params> + </methodResponse> +``` + +SOAP (Simple Object Access Protocol) is a successor of XML-RPC as a web-services protocol for communicating between a client and server. It was initially designed by a group at Microsoft {% cite soaparticle1 --file rpc %}. The SOAP message is an XML-formatted message composed of an envelope inside which a header and a payload are provided(just like XML-RPC). The payload of the message contains the request and response of the message, which is transmitted over HTTP or SMTP(unlike XML-RPC). + +SOAP can be viewed as the superset of XML-RPC that provides support for more complex authentication schemes{%cite soapvsxml --file rpc %} as well as its support for WSDL(Web Services Description Language), allowing easier discovery and integration with remote web services{%cite soapvsxml --file rpc %}. + +The benefit of SOAP is that it provides the flexibility for transmission over multiple transport protocol. The XML-based messages allow SOAP to become language agnostic, though parsing such messages could become a bottleneck. #### Thrift -Thrift is an RPC system created by Facebook and now part of the Apache Foundation {% cite thrift --file rpc %}. It is a language-agnostic IDL by which one generates the code for the client and server. It provides the opportunity for compressed serialization by customizing the protocol and the transport after the description file has been processed. +Thrift is an *asynchronous* RPC system created by Facebook and now part of the Apache Foundation {% cite thrift --file rpc %}. It is a language-agnostic Interface Description Language(IDL) by which one generates the code for the client and server. It provides the opportunity for compressed serialization by customizing the protocol and the transport after the description file has been processed. + +Perhaps, the biggest advantage of Thrift is that its binary data format has a very low overhead. It has a relatively lower transmission cost(as compared to other alternatives like SOAP){%cite thrifttut --file rpc %} making it very efficient for large amounts of data transfer. #### Finagle -Finagle was generated by Twitter and is an RPC system written in Scala and can run on a JVM. It is based on three object types: Service objects, Filter objects and Future objects {% cite finagle --file rpc %}. The Future objects act by asynchronously being requested for a computation that would return a response at some time in the future. The Service objects are an endpoint that will return a Future upon processing a request. A Filter object transforms requests for further processing in case additional customization is required from a request. +Finagle is a fault-tolerant, protocol-agnostic runtime for doing RPC and high-level API for composing futures(see Async RPC section), with RPC calls generated under the hood. It was created by Twitter and is written in Scala to run on a JVM. It is based on three object types: Service objects, Filter objects and Future objects {% cite finagle --file rpc %}. + +The Future objects act by asynchronously being requested for a computation that would return a response at some time in the future. These Future objects are the main communication mechanism in Finagle. All the inputs and the output are represented as Future objects. + +The Service objects are an endpoint that will return a Future upon processing a request. These Service objects can be viewed as the interfaces used to implement a client or a server. + +A sample Finagle Server that reads a request and returns the version of the request is shown below. This example is taken from Finagle documentation{% cite finagletut --file rpc %} + +```Scala +import com.twitter.finagle.{Http, Service} +import com.twitter.finagle.http +import com.twitter.util.{Await, Future} + +object Server extends App { + val service = new Service[http.Request, http.Response] { + def apply(req: http.Request): Future[http.Response] = + Future.value( + http.Response(req.version, http.Status.Ok) + ) + } + val server = Http.serve(":8080", service) + Await.ready(server) +} +``` + +A Filter object transforms requests for further processing in case additional customization is required from a request. These provide program-independent operations like, timeouts, etc. They take in a Service and provide a new Service object with the applied Filter. Aggregating multiple Filters is alos possible in Finagle. + +A sample timeout Filter that takes in a service and creates a new service with timeouts is shown below. This example is taken from Finagle documentation{% cite finagletut --file rpc %} + +```Scala +import com.twitter.finagle.{Service, SimpleFilter} +import com.twitter.util.{Duration, Future, Timer} + +class TimeoutFilter[Req, Rep](timeout: Duration, timer: Timer) + extends SimpleFilter[Req, Rep] { + + def apply(request: Req, service: Service[Req, Rep]): Future[Rep] = { + val res = service(request) + res.within(timer, timeout) + } +} +``` #### Open Network Computing RPC(ONC RPC) -ONC was originally introduced as SunRPC {%cite sunrpc --file rpc %} for the Sun NFS. The Sun NFS system had a stateless server, with client-side caching, unique file-handlers, and supported NFS read, write, truncate, unlink, etc operations. However, SunRPC was later revised as ONC in 1995 {%cite rfc1831 --file rpc %} and then in 2009 {%cite rfc5531 --file rpc %}. The IDL used in ONC(and SunRPC) is External Data Representation (XDR), a serialization mechanism specific to networks communication and therefore, ONC is limited to applications like Network File Systems. +ONC was originally introduced as SunRPC {%cite sunnfs --file rpc %} for the Sun NFS. The Sun NFS system had a stateless server, with client-side caching, unique file handlers, and supported NFS read, write, truncate, unlink, etc operations. However, SunRPC was later revised as ONC in 1995 {%cite rfc1831 --file rpc %} and then in 2009 {%cite rfc5531 --file rpc %}. The IDL used in ONC(and SunRPC) is External Data Representation (XDR), a serialization mechanism specific to networks communication and therefore, ONC is limited to applications like Network File Systems. #### Mobile Assistance Using Infrastructure(MAUI) The MAUI project {% cite maui --file rpc %}, developed by Microsoft is a computation offloading system for mobile systems. It's an automated system that offloads a mobile code to a dedicated infrastructure in order to increase the battery life of the mobile, minimize the load on the programmer and perform complex computations offsite. MAUI uses RPC as the communication protocol between the mobile and the infrastructure. #### gRPC -gRPC has been built as a collaboration between Google and Square as a public replacement of Stubby, ARCWire, and Sake {% cite Apigee --file rpc %}. The IDL for gRPC is Protocol Buffers(also referred as ProtoBuf). +gRPC is a multiplexed, bi-directional streaming RPC protocol developed Google and Square. The IDL for gRPC is Protocol Buffers(also referred as ProtoBuf) and is meant as a public replacement of Stubby, ARCWire, and Sake {% cite Apigee --file rpc %}. More details on Protocol Buffers, Stubby, ARCWire, and Sake are available in our gRPC chapter{% cite grpcchapter --file rpc %}. + +gRPC provides a platform for scalable, bi-directional streaming using both synchronized and asynchronous communication. + +In a general RPC mechanism, the client initiates a connection to the server and only the client can *request* while the server can only *respond* to the incoming requests. However, in bi-directional gRPC streams, although the initial connection is initiated by the client(call it *endpoint 1*), once the connection is established, both the server(call it *endpoint 2*) and the *endpoint 1* can send *requests* and receive *responses*. This significantly eases the development where both *endpoints* are communicating with each other(like, grid computing). It also saves the hassle of creating two separate connections between the endpoints (one from *endpoint 1* to *endpoint 2* and another from *endpoint 2* to *endpoint 1*) since both streams are independent. -gRPC provides a platform for scalable, bi-directional streaming using both synchronized and asynchronous communication. It multiplexes the requests over a single connection using header compression. This makes it possible for gRPC to be used for mobile clients where battery life and data usage are important. +It multiplexes the requests over a single connection using header compression. This makes it possible for gRPC to be used for mobile clients where battery life and data usage are important. The core library is in C -- except for Java and GO -- and surface APIs are implemented for all the other languages connecting through it{% cite CoreSurfaceAPIs --file rpc %}. Since Protocol Buffers has been utilized by many individuals and companies, gRPC makes it natural to extend their RPC ecosystems via gRPC. Companies like Cisco, Juniper and Netflix {% cite gRPCCompanies --file rpc %} have found it practical to adopt it. A majority of the Google Public APIs, like their places and maps APIs, have been ported to gRPC ProtoBuf {% cite gRPCProtos --file rpc %} as well. +More details about gRPC and bi-directional streaming can be found in our gRPC chapter {% cite grpcchapter --file rpc %} + #### Cap'n Proto -CapnProto{% cite capnproto --file rpc %} is a data interchange RPC system between that bypasses data-encoding step(like JSON or ProtoBuf) to significantly improve the performance. It's developed by the original author of gRPC's ProtoBuf, but since it uses bytes(binary data) for encoding/decoding, it outperforms gRPC's ProtoBuf. It uses futures and promises to combine various remote operations into a single to save the transportation round-trips. +CapnProto{% cite capnprotosecure --file rpc %} is a data interchange RPC system that bypasses data-encoding step(like JSON or ProtoBuf) to significantly improve the performance. It's developed by the original author of gRPC's ProtoBuf, but since it uses bytes(binary data) for encoding/decoding, it outperforms gRPC's ProtoBuf. It uses futures and promises to combine various remote operations into a single operation to save the transportation round-trips. This means if an client calls a function `foo` and then calls another function `bar` on the output of `foo`, Cap'n Proto will aggregate these two operations into a single `bar(foo(x))` where `x` is the input to the function `foo` {% cite capnprotosecure --file rpc %}. This saves multiple roundtrips, especially in object-oriented programs. ### The Heir to the Throne: gRPC or Thrift -Although there are many candidates to be considered as top contenders for RPC throne, most of these are targeted for a specific type of application. ONC is generally specific to the Network File System(though it's being pushed as a standard), Cap'n Proto is relatively new and untested, MAUI is specific to mobile systems, the open-source Finagle is primarily being used at Twitter(not widespread), and the Java RMI simply doesn't even close anyways(sorry to burst your bubble Java fans). +Although there are many candidates to be considered as top contenders for RPC throne, most of these are targeted for a specific type of application. ONC is generally specific to the Network File System(though it's being pushed as a standard), Cap'n Proto is relatively new and untested, MAUI is specific to mobile systems, the open-source Finagle is primarily being used at Twitter(not widespread), and the Java RMI simply doesn't even come close due to its transparency issues(sorry to burst your bubble Java fans). -Probably, the most powerful, and practical systems out there are Apache Thrift and Google's gRPC, primarily because *variants* of these two systems have been developed and used by Facebook and Google, respectively. This might be considered as biased view against other RPC implementations, however, when one considers Big Data and Internet-scale, only these two companies (and these two systems) come close. +Probably, the most powerful, and practical systems out there are Apache Thrift and Google's gRPC, primarily because these two systems cater to a large number of programming languages, have a significant performance benefit over other techniques and are being actively developed. Thrift was actually released a few years ago, while the first stable release for gRPC came out in August 2016. However, despite being 'out there', Thrift is currently less popular than gRPC {%cite trendrpcthrift --file rpc %}. @@ -140,13 +278,13 @@ gRPC {% cite gRPCLanguages --file rpc %} and Thrift, both, support most of the p The gRPC core is written in C(with the exception of Java and Go) and wrappers are written in other languages to communicate with the core, while the Thrift core is written in C++. -gRPC also provides easier bi-drectional streaming communicaiton between the caller and callee. The client generally initiates the communication {% cite gRPCLanguages --file rpc %} and once the connection is established the client and the server can perform reads and writes independently of each other. However, bi-directional streaming in Thrift might be a little difficult to handle, since it focuses explicitly on a client-server model. To enable bi-directionaly, async streaming, one may have to run two seperate systems {%cite grpcbetter --file rpc%}. +gRPC also provides easier bidrectional streaming communication between the caller and callee. The client generally initiates the communication {% cite gRPCLanguages --file rpc %} and once the connection is established the client and the server can perform reads and writes independently of each other. However, bi-directional streaming in Thrift might be a little difficult to handle, since it focuses explicitly on a client-server model. To enable bidirectional, async streaming, one may have to run two separate systems {%cite grpcbetter --file rpc%}. -Thrift provides exception-handling as a message while the programmer has to handle exceptions in gRPC. In Thrift, exceptions can be returned built into the message, while in gRPC, the programmer explicitly defines this behaviour. This Thrift exception-handling makes it easier to write client-side applications. +Thrift provides exception-handling as a message while the programmer has to handle exceptions in gRPC. In Thrift, exceptions can be returned built into the message, while in gRPC, the programmer explicitly defines this behavior. This Thrift exception-handling makes it easier to write client-side applications. Although custom authentication mechanisms can be implemented in both these system, gRPC come with a Google-backed authentication using SSL/TLS and Google Tokens {% cite grpcauth --file rpc %}. -Moreover, gRPC-based network communication is done using HTTP/2. HTTP/2 makes it feasible for communicating parties to multiplex network connections using the same port. This is more efficient(in terms of memory usage) as compared to HTTP/1.1. Since, gRPC communication is done HTTP/2, it means that gRPC can easily multiplex different services. As for Thrift, multiplexing services is possible, however, due to lack of support from underlying transport protocol, it is performed using a `TMulitplexingProcessor` class {% cite multiplexingthrift --file rpc %}. +Moreover, gRPC-based network communication is done using HTTP/2. HTTP/2 makes it feasible for communicating parties to multiplex network connections using the same port. This is more efficient(in terms of memory usage) as compared to HTTP/1.1. Since gRPC communication is done HTTP/2, it means that gRPC can easily multiplex different services. As for Thrift, multiplexing services is possible, however, due to lack of support from underlying transport protocol, it is performed using a `TMulitplexingProcessor` class(in code) {% cite multiplexingthrift --file rpc %}. However, both gRPC and Thrift allow async RPC calls. This means that a client can send a request to the server and continue with its execution and the response from the server is processed it arrives. @@ -162,11 +300,11 @@ The major comparison between gRPC and Thrift can be summed in this table. | Exceptions | Allows being built in the message | Implemented by the programmer | | Authentication | Custom | Custom + Google Tokens | | Bi-Directionality | Not straightforward | Straightforward | -| Multiplexing | Possible via | Possible via HTTP/2 | +| Multiplexing | Possible via `TMulitplexingProcessor` class | Possible via HTTP/2 | -Although, it's difficult to specifically choose one over the other, however, with increasing popularity of gRPC, and the fact that it's still in early stages of development, the general trend{%cite trendrpcthrift --file rpc %} over the past year has started to shift in favor of gRPC and it's giving Thrift a run for its money. +Although, it's difficult to specifically choose one over the other, however, with increasing popularity of gRPC, and the fact that it's still in early stages of development, the general trend{%cite trendrpcthrift --file rpc %} over the past year has started to shift in favor of gRPC and it's giving Thrift a run for its money. Although, it may not be considered as a metric, but the gRPC was searched, on average, three times more as compared to Thrift{%cite trendrpcthrift --file rpc %}. -**Note:** This study is performed in December 2016 so the results are expected to change with time. +**Note:** This comparison is performed in December 2016 so the results are expected to change with time. ## Applications: @@ -174,13 +312,15 @@ Since its inception, various papers have been published in applying RPC paradigm #### Shared State and Persistence Layer -One major limitation (and the advantage) of RPC is considered the separate *address space* of all the machines in the network. This means that *pointers* or *references* to a data object cannot be passed between the caller and the callee. Therefore, Interweave {% cite interweave2 interweave1 interweave3 --file rpc %} is a middleware system that allows scalable sharing of arbitrary data-types and language-independent processes running heterogeneous hardware. Interweave is specifically designed and is compatible with RPC-based systems and allows easier access to the shared resources between different applications. It even allows passing C *pointers* between the caller and the callee. +One major limitation(and the advantage) of RPC is considered the separate *address space* of all the machines in the network. This means that *pointers* or *references* to a data object cannot be passed between the caller and the callee. Therefore, Interweave {% cite interweave2 interweave1 interweave3 --file rpc %} is a *middleware* system that allows scalable sharing of arbitrary datatypes and language-independent processes running on heterogeneous hardware. Interweave is specifically designed and is compatible with RPC-based systems and allows easier access to the shared resources between different applications using memory blocks and locks. + +Although research has been done in order to ensure a global shared state for an RPC-based system, However, these systems tend to take away the sense of independence and modularity between the *caller* and the *callee* by using a shared storage instead of a separate *address space*. #### GridRPC Grid computing is one of the most widely used applications of RPC paradigm. At a high level, it can be seen as a mesh (or a network) of computers connected with each other to for *grid* such each system can leverage resources from any other system in the network. -In the GridRPC paradigm, each computer in the network can act as the *caller* or the *callee* depending on the amount of resources required {% cite grid1 --file rpc %}. It's also possible for the same computer to act as the *caller* as well as the *callee* for *different* computations. +In the GridRPC paradigm, each computer in the network can act as the *caller* or the *callee* depending on the amount of resources required {% cite grid1 --file rpc %}. It's also possible for the same computer to act as the *caller* as well as the *callee* for *different* computations. Some of the most popular implementations that allow one to have GridRPC-compliant middleware are GridSolve{% cite gridsolve1 gridsolve2 --file rpc %} and Ninf-G{% cite ninf --file rpc %}. Ninf is relatively older than GridSolve and was first published in the late 1990's. It's a simple RPC layer that also provides authentication and secure communication between the two parties. GridSolve, on the other hand, is relatively complex and provides a middleware for the communications using a client-agent-server model. @@ -188,49 +328,51 @@ Some of the most popular implementations that allow one to have GridRPC-complian Mobile systems have become very powerful these days. With multi-core processors and gigabytes of RAM, they can undertake relatively complex computations without a hassle. Due to this advancement, they consume a larger amount of energy and hence, their batteries, despite becoming larger, drain quickly with usage. Moreover, mobile data (network bandwidth) is still limited and expensive. Due to these requirements, it's better to offload mobile computations from mobile systems when possible. RPC plays an important role in the communication for this *computation offloading*. Some of these services use Grid RPC technologies to offload this computation. Whereas, other technologies use an RMI(Remote Method Invocation) system for this. -The Ibis Project {% cite ibis --file rpc %} builds an RMI and GMI (Group Method Invocation) model to facilitate outsourcing computation. Cuckoo {% cite cuckoo --file rpc %} uses this Ibis communication middleware to offload computation. +The Ibis Project {% cite ibis --file rpc %} builds an RMI(similar to JavaRMI) and GMI (Group Method Invocation) model to facilitate outsourcing computation. Cuckoo {% cite cuckoo --file rpc %} uses this Ibis communication middleware to offload computation from applications(built using Cuckoo) running on Android smartphones to remote Cuckoo servers. The Microsoft's MAUI Project {% cite maui --file rpc %} uses RPC communication and allows partitioning of .NET applications and "fine-grained code offload to maximize energy savings with minimal burden on the programmer". MAUI decides the methods to offload to the external MAUI server at runtime. #### Async RPC, Futures and Promises -Remote Procedure Calls can be asynchronous. Not only that but these async RPCs play in integral role in the *futures* and *promises*. *Future* and *promises* are programming constructs that where a *future* is seen as variable/data/return type/error while a *promise* is seen as a *future* that doesn't have a value, yet. We follow Finagle's {% cite finagle --file rpc %} definition of *futures* and *promises*, where the *promise* of a *future*(an empty *future*) is considered as a *request* while the async fulfillment of this *promise* by a *future* is seen as the *response*. This construct is primarily used for concurrent programming. +Remote Procedure Calls can be asynchronous. Not only that but these async RPCs play in integral role in the *futures* and *promises*. *Future* and *promises* are programming constructs that where a *future* is seen as variable/data/return type/error while a *promise* is seen as a *future* that doesn't have a value, yet. We follow Finagle's {% cite finagle --file rpc %} definition of *futures* and *promises*, where the *promise* of a *future*(an empty *future*) is considered as a *request* while the async fulfillment of this *promise* by a *future* is seen as the *response*. This construct is primarily used for asynchronous programming. -Perhaps the most renowned systems using this type of RPC model are Twitter's Finagle{% cite finagle --file rpc %} and Cap'n Proto{% cite capnproto --file rpc %}. +Perhaps the most renowned systems using this type of RPC model are Twitter's Finagle{% cite finagle --file rpc %} and Cap'n Proto{% cite capnprotosecure --file rpc %}. #### RPC in Microservices Ecosystem: -RPC implementations have moved from a one-server model to multiple servers and on to dynamically-created, load-balanced microservices. RPC started as a separate implementations of REST, Streaming RPC, MAUI, gRPC, Cap'n Proto, and has now made it possible for integration of all these implementations as a single abstraction as a user *endpoint* service. The endpoints are the building blocks of *microservices*. These *microservices* interact with each other and applications and combine to give the feel of one large monolithic service. +RPC implementations have moved from a one-server model to multiple servers and on to dynamically-created, load-balanced microservices. RPC started as separate implementations of REST, Streaming RPC, MAUI, gRPC, Cap'n Proto, and has now made it possible for integration of all these implementations as a single abstraction as a user *endpoint*. The endpoints are the building blocks of *microservices*. A *microservice* is usually *service* with a very simple, well-defined purpose, written in almost any language that interacts with other microservices to give the feel of one large monolithic *service*. These microservices are language-agnostic. One *microservice* for airline tickets written in C/C\++, might be communicating with a number of other microservices for individual airlines written in different languages(Python, C\++, Java, Node.js) using a language-agnostic, asynchronous, RPC framework like gRPC{%cite grpc --file rpc %} or Thrift{%cite thrift --file rpc %}. The use of RPC has allowed us to create new microservices on-the-fly. The microservices can not only created and bootstrapped at runtime but also have inherent features like load-balancing and failure-recovery. This bootstrapping might occur on the same machine, adding to a Docker container {% cite docker --file rpc %}, or across a network (using any combination of DNS, NATs or other mechanisms). -RPC can be defined as the "glue" that holds all the microservices together{% cite microservices1rpc --file rpc %}. This means that RPC is one of the primary communication mechanism between different microservices running on different systems. A microservice requests another microservice to perform an operation/query. The other microservice, upon receiving such request, performs an operation and returns a response. This operation could vary from a simple computation to invoking another microservice creating a series of RPC events to creating new microservices on the fly to dynamically load balance the microservices system. +RPC can be defined as the "glue" that holds all the microservices together{% cite microservices1rpc --file rpc %}. This means that RPC is one of the primary communication mechanism between different microservices running on different systems. A microservice requests another microservice to perform an operation/query. The other microservice, upon receiving such request, performs an operation and returns a response. This operation could vary from a simple computation to invoking another microservice creating a series of RPC events to creating new microservices on the fly to dynamically load balance the microservices system. These microservices are language-agnostic. One *microservice* could be written in C/C++, another one could be in different languages(Python, C++, Java, Node.js) and they all might be communicating with each other using a language-agnostic, asynchronous, performant RPC framework like gRPC{%cite grpc --file rpc %} or Thrift{%cite thrift --file rpc %}. -An example of a microservices ecosystem that uses futures/promises is Finagle at Twitter. +An example of a microservices ecosystem that uses futures/promises is Finagle{%cite finagle --file rpc %} at Twitter. ## Security in RPC: -The initial RPC implementation {% cite implementingrpc --file rpc %} was developed for an isolated LAN network and didn't focus much on security. There're various attack surfaces in that model, from the malicious registry, to a malicious server, to a client targeting for Denial-of-Service to Man-in-the-Middle attack between client and server. +The initial RPC implementation {% cite implementingrpc --file rpc %} was developed for an isolated LAN network and didn't focus much on security. There're various attack surfaces in that model, from the malicious registry to a malicious server, to a client targeting for Denial-of-Service to Man-in-the-Middle attack between client and server. -As time progressed and internet evolved, new standards came along, and RPC implementations became much more secure. Security, in RPC, is generally added as a *module* or a *package*. These modules have libraries for authentication and authorization of the communication services (caller and callee). These modules are not always bug-free and it's possible to gain unauthorized access to the system. Efforts are being made to rectify these situations by the security in general, using code inspection and bug bounty programs to catch these bugs before-hand. However, with time new bugs arise and this cycle continues. It's a vicious cycle between attackers and security experts, both of whom tries to outdo their opponent. +As time progressed and internet evolved, new standards came along, and RPC implementations became much more secure. Security, in RPC, is generally added as a *module* or a *package*. These modules have libraries for authentication and authorization of the communication services (caller and callee). These modules are not always bug-free and it's possible to gain unauthorized access to the system. Efforts are being made to rectify these situations by the security in general, using code inspection and bug bounty programs to catch these bugs beforehand. However, with time new bugs arise and this cycle continues. It's a vicious cycle between attackers and security experts, both of whom tries to outdo their opponent. For example, the Oracle Network File System uses a *Secure RPC*{% cite oraclenfs --file rpc %} to perform authentication in the NFS. This *Secure RPC* uses Diffie-Hellman authentication mechanism with DES encryption to allow only authorized users to access the NFS. Similarly, Cap'n Proto {% cite capnprotosecure --file rpc %} claims that it is resilient to memory leaks, segfaults, and malicious inputs and can be used between mutually untrusting parties. However, in Cap'n Proto "the RPC layer is not robust against resource exhaustion attacks, possibly allowing denials of service", nor has it undergone any formal verification {% cite capnprotosecure --file rpc %}. -Although, it's possible to come up with a *Threat Model* that would make an RPC implementation insecure to use, however, one has to understand that using any distributed system increases the attack surface anyways and claiming one *paradigm* to be more secure than another would be a biased statement, since *paradigms* are generally an idea and it depends on different system designers to use these *paradigms* to build their systems and take care of features specific to real systems, like security and load-balancing. There's always a possibility of rerouting a request to a malicious server(if the registry gets hacked), or there's no trust between the *caller* and *callee*. However, we maintain that RPC *paradigm* is not secure or insecure(for that matter), and that the most secure systems are the ones that are in an isolated environment, disconnected from the public internet with a self-destruct mechanism{% cite self --file rpc %} in place, in an impenetrable bunker, and guarded by the Knights Templar(*they don't exist! Well, maybe Fort Meade comes close*). +Although, it's possible to come up with a *Threat Model* that would make an RPC implementation insecure to use, however, one has to understand that using any distributed system increases the attack surface anyways and claiming one *paradigm* to be more secure than another would be a biased statement, since *paradigms* are generally an idea and it depends on different system designers to use these *paradigms* to build their systems and take care of features specific to real systems, like security and load-balancing. There's always a possibility of rerouting a request to a malicious server(if the registry gets hacked), or there's no trust between the *caller* and *callee*. However, we maintain that RPC *paradigm* is not secure or insecure(for that matter), and that the most secure systems are the ones that are in an isolated environment, disconnected from the public internet with a self-destruct mechanism{% cite selfdest --file rpc %} in place, in an impenetrable bunker, and guarded by the Knights Templar(*they don't exist! Well, maybe Fort Meade comes close*). ## Discussion: RPC *paradigm* shines the most in *request-response* mechanisms. Futures and Promises also appear to a new breed of RPC. This leads one to question, as to whether every *request-response* system is a modified implementation to of the RPC *paradigm*, or does it actually bring anything new to the table? These modern communication protocols, like HTTP and REST, might just be a different flavor of RPC. In HTTP, a client *requests* a web page(or some other content), the server then *responds* with the required content. The dynamics of this communication might be slightly different from your traditional RPC, however, an HTTP Stateless server adheres to most of the concepts behind RPC *paradigm*. Similarly, consider sending a request to your favorite Google API. Say, you want to translate your latitude/longitude to an address using their Reverse Geocoding API, or maybe want to find out a good restaurant in your vicinity using their Places API, you'll send a *request* to their server to perform a *procedure* that would take a few input arguments, like the coordinates, and return the result. Even though these APIs follow a RESTful design, it appears to be an extension to the RPC *paradigm*. -RPC paradigm has evolved over time. It has evolved to the extent that, currently, it's become very difficult differentiate RPC from non-RPC. For the past decades, researchers and industry leaders have tried to come up with *their* definition of RPC. The proponents of RPC paradigm view every *request-response* communication as an implementation the RPC paradigm while those against RPC try to explicitly come up with the bounds of RPC. RPC supporters consider it as the Holy Grail of distributed systems. They view it as the foundation of modern distributed communication. From Apache Thrift and ONC to HTTP and REST, they advocate it all as RPC while REST developers have strong opinions against RPC. +RPC paradigm has evolved over time. It has evolved to the extent that, currently, it's become very difficult differentiate RPC from non-RPC. With each passing year, the restrictions and limitations of RPC evolve. Current RPC implementations even have the support for the server to *request* information from the client to *respond* to these requests and vice versa (bidirectionality). This *bidirectional* nature of RPCs have transitioned RPC from simple *client-server* model to a set of *endpoints* communicating with each other. + +For the past four decades, researchers and industry leaders have tried to come up with *their* definition of RPC. The proponents of RPC paradigm view every *request-response* communication as an implementation the RPC paradigm while those against RPC try to explicitly enumerate the limitations of RPC. These limitations, however, seem to slowly vanish as new RPC models are introduced with time. RPC supporters consider it as the Holy Grail of distributed systems. They view it as the foundation of modern distributed communication. From Apache Thrift and ONC to HTTP and REST, they advocate it all as RPC while REST developers have strong opinions against RPC. Moreover, with modern global storage mechanisms, the need for RPC systems to have a separate *address space* seems to be slowly dissolving and disappearing into thin air. So, the question remains what *is* RPC and what * is not* RPC? This is an open-ended question. There is no unanimous agreement about what RPC should look like, except that it has communication between two *endpoints*. What we think of RPC is: -*"In the world of distributed systems, where every individual component of a system, be it a hard disk, a multi-core processor, or a microservice, is an extension of the RPC, it's difficult to come with a concrete definition of the RPC paradigm. Therefore, anything loosely associated with a request-response mechanism can be considered as RPC".* +*In the world of distributed systems, where every individual component of a system, be it a hard disk, a multi-core processor, or a microservice, is an extension of the RPC, it's difficult to come with a concrete definition of the RPC paradigm. Therefore, anything loosely associated with a request-response mechanism can be considered as RPC.* <blockquote> <p align="center"> -**RPC is not dead, long live RPC!** +<em>**RPC is not dead, long live RPC!**</em> </p> </blockquote> diff --git a/chapter/2/1.png b/chapter/2/1.png Binary files differdeleted file mode 100644 index 1d98f19..0000000 --- a/chapter/2/1.png +++ /dev/null diff --git a/chapter/2/10.png b/chapter/2/10.png Binary files differdeleted file mode 100644 index f54711d..0000000 --- a/chapter/2/10.png +++ /dev/null diff --git a/chapter/2/11.png b/chapter/2/11.png Binary files differdeleted file mode 100644 index 7673d90..0000000 --- a/chapter/2/11.png +++ /dev/null diff --git a/chapter/2/12.png b/chapter/2/12.png Binary files differdeleted file mode 100644 index 7b2e13f..0000000 --- a/chapter/2/12.png +++ /dev/null diff --git a/chapter/2/13.png b/chapter/2/13.png Binary files differdeleted file mode 100644 index a2b8457..0000000 --- a/chapter/2/13.png +++ /dev/null diff --git a/chapter/2/14.png b/chapter/2/14.png Binary files differdeleted file mode 100644 index 5027666..0000000 --- a/chapter/2/14.png +++ /dev/null diff --git a/chapter/2/15.png b/chapter/2/15.png Binary files differdeleted file mode 100644 index 4f2c188..0000000 --- a/chapter/2/15.png +++ /dev/null diff --git a/chapter/2/2.png b/chapter/2/2.png Binary files differdeleted file mode 100644 index a75c08b..0000000 --- a/chapter/2/2.png +++ /dev/null diff --git a/chapter/2/3.png b/chapter/2/3.png Binary files differdeleted file mode 100644 index 9cc66b5..0000000 --- a/chapter/2/3.png +++ /dev/null diff --git a/chapter/2/4.png b/chapter/2/4.png Binary files differdeleted file mode 100644 index 8cfec98..0000000 --- a/chapter/2/4.png +++ /dev/null diff --git a/chapter/2/futures.md b/chapter/2/futures.md index 45d2d0b..0075773 100644 --- a/chapter/2/futures.md +++ b/chapter/2/futures.md @@ -4,115 +4,120 @@ title: "Futures" by: "Kisalaya Prasad and Avanti Patil" --- -#Introduction +# Introduction -As human beings we have an ability to multitask ie. we can walk, talk and eat at the same time except when you sneeze. Sneeze is like a blocking activity from the normal course of action, because it forces you to stop what you’re doing for a brief moment and then you resume where you left off. Activities like multitasking are called multithreading in computer lingo. In contrast to this behaviour, computer processors are single threaded. So when we say that a computer system has multi-threaded environment, it is actually just an illusion created by processor where processor’s time is shared between multiple processes. Sometimes processor gets blocked when some tasks are hindered from normal execution due to blocking calls. Such blocking calls can range from IO operations like read/write to disk or sending/receiving packets to/from network. Blocking calls can take disproportionate amount of time compared to the processor’s task execution i.e. iterating over a list. +As human beings we have an ability to multitask ie. we can walk, talk and eat at the same time except when you sneeze. Sneeze is like a blocking activity from the normal course of action, because it forces you to stop what you’re doing for a brief moment and then you resume where you left off. Activities like multitasking are called multithreading in computer lingo. In contrast to this behaviour, computer processors are single threaded. So when we say that a computer system has multi-threaded environment, it is actually just an illusion created by processor where processor’s time is shared between multiple processes. Sometimes processor gets blocked when some tasks are hindered from normal execution due to blocking calls. Such blocking calls can range from IO operations like read/write to disk or sending/receiving packets to/from network. Blocking calls can take disproportionate amount of time compared to the processor’s task execution i.e. iterating over a list. The processor can either handle blocking calls in two ways: - **Synchronous method**: As a part of running task in synchronous method, processor continues to wait for the blocking call to complete the task and return the result. After this processor will resume processing next task. Problem with this kind of method is CPU time not utilized in an ideal manner. -- **Asynchronous method**: When you add asynchrony, you can utilize the time of CPU to work on some other task using one of the preemptive time sharing algorithm. Now when the asynchronous call returns the result, processor can again switch back to the previous process using preemption and resume the process from the point where it’d left off. +- **Asynchronous method**: When you add asynchrony, you can utilize the time of CPU to work on some other task using one of the preemptive time sharing algorithm. This is not blocking the processor at any time and when the asynchronous call returns the result, processor can again switch back to the previous process using preemption and resume the process from the point where it’d left off. -In the world of asynchronous communications many terminologies were defined to help programmers reach the ideal level of resource utilization. As a part of this article we will talk about motivation behind rise of Promises and Futures, we will explain programming model associated with it and discuss evolution of this programming construct, finally we will end this discussion with how this construct helps us today in different general purpose programming languages. +In the world of asynchronous communications many terminologies were defined to help programmers reach the ideal level of resource utilization. As a part of this article we will talk about motivation behind rise of Promises and Futures, how the current notion we have of futures and promises have evolved over time, try to explain various execution models associated with it and finally we will end this discussion with how this construct helps us today in different general purpose programming languages. -<figure class="main-container"> - <img src="./1.png" alt="timeline" /> +<figure> + <img src="./images/1.png" alt="timeline" /> </figure> -#Motivation +# Motivation +The rise of promises and futures as a topic of relevance can be traced parallel to the rise of asynchronous or distributed systems. This seems natural, since futures represent a value available in Future which fits in very naturally with the latency which is inherent to these heterogeneous systems. The recent adoption of NodeJS and server side Javascript has only made promises more relevant. But, the idea of having a placeholder for a result came in significantly before than the current notion of futures and promises. As we will see in further sections, this idea of having a *"placeholder for a value that might not be available"* has changed meanings over time. -A “Promise” object represents a value that may not be available yet. A Promise is an object that represents a task with two possible outcomes, success or failure and holds callbacks that fire when one outcome or the other has occurred. +Thunks can be thought of as a primitive notion of a Future or Promise. According to its inventor P. Z. Ingerman, thunks are "A piece of coding which provides an address". {% cite 23 --file futures %} They were designed as a way of binding actual parameters to their formal definitions in Algol-60 procedure calls. If a procedure is called with an expression in the place of a formal parameter, the compiler generates a thunk which computes the expression and leaves the address of the result in some standard location. -The rise of promises and futures as a topic of relevance can be traced parallel to the rise of asynchronous or distributed systems. This seems natural, since futures represent a value available in Future which fits in very naturally with the latency which is inherent to these heterogeneous systems. The recent adoption of NodeJS and server side Javascript has only made promises more relevant. But, the idea of having a placeholder for a result came in significantly before than the current notion of futures and promises. - - -Thunks can be thought of as a primitive notion of a Future or Promise. According to its inventor P. Z. Ingerman, thunks are "A piece of coding which provides an address". They were designed as a way of binding actual parameters to their formal definitions in Algol-60 procedure calls. If a procedure is called with an expression in the place of a formal parameter, the compiler generates a thunk which computes the expression and leaves the address of the result in some standard location. - - -The first mention of Futures was by Baker and Hewitt in a paper on Incremental Garbage Collection of Processes. They coined the term - call-by-futures to describe a calling convention in which each formal parameter to a method is bound to a process which evaluates the expression in the parameter in parallel with other parameters. Before this paper, Algol 68 also presented a way to make this kind of concurrent parameter evaluation possible, using the collateral clauses and parallel clauses for parameter binding. +The first mention of Futures was by Baker and Hewitt in a paper on Incremental Garbage Collection of Processes. They coined the term - call-by-futures to describe a calling convention in which each formal parameter to a method is bound to a process which evaluates the expression in the parameter in parallel with other parameters. Before this paper, Algol 68 also presented a way to make this kind of concurrent parameter evaluation possible, using the collateral clauses and parallel clauses for parameter binding. In their paper, Baker and Hewitt introduced a notion of Futures as a 3-tuple representing an expression E consisting of (1) A process which evaluates E, (2) A memory location where the result of E needs to be stored, (3) A list of processes which are waiting on E. But, the major focus of their work was not on role of futures and the role they play in Asynchronous distributed computing, and focused on garbage collecting the processes which evaluate expressions not needed by the function. -The Multilisp language, presented by Halestead in 1985 built upon this call-by-future with a Future annotation. Binding a variable to a future expression creates a process which evaluates that expression and binds x to a token which represents its (eventual) result. This design of futures influenced the paper of design of Promises in Argus by Liskov and Shrira in 1988. Building upon the initial design of Future in Multilisp, they extended the original idea by introducing strongly typed Promises and integration with call streams.This made it easier to handle exception propagation from callee to the caller and also to handle the typical problems in a multi-computer system like network failures. This paper also talked about stream composition, a notion which is similar to promise pipelining today. +The Multilisp language, presented by Halestead in 1985 built upon this call-by-future with a Future annotation. Binding a variable to a future expression creates a process which evaluates that expression and binds x to a token which represents its (eventual) result. It allowed an operation to move past the actual computation without waiting for it to complete. If the value is never used, the current computation will not pause. MultiLisp also had a lazy future construct, called Delay, which only gets evaluated when the value is first required. + This design of futures influenced the paper of design of Promises in Argus by Liskov and Shrira in 1988. Both futures in MultiLisp and Promises in Argus provisioned for the result of a call to be picked up later. Building upon the initial design of Future in MultiLisp, they extended the original idea by introducing strongly typed Promises and integration with call streams. Call streams are a language-independent communication mechanism connecting a sender and a receiver in a distributed programming environment. It is used to make calls from sender to receiver like normal RPC. In addition, sender could also make stream-calls where it chooses to not wait for the reply and can make further calls. Stream calls seem like a good use-case for a placeholder to access the result of a call in the future : Promises. Call streams also had provisions for handling network failures. This made it easier to handle exception propagation from callee to the caller and also to handle the typical problems in a multi-computer system. This paper also talked about stream composition. The call-streams could be arranged in pipelines where output of one stream could be used as input on next stream. This notion is not much different to what is known as promise pipelining today, which will be introduced in more details later. -E is an object-oriented programming language for secure distributed computing, created by Mark S. Miller, Dan Bornstein, and others at Electric Communities in 1997. One of the major contribution of E was the first non-blocking implementation of Promises. It traces its routes to Joule which was a dataflow programming language. The notion of promise pipelining in E is inherited from Joule. - -Among the modern languages, Python was perhaps the first to come up with something on the lines of E’s promises with the Twisted library. Coming out in 2002, it had a concept of Deferred objects, which were used to receive the result of an operation not yet completed. They were just like normal objects and could be passed along, but they didn’t have a value. They supported a callback which would get called once the result of the operation was complete. +E is an object-oriented programming language for secure distributed computing, created by Mark S. Miller, Dan Bornstein, and others at Electric Communities in 1997. One of the major contribution of E was the first non-blocking implementation of Promises. It traces its routes to Joule which was a dataflow programming language. E had an eventually operator, * <- * . This created what is called an eventual send in E : the program doesn't wait for the operation to complete and moves to next sequential statement. Eventual-sends queue a pending delivery and complete immediately, returning a promise. A pending delivery includes a resolver for the promise. Further messages can also be eventually send to a promise before it is resolved. These messages are queued up and forwarded once the promise is resolved. The notion of promise pipelining in E is also inherited from Joule. -Promises and javascript have an interesting history. In 2007 inspired by Python’s twisted, dojo came up with it’s own implementation of of dojo.Deferred. This inspired Kris Zyp to then come up with the CommonJS Promises/A spec in 2009. Ryan Dahl introduced the world to NodeJS in the same year. In it’s early versions, Node used promises for the non-blocking API. When NodeJS moved away from promises to its now familiar error-first callback API, it left a void for a promises API. Q.js was an implementation of Promises/A spec by Kris Kowal around this time. FuturesJS library by AJ ONeal was another library which aimed to solve flow-control problems without using Promises in the strictest of senses. In 2011, JQuery v1.5 first introduced Promises to its wider and ever-growing audience. The API for JQuery was subtly different than the Promises/A spec. With the rise of HTML5 and different APIs, there came a problem of different and messy interfaces. A+ promises aimed to solve this problem. From this point on, leading from widespread adoption of A+ spec, promises was finally made a part of ECMAScript® 2015 Language Specification. Still, a lack of backward compatibility and additional features provided means that libraries like BlueBird and Q.js still have a place in the javascript ecosystem. +Among the modern languages, Python was perhaps the first to come up with something on the lines of E’s promises with the Twisted library. Coming out in 2002, it had a concept of Deferred objects, which were used to receive the result of an operation not yet completed. They were just like normal objects and could be passed along, but they didn’t have a value. They supported a callback which would get called once the result of the operation was complete. -#Different Definitions +Promises and javascript have an interesting history. In 2007 inspired by Python’s twisted, dojo came up with it’s own implementation of of dojo.Deferred. This inspired Kris Zyp to then come up with the CommonJS Promises/A spec in 2009. Ryan Dahl introduced the world to NodeJS in the same year. In it’s early versions, Node used promises for the non-blocking API. When NodeJS moved away from promises to its now familiar error-first callback API (the first argument for the callback should be an error object), it left a void for a promises API. Q.js was an implementation of Promises/A spec by Kris Kowal around this time. FuturesJS library by AJ ONeal was another library which aimed to solve flow-control problems without using Promises in the strictest of senses. In 2011, JQuery v1.5 first introduced Promises to its wider and ever-growing audience. The API for JQuery was subtly different than the Promises/A spec. With the rise of HTML5 and different APIs, there came a problem of different and messy interfaces which added to the already infamous callback hell. A+ promises aimed to solve this problem. From this point on, leading from widespread adoption of A+ spec, promises was finally made a part of ECMAScript® 2015 Language Specification. Still, a lack of backward compatibility and additional features provided means that libraries like BlueBird and Q.js still have a place in the javascript ecosystem. -Future, promise, Delay or Deferred generally refer to same synchronisation mechanism where an object acts as a proxy for a yet unknown result. When the result is discovered, promises hold some code which then gets executed. The definitions have changed a little over the years but the idea remained the same. +# Different Definitions -In some languages however, there is a subtle difference between what is a Future and a Promise. -“A ‘Future’ is a read-only reference to a yet-to-be-computed value”. -“A ‘Promise’ is a pretty much the same except that you can write to it as well.” +Future, promise, Delay or Deferred generally refer to same synchronisation mechanism where an object acts as a proxy for a yet unknown result. When the result is discovered, promises hold some code which then gets executed. +In some languages however, there is a subtle difference between what is a Future and a Promise. +“A ‘Future’ is a read-only reference to a yet-to-be-computed value”. +“A ‘Promise’ is a pretty much the same except that you can write to it as well.” -In other words, you can read from both Futures and Promises, but you can only write to Promises. You can get the Future associated with a Promise by calling the future method on it, but conversion in the other direction is not possible. Another way to look at it would be, if you Promise something, you are responsible for keeping it, but if someone else makes a Promise to you, you expect them to honor it in Future. +In other words, a future is a read-only window to a value written into a promise. You can get the Future associated with a Promise by calling the future method on it, but conversion in the other direction is not possible. Another way to look at it would be, if you Promise something, you are responsible for keeping it, but if someone else makes a Promise to you, you expect them to honor it in Future. -More technically, in Scala, “SIP-14 – Futures and Promises” defines them as follows: -A future is as a placeholder object for a result that does not yet exist. +More technically, in Scala, “SIP-14 – Futures and Promises” defines them as follows: +A future is a placeholder object for a result that does not yet exist. A promise is a writable, single-assignment container, which completes a future. Promises can complete the future with a result to indicate success, or with an exception to indicate failure. +An important difference between Scala and Java (6) futures is that Scala futures were asynchronous in nature. Java's future, at least till Java 6, were blocking. Java 7 introduced the Futures as the asynchronous construct which are more familiar in the distributed computing world. + -C# also makes the distinction between futures and promises. In C#, futures are implemented as Task<T> and in fact in earlier versions of the Task Parallel Library futures were implemented with a class Future<T> which later became Task<T>. The result of the future is available in the readonly property Task<T>.Result which returns T +In Java 8, the Future<T> interface has methods to check if the computation is complete, to wait for its completion, and to retrieve the result of the computation when it is complete. CompletableFutures can be thought of as Promises as their value can be set. But it also implements the Future interface and therefore it can be used as a Future too. Promises can be thought of as a future with a public set method which the caller (or anybody else) can use to set the value of the future. -In Javascript world, Jquery introduces a notion of Deferred objects which are used to represent a unit of work which is not yet finished. Deferred object contains a promise object which represent the result of that unit of work. Promises are values returned by a function, while the deferred object can be canceled by its caller. +In Javascript world, Jquery introduces a notion of Deferred objects which are used to represent a unit of work which is not yet finished. Deferred object contains a promise object which represent the result of that unit of work. Promises are values returned by a function, while the deferred object can be canceled by its caller. -In Java 8, the Future<T> interface has methods to check if the computation is complete, to wait for its completion, and to retrieve the result of the computation when it is complete. CompletableFutures can be thought of as Promises as their value can be set. But it also implements the Future interface and therefore it can be used as a Future too. Promises can be thought of as a future with a public set method which the caller (or anybody else) can use to set the value of the future. +C# also makes the distinction between futures and promises. In C#, futures are implemented as Task<T> and in fact in earlier versions of the Task Parallel Library futures were implemented with a class Future<T> which later became Task<T>. The result of the future is available in the readonly property Task<T>.Result which returns T. Tasks are asynchronous in C#. # Semantics of Execution -Over the years promises and futures have been implemented in different programming languages and created a buzz in parallel computing world. We will take a look at some of the programming languages who designed frameworks to enhance performance of applications using Promises and futures. +Over the years promises and futures have been implemented in different programming languages. Different languages chose to implement futures/promises in a different way. In this section, we try to introduce some different ways in which futures and promises actually get executed and resolved underneath their APIs. -## Fork-Join +## Thread Pools -Doing things in parallel is usually an effective way of doing things in modern systems. The systems are getting more and more capable of running more than one things at once, and the latency associated with doing things in a distributed environment is not going away anytime soon. Inside the JVM, threads are a basic unit of concurrency. Threads are independent, heap-sharing execution contexts. Threads are generally considered to be lightweight when compared to a process, and can share both code and data. The cost of context switching between threads is cheap. But, even if we claim that threads are lightweight, the cost of creation and destruction of threads in a long running threads can add up to something significant. A practical way is address this problem is to manage a pool of worker threads. +Thread pools are a group of ready, idle threads which can be given work. They help with the overhead of worker creation, which can add up in a long running process. The actual implementation may vary everywhere, but what differentiates thread pools is the number of threads it uses. It can either be fixed, or dynamic. Advantage of having a fixed thread pool is that it degrades gracefully : the amount of load a system can handle is fixed, and using fixed thread pool, we can effectively limit the amount of load it is put under. Granularity of a thread pool is the number of threads it instantiates. -In Java executor is an object which executes the Runnable tasks. Executors provides a way of abstracting out how the details of how a task will actually run. These details, like selecting a thread to run the task, how the task is scheduled are managed by the object implementing the Executor interface. Threads are an example of a Runnable in java. Executors can be used instead of creating a thread explicitly. +In Java executor is an object which executes the Runnable tasks. Executors provides a way of abstracting out how the details of how a task will actually run. These details, like selecting a thread to run the task, how the task is scheduled are managed by the object implementing the Executor interface. Threads are an example of a Runnable in java. Executors can be used instead of creating a thread explicitly. -Similar to Executor, there is an ExecutionContext as part of scala.concurrent. The basic intent behind it is same as an Executor : it is responsible for executing computations. How it does it can is opaque to the caller. It can create a new thread, use a pool of threads or run it on the same thread as the caller, although the last option is generally not recommended. Scala.concurrent package comes with an implementation of ExecutionContext by default, which is a global static thread pool. +Similar to Executor, there is an ExecutionContext as part of scala.concurrent. The basic intent behind it is same as an Executor : it is responsible for executing computations. How it does it can is opaque to the caller. It can create a new thread, use a pool of threads or run it on the same thread as the caller, although the last option is generally not recommended. Scala.concurrent package comes with an implementation of ExecutionContext by default, which is a global static thread pool. -ExecutionContext.global is an execution context backed by a ForkJoinPool. ForkJoin is a thread pool implementation designed to take advantage of a multiprocessor environment. What makes fork join unique is that it implements a type of work-stealing algorithm : idle threads pick up work from still busy threads. ForkJoinPool manages a small number of threads, usually limited to the number of processor cores available. It is possible to increase the number of threads, if all of the available threads are busy and wrapped inside a blocking call, although such situation would typically come with a bad system design. ForkJoin framework work to avoid pool-induced deadlock and minimize the amount of time spent switching between the threads. +ExecutionContext.global is an execution context backed by a ForkJoinPool. ForkJoin is a thread pool implementation designed to take advantage of a multiprocessor environment. What makes fork join unique is that it implements a type of work-stealing algorithm : idle threads pick up work from still busy threads. ForkJoinPool manages a small number of threads, usually limited to the number of processor cores available. It is possible to increase the number of threads, if all of the available threads are busy and wrapped inside a blocking call, although such situation would be highly undesirable for most of the systems. ForkJoin framework work to avoid pool-induced deadlock and minimize the amount of time spent switching between the threads. -Futures are generally a good way to reason about asynchronous code. A good way to call a webservice, add a block of code to do something when you get back the response, and move on without waiting for the response. They’re also a good framework to reason about concurrency as they can be executed in parallel, waited on, are composable, immutable once written and most importantly, are non blocking. in Scala, futures (and promises) are based on ExecutionContext. +In Scala, Futures are generally a good framework to reason about concurrency as they can be executed in parallel, waited on, are composable, immutable once written and most importantly, are non blocking (although it is possible to have blocking futures, like Java 6). In Scala, futures (and promises) are based on ExecutionContext. Using ExecutionContext gives users flexibility to implement their own ExecutionContext if they need a specific behavior, like blocking futures. The default ForkJoin pool works well in most of the scenarios. +Scala futures api expects an ExecutionContext to be passed along. This parameter is implicit, and usually ExecutionContext.global. An example : -In Scala, futures are created using an ExecutionContext. This gives the users flexibility to implement their own ExecutionContext if they need a specific behavior, like blocking futures. The default ForkJoin pool works well in most of the scenarios. Futures in scala are placeholders for a yet unknown value. A promise then can be thought of as a way to provide that value. A promise p completes the future returned by p.future. +```scala +implicit val ec = ExecutionContext.global +val f : Future[String] = Future { “hello world” } +``` -Scala futures api expects an ExecutionContext to be passed along. This parameter is implicit, and usually ExecutionContext.global. An example : +In this example, the global execution context is used to asynchronously run the created future. Taking another example, -<figure class="main-container"> - <img src="./2.png" alt="timeline" /> -</figure> +```scala +implicit val ec = ExecutionContext.global -In this example, the global execution context is used to asynchronously run the created future. Taking another example, +val f = Future { + Http("http://api.fixed.io/latest?base=USD").asString +} + +f.onComplete { + case success(response) => println(response.body) + case Failure(t) => println(t) +} +``` -<figure class="main-container"> - <img src="./3.png" alt="timeline" /> -</figure> It is generally a good idea to use callbacks with Futures, as the value may not be available when you want to use it. @@ -121,16 +126,15 @@ So, how does it all work together ? As we mentioned, Futures require an ExecutionContext, which is an implicit parameter to virtually all of the futures API. This ExecutionContext is used to execute the future. Scala is flexible enough to let users implement their own Execution Contexts, but let’s talk about the default ExecutionContext, which is a ForkJoinPool. -ForkJoinPool is ideal for many small computations that spawn off and then come back together. Scala’s ForkJoinPool requires the tasks submitted to it to be a ForkJoinTask. The tasks submitted to the global ExecutionContext is quietly wrapped inside a ForkJoinTask and then executed. ForkJoinPool also supports a possibly blocking task, using ManagedBlock method which creates a spare thread if required to ensure that there is sufficient parallelism if the current thread is blocked. To summarize, ForkJoinPool is an really good general purpose ExecutionContext, which works really well in most of the scenarios. - +ForkJoinPool is ideal for many small computations that spawn off and then come back together. Scala’s ForkJoinPool requires the tasks submitted to it to be a ForkJoinTask. The tasks submitted to the global ExecutionContext is quietly wrapped inside a ForkJoinTask and then executed. ForkJoinPool also supports a possibly blocking task, using ManagedBlock method which creates a spare thread if required to ensure that there is sufficient parallelism if the current thread is blocked. To summarize, ForkJoinPool is an really good general purpose ExecutionContext, which works really well in most of the scenarios. ## Event Loops -Modern systems typically rely on many other systems to provide the functionality they do. There’s a file system underneath, a database system, and other web services to rely on for the information. Interaction with these components typically involves a period where we’re doing nothing but waiting for the response back. This is single largest waste of computing resources. +Modern systems typically rely on many other systems to provide the functionality they do. There’s a file system underneath, a database system, and other web services to rely on for the information. Interaction with these components typically involves a period where we’re doing nothing but waiting for the response back. This is single largest waste of computing resources. -Javascript is a single threaded asynchronous runtime. Now, conventionally async programming is generally associated with multi-threading, but we’re not allowed to create new threads in Javascript. Instead, asynchronicity in Javascript is achieved using an event-loop mechanism. +Javascript is a single threaded asynchronous runtime. Now, conventionally async programming is generally associated with multi-threading, but we’re not allowed to create new threads in Javascript. Instead, asynchronicity in Javascript is achieved using an event-loop mechanism. Javascript has historically been used to interact with the DOM and user interactions in the browser, and thus an event-driven programming model was a natural fit for the language. This has scaled up surprisingly well in high throughput scenarios in NodeJS. @@ -143,67 +147,109 @@ A typical Javascript engine has a few basic components. They are : - **Heap** Used to allocate memory for objects - **Stack** -Function call frames go into a stack from where they’re picked up from top to be executed. +Function call frames go into a stack from where they’re picked up from top to be executed. - **Queue** - A message queue holds the messages to be processed. + A message queue holds the messages to be processed. -Each message has a callback function which is fired when the message is processed. These messages can be generated by user actions like button clicks or scrolling, or by actions like HTTP requests, request to a database to fetch records or reading/writing to a file. +Each message has a callback function which is fired when the message is processed. These messages can be generated by user actions like button clicks or scrolling, or by actions like HTTP requests, request to a database to fetch records or reading/writing to a file. Separating when a message is queued from when it is executed means the single thread doesn’t have to wait for an action to complete before moving on to another. We attach a callback to the action we want to do, and when the time comes, the callback is run with the result of our action. Callbacks work good in isolation, but they force us into a continuation passing style of execution, what is otherwise known as Callback hell. -<figure class="main-container"> - <img src="./4.png" alt="timeline" /> -</figure> -**Programs must be written for people to read, and only incidentally for machines to execute.** - *Harold Abelson and Gerald Jay Sussman* +```javascript + +getData = function(param, callback){ + $.get('http://example.com/get/'+param, + function(responseText){ + callback(responseText); + }); +} + +getData(0, function(a){ + getData(a, function(b){ + getData(b, function(c){ + getData(c, function(d){ + getData(d, function(e){ + + }); + }); + }); + }); +}); + +``` + +<center><h4> VS </h4></center> + +```javascript + +getData = function(param, callback){ + return new Promise(function(resolve, reject) { + $.get('http://example.com/get/'+param, + function(responseText){ + resolve(responseText); + }); + }); +} -Promises are an abstraction which make working with async operations in javascript much more fun. Moving on from a continuation passing style, where you specify what needs to be done once the action is done, the callee simply returns a Promise object. This inverts the chain of responsibility, as now the caller is responsible for handling the result of the promise when it is settled. +getData(0).then(getData) + .then(getData). + then(getData). + then(getData); -The ES2015 spec specifies that “promises must not fire their resolution/rejection function on the same turn of the event loop that they are created on.” This is an important property because it ensures deterministic order of execution. Also, once a promise is fulfilled or failed, the promise’s value MUST not be changed. This ensures that a promise cannot be resolved more than once. + +``` + +> **Programs must be written for people to read, and only incidentally for machines to execute.** - *Harold Abelson and Gerald Jay Sussman* + + +Promises are an abstraction which make working with async operations in javascript much more fun. Callbacks lead to inversion of control, which is difficult to reason about at scale. Moving on from a continuation passing style, where you specify what needs to be done once the action is done, the callee simply returns a Promise object. This inverts the chain of responsibility, as now the caller is responsible for handling the result of the promise when it is settled. + +The ES2015 spec specifies that “promises must not fire their resolution/rejection function on the same turn of the event loop that they are created on.” This is an important property because it ensures deterministic order of execution. Also, once a promise is fulfilled or failed, the promise’s value MUST not be changed. This ensures that a promise cannot be resolved more than once. Let’s take an example to understand the promise resolution workflow as it happens inside the Javascript Engine. -Suppose we execute a function, here g() which in turn, calls function f(). Function f returns a promise, which, after counting down for 1000 ms, resolves the promise with a single value, true. Once f gets resolved, a value true or false is alerted based on the value of the promise. +Suppose we execute a function, here g() which in turn, calls function f(). Function f returns a promise, which, after counting down for 1000 ms, resolves the promise with a single value, true. Once f gets resolved, a value true or false is alerted based on the value of the promise. -<figure class="main-container"> - <img src="./5.png" alt="timeline" /> +<figure> + <img src="./images/5.png" alt="timeline" /> </figure> Now, javascript’s runtime is single threaded. This statement is true, and not true. The thread which executes the user code is single threaded. It executes what is on top of the stack, runs it to completion, and then moves onto what is next on the stack. But, there are also a number of helper threads which handle things like network or timer/settimeout type events. This timing thread handles the counter for setTimeout. -<figure class="main-container"> - <img src="./6.png" alt="timeline" /> +<figure> + <img src="./images/6.png" alt="timeline" /> </figure> Once the timer expires, the timer thread puts a message on the message queue. The queued up messages are then handled by the event loop. The event loop as described above, is simply an infinite loop which checks if a message is ready to be processed, picks it up and puts it on the stack for it’s callback to be executed. -<figure class="main-container"> - <img src="./7.png" alt="timeline" /> +<figure> + <img src="./images/7.png" alt="timeline" /> </figure> -Here, since the future is resolved with a value of true, we are alerted with a value true when the callback is picked up for execution. +Here, since the future is resolved with a value of true, we are alerted with a value true when the callback is picked up for execution. -<figure class="main-container"> - <img src="./8.png" alt="timeline" /> +<figure> + <img src="./images/8.png" alt="timeline" /> </figure> Some finer details : We’ve ignored the heap here, but all the functions, variables and callbacks are stored on heap. -As we’ve seen here, even though Javascript is said to be single threaded, there are number of helper threads to help main thread do things like timeout, UI, network operations, file operations etc. -Run-to-completion helps us reason about the code in a nice way. Whenever a function starts, it needs to finish before yielding the main thread. The data it accesses cannot be modified by someone else. This also means every function needs to finish in a reasonable amount of time, otherwise the program seems hung. This makes Javascript well suited for I/O tasks which are queued up and then picked up when finished, but not for data processing intensive tasks which generally take long time to finish. +As we’ve seen here, even though Javascript is said to be single threaded, there are number of helper threads to help main thread do things like timeout, UI, network operations, file operations etc. +Run-to-completion helps us reason about the code in a nice way. Whenever a function starts, it needs to finish before yielding the main thread. The data it accesses cannot be modified by someone else. This also means every function needs to finish in a reasonable amount of time, otherwise the program seems hung. This makes Javascript well suited for I/O tasks which are queued up and then picked up when finished, but not for data processing intensive tasks which generally take long time to finish. We haven’t talked about error handling, but it gets handled the same exact way, with the error callback being called with the error object the promise is rejected with. -Event loops have proven to be surprisingly performant. When network servers are designed around multithreading, as soon as you end up with a few hundred concurrent connections, the CPU spends so much of its time task switching that you start to lose overall performance. Switching from one thread to another has overhead which can add up significantly at scale. Apache used to choke even as low as a few hundred concurrent users when using a thread per connection while Node can scale up to a 100,000 concurrent connections based on event loops and asynchronous IO. +Event loops have proven to be surprisingly performant. When network servers are designed around multithreading, as soon as you end up with a few hundred concurrent connections, the CPU spends so much of its time task switching that you start to lose overall performance. Switching from one thread to another has overhead which can add up significantly at scale. Apache used to choke even as low as a few hundred concurrent users when using a thread per connection while Node can scale up to a 100,000 concurrent connections based on event loops and asynchronous IO. -##Thread Model +## Thread Model -Oz programming language introduced an idea of dataflow concurrency model. In Oz, whenever the program comes across an unbound variable, it waits for it to be resolved. This dataflow property of variables helps us write threads in Oz that communicate through streams in a producer-consumer pattern. The major benefit of dataflow based concurrency model is that it’s deterministic - same operation called with same parameters always produces the same result. It makes it a lot easier to reason about concurrent programs, if the code is side-effect free. +Oz programming language introduced an idea of dataflow concurrency model. In Oz, whenever the program comes across an unbound variable, it waits for it to be resolved. This dataflow property of variables helps us write threads in Oz that communicate through streams in a producer-consumer pattern. The major benefit of dataflow based concurrency model is that it’s deterministic - same operation called with same parameters always produces the same result. It makes it a lot easier to reason about concurrent programs, if the code is side-effect free. Alice ML is a dialect of Standard ML with support for lazy evaluation, concurrent, distributed, and constraint programming. The early aim of Alice project was to reconstruct the functionalities of Oz programming language on top of a typed programming language. Building on the Standard ML dialect, Alice also provides concurrency features as part of the language through the use of a future type. Futures in Alice represent an undetermined result of a concurrent operation. Promises in Alice ML are explicit handles for futures. @@ -214,96 +260,346 @@ Any expression in Alice can be evaluated in it's own thread using spawn keyword. Alice also allows for lazy evaluation of expressions. Expressions preceded with the lazy keyword are evaluated to a lazy future. The lazy future is evaluated when it is needed. If the computation associated with a concurrent or lazy future ends with an exception, it results in a failed future. Requesting a failed future does not block, it simply raises the exception that was the cause of the failure. -#Implicit vs. Explicit Promises +# Implicit vs. Explicit Promises + + +We define Implicit promises as ones where we don’t have to manually trigger the computation vs Explicit promises where we have to trigger the resolution of future manually, either by calling a start function or by requiring the value. This distinction can be understood in terms of what triggers the calculation : With Implicit promises, the creation of a promise also triggers the computation, while with Explicit futures, one needs to triggers the resolution of a promise. This trigger can in turn be explicit, like calling a start method, or implicit, like lazy evaluation where the first use of a promise’s value triggers its evaluation. -We define Implicit promises as ones where we don’t have to manually trigger the computation vs Explicit promises where we have to trigger the resolution of future manually, either by calling a start function or by requiring the value. This distinction can be understood in terms of what triggers the calculation : With Implicit promises, the creation of a promise also triggers the computation, while with Explicit futures, one needs to triggers the resolution of a promise. This trigger can in turn be explicit, like calling a start method, or implicit, like lazy evaluation where the first use of a promise’s value triggers its evaluation. +The idea for explicit futures were introduced in the Baker and Hewitt paper. They’re a little trickier to implement, and require some support from the underlying language, and as such they aren’t that common. The Baker and Hewitt paper talked about using futures as placeholders for arguments to a function, which get evaluated in parallel, but when they’re needed. MultiLisp also had a mechanism to delay the evaluation of the future to the time when it's value is first used, using the defer construct. Lazy futures in Alice ML have a similar explicit invocation mechanism, the first thread touching a future triggers its evaluation. +An example for Explicit Futures would be (from AliceML): -The idea for explicit futures were introduced in the Baker and Hewitt paper. They’re a little trickier to implement, and require some support from the underlying language, and as such they aren’t that common. The Baker and Hewitt paper talked about using futures as placeholders for arguments to a function, which get evaluated in parallel, but when they’re needed. Also, lazy futures in Alice ML have a similar explicit invocation mechanism, the first thread touching a future triggers its evaluation. +``` +fun enum n = lazy n :: enum (n+1) + +``` + +This example generates an infinite stream of integers and if stated when it is created, will compete for the system resources. + +Implicit futures were introduced originally by Friedman and Wise in a paper in 1978. The ideas presented in that paper inspired the design of promises in MultiLisp. Futures are also implicit in Scala and Javascript, where they’re supported as libraries on top of the core languages. Implicit futures can be implemented this way as they don’t require support from language itself. Alice ML’s concurrent futures are also an example of implicit invocation. + +For example + +```scala + +val f = Future { + Http("http://api.fixer.io/latest?base=USD").asString +} + +f onComplete { + case Success(response) => println(response.body) + case Failure(t) => println(t) +} + +``` + +This sends the HTTP call as soon as it the Future is created. In Scala, although the futures are implicit, Promises can be used to have an explicit-like behavior. This is useful in a scenario where we need to stack up some computations and then resolve the Promise. + +An Example : + +```scala + +val p = Promise[Foo]() + +p.future.map( ... ).filter( ... ) foreach println + +p.complete(new Foo) + +``` + +Here, we create a Promise, and complete it later. In between we stack up a set of computations which get executed once the promise is completed. -Implicit futures were introduced originally by Friedman and Wise in a paper in 1978. The ideas presented in that paper inspired the design of promises in MultiLisp. Futures are also implicit in Scala and Javascript, where they’re supported as libraries on top of the core languages. Implicit futures can be implemented this way as they don’t require support from language itself. Alice ML’s concurrent futures are also an example of implicit invocation. # Promise Pipelining + One of the criticism of traditional RPC systems would be that they’re blocking. Imagine a scenario where you need to call an API ‘a’ and another API ‘b’, then aggregate the results of both the calls and use that result as a parameter to another API ‘c’. Now, the logical way to go about doing this would be to call A and B in parallel, then once both finish, aggregate the result and call C. Unfortunately, in a blocking system, the way to go about is call a, wait for it to finish, call b, wait, then aggregate and call c. This seems like a waste of time, but in absence of asynchronicity, it is impossible. Even with asynchronicity, it gets a little difficult to manage or scale up the system linearly. Fortunately, we have promises. -<figure class="main-container"> - <img src="./9.png" alt="timeline" /> + +<figure> + <img src="./images/p-1.png" alt="timeline" /> +</figure> + +<figure> + <img src="./images/p-2.png" alt="timeline" /> </figure> -Futures/Promises can be passed along, waited upon, or chained and joined together. These properties helps make life easier for the programmers working with them. This also reduces the latency associated with distributed computing. Promises enable dataflow concurrency, which is also deterministic, and easier to reason. +Futures/Promises can be passed along, waited upon, or chained and joined together. These properties helps make life easier for the programmers working with them. This also reduces the latency associated with distributed computing. Promises enable dataflow concurrency, which is also deterministic, and easier to reason. + +The history of promise pipelining can be traced back to the call-streams in Argus. In Argus, Call streams are a mechanism for communication between distributed components. The communicating entities, a sender and a receiver are connected by a stream, and sender can make calls to receiver over it. Streams can be thought of as RPC, except that these allow callers to run in parallel with the receiver while processing the call. When making a call in Argus, the caller receives a promise for the result. In the paper on Promises by Liskov and Shrira, they mention that having integrated Promises into call streams, next logical step would be to talk about stream composition. This means arranging streams into pipelines where output of one stream can be used as input of the next stream. They talk about composing streams using fork and coenter. + +Channels in Joule were a similar idea, providing a channel which connects an acceptor and a distributor. Joule was a direct ancestor to E language, and talked about it in more detail. + +``` + +t3 := (x <- a()) <- c(y <- b()) + +t1 := x <- a() +t2 := y <- b() +t3 := t1 <- c(t2) + +``` + +Without pipelining in E, this call will require three round trips. First to send a() to x, then b() to y then finally c to the result t1 with t2 as an argument. But with pipelining, the later messages can be sent with promises as result of earlier messages as argument. This allowed sending all the messages together, thereby saving the costly round trips. This is assuming x and y are on the same remote machine, otherwise we can still evaluate t1 and t2 parallely. + + +Notice that this pipelining mechanism is different from asynchronous message passing, as in asynchronous message passing, even if t1 and t2 get evaluated in parallel, to resolve t3 we still wait for t1 and t2 to be resolved, and send it again in another call to the remote machine. + -The history of promise pipelining can be traced back to the call-streams in Argus and channels in Joule. In Argus, Call streams are a mechanism for communication between distributed components. The communicating entities, a sender and a receiver are connected by a stream, and sender can make calls to receiver over it. Streams can be thought of as RPC, except that these allow callers to run in parallel with the receiver while processing the call. When making a call in Argus, the caller receives a promise for the result. In the paper on Promises by Liskov and Shrira, they mention that having integrated futures into call streams, next logical step would be to talk about stream composition. This means arranging streams into pipelines where output of one stream can be used as input of the next stream. They talk about composing streams using fork and coenter. +Modern promise specifications, like one in Javascript comes with methods which help working with promise pipelining easier. In javascript, a Promises.all method is provided, which takes in an iterable and returns a new Promise which gets resolved when all the promises in the iterable get resolved. There’s also a race method, which returns a promise which is resolved when the first promise in the iterable gets resolved. +```javascript -Modern promise specifications, like one in Javascript comes with methods which help working with promise pipelining easier. In javascript, a Promises.all method is provided, which takes in an iterable over Promises, and returns a new Promise which gets resolved when all the promises in the iterable get resolved. There’s also a race method, which returns a promise which is resolved when the first promise in the iterable gets resolved. +var a = Promise.resolve(1); +var b = new Promise(function (resolve, reject) { + setTimeout(resolve, 100, 2); +}); +Promise.all([p1, p2]).then(values => { + console.log(values); // [1,2] +}); + +Promise.race([p1, p2]).then(function(value) { + console.log(value); // 1 +}); + +``` + +In Scala, futures have a onSuccess method which acts as a callback to when the future is complete. This callback itself can be used to sequentially chain futures together. But this results in bulkier code. Fortunately, Scala api comes with combinators which allow for easier combination of results from futures. Examples of combinators are map, flatmap, filter, withFilter. -In scala, futures have a onSuccess method which acts as a callback to when the future is complete. This callback itself can be used to sequentially chain futures together. But this results in bulkier code. Fortunately, Scala api comes with combinators which allow for easier combination of results from futures. Examples of combinators are map, flatmap, filter, withFilter. # Handling Errors -In a synchronous programming model, the most logical way of handling errors is a try...catch block. +If world would have run without errors we would rejoice in unison, but it is not the case in programming world as well. When you run a program you either receive an expected output or an error. Error can be defined as wrong output or an exception. In a synchronous programming model, the most logical way of handling errors is a try...catch block. -<figure class="main-container"> - <img src="./10.png" alt="timeline" /> -</figure> +```javascript +try{ + do something1; + do something2; + do something3; + ... +} catch ( exception ){ + HandleException; +} -Unfortunately, the same thing doesn’t directly translate to asynchronous code. +``` -<figure class="main-container"> - <img src="./11.png" alt="timeline" /> -</figure> +Unfortunately, the same thing doesn’t directly translate to asynchronous code. -In javascript world, some patterns emerged, most noticeably the error-first callback style, also adopted by Node. Although this works, but it is not very composable, and eventually takes us back to what is called callback hell. Fortunately, Promises come to the rescue. +```javascript -Although most of the earlier papers did not talk about error handling, the Promises paper by Liskov and Shrira did acknowledge the possibility of failure in a distributed environment. They talked about propagation of exceptions from the called procedure to the caller and also about call streams, and how broken streams could be handled. E language also talked about broken promises and setting a promise to the exception of broken references. +foo = doSomethingAsync(); -In modern languages, Promises generally come with two callbacks. One to handle the success case and other to handle the failure. +try{ + foo(); + // This doesn’t work as the error might not have been thrown yet +} catch ( exception ){ + handleException; +} -<figure class="main-container"> - <img src="./12.png" alt="timeline" /> -</figure> -In Javascript, Promises also have a catch method, which help deal with errors in a composition. Exceptions in promises behave the same way as they do in a synchronous block of code : they jump to the nearest exception handler. +``` -<figure class="main-container"> - <img src="./13.png" alt="timeline" /> -</figure> + +Although most of the earlier papers did not talk about error handling, the Promises paper by Liskov and Shrira did acknowledge the possibility of failure in a distributed environment. To put this in Argus's perspective, the 'claim' operation waits until the promise is ready. Then it returns normally if the call terminated normally, and otherwise it signals the appropriate 'exception', e.g., + +``` +y: real := pt$claim(x) + except when foo: ... + when unavailable(s: string): . + when failure(s: string): . . + end + +``` +Here x is a promise object of type pt; the form pi$claim illustrates the way Argus identifies an operation of a type by concatenating the type name with the operation name. When there are communication problems, RPCs in Argus terminate either with the 'unavailable' exception or the 'failure' exception. +'Unavailable' - means that the problem is temporary, e.g., communication is impossible right now. +'Failure' - means that the problem is permanent, e.g., the handler’s guardian does not exist. +Thus stream calls (and sends) whose replies are lost because of broken streams will terminate with one of these exceptions. Both exceptions have a string argument that explains the reason for the failure, e.g., future(“handler does not exist”), or unavailable(“cannot communicate”). Since any call can fail, every handler can raise the exceptions failure and unavailable. In this paper they also talked about propagation of exceptions from the called procedure to the caller. In paper about E language they talk about broken promises and setting a promise to the exception of broken references. + +In modern languages like Scala, Promises generally come with two callbacks. One to handle the success case and other to handle the failure. e.g. + +```scala + +f onComplete { + case Success(data) => handleSuccess(data) + case Failure(e) => handleFailure(e) +} +``` + +In Scala, the Try type represents a computation that may either result in an exception, or return a successfully computed value. For example, Try[Int] represents a computation which can either result in Int if it's successful, or return a Throwable if something is wrong. + +```scala + +val a: Int = 100 +val b: Int = 0 +def divide: Try[Int] = Try(a/b) + +divide match { + case Success(v) => + println(v) + case Failure(e) => + println(e) // java.lang.ArithmeticException: / by zero +} + +``` + +Try type can be pipelined, allowing for catching exceptions and recovering from them along the way. + +#### In Javascript +```javascript + +promise.then(function (data) { + // success callback + console.log(data); +}, function (error) { + // failure callback + console.error(error); +}); + +``` +Scala futures exception handling: + +When asynchronous computations throw unhandled exceptions, futures associated with those computations fail. Failed futures store an instance of Throwable instead of the result value. Futures provide the onFailure callback method, which accepts a PartialFunction to be applied to a Throwable. TimeoutException, scala.runtime.NonLocalReturnControl[] and ExecutionException exceptions are treated differently + +Scala promises exception handling: + +When failing a promise with an exception, three subtypes of Throwables are handled specially. If the Throwable used to break the promise is a scala.runtime.NonLocalReturnControl, then the promise is completed with the corresponding value. If the Throwable used to break the promise is an instance of Error, InterruptedException, or scala.util.control.ControlThrowable, the Throwable is wrapped as the cause of a new ExecutionException which, in turn, is failing the promise. + + +To handle errors with asynchronous methods and callbacks, the error-first callback style ( which we've seen before, also adopted by Node) is the most common convention. Although this works, but it is not very composable, and eventually takes us back to what is called callback hell. Fortunately, Promises allow asynchronous code to apply structured error handling. Promises .then method takes in two callbacks, a onFulfilled to handle when a promise is resolved successfully and a onRejected to handle if the promise is rejected. + +```javascript + +var p = new Promise(function(resolve, reject){ + resolve(100); +}); + +p.then(function(data){ + console.log(data); // 100 +},function(error){ + console.err(error); +}); + +var q = new Promise(function(resolve, reject){ + reject(new Error( + {'message':'Divide by zero'} + )); +}); + +q.then(function(data){ + console.log(data); +},function(error){ + console.err(error);// {'message':'Divide by zero'} +}); + +``` + + +Promises also have a catch method, which work the same way as onFailure callback, but also help deal with errors in a composition. Exceptions in promises behave the same way as they do in a synchronous block of code : they jump to the nearest exception handler. + + +```javascript +function work(data) { + return Promise.resolve(data+"1"); +} + +function error(data) { + return Promise.reject(data+"2"); +} + +function handleError(error) { + return error +"3"; +} + + +work("") +.then(work) +.then(error) +.then(work) // this will be skipped +.then(work, handleError) +.then(check); + +function check(data) { + console.log(data == "1123"); + return Promise.resolve(); +} + +``` The same behavior can be written using catch block. -<figure class="main-container"> - <img src="./14.png" alt="timeline" /> -</figure> +```javascript + +work("") +.then(work) +.then(error) +.then(work) +.catch(handleError) +.then(check); +function check(data) { + console.log(data == "1123"); + return Promise.resolve(); +} -#Futures and Promises in Action +``` -##Twitter Finagle +# Futures and Promises in Action -Finagle is a protocol-agnostic, asynchronous RPC system for the JVM that makes it easy to build robust clients and servers in Java, Scala, or any JVM-hosted language. It uses idea of Futures to encapsulate concurrent tasks and are analogous to threads, but even more lightweight. +## Twitter Finagle -##Correctables -Correctables were introduced by Rachid Guerraoui, Matej Pavlovic, and Dragos-Adrian Seredinschi at OSDI ‘16, in a paper titled Incremental Consistency Guarantees for Replicated Objects. As the title suggests, Correctables aim to solve the problems with consistency in replicated objects. They provide incremental consistency guarantees by capturing successive changes to the value of a replicated object. Applications can opt to receive a fast but possibly inconsistent result if eventual consistency is acceptable, or to wait for a strongly consistent result. Correctables API draws inspiration from, and builds on the API of Promises. Promises have a two state model to represent an asynchronous task, it starts in blocked state and proceeds to a ready state when the value is available. This cannot represent the incremental nature of correctables. Instead, Correctables have a updating state when it starts. From there on, it remains in updating state during intermediate updates, and when the final result is available, it transitions to final state. If an error occurs in between, it moves into an error state. Each state change triggers a callback. +Finagle is a protocol-agnostic, asynchronous RPC system for the JVM that makes it easy to build robust clients and servers in Java, Scala, or any JVM-hosted language. It uses Futures to encapsulate concurrent tasks. Finagle +introduces two other abstractions built on top of Futures to reason about distributed software : -<figure class="main-container"> - <img src="./15.png" alt="timeline" /> +- ** Services ** are asynchronous functions which represent system boundaries. + +- ** Filters ** are application-independent blocks of logic like handling timeouts and authentication. + +In Finagle, operations describe what needs to be done, while the actual execution is left to be handled by the runtime. The runtime comes with a robust implementation of connection pooling, failure detection and recovery and load balancers. + +Example of a Service: + + +```scala + +val service = new Service[HttpRequest, HttpResponse] { + def apply(request: HttpRequest) = + Future(new DefaultHttpResponse(HTTP_1_1, OK)) +} + +``` +A timeout filter can be implemented as : + +```scala + +def timeoutFilter(d: Duration) = + { (req, service) => service(req).within(d) } + +``` + + +## Correctables +Correctables were introduced by Rachid Guerraoui, Matej Pavlovic, and Dragos-Adrian Seredinschi at OSDI ‘16, in a paper titled Incremental Consistency Guarantees for Replicated Objects. As the title suggests, Correctables aim to solve the problems with consistency in replicated objects. They provide incremental consistency guarantees by capturing successive changes to the value of a replicated object. Applications can opt to receive a fast but possibly inconsistent result if eventual consistency is acceptable, or to wait for a strongly consistent result. Correctables API draws inspiration from, and builds on the API of Promises. Promises have a two state model to represent an asynchronous task, it starts in blocked state and proceeds to a ready state when the value is available. This cannot represent the incremental nature of correctables. Instead, Correctables have a updating state when it starts. From there on, it remains in updating state during intermediate updates, and when the final result is available, it transitions to final state. If an error occurs in between, it moves into an error state. Each state change triggers a callback. + +<figure> + <img src="./images/15.png" alt="timeline" /> </figure> -##Folly Futures + +## Folly Futures Folly is a library by Facebook for asynchronous C++ inspired by the implementation of Futures by Twitter for Scala. It builds upon the Futures in the C++11 Standard. Like Scala’s futures, they also allow for implementing a custom executor which provides different ways of running a Future (thread pool, event loop etc). -##NodeJS Fiber -Fibers provide coroutine support for v8 and node. Applications can use Fibers to allow users to write code without using a ton of callbacks, without sacrificing the performance benefits of asynchronous IO. Think of fibers as light-weight threads for nodejs where the scheduling is in the hands of the programmer. The node-fibers library doesn’t recommend using raw API and code together without any abstractions, and provides a Futures implementation which is ‘fiber-aware’. +## NodeJS Fiber +Fibers provide coroutine support for v8 and node. Applications can use Fibers to allow users to write code without using a ton of callbacks, without sacrificing the performance benefits of asynchronous IO. Think of fibers as light-weight threads for NodeJs where the scheduling is in the hands of the programmer. The node-fibers library doesn’t recommend using raw API and code together without any abstractions, and provides a Futures implementation which is ‘fiber-aware’. + -## References +# References {% bibliography --file futures %} diff --git a/chapter/2/images/1.png b/chapter/2/images/1.png Binary files differnew file mode 100644 index 0000000..569c326 --- /dev/null +++ b/chapter/2/images/1.png diff --git a/chapter/2/images/15.png b/chapter/2/images/15.png Binary files differnew file mode 100644 index 0000000..15a2a81 --- /dev/null +++ b/chapter/2/images/15.png diff --git a/chapter/2/5.png b/chapter/2/images/5.png Binary files differindex b86de04..b86de04 100644 --- a/chapter/2/5.png +++ b/chapter/2/images/5.png diff --git a/chapter/2/6.png b/chapter/2/images/6.png Binary files differindex aaafdbd..aaafdbd 100644 --- a/chapter/2/6.png +++ b/chapter/2/images/6.png diff --git a/chapter/2/7.png b/chapter/2/images/7.png Binary files differindex 7183fb6..7183fb6 100644 --- a/chapter/2/7.png +++ b/chapter/2/images/7.png diff --git a/chapter/2/8.png b/chapter/2/images/8.png Binary files differindex d6d2e0e..d6d2e0e 100644 --- a/chapter/2/8.png +++ b/chapter/2/images/8.png diff --git a/chapter/2/9.png b/chapter/2/images/9.png Binary files differindex 1b67a45..1b67a45 100644 --- a/chapter/2/9.png +++ b/chapter/2/images/9.png diff --git a/chapter/2/images/p-1.png b/chapter/2/images/p-1.png Binary files differnew file mode 100644 index 0000000..7061fe3 --- /dev/null +++ b/chapter/2/images/p-1.png diff --git a/chapter/2/images/p-1.svg b/chapter/2/images/p-1.svg new file mode 100644 index 0000000..87e180b --- /dev/null +++ b/chapter/2/images/p-1.svg @@ -0,0 +1,4 @@ +<?xml version="1.0" standalone="yes"?> + +<svg version="1.1" viewBox="0.0 0.0 720.0 540.0" fill="none" stroke="none" stroke-linecap="square" stroke-miterlimit="10" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><clipPath id="p.0"><path d="m0 0l720.0 0l0 540.0l-720.0 0l0 -540.0z" clip-rule="nonzero"></path></clipPath><g clip-path="url(#p.0)"><path fill="#000000" fill-opacity="0.0" d="m0 0l720.0 0l0 540.0l-720.0 0z" fill-rule="nonzero"></path><path fill="#000000" fill-opacity="0.0" d="m273.45404 246.13159l163.37006 -17.354324" fill-rule="nonzero"></path><path stroke="#93c47d" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m276.86194 245.76958l159.96216 -16.99231" fill-rule="evenodd"></path><path fill="#93c47d" stroke="#93c47d" stroke-width="1.0" stroke-linecap="butt" d="m276.86194 245.76959l0.9995117 -1.2370911l-2.9537048 1.4446716l3.1912842 0.7919159z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m40.0 88.13911l613.98425 0l0 44.000008l-613.98425 0z" fill-rule="nonzero"></path><path fill="#000000" d="m151.20563 109.902855q0 0.34375 -0.015625 0.578125q-0.015625 0.234375 -0.03125 0.4375l-6.53125 0q0 1.4375 0.796875 2.203125q0.796875 0.765625 2.296875 0.765625q0.40625 0 0.8125 -0.03125q0.40625 -0.046875 0.78125 -0.09375q0.390625 -0.0625 0.734375 -0.125q0.34375 -0.078125 0.640625 -0.15625l0 1.328125q-0.65625 0.1875 -1.484375 0.296875q-0.828125 0.125 -1.71875 0.125q-1.203125 0 -2.0625 -0.328125q-0.859375 -0.328125 -1.421875 -0.9375q-0.546875 -0.625 -0.8125 -1.515625q-0.265625 -0.890625 -0.265625 -2.03125q0 -0.984375 0.28125 -1.859375q0.296875 -0.875 0.828125 -1.53125q0.546875 -0.671875 1.328125 -1.0625q0.796875 -0.390625 1.796875 -0.390625q0.984375 0 1.734375 0.3125q0.75 0.296875 1.265625 0.859375q0.515625 0.5625 0.78125 1.375q0.265625 0.796875 0.265625 1.78125zm-1.6875 -0.21875q0.03125 -0.625 -0.125 -1.140625q-0.140625 -0.515625 -0.453125 -0.890625q-0.3125 -0.375 -0.78125 -0.578125q-0.453125 -0.203125 -1.078125 -0.203125q-0.515625 0 -0.953125 0.203125q-0.4375 0.203125 -0.765625 0.578125q-0.3125 0.359375 -0.5 0.890625q-0.1875 0.515625 -0.234375 1.140625l4.890625 0zm12.460419 5.375l-2.140625 0l-2.515625 -3.546875l-2.484375 3.546875l-2.078125 0l3.609375 -4.671875l-3.453125 -4.640625l2.078125 0l2.4375 3.578125l2.40625 -3.578125l2.0 0l-3.5 4.671875l3.640625 4.640625zm9.819794 -4.828125q0 1.25 -0.34375 2.1875q-0.34375 0.921875 -0.953125 1.53125q-0.609375 0.609375 -1.453125 0.921875q-0.828125 0.296875 -1.8125 0.296875q-0.4375 0 -0.890625 -0.046875q-0.4375 -0.046875 -0.890625 -0.15625l0 3.890625l-1.609375 0l0 -13.109375l1.4375 0l0.109375 1.5625q0.6875 -0.96875 1.46875 -1.34375q0.796875 -0.390625 1.71875 -0.390625q0.796875 0 1.390625 0.34375q0.609375 0.328125 1.015625 0.9375q0.40625 0.609375 0.609375 1.46875q0.203125 0.859375 0.203125 1.90625zm-1.640625 0.078125q0 -0.734375 -0.109375 -1.34375q-0.109375 -0.609375 -0.34375 -1.046875q-0.234375 -0.4375 -0.59375 -0.6875q-0.359375 -0.25 -0.859375 -0.25q-0.3125 0 -0.625 0.109375q-0.3125 0.09375 -0.65625 0.328125q-0.328125 0.21875 -0.703125 0.59375q-0.375 0.375 -0.8125 0.9375l0 4.515625q0.453125 0.1875 0.9375 0.296875q0.5 0.09375 0.96875 0.09375q1.3125 0 2.046875 -0.875q0.75 -0.890625 0.75 -2.671875zm21.936462 -1.25l-7.984375 0l0 -1.359375l7.984375 0l0 1.359375zm0 3.234375l-7.984375 0l0 -1.359375l7.984375 0l0 1.359375z" fill-rule="nonzero"></path><path fill="#0000ff" d="m210.85876 115.059105l-0.03125 -1.25q-0.765625 0.75 -1.546875 1.09375q-0.78125 0.328125 -1.65625 0.328125q-0.796875 0 -1.359375 -0.203125q-0.5625 -0.203125 -0.9375 -0.5625q-0.359375 -0.359375 -0.53125 -0.84375q-0.171875 -0.484375 -0.171875 -1.046875q0 -1.40625 1.046875 -2.1875q1.046875 -0.796875 3.078125 -0.796875l1.9375 0l0 -0.828125q0 -0.8125 -0.53125 -1.3125q-0.53125 -0.5 -1.609375 -0.5q-0.796875 0 -1.5625 0.1875q-0.765625 0.171875 -1.578125 0.484375l0 -1.453125q0.296875 -0.109375 0.671875 -0.21875q0.390625 -0.109375 0.796875 -0.1875q0.421875 -0.078125 0.875 -0.125q0.453125 -0.0625 0.921875 -0.0625q0.84375 0 1.515625 0.1875q0.6875 0.1875 1.15625 0.578125q0.46875 0.375 0.71875 0.953125q0.25 0.5625 0.25 1.34375l0 6.421875l-1.453125 0zm-0.171875 -4.234375l-2.0625 0q-0.59375 0 -1.03125 0.125q-0.4375 0.109375 -0.71875 0.34375q-0.28125 0.21875 -0.421875 0.53125q-0.125 0.296875 -0.125 0.6875q0 0.28125 0.078125 0.53125q0.09375 0.234375 0.28125 0.421875q0.1875 0.1875 0.484375 0.3125q0.296875 0.109375 0.71875 0.109375q0.5625 0 1.28125 -0.34375q0.71875 -0.34375 1.515625 -1.078125l0 -1.640625z" fill-rule="nonzero"></path><path fill="#980000" d="m230.9671 118.94973q-4.28125 -3.953125 -4.28125 -8.75q0 -1.125 0.21875 -2.234375q0.234375 -1.125 0.734375 -2.25q0.515625 -1.125 1.34375 -2.234375q0.828125 -1.125 2.015625 -2.234375l0.9375 0.953125q-3.59375 3.546875 -3.59375 7.875q0 2.15625 0.90625 4.140625q0.90625 1.984375 2.6875 3.75l-0.96875 0.984375z" fill-rule="nonzero"></path><path fill="#0000ff" d="m253.85669 110.23098q0 1.15625 -0.328125 2.078125q-0.3125 0.90625 -0.90625 1.546875q-0.578125 0.640625 -1.421875 0.984375q-0.84375 0.328125 -1.90625 0.328125q-0.828125 0 -1.6875 -0.15625q-0.859375 -0.15625 -1.703125 -0.5l0 -12.5625l1.609375 0l0 3.609375l-0.0625 1.71875q0.6875 -0.9375 1.484375 -1.3125q0.796875 -0.390625 1.703125 -0.390625q0.796875 0 1.390625 0.34375q0.609375 0.328125 1.015625 0.9375q0.40625 0.609375 0.609375 1.46875q0.203125 0.859375 0.203125 1.90625zm-1.640625 0.078125q0 -0.734375 -0.109375 -1.34375q-0.109375 -0.609375 -0.34375 -1.046875q-0.234375 -0.4375 -0.59375 -0.6875q-0.359375 -0.25 -0.859375 -0.25q-0.3125 0 -0.625 0.109375q-0.3125 0.09375 -0.65625 0.328125q-0.328125 0.21875 -0.703125 0.59375q-0.375 0.375 -0.8125 0.9375l0 4.515625q0.484375 0.1875 0.96875 0.296875q0.5 0.09375 0.9375 0.09375q0.5625 0 1.0625 -0.171875q0.5 -0.171875 0.890625 -0.578125q0.390625 -0.421875 0.609375 -1.09375q0.234375 -0.6875 0.234375 -1.703125z" fill-rule="nonzero"></path><path fill="#980000" d="m271.99628 118.94973q-4.28125 -3.953125 -4.28125 -8.75q0 -1.125 0.21875 -2.234375q0.234375 -1.125 0.734375 -2.25q0.515625 -1.125 1.34375 -2.234375q0.828125 -1.125 2.015625 -2.234375l0.9375 0.953125q-3.59375 3.546875 -3.59375 7.875q0 2.15625 0.90625 4.140625q0.90625 1.984375 2.6875 3.75l-0.96875 0.984375z" fill-rule="nonzero"></path><path fill="#0000ff" d="m294.1671 114.715355q-0.625 0.234375 -1.296875 0.34375q-0.65625 0.125 -1.359375 0.125q-2.21875 0 -3.40625 -1.1875q-1.1875 -1.203125 -1.1875 -3.5q0 -1.109375 0.34375 -2.0q0.34375 -0.90625 0.953125 -1.546875q0.625 -0.640625 1.484375 -0.984375q0.875 -0.34375 1.90625 -0.34375q0.734375 0 1.359375 0.109375q0.625 0.09375 1.203125 0.3125l0 1.546875q-0.59375 -0.3125 -1.234375 -0.453125q-0.625 -0.15625 -1.28125 -0.15625q-0.625 0 -1.1875 0.25q-0.546875 0.234375 -0.96875 0.6875q-0.40625 0.4375 -0.65625 1.078125q-0.234375 0.640625 -0.234375 1.4375q0 1.6875 0.8125 2.53125q0.828125 0.84375 2.28125 0.84375q0.65625 0 1.265625 -0.140625q0.625 -0.15625 1.203125 -0.453125l0 1.5z" fill-rule="nonzero"></path><path fill="#980000" d="m313.02545 118.94973q-4.28125 -3.953125 -4.28125 -8.75q0 -1.125 0.21875 -2.234375q0.234375 -1.125 0.734375 -2.25q0.515625 -1.125 1.34375 -2.234375q0.828125 -1.125 2.015625 -2.234375l0.9375 0.953125q-3.59375 3.546875 -3.59375 7.875q0 2.15625 0.90625 4.140625q0.90625 1.984375 2.6875 3.75l-0.96875 0.984375zm6.5854187 -17.703125q4.265625 3.953125 4.265625 8.8125q0 1.0 -0.203125 2.078125q-0.203125 1.078125 -0.703125 2.203125q-0.484375 1.125 -1.3125 2.28125q-0.828125 1.171875 -2.09375 2.328125l-0.9375 -0.953125q1.8125 -1.78125 2.703125 -3.734375q0.890625 -1.953125 0.890625 -4.078125q0 -4.421875 -3.59375 -7.953125l0.984375 -0.984375z" fill-rule="nonzero"></path><path fill="#980000" d="m340.12546 101.246605q4.265625 3.953125 4.265625 8.8125q0 1.0 -0.203125 2.078125q-0.203125 1.078125 -0.703125 2.203125q-0.484375 1.125 -1.3125 2.28125q-0.828125 1.171875 -2.09375 2.328125l-0.9375 -0.953125q1.8125 -1.78125 2.703125 -3.734375q0.890625 -1.953125 0.890625 -4.078125q0 -4.421875 -3.59375 -7.953125l0.984375 -0.984375z" fill-rule="nonzero"></path><path fill="#000000" d="m349.19525 116.965355q0.484375 0.015625 0.921875 -0.09375q0.453125 -0.09375 0.78125 -0.296875q0.34375 -0.203125 0.546875 -0.5q0.203125 -0.296875 0.203125 -0.671875q0 -0.390625 -0.140625 -0.625q-0.125 -0.25 -0.296875 -0.453125q-0.171875 -0.203125 -0.3125 -0.4375q-0.125 -0.234375 -0.125 -0.625q0 -0.1875 0.078125 -0.390625q0.078125 -0.21875 0.21875 -0.390625q0.15625 -0.1875 0.390625 -0.296875q0.25 -0.109375 0.5625 -0.109375q0.328125 0 0.625 0.140625q0.3125 0.125 0.53125 0.40625q0.234375 0.28125 0.359375 0.703125q0.140625 0.40625 0.140625 0.96875q0 0.78125 -0.28125 1.484375q-0.28125 0.703125 -0.84375 1.25q-0.5625 0.5625 -1.40625 0.875q-0.828125 0.328125 -1.953125 0.328125l0 -1.265625z" fill-rule="nonzero"></path><path fill="#0000ff" d="m368.52234 110.590355q0 -1.1875 0.3125 -2.109375q0.328125 -0.921875 0.921875 -1.546875q0.609375 -0.640625 1.4375 -0.96875q0.84375 -0.328125 1.875 -0.328125q0.453125 0 0.875 0.0625q0.4375 0.046875 0.859375 0.171875l0 -3.921875l1.625 0l0 13.109375l-1.453125 0l-0.0625 -1.765625q-0.671875 0.984375 -1.46875 1.46875q-0.78125 0.46875 -1.703125 0.46875q-0.796875 0 -1.40625 -0.328125q-0.59375 -0.34375 -1.0 -0.953125q-0.40625 -0.609375 -0.609375 -1.453125q-0.203125 -0.859375 -0.203125 -1.90625zm1.640625 -0.09375q0 1.6875 0.5 2.515625q0.5 0.828125 1.40625 0.828125q0.609375 0 1.296875 -0.546875q0.6875 -0.546875 1.4375 -1.625l0 -4.3125q-0.40625 -0.1875 -0.890625 -0.28125q-0.484375 -0.109375 -0.953125 -0.109375q-1.3125 0 -2.0625 0.859375q-0.734375 0.84375 -0.734375 2.671875z" fill-rule="nonzero"></path><path fill="#980000" d="m395.0838 118.94973q-4.28125 -3.953125 -4.28125 -8.75q0 -1.125 0.21875 -2.234375q0.234375 -1.125 0.734375 -2.25q0.515625 -1.125 1.34375 -2.234375q0.828125 -1.125 2.015625 -2.234375l0.9375 0.953125q-3.59375 3.546875 -3.59375 7.875q0 2.15625 0.90625 4.140625q0.90625 1.984375 2.6875 3.75l-0.96875 0.984375z" fill-rule="nonzero"></path><path fill="#0000ff" d="m417.89526 109.902855q0 0.34375 -0.015625 0.578125q-0.015625 0.234375 -0.03125 0.4375l-6.53125 0q0 1.4375 0.796875 2.203125q0.796875 0.765625 2.296875 0.765625q0.40625 0 0.8125 -0.03125q0.40625 -0.046875 0.78125 -0.09375q0.390625 -0.0625 0.734375 -0.125q0.34375 -0.078125 0.640625 -0.15625l0 1.328125q-0.65625 0.1875 -1.484375 0.296875q-0.828125 0.125 -1.71875 0.125q-1.203125 0 -2.0625 -0.328125q-0.859375 -0.328125 -1.421875 -0.9375q-0.546875 -0.625 -0.8125 -1.515625q-0.265625 -0.890625 -0.265625 -2.03125q0 -0.984375 0.28125 -1.859375q0.296875 -0.875 0.828125 -1.53125q0.546875 -0.671875 1.328125 -1.0625q0.796875 -0.390625 1.796875 -0.390625q0.984375 0 1.734375 0.3125q0.75 0.296875 1.265625 0.859375q0.515625 0.5625 0.78125 1.375q0.265625 0.796875 0.265625 1.78125zm-1.6875 -0.21875q0.03125 -0.625 -0.125 -1.140625q-0.140625 -0.515625 -0.453125 -0.890625q-0.3125 -0.375 -0.78125 -0.578125q-0.453125 -0.203125 -1.078125 -0.203125q-0.515625 0 -0.953125 0.203125q-0.4375 0.203125 -0.765625 0.578125q-0.3125 0.359375 -0.5 0.890625q-0.1875 0.515625 -0.234375 1.140625l4.890625 0z" fill-rule="nonzero"></path><path fill="#980000" d="m436.11298 118.94973q-4.28125 -3.953125 -4.28125 -8.75q0 -1.125 0.21875 -2.234375q0.234375 -1.125 0.734375 -2.25q0.515625 -1.125 1.34375 -2.234375q0.828125 -1.125 2.015625 -2.234375l0.9375 0.953125q-3.59375 3.546875 -3.59375 7.875q0 2.15625 0.90625 4.140625q0.90625 1.984375 2.6875 3.75l-0.96875 0.984375zm6.5854187 -17.703125q4.265625 3.953125 4.265625 8.8125q0 1.0 -0.203125 2.078125q-0.203125 1.078125 -0.703125 2.203125q-0.484375 1.125 -1.3125 2.28125q-0.828125 1.171875 -2.09375 2.328125l-0.9375 -0.953125q1.8125 -1.78125 2.703125 -3.734375q0.890625 -1.953125 0.890625 -4.078125q0 -4.421875 -3.59375 -7.953125l0.984375 -0.984375z" fill-rule="nonzero"></path><path fill="#000000" d="m451.7682 116.965355q0.484375 0.015625 0.921875 -0.09375q0.453125 -0.09375 0.78125 -0.296875q0.34375 -0.203125 0.546875 -0.5q0.203125 -0.296875 0.203125 -0.671875q0 -0.390625 -0.140625 -0.625q-0.125 -0.25 -0.296875 -0.453125q-0.171875 -0.203125 -0.3125 -0.4375q-0.125 -0.234375 -0.125 -0.625q0 -0.1875 0.078125 -0.390625q0.078125 -0.21875 0.21875 -0.390625q0.15625 -0.1875 0.390625 -0.296875q0.25 -0.109375 0.5625 -0.109375q0.328125 0 0.625 0.140625q0.3125 0.125 0.53125 0.40625q0.234375 0.28125 0.359375 0.703125q0.140625 0.40625 0.140625 0.96875q0 0.78125 -0.28125 1.484375q-0.28125 0.703125 -0.84375 1.25q-0.5625 0.5625 -1.40625 0.875q-0.828125 0.328125 -1.953125 0.328125l0 -1.265625z" fill-rule="nonzero"></path><path fill="#0000ff" d="m479.82965 103.44973q-1.265625 -0.265625 -2.1875 -0.265625q-2.1875 0 -2.1875 2.28125l0 1.640625l4.09375 0l0 1.34375l-4.09375 0l0 6.609375l-1.640625 0l0 -6.609375l-2.984375 0l0 -1.34375l2.984375 0l0 -1.546875q0 -3.71875 3.875 -3.71875q0.96875 0 2.140625 0.21875l0 1.390625zm-9.75 2.296875l0 0z" fill-rule="nonzero"></path><path fill="#980000" d="m497.65674 118.94973q-4.28125 -3.953125 -4.28125 -8.75q0 -1.125 0.21875 -2.234375q0.234375 -1.125 0.734375 -2.25q0.515625 -1.125 1.34375 -2.234375q0.828125 -1.125 2.015625 -2.234375l0.9375 0.953125q-3.59375 3.546875 -3.59375 7.875q0 2.15625 0.90625 4.140625q0.90625 1.984375 2.6875 3.75l-0.96875 0.984375zm6.5854187 -17.703125q4.265625 3.953125 4.265625 8.8125q0 1.0 -0.203125 2.078125q-0.203125 1.078125 -0.703125 2.203125q-0.484375 1.125 -1.3125 2.28125q-0.828125 1.171875 -2.09375 2.328125l-0.9375 -0.953125q1.8125 -1.78125 2.703125 -3.734375q0.890625 -1.953125 0.890625 -4.078125q0 -4.421875 -3.59375 -7.953125l0.984375 -0.984375z" fill-rule="nonzero"></path><path fill="#980000" d="m524.7567 101.246605q4.265625 3.953125 4.265625 8.8125q0 1.0 -0.203125 2.078125q-0.203125 1.078125 -0.703125 2.203125q-0.484375 1.125 -1.3125 2.28125q-0.828125 1.171875 -2.09375 2.328125l-0.9375 -0.953125q1.8125 -1.78125 2.703125 -3.734375q0.890625 -1.953125 0.890625 -4.078125q0 -4.421875 -3.59375 -7.953125l0.984375 -0.984375zm20.514648 0q4.265625 3.953125 4.265625 8.8125q0 1.0 -0.203125 2.078125q-0.203125 1.078125 -0.703125 2.203125q-0.484375 1.125 -1.3125 2.28125q-0.828125 1.171875 -2.09375 2.328125l-0.9375 -0.953125q1.8125 -1.78125 2.703125 -3.734375q0.890625 -1.953125 0.890625 -4.078125q0 -4.421875 -3.59375 -7.953125l0.984375 -0.984375z" fill-rule="nonzero"></path><path fill="#d0e0e3" d="m433.02225 144.22713l64.97638 0l0 384.75592l-64.97638 0z" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m433.02225 144.22713l64.97638 0l0 384.75592l-64.97638 0z" fill-rule="nonzero"></path><path fill="#434343" d="m469.6318 285.2438q0 0.859375 -0.359375 1.515625q-0.34375 0.640625 -0.984375 1.078125q-0.625 0.421875 -1.515625 0.640625q-0.875 0.21875 -1.953125 0.21875q-0.46875 0 -0.953125 -0.046875q-0.484375 -0.03125 -0.921875 -0.09375q-0.4375 -0.046875 -0.828125 -0.125q-0.390625 -0.078125 -0.703125 -0.15625l0 -1.59375q0.6875 0.25 1.546875 0.40625q0.875 0.140625 1.984375 0.140625q0.796875 0 1.359375 -0.125q0.5625 -0.125 0.921875 -0.359375q0.359375 -0.25 0.515625 -0.59375q0.171875 -0.359375 0.171875 -0.8125q0 -0.5 -0.28125 -0.84375q-0.265625 -0.34375 -0.71875 -0.609375q-0.4375 -0.28125 -1.015625 -0.5q-0.578125 -0.234375 -1.171875 -0.46875q-0.59375 -0.25 -1.171875 -0.53125q-0.5625 -0.28125 -1.015625 -0.671875q-0.4375 -0.390625 -0.71875 -0.90625q-0.265625 -0.515625 -0.265625 -1.234375q0 -0.625 0.265625 -1.21875q0.265625 -0.609375 0.8125 -1.078125q0.546875 -0.46875 1.40625 -0.75q0.859375 -0.296875 2.046875 -0.296875q0.296875 0 0.65625 0.03125q0.359375 0.03125 0.71875 0.078125q0.375 0.046875 0.734375 0.125q0.359375 0.0625 0.65625 0.125l0 1.484375q-0.71875 -0.203125 -1.4375 -0.296875q-0.703125 -0.109375 -1.375 -0.109375q-1.421875 0 -2.09375 0.46875q-0.65625 0.46875 -0.65625 1.265625q0 0.5 0.265625 0.859375q0.28125 0.34375 0.71875 0.625q0.453125 0.28125 1.015625 0.515625q0.578125 0.21875 1.171875 0.46875q0.59375 0.234375 1.15625 0.515625q0.578125 0.28125 1.015625 0.6875q0.453125 0.390625 0.71875 0.921875q0.28125 0.515625 0.28125 1.25z" fill-rule="nonzero"></path><path fill="#434343" d="m469.14743 310.52505l-6.90625 0l0 -12.125l6.90625 0l0 1.390625l-5.25 0l0 3.75l5.03125 0l0 1.40625l-5.03125 0l0 4.171875l5.25 0l0 1.40625z" fill-rule="nonzero"></path><path fill="#434343" d="m470.1318 332.52505l-1.859375 0l-1.8125 -3.875q-0.203125 -0.453125 -0.421875 -0.734375q-0.203125 -0.296875 -0.453125 -0.46875q-0.25 -0.171875 -0.546875 -0.25q-0.28125 -0.078125 -0.640625 -0.078125l-0.78125 0l0 5.40625l-1.65625 0l0 -12.125l3.25 0q1.046875 0 1.8125 0.234375q0.765625 0.234375 1.25 0.65625q0.484375 0.40625 0.703125 1.0q0.234375 0.578125 0.234375 1.296875q0 0.5625 -0.171875 1.078125q-0.15625 0.5 -0.484375 0.921875q-0.328125 0.40625 -0.828125 0.71875q-0.484375 0.296875 -1.109375 0.4375q0.515625 0.171875 0.859375 0.625q0.359375 0.4375 0.734375 1.171875l1.921875 3.984375zm-2.640625 -8.796875q0 -0.96875 -0.609375 -1.453125q-0.609375 -0.484375 -1.71875 -0.484375l-1.546875 0l0 4.015625l1.328125 0q0.59375 0 1.0625 -0.140625q0.46875 -0.140625 0.796875 -0.40625q0.328125 -0.265625 0.5 -0.640625q0.1875 -0.390625 0.1875 -0.890625z" fill-rule="nonzero"></path><path fill="#434343" d="m470.78806 342.40005l-4.109375 12.125l-2.234375 0l-4.03125 -12.125l1.875 0l2.609375 8.171875l0.75 2.390625l0.75 -2.390625l2.625 -8.171875l1.765625 0z" fill-rule="nonzero"></path><path fill="#434343" d="m469.14743 376.52505l-6.90625 0l0 -12.125l6.90625 0l0 1.390625l-5.25 0l0 3.75l5.03125 0l0 1.40625l-5.03125 0l0 4.171875l5.25 0l0 1.40625z" fill-rule="nonzero"></path><path fill="#434343" d="m470.1318 398.52505l-1.859375 0l-1.8125 -3.875q-0.203125 -0.453125 -0.421875 -0.734375q-0.203125 -0.296875 -0.453125 -0.46875q-0.25 -0.171875 -0.546875 -0.25q-0.28125 -0.078125 -0.640625 -0.078125l-0.78125 0l0 5.40625l-1.65625 0l0 -12.125l3.25 0q1.046875 0 1.8125 0.234375q0.765625 0.234375 1.25 0.65625q0.484375 0.40625 0.703125 1.0q0.234375 0.578125 0.234375 1.296875q0 0.5625 -0.171875 1.078125q-0.15625 0.5 -0.484375 0.921875q-0.328125 0.40625 -0.828125 0.71875q-0.484375 0.296875 -1.109375 0.4375q0.515625 0.171875 0.859375 0.625q0.359375 0.4375 0.734375 1.171875l1.921875 3.984375zm-2.640625 -8.796875q0 -0.96875 -0.609375 -1.453125q-0.609375 -0.484375 -1.71875 -0.484375l-1.546875 0l0 4.015625l1.328125 0q0.59375 0 1.0625 -0.140625q0.46875 -0.140625 0.796875 -0.40625q0.328125 -0.265625 0.5 -0.640625q0.1875 -0.390625 0.1875 -0.890625z" fill-rule="nonzero"></path><path fill="#d0e0e3" d="m208.50131 144.22713l64.97638 0l0 384.75592l-64.97638 0z" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m208.50131 144.22713l64.97638 0l0 384.75592l-64.97638 0z" fill-rule="nonzero"></path><path fill="#434343" d="m245.09523 288.07193q-1.453125 0.609375 -3.0625 0.609375q-2.5625 0 -3.9375 -1.53125q-1.375 -1.546875 -1.375 -4.546875q0 -1.46875 0.375 -2.640625q0.375 -1.171875 1.078125 -2.0q0.71875 -0.828125 1.71875 -1.265625q1.0 -0.453125 2.234375 -0.453125q0.84375 0 1.5625 0.15625q0.734375 0.140625 1.40625 0.4375l0 1.625q-0.65625 -0.359375 -1.375 -0.546875q-0.703125 -0.203125 -1.53125 -0.203125q-0.859375 0 -1.546875 0.328125q-0.6875 0.3125 -1.171875 0.921875q-0.484375 0.609375 -0.75 1.484375q-0.25 0.875 -0.25 2.0q0 2.359375 0.953125 3.5625q0.953125 1.1875 2.796875 1.1875q0.78125 0 1.5 -0.171875q0.71875 -0.1875 1.375 -0.515625l0 1.5625z" fill-rule="nonzero"></path><path fill="#434343" d="m245.00148 310.52505l-6.984375 0l0 -12.125l1.6875 0l0 10.71875l5.296875 0l0 1.40625z" fill-rule="nonzero"></path><path fill="#434343" d="m240.25148 321.79068l-2.796875 0l0 -1.390625l7.25 0l0 1.390625l-2.78125 0l0 9.328125l2.78125 0l0 1.40625l-7.25 0l0 -1.40625l2.796875 0l0 -9.328125z" fill-rule="nonzero"></path><path fill="#434343" d="m244.62648 354.52505l-6.90625 0l0 -12.125l6.90625 0l0 1.390625l-5.25 0l0 3.75l5.03125 0l0 1.40625l-5.03125 0l0 4.171875l5.25 0l0 1.40625z" fill-rule="nonzero"></path><path fill="#434343" d="m245.22023 376.52505l-2.15625 0l-3.53125 -7.5625l-1.03125 -2.421875l0 6.109375l0 3.875l-1.53125 0l0 -12.125l2.125 0l3.359375 7.15625l1.21875 2.78125l0 -6.5l0 -3.4375l1.546875 0l0 12.125z" fill-rule="nonzero"></path><path fill="#434343" d="m245.5171 387.8063l-3.59375 0l0 10.71875l-1.671875 0l0 -10.71875l-3.59375 0l0 -1.40625l8.859375 0l0 1.40625z" fill-rule="nonzero"></path><path fill="#000000" fill-opacity="0.0" d="m275.37988 154.37495l159.52756 23.685043" fill-rule="nonzero"></path><path stroke="#e06666" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m275.3799 154.37495l156.1376 23.181747" fill-rule="evenodd"></path><path fill="#e06666" stroke="#e06666" stroke-width="1.0" stroke-linecap="butt" d="m431.51752 177.5567l-1.2775574 0.9472351l3.2214355 -0.6586304l-2.8911133 -1.5661621z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m343.18604 134.28076l22.677185 2.9606323l-2.551178 14.992126l-22.677185 -2.9606323z" fill-rule="nonzero"></path><path fill="#e06666" d="m354.0799 156.38391l1.5900879 0.42819214q-0.5466919 1.6304474 -1.8093567 2.4425812q-1.2600708 0.79670715 -2.871399 0.5863342q-1.9986572 -0.26094055 -3.0022888 -1.7156067q-0.98553467 -1.4680634 -0.57107544 -3.903656q0.26757812 -1.5723419 0.97821045 -2.6771393q0.72875977 -1.1181946 1.8974915 -1.5643921q1.1868591 -0.45959473 2.4418335 -0.2957611q1.5958252 0.2083435 2.4664917 1.1414185q0.870697 0.9330597 0.9132385 2.451355l-1.6532898 0.03627014q-0.06451416 -1.0169067 -0.56933594 -1.5870667q-0.5048218 -0.57014465 -1.3259583 -0.6773529q-1.2549744 -0.16383362 -2.1972961 0.6270752q-0.92681885 0.79293823 -1.2547302 2.7198334q-0.33312988 1.9577179 0.27389526 2.9509125q0.6096802 0.9777832 1.8181763 1.1355591q0.9760742 0.12742615 1.7265015 -0.37338257q0.75302124 -0.51623535 1.1488037 -1.725174z" fill-rule="nonzero"></path><path fill="#000000" fill-opacity="0.0" d="m273.4716 190.73802l160.53543 -11.842529" fill-rule="nonzero"></path><path stroke="#e06666" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m276.88937 190.48589l157.11765 -11.590378" fill-rule="evenodd"></path><path fill="#e06666" stroke="#e06666" stroke-width="1.0" stroke-linecap="butt" d="m276.88937 190.4859l1.0388184 -1.2042694l-2.9986572 1.3488464l3.1641235 0.8942261z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m275.37988 209.34238l158.61417 19.433075" fill-rule="nonzero"></path><path stroke="#93c47d" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m275.3799 209.34238l155.2125 19.016296" fill-rule="evenodd"></path><path fill="#93c47d" stroke="#93c47d" stroke-width="1.0" stroke-linecap="butt" d="m430.5924 228.35869l-1.2529907 0.9794769l3.2035828 -0.7404938l-2.9300842 -1.4919891z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m333.4637 185.07516l55.62204 7.3385773l-2.551178 14.992126l-55.62204 -7.3385773z" fill-rule="nonzero"></path><path fill="#93c47d" d="m344.0724 210.80086l-1.5335693 -0.20233154l2.282013 -13.410477l1.6420288 0.21664429l-0.81314087 4.7784424q1.2763367 -1.1712341 2.9028625 -0.9566345q0.898468 0.11853027 1.6410217 0.5947571q0.74520874 0.46080017 1.1436157 1.1910706q0.4165039 0.7168884 0.5534363 1.6805725q0.13696289 0.96369934 -0.041412354 2.0118713q-0.42492676 2.4971313 -1.897644 3.70549q-1.4700928 1.1929626 -3.2050476 0.96406555q-1.7349548 -0.22891235 -2.4669495 -1.7911987l-0.20721436 1.2177277zm0.82388306 -4.9346313q-0.29638672 1.7418213 0.0345459 2.589264q0.5749512 1.3682098 1.907135 1.5439758q1.0843506 0.1430664 2.0317688 -0.6775665q0.9500427 -0.83602905 1.2674255 -2.7011719q0.32263184 -1.8959656 -0.28164673 -2.905548q-0.6043091 -1.0095978 -1.6731567 -1.1506195q-1.0843506 -0.1430664 -2.0343933 0.6929779q-0.9500427 0.8360443 -1.2516785 2.6086884zm10.417725 10.452469q-1.069397 -1.90625 -1.6235046 -4.327667q-0.55148315 -2.4368134 -0.13180542 -4.9031067q0.37246704 -2.1888428 1.4079285 -4.085312q1.22995 -2.2017975 3.340271 -4.2716675l1.1927795 0.15737915q-1.4379578 1.7488098 -1.9332886 2.518753q-0.7727356 1.1903992 -1.3315125 2.5193634q-0.6939087 1.6578522 -0.9876709 3.384262q-0.7501831 4.408493 1.2595825 9.165375l-1.1927795 -0.15737915zm10.658783 -6.2690277l1.5898132 0.43040466q-0.54663086 1.6300049 -1.809082 2.4405823q-1.2598572 0.795166 -2.8709106 0.5826111q-1.998291 -0.26365662 -3.0017395 -1.7199249q-0.98532104 -1.469635 -0.5708618 -3.9050903q0.2675476 -1.5722656 0.9780884 -2.6763153q0.7286377 -1.1174164 1.8971863 -1.5621338q1.1866455 -0.45809937 2.4414062 -0.2925415q1.5955505 0.21051025 2.466034 1.1448975q0.8705139 0.9343872 0.9130249 2.453003l-1.6530151 0.034072876q-0.06448364 -1.0171661 -0.56918335 -1.588089q-0.5047302 -0.57092285 -1.3257141 -0.679245q-1.2547607 -0.16555786 -2.19693 0.62423706q-0.92666626 0.79185486 -1.2545471 2.7186432q-0.33312988 1.9576111 0.2737732 2.9517975q0.6095581 0.97875977 1.8178406 1.1381836q0.9758911 0.12875366 1.7261963 -0.3711548q0.75289917 -0.5153198 1.1486206 -1.723938zm2.6727295 8.027954l-1.1772766 -0.15533447q3.4894104 -4.0313263 4.2395935 -8.439835q0.2911682 -1.7109833 0.19244385 -3.4576569q-0.09185791 -1.4147949 -0.43444824 -2.7523499q-0.21463013 -0.8793793 -1.0047302 -2.937912l1.1773071 0.15531921q1.3441162 2.52565 1.771698 4.946121q0.37420654 2.0824585 0.0017089844 4.2713013q-0.41967773 2.4662933 -1.7735596 4.651718q-1.3357544 2.1720734 -2.9927368 3.718628z" fill-rule="nonzero"></path><path fill="#000000" fill-opacity="0.0" d="m276.33405 274.71732l159.52756 23.685028" fill-rule="nonzero"></path><path stroke="#bf9000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m276.33405 274.71732l156.1376 23.181732" fill-rule="evenodd"></path><path fill="#bf9000" stroke="#bf9000" stroke-width="1.0" stroke-linecap="butt" d="m432.47165 297.89905l-1.2775269 0.9472351l3.221405 -0.6586304l-2.8911133 -1.5661621z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m343.18744 255.03127l22.677185 2.9606476l-2.551178 14.992126l-22.677185 -2.9606323z" fill-rule="nonzero"></path><path fill="#bf9000" d="m353.7983 277.53867l1.667572 0.43832397q-0.6546631 1.4272766 -1.8963318 2.1160583q-1.2236023 0.67541504 -2.927887 0.45291138q-2.138092 -0.2791443 -3.170105 -1.7532654q-1.0320129 -1.4741516 -0.62802124 -3.848053q0.41708374 -2.4510193 1.9028931 -3.6437073q1.5013123 -1.1906738 3.5309448 -0.9256897q1.9676819 0.25689697 2.9815674 1.7444153q1.0138855 1.4875183 0.6020508 3.9077148q-0.023590088 0.13873291 -0.08892822 0.42959595l-7.281952 -0.9507141q-0.1798706 1.6153259 0.4970398 2.570343q0.6768799 0.9550476 1.9008484 1.1148376q0.8986206 0.11734009 1.6125488 -0.2621765q0.73205566 -0.39291382 1.29776 -1.3905945zm-4.9844055 -3.3768005l5.453705 0.7120056q0.0987854 -1.2319336 -0.30758667 -1.9153137q-0.62753296 -1.0588989 -1.8979797 -1.224762q-1.1310425 -0.14764404 -2.0523682 0.5199585q-0.90319824 0.6541748 -1.1957703 1.9081116z" fill-rule="nonzero"></path><path fill="#000000" fill-opacity="0.0" d="m274.42575 311.08038l160.53543 -11.842529" fill-rule="nonzero"></path><path stroke="#bf9000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m277.84354 310.82825l157.11761 -11.590393" fill-rule="evenodd"></path><path fill="#bf9000" stroke="#bf9000" stroke-width="1.0" stroke-linecap="butt" d="m277.84354 310.82825l1.0387878 -1.2042542l-2.9986572 1.3488464l3.1641235 0.8942261z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m275.38113 346.36475l159.52756 23.685028" fill-rule="nonzero"></path><path stroke="#134f5c" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m275.38116 346.36475l156.1376 23.181732" fill-rule="evenodd"></path><path fill="#134f5c" stroke="#134f5c" stroke-width="1.0" stroke-linecap="butt" d="m431.51877 369.54648l-1.2775269 0.9472351l3.221405 -0.6586304l-2.8910828 -1.5661316z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m343.18732 325.66556l22.677155 2.9606323l-2.551178 14.992126l-22.677185 -2.9606323z" fill-rule="nonzero"></path><path fill="#134f5c" d="m349.54965 350.8171l1.4348755 -8.432098l-1.4718628 -0.19213867l0.22033691 -1.2948914l1.4718933 0.19216919l0.17575073 -1.0328064q0.16525269 -0.9711609 0.4169922 -1.4267883q0.34259033 -0.6170654 1.0123901 -0.923584q0.67245483 -0.3218994 1.757019 -0.18029785q0.6972046 0.091033936 1.5231018 0.3564148l-0.49447632 1.4166565q-0.49554443 -0.15924072 -0.96035767 -0.21990967q-0.7591553 -0.099121094 -1.124115 0.18414307q-0.3623352 0.26785278 -0.51187134 1.1465149l-0.15213013 0.8940735l1.9057007 0.24880981l-0.22033691 1.2948608l-1.9057007 -0.24880981l-1.4348755 8.432098l-1.642334 -0.2144165z" fill-rule="nonzero"></path><path fill="#000000" fill-opacity="0.0" d="m273.47284 382.7278l160.53543 -11.842529" fill-rule="nonzero"></path><path stroke="#134f5c" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m276.89062 382.47568l157.11765 -11.590393" fill-rule="evenodd"></path><path fill="#134f5c" stroke="#134f5c" stroke-width="1.0" stroke-linecap="butt" d="m276.89062 382.47568l1.0388184 -1.2042542l-2.9986572 1.3488464l3.1641235 0.8942261z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m275.37988 417.41953l159.52756 23.685059" fill-rule="nonzero"></path><path stroke="#a64d79" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m275.3799 417.41953l156.1376 23.181732" fill-rule="evenodd"></path><path fill="#a64d79" stroke="#a64d79" stroke-width="1.0" stroke-linecap="butt" d="m431.51752 440.6013l-1.2775574 0.9472351l3.2214355 -0.6586304l-2.8911133 -1.5661621z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m318.4788 393.75833l72.09448 9.480316l-2.551178 14.992126l-72.09448 -9.480316z" fill-rule="nonzero"></path><path fill="#741b47" d="m336.46692 420.44815l0.20986938 -1.2331848q-1.1760864 1.3267517 -2.973114 1.0904541q-1.1618652 -0.15280151 -2.0457764 -0.91516113q-0.8658142 -0.77575684 -1.2139282 -1.9877319q-0.32995605 -1.2253723 -0.075531006 -2.720581q0.24655151 -1.4489746 0.928772 -2.5727234q0.6977234 -1.1217346 1.7657471 -1.6274414q1.0835266 -0.5036621 2.29187 -0.34475708q0.8830261 0.116119385 1.501709 0.5756836q0.6341553 0.4616394 0.9656372 1.1198425l0.8183899 -4.8093567l1.6421204 0.21594238l-2.282074 13.410675l-1.5336914 -0.20166016zm-4.4098816 -5.544159q-0.31741333 1.8651733 0.3152771 2.8939514q0.64819336 1.0307922 1.717102 1.1713562q1.0844116 0.14260864 1.993042 -0.63619995q0.90859985 -0.7788086 1.2181091 -2.5977478q0.3383789 -1.9884644 -0.2788086 -3.0151978q-0.6145935 -1.0421448 -1.7454834 -1.1908569q-1.099884 -0.14465332 -1.995636 0.6516113q-0.89572144 0.79626465 -1.2236023 2.7230835zm10.849762 10.425415q-1.0694885 -1.9057007 -1.6236267 -4.326721q-0.5515442 -2.4364624 -0.13183594 -4.9028015q0.37246704 -2.1888733 1.407959 -4.085663q1.230011 -2.2022095 3.3404236 -4.2728577l1.1928406 0.15686035q-1.4380188 1.7493286 -1.9333496 2.5194397q-0.77279663 1.1906738 -1.3315735 2.5197754q-0.6939392 1.6580505 -0.98773193 3.384491q-0.7501831 4.4085693 1.2597351 9.164337l-1.1928406 -0.15686035zm10.895721 -5.8008423l1.6673584 0.43988037q-0.65460205 1.4268494 -1.8961487 2.1145935q-1.2234192 0.67437744 -2.9275208 0.45028687q-2.137848 -0.28112793 -3.1697083 -1.7563782q-1.0318604 -1.4752197 -0.62789917 -3.8490906q0.41705322 -2.4508972 1.90271 -3.642395q1.5011597 -1.1894226 3.530548 -0.9225769q1.9674377 0.25872803 2.9812012 1.747345q1.0137329 1.4886475 0.6019287 3.908722q-0.023620605 0.13873291 -0.08895874 0.42956543l-7.281067 -0.9574585q-0.17984009 1.6153564 0.49694824 2.5711365q0.67678833 0.9557495 1.9006348 1.1166992q0.89849854 0.118133545 1.6123657 -0.2607727q0.7319641 -0.39230347 1.2976074 -1.3895569zm-4.9837646 -3.3817444l5.453064 0.71707153q0.0987854 -1.2320251 -0.30752563 -1.9158325q-0.6274414 -1.0596008 -1.8977661 -1.226654q-1.1308899 -0.14868164 -2.052124 0.51812744q-0.9031067 0.6534729 -1.1956482 1.9072876zm8.479828 7.0406494l0.32000732 -1.8805847l1.8899841 0.24853516l-0.32000732 1.8805847q-0.17575073 1.0327759 -0.65509033 1.6158752q-0.4819641 0.59854126 -1.329773 0.83377075l-0.3440857 -0.77020264q0.56344604 -0.14654541 0.88739014 -0.5609741q0.3239441 -0.4144287 0.4965515 -1.2427368l-0.9449768 -0.12426758zm5.1080627 0.6717224l1.434845 -8.431793l-1.4717102 -0.19351196l0.22033691 -1.2948303l1.4717102 0.19351196l0.17572021 -1.0327759q0.16525269 -0.97109985 0.4169922 -1.4265442q0.3425293 -0.6168823 1.0122986 -0.9227905q0.6723633 -0.32131958 1.7567749 -0.17871094q0.69714355 0.09164429 1.5229492 0.35784912l-0.4944458 1.4163818q-0.4954834 -0.159729 -0.9602356 -0.2208252q-0.75909424 -0.099823 -1.1239929 0.18313599q-0.3623047 0.2675476 -0.5118103 1.1461792l-0.15216064 0.89404297l1.9054871 0.25057983l-0.22033691 1.2947998l-1.9054871 -0.25054932l-1.4348145 8.431763l-1.6421204 -0.21591187zm5.1492004 4.7115173l-1.1773682 -0.15481567q3.4895935 -4.0325623 4.239807 -8.441132q0.2911377 -1.711029 0.19238281 -3.4575806q-0.09185791 -1.4146729 -0.43447876 -2.7519836q-0.21466064 -0.87924194 -1.0047913 -2.9373474l1.1773682 0.15484619q1.3442383 2.5249329 1.7718201 4.9450684q0.37423706 2.0821838 0.0017700195 4.271057q-0.41970825 2.466339 -1.7736206 4.6522217q-1.335846 2.1725159 -2.9928894 3.7196655z" fill-rule="nonzero"></path><path fill="#000000" fill-opacity="0.0" d="m273.4716 453.7826l160.53543 -11.842499" fill-rule="nonzero"></path><path stroke="#741b47" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m276.88937 453.53046l157.11765 -11.590363" fill-rule="evenodd"></path><path fill="#741b47" stroke="#741b47" stroke-width="1.0" stroke-linecap="butt" d="m276.88937 453.5305l1.0388184 -1.2042847l-2.9986572 1.3488464l3.1641235 0.8942261z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m274.42447 484.65225l159.52759 23.685028" fill-rule="nonzero"></path><path stroke="#3d85c6" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m274.42447 484.65222l156.13766 23.181732" fill-rule="evenodd"></path><path fill="#3d85c6" stroke="#3d85c6" stroke-width="1.0" stroke-linecap="butt" d="m430.56213 507.83395l-1.2775574 0.9472351l3.2214355 -0.65859985l-2.8911133 -1.5661621z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m272.51617 521.0153l160.53543 -11.842529" fill-rule="nonzero"></path><path stroke="#3c78d8" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m275.93396 520.7632l157.11765 -11.590393" fill-rule="evenodd"></path><path fill="#3c78d8" stroke="#3c78d8" stroke-width="1.0" stroke-linecap="butt" d="m275.934 520.7632l1.0387878 -1.2042847l-2.9986572 1.348877l3.1641235 0.89416504z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m318.4788 462.90244l72.09448 9.480316l-2.551178 14.992126l-72.09448 -9.480316z" fill-rule="nonzero"></path><path fill="#3d85c6" d="m334.14395 488.05753q-1.0632629 0.6639099 -1.970398 0.87557983q-0.9045105 0.19625854 -1.8804626 0.06790161q-1.5956421 -0.20980835 -2.3320312 -1.0946045q-0.73373413 -0.90023804 -0.5265198 -2.117981q0.123291016 -0.7244873 0.5482788 -1.267456q0.4250183 -0.54299927 1.0120544 -0.8282471q0.58703613 -0.28527832 1.284668 -0.3826599q0.5193176 -0.07354736 1.5136719 -0.053100586q2.0558777 0.018188477 3.0559387 -0.1812439q0.05770874 -0.33914185 0.07345581 -0.4316101q0.17050171 -1.0019531 -0.22341919 -1.4792786q-0.54074097 -0.63842773 -1.7955627 -0.8034363q-1.1618652 -0.15280151 -1.7877502 0.1746521q-0.6259155 0.3274536 -1.067627 1.3410034l-1.5872803 -0.4451294q0.40811157 -1.0021973 1.011383 -1.5690308q0.6187744 -0.5647583 1.62146 -0.77960205q1.020813 -0.22824097 2.2911377 -0.06121826q1.2548218 0.16500854 1.9795532 0.5597534q0.72476196 0.39474487 1.0204773 0.8906555q0.29574585 0.49591064 0.31976318 1.1924744q0.022125244 0.42843628 -0.16412354 1.5228577l-0.37509155 2.2042847q-0.39083862 2.2967834 -0.40283203 2.9255676q0.006164551 0.615448 0.23706055 1.2131348l-1.7350769 -0.22814941q-0.17678833 -0.54330444 -0.12072754 -1.2451172zm0.48486328 -3.6870117q-0.9588318 0.23638916 -2.8159485 0.26010132q-1.046051 0.004272461 -1.4958191 0.13424683q-0.44973755 0.12997437 -0.74243164 0.45394897q-0.2927246 0.3239746 -0.3661499 0.7555847q-0.11279297 0.6628418 0.30685425 1.1750488q0.43777466 0.49884033 1.3982544 0.6251221q0.96047974 0.12631226 1.7749023 -0.19210815q0.8170471 -0.3338318 1.2940063 -0.9960327q0.3604126 -0.53570557 0.54403687 -1.6147461l0.10229492 -0.6011658zm5.703949 9.764496q-1.0694885 -1.9057007 -1.6236572 -4.326721q-0.5515137 -2.4364624 -0.13183594 -4.9028015q0.37249756 -2.1888428 1.4079895 -4.085663q1.230011 -2.202179 3.3404236 -4.272827l1.1928406 0.15686035q-1.4380188 1.7492981 -1.9333496 2.5194397q-0.77279663 1.1906433 -1.3315735 2.5197754q-0.6939392 1.6580505 -0.98773193 3.3844604q-0.7502136 4.4086 1.2597351 9.164337l-1.1928406 -0.15686035zm5.204529 -3.3500366l-1.5336914 -0.20166016l2.282074 -13.410706l1.6421204 0.21594238l-0.81314087 4.778534q1.2763672 -1.1717224 2.9030151 -0.9578247q0.89849854 0.118133545 1.6411133 0.59402466q0.74523926 0.46047974 1.1436768 1.1905212q0.41653442 0.7166748 0.5534973 1.6802673q0.13696289 0.963562 -0.041412354 2.0117493q-0.42492676 2.4971619 -1.8977356 3.7061157q-1.4701538 1.193512 -3.2052002 0.96533203q-1.7350769 -0.22814941 -2.467102 -1.7900391l-0.20721436 1.2177429zm0.82388306 -4.9346924q-0.29641724 1.7418518 0.034576416 2.5891113q0.5749817 1.3678894 1.9072571 1.5430603q1.0844116 0.14260864 2.0318604 -0.67837524q0.95007324 -0.83639526 1.2674866 -2.7015686q0.32263184 -1.8959961 -0.28170776 -2.9052734q-0.6043091 -1.0092773 -1.6732483 -1.1498413q-1.0844116 -0.14257812 -2.0344849 0.69381714q-0.95010376 0.83639526 -1.2517395 2.6090698zm8.363342 6.1427917l0.32003784 -1.8805542l1.8899841 0.24850464l-0.32003784 1.8805847q-0.17575073 1.0327759 -0.65509033 1.6159058q-0.4819641 0.59851074 -1.3297424 0.83374023l-0.3440857 -0.77020264q0.56344604 -0.1465149 0.8873596 -0.5609436q0.3239441 -0.4144287 0.49658203 -1.2427673l-0.9450073 -0.12426758zm11.041382 1.4519348l0.20983887 -1.2331543q-1.1760559 1.3267212 -2.9730835 1.0904236q-1.1618652 -0.152771 -2.0457764 -0.91516113q-0.8658142 -0.77575684 -1.2139282 -1.9877319q-0.32998657 -1.2253418 -0.075531006 -2.7205505q0.24655151 -1.4489746 0.928772 -2.572754q0.6977234 -1.1217346 1.7657471 -1.6274414q1.0835266 -0.5036621 2.29187 -0.34475708q0.8830261 0.116119385 1.501709 0.5757141q0.6341553 0.4616089 0.9656067 1.119812l0.8184204 -4.8093567l1.6421204 0.21594238l-2.282074 13.410706l-1.5336914 -0.20169067zm-4.409912 -5.5441284q-0.3173828 1.8651428 0.31530762 2.893921q0.64819336 1.0307922 1.717102 1.1713562q1.0844116 0.14260864 1.9930115 -0.63619995q0.9086304 -0.7788086 1.2181396 -2.5977478q0.3383789 -1.9884644 -0.2788086 -3.0151978q-0.6145935 -1.0421448 -1.7454834 -1.1908569q-1.099884 -0.1446228 -1.995636 0.65164185q-0.89572144 0.79626465 -1.2236328 2.7230835zm8.773895 10.152435l-1.1773376 -0.15484619q3.4895935 -4.0325623 4.2397766 -8.441132q0.2911682 -1.711029 0.19241333 -3.45755q-0.09188843 -1.4147034 -0.43447876 -2.7520142q-0.21466064 -0.87924194 -1.0047913 -2.937317l1.1773376 0.15481567q1.3442383 2.5249329 1.7718506 4.9450684q0.37423706 2.0822144 0.001739502 4.271057q-0.41967773 2.466339 -1.7736206 4.6522217q-1.3358154 2.1725159 -2.9928894 3.719696z" fill-rule="nonzero"></path><path fill="#000000" fill-opacity="0.0" d="m7.0 5.0l689.98425 0l0 49.007874l-689.98425 0z" fill-rule="nonzero"></path><path fill="#434343" d="m279.24628 31.451248q-0.8125 0.3125 -1.5625 0.46875q-0.75 0.171875 -1.578125 0.171875q-1.296875 0 -2.3125 -0.390625q-1.0 -0.390625 -1.703125 -1.140625q-0.6875 -0.765625 -1.046875 -1.890625q-0.34375 -1.125 -0.34375 -2.625q0 -1.53125 0.390625 -2.71875q0.390625 -1.1875 1.109375 -2.015625q0.71875 -0.828125 1.75 -1.25q1.046875 -0.4375 2.328125 -0.4375q0.421875 0 0.78125 0.03125q0.375 0.015625 0.71875 0.0625q0.359375 0.046875 0.71875 0.140625q0.359375 0.078125 0.75 0.203125l0 2.265625q-0.78125 -0.375 -1.5 -0.53125q-0.71875 -0.15625 -1.296875 -0.15625q-0.859375 0 -1.484375 0.3125q-0.609375 0.3125 -1.0 0.875q-0.390625 0.5625 -0.578125 1.34375q-0.1875 0.765625 -0.1875 1.6875q0 0.984375 0.1875 1.765625q0.1875 0.765625 0.578125 1.3125q0.40625 0.53125 1.03125 0.8125q0.625 0.28125 1.484375 0.28125q0.296875 0 0.65625 -0.046875q0.359375 -0.0625 0.71875 -0.15625q0.375 -0.109375 0.734375 -0.234375q0.359375 -0.140625 0.65625 -0.28125l0 2.140625zm10.726044 -4.3125q0 1.109375 -0.328125 2.03125q-0.3125 0.921875 -0.90625 1.578125q-0.59375 0.65625 -1.453125 1.03125q-0.859375 0.359375 -1.96875 0.359375q-1.046875 0 -1.875 -0.3125q-0.8125 -0.3125 -1.390625 -0.90625q-0.578125 -0.609375 -0.890625 -1.515625q-0.296875 -0.921875 -0.296875 -2.140625q0 -1.125 0.3125 -2.03125q0.328125 -0.921875 0.921875 -1.578125q0.59375 -0.65625 1.453125 -1.0q0.875 -0.359375 1.953125 -0.359375q1.0625 0 1.890625 0.3125q0.828125 0.296875 1.390625 0.921875q0.578125 0.609375 0.875 1.515625q0.3125 0.90625 0.3125 2.09375zm-2.359375 0.046875q0 -1.46875 -0.5625 -2.203125q-0.546875 -0.734375 -1.625 -0.734375q-0.59375 0 -1.015625 0.234375q-0.40625 0.234375 -0.671875 0.640625q-0.265625 0.390625 -0.390625 0.9375q-0.125 0.53125 -0.125 1.140625q0 1.484375 0.59375 2.234375q0.59375 0.734375 1.609375 0.734375q0.578125 0 0.984375 -0.21875q0.421875 -0.234375 0.671875 -0.625q0.265625 -0.40625 0.390625 -0.953125q0.140625 -0.546875 0.140625 -1.1875zm9.741669 4.734375l0 -6.140625q0 -1.546875 -1.140625 -1.546875q-0.578125 0 -1.109375 0.46875q-0.515625 0.453125 -1.109375 1.25l0 5.96875l-2.25 0l0 -9.421875l1.953125 0l0.046875 1.390625q0.296875 -0.359375 0.609375 -0.65625q0.3125 -0.296875 0.671875 -0.5q0.359375 -0.21875 0.765625 -0.328125q0.421875 -0.109375 0.953125 -0.109375q0.71875 0 1.25 0.234375q0.546875 0.234375 0.90625 0.671875q0.359375 0.421875 0.53125 1.03125q0.1875 0.609375 0.1875 1.359375l0 6.328125l-2.265625 0zm9.913544 0l-2.609375 0l-3.734375 -9.421875l2.515625 0l1.953125 5.34375l0.59375 1.71875l0.578125 -1.65625l1.96875 -5.40625l2.4375 0l-3.703125 9.421875zm13.194794 -5.4375q0 0.234375 -0.015625 0.609375q-0.015625 0.359375 -0.046875 0.6875l-6.1875 0q0 0.625 0.1875 1.109375q0.1875 0.46875 0.53125 0.78125q0.359375 0.3125 0.84375 0.484375q0.484375 0.171875 1.078125 0.171875q0.6875 0 1.46875 -0.109375q0.78125 -0.109375 1.625 -0.34375l0 1.796875q-0.359375 0.09375 -0.78125 0.1875q-0.421875 0.078125 -0.875 0.140625q-0.4375 0.078125 -0.90625 0.109375q-0.453125 0.03125 -0.875 0.03125q-1.078125 0 -1.9375 -0.3125q-0.84375 -0.3125 -1.4375 -0.90625q-0.59375 -0.59375 -0.90625 -1.46875q-0.3125 -0.890625 -0.3125 -2.046875q0 -1.15625 0.3125 -2.09375q0.3125 -0.9375 0.890625 -1.609375q0.578125 -0.671875 1.390625 -1.03125q0.828125 -0.375 1.828125 -0.375q1.015625 0 1.78125 0.3125q0.765625 0.296875 1.28125 0.859375q0.53125 0.5625 0.796875 1.328125q0.265625 0.765625 0.265625 1.6875zm-2.296875 -0.328125q0 -0.546875 -0.15625 -0.953125q-0.140625 -0.421875 -0.390625 -0.6875q-0.25 -0.28125 -0.59375 -0.40625q-0.34375 -0.125 -0.734375 -0.125q-0.84375 0 -1.390625 0.578125q-0.546875 0.5625 -0.65625 1.59375l3.921875 0zm9.960419 5.765625l0 -6.140625q0 -1.546875 -1.140625 -1.546875q-0.578125 0 -1.109375 0.46875q-0.515625 0.453125 -1.109375 1.25l0 5.96875l-2.25 0l0 -9.421875l1.953125 0l0.046875 1.390625q0.296875 -0.359375 0.609375 -0.65625q0.3125 -0.296875 0.671875 -0.5q0.359375 -0.21875 0.765625 -0.328125q0.421875 -0.109375 0.953125 -0.109375q0.71875 0 1.25 0.234375q0.546875 0.234375 0.90625 0.671875q0.359375 0.421875 0.53125 1.03125q0.1875 0.609375 0.1875 1.359375l0 6.328125l-2.265625 0zm12.413544 -0.09375q-0.609375 0.140625 -1.234375 0.21875q-0.625 0.09375 -1.171875 0.09375q-0.9375 0 -1.609375 -0.203125q-0.671875 -0.1875 -1.109375 -0.578125q-0.4375 -0.40625 -0.65625 -1.015625q-0.203125 -0.625 -0.203125 -1.484375l0 -4.59375l-2.53125 0l0 -1.765625l2.53125 0l0 -2.421875l2.328125 -0.59375l0 3.015625l3.65625 0l0 1.765625l-3.65625 0l0 4.421875q0 0.8125 0.359375 1.234375q0.375 0.40625 1.25 0.40625q0.5625 0 1.078125 -0.09375q0.53125 -0.09375 0.96875 -0.21875l0 1.8125zm8.038544 -11.90625q0 0.296875 -0.125 0.578125q-0.109375 0.265625 -0.3125 0.46875q-0.1875 0.1875 -0.46875 0.3125q-0.265625 0.109375 -0.578125 0.109375q-0.3125 0 -0.59375 -0.109375q-0.265625 -0.125 -0.46875 -0.3125q-0.203125 -0.203125 -0.3125 -0.46875q-0.109375 -0.28125 -0.109375 -0.578125q0 -0.3125 0.109375 -0.578125q0.109375 -0.265625 0.3125 -0.46875q0.203125 -0.203125 0.46875 -0.3125q0.28125 -0.125 0.59375 -0.125q0.3125 0 0.578125 0.125q0.28125 0.109375 0.46875 0.3125q0.203125 0.203125 0.3125 0.46875q0.125 0.265625 0.125 0.578125zm-2.515625 4.34375l-2.65625 0l0 -1.765625l4.984375 0l0 7.65625l2.71875 0l0 1.765625l-8.03125 0l0 -1.765625l2.984375 0l0 -5.890625zm15.710419 2.875q0 1.109375 -0.328125 2.03125q-0.3125 0.921875 -0.90625 1.578125q-0.59375 0.65625 -1.453125 1.03125q-0.859375 0.359375 -1.96875 0.359375q-1.046875 0 -1.875 -0.3125q-0.8125 -0.3125 -1.390625 -0.90625q-0.578125 -0.609375 -0.890625 -1.515625q-0.296875 -0.921875 -0.296875 -2.140625q0 -1.125 0.3125 -2.03125q0.328125 -0.921875 0.921875 -1.578125q0.59375 -0.65625 1.453125 -1.0q0.875 -0.359375 1.953125 -0.359375q1.0625 0 1.890625 0.3125q0.828125 0.296875 1.390625 0.921875q0.578125 0.609375 0.875 1.515625q0.3125 0.90625 0.3125 2.09375zm-2.359375 0.046875q0 -1.46875 -0.5625 -2.203125q-0.546875 -0.734375 -1.625 -0.734375q-0.59375 0 -1.015625 0.234375q-0.40625 0.234375 -0.671875 0.640625q-0.265625 0.390625 -0.390625 0.9375q-0.125 0.53125 -0.125 1.140625q0 1.484375 0.59375 2.234375q0.59375 0.734375 1.609375 0.734375q0.578125 0 0.984375 -0.21875q0.421875 -0.234375 0.671875 -0.625q0.265625 -0.40625 0.390625 -0.953125q0.140625 -0.546875 0.140625 -1.1875zm9.741669 4.734375l0 -6.140625q0 -1.546875 -1.140625 -1.546875q-0.578125 0 -1.109375 0.46875q-0.515625 0.453125 -1.109375 1.25l0 5.96875l-2.25 0l0 -9.421875l1.953125 0l0.046875 1.390625q0.296875 -0.359375 0.609375 -0.65625q0.3125 -0.296875 0.671875 -0.5q0.359375 -0.21875 0.765625 -0.328125q0.421875 -0.109375 0.953125 -0.109375q0.71875 0 1.25 0.234375q0.546875 0.234375 0.90625 0.671875q0.359375 0.421875 0.53125 1.03125q0.1875 0.609375 0.1875 1.359375l0 6.328125l-2.265625 0zm10.554169 0l-0.0625 -1.234375q-0.296875 0.3125 -0.625 0.578125q-0.3125 0.265625 -0.703125 0.46875q-0.390625 0.1875 -0.859375 0.296875q-0.453125 0.109375 -1.0 0.109375q-0.71875 0 -1.265625 -0.21875q-0.546875 -0.21875 -0.921875 -0.59375q-0.375 -0.375 -0.5625 -0.90625q-0.1875 -0.546875 -0.1875 -1.203125q0 -0.671875 0.28125 -1.234375q0.28125 -0.5625 0.859375 -0.96875q0.578125 -0.40625 1.4375 -0.640625q0.875 -0.234375 2.046875 -0.234375l1.234375 0l0 -0.5625q0 -0.359375 -0.109375 -0.65625q-0.09375 -0.296875 -0.328125 -0.5q-0.21875 -0.203125 -0.578125 -0.3125q-0.359375 -0.109375 -0.890625 -0.109375q-0.84375 0 -1.65625 0.1875q-0.8125 0.1875 -1.5625 0.53125l0 -1.8125q0.671875 -0.265625 1.546875 -0.4375q0.890625 -0.171875 1.859375 -0.171875q1.046875 0 1.796875 0.203125q0.75 0.1875 1.234375 0.59375q0.484375 0.390625 0.71875 1.0q0.234375 0.59375 0.234375 1.390625l0 6.4375l-1.9375 0zm-0.328125 -4.171875l-1.375 0q-0.578125 0 -0.984375 0.125q-0.390625 0.109375 -0.640625 0.3125q-0.25 0.1875 -0.375 0.4375q-0.109375 0.25 -0.109375 0.546875q0 0.5625 0.359375 0.875q0.375 0.296875 1.015625 0.296875q0.46875 0 0.984375 -0.34375q0.515625 -0.34375 1.125 -0.984375l0 -1.265625zm7.7104187 -7.171875l-2.65625 0l0 -1.765625l4.984375 0l0 11.34375l2.71875 0l0 1.765625l-8.03125 0l0 -1.765625l2.984375 0l0 -9.578125zm23.498962 11.34375l-1.703125 -3.890625q-0.25 -0.5625 -0.6875 -0.84375q-0.421875 -0.28125 -1.0 -0.28125l-0.4375 0l0 5.015625l-2.28125 0l0 -12.125l3.53125 0q1.0 0 1.8125 0.171875q0.8125 0.171875 1.390625 0.578125q0.578125 0.390625 0.890625 1.03125q0.3125 0.640625 0.3125 1.5625q0 0.671875 -0.203125 1.203125q-0.1875 0.515625 -0.546875 0.890625q-0.34375 0.375 -0.84375 0.609375q-0.484375 0.21875 -1.046875 0.3125q0.4375 0.09375 0.8125 0.515625q0.375 0.40625 0.734375 1.1875l1.9375 4.0625l-2.671875 0zm-0.5625 -8.546875q0 -0.890625 -0.578125 -1.28125q-0.5625 -0.390625 -1.6875 -0.390625l-1.0 0l0 3.421875l0.921875 0q0.53125 0 0.953125 -0.109375q0.4375 -0.109375 0.734375 -0.328125q0.3125 -0.234375 0.484375 -0.5625q0.171875 -0.328125 0.171875 -0.75zm13.179169 0.28125q0 0.953125 -0.328125 1.75q-0.3125 0.796875 -0.9375 1.390625q-0.609375 0.578125 -1.546875 0.90625q-0.921875 0.328125 -2.140625 0.328125l-1.171875 0l0 3.890625l-2.296875 0l0 -12.125l3.5625 0q1.171875 0 2.078125 0.265625q0.90625 0.25 1.515625 0.75q0.625 0.484375 0.9375 1.203125q0.328125 0.71875 0.328125 1.640625zm-2.390625 0.15625q0 -0.484375 -0.15625 -0.875q-0.15625 -0.390625 -0.46875 -0.671875q-0.3125 -0.28125 -0.78125 -0.421875q-0.46875 -0.15625 -1.125 -0.15625l-1.203125 0l0 4.4375l1.28125 0q0.59375 0 1.046875 -0.15625q0.453125 -0.15625 0.765625 -0.453125q0.3125 -0.3125 0.46875 -0.734375q0.171875 -0.4375 0.171875 -0.96875zm12.288544 7.640625q-0.8125 0.3125 -1.5625 0.46875q-0.75 0.171875 -1.578125 0.171875q-1.296875 0 -2.3125 -0.390625q-1.0 -0.390625 -1.703125 -1.140625q-0.6875 -0.765625 -1.046875 -1.890625q-0.34375 -1.125 -0.34375 -2.625q0 -1.53125 0.390625 -2.71875q0.390625 -1.1875 1.109375 -2.015625q0.71875 -0.828125 1.75 -1.25q1.046875 -0.4375 2.328125 -0.4375q0.421875 0 0.78125 0.03125q0.375 0.015625 0.71875 0.0625q0.359375 0.046875 0.71875 0.140625q0.359375 0.078125 0.75 0.203125l0 2.265625q-0.78125 -0.375 -1.5 -0.53125q-0.71875 -0.15625 -1.296875 -0.15625q-0.859375 0 -1.484375 0.3125q-0.609375 0.3125 -1.0 0.875q-0.390625 0.5625 -0.578125 1.34375q-0.1875 0.765625 -0.1875 1.6875q0 0.984375 0.1875 1.765625q0.1875 0.765625 0.578125 1.3125q0.40625 0.53125 1.03125 0.8125q0.625 0.28125 1.484375 0.28125q0.296875 0 0.65625 -0.046875q0.359375 -0.0625 0.71875 -0.15625q0.375 -0.109375 0.734375 -0.234375q0.359375 -0.140625 0.65625 -0.28125l0 2.140625z" fill-rule="nonzero"></path></g></svg> + diff --git a/chapter/2/images/p-2.png b/chapter/2/images/p-2.png Binary files differnew file mode 100644 index 0000000..ccc5d09 --- /dev/null +++ b/chapter/2/images/p-2.png diff --git a/chapter/2/images/p-2.svg b/chapter/2/images/p-2.svg new file mode 100644 index 0000000..f5c6b05 --- /dev/null +++ b/chapter/2/images/p-2.svg @@ -0,0 +1,4 @@ +<?xml version="1.0" standalone="yes"?> + +<svg version="1.1" viewBox="0.0 0.0 720.0 540.0" fill="none" stroke="none" stroke-linecap="square" stroke-miterlimit="10" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><clipPath id="p.0"><path d="m0 0l720.0 0l0 540.0l-720.0 0l0 -540.0z" clip-rule="nonzero"></path></clipPath><g clip-path="url(#p.0)"><path fill="#000000" fill-opacity="0.0" d="m0 0l720.0 0l0 540.0l-720.0 0z" fill-rule="nonzero"></path><path fill="#000000" fill-opacity="0.0" d="m40.0 88.13911l613.98425 0l0 44.000008l-613.98425 0z" fill-rule="nonzero"></path><path fill="#000000" d="m151.20563 109.902855q0 0.34375 -0.015625 0.578125q-0.015625 0.234375 -0.03125 0.4375l-6.53125 0q0 1.4375 0.796875 2.203125q0.796875 0.765625 2.296875 0.765625q0.40625 0 0.8125 -0.03125q0.40625 -0.046875 0.78125 -0.09375q0.390625 -0.0625 0.734375 -0.125q0.34375 -0.078125 0.640625 -0.15625l0 1.328125q-0.65625 0.1875 -1.484375 0.296875q-0.828125 0.125 -1.71875 0.125q-1.203125 0 -2.0625 -0.328125q-0.859375 -0.328125 -1.421875 -0.9375q-0.546875 -0.625 -0.8125 -1.515625q-0.265625 -0.890625 -0.265625 -2.03125q0 -0.984375 0.28125 -1.859375q0.296875 -0.875 0.828125 -1.53125q0.546875 -0.671875 1.328125 -1.0625q0.796875 -0.390625 1.796875 -0.390625q0.984375 0 1.734375 0.3125q0.75 0.296875 1.265625 0.859375q0.515625 0.5625 0.78125 1.375q0.265625 0.796875 0.265625 1.78125zm-1.6875 -0.21875q0.03125 -0.625 -0.125 -1.140625q-0.140625 -0.515625 -0.453125 -0.890625q-0.3125 -0.375 -0.78125 -0.578125q-0.453125 -0.203125 -1.078125 -0.203125q-0.515625 0 -0.953125 0.203125q-0.4375 0.203125 -0.765625 0.578125q-0.3125 0.359375 -0.5 0.890625q-0.1875 0.515625 -0.234375 1.140625l4.890625 0zm12.460419 5.375l-2.140625 0l-2.515625 -3.546875l-2.484375 3.546875l-2.078125 0l3.609375 -4.671875l-3.453125 -4.640625l2.078125 0l2.4375 3.578125l2.40625 -3.578125l2.0 0l-3.5 4.671875l3.640625 4.640625zm9.819794 -4.828125q0 1.25 -0.34375 2.1875q-0.34375 0.921875 -0.953125 1.53125q-0.609375 0.609375 -1.453125 0.921875q-0.828125 0.296875 -1.8125 0.296875q-0.4375 0 -0.890625 -0.046875q-0.4375 -0.046875 -0.890625 -0.15625l0 3.890625l-1.609375 0l0 -13.109375l1.4375 0l0.109375 1.5625q0.6875 -0.96875 1.46875 -1.34375q0.796875 -0.390625 1.71875 -0.390625q0.796875 0 1.390625 0.34375q0.609375 0.328125 1.015625 0.9375q0.40625 0.609375 0.609375 1.46875q0.203125 0.859375 0.203125 1.90625zm-1.640625 0.078125q0 -0.734375 -0.109375 -1.34375q-0.109375 -0.609375 -0.34375 -1.046875q-0.234375 -0.4375 -0.59375 -0.6875q-0.359375 -0.25 -0.859375 -0.25q-0.3125 0 -0.625 0.109375q-0.3125 0.09375 -0.65625 0.328125q-0.328125 0.21875 -0.703125 0.59375q-0.375 0.375 -0.8125 0.9375l0 4.515625q0.453125 0.1875 0.9375 0.296875q0.5 0.09375 0.96875 0.09375q1.3125 0 2.046875 -0.875q0.75 -0.890625 0.75 -2.671875zm21.936462 -1.25l-7.984375 0l0 -1.359375l7.984375 0l0 1.359375zm0 3.234375l-7.984375 0l0 -1.359375l7.984375 0l0 1.359375z" fill-rule="nonzero"></path><path fill="#0000ff" d="m210.85876 115.059105l-0.03125 -1.25q-0.765625 0.75 -1.546875 1.09375q-0.78125 0.328125 -1.65625 0.328125q-0.796875 0 -1.359375 -0.203125q-0.5625 -0.203125 -0.9375 -0.5625q-0.359375 -0.359375 -0.53125 -0.84375q-0.171875 -0.484375 -0.171875 -1.046875q0 -1.40625 1.046875 -2.1875q1.046875 -0.796875 3.078125 -0.796875l1.9375 0l0 -0.828125q0 -0.8125 -0.53125 -1.3125q-0.53125 -0.5 -1.609375 -0.5q-0.796875 0 -1.5625 0.1875q-0.765625 0.171875 -1.578125 0.484375l0 -1.453125q0.296875 -0.109375 0.671875 -0.21875q0.390625 -0.109375 0.796875 -0.1875q0.421875 -0.078125 0.875 -0.125q0.453125 -0.0625 0.921875 -0.0625q0.84375 0 1.515625 0.1875q0.6875 0.1875 1.15625 0.578125q0.46875 0.375 0.71875 0.953125q0.25 0.5625 0.25 1.34375l0 6.421875l-1.453125 0zm-0.171875 -4.234375l-2.0625 0q-0.59375 0 -1.03125 0.125q-0.4375 0.109375 -0.71875 0.34375q-0.28125 0.21875 -0.421875 0.53125q-0.125 0.296875 -0.125 0.6875q0 0.28125 0.078125 0.53125q0.09375 0.234375 0.28125 0.421875q0.1875 0.1875 0.484375 0.3125q0.296875 0.109375 0.71875 0.109375q0.5625 0 1.28125 -0.34375q0.71875 -0.34375 1.515625 -1.078125l0 -1.640625z" fill-rule="nonzero"></path><path fill="#980000" d="m230.9671 118.94973q-4.28125 -3.953125 -4.28125 -8.75q0 -1.125 0.21875 -2.234375q0.234375 -1.125 0.734375 -2.25q0.515625 -1.125 1.34375 -2.234375q0.828125 -1.125 2.015625 -2.234375l0.9375 0.953125q-3.59375 3.546875 -3.59375 7.875q0 2.15625 0.90625 4.140625q0.90625 1.984375 2.6875 3.75l-0.96875 0.984375z" fill-rule="nonzero"></path><path fill="#0000ff" d="m253.85669 110.23098q0 1.15625 -0.328125 2.078125q-0.3125 0.90625 -0.90625 1.546875q-0.578125 0.640625 -1.421875 0.984375q-0.84375 0.328125 -1.90625 0.328125q-0.828125 0 -1.6875 -0.15625q-0.859375 -0.15625 -1.703125 -0.5l0 -12.5625l1.609375 0l0 3.609375l-0.0625 1.71875q0.6875 -0.9375 1.484375 -1.3125q0.796875 -0.390625 1.703125 -0.390625q0.796875 0 1.390625 0.34375q0.609375 0.328125 1.015625 0.9375q0.40625 0.609375 0.609375 1.46875q0.203125 0.859375 0.203125 1.90625zm-1.640625 0.078125q0 -0.734375 -0.109375 -1.34375q-0.109375 -0.609375 -0.34375 -1.046875q-0.234375 -0.4375 -0.59375 -0.6875q-0.359375 -0.25 -0.859375 -0.25q-0.3125 0 -0.625 0.109375q-0.3125 0.09375 -0.65625 0.328125q-0.328125 0.21875 -0.703125 0.59375q-0.375 0.375 -0.8125 0.9375l0 4.515625q0.484375 0.1875 0.96875 0.296875q0.5 0.09375 0.9375 0.09375q0.5625 0 1.0625 -0.171875q0.5 -0.171875 0.890625 -0.578125q0.390625 -0.421875 0.609375 -1.09375q0.234375 -0.6875 0.234375 -1.703125z" fill-rule="nonzero"></path><path fill="#980000" d="m271.99628 118.94973q-4.28125 -3.953125 -4.28125 -8.75q0 -1.125 0.21875 -2.234375q0.234375 -1.125 0.734375 -2.25q0.515625 -1.125 1.34375 -2.234375q0.828125 -1.125 2.015625 -2.234375l0.9375 0.953125q-3.59375 3.546875 -3.59375 7.875q0 2.15625 0.90625 4.140625q0.90625 1.984375 2.6875 3.75l-0.96875 0.984375z" fill-rule="nonzero"></path><path fill="#0000ff" d="m294.1671 114.715355q-0.625 0.234375 -1.296875 0.34375q-0.65625 0.125 -1.359375 0.125q-2.21875 0 -3.40625 -1.1875q-1.1875 -1.203125 -1.1875 -3.5q0 -1.109375 0.34375 -2.0q0.34375 -0.90625 0.953125 -1.546875q0.625 -0.640625 1.484375 -0.984375q0.875 -0.34375 1.90625 -0.34375q0.734375 0 1.359375 0.109375q0.625 0.09375 1.203125 0.3125l0 1.546875q-0.59375 -0.3125 -1.234375 -0.453125q-0.625 -0.15625 -1.28125 -0.15625q-0.625 0 -1.1875 0.25q-0.546875 0.234375 -0.96875 0.6875q-0.40625 0.4375 -0.65625 1.078125q-0.234375 0.640625 -0.234375 1.4375q0 1.6875 0.8125 2.53125q0.828125 0.84375 2.28125 0.84375q0.65625 0 1.265625 -0.140625q0.625 -0.15625 1.203125 -0.453125l0 1.5z" fill-rule="nonzero"></path><path fill="#980000" d="m313.02545 118.94973q-4.28125 -3.953125 -4.28125 -8.75q0 -1.125 0.21875 -2.234375q0.234375 -1.125 0.734375 -2.25q0.515625 -1.125 1.34375 -2.234375q0.828125 -1.125 2.015625 -2.234375l0.9375 0.953125q-3.59375 3.546875 -3.59375 7.875q0 2.15625 0.90625 4.140625q0.90625 1.984375 2.6875 3.75l-0.96875 0.984375zm6.5854187 -17.703125q4.265625 3.953125 4.265625 8.8125q0 1.0 -0.203125 2.078125q-0.203125 1.078125 -0.703125 2.203125q-0.484375 1.125 -1.3125 2.28125q-0.828125 1.171875 -2.09375 2.328125l-0.9375 -0.953125q1.8125 -1.78125 2.703125 -3.734375q0.890625 -1.953125 0.890625 -4.078125q0 -4.421875 -3.59375 -7.953125l0.984375 -0.984375z" fill-rule="nonzero"></path><path fill="#980000" d="m340.12546 101.246605q4.265625 3.953125 4.265625 8.8125q0 1.0 -0.203125 2.078125q-0.203125 1.078125 -0.703125 2.203125q-0.484375 1.125 -1.3125 2.28125q-0.828125 1.171875 -2.09375 2.328125l-0.9375 -0.953125q1.8125 -1.78125 2.703125 -3.734375q0.890625 -1.953125 0.890625 -4.078125q0 -4.421875 -3.59375 -7.953125l0.984375 -0.984375z" fill-rule="nonzero"></path><path fill="#000000" d="m349.19525 116.965355q0.484375 0.015625 0.921875 -0.09375q0.453125 -0.09375 0.78125 -0.296875q0.34375 -0.203125 0.546875 -0.5q0.203125 -0.296875 0.203125 -0.671875q0 -0.390625 -0.140625 -0.625q-0.125 -0.25 -0.296875 -0.453125q-0.171875 -0.203125 -0.3125 -0.4375q-0.125 -0.234375 -0.125 -0.625q0 -0.1875 0.078125 -0.390625q0.078125 -0.21875 0.21875 -0.390625q0.15625 -0.1875 0.390625 -0.296875q0.25 -0.109375 0.5625 -0.109375q0.328125 0 0.625 0.140625q0.3125 0.125 0.53125 0.40625q0.234375 0.28125 0.359375 0.703125q0.140625 0.40625 0.140625 0.96875q0 0.78125 -0.28125 1.484375q-0.28125 0.703125 -0.84375 1.25q-0.5625 0.5625 -1.40625 0.875q-0.828125 0.328125 -1.953125 0.328125l0 -1.265625z" fill-rule="nonzero"></path><path fill="#0000ff" d="m368.52234 110.590355q0 -1.1875 0.3125 -2.109375q0.328125 -0.921875 0.921875 -1.546875q0.609375 -0.640625 1.4375 -0.96875q0.84375 -0.328125 1.875 -0.328125q0.453125 0 0.875 0.0625q0.4375 0.046875 0.859375 0.171875l0 -3.921875l1.625 0l0 13.109375l-1.453125 0l-0.0625 -1.765625q-0.671875 0.984375 -1.46875 1.46875q-0.78125 0.46875 -1.703125 0.46875q-0.796875 0 -1.40625 -0.328125q-0.59375 -0.34375 -1.0 -0.953125q-0.40625 -0.609375 -0.609375 -1.453125q-0.203125 -0.859375 -0.203125 -1.90625zm1.640625 -0.09375q0 1.6875 0.5 2.515625q0.5 0.828125 1.40625 0.828125q0.609375 0 1.296875 -0.546875q0.6875 -0.546875 1.4375 -1.625l0 -4.3125q-0.40625 -0.1875 -0.890625 -0.28125q-0.484375 -0.109375 -0.953125 -0.109375q-1.3125 0 -2.0625 0.859375q-0.734375 0.84375 -0.734375 2.671875z" fill-rule="nonzero"></path><path fill="#980000" d="m395.0838 118.94973q-4.28125 -3.953125 -4.28125 -8.75q0 -1.125 0.21875 -2.234375q0.234375 -1.125 0.734375 -2.25q0.515625 -1.125 1.34375 -2.234375q0.828125 -1.125 2.015625 -2.234375l0.9375 0.953125q-3.59375 3.546875 -3.59375 7.875q0 2.15625 0.90625 4.140625q0.90625 1.984375 2.6875 3.75l-0.96875 0.984375z" fill-rule="nonzero"></path><path fill="#0000ff" d="m417.89526 109.902855q0 0.34375 -0.015625 0.578125q-0.015625 0.234375 -0.03125 0.4375l-6.53125 0q0 1.4375 0.796875 2.203125q0.796875 0.765625 2.296875 0.765625q0.40625 0 0.8125 -0.03125q0.40625 -0.046875 0.78125 -0.09375q0.390625 -0.0625 0.734375 -0.125q0.34375 -0.078125 0.640625 -0.15625l0 1.328125q-0.65625 0.1875 -1.484375 0.296875q-0.828125 0.125 -1.71875 0.125q-1.203125 0 -2.0625 -0.328125q-0.859375 -0.328125 -1.421875 -0.9375q-0.546875 -0.625 -0.8125 -1.515625q-0.265625 -0.890625 -0.265625 -2.03125q0 -0.984375 0.28125 -1.859375q0.296875 -0.875 0.828125 -1.53125q0.546875 -0.671875 1.328125 -1.0625q0.796875 -0.390625 1.796875 -0.390625q0.984375 0 1.734375 0.3125q0.75 0.296875 1.265625 0.859375q0.515625 0.5625 0.78125 1.375q0.265625 0.796875 0.265625 1.78125zm-1.6875 -0.21875q0.03125 -0.625 -0.125 -1.140625q-0.140625 -0.515625 -0.453125 -0.890625q-0.3125 -0.375 -0.78125 -0.578125q-0.453125 -0.203125 -1.078125 -0.203125q-0.515625 0 -0.953125 0.203125q-0.4375 0.203125 -0.765625 0.578125q-0.3125 0.359375 -0.5 0.890625q-0.1875 0.515625 -0.234375 1.140625l4.890625 0z" fill-rule="nonzero"></path><path fill="#980000" d="m436.11298 118.94973q-4.28125 -3.953125 -4.28125 -8.75q0 -1.125 0.21875 -2.234375q0.234375 -1.125 0.734375 -2.25q0.515625 -1.125 1.34375 -2.234375q0.828125 -1.125 2.015625 -2.234375l0.9375 0.953125q-3.59375 3.546875 -3.59375 7.875q0 2.15625 0.90625 4.140625q0.90625 1.984375 2.6875 3.75l-0.96875 0.984375zm6.5854187 -17.703125q4.265625 3.953125 4.265625 8.8125q0 1.0 -0.203125 2.078125q-0.203125 1.078125 -0.703125 2.203125q-0.484375 1.125 -1.3125 2.28125q-0.828125 1.171875 -2.09375 2.328125l-0.9375 -0.953125q1.8125 -1.78125 2.703125 -3.734375q0.890625 -1.953125 0.890625 -4.078125q0 -4.421875 -3.59375 -7.953125l0.984375 -0.984375z" fill-rule="nonzero"></path><path fill="#000000" d="m451.7682 116.965355q0.484375 0.015625 0.921875 -0.09375q0.453125 -0.09375 0.78125 -0.296875q0.34375 -0.203125 0.546875 -0.5q0.203125 -0.296875 0.203125 -0.671875q0 -0.390625 -0.140625 -0.625q-0.125 -0.25 -0.296875 -0.453125q-0.171875 -0.203125 -0.3125 -0.4375q-0.125 -0.234375 -0.125 -0.625q0 -0.1875 0.078125 -0.390625q0.078125 -0.21875 0.21875 -0.390625q0.15625 -0.1875 0.390625 -0.296875q0.25 -0.109375 0.5625 -0.109375q0.328125 0 0.625 0.140625q0.3125 0.125 0.53125 0.40625q0.234375 0.28125 0.359375 0.703125q0.140625 0.40625 0.140625 0.96875q0 0.78125 -0.28125 1.484375q-0.28125 0.703125 -0.84375 1.25q-0.5625 0.5625 -1.40625 0.875q-0.828125 0.328125 -1.953125 0.328125l0 -1.265625z" fill-rule="nonzero"></path><path fill="#0000ff" d="m479.82965 103.44973q-1.265625 -0.265625 -2.1875 -0.265625q-2.1875 0 -2.1875 2.28125l0 1.640625l4.09375 0l0 1.34375l-4.09375 0l0 6.609375l-1.640625 0l0 -6.609375l-2.984375 0l0 -1.34375l2.984375 0l0 -1.546875q0 -3.71875 3.875 -3.71875q0.96875 0 2.140625 0.21875l0 1.390625zm-9.75 2.296875l0 0z" fill-rule="nonzero"></path><path fill="#980000" d="m497.65674 118.94973q-4.28125 -3.953125 -4.28125 -8.75q0 -1.125 0.21875 -2.234375q0.234375 -1.125 0.734375 -2.25q0.515625 -1.125 1.34375 -2.234375q0.828125 -1.125 2.015625 -2.234375l0.9375 0.953125q-3.59375 3.546875 -3.59375 7.875q0 2.15625 0.90625 4.140625q0.90625 1.984375 2.6875 3.75l-0.96875 0.984375zm6.5854187 -17.703125q4.265625 3.953125 4.265625 8.8125q0 1.0 -0.203125 2.078125q-0.203125 1.078125 -0.703125 2.203125q-0.484375 1.125 -1.3125 2.28125q-0.828125 1.171875 -2.09375 2.328125l-0.9375 -0.953125q1.8125 -1.78125 2.703125 -3.734375q0.890625 -1.953125 0.890625 -4.078125q0 -4.421875 -3.59375 -7.953125l0.984375 -0.984375z" fill-rule="nonzero"></path><path fill="#980000" d="m524.7567 101.246605q4.265625 3.953125 4.265625 8.8125q0 1.0 -0.203125 2.078125q-0.203125 1.078125 -0.703125 2.203125q-0.484375 1.125 -1.3125 2.28125q-0.828125 1.171875 -2.09375 2.328125l-0.9375 -0.953125q1.8125 -1.78125 2.703125 -3.734375q0.890625 -1.953125 0.890625 -4.078125q0 -4.421875 -3.59375 -7.953125l0.984375 -0.984375zm20.514648 0q4.265625 3.953125 4.265625 8.8125q0 1.0 -0.203125 2.078125q-0.203125 1.078125 -0.703125 2.203125q-0.484375 1.125 -1.3125 2.28125q-0.828125 1.171875 -2.09375 2.328125l-0.9375 -0.953125q1.8125 -1.78125 2.703125 -3.734375q0.890625 -1.953125 0.890625 -4.078125q0 -4.421875 -3.59375 -7.953125l0.984375 -0.984375z" fill-rule="nonzero"></path><path fill="#000000" fill-opacity="0.0" d="m349.9367 132.14035l22.677155 2.9606323l-2.551178 14.992126l-22.677155 -2.9606323z" fill-rule="nonzero"></path><path fill="#e06666" d="m360.83054 154.24348l1.5900879 0.4282074q-0.5466919 1.6304474 -1.8093567 2.442566q-1.2600403 0.79670715 -2.8713684 0.5863342q-1.9986572 -0.2609253 -3.0023193 -1.7156067q-0.98550415 -1.4680481 -0.5710449 -3.9036407q0.2675476 -1.5723419 0.97821045 -2.6771545q0.72875977 -1.1181793 1.8974915 -1.5643921q1.1868286 -0.45959473 2.441803 -0.29574585q1.5958557 0.2083435 2.4665222 1.1414032q0.8706665 0.93307495 0.913208 2.451355l-1.6532898 0.03627014q-0.06451416 -1.0169067 -0.56933594 -1.5870514q-0.50479126 -0.57014465 -1.3259583 -0.6773529q-1.2549744 -0.16384888 -2.1972961 0.6270752q-0.92681885 0.79293823 -1.2546997 2.719818q-0.3331604 1.9577332 0.27389526 2.9509277q0.60964966 0.97776794 1.8181458 1.1355438q0.97610474 0.1274414 1.7265015 -0.37338257q0.75302124 -0.51623535 1.1488037 -1.725174z" fill-rule="nonzero"></path><path fill="#000000" fill-opacity="0.0" d="m7.0 5.0l689.98425 0l0 49.007874l-689.98425 0z" fill-rule="nonzero"></path><path fill="#434343" d="m284.5312 31.919998l-2.6875 0l-1.203125 -3.734375l-0.421875 -1.53125l-0.421875 1.5625l-1.1875 3.703125l-2.5625 0l-0.671875 -12.125l2.0 0l0.296875 7.78125l0.078125 2.109375l0.546875 -1.890625l1.328125 -4.3125l1.4375 0l1.40625 4.578125l0.46875 1.609375l0.03125 -1.890625l0.296875 -7.984375l1.953125 0l-0.6875 12.125zm7.6322937 -12.0q0 0.296875 -0.125 0.578125q-0.109375 0.265625 -0.3125 0.46875q-0.1875 0.1875 -0.46875 0.3125q-0.265625 0.109375 -0.578125 0.109375q-0.3125 0 -0.59375 -0.109375q-0.265625 -0.125 -0.46875 -0.3125q-0.203125 -0.203125 -0.3125 -0.46875q-0.109375 -0.28125 -0.109375 -0.578125q0 -0.3125 0.109375 -0.578125q0.109375 -0.265625 0.3125 -0.46875q0.203125 -0.203125 0.46875 -0.3125q0.28125 -0.125 0.59375 -0.125q0.3125 0 0.578125 0.125q0.28125 0.109375 0.46875 0.3125q0.203125 0.203125 0.3125 0.46875q0.125 0.265625 0.125 0.578125zm-2.515625 4.34375l-2.65625 0l0 -1.765625l4.984375 0l0 7.65625l2.71875 0l0 1.765625l-8.03125 0l0 -1.765625l2.984375 0l0 -5.890625zm14.991669 7.5625q-0.609375 0.140625 -1.234375 0.21875q-0.625 0.09375 -1.171875 0.09375q-0.9375 0 -1.609375 -0.203125q-0.671875 -0.1875 -1.109375 -0.578125q-0.4375 -0.40625 -0.65625 -1.015625q-0.203125 -0.625 -0.203125 -1.484375l0 -4.59375l-2.53125 0l0 -1.765625l2.53125 0l0 -2.421875l2.328125 -0.59375l0 3.015625l3.65625 0l0 1.765625l-3.65625 0l0 4.421875q0 0.8125 0.359375 1.234375q0.375 0.40625 1.25 0.40625q0.5625 0 1.078125 -0.09375q0.53125 -0.09375 0.96875 -0.21875l0 1.8125zm8.101044 0.09375l0 -6.140625q0 -1.546875 -1.140625 -1.546875q-0.578125 0 -1.109375 0.46875q-0.515625 0.453125 -1.109375 1.25l0 5.96875l-2.25 0l0 -13.109375l2.25 0l0 3.234375l-0.109375 1.703125q0.296875 -0.34375 0.59375 -0.609375q0.296875 -0.28125 0.640625 -0.46875q0.34375 -0.1875 0.734375 -0.28125q0.40625 -0.09375 0.890625 -0.09375q0.71875 0 1.25 0.234375q0.546875 0.234375 0.90625 0.671875q0.359375 0.421875 0.53125 1.03125q0.1875 0.609375 0.1875 1.359375l0 6.328125l-2.265625 0zm23.280212 -8.265625q0 0.953125 -0.328125 1.75q-0.3125 0.796875 -0.9375 1.390625q-0.609375 0.578125 -1.546875 0.90625q-0.921875 0.328125 -2.140625 0.328125l-1.171875 0l0 3.890625l-2.296875 0l0 -12.125l3.5625 0q1.171875 0 2.078125 0.265625q0.90625 0.25 1.515625 0.75q0.625 0.484375 0.9375 1.203125q0.328125 0.71875 0.328125 1.640625zm-2.390625 0.15625q0 -0.484375 -0.15625 -0.875q-0.15625 -0.390625 -0.46875 -0.671875q-0.3125 -0.28125 -0.78125 -0.421875q-0.46875 -0.15625 -1.125 -0.15625l-1.203125 0l0 4.4375l1.28125 0q0.59375 0 1.046875 -0.15625q0.453125 -0.15625 0.765625 -0.453125q0.3125 -0.3125 0.46875 -0.734375q0.171875 -0.4375 0.171875 -0.96875zm9.819794 -3.890625q0 0.296875 -0.125 0.578125q-0.109375 0.265625 -0.3125 0.46875q-0.1875 0.1875 -0.46875 0.3125q-0.265625 0.109375 -0.578125 0.109375q-0.3125 0 -0.59375 -0.109375q-0.265625 -0.125 -0.46875 -0.3125q-0.203125 -0.203125 -0.3125 -0.46875q-0.109375 -0.28125 -0.109375 -0.578125q0 -0.3125 0.109375 -0.578125q0.109375 -0.265625 0.3125 -0.46875q0.203125 -0.203125 0.46875 -0.3125q0.28125 -0.125 0.59375 -0.125q0.3125 0 0.578125 0.125q0.28125 0.109375 0.46875 0.3125q0.203125 0.203125 0.3125 0.46875q0.125 0.265625 0.125 0.578125zm-2.515625 4.34375l-2.65625 0l0 -1.765625l4.984375 0l0 7.65625l2.71875 0l0 1.765625l-8.03125 0l0 -1.765625l2.984375 0l0 -5.890625zm15.694794 2.78125q0 1.296875 -0.375 2.25q-0.359375 0.9375 -1.015625 1.5625q-0.640625 0.625 -1.53125 0.9375q-0.890625 0.296875 -1.9375 0.296875q-0.359375 0 -0.71875 -0.046875q-0.34375 -0.046875 -0.640625 -0.125l0 3.6875l-2.25 0l0 -13.109375l1.953125 0l0.046875 1.390625q0.296875 -0.359375 0.609375 -0.65625q0.3125 -0.296875 0.671875 -0.5q0.359375 -0.21875 0.765625 -0.328125q0.421875 -0.109375 0.953125 -0.109375q0.828125 0 1.46875 0.328125q0.65625 0.328125 1.09375 0.953125q0.453125 0.609375 0.671875 1.5q0.234375 0.875 0.234375 1.96875zm-2.375 0.09375q0 -0.78125 -0.109375 -1.328125q-0.109375 -0.546875 -0.328125 -0.890625q-0.203125 -0.359375 -0.5 -0.515625q-0.296875 -0.171875 -0.6875 -0.171875q-0.578125 0 -1.109375 0.46875q-0.515625 0.453125 -1.109375 1.25l0 4.125q0.28125 0.09375 0.671875 0.171875q0.390625 0.0625 0.796875 0.0625q0.546875 0 0.984375 -0.21875q0.4375 -0.234375 0.75 -0.640625q0.3125 -0.40625 0.46875 -0.984375q0.171875 -0.59375 0.171875 -1.328125zm12.366669 -0.65625q0 0.234375 -0.015625 0.609375q-0.015625 0.359375 -0.046875 0.6875l-6.1875 0q0 0.625 0.1875 1.109375q0.1875 0.46875 0.53125 0.78125q0.359375 0.3125 0.84375 0.484375q0.484375 0.171875 1.078125 0.171875q0.6875 0 1.46875 -0.109375q0.78125 -0.109375 1.625 -0.34375l0 1.796875q-0.359375 0.09375 -0.78125 0.1875q-0.421875 0.078125 -0.875 0.140625q-0.4375 0.078125 -0.90625 0.109375q-0.453125 0.03125 -0.875 0.03125q-1.078125 0 -1.9375 -0.3125q-0.84375 -0.3125 -1.4375 -0.90625q-0.59375 -0.59375 -0.90625 -1.46875q-0.3125 -0.890625 -0.3125 -2.046875q0 -1.15625 0.3125 -2.09375q0.3125 -0.9375 0.890625 -1.609375q0.578125 -0.671875 1.390625 -1.03125q0.828125 -0.375 1.828125 -0.375q1.015625 0 1.78125 0.3125q0.765625 0.296875 1.28125 0.859375q0.53125 0.5625 0.796875 1.328125q0.265625 0.765625 0.265625 1.6875zm-2.296875 -0.328125q0 -0.546875 -0.15625 -0.953125q-0.140625 -0.421875 -0.390625 -0.6875q-0.25 -0.28125 -0.59375 -0.40625q-0.34375 -0.125 -0.734375 -0.125q-0.84375 0 -1.390625 0.578125q-0.546875 0.5625 -0.65625 1.59375l3.921875 0zm7.3822937 -5.578125l-2.65625 0l0 -1.765625l4.984375 0l0 11.34375l2.71875 0l0 1.765625l-8.03125 0l0 -1.765625l2.984375 0l0 -9.578125zm12.772919 -0.65625q0 0.296875 -0.125 0.578125q-0.109375 0.265625 -0.3125 0.46875q-0.1875 0.1875 -0.46875 0.3125q-0.265625 0.109375 -0.578125 0.109375q-0.3125 0 -0.59375 -0.109375q-0.265625 -0.125 -0.46875 -0.3125q-0.203125 -0.203125 -0.3125 -0.46875q-0.109375 -0.28125 -0.109375 -0.578125q0 -0.3125 0.109375 -0.578125q0.109375 -0.265625 0.3125 -0.46875q0.203125 -0.203125 0.46875 -0.3125q0.28125 -0.125 0.59375 -0.125q0.3125 0 0.578125 0.125q0.28125 0.109375 0.46875 0.3125q0.203125 0.203125 0.3125 0.46875q0.125 0.265625 0.125 0.578125zm-2.515625 4.34375l-2.65625 0l0 -1.765625l4.984375 0l0 7.65625l2.71875 0l0 1.765625l-8.03125 0l0 -1.765625l2.984375 0l0 -5.890625zm12.835419 7.65625l0 -6.140625q0 -1.546875 -1.140625 -1.546875q-0.578125 0 -1.109375 0.46875q-0.515625 0.453125 -1.109375 1.25l0 5.96875l-2.25 0l0 -9.421875l1.953125 0l0.046875 1.390625q0.296875 -0.359375 0.609375 -0.65625q0.3125 -0.296875 0.671875 -0.5q0.359375 -0.21875 0.765625 -0.328125q0.421875 -0.109375 0.953125 -0.109375q0.71875 0 1.25 0.234375q0.546875 0.234375 0.90625 0.671875q0.359375 0.421875 0.53125 1.03125q0.1875 0.609375 0.1875 1.359375l0 6.328125l-2.265625 0zm10.194794 -12.0q0 0.296875 -0.125 0.578125q-0.109375 0.265625 -0.3125 0.46875q-0.1875 0.1875 -0.46875 0.3125q-0.265625 0.109375 -0.578125 0.109375q-0.3125 0 -0.59375 -0.109375q-0.265625 -0.125 -0.46875 -0.3125q-0.203125 -0.203125 -0.3125 -0.46875q-0.109375 -0.28125 -0.109375 -0.578125q0 -0.3125 0.109375 -0.578125q0.109375 -0.265625 0.3125 -0.46875q0.203125 -0.203125 0.46875 -0.3125q0.28125 -0.125 0.59375 -0.125q0.3125 0 0.578125 0.125q0.28125 0.109375 0.46875 0.3125q0.203125 0.203125 0.3125 0.46875q0.125 0.265625 0.125 0.578125zm-2.515625 4.34375l-2.65625 0l0 -1.765625l4.984375 0l0 7.65625l2.71875 0l0 1.765625l-8.03125 0l0 -1.765625l2.984375 0l0 -5.890625zm12.835419 7.65625l0 -6.140625q0 -1.546875 -1.140625 -1.546875q-0.578125 0 -1.109375 0.46875q-0.515625 0.453125 -1.109375 1.25l0 5.96875l-2.25 0l0 -9.421875l1.953125 0l0.046875 1.390625q0.296875 -0.359375 0.609375 -0.65625q0.3125 -0.296875 0.671875 -0.5q0.359375 -0.21875 0.765625 -0.328125q0.421875 -0.109375 0.953125 -0.109375q0.71875 0 1.25 0.234375q0.546875 0.234375 0.90625 0.671875q0.359375 0.421875 0.53125 1.03125q0.1875 0.609375 0.1875 1.359375l0 6.328125l-2.265625 0zm11.710419 -7.78125q0.265625 0.328125 0.359375 0.6875q0.109375 0.359375 0.109375 0.734375q0 0.78125 -0.28125 1.390625q-0.265625 0.59375 -0.765625 1.015625q-0.484375 0.40625 -1.1875 0.609375q-0.6875 0.203125 -1.515625 0.203125q-0.5 0 -0.921875 -0.09375q-0.40625 -0.09375 -0.625 -0.21875q-0.15625 0.15625 -0.265625 0.34375q-0.109375 0.1875 -0.109375 0.421875q0 0.15625 0.0625 0.3125q0.078125 0.140625 0.21875 0.265625q0.15625 0.109375 0.34375 0.1875q0.203125 0.0625 0.453125 0.078125l2.234375 0.078125q0.765625 0.015625 1.359375 0.1875q0.609375 0.171875 1.046875 0.5q0.4375 0.3125 0.671875 0.765625q0.234375 0.4375 0.234375 1.015625q0 0.65625 -0.296875 1.234375q-0.296875 0.59375 -0.890625 1.015625q-0.59375 0.4375 -1.484375 0.6875q-0.890625 0.25 -2.078125 0.25q-1.140625 0 -1.96875 -0.1875q-0.8125 -0.171875 -1.34375 -0.5q-0.515625 -0.3125 -0.765625 -0.765625q-0.25 -0.453125 -0.25 -0.984375q0 -0.328125 0.078125 -0.609375q0.09375 -0.28125 0.25 -0.53125q0.171875 -0.25 0.421875 -0.484375q0.25 -0.25 0.59375 -0.5q-0.453125 -0.25 -0.6875 -0.65625q-0.234375 -0.421875 -0.234375 -0.875q0 -0.328125 0.078125 -0.59375q0.09375 -0.28125 0.21875 -0.53125q0.140625 -0.25 0.3125 -0.46875q0.171875 -0.234375 0.375 -0.46875q-0.34375 -0.34375 -0.578125 -0.828125q-0.21875 -0.484375 -0.21875 -1.21875q0 -0.78125 0.28125 -1.390625q0.28125 -0.625 0.78125 -1.046875q0.5 -0.421875 1.1875 -0.640625q0.703125 -0.21875 1.515625 -0.21875q0.421875 0 0.796875 0.046875q0.390625 0.03125 0.703125 0.140625l3.265625 0l0 1.640625l-1.484375 0zm-5.328125 9.03125q0 0.546875 0.546875 0.796875q0.546875 0.265625 1.546875 0.265625q0.640625 0 1.078125 -0.125q0.453125 -0.109375 0.71875 -0.3125q0.28125 -0.1875 0.40625 -0.453125q0.125 -0.25 0.125 -0.53125q0 -0.25 -0.125 -0.421875q-0.109375 -0.171875 -0.328125 -0.296875q-0.203125 -0.109375 -0.484375 -0.171875q-0.28125 -0.0625 -0.625 -0.078125l-2.0 -0.03125q-0.265625 0.1875 -0.4375 0.34375q-0.171875 0.171875 -0.265625 0.328125q-0.09375 0.171875 -0.125 0.328125q-0.03125 0.171875 -0.03125 0.359375zm0.375 -7.5625q0 0.75 0.4375 1.203125q0.4375 0.4375 1.234375 0.4375q0.421875 0 0.71875 -0.140625q0.3125 -0.140625 0.515625 -0.375q0.203125 -0.234375 0.296875 -0.53125q0.109375 -0.3125 0.109375 -0.640625q0 -0.796875 -0.4375 -1.234375q-0.4375 -0.4375 -1.21875 -0.4375q-0.421875 0 -0.734375 0.140625q-0.3125 0.140625 -0.515625 0.375q-0.203125 0.234375 -0.3125 0.546875q-0.09375 0.3125 -0.09375 0.65625z" fill-rule="nonzero"></path><path fill="#d0e0e3" d="m439.77292 141.8203l64.97638 0l0 384.75592l-64.97638 0z" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m439.77292 141.8203l64.97638 0l0 384.75592l-64.97638 0z" fill-rule="nonzero"></path><path fill="#434343" d="m476.38245 282.837q0 0.859375 -0.359375 1.515625q-0.34375 0.640625 -0.984375 1.078125q-0.625 0.421875 -1.515625 0.640625q-0.875 0.21875 -1.953125 0.21875q-0.46875 0 -0.953125 -0.046875q-0.484375 -0.03125 -0.921875 -0.09375q-0.4375 -0.046875 -0.828125 -0.125q-0.390625 -0.078125 -0.703125 -0.15625l0 -1.59375q0.6875 0.25 1.546875 0.40625q0.875 0.140625 1.984375 0.140625q0.796875 0 1.359375 -0.125q0.5625 -0.125 0.921875 -0.359375q0.359375 -0.25 0.515625 -0.59375q0.171875 -0.359375 0.171875 -0.8125q0 -0.5 -0.28125 -0.84375q-0.265625 -0.34375 -0.71875 -0.609375q-0.4375 -0.28125 -1.015625 -0.5q-0.578125 -0.234375 -1.171875 -0.46875q-0.59375 -0.25 -1.171875 -0.53125q-0.5625 -0.28125 -1.015625 -0.671875q-0.4375 -0.390625 -0.71875 -0.90625q-0.265625 -0.515625 -0.265625 -1.234375q0 -0.625 0.265625 -1.21875q0.265625 -0.609375 0.8125 -1.078125q0.546875 -0.46875 1.40625 -0.75q0.859375 -0.296875 2.046875 -0.296875q0.296875 0 0.65625 0.03125q0.359375 0.03125 0.71875 0.078125q0.375 0.046875 0.734375 0.125q0.359375 0.0625 0.65625 0.125l0 1.484375q-0.71875 -0.203125 -1.4375 -0.296875q-0.703125 -0.109375 -1.375 -0.109375q-1.421875 0 -2.09375 0.46875q-0.65625 0.46875 -0.65625 1.265625q0 0.5 0.265625 0.859375q0.28125 0.34375 0.71875 0.625q0.453125 0.28125 1.015625 0.515625q0.578125 0.21875 1.171875 0.46875q0.59375 0.234375 1.15625 0.515625q0.578125 0.28125 1.015625 0.6875q0.453125 0.390625 0.71875 0.921875q0.28125 0.515625 0.28125 1.25z" fill-rule="nonzero"></path><path fill="#434343" d="m475.89807 308.11826l-6.90625 0l0 -12.125l6.90625 0l0 1.390625l-5.25 0l0 3.75l5.03125 0l0 1.40625l-5.03125 0l0 4.171875l5.25 0l0 1.40625z" fill-rule="nonzero"></path><path fill="#434343" d="m476.88245 330.11826l-1.859375 0l-1.8125 -3.875q-0.203125 -0.453125 -0.421875 -0.734375q-0.203125 -0.296875 -0.453125 -0.46875q-0.25 -0.171875 -0.546875 -0.25q-0.28125 -0.078125 -0.640625 -0.078125l-0.78125 0l0 5.40625l-1.65625 0l0 -12.125l3.25 0q1.046875 0 1.8125 0.234375q0.765625 0.234375 1.25 0.65625q0.484375 0.40625 0.703125 1.0q0.234375 0.578125 0.234375 1.296875q0 0.5625 -0.171875 1.078125q-0.15625 0.5 -0.484375 0.921875q-0.328125 0.40625 -0.828125 0.71875q-0.484375 0.296875 -1.109375 0.4375q0.515625 0.171875 0.859375 0.625q0.359375 0.4375 0.734375 1.171875l1.921875 3.984375zm-2.640625 -8.796875q0 -0.96875 -0.609375 -1.453125q-0.609375 -0.484375 -1.71875 -0.484375l-1.546875 0l0 4.015625l1.328125 0q0.59375 0 1.0625 -0.140625q0.46875 -0.140625 0.796875 -0.40625q0.328125 -0.265625 0.5 -0.640625q0.1875 -0.390625 0.1875 -0.890625z" fill-rule="nonzero"></path><path fill="#434343" d="m477.5387 339.99326l-4.109375 12.125l-2.234375 0l-4.03125 -12.125l1.875 0l2.609375 8.171875l0.75 2.390625l0.75 -2.390625l2.625 -8.171875l1.765625 0z" fill-rule="nonzero"></path><path fill="#434343" d="m475.89807 374.11826l-6.90625 0l0 -12.125l6.90625 0l0 1.390625l-5.25 0l0 3.75l5.03125 0l0 1.40625l-5.03125 0l0 4.171875l5.25 0l0 1.40625z" fill-rule="nonzero"></path><path fill="#434343" d="m476.88245 396.11826l-1.859375 0l-1.8125 -3.875q-0.203125 -0.453125 -0.421875 -0.734375q-0.203125 -0.296875 -0.453125 -0.46875q-0.25 -0.171875 -0.546875 -0.25q-0.28125 -0.078125 -0.640625 -0.078125l-0.78125 0l0 5.40625l-1.65625 0l0 -12.125l3.25 0q1.046875 0 1.8125 0.234375q0.765625 0.234375 1.25 0.65625q0.484375 0.40625 0.703125 1.0q0.234375 0.578125 0.234375 1.296875q0 0.5625 -0.171875 1.078125q-0.15625 0.5 -0.484375 0.921875q-0.328125 0.40625 -0.828125 0.71875q-0.484375 0.296875 -1.109375 0.4375q0.515625 0.171875 0.859375 0.625q0.359375 0.4375 0.734375 1.171875l1.921875 3.984375zm-2.640625 -8.796875q0 -0.96875 -0.609375 -1.453125q-0.609375 -0.484375 -1.71875 -0.484375l-1.546875 0l0 4.015625l1.328125 0q0.59375 0 1.0625 -0.140625q0.46875 -0.140625 0.796875 -0.40625q0.328125 -0.265625 0.5 -0.640625q0.1875 -0.390625 0.1875 -0.890625z" fill-rule="nonzero"></path><path fill="#d0e0e3" d="m215.25197 141.8203l64.976364 0l0 384.75592l-64.976364 0z" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m215.25197 141.8203l64.976364 0l0 384.75592l-64.976364 0z" fill-rule="nonzero"></path><path fill="#434343" d="m251.84589 285.66513q-1.453125 0.609375 -3.0625 0.609375q-2.5625 0 -3.9375 -1.53125q-1.375 -1.546875 -1.375 -4.546875q0 -1.46875 0.375 -2.640625q0.375 -1.171875 1.078125 -2.0q0.71875 -0.828125 1.71875 -1.265625q1.0 -0.453125 2.234375 -0.453125q0.84375 0 1.5625 0.15625q0.734375 0.140625 1.40625 0.4375l0 1.625q-0.65625 -0.359375 -1.375 -0.546875q-0.703125 -0.203125 -1.53125 -0.203125q-0.859375 0 -1.546875 0.328125q-0.6875 0.3125 -1.171875 0.921875q-0.484375 0.609375 -0.75 1.484375q-0.25 0.875 -0.25 2.0q0 2.359375 0.953125 3.5625q0.953125 1.1875 2.796875 1.1875q0.78125 0 1.5 -0.171875q0.71875 -0.1875 1.375 -0.515625l0 1.5625z" fill-rule="nonzero"></path><path fill="#434343" d="m251.75214 308.11826l-6.984375 0l0 -12.125l1.6875 0l0 10.71875l5.296875 0l0 1.40625z" fill-rule="nonzero"></path><path fill="#434343" d="m247.00214 319.38388l-2.796875 0l0 -1.390625l7.25 0l0 1.390625l-2.78125 0l0 9.328125l2.78125 0l0 1.40625l-7.25 0l0 -1.40625l2.796875 0l0 -9.328125z" fill-rule="nonzero"></path><path fill="#434343" d="m251.37714 352.11826l-6.90625 0l0 -12.125l6.90625 0l0 1.390625l-5.25 0l0 3.75l5.03125 0l0 1.40625l-5.03125 0l0 4.171875l5.25 0l0 1.40625z" fill-rule="nonzero"></path><path fill="#434343" d="m251.97089 374.11826l-2.15625 0l-3.53125 -7.5625l-1.03125 -2.421875l0 6.109375l0 3.875l-1.53125 0l0 -12.125l2.125 0l3.359375 7.15625l1.21875 2.78125l0 -6.5l0 -3.4375l1.546875 0l0 12.125z" fill-rule="nonzero"></path><path fill="#434343" d="m252.26776 385.3995l-3.59375 0l0 10.71875l-1.671875 0l0 -10.71875l-3.59375 0l0 -1.40625l8.859375 0l0 1.40625z" fill-rule="nonzero"></path><path fill="#000000" fill-opacity="0.0" d="m282.13055 151.96812l159.52756 23.685043" fill-rule="nonzero"></path><path stroke="#e06666" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m282.13055 151.96812l156.1376 23.181747" fill-rule="evenodd"></path><path fill="#e06666" stroke="#e06666" stroke-width="1.0" stroke-linecap="butt" d="m438.26816 175.14987l-1.2775269 0.9472351l3.221405 -0.6586304l-2.8911133 -1.5661469z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m281.175 287.1842l160.53543 -11.842499" fill-rule="nonzero"></path><path stroke="#e06666" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m284.59277 286.9321l157.11765 -11.590393" fill-rule="evenodd"></path><path fill="#e06666" stroke="#e06666" stroke-width="1.0" stroke-linecap="butt" d="m284.5928 286.9321l1.0387878 -1.2042847l-2.9986572 1.3488464l3.1641235 0.8942261z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m282.13196 195.7803l159.52756 23.685043" fill-rule="nonzero"></path><path stroke="#bf9000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m282.13196 195.7803l156.1376 23.181747" fill-rule="evenodd"></path><path fill="#bf9000" stroke="#bf9000" stroke-width="1.0" stroke-linecap="butt" d="m438.26956 218.96205l-1.2775574 0.94721985l3.2214355 -0.6586151l-2.8911133 -1.5661621z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m348.98535 176.09427l22.677155 2.960617l-2.551178 14.992126l-22.677155 -2.9606323z" fill-rule="nonzero"></path><path fill="#bf9000" d="m359.59622 198.60167l1.667572 0.43832397q-0.6546631 1.4272461 -1.8963623 2.1160583q-1.2235718 0.6753998 -2.9278564 0.45289612q-2.138092 -0.2791443 -3.170105 -1.7532654q-1.0320129 -1.4741364 -0.62805176 -3.8480682q0.41708374 -2.451004 1.9028931 -3.643692q1.5013123 -1.1906586 3.5309753 -0.92567444q1.9676819 0.2568817 2.9815674 1.7444153q1.0138855 1.4875183 0.6020508 3.9076996q-0.023620605 0.13873291 -0.08895874 0.42959595l-7.281952 -0.95069885q-0.17984009 1.6153107 0.4970398 2.570343q0.6768799 0.9550476 1.9008789 1.1148376q0.8986206 0.11732483 1.6125488 -0.26219177q0.73205566 -0.39291382 1.29776 -1.3905792zm-4.9844055 -3.3768005l5.453705 0.7120056q0.0987854 -1.2319489 -0.30758667 -1.9153137q-0.62753296 -1.0588989 -1.8980103 -1.224762q-1.131012 -0.1476593 -2.0523376 0.519928q-0.90322876 0.6542053 -1.1957703 1.9081421z" fill-rule="nonzero"></path><path fill="#000000" fill-opacity="0.0" d="m281.1764 308.67355l160.53543 -11.842529" fill-rule="nonzero"></path><path stroke="#bf9000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m284.59418 308.42142l157.11765 -11.590393" fill-rule="evenodd"></path><path fill="#bf9000" stroke="#bf9000" stroke-width="1.0" stroke-linecap="butt" d="m284.59418 308.42142l1.0388184 -1.2042542l-2.9986572 1.3488464l3.1641235 0.8942261z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m281.17642 226.63377l159.52756 23.685028" fill-rule="nonzero"></path><path stroke="#134f5c" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m281.17642 226.63377l156.13763 23.181747" fill-rule="evenodd"></path><path fill="#134f5c" stroke="#134f5c" stroke-width="1.0" stroke-linecap="butt" d="m437.31406 249.8155l-1.2775574 0.9472351l3.2214355 -0.6586151l-2.8911133 -1.5661621z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m348.98257 205.9346l22.677185 2.960617l-2.5512085 14.992126l-22.677155 -2.960617z" fill-rule="nonzero"></path><path fill="#134f5c" d="m355.34494 231.08614l1.4348755 -8.432083l-1.4718933 -0.19216919l0.22033691 -1.2948608l1.4718933 0.19215393l0.17575073 -1.0328064q0.16525269 -0.9711609 0.4170227 -1.4267731q0.3425598 -0.61709595 1.0123901 -0.923584q0.67245483 -0.3218994 1.7569885 -0.18031311q0.6972046 0.09101868 1.5231323 0.35643005l-0.49447632 1.4166565q-0.49554443 -0.15924072 -0.96035767 -0.21992493q-0.7591858 -0.099121094 -1.1241455 0.18414307q-0.3623352 0.26785278 -0.5118408 1.1465149l-0.15216064 0.8940735l1.9057007 0.24880981l-0.22033691 1.2948608l-1.9057007 -0.24879456l-1.4348755 8.432068l-1.6423035 -0.21440125z" fill-rule="nonzero"></path><path fill="#000000" fill-opacity="0.0" d="m280.22348 326.75668l160.53543 -11.842529" fill-rule="nonzero"></path><path stroke="#134f5c" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m283.6413 326.50452l157.11765 -11.590363" fill-rule="evenodd"></path><path fill="#134f5c" stroke="#134f5c" stroke-width="1.0" stroke-linecap="butt" d="m283.6413 326.50455l1.0387878 -1.2042847l-2.9986572 1.3488464l3.1641235 0.8942261z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m282.13055 351.51535l159.52756 23.685028" fill-rule="nonzero"></path><path stroke="#a64d79" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m282.13055 351.51535l156.1376 23.181702" fill-rule="evenodd"></path><path fill="#a64d79" stroke="#a64d79" stroke-width="1.0" stroke-linecap="butt" d="m438.26816 374.69708l-1.2775269 0.9472351l3.221405 -0.6586304l-2.8911133 -1.5661621z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m325.22943 326.89877l72.09448 9.480286l-2.551178 14.992126l-72.09448 -9.480316z" fill-rule="nonzero"></path><path fill="#741b47" d="m343.2176 353.58856l0.20983887 -1.2331543q-1.1760559 1.3267212 -2.9730835 1.0904236q-1.1618958 -0.152771 -2.045807 -0.91516113q-0.8657837 -0.77575684 -1.2138977 -1.9877319q-0.32998657 -1.2253418 -0.07556152 -2.7205505q0.24658203 -1.4489746 0.9288025 -2.572754q0.6976929 -1.1217346 1.7657471 -1.6274414q1.0834961 -0.5036621 2.2918396 -0.34475708q0.8830261 0.116119385 1.501709 0.5757141q0.6341858 0.4616089 0.9656372 1.119812l0.8183899 -4.8093567l1.6421204 0.21594238l-2.282074 13.410706l-1.5336609 -0.20169067zm-4.409912 -5.5441284q-0.3173828 1.8651428 0.31530762 2.893921q0.64816284 1.0307922 1.717102 1.1713562q1.0844116 0.14260864 1.9930115 -0.63619995q0.90859985 -0.7788086 1.2181396 -2.5977478q0.3383789 -1.9884644 -0.2788391 -3.0151978q-0.614563 -1.0421448 -1.7454529 -1.1908569q-1.0999146 -0.1446228 -1.995636 0.6516113q-0.89575195 0.79626465 -1.2236328 2.723114zm10.849762 10.4253845q-1.069458 -1.9057007 -1.6236267 -4.326721q-0.5515137 -2.4364624 -0.13183594 -4.9028015q0.37246704 -2.1888733 1.4079895 -4.085663q1.230011 -2.202179 3.340393 -4.272827l1.1928711 0.15682983q-1.4380493 1.7493286 -1.9333801 2.5194397q-0.7727661 1.1906738 -1.331543 2.519806q-0.6939697 1.6580505 -0.98773193 3.3844604q-0.7502136 4.4085693 1.2597351 9.164337l-1.1928711 -0.15686035zm10.895752 -5.8008423l1.6673584 0.4399109q-0.65460205 1.4268188 -1.8961487 2.114563q-1.2234497 0.67437744 -2.9275208 0.45028687q-2.137848 -0.2810974 -3.1697083 -1.7563477q-1.0318604 -1.4752502 -0.6279297 -3.8490906q0.41708374 -2.4509277 1.9027405 -3.642395q1.5011292 -1.1894531 3.530548 -0.9225769q1.9674377 0.2586975 2.9811707 1.747345q1.0137634 1.488617 0.6019287 3.9086914q-0.023590088 0.13873291 -0.08892822 0.42956543l-7.281067 -0.957428q-0.17984009 1.6153259 0.49691772 2.571106q0.67678833 0.95578 1.9006348 1.1166992q0.89852905 0.11816406 1.6123657 -0.2607727q0.7319641 -0.39227295 1.2976379 -1.3895569zm-4.983795 -3.3817444l5.453064 0.71707153q0.0987854 -1.2320251 -0.30752563 -1.9158325q-0.6274414 -1.0596008 -1.8977356 -1.2266235q-1.1308899 -0.14871216 -2.052124 0.51812744q-0.9031067 0.6534424 -1.1956787 1.9072571zm8.479828 7.0406494l0.32003784 -1.8805542l1.8899536 0.24850464l-0.32000732 1.8805847q-0.17575073 1.0327759 -0.65509033 1.6159058q-0.4819641 0.59851074 -1.3297424 0.83374023l-0.3440857 -0.77020264q0.56344604 -0.1465149 0.8873596 -0.5609436q0.3239441 -0.4144287 0.49658203 -1.2427673l-0.9450073 -0.12426758zm5.1080933 0.6717224l1.4348145 -8.431793l-1.4717102 -0.19351196l0.22033691 -1.2948303l1.4717102 0.19354248l0.17575073 -1.0328064q0.16525269 -0.97109985 0.41696167 -1.4265442q0.3425598 -0.6168518 1.0122986 -0.9227905q0.6723938 -0.32131958 1.7568054 -0.17871094q0.69711304 0.091674805 1.5229187 0.35784912l-0.49441528 1.4163818q-0.49551392 -0.159729 -0.9602356 -0.2208252q-0.75909424 -0.099823 -1.1240234 0.18313599q-0.3623047 0.2675476 -0.5118103 1.1461792l-0.15213013 0.89404297l1.9054565 0.25057983l-0.22033691 1.2948303l-1.9054565 -0.25057983l-1.4348145 8.431793l-1.6421204 -0.21594238zm5.1492004 4.711548l-1.1773682 -0.15481567q3.4895935 -4.032593 4.2397766 -8.441162q0.2911682 -1.711029 0.19241333 -3.45755q-0.09185791 -1.4146729 -0.43447876 -2.7520142q-0.21466064 -0.87924194 -1.0047913 -2.937317l1.1773682 0.15481567q1.3442078 2.5249329 1.7718201 4.9450684q0.37423706 2.0822144 0.001739502 4.2710876q-0.41967773 2.4663086 -1.7736206 4.652191q-1.3358154 2.1725159 -2.992859 3.719696z" fill-rule="nonzero"></path><path fill="#000000" fill-opacity="0.0" d="m280.22223 430.7826l160.53543 -11.842499" fill-rule="nonzero"></path><path stroke="#741b47" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m283.64005 430.53046l157.11761 -11.590363" fill-rule="evenodd"></path><path fill="#741b47" stroke="#741b47" stroke-width="1.0" stroke-linecap="butt" d="m283.64005 430.5305l1.0387878 -1.2042847l-2.9986572 1.3488464l3.1641235 0.8942261z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m281.17514 482.24542l159.52756 23.685059" fill-rule="nonzero"></path><path stroke="#3d85c6" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m281.17514 482.2454l156.13763 23.181732" fill-rule="evenodd"></path><path fill="#3d85c6" stroke="#3d85c6" stroke-width="1.0" stroke-linecap="butt" d="m437.31277 505.42715l-1.2775269 0.9472351l3.221405 -0.6586304l-2.8911133 -1.5661621z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m279.2668 518.6085l160.53546 -11.84256" fill-rule="nonzero"></path><path stroke="#3c78d8" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m282.68463 518.3563l157.11761 -11.590363" fill-rule="evenodd"></path><path fill="#3c78d8" stroke="#3c78d8" stroke-width="1.0" stroke-linecap="butt" d="m282.68463 518.3563l1.0388184 -1.2042236l-2.9986877 1.3488159l3.164154 0.8942261z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m325.22943 460.4956l72.09448 9.480316l-2.551178 14.992126l-72.09448 -9.480316z" fill-rule="nonzero"></path><path fill="#3d85c6" d="m340.89462 485.6507q-1.0632935 0.6639404 -1.970398 0.87557983q-0.9045105 0.19625854 -1.8804932 0.06793213q-1.5956421 -0.20983887 -2.3320007 -1.094635q-0.73376465 -0.90023804 -0.5265503 -2.117981q0.123291016 -0.7244873 0.5483093 -1.267456q0.4249878 -0.54296875 1.0120239 -0.8282471q0.58706665 -0.28527832 1.284668 -0.3826599q0.51934814 -0.07354736 1.5136719 -0.053100586q2.0558777 0.018188477 3.0559692 -0.1812439q0.05770874 -0.33914185 0.07345581 -0.4316101q0.17047119 -1.0019531 -0.2234497 -1.479248q-0.54071045 -0.63845825 -1.7955322 -0.8034668q-1.1618958 -0.152771 -1.7877808 0.1746521q-0.625885 0.3274536 -1.067627 1.3410034l-1.5872803 -0.44509888q0.4081421 -1.0022278 1.0114136 -1.5690308q0.6187744 -0.5647888 1.62146 -0.77963257q1.020813 -0.22824097 2.2911377 -0.061187744q1.2548218 0.16500854 1.9795532 0.5597229q0.72473145 0.39474487 1.0204773 0.8906555q0.29571533 0.49591064 0.31973267 1.1924744q0.022125244 0.42843628 -0.16409302 1.5228577l-0.37512207 2.2042847q-0.39083862 2.2967834 -0.4028015 2.9255981q0.006134033 0.6154175 0.23703003 1.2131348l-1.7350464 -0.22817993q-0.17681885 -0.54330444 -0.12072754 -1.2451172zm0.48486328 -3.6869812q-0.9588623 0.23635864 -2.815979 0.2600708q-1.046051 0.004272461 -1.4957886 0.13424683q-0.44976807 0.12997437 -0.74246216 0.45394897q-0.2926941 0.3239746 -0.3661499 0.7555847q-0.11279297 0.6628418 0.30688477 1.1750488q0.43777466 0.49884033 1.3982544 0.6251526q0.96047974 0.12628174 1.7749023 -0.19213867q0.8170471 -0.33380127 1.2940063 -0.9960327q0.3604126 -0.53570557 0.54403687 -1.6147156l0.10229492 -0.6011658zm5.7039185 9.764496q-1.0694885 -1.9057007 -1.6236267 -4.3267517q-0.5515442 -2.4364624 -0.13183594 -4.902771q0.37246704 -2.1888733 1.407959 -4.0856934q1.230011 -2.202179 3.3404236 -4.272827l1.1928711 0.15686035q-1.4380493 1.7492981 -1.9333801 2.5194397q-0.77279663 1.1906433 -1.3315735 2.5197754q-0.6939392 1.6580505 -0.98773193 3.384491q-0.7501831 4.4085693 1.2597656 9.164337l-1.1928711 -0.15686035zm5.204529 -3.3500671l-1.5336609 -0.20166016l2.282074 -13.410706l1.6420898 0.21594238l-0.81314087 4.778534q1.2763977 -1.1717224 2.9030151 -0.9578247q0.89852905 0.11816406 1.6411133 0.59402466q0.74523926 0.46047974 1.1436768 1.1905212q0.41656494 0.7166748 0.5534973 1.6802673q0.13696289 0.963562 -0.041412354 2.0117798q-0.42492676 2.4971619 -1.8977051 3.7060852q-1.4701538 1.193512 -3.2052307 0.96533203q-1.7350464 -0.22814941 -2.467102 -1.7900391l-0.20721436 1.2177429zm0.82388306 -4.9346924q-0.29638672 1.7418518 0.034576416 2.5891113q0.5749817 1.3678894 1.9072571 1.5430603q1.0844116 0.14260864 2.0318909 -0.67837524q0.95007324 -0.83639526 1.267456 -2.7015686q0.32263184 -1.8959656 -0.28167725 -2.9052734q-0.6043396 -1.0092773 -1.6732483 -1.1498413q-1.0844421 -0.14257812 -2.0345154 0.69381714q-0.95007324 0.83639526 -1.2517395 2.6090698zm8.363373 6.1428223l0.32000732 -1.8805847l1.8899841 0.24853516l-0.32000732 1.8805542q-0.17575073 1.0328064 -0.65509033 1.6159058q-0.4819641 0.59851074 -1.3297424 0.83374023l-0.3440857 -0.7701721q0.5634155 -0.14654541 0.8873596 -0.5609741q0.3239441 -0.4144287 0.4965515 -1.2427368l-0.9449768 -0.12426758zm11.041382 1.4519043l0.20983887 -1.2331543q-1.1760559 1.3267517 -2.9730835 1.0904236q-1.1618958 -0.152771 -2.045807 -0.91516113q-0.8658142 -0.7757263 -1.2138977 -1.9877319q-0.32998657 -1.2253418 -0.07556152 -2.7205505q0.24658203 -1.4489746 0.9288025 -2.572754q0.6976929 -1.1217346 1.7657166 -1.6274109q1.0835266 -0.5036621 2.29187 -0.3447876q0.8830261 0.116119385 1.501709 0.5757141q0.6341858 0.4616089 0.9656372 1.119812l0.8183899 -4.809326l1.6421204 0.21591187l-2.282074 13.410706l-1.5336609 -0.20169067zm-4.409912 -5.5441284q-0.3173828 1.8651733 0.31530762 2.893921q0.64816284 1.0308228 1.717102 1.1713867q1.0844116 0.14257812 1.9930115 -0.63623047q0.90859985 -0.7788086 1.2181396 -2.5977173q0.3383484 -1.9884949 -0.2788391 -3.0152283q-0.614563 -1.0421448 -1.7454529 -1.1908569q-1.0999146 -0.1446228 -1.995636 0.65164185q-0.89575195 0.79626465 -1.2236328 2.7230835zm8.773895 10.152435l-1.1773682 -0.15481567q3.4895935 -4.032593 4.239807 -8.441162q0.2911377 -1.711029 0.19238281 -3.45755q-0.09185791 -1.4146729 -0.43447876 -2.7520142q-0.21466064 -0.87924194 -1.0047913 -2.937317l1.1773682 0.15481567q1.3442383 2.5249329 1.7718201 4.945099q0.37423706 2.0821838 0.0017700195 4.271057q-0.41970825 2.4663086 -1.7736511 4.6522217q-1.3358154 2.1724854 -2.992859 3.7196655z" fill-rule="nonzero"></path><path fill="#000000" fill-opacity="0.0" d="m280.20993 463.73132l163.37009 -17.35431" fill-rule="nonzero"></path><path stroke="#93c47d" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m283.61786 463.36935l159.96216 -16.99234" fill-rule="evenodd"></path><path fill="#93c47d" stroke="#93c47d" stroke-width="1.0" stroke-linecap="butt" d="m283.61786 463.36932l0.9994812 -1.2370911l-2.9536743 1.4446716l3.1912537 0.79193115z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m279.435 383.9106l158.6142 19.433075" fill-rule="nonzero"></path><path stroke="#93c47d" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m279.43503 383.91058l155.2125 19.016327" fill-rule="evenodd"></path><path fill="#93c47d" stroke="#93c47d" stroke-width="1.0" stroke-linecap="butt" d="m434.64752 402.9269l-1.2529907 0.97946167l3.2035828 -0.7404785l-2.9300842 -1.4919739z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m327.2065 356.47412l55.62204 7.338562l-2.551178 14.992126l-55.62207 -7.338562z" fill-rule="nonzero"></path><path fill="#93c47d" d="m337.8152 382.1998l-1.5335999 -0.20233154l2.2820435 -13.410461l1.6420288 0.21664429l-0.81314087 4.7784424q1.2763062 -1.1712341 2.902832 -0.9566345q0.898468 0.11853027 1.6410522 0.5947571q0.7451782 0.4607849 1.1435852 1.1910706q0.41653442 0.7168884 0.5534668 1.6805725q0.13693237 0.9636841 -0.041412354 2.0118713q-0.42495728 2.4971313 -1.897644 3.7055054q-1.4700928 1.1929321 -3.2050476 0.9640503q-1.7349854 -0.22891235 -2.4669495 -1.7911987l-0.20721436 1.2177124zm0.82385254 -4.9346313q-0.29638672 1.7418213 0.034576416 2.589264q0.57492065 1.3682251 1.907135 1.5439758q1.0843506 0.1430664 2.0317688 -0.67755127q0.9500122 -0.83602905 1.267395 -2.7011719q0.32263184 -1.8959656 -0.28164673 -2.905548q-0.60427856 -1.009613 -1.6731567 -1.1506348q-1.0843506 -0.1430664 -2.0343628 0.69299316q-0.9500427 0.83602905 -1.251709 2.608673zm10.417755 10.452484q-1.0694275 -1.90625 -1.6235352 -4.327667q-0.55148315 -2.4368286 -0.1317749 -4.9031067q0.37246704 -2.1888428 1.4079285 -4.085327q1.22995 -2.2017822 3.3402405 -4.2716675l1.1927795 0.15737915q-1.4379578 1.7488098 -1.933258 2.5187683q-0.7727661 1.1903992 -1.3315125 2.5193481q-0.6939087 1.6578674 -0.9877014 3.3842773q-0.7501831 4.408478 1.259613 9.165375l-1.1927795 -0.15737915zm10.658783 -6.269043l1.5898132 0.43041992q-0.54663086 1.6300049 -1.8091125 2.4405823q-1.2598572 0.795166 -2.8708801 0.5826111q-1.9983215 -0.26367188 -3.0017395 -1.7199402q-0.98532104 -1.469635 -0.57089233 -3.9050903q0.2675476 -1.5722656 0.9780884 -2.6763q0.7286682 -1.1174316 1.8972168 -1.5621338q1.1866455 -0.45809937 2.4413757 -0.2925415q1.5955505 0.21051025 2.4660645 1.1448975q0.8705139 0.9343872 0.9130249 2.453003l-1.6530151 0.034057617q-0.06448364 -1.0171509 -0.56921387 -1.5880737q-0.5046997 -0.57092285 -1.3257141 -0.67926025q-1.2547607 -0.16555786 -2.1968994 0.6242676q-0.9266968 0.7918396 -1.2545776 2.718628q-0.33309937 1.9576111 0.2738037 2.9517822q0.6095276 0.97875977 1.81781 1.1381836q0.97592163 0.12875366 1.7261963 -0.3711548q0.7529297 -0.5153198 1.1486511 -1.723938zm2.6727295 8.027954l-1.1773071 -0.15533447q3.489441 -4.031311 4.239624 -8.439819q0.2911377 -1.7109985 0.19241333 -3.457672q-0.09185791 -1.4147949 -0.43444824 -2.7523499q-0.21463013 -0.879364 -1.0046997 -2.9378967l1.1772766 0.15533447q1.3441467 2.5256348 1.771698 4.946106q0.37420654 2.0824585 0.001739502 4.2713013q-0.41967773 2.466278 -1.7735596 4.6517334q-1.3357849 2.172058 -2.9927368 3.7185974z" fill-rule="nonzero"></path></g></svg> + diff --git a/chapter/8/big-data.md b/chapter/8/big-data.md index f3055b0..6c0781d 100644 --- a/chapter/8/big-data.md +++ b/chapter/8/big-data.md @@ -457,12 +457,12 @@ Spark achieves fault tolerant, high throughput data streaming workloads in real- *Apache Mesos* -Apache Mesos{%cite hindman2011mesos --file big-data%} is an open source cluster/resource manager developed at the University of California, Berkley and used by companies such as Twitter, Airbnb, Netflix etc. for handling workloads in a distributed environment through dynamic resource sharing and isolation. It aids in the deployment and management of applications in large-scale clustered environments. Mesos abstracts node allocation by combining the existing resources of the machines/nodes in a cluster into a single pool and enabling fault-tolerant elastic distributed systems. Variety of workloads can utilize the nodes from this single pool voiding the need of allocating specific machines for different workloads. Mesos is highly scalable, achieves fault tolerance through Apache Zookeeper and is a efficient CPU and memory-aware resource scheduler. +Apache Mesos{%cite hindman2011mesos --file big-data%} is an open source heterogenous cluster/resource manager developed at the University of California, Berkley and used by companies such as Twitter, Airbnb, Netflix etc. for handling workloads in a distributed environment through dynamic resource sharing and isolation. It aids in the deployment and management of applications in large-scale clustered environments. Mesos abstracts node allocation by combining the existing resources of the machines/nodes in a cluster into a single pool and enabling fault-tolerant elastic distributed systems. Variety of workloads can utilize the nodes from this single pool voiding the need of allocating specific machines for different workloads. Mesos is highly scalable, achieves fault tolerance through Apache Zookeeper {%cite hunt2010zookeeper --file big-data%} and is a efficient CPU and memory-aware resource scheduler. *Alluxio/Tachyon* -Alluxio/Tachyon{% cite Tachyon --file big-data%} is an open source memory-centric distributed storage system that provides high throughput writes and reads enabling reliable data sharing at memory-speed across cluster jobs. Tachyon can integrate with different computation frameworks, such as Apache Spark and Apache MapReduce. In the big data ecosystem, Tachyon fits between computation frameworks or jobs like spark or mapreducce and various kinds of storage systems, such as Amazon S3, OpenStack Swift, GlusterFS, HDFS, or Ceph. It caches the frequently read datasets in memory, thereby avoiding going to disk to load every dataset. In Spark RDDs can automatically be stored inside Tachyon to make Spark more resilient and avoid GC overheads. +Alluxio/Tachyon{% cite li2014tachyon --file big-data%} is an open source memory-centric distributed storage system that provides high throughput writes and reads enabling reliable data sharing at memory-speed across cluster jobs. Tachyon can integrate with different computation frameworks, such as Apache Spark and Apache MapReduce. In the big data ecosystem, Tachyon fits between computation frameworks or jobs like spark or mapreducce and various kinds of storage systems, such as Amazon S3, OpenStack Swift, GlusterFS, HDFS, or Ceph. It caches the frequently read datasets in memory, thereby avoiding going to disk to load every dataset. In Spark RDDs can automatically be stored inside Tachyon to make Spark more resilient and avoid GC overheads. |
