Skip to content

Add zh-CN tutorial translation #780

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jan 11, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions _zh-cn/overviews/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
layout: guides-index
language: zh-cn
title: 目录
---

<div class="page-header-index">
<h2>核心库</h2>
</div>
* Scala的容器类
* [简介](/zh-cn/overviews/collections/introduction.html)
* [Mutable和Immutable集合](/zh-cn/overviews/collections/overview.html)
* [Trait Traversable](/zh-cn/overviews/collections/trait-traversable.html)
* [Trait Iterable](/zh-cn/overviews/collections/trait-iterable.html)
* [序列trait:Seq、IndexedSeq 及 LinearSeq](/zh-cn/overviews/collections/seqs.html)
* [集合](/zh-cn/overviews/collections/sets.html)
* [映射](/zh-cn/overviews/collections/maps.html)
* [具体的不可变集实体类](/zh-cn/overviews/collections/concrete-immutable-collection-classes.html)
* [具体的可变容器类](/zh-cn/overviews/collections/concrete-mutable-collection-classes.html)
* [数组](/zh-cn/overviews/collections/arrays.html)
* [字符串](/zh-cn/overviews/collections/strings.html)
* [性能特点](/zh-cn/overviews/collections/performance-characteristics.html)
* [等价性](/zh-cn/overviews/collections/equality.html)
* [视图](/zh-cn/overviews/collections/views.html)
* [Iterators](/zh-cn/overviews/collections/iterators.html)
* [从头定义新容器](/zh-cn/overviews/collections/creating-collections-from-scratch.html)
* [Java和Scala容器的转换](/zh-cn/overviews/collections/conversions-between-java-and-scala-collections.html)
* [Scala 2.7迁移指南](/zh-cn/overviews/collections/migrating-from-scala-27.html)
* [Scala容器类体系结构](/zh-cn/overviews/core/architecture-of-scala-collections.html)
* [字符串插值](/zh-cn/overviews/core/string-interpolation.html) <span class="label success">New in 2.10</span>
* [Implicit Classes](/zh-cn/overviews/core/implicit-classes.html) <span class="label success">New in 2.10</span>
* [Value Classes and Universal Traits](/zh-cn/overviews/core/value-classes.html) <span class="label success">New in 2.10</span>

<div class="page-header-index">
<h2>Parallel and Concurrent Programming</h2>
</div>
* [Future和Promise](/zh-cn/overviews/core/futures.html) <span class="label success">New in 2.10</span>
* Scala的并行容器类
* [概述](/zh-cn/overviews/parallel-collections/overview.html)
* [具体并行集合类](/zh-cn/overviews/parallel-collections/concrete-parallel-collections.html)
* [并行容器的转换](/zh-cn/overviews/parallel-collections/conversions.html)
* [并发字典树](/zh-cn/overviews/parallel-collections/ctries.html)
* [并行集合库的架构](/zh-cn/overviews/parallel-collections/architecture.html)
* [创建自定义并行容器](/zh-cn/overviews/parallel-collections/custom-parallel-collections.html)
* [配置并行集合](/zh-cn/overviews/parallel-collections/configuration.html)
* [测量性能](/zh-cn/overviews/parallel-collections/performance.html)
* [Scala Actors迁移指南](/zh-cn/overviews/core/actors-migration-guide.html) <span class="label success">New in 2.10</span>
* [The Scala Actors API](/zh-cn/overviews/core/actors.html) <span class="label important">Deprecated</span>

<div class="page-header-index">
<h2>Acknowledgements</h2>
</div>
* [致谢名单](/zh-cn/overviews/thanks.html)
156 changes: 138 additions & 18 deletions _zh-cn/overviews/parallel-collections/performance.md
Original file line number Diff line number Diff line change
@@ -1,29 +1,27 @@
---
layout: multipage-overview
layout: overview-large
title: 测量性能

discourse: false
disqus: true

partof: parallel-collections
overview-name: Parallel Collections

num: 8
language: zh-cn
---

## 在JVM上的性能
### 在JVM上的性能

对JVM性能模型的评论常常令人费解,其结论也往往不易理解。由于种种原因,代码也可能不像预期的那样高性能、可扩展。在这里,我们提供了一些示例。

其中一个原因是JVM应用程序的编译过程不同于静态编译语言(见[[2]])。Java和Scala的编译器将源代码转换为JVM的字节码,做了非常少的优化。大多数现代JVM,运行时,会把字节码转化成相应机器架构的机器代码。这个过程被称为即时编译。由于追求运行速度,所以实时编译的代码优化程度较低。为了避免重新编译,所谓的HotSpot编译器只优化了部分经常被运行的代码。这对于基准程序作者来说,这意味着程序每次运行时的性能都可能不同。在同一个JVM实例中多次执行一段相同的代码(比如一个方法)可能会得到非常不同的性能结果,这取决于这段代码在运行过程中是否被优化。另外,在测量某些代码的执行时间时其中可能包含JIT编译器对代码进行优化的时间,因此可能得到不一致的结果。
其中一个原因是JVM应用程序的编译过程不同于静态编译语言(见[[2](http://www.ibm.com/developerworks/library/j-jtp12214/)])。Java和Scala的编译器将源代码转换为JVM的字节码,做了非常少的优化。大多数现代JVM,运行时,会把字节码转化成相应机器架构的机器代码。这个过程被称为即时编译。由于追求运行速度,所以实时编译的代码优化程度较低。为了避免重新编译,所谓的HotSpot编译器只优化了部分经常被运行的代码。这对于基准程序作者来说,这意味着程序每次运行时的性能都可能不同。在同一个JVM实例中多次执行一段相同的代码(比如一个方法)可能会得到非常不同的性能结果,这取决于这段代码在运行过程中是否被优化。另外,在测量某些代码的执行时间时其中可能包含JIT编译器对代码进行优化的时间,因此可能得到不一致的结果。

另一个在JVM上隐藏执行的是内存自动管理。每隔一段时间,程序的运行就被阻塞并且启动垃圾收集器。如果被进行基准测试的程序分配了任何堆内存(大部分JVM程序都会分配),垃圾收集器将会工作,因此可能会影响测量结果。为了缓冲垃圾收集的影响,被测量的程序应该运行多次以便触发多次垃圾回收。

性能恶化的常见原因之一是将原始类型作为参数传递给泛型方法时发生的隐式装箱和拆箱。在运行时,原始类型被转换为封装对象,这样它们就可以作为参数传给有泛型类型参数的方法。这会导致额外的空间分配并且运行速度会更慢,也会在堆中产生额外的垃圾。

就并行性能而言,一个常见的问题是存储冲突,因为程序员针对对象的内存分配没有做明确的控制。事实上,由于GC的影响,冲突可以发生在应用程序生命期的最后,在对象被移出内存后。在编写基准测试时这种影响需要被考虑到。

## 微基准测试的例子
### 微基准测试的例子

有几种方法可以在测试中避免上述影响。首先,目标微基准测试必须被执行足够多次来确保实时编译器将程序编译为机器码并被优化过。这就是所谓的预热阶段。

Expand All @@ -33,9 +31,43 @@ language: zh-cn

最后,为了减少在基准测试中间发生垃圾回收的可能性,理想的垃圾回收周期应该发生在基准测试之前,并尽可能的推迟下一个垃圾回收周期。

正确基准的范例,你可以参考在[Scala library benchmarks][3]的源代码。
scala.testing.Benchmark trait 是在Scala标准库中被预先定义的,并按前面提到的方式设计。下面是一个用于测试并行算法中映射操作的例子:

import collection.parallel.mutable.ParTrieMap
import collection.parallel.ForkJoinTaskSupport

object Map extends testing.Benchmark {
val length = sys.props("length").toInt
val par = sys.props("par").toInt
val partrie = ParTrieMap((0 until length) zip (0 until length): _*)

partrie.tasksupport = new ForkJoinTaskSupport(new scala.concurrent.forkjoin.ForkJoinPool(par))

def run = {
partrie map {
kv => kv
}
}
}

run方法包含了基准测试代码,重复运行时测量执行时间。上面的Map对象扩展了scala.testing.Benchmark trait,同时,参数par为系统的并行度,length为trie中元素数量的长度。

在编译上面的程序之后,可以这样运行:

java -server -cp .:../../build/pack/lib/scala-library.jar -Dpar=1 -Dlength=300000 Map 10

server参数指定需要使用server类型的虚拟机。cp参数指定了类文件的路径,包含当前文件夹的类文件以及以及scala类库的jar包。参数-Dpar和-Dlength分别对应并行度和元素数量。最后,10意味着基准测试需要在同一个JVM中运行的次数。

在i7四核超线程处理器上将par的值设置为1、2、4、8并获得对应的执行时间。

## 多大的容器才应该使用并发?
Map$ 126 57 56 57 54 54 54 53 53 53
Map$ 90 99 28 28 26 26 26 26 26 26
Map$ 201 17 17 16 15 15 16 14 18 15
Map$ 182 12 13 17 16 14 14 12 12 12

我们从上面的结果可以看到运行时间在最初的几次运行中是较高的,但是在代码被优化后时间就缩短了。另外,我们可以看到在这个例子中超线程带来的好处并不明显,从4线程到8线程的结果说明性能只有小幅提升。

### 多大的容器才应该使用并发?

这是一个经常被问到的问题。答案是有些复杂的。

Expand All @@ -49,13 +81,101 @@ collection的大小所对应的实际并发消耗取决于很多因素。部分
- 副作用。当同时修改内存区域或者在foreach、map等语句中使用同步时,就会发生竞争。
- 内存管理。当分配大量对象时垃圾回收机制就会被触发。GC循环会消耗多长时间取决于新对象的引用如何进行传递。

即使单独的来看,对上面的问题进行推断并给出关于容器应有大小的明确答案也是不容易的。为了粗略的说明容器的应有大小,我们给出了一个无副作用的在i7四核处理器(没有使用超线程)和JDK7上运行的并行矢量减(在这个例子中进行的是求和)处理性能的例子:

import collection.parallel.immutable.ParVector

object Reduce extends testing.Benchmark {
val length = sys.props("length").toInt
val par = sys.props("par").toInt
val parvector = ParVector((0 until length): _*)

parvector.tasksupport = new collection.parallel.ForkJoinTaskSupport(new scala.concurrent.forkjoin.ForkJoinPool(par))

def run = {
parvector reduce {
(a, b) => a + b
}
}
}

object ReduceSeq extends testing.Benchmark {
val length = sys.props("length").toInt
val vector = collection.immutable.Vector((0 until length): _*)

def run = {
vector reduce {
(a, b) => a + b
}
}

}
首先我们设定在元素数量为250000的情况下运行基准测试,在线程数设置为1、2、4的情况下得到了如下结果:

java -server -cp .:../../build/pack/lib/scala-library.jar -Dpar=1 -Dlength=250000 Reduce 10 10
Reduce$ 54 24 18 18 18 19 19 18 19 19
java -server -cp .:../../build/pack/lib/scala-library.jar -Dpar=2 -Dlength=250000 Reduce 10 10
Reduce$ 60 19 17 13 13 13 13 14 12 13
java -server -cp .:../../build/pack/lib/scala-library.jar -Dpar=4 -Dlength=250000 Reduce 10 10
Reduce$ 62 17 15 14 13 11 11 11 11 9
然后我们将元素数量降低到120000,使用4个线程来比较序列矢量减运行的时间:

java -server -cp .:../../build/pack/lib/scala-library.jar -Dpar=4 -Dlength=120000 Reduce 10 10
Reduce$ 54 10 8 8 8 7 8 7 6 5
java -server -cp .:../../build/pack/lib/scala-library.jar -Dlength=120000 ReduceSeq 10 10
ReduceSeq$ 31 7 8 8 7 7 7 8 7 8
在这个例子中,元素数量为120000时看起来正处于阈值附近。

在另一个例子中,我们使用mutable.ParHashMap和map方法(一个转换方法),并在同样的环境中运行下面的测试程序:

import collection.parallel.mutable.ParHashMap

object Map extends testing.Benchmark {
val length = sys.props("length").toInt
val par = sys.props("par").toInt
val phm = ParHashMap((0 until length) zip (0 until length): _*)

phm.tasksupport = new collection.parallel.ForkJoinTaskSupport(new scala.concurrent.forkjoin.ForkJoinPool(par))

def run = {
phm map {
kv => kv
}
}
}

object MapSeq extends testing.Benchmark {
val length = sys.props("length").toInt
val hm = collection.mutable.HashMap((0 until length) zip (0 until length): _*)

def run = {
hm map {
kv => kv
}
}
}
在元素数量为120000、线程数量从1增加至4的时候,我们得到了如下结果:

java -server -cp .:../../build/pack/lib/scala-library.jar -Dpar=1 -Dlength=120000 Map 10 10
Map$ 187 108 97 96 96 95 95 95 96 95
java -server -cp .:../../build/pack/lib/scala-library.jar -Dpar=2 -Dlength=120000 Map 10 10
Map$ 138 68 57 56 57 56 56 55 54 55
java -server -cp .:../../build/pack/lib/scala-library.jar -Dpar=4 -Dlength=120000 Map 10 10
Map$ 124 54 42 40 38 41 40 40 39 39

现在,如果我们将元素数量降低到15000来跟序列化哈希映射做比较:

java -server -cp .:../../build/pack/lib/scala-library.jar -Dpar=1 -Dlength=15000 Map 10 10
Map$ 41 13 10 10 10 9 9 9 10 9
java -server -cp .:../../build/pack/lib/scala-library.jar -Dpar=2 -Dlength=15000 Map 10 10
Map$ 48 15 9 8 7 7 6 7 8 6
java -server -cp .:../../build/pack/lib/scala-library.jar -Dlength=15000 MapSeq 10 10
MapSeq$ 39 9 9 9 8 9 9 9 9 9

对这个容器和操作来说,当元素数量大于15000的时候采用并发是有意义的(通常情况下,对于数组和向量来说使用更少的元素来并行处理hashmap和hashset是可行的但不是必须的)。

**引用**

1. [Anatomy of a flawed microbenchmark,Brian Goetz](http://www.ibm.com/developerworks/java/library/j-jtp02225/index.html)
2. [Dynamic compilation and performance measurement, Brian Goetz](http://www.ibm.com/developerworks/library/j-jtp12214/)

## 引用

1. [Anatomy of a flawed microbenchmark, Brian Goetz][1]
2. [Dynamic compilation and performance measurement, Brian Goetz][2]
3. [Scala library benchmarks][3]

[1]: http://www.ibm.com/developerworks/java/library/j-jtp02225/index.html "flawed-benchmark"
[2]: http://www.ibm.com/developerworks/library/j-jtp12214/ "dynamic-compilation"
[3]: https://github.com/scala/scala/tree/2.12.x/test/benchmarks
47 changes: 47 additions & 0 deletions _zh-cn/overviews/thanks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
layout: guides-thanks
language: zh-cn
title: 致谢名单
---

2013年10月份起,CSDN CODE开始组织志愿者翻译Scala官方文档。计划翻译的文档主要为Scala官网上overview部分的内容,包含以下部分:

- The Scala Actors Migration Guide
- Value Classes and Universal Traits
- String Interpolation
- Implicit Classes
- Futures and Promises
- Scala’s Parallel Collections Library
- The Architecture of Scala Collections
- The Scala Actors API
- Scala’s Collections Library

经过公开征集、筛选,我们最终组织了二十多位志愿者来进行此项翻译工作。我们并邀请到了国内Scala知名社区“Scala研学社”的两位老师**连城**、**尹绪森**来担任顾问和翻译校对的工作。在此向Scala研学社表示衷心的感谢!

更要特别感谢的是在此次翻译工作中付出辛勤劳动的、广大的翻译志愿者朋友们,他们是:
(以下按姓氏拼音排序)
姓名 CSDN ID
陈骏 [jacty0219](https://code.csdn.net/jacty0219)
陈幸 Meteor2520
董泉 dqsweet
何乃梧 [yuyi20112011](https://code.csdn.net/yuyi20112011)
黄越勇 aptweasel
赖正兴 laizx
李奕飞 fancylee
林君 a455642158
刘国锋 [iceongrass](https://code.csdn.net/iceongrass)
吕浩志 lvhaozhi
聂雪珲 blueforgetmenot
潘栋华
潘义文 Caidaoqq
王金岩 i9901028
王雨施
熊杰 [xiaoxiong345064855](https://code.csdn.net/xiaoxiong345064855)
杨志斌 qwewegfd
张冰 usen521
张明明 [a775901421](https://code.csdn.net/a775901421)
张欣 [email protected]
周逸灵 pastgift

感谢大家的辛勤劳动!
我们已将经过最终校审的Scala文档中文版上传在此文档项目中,欢迎各位阅读、指正。如果您发现翻译稿件中有什么错误或问题,可以在此项目中给我们留言,或者直接派生、修改后提交合并请求给我们。谢谢!
Loading