You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flink.apache.org by se...@apache.org on 2020/11/03 15:34:43 UTC
[flink] 09/10: [FLINK-19602][network] Introduce new config options
to enable sort-merge based blocking shuffle
This is an automated email from the ASF dual-hosted git repository.
sewen pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/flink.git
commit 11ba5b3b26e146d80e1319d77d1ee5ef2dd261d1
Author: kevin.cyj <ke...@alibaba-inc.com>
AuthorDate: Mon Oct 12 20:45:49 2020 +0800
[FLINK-19602][network] Introduce new config options to enable sort-merge based blocking shuffle
Two new config options are added to control the behavior of the sort-merge based blocking shuffle:
1. taskmanager.network.sort-shuffle.min-buffers: Minimum number of network buffers required per sort-merge blocking result partition.
2. taskmanager.network.sort-shuffle.min-parallelism: Parallelism threshold to switch between sort-merge blocking shuffle and the default hash-based blocking shuffle.
With these new config options, the default behavior of blocking shuffle stays unchanged.
---
.../generated/all_taskmanager_network_section.html | 12 ++
.../netty_shuffle_environment_configuration.html | 12 ++
docs/ops/memory/mem_tuning.md | 20 ++++
docs/ops/memory/mem_tuning.zh.md | 17 +++
.../NettyShuffleEnvironmentOptions.java | 30 +++++
.../io/network/NettyShuffleServiceFactory.java | 4 +-
.../network/partition/ResultPartitionFactory.java | 68 ++++++++----
.../NettyShuffleEnvironmentConfiguration.java | 33 +++++-
.../io/network/NettyShuffleEnvironmentBuilder.java | 18 ++-
.../network/partition/ResultPartitionBuilder.java | 22 +++-
.../partition/ResultPartitionFactoryTest.java | 29 ++++-
.../flink/test/runtime/BlockingShuffleITCase.java | 123 +++++++++++++++++++++
.../flink/test/runtime/JobGraphRunningUtil.java | 62 +++++++++++
.../test/runtime/ShuffleCompressionITCase.java | 33 +-----
14 files changed, 423 insertions(+), 60 deletions(-)
diff --git a/docs/_includes/generated/all_taskmanager_network_section.html b/docs/_includes/generated/all_taskmanager_network_section.html
index 6c2a11b..5e5336d 100644
--- a/docs/_includes/generated/all_taskmanager_network_section.html
+++ b/docs/_includes/generated/all_taskmanager_network_section.html
@@ -104,5 +104,17 @@
<td>Integer</td>
<td>The number of retry attempts for network communication. Currently it's only used for establishing input/output channel connections</td>
</tr>
+ <tr>
+ <td><h5>taskmanager.network.sort-shuffle.min-buffers</h5></td>
+ <td style="word-wrap: break-word;">64</td>
+ <td>Integer</td>
+ <td>Minimum number of network buffers required per sort-merge blocking result partition. For large scale batch jobs, it is suggested to increase this config value to improve compression ratio and reduce small network packets. Note: to increase this config value, you may also need to increase the size of total network memory to avoid "insufficient number of network buffers" error.</td>
+ </tr>
+ <tr>
+ <td><h5>taskmanager.network.sort-shuffle.min-parallelism</h5></td>
+ <td style="word-wrap: break-word;">2147483647</td>
+ <td>Integer</td>
+ <td>Parallelism threshold to switch between sort-merge blocking shuffle and the default hash-based blocking shuffle, which means for small parallelism, hash-based blocking shuffle will be used and for large parallelism, sort-merge blocking shuffle will be used. Note: sort-merge blocking shuffle uses unmanaged direct memory for shuffle data writing and reading so just increase the size of direct memory if direct memory OOM error occurs.</td>
+ </tr>
</tbody>
</table>
diff --git a/docs/_includes/generated/netty_shuffle_environment_configuration.html b/docs/_includes/generated/netty_shuffle_environment_configuration.html
index 018296a..9d54dca 100644
--- a/docs/_includes/generated/netty_shuffle_environment_configuration.html
+++ b/docs/_includes/generated/netty_shuffle_environment_configuration.html
@@ -122,5 +122,17 @@
<td>Integer</td>
<td>The number of retry attempts for network communication. Currently it's only used for establishing input/output channel connections</td>
</tr>
+ <tr>
+ <td><h5>taskmanager.network.sort-shuffle.min-buffers</h5></td>
+ <td style="word-wrap: break-word;">64</td>
+ <td>Integer</td>
+ <td>Minimum number of network buffers required per sort-merge blocking result partition. For large scale batch jobs, it is suggested to increase this config value to improve compression ratio and reduce small network packets. Note: to increase this config value, you may also need to increase the size of total network memory to avoid "insufficient number of network buffers" error.</td>
+ </tr>
+ <tr>
+ <td><h5>taskmanager.network.sort-shuffle.min-parallelism</h5></td>
+ <td style="word-wrap: break-word;">2147483647</td>
+ <td>Integer</td>
+ <td>Parallelism threshold to switch between sort-merge blocking shuffle and the default hash-based blocking shuffle, which means for small parallelism, hash-based blocking shuffle will be used and for large parallelism, sort-merge blocking shuffle will be used. Note: sort-merge blocking shuffle uses unmanaged direct memory for shuffle data writing and reading so just increase the size of direct memory if direct memory OOM error occurs.</td>
+ </tr>
</tbody>
</table>
diff --git a/docs/ops/memory/mem_tuning.md b/docs/ops/memory/mem_tuning.md
index bbb210c..2cbbdbc 100644
--- a/docs/ops/memory/mem_tuning.md
+++ b/docs/ops/memory/mem_tuning.md
@@ -88,3 +88,23 @@ on the performance of your applications. Flink will attempt to allocate and use
as configured for batch jobs but not go beyond its limits. This prevents `OutOfMemoryError`'s because Flink knows precisely
how much memory it has to leverage. If the [managed memory](../memory/mem_setup_tm.html#managed-memory) is not sufficient,
Flink will gracefully spill to disk.
+
+## Configure memory for sort-merge blocking shuffle
+
+The number of required network buffers per sort-merge blocking result partition is controlled by
+[taskmanager.network.sort-shuffle.min-buffers](../config.html#taskmanager-network-sort-shuffle-min-buffers)
+and the default value is 64 which is quite small. Though it can work for arbitrary parallelism, the
+performance may not be the best. For large scale jobs, it is suggested to increase this config value
+to improve compression ratio and reduce small network packets which is good for performance. To increase
+this value, you may also need to increase the size of total network memory by adjusting the config
+values of [taskmanager.memory.network.fraction](../config.html#taskmanager-memory-network-fraction),
+[taskmanager.memory.network.min](../config.html#taskmanager-memory-network-min) and [taskmanager.
+memory.network.max](../config.html#taskmanager-memory-network-max) to avoid `insufficient number of
+network buffers` error.
+
+Except for network memory, the sort-merge blocking shuffle implementation also uses some unmanaged
+direct memory for shuffle data writing and reading. So to use sort-merge blocking shuffle, you may
+need to reserve some direct memory for it by increasing the config value of [taskmanager.memory.task
+.off-heap.size](../config.html#taskmanager-memory-task-off-heap-size). If direct memory OOM error
+occurs after you enable the sort-merge blocking shuffle, you can just give more direct memory until
+the OOM error disappears.
diff --git a/docs/ops/memory/mem_tuning.zh.md b/docs/ops/memory/mem_tuning.zh.md
index e4f8c99..1533012 100644
--- a/docs/ops/memory/mem_tuning.zh.md
+++ b/docs/ops/memory/mem_tuning.zh.md
@@ -85,3 +85,20 @@ Flink 批处理算子使用[托管内存](../memory/mem_setup_tm.html#managed-me
因此 Flink 会在不超过其配置限额的前提下,尽可能分配更多的[托管内存](../memory/mem_setup_tm.html#managed-memory)。
Flink 明确知道可以使用的内存大小,因此可以有效避免 `OutOfMemoryError` 的发生。
当[托管内存](../memory/mem_setup_tm.html#managed-memory)不足时,Flink 会优雅地将数据落盘。
+
+## SortMerge数据Shuffle内存配置
+
+对于SortMerge数据Shuffle,每个ResultPartition需要的网络缓冲区(Buffer)数目是由[taskmanager.network.sort-
+shuffle.min-buffers](../config.html#taskmanager-network-sort-shuffle-min-buffers)这个配置决定的。它的
+默认值是64,是比较小的。虽然64个网络Buffer已经可以支持任意规模的并发,但性能可能不是最好的。对于大并发的作业,通
+过增大这个配置值,可以提高落盘数据的压缩率并且减少网络小包的数量,从而有利于提高Shuffle性能。为了增大这个配置值,
+你可能需要通过调整[taskmanager.memory.network.fraction](../config.html#taskmanager-memory-network-fraction),
+[taskmanager.memory.network.min](../config.html#taskmanager-memory-network-min)和[taskmanager.memory
+.network.max](../config.html#taskmanager-memory-network-max)这三个参数来增大总的网络内存大小从而避免出现
+`insufficient number of network buffers`错误。
+
+除了网络内存,SortMerge数据Shuffle还需要使用一些JVM Direct Memory来进行Shuffle数据的写出与读取。所以,为了使
+用SortMerge数据Shuffle你可能还需要通过增大这个配置值[taskmanager.memory.task.off-heap.size
+](../config.html#taskmanager-memory-task-off-heap-size)来为其来预留一些JVM Direct Memory。如果在你开启
+SortMerge数据Shuffle之后出现了Direct Memory OOM的错误,你只需要继续加大上面的配置值来预留更多的Direct Memory
+直到不再发生Direct Memory OOM的错误为止。
diff --git a/flink-core/src/main/java/org/apache/flink/configuration/NettyShuffleEnvironmentOptions.java b/flink-core/src/main/java/org/apache/flink/configuration/NettyShuffleEnvironmentOptions.java
index 584bc6e..f8c71c6 100644
--- a/flink-core/src/main/java/org/apache/flink/configuration/NettyShuffleEnvironmentOptions.java
+++ b/flink-core/src/main/java/org/apache/flink/configuration/NettyShuffleEnvironmentOptions.java
@@ -174,6 +174,36 @@ public class NettyShuffleEnvironmentOptions {
" increased in case of higher round trip times between nodes and/or larger number of machines in the cluster.");
/**
+ * Minimum number of network buffers required per sort-merge blocking result partition.
+ */
+ @Documentation.Section(Documentation.Sections.ALL_TASK_MANAGER_NETWORK)
+ public static final ConfigOption<Integer> NETWORK_SORT_SHUFFLE_MIN_BUFFERS =
+ key("taskmanager.network.sort-shuffle.min-buffers")
+ .intType()
+ .defaultValue(64)
+ .withDescription("Minimum number of network buffers required per sort-merge blocking "
+ + "result partition. For large scale batch jobs, it is suggested to increase this"
+ + " config value to improve compression ratio and reduce small network packets. "
+ + "Note: to increase this config value, you may also need to increase the size of "
+ + "total network memory to avoid \"insufficient number of network buffers\" error.");
+
+ /**
+ * Parallelism threshold to switch between sort-merge based blocking shuffle and the default
+ * hash-based blocking shuffle.
+ */
+ @Documentation.Section(Documentation.Sections.ALL_TASK_MANAGER_NETWORK)
+ public static final ConfigOption<Integer> NETWORK_SORT_SHUFFLE_MIN_PARALLELISM =
+ key("taskmanager.network.sort-shuffle.min-parallelism")
+ .intType()
+ .defaultValue(Integer.MAX_VALUE)
+ .withDescription("Parallelism threshold to switch between sort-merge blocking shuffle "
+ + "and the default hash-based blocking shuffle, which means for small parallelism,"
+ + " hash-based blocking shuffle will be used and for large parallelism, sort-merge"
+ + " blocking shuffle will be used. Note: sort-merge blocking shuffle uses unmanaged"
+ + " direct memory for shuffle data writing and reading so just increase the size of"
+ + " direct memory if direct memory OOM error occurs.");
+
+ /**
* Number of max buffers can be used for each output subparition.
*/
@Documentation.Section(Documentation.Sections.ALL_TASK_MANAGER_NETWORK)
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/io/network/NettyShuffleServiceFactory.java b/flink-runtime/src/main/java/org/apache/flink/runtime/io/network/NettyShuffleServiceFactory.java
index d5863d7..ecd8027 100644
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/io/network/NettyShuffleServiceFactory.java
+++ b/flink-runtime/src/main/java/org/apache/flink/runtime/io/network/NettyShuffleServiceFactory.java
@@ -126,7 +126,9 @@ public class NettyShuffleServiceFactory implements ShuffleServiceFactory<NettySh
config.networkBufferSize(),
config.isBlockingShuffleCompressionEnabled(),
config.getCompressionCodec(),
- config.getMaxBuffersPerChannel());
+ config.getMaxBuffersPerChannel(),
+ config.sortShuffleMinBuffers(),
+ config.sortShuffleMinParallelism());
SingleInputGateFactory singleInputGateFactory = new SingleInputGateFactory(
taskExecutorResourceId,
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/io/network/partition/ResultPartitionFactory.java b/flink-runtime/src/main/java/org/apache/flink/runtime/io/network/partition/ResultPartitionFactory.java
index c6a3a4e..c83eaff 100755
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/io/network/partition/ResultPartitionFactory.java
+++ b/flink-runtime/src/main/java/org/apache/flink/runtime/io/network/partition/ResultPartitionFactory.java
@@ -64,6 +64,10 @@ public class ResultPartitionFactory {
private final int maxBuffersPerChannel;
+ private final int sortShuffleMinBuffers;
+
+ private final int sortShuffleMinParallelism;
+
public ResultPartitionFactory(
ResultPartitionManager partitionManager,
FileChannelManager channelManager,
@@ -74,7 +78,9 @@ public class ResultPartitionFactory {
int networkBufferSize,
boolean blockingShuffleCompressionEnabled,
String compressionCodec,
- int maxBuffersPerChannel) {
+ int maxBuffersPerChannel,
+ int sortShuffleMinBuffers,
+ int sortShuffleMinParallelism) {
this.partitionManager = partitionManager;
this.channelManager = channelManager;
@@ -86,6 +92,8 @@ public class ResultPartitionFactory {
this.blockingShuffleCompressionEnabled = blockingShuffleCompressionEnabled;
this.compressionCodec = compressionCodec;
this.maxBuffersPerChannel = maxBuffersPerChannel;
+ this.sortShuffleMinBuffers = sortShuffleMinBuffers;
+ this.sortShuffleMinParallelism = sortShuffleMinParallelism;
}
public ResultPartition create(
@@ -146,25 +154,40 @@ public class ResultPartitionFactory {
partition = pipelinedPartition;
}
else if (type == ResultPartitionType.BLOCKING || type == ResultPartitionType.BLOCKING_PERSISTENT) {
- final BoundedBlockingResultPartition blockingPartition = new BoundedBlockingResultPartition(
- taskNameWithSubtaskAndId,
- partitionIndex,
- id,
- type,
- subpartitions,
- maxParallelism,
- partitionManager,
- bufferCompressor,
- bufferPoolFactory);
-
- initializeBoundedBlockingPartitions(
- subpartitions,
- blockingPartition,
- blockingSubpartitionType,
- networkBufferSize,
- channelManager);
-
- partition = blockingPartition;
+ if (numberOfSubpartitions >= sortShuffleMinParallelism) {
+ partition = new SortMergeResultPartition(
+ taskNameWithSubtaskAndId,
+ partitionIndex,
+ id,
+ type,
+ subpartitions.length,
+ maxParallelism,
+ networkBufferSize,
+ partitionManager,
+ channelManager.createChannel().getPath(),
+ bufferCompressor,
+ bufferPoolFactory);
+ } else {
+ final BoundedBlockingResultPartition blockingPartition = new BoundedBlockingResultPartition(
+ taskNameWithSubtaskAndId,
+ partitionIndex,
+ id,
+ type,
+ subpartitions,
+ maxParallelism,
+ partitionManager,
+ bufferCompressor,
+ bufferPoolFactory);
+
+ initializeBoundedBlockingPartitions(
+ subpartitions,
+ blockingPartition,
+ blockingSubpartitionType,
+ networkBufferSize,
+ channelManager);
+
+ partition = blockingPartition;
+ }
}
else {
throw new IllegalArgumentException("Unrecognized ResultPartitionType: " + type);
@@ -224,10 +247,13 @@ public class ResultPartitionFactory {
return () -> {
int maxNumberOfMemorySegments = type.isBounded() ?
numberOfSubpartitions * networkBuffersPerChannel + floatingNetworkBuffersPerGate : Integer.MAX_VALUE;
+ int numRequiredBuffers = !type.isPipelined() && numberOfSubpartitions >= sortShuffleMinParallelism ?
+ sortShuffleMinBuffers : numberOfSubpartitions + 1;
+
// If the partition type is back pressure-free, we register with the buffer pool for
// callbacks to release memory.
return bufferPoolFactory.createBufferPool(
- numberOfSubpartitions + 1,
+ numRequiredBuffers,
maxNumberOfMemorySegments,
numberOfSubpartitions,
maxBuffersPerChannel);
diff --git a/flink-runtime/src/main/java/org/apache/flink/runtime/taskmanager/NettyShuffleEnvironmentConfiguration.java b/flink-runtime/src/main/java/org/apache/flink/runtime/taskmanager/NettyShuffleEnvironmentConfiguration.java
index 09505dc..8f32660 100644
--- a/flink-runtime/src/main/java/org/apache/flink/runtime/taskmanager/NettyShuffleEnvironmentConfiguration.java
+++ b/flink-runtime/src/main/java/org/apache/flink/runtime/taskmanager/NettyShuffleEnvironmentConfiguration.java
@@ -58,6 +58,10 @@ public class NettyShuffleEnvironmentConfiguration {
/** Number of extra network buffers to use for each outgoing/incoming gate (result partition/input gate). */
private final int floatingNetworkBuffersPerGate;
+ private final int sortShuffleMinBuffers;
+
+ private final int sortShuffleMinParallelism;
+
private final Duration requestSegmentsTimeout;
private final boolean isNetworkDetailedMetrics;
@@ -88,7 +92,9 @@ public class NettyShuffleEnvironmentConfiguration {
BoundedBlockingSubpartitionType blockingSubpartitionType,
boolean blockingShuffleCompressionEnabled,
String compressionCodec,
- int maxBuffersPerChannel) {
+ int maxBuffersPerChannel,
+ int sortShuffleMinBuffers,
+ int sortShuffleMinParallelism) {
this.numNetworkBuffers = numNetworkBuffers;
this.networkBufferSize = networkBufferSize;
@@ -104,6 +110,8 @@ public class NettyShuffleEnvironmentConfiguration {
this.blockingShuffleCompressionEnabled = blockingShuffleCompressionEnabled;
this.compressionCodec = Preconditions.checkNotNull(compressionCodec);
this.maxBuffersPerChannel = maxBuffersPerChannel;
+ this.sortShuffleMinBuffers = sortShuffleMinBuffers;
+ this.sortShuffleMinParallelism = sortShuffleMinParallelism;
}
// ------------------------------------------------------------------------
@@ -132,6 +140,14 @@ public class NettyShuffleEnvironmentConfiguration {
return floatingNetworkBuffersPerGate;
}
+ public int sortShuffleMinBuffers() {
+ return sortShuffleMinBuffers;
+ }
+
+ public int sortShuffleMinParallelism() {
+ return sortShuffleMinParallelism;
+ }
+
public Duration getRequestSegmentsTimeout() {
return requestSegmentsTimeout;
}
@@ -201,6 +217,11 @@ public class NettyShuffleEnvironmentConfiguration {
int maxBuffersPerChannel = configuration.getInteger(NettyShuffleEnvironmentOptions.NETWORK_MAX_BUFFERS_PER_CHANNEL);
+ int sortShuffleMinBuffers = configuration.getInteger(
+ NettyShuffleEnvironmentOptions.NETWORK_SORT_SHUFFLE_MIN_BUFFERS);
+ int sortShuffleMinParallelism = configuration.getInteger(
+ NettyShuffleEnvironmentOptions.NETWORK_SORT_SHUFFLE_MIN_PARALLELISM);
+
boolean isNetworkDetailedMetrics = configuration.getBoolean(NettyShuffleEnvironmentOptions.NETWORK_DETAILED_METRICS);
String[] tempDirs = ConfigurationUtils.parseTempDirectories(configuration);
@@ -228,7 +249,9 @@ public class NettyShuffleEnvironmentConfiguration {
blockingSubpartitionType,
blockingShuffleCompressionEnabled,
compressionCodec,
- maxBuffersPerChannel);
+ maxBuffersPerChannel,
+ sortShuffleMinBuffers,
+ sortShuffleMinParallelism);
}
/**
@@ -350,6 +373,8 @@ public class NettyShuffleEnvironmentConfiguration {
result = 31 * result + (blockingShuffleCompressionEnabled ? 1 : 0);
result = 31 * result + Objects.hashCode(compressionCodec);
result = 31 * result + maxBuffersPerChannel;
+ result = 31 * result + sortShuffleMinBuffers;
+ result = 31 * result + sortShuffleMinParallelism;
return result;
}
@@ -370,6 +395,8 @@ public class NettyShuffleEnvironmentConfiguration {
this.partitionRequestMaxBackoff == that.partitionRequestMaxBackoff &&
this.networkBuffersPerChannel == that.networkBuffersPerChannel &&
this.floatingNetworkBuffersPerGate == that.floatingNetworkBuffersPerGate &&
+ this.sortShuffleMinBuffers == that.sortShuffleMinBuffers &&
+ this.sortShuffleMinParallelism == that.sortShuffleMinParallelism &&
this.requestSegmentsTimeout.equals(that.requestSegmentsTimeout) &&
(nettyConfig != null ? nettyConfig.equals(that.nettyConfig) : that.nettyConfig == null) &&
Arrays.equals(this.tempDirs, that.tempDirs) &&
@@ -394,6 +421,8 @@ public class NettyShuffleEnvironmentConfiguration {
", blockingShuffleCompressionEnabled=" + blockingShuffleCompressionEnabled +
", compressionCodec=" + compressionCodec +
", maxBuffersPerChannel=" + maxBuffersPerChannel +
+ ", sortShuffleMinBuffers=" + sortShuffleMinBuffers +
+ ", sortShuffleMinParallelism=" + sortShuffleMinParallelism +
'}';
}
}
diff --git a/flink-runtime/src/test/java/org/apache/flink/runtime/io/network/NettyShuffleEnvironmentBuilder.java b/flink-runtime/src/test/java/org/apache/flink/runtime/io/network/NettyShuffleEnvironmentBuilder.java
index 1d625fc..08d2481d 100644
--- a/flink-runtime/src/test/java/org/apache/flink/runtime/io/network/NettyShuffleEnvironmentBuilder.java
+++ b/flink-runtime/src/test/java/org/apache/flink/runtime/io/network/NettyShuffleEnvironmentBuilder.java
@@ -54,6 +54,10 @@ public class NettyShuffleEnvironmentBuilder {
private int floatingNetworkBuffersPerGate = 8;
+ private int sortShuffleMinBuffers = 100;
+
+ private int sortShuffleMinParallelism = Integer.MAX_VALUE;
+
private int maxBuffersPerChannel = Integer.MAX_VALUE;
private boolean blockingShuffleCompressionEnabled = false;
@@ -110,6 +114,16 @@ public class NettyShuffleEnvironmentBuilder {
return this;
}
+ public NettyShuffleEnvironmentBuilder setSortShuffleMinBuffers(int sortShuffleMinBuffers) {
+ this.sortShuffleMinBuffers = sortShuffleMinBuffers;
+ return this;
+ }
+
+ public NettyShuffleEnvironmentBuilder setSortShuffleMinParallelism(int sortShuffleMinParallelism) {
+ this.sortShuffleMinParallelism = sortShuffleMinParallelism;
+ return this;
+ }
+
public NettyShuffleEnvironmentBuilder setBlockingShuffleCompressionEnabled(boolean blockingShuffleCompressionEnabled) {
this.blockingShuffleCompressionEnabled = blockingShuffleCompressionEnabled;
return this;
@@ -156,7 +170,9 @@ public class NettyShuffleEnvironmentBuilder {
BoundedBlockingSubpartitionType.AUTO,
blockingShuffleCompressionEnabled,
compressionCodec,
- maxBuffersPerChannel),
+ maxBuffersPerChannel,
+ sortShuffleMinBuffers,
+ sortShuffleMinParallelism),
taskManagerLocation,
new TaskEventDispatcher(),
resultPartitionManager,
diff --git a/flink-runtime/src/test/java/org/apache/flink/runtime/io/network/partition/ResultPartitionBuilder.java b/flink-runtime/src/test/java/org/apache/flink/runtime/io/network/partition/ResultPartitionBuilder.java
index 826df0b..67e7adb 100644
--- a/flink-runtime/src/test/java/org/apache/flink/runtime/io/network/partition/ResultPartitionBuilder.java
+++ b/flink-runtime/src/test/java/org/apache/flink/runtime/io/network/partition/ResultPartitionBuilder.java
@@ -55,6 +55,10 @@ public class ResultPartitionBuilder {
private int floatingNetworkBuffersPerGate = 1;
+ private int sortShuffleMinBuffers = 100;
+
+ private int sortShuffleMinParallelism = Integer.MAX_VALUE;
+
private int maxBuffersPerChannel = Integer.MAX_VALUE;
private int networkBufferSize = 1;
@@ -105,7 +109,9 @@ public class ResultPartitionBuilder {
return setNetworkBuffersPerChannel(environment.getConfiguration().networkBuffersPerChannel())
.setFloatingNetworkBuffersPerGate(environment.getConfiguration().floatingNetworkBuffersPerGate())
.setNetworkBufferSize(environment.getConfiguration().networkBufferSize())
- .setNetworkBufferPool(environment.getNetworkBufferPool());
+ .setNetworkBufferPool(environment.getNetworkBufferPool())
+ .setSortShuffleMinBuffers(environment.getConfiguration().sortShuffleMinBuffers())
+ .setSortShuffleMinParallelism(environment.getConfiguration().sortShuffleMinParallelism());
}
public ResultPartitionBuilder setNetworkBufferPool(NetworkBufferPool networkBufferPool) {
@@ -139,6 +145,16 @@ public class ResultPartitionBuilder {
return this;
}
+ public ResultPartitionBuilder setSortShuffleMinBuffers(int sortShuffleMinBuffers) {
+ this.sortShuffleMinBuffers = sortShuffleMinBuffers;
+ return this;
+ }
+
+ public ResultPartitionBuilder setSortShuffleMinParallelism(int sortShuffleMinParallelism) {
+ this.sortShuffleMinParallelism = sortShuffleMinParallelism;
+ return this;
+ }
+
public ResultPartitionBuilder setCompressionCodec(String compressionCodec) {
this.compressionCodec = compressionCodec;
return this;
@@ -161,7 +177,9 @@ public class ResultPartitionBuilder {
networkBufferSize,
blockingShuffleCompressionEnabled,
compressionCodec,
- maxBuffersPerChannel);
+ maxBuffersPerChannel,
+ sortShuffleMinBuffers,
+ sortShuffleMinParallelism);
SupplierWithException<BufferPool, IOException> factory = bufferPoolFactory.orElseGet(() ->
resultPartitionFactory.createBufferPoolFactory(numberOfSubpartitions, partitionType));
diff --git a/flink-runtime/src/test/java/org/apache/flink/runtime/io/network/partition/ResultPartitionFactoryTest.java b/flink-runtime/src/test/java/org/apache/flink/runtime/io/network/partition/ResultPartitionFactoryTest.java
index 903878b..40297f6 100644
--- a/flink-runtime/src/test/java/org/apache/flink/runtime/io/network/partition/ResultPartitionFactoryTest.java
+++ b/flink-runtime/src/test/java/org/apache/flink/runtime/io/network/partition/ResultPartitionFactoryTest.java
@@ -72,7 +72,13 @@ public class ResultPartitionFactoryTest extends TestLogger {
}
@Test
- public void testConsumptionOnReleaseForPipelined() {
+ public void testSortMergePartitionCreated() {
+ ResultPartition resultPartition = createResultPartition(ResultPartitionType.BLOCKING, 1);
+ assertTrue(resultPartition instanceof SortMergeResultPartition);
+ }
+
+ @Test
+ public void testReleaseOnConsumptionForPipelinedPartition() {
final ResultPartition resultPartition = createResultPartition(ResultPartitionType.PIPELINED);
resultPartition.onConsumedSubpartition(0);
@@ -81,7 +87,7 @@ public class ResultPartitionFactoryTest extends TestLogger {
}
@Test
- public void testNoConsumptionOnReleaseForBlocking() {
+ public void testNoReleaseOnConsumptionForBoundedBlockingPartition() {
final ResultPartition resultPartition = createResultPartition(ResultPartitionType.BLOCKING);
resultPartition.onConsumedSubpartition(0);
@@ -89,7 +95,22 @@ public class ResultPartitionFactoryTest extends TestLogger {
assertFalse(resultPartition.isReleased());
}
+ @Test
+ public void testNoReleaseOnConsumptionForSortMergePartition() {
+ final ResultPartition resultPartition = createResultPartition(ResultPartitionType.BLOCKING, 1);
+
+ resultPartition.onConsumedSubpartition(0);
+
+ assertFalse(resultPartition.isReleased());
+ }
+
private static ResultPartition createResultPartition(ResultPartitionType partitionType) {
+ return createResultPartition(partitionType, Integer.MAX_VALUE);
+ }
+
+ private static ResultPartition createResultPartition(
+ ResultPartitionType partitionType,
+ int sortShuffleMinParallelism) {
final ResultPartitionManager manager = new ResultPartitionManager();
final ResultPartitionFactory factory = new ResultPartitionFactory(
@@ -102,7 +123,9 @@ public class ResultPartitionFactoryTest extends TestLogger {
SEGMENT_SIZE,
false,
"LZ4",
- Integer.MAX_VALUE);
+ Integer.MAX_VALUE,
+ 10,
+ sortShuffleMinParallelism);
final ResultPartitionDeploymentDescriptor descriptor = new ResultPartitionDeploymentDescriptor(
PartitionDescriptorBuilder
diff --git a/flink-tests/src/test/java/org/apache/flink/test/runtime/BlockingShuffleITCase.java b/flink-tests/src/test/java/org/apache/flink/test/runtime/BlockingShuffleITCase.java
new file mode 100644
index 0000000..74c3aef
--- /dev/null
+++ b/flink-tests/src/test/java/org/apache/flink/test/runtime/BlockingShuffleITCase.java
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.flink.test.runtime;
+
+import org.apache.flink.api.common.functions.MapFunction;
+import org.apache.flink.configuration.Configuration;
+import org.apache.flink.configuration.NettyShuffleEnvironmentOptions;
+import org.apache.flink.runtime.jobgraph.JobGraph;
+import org.apache.flink.runtime.jobgraph.ScheduleMode;
+import org.apache.flink.streaming.api.datastream.DataStream;
+import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
+import org.apache.flink.streaming.api.functions.sink.SinkFunction;
+import org.apache.flink.streaming.api.functions.source.ParallelSourceFunction;
+import org.apache.flink.streaming.api.graph.GlobalDataExchangeMode;
+import org.apache.flink.streaming.api.graph.StreamGraph;
+import org.apache.flink.streaming.api.graph.StreamingJobGraphGenerator;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests for blocking shuffle.
+ */
+public class BlockingShuffleITCase {
+
+ private static final String RECORD = "hello, world!";
+
+ private final int numTaskManagers = 2;
+
+ private final int numSlotsPerTaskManager = 4;
+
+ @Test
+ public void testBoundedBlockingShuffle() throws Exception {
+ JobGraph jobGraph = createJobGraph(1000000);
+ Configuration configuration = new Configuration();
+ JobGraphRunningUtil.execute(jobGraph, configuration, numTaskManagers, numSlotsPerTaskManager);
+ }
+
+ @Test
+ public void testBoundedBlockingShuffleWithoutData() throws Exception {
+ JobGraph jobGraph = createJobGraph(0);
+ Configuration configuration = new Configuration();
+ JobGraphRunningUtil.execute(jobGraph, configuration, numTaskManagers, numSlotsPerTaskManager);
+ }
+
+ @Test
+ public void testSortMergeBlockingShuffle() throws Exception {
+ Configuration configuration = new Configuration();
+ configuration.setInteger(NettyShuffleEnvironmentOptions.NETWORK_SORT_SHUFFLE_MIN_PARALLELISM, 1);
+
+ JobGraph jobGraph = createJobGraph(1000000);
+ JobGraphRunningUtil.execute(jobGraph, configuration, numTaskManagers, numSlotsPerTaskManager);
+ }
+
+ @Test
+ public void testSortMergeBlockingShuffleWithoutData() throws Exception {
+ Configuration configuration = new Configuration();
+ configuration.setInteger(NettyShuffleEnvironmentOptions.NETWORK_SORT_SHUFFLE_MIN_PARALLELISM, 1);
+
+ JobGraph jobGraph = createJobGraph(0);
+ JobGraphRunningUtil.execute(jobGraph, configuration, numTaskManagers, numSlotsPerTaskManager);
+ }
+
+ private JobGraph createJobGraph(int numRecordsToSend) {
+ StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
+ env.setParallelism(numTaskManagers * numSlotsPerTaskManager);
+ DataStream<String> source = env.addSource(new StringSource(numRecordsToSend));
+ source
+ .rebalance().map((MapFunction<String, String>) value -> value)
+ .broadcast().addSink(new VerifySink());
+
+ StreamGraph streamGraph = env.getStreamGraph();
+ streamGraph.setGlobalDataExchangeMode(GlobalDataExchangeMode.ALL_EDGES_BLOCKING);
+ streamGraph.setScheduleMode(ScheduleMode.LAZY_FROM_SOURCES);
+ return StreamingJobGraphGenerator.createJobGraph(streamGraph);
+ }
+
+ private static class StringSource implements ParallelSourceFunction<String> {
+ private volatile boolean isRunning = true;
+ private int numRecordsToSend;
+
+ StringSource(int numRecordsToSend) {
+ this.numRecordsToSend = numRecordsToSend;
+ }
+
+ @Override
+ public void run(SourceContext<String> ctx) throws Exception {
+ while (isRunning && numRecordsToSend-- > 0) {
+ ctx.collect(RECORD);
+ }
+ }
+
+ @Override
+ public void cancel() {
+ isRunning = false;
+ }
+ }
+
+ private static class VerifySink implements SinkFunction<String> {
+
+ @Override
+ public void invoke(String value) throws Exception {
+ assertEquals(RECORD, value);
+ }
+ }
+}
diff --git a/flink-tests/src/test/java/org/apache/flink/test/runtime/JobGraphRunningUtil.java b/flink-tests/src/test/java/org/apache/flink/test/runtime/JobGraphRunningUtil.java
new file mode 100644
index 0000000..f2c93a3
--- /dev/null
+++ b/flink-tests/src/test/java/org/apache/flink/test/runtime/JobGraphRunningUtil.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.flink.test.runtime;
+
+import org.apache.flink.api.common.JobID;
+import org.apache.flink.client.program.MiniClusterClient;
+import org.apache.flink.configuration.Configuration;
+import org.apache.flink.configuration.MemorySize;
+import org.apache.flink.configuration.TaskManagerOptions;
+import org.apache.flink.runtime.jobgraph.JobGraph;
+import org.apache.flink.runtime.jobmaster.JobResult;
+import org.apache.flink.runtime.minicluster.MiniCluster;
+import org.apache.flink.runtime.minicluster.MiniClusterConfiguration;
+
+/**
+ * Utils to run {@link JobGraph} on {@link MiniCluster}.
+ */
+public class JobGraphRunningUtil {
+
+ public static void execute(
+ JobGraph jobGraph,
+ Configuration configuration,
+ int numTaskManagers,
+ int numSlotsPerTaskManager) throws Exception {
+ configuration.set(TaskManagerOptions.TOTAL_FLINK_MEMORY, MemorySize.parse("1g"));
+
+ final MiniClusterConfiguration miniClusterConfiguration = new MiniClusterConfiguration.Builder()
+ .setConfiguration(configuration)
+ .setNumTaskManagers(numTaskManagers)
+ .setNumSlotsPerTaskManager(numSlotsPerTaskManager)
+ .build();
+
+ try (MiniCluster miniCluster = new MiniCluster(miniClusterConfiguration)) {
+ miniCluster.start();
+
+ MiniClusterClient miniClusterClient = new MiniClusterClient(configuration, miniCluster);
+ // wait for the submission to succeed
+ JobID jobID = miniClusterClient.submitJob(jobGraph).get();
+
+ JobResult jobResult = miniClusterClient.requestJobResult(jobID).get();
+ if (jobResult.getSerializedThrowable().isPresent()) {
+ throw new AssertionError(jobResult.getSerializedThrowable().get());
+ }
+ }
+ }
+}
diff --git a/flink-tests/src/test/java/org/apache/flink/test/runtime/ShuffleCompressionITCase.java b/flink-tests/src/test/java/org/apache/flink/test/runtime/ShuffleCompressionITCase.java
index 3e118a2..ee1db78 100644
--- a/flink-tests/src/test/java/org/apache/flink/test/runtime/ShuffleCompressionITCase.java
+++ b/flink-tests/src/test/java/org/apache/flink/test/runtime/ShuffleCompressionITCase.java
@@ -20,12 +20,8 @@ package org.apache.flink.test.runtime;
import org.apache.flink.api.common.ExecutionConfig;
import org.apache.flink.api.common.ExecutionMode;
-import org.apache.flink.api.common.JobID;
-import org.apache.flink.client.program.MiniClusterClient;
import org.apache.flink.configuration.Configuration;
-import org.apache.flink.configuration.MemorySize;
import org.apache.flink.configuration.NettyShuffleEnvironmentOptions;
-import org.apache.flink.configuration.TaskManagerOptions;
import org.apache.flink.runtime.execution.Environment;
import org.apache.flink.runtime.io.network.api.reader.MutableRecordReader;
import org.apache.flink.runtime.io.network.api.writer.RecordWriter;
@@ -38,9 +34,6 @@ import org.apache.flink.runtime.jobgraph.JobVertex;
import org.apache.flink.runtime.jobgraph.ScheduleMode;
import org.apache.flink.runtime.jobgraph.tasks.AbstractInvokable;
import org.apache.flink.runtime.jobmanager.scheduler.SlotSharingGroup;
-import org.apache.flink.runtime.jobmaster.JobResult;
-import org.apache.flink.runtime.minicluster.MiniCluster;
-import org.apache.flink.runtime.minicluster.MiniClusterConfiguration;
import org.apache.flink.runtime.util.EnvironmentInformation;
import org.apache.flink.streaming.runtime.partitioner.BroadcastPartitioner;
import org.apache.flink.types.LongValue;
@@ -86,32 +79,12 @@ public class ShuffleCompressionITCase {
@Test
public void testDataCompressionForBlockingShuffle() throws Exception {
- executeTest(createJobGraph(ScheduleMode.LAZY_FROM_SOURCES, ResultPartitionType.BLOCKING, ExecutionMode.BATCH));
- }
-
- private void executeTest(JobGraph jobGraph) throws Exception {
Configuration configuration = new Configuration();
- configuration.set(TaskManagerOptions.TOTAL_FLINK_MEMORY, MemorySize.parse("1g"));
configuration.setBoolean(NettyShuffleEnvironmentOptions.BLOCKING_SHUFFLE_COMPRESSION_ENABLED, true);
- final MiniClusterConfiguration miniClusterConfiguration = new MiniClusterConfiguration.Builder()
- .setConfiguration(configuration)
- .setNumTaskManagers(NUM_TASKMANAGERS)
- .setNumSlotsPerTaskManager(NUM_SLOTS)
- .build();
-
- try (MiniCluster miniCluster = new MiniCluster(miniClusterConfiguration)) {
- miniCluster.start();
-
- MiniClusterClient miniClusterClient = new MiniClusterClient(configuration, miniCluster);
- // wait for the submission to succeed
- JobID jobID = miniClusterClient.submitJob(jobGraph).get();
-
- JobResult jobResult = miniClusterClient.requestJobResult(jobID).get();
- if (jobResult.getSerializedThrowable().isPresent()) {
- throw new AssertionError(jobResult.getSerializedThrowable().get());
- }
- }
+ JobGraph jobGraph = createJobGraph(
+ ScheduleMode.LAZY_FROM_SOURCES, ResultPartitionType.BLOCKING, ExecutionMode.BATCH);
+ JobGraphRunningUtil.execute(jobGraph, configuration, NUM_TASKMANAGERS, NUM_SLOTS);
}
private static JobGraph createJobGraph(