Concurrency Programming Guide 并发设计指引(四)

8 篇文章 0 订阅

以下翻译是本人通过谷歌工具进行翻译,并进行修正后的结果,希望能对大家有所帮助。如果您发现翻译的不正确不合适的地方,希望您能够发表评论指正,谢谢。转载请注明出处。


Factor Out Executable Units of Work
From your understanding of your application’s tasks, you should already be able to identify places where your code might benefit from concurrency. If changing the order of one or more steps in a task changes the results, you probably need to continue performing those steps serially. If changing the order has no effect on the output, though, you should consider performing those steps concurrently. In both cases, you define the executable unit of work that represents the step or steps to be performed. This unit of work then becomes what you encapsulate using either a block or an operation object and dispatch to the appropriate queue.

For each executable unit of work you identify, do not worry too much about the amount of work being performed, at least initially. Although there is always a cost to spinning up a thread, one of the advantages of dispatch queues and operation queues is that in many cases those costs are much smaller than they are for traditional threads. Thus, it is possible for you to execute smaller units of work more efficiently using queues than you could using threads. Of course, you should always measure your actual performance and adjust the size of your tasks as needed, but initially, no task should be considered too small.

分解出可执行的工作单元
以你对应用程序的任务的理解,你应该已经能够确定你的代码可能适合使用并发的地方。如果改变任务中的一个或多个步骤的顺序改变了输出结果,你可能需要继续串行执行这些步骤。如果改变顺序后没有对输出的影响造成影响,你应该考虑并行执行这些步骤。在这两种情况下,你定义可执行的工作单元,工作单元表示要执行的一个或多个步骤,然后这个单位的工元成为你封装使用一个块或操作对象,并派遣到合适的队列中。
对于每个你确定的可执行工作单元,不需要太担心正在执行的任务所需的工作量,至少在最初阶段。虽然总有创建线程的开销,但在许多情况下,调度队列和操作队列的优点是这些费用是远小于传统的线程。因此,它可以为您执行更小的单位的工作,更有效地使用队列比你能使用的线程。当然,你应该经常测量你的实际表现,你的任务需要调整大小,但最初,不应该把任务考虑的太小。


Identify the Queues You Need
Now that your tasks are broken up into distinct units of work and encapsulated using block objects or operation objects, you need to define the queues you are going to use to execute that code. For a given task, examine the blocks or operation objects you created and the order in which they must be executed to perform the task correctly.

If you implemented your tasks using blocks, you can add your blocks to either a serial or concurrent dispatch queue. If a specific order is required, you would always add your blocks to a serial dispatch queue. If a specific order is not required, you can add the blocks to a concurrent dispatch queue or add them to several different dispatch queues, depending on your needs.

If you implemented your tasks using operation objects, the choice of queue is often less interesting than the configuration of your objects. To perform operation objects serially, you must configure dependencies between the related objects. Dependencies prevent one operation from executing until the objects on which it depends have finished their work.

确定你需要的队列
现在你的任务被分解成不同的单位工作,并使用块对象或操作对象封装,你需要你要使用执行该代码定义的队列。对于一个给定的任务,检查的块或操作您所创建的对象,他们必须执行的顺序正确执行任务。

如果您用块实施了你的任务,你可以使用块添加块到任何一个串行或并行调度队列。如果需要一个特定的顺序,你需要添加块到串行调度队列。如果一个特定的顺序不是必需的,你可以添加块到并发调度队列,或根据您的需要将它们添加到几种不同的调度队列。

如果您使用操作对象实施了你的任务,队列的选择往往不比你的对象的配置那么有趣。要连续执行操作对象,您必须配置相关的对象之间的依赖关系。依赖性防止一个操作执行,直到它依赖的对象已经完成了他们的工作。

Tips for Improving Efficiency
In addition to simply factoring your code into smaller tasks and adding them to a queue, there are other ways to improve the overall efficiency of your code using queues:

1.Consider computing values directly within your task if memory usage is a factor. If your application is already memory bound, computing values directly now may be faster than loading cached values from main memory. Computing values directly uses the registers and caches of the given processor core, which are much faster than main memory. Of course, you should only do this if testing indicates this is a performance win.
2.Identify serial tasks early and do what you can to make them more concurrent. If a task must be executed serially because it relies on some shared resource, consider changing your architecture to remove that shared resource. You might consider making copies of the resource for each client that needs one or eliminate the resource altogether.
3.Avoid using locks. The support provided by dispatch queues and operation queues makes locks unnecessary in most situations. Instead of using locks to protect some shared resource, designate a serial queue (or use operation object dependencies) to execute tasks in the correct order.
4.Rely on the system frameworks whenever possible. The best way to achieve concurrency is to take advantage of the built-in concurrency provided by the system frameworks. Many frameworks use threads and other technologies internally to implement concurrent behaviors. When defining your tasks, look to see if an existing framework defines a function or method that does exactly what you want and does so concurrently. Using that API may save you effort and is more likely to give you the maximum concurrency possible.

提高效率的技巧
除了简单划分你的代码为较小的任务,并将它们添加到队列中,还有其他的方法来提高你的代码使用队列的整体效率:

1.考虑在你的任务中直接计算值,如果你的内存是一个因素。如果你的应用程序已经绑定内存,直接计算值可能会比从主内存中加载缓存的值更快。直接计算值使用的寄存器和高速缓存的处理器核心,这是远快于主存储器。当然,你应该只做到这一点,如果测试结果表明这是一个性能的双赢。
2.及早确定串行任务以及你可以做一些使他们更多的并发的事。如果一个任务必须串行执行,因为它依赖于一些共享资源,可以考虑改变你的架构去删除共享资源。您可能会考虑为每一个客户制作一个资源的副本,或者完全消除资源。
3.避免使用锁。调度队列和运行队列提供的支持使得在大多数情况下不必要的锁。使用锁来保护一些共享资源,而是指定一个串行队列(或使用操作对象依赖) ,以正确的顺序执行任务。
4.尽可能依靠系统的框架。最好的方式来实现并发是利用系统框架所提供的内置的并发性。许多框架内部使用线程和其他技术来实现并发行为。当定义你的任务,看看,如果现有的框架定义了一个函数或方法,这是不是正是你想要的。使用该API可以节省您的精力和更可能给你的最大并发可能。

Performance Implications

Operation queues, dispatch queues, and dispatch sources are provided to make it easier for you to execute more code concurrently. However, these technologies do not guarantee improvements to the efficiency or responsiveness in your application. It is still your responsibility to use queues in a manner that is both effective for your needs and does not impose an undue burden on your application’s other resources. For example, although you could create 10,000 operation objects and submit them to an operation queue, doing so would cause your application to allocate a potentially nontrivial amount of memory, which could lead to paging and decreased performance.

Before introducing any amount of concurrency to your code—whether using queues or threads—you should always gather a set of baseline metrics that reflect your application’s current performance. After introducing your changes, you should then gather additional metrics and compare them to your baseline to see if your application’s overall efficiency has improved. If the introduction of concurrency makes your application less efficient or responsive, you should use the available performance tools to check for the potential causes.

For an introduction to performance and the available performance tools, and for links to more advanced performance-related topics, see Performance Overview.

性能影响

操作队列,调度队列和调度来源,使其更容易为你同时执行更多的代码。然而,这些技术不保证在您的应用程序的效率或响应的改进。它仍然是你的责任,使用队列的方式,既有效满足您的需求,同时不会对你的应用程序的其他资源造成不必要的负担。例如,虽然您可以创建10,000操作对象,并将其提交到一个操作队列中,这样做会导致您的应用程序分配一个潜在的非正常的内存量,这可能导致性能下降。

在引入任何数量的并发量到你的代码之前—是否使用队列或线程,你应该总是收集了一组反映您的应用程序的当前表现的基准指标。然后引入变更后,你应该收集更多的指标,并比较它们的基准,看看您的应用程序的整体效率是否提高。如果并发引入使您的应用程序效率较低或响应,你应该使用可用的性能工具来检查的潜在原因。

介绍了性能和可用的性能工具,以及更先进的性能相关的主题的链接,请参见性能概述。



Concurrency and Other Technologies

Factoring your code into modular tasks is the best way to try and improve the amount of concurrency in your application. However, this design approach may not satisfy the needs of every application in every case. Depending on your tasks, there might be other options that can offer additional improvements in your application’s overall concurrency. This section outlines some of the other technologies to consider using as part of your design.

并发和其他技术
尝试和改进的在您的应用程序的并发量的最好的方式,就是将你的代码模块化。然而,这种设计方法可能无法满足在每一种情况下的每一个应用程序的需要。根据你的任务,可能还有其他的选项,可以提供额外的改进,在您的应用程序的整体并发。本节概述一些其他技术去考虑使用你的设计的一部分。

When to Use Threads
Although operation queues and dispatch queues are the preferred way to perform tasks concurrently, they are not a panacea. Depending on your application, there may still be times when you need to create custom threads. If you do create custom threads, you should strive to create as few threads as possible yourself and you should use those threads only for specific tasks that cannot be implemented any other way.

Threads are still a good way to implement code that must run in real time. Dispatch queues make every attempt to run their tasks as fast as possible but they do not address real time constraints. If you need more predictable behavior from code running in the background, threads may still offer a better alternative.

As with any threaded programming, you should always use threads judiciously and only when absolutely necessary. For more information about thread packages and how you use them, see Threading Programming Guide.

何时使用线程
虽然操作队列调度队列是同时执行任务的首选方式,他们不是万能的。根据您的应用程序,仍然有时候需要你创建自定义的线程。如果你创建了自定义线程,你应该尽可能的创建少量的线程,而且这些线程是为了某些特定的不能被其他方式替代的任务。
在必须实施运行的代码中,线程仍然是一种很好的方式。调度队列尽一切努力尽可能快地执行他们的任务,但他们不解决实时约束。如果您需要在后台运行的代码更可预测的行为,线程可能依然会提供一个更好的选择。

任何线程编程,你应该总是明智的和只有在绝对必要的时候使用线程。欲了解更多有关线程包,以及如何使用它们的信息,请参见线程编程指南。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值