
Hi, Habrozhiteli! The
Ricardo Terrelli book (Riccardo Terrell) provides insight into the recommended methods for creating competitive and scalable programs in .NET, highlighting the advantages of the functional paradigm and providing the appropriate tools and principles to easily and properly maintain competitiveness. As a result, armed with new skills, you will gain the knowledge necessary to become an expert in providing successful high-performance solutions.
If you are writing multithreaded code in .NET, then this book can help you. If you are interested in using a functional paradigm to simplify competitive programming and maximize application performance, then this book will be an important guide for you. It will benefit any .NET developers who want to write competitive, reactive and asynchronous applications that scale and automatically adapt to existing hardware resources wherever such programs work.
Publication structure: roadmap
The fourteen chapters of this book are divided into three parts. Part I presents the functional concepts of competitive programming and describes the skills needed to understand the functional aspects of writing multi-threaded programs.
- Chapter 1 describes the basic concepts and goals of competitive programming, as well as the reasons for using functional programming to write multi-threaded applications.
- Chapter 2 explores a number of functional programming technologies to improve the performance of multi-threaded applications. The purpose of this chapter is to provide the reader with the concepts used in the rest of the book, and to introduce powerful ideas from the functional paradigm.
- Chapter 3 provides an overview of the functional concept of immutability. It explains how immutability is used to write predictable and correct competitive programs and to implement functional data structures that are thread-safe in nature.
Part II examines in depth the various models of competitive programming in the functional paradigm. We will explore topics such as the Task Parallel Library (TPL) and implement parallel templates such as Fork / Join, Divide and Conquer, and MapReduce. This part also discusses declarative layout, high-level abstractions in asynchronous operations, agent-based programming, and message passing semantics.
')
- Chapter 4 outlines the basics of processing a large amount of data in parallel, including patterns such as Fork / Join.
- Chapter 5 presents more sophisticated methods for parallel processing of large volumes of information, such as parallel aggregation, data reduction and implementation of the parallel MapReduce pattern.
- Chapter 6 provides detailed information about functional methods for processing real-time event (data) streams using high-order functional operators in .NET Reactive Extensions to form asynchronous event combinators. The studied methods will then be used to implement a competitive publisher – subscriber reactive pattern.
- Chapter 7 explains the task-based programming model as applied to functional programming to implement competitive operations using the Monadic template. Then this method is used to build a competitive pipeline based on the functional programming paradigm.
- Chapter 8 is devoted to the implementation of unlimited parallel computing using the asynchronous programming model in C #. This chapter also discusses error handling methods and methods for constructing asynchronous operations.
- Chapter 9 describes the asynchronous workflow on F #. It shows how a delayed and explicit assessment in this model allows us to obtain a higher compositional semantics. Then we will learn how to implement custom computational expressions to increase the level of abstraction to declarative programming.
- Chapter 10 shows how, based on the knowledge gained in previous chapters, you can implement combinators and patterns, such as Functor, Monad, and Applicative, to compose and run several asynchronous operations and error handling without side effects.
- Chapter 11 analyzes reactive programming using a program model of message passing. It reveals the concept of natural isolation as a technology that complements immutability and allows you to create competitive programs. This chapter focuses on the MailboxProcessor class used in F # to distribute parallel work using agent-based programming and a resource-free approach.
- Chapter 12 describes agent programming using the .NET TPL Dataflow library with examples in C #. Here it is shown how to implement stateless and stateful agents on C #, as well as how to perform several calculations in parallel, which exchange data with each other, applying (transmitting) messages in a pipeline style.
Part III shows how to put into practice all the functional methods of competitive programming studied in previous chapters.
- Chapter 13 presents a set of useful recipes for solving complex problems of competitiveness, taken from actual practice. These recipes use all the functional patterns described in this book.
- Chapter 14 describes a complete application developed and implemented using functional competitive patterns and methods studied in this book. You will create a highly scalable, responsive server application and a reactive client program. The book presents two versions: one for iOS (iPad), created using Xamarin Visual Studio, and the second - created using Windows Presentation Foundation (WPF). To ensure maximum scalability in the server application, a combination of various programming models, such as asynchronous, agent and reactive, is used.
The book also contains three applications.
- Appendix A briefly describes the basic concepts of functional programming, and also presents the basic theory of functional methods used in this book.
- Appendix B covers the basic concepts of the F # language. This is a basic F # review that will allow you to get a closer look at this language and feel comfortable while reading a book.
- Appendix B illustrates several methods that simplify the interaction between an asynchronous workflow in F # and a .NET task in C #.
Excerpt 11.6. F # MailboxProcessor: 10,000 Agents for Game of Life
Compared with the flows MailboxProcessor in combination with asynchronous workflows is a simple computing unit (primitive). Agents can appear and be destroyed with minimal cost. You can distribute the work among several MailboxProcessor objects in the same way that you can use threads without the additional overhead associated with creating a new thread. Due to this, it is quite possible to create applications consisting of hundreds of thousands of agents working in parallel, with minimal load on computer resources.
In this section, we will use multiple instances of MailboxProcessor to implement the Game of Life game (Life game) (
wiki-eng and
wiki-rus ). According to Wikipedia, Game of Life, in simple terms, is a cellular automaton. It is a game without players — in other words, when a game starts with a random initial configuration, it runs without any other input. The game consists of a set of cells that form a grid; in each cell several mathematical rules are fulfilled. Cells can live, die and multiply. Each cell interacts with eight neighbors (neighboring cells). To move cells in accordance with these rules, it is necessary to constantly calculate the new state of the grid.
Game of Life has the following rules:
- if a cell has only one neighbor or no neighbors, then it dies “from loneliness”;
- if four or more neighbors of the cell died, then it dies “due to overpopulation”;
- if a cell has two or three neighbors, then it remains to live;
- if a cell has three neighbors, then it multiplies.
Depending on the initial conditions, the cells form characteristic structures throughout the game. Through repeated application of the rules, the next generations of cells are created until the cells reach a stable state (Fig. 11.12).
Listing 11.9 shows the implementation of the Game of Life AgentCell cell, based on the MailboxProcessor F # -types based on MailboxProcessor. Each cell-agent interacts with neighboring cells through asynchronous message passing, thus creating a fully parallelized Game of Life. For brevity, I have omitted some parts of the code, since they are not related to the main topic of the example. Full implementation you will find in the source code for this book, laid out on the publisher's website.
AgentCell describes a cell in the Game of Life grid. The basic concept is that each agent communicates with its neighboring cells about its current state through asynchronous message passing. This template creates a chain of interconnected parallel communications that involves all cells that send their updated state to the MailboxProcessor updateAgent. After receiving this data, updateAgent updates the graphics in the user interface (Listing 11.10).
updateAgent, as the name suggests, updates the state of each pixel according to the cell value received in the Update message. The agent maintains the state of pixels and uses it to create a new image when all cells transfer their new state. Then updateAgent updates the graphical WPF user interface using this new image that matches the current Game of Life grid:
do! Async.SwitchToContext ctx image.Source <- createImage pixels do! Async.SwitchToThreadPool()
It is important to note that the updateAgent agent uses the current synchronization context to correctly update the WPF controller. The current thread is switched to the user interface stream using the Async.SwitchToContext function (described in chapter 9).
The final code snippet for executing Game of Life generates a grid that serves as a playing field for the cells, and then the timer notifies the cells to perform the update (Listing 11.11). In this example, the grid is a square of 100 Ă— 100 cells, a total of 10,000 cells (MailboxProcessor objects), which are calculated in parallel by a timer every 50 ms, as shown in Fig. 11.13. Ten thousand MailboxProcessor objects interact and update the user interface 20 times per second (the code to which you should pay attention is in bold).
Notifications to all cells (agents) are sent in parallel, using PLINQ. Cells are F # -sequences that are considered .NET IEnumerable, which makes LINQ / PLINQ easy to integrate.
When executing the code, the program generates 10,000 F # objects of the type MailboxProcessor in less than 1 ms, while the agents occupy less than 25 MB in memory. Impressive!
Summary
- The agent-based programming model naturally provides immutability and isolation when writing competitive systems, making it even easier to discuss complex systems, since agents are encapsulated inside active objects.
- A reactive manifest defines properties for implementing a reactive system that is flexible, loosely coupled, and scalable.
- Natural isolation is important for writing contention-free code. In a multi-threaded program, isolation solves the problem of shared states by providing each stream with a copied portion of data to perform local calculations. When using isolation, there is no race condition.
- Asynchronous, agents are simple because they do not block threads, waiting for messages. As a result, you can use hundreds of thousands of agents in one application without much impact on the amount of memory.
- The MailboxProcessor F # object provides for two-way communication: the agent can use an asynchronous channel to return (respond) to the caller the result of the calculation.
- The agent-based programming model in F # through MailboxProcessor is an excellent tool for solving bottlenecks in applications such as multi-competitive access to a database. In fact, with the help of agents, applications can be significantly accelerated while maintaining server responsiveness.
- Other .NET programming languages ​​allow you to use the MailboxProcessor F # -type by providing methods using a convenient TPL-based task-based programming model.
»More information about the book can be found on
the publisher's website.»
Table of Contents»
ExcerptHubrozhiteley 20% discount coupon -
Concurrency in .NETUpon payment of the paper version of the book, an electronic version of the book is sent to the e-mail.