
嗨,habrozhiteli! Riccardo Terrell的书提供了有关如何在.NET中创建具有竞争力的可伸缩程序的指南,着重介绍了功能范式的好处,并提供了适当的工具和原则来轻松正确地进行竞争。 这样一来,凭借新技能,您将获得成为成功提供高性能解决方案专家所需的知识。
如果您正在.NET中编写多线程代码,那么本书可能会对您有所帮助。 如果您对使用功能范式简化竞争性编程并最大化应用程序性能感兴趣,那么这本书将是您的重要指南。 任何希望编写有竞争力,反应性和异步应用程序的.NET开发人员都将从中受益,只要这些程序在任何地方运行,它们都可以扩展并自动适应可用的硬件资源。
出版结构:路线图
本书的十四章分为三个部分。 第一部分介绍了竞争性编程的功能概念,并介绍了理解编写多线程程序的功能方面所必需的技能。
- 第1章介绍竞争性编程的基本概念和目标,以及使用函数式编程编写多线程应用程序的原因。
- 第2章探讨了一系列功能编程技术,以提高多线程应用程序的性能。 本章的目的是向读者提供本书其余部分中使用的概念,并介绍功能范式所产生的强大思想。
- 第3章概述了不变性的功能概念。 它解释了不变性如何用于编写可预测和正确的竞争程序以及实现本质上线程安全的功能数据结构。
在第二部分中,将深入研究功能范式中竞争性编程的各种模型。 我们将探索诸如任务并行库(TPL)之类的主题,并实现诸如Fork / Join,分治法和MapReduce之类的并行模式。 本节还讨论了声明式布局,异步操作中的高级抽象,代理编程和消息传输语义。
- 第4章概述了并行处理大量数据的基础,包括Fork / Join等模板。
- 第5章介绍了用于并行处理大量信息的更复杂的方法,例如并行聚合,数据缩减以及并行MapReduce模板的实现。
- 第6章提供了有关使用.NET Reactive Extensions中的高阶函数运算符实时形成事件(数据)流的功能方法的详细信息,以形成异步事件组合器。 然后,将使用研究的方法来实施竞争性的发布者-订阅者反应性模板。
- 第7章提供了基于任务的编程模型的说明,该模型适用于使用Monadic模板实施竞争性操作的函数式编程。 然后,该方法用于基于功能编程范例构建竞争管道。
- 第8章致力于使用C#异步编程模型实现无限并行计算。 本章还讨论了错误处理方法以及用于构造异步操作的方法。
- 第9章介绍了F#中的异步工作流。 它显示了此模型中的延迟和显式评估如何允许更高的构成语义。 然后,我们将学习如何实现自定义计算表达式,以提高对声明式编程的抽象水平。
- 第10章展示了如何根据前几章获得的知识来实现组合器和模板,例如Functor,Monad和Applicative,以组成并运行多个异步操作并处理错误而没有副作用。
- 第11章使用软件消息传递模型分析反应式编程。 它揭示了自然隔离的概念,它是补充不变性并允许创建竞争程序的技术。 本章重点介绍F#中使用的MailboxProcessor类,该类使用代理程序编程和无资源的方法来分发并行工作。
- 第12章使用C#中的示例描述了使用.NET的TPL Dataflow库进行的代理编程。 它显示了如何在C#中实现无状态代理和有状态代理,以及如何使用流水线式的(发送)消息并行执行几个相互交换数据的计算。
第三部分显示了如何将前几章研究的竞争性编程的所有功能方法付诸实践。
- 第13章提供了一组解决实际竞争问题的有用方法,这些方法是从实际操作中获得的。 这些配方使用本书中描述的所有功能模式。
- 第14章介绍了使用本书中研究的功能竞争模板和方法开发和实现的完整应用程序。 您将创建一个高度可扩展的响应服务器应用程序和响应客户端程序。 本书包含两个版本:一个用于iOS(iPad),使用Xamarin Visual Studio创建,第二个-使用Windows Presentation Foundation(WPF)创建。 为了确保服务器应用程序中的最大可伸缩性,使用了各种编程模型的组合,例如异步,代理和反应式。
本书还包含三个应用程序。
- 附录A简要描述了函数编程的基本概念,并介绍了本书中使用的函数方法的基本理论。
- 附录B揭示了F#语言的基本概念。 这是对F#的基本回顾,它将使您熟悉这种语言并在读书时感到自在。
- 附录B演示了几种简化F#中的异步工作流与C#中的.NET任务之间的交互的方法。
摘录。 11.6。 F#MailboxProcessor:10,000个人生游戏代理
与线程相比,与异步工作流结合使用的MailboxProcessor是一个简单的计算单元(原始)。 特工可以最小的代价出现并被摧毁。 您可以以与使用线程相同的方式在多个MailboxProcessor对象之间分配工作,而无需增加与创建新线程相关的开销。 因此,很有可能创建由成千上万的代理组成的应用程序,这些代理可以在不占用计算机资源的情况下最小地并行工作。
在本节中,我们将使用MailboxProcessor的多个实例来实现游戏“生活游戏”(游戏“ Life”)(
wiki-eng和
wiki-eng )。 根据维基百科,简而言之,生命游戏是一个细胞自动机。 这是一款没有玩家的游戏-换句话说,当游戏以随机的初始配置开始时,它的运行无需任何其他输入。 游戏由一组形成网格的单元组成; 在每个单元格中都满足一些数学规则。 细胞可以生存,死亡和繁殖。 每个单元与八个邻居(邻居单元)交互。 要按照这些规则移动单元,必须不断地计算网格的新状态。
生命游戏具有以下规则:
- 如果一个小区只有一个邻居或没有邻居,则“死于寂寞”;
- 如果一个单元格的四个或更多邻居死亡,则其“由于人口过多”而死亡;
- 如果该小区有两个或三个邻居,则它仍然可以存活;
- 如果一个单元有三个邻居,则它相乘。
根据初始条件,游戏单元会在整个游戏过程中形成特征结构。 通过重复应用规则,将创建以下几代细胞,直到这些细胞达到稳定状态为止(图11.12)。
清单11.9显示了基于MailboxProcessor的F#类型的生命游戏AgentCell单元的实现。 每个代理单元都通过异步消息传递与相邻单元交互,从而创建完全并行的生命游戏。 为简洁起见,我省略了代码的某些部分,因为它们与示例的主要主题无关。 您可以在发布商网站上发布的本书的源代码中找到完整的实现。
AgentCell在“生命游戏”网格中描述了一个单元。 基本概念是每个代理通过异步消息传递与相邻小区交换有关其当前状态的信息。 此模板创建了一个互连的并行通信链,该通信涉及所有单元将其更新状态发送到MailboxProcessor updateAgent。 收到此数据后,updateAgent将更新用户界面中的图形(清单11.10)。
顾名思义,updateAgent根据更新消息中接收的单元格值更新每个像素的状态。 当所有单元格通过其新状态时,代理会维护像素的状态并使用它来创建新图像。 然后,UpdateAgent使用与当前“生命游戏”网格匹配的新图像来更新WPF GUI:
do! Async.SwitchToContext ctx image.Source <- createImage pixels do! Async.SwitchToThreadPool()
重要的是要注意,updateAgent使用当前的同步上下文正确更新WPF控制器。 使用Async.SwitchToContext函数(在第9章中介绍)将当前线程切换到用户界面线程。
执行“生命游戏”的最后一段代码生成一个网格,用作单元的运动场,然后计时器通知单元有关执行更新的需要(清单11.11)。 在此示例中,网格是100×100单元的正方形,总共10,000个单元(MailboxProcessor对象),每50毫秒与计时器并行计算一次,如图2所示。 11.13。 一万个MailboxProcessor对象每秒交互和更新用户界面20次(粗体显示您应注意的代码)。
使用PLINQ并行发送到所有单元(代理)的通知。 单元是被视为.NET IEnumerable的F#序列,从而使LINQ / PLINQ易于集成。
执行代码后,程序将在不到1 ms的时间内生成10,000个F#对象,类型为MailboxProcessor,而代理程序则占用不到25 MB的内存。 令人印象深刻!
总结
- 基于代理的编程模型在编写竞争性系统时自然会提供不变性和隔离性,因为将代理封装在活动对象中,因此讨论复杂系统甚至变得更加容易。
- 反应性清单定义了用于实现灵活,松散耦合和可伸缩的反应性系统的属性。
- 自然隔离对于编写具有竞争力的代码而不受阻碍很重要。 在多线程程序中,隔离通过为每个线程提供复制的数据片段来执行本地计算,从而解决了共享状态的问题。 使用绝缘材料时,没有竞争条件。
- 作为异步,代理很简单,因为它们在等待消息时不会阻塞线程。 结果,您可以在一个应用程序中使用成千上万的代理,而不会对内存大小产生太大影响。
- MailboxProcessor F#对象提供双向通信:代理可以使用异步通道将计算结果返回(应答)给调用对象。
- F#中通过MailboxProcessor进行的代理程序编程模型是解决应用程序瓶颈(例如多个并发数据库访问)的出色工具。 实际上,在代理的帮助下,您可以显着加快应用程序的速度,同时保持服务器的响应速度。
- 其他.NET编程语言允许您使用F#类型的MailboxProcessor,并使用基于任务的便捷TPL编程模型提供方法。
»这本书的更多信息可以
在出版商的网站上找到»
目录»
摘录小贩可享受20%的优惠券-.NET中的
并发支付纸质版本的书后,将通过电子邮件发送该书的电子版本。