This is an automated email from the ASF dual-hosted git repository.
zhouky pushed a commit to branch branch-0.2
in repository https://gitbox.apache.org/repos/asf/incubator-celeborn.git
The following commit(s) were added to refs/heads/branch-0.2 by this push:
new 730815e8a [CELEBORN-301] Refactor PartitionLocationInfo to use
ConcurrentHashMap (#1236)
730815e8a is described below
commit 730815e8a33c385e11358ff2d60ec9c37f5756f1
Author: Keyong Zhou <[email protected]>
AuthorDate: Sun Feb 26 00:08:20 2023 +0800
[CELEBORN-301] Refactor PartitionLocationInfo to use ConcurrentHashMap
(#1236)
---
.../spark/shuffle/celeborn/SortBasedPusher.java | 3 +-
.../common/meta/PartitionLocationInfo.scala | 228 ++++++++-------------
.../celeborn/service/deploy/worker/Worker.scala | 1 +
3 files changed, 83 insertions(+), 149 deletions(-)
diff --git
a/client-spark/common/src/main/java/org/apache/spark/shuffle/celeborn/SortBasedPusher.java
b/client-spark/common/src/main/java/org/apache/spark/shuffle/celeborn/SortBasedPusher.java
index 82dd6c9ab..a23ac2646 100644
---
a/client-spark/common/src/main/java/org/apache/spark/shuffle/celeborn/SortBasedPusher.java
+++
b/client-spark/common/src/main/java/org/apache/spark/shuffle/celeborn/SortBasedPusher.java
@@ -52,6 +52,7 @@ public class SortBasedPusher extends MemoryConsumer {
private final int pushBufferMaxSize;
private final long pushSortMemoryThreshold;
final int uaoSize = UnsafeAlignedOffset.getUaoSize();
+ static final long size8k = Utils.byteStringAsBytes("8k");
String appId;
int shuffleId;
@@ -182,7 +183,7 @@ public class SortBasedPusher extends MemoryConsumer {
throws IOException {
if (getUsed() > pushSortMemoryThreshold
- && pageCursor + Utils.byteStringAsBytes("8k")
+ && pageCursor + size8k
> currentPage.getBaseOffset() + currentPage.size()) {
logger.info(
"Memory Used across threshold, trigger push. Memory: "
diff --git
a/common/src/main/scala/org/apache/celeborn/common/meta/PartitionLocationInfo.scala
b/common/src/main/scala/org/apache/celeborn/common/meta/PartitionLocationInfo.scala
index 4f29c63a7..277b86add 100644
---
a/common/src/main/scala/org/apache/celeborn/common/meta/PartitionLocationInfo.scala
+++
b/common/src/main/scala/org/apache/celeborn/common/meta/PartitionLocationInfo.scala
@@ -18,6 +18,7 @@
package org.apache.celeborn.common.meta
import java.util
+import java.util.concurrent.ConcurrentHashMap
import java.util.function.BiFunction
import scala.collection.JavaConverters._
@@ -27,33 +28,34 @@ import org.apache.celeborn.common.protocol.PartitionLocation
class PartitionLocationInfo extends Logging {
- // key: ShuffleKey, values: (partitionId -> partition locations)
- type PartitionInfo = util.HashMap[String, util.Map[Int,
util.List[PartitionLocation]]]
+ // key: ShuffleKey, values: (encodeUniqueId -> partition location)
+ type PartitionInfo = ConcurrentHashMap[String, ConcurrentHashMap[Long,
PartitionLocation]]
private val masterPartitionLocations = new PartitionInfo
private val slavePartitionLocations = new PartitionInfo
+ def encode(partitionId: Int, epoch: Int): Long = {
+ partitionId.toLong << 32 | epoch
+ }
+
+ def encodeUniqueId(uniqueId: String): Long = {
+ val tokens = uniqueId.split("-", 2)
+ val partitionId = tokens(0).toInt
+ val epoch = tokens(1).toInt
+ encode(partitionId, epoch)
+ }
+
def shuffleKeySet: util.HashSet[String] = {
val shuffleKeySet = new util.HashSet[String]()
- this.synchronized {
- shuffleKeySet.addAll(masterPartitionLocations.keySet())
- shuffleKeySet.addAll(slavePartitionLocations.keySet())
- }
+ shuffleKeySet.addAll(masterPartitionLocations.keySet())
+ shuffleKeySet.addAll(slavePartitionLocations.keySet())
shuffleKeySet
}
- def containsShuffle(shuffleKey: String): Boolean = this.synchronized {
+ def containsShuffle(shuffleKey: String): Boolean = {
masterPartitionLocations.containsKey(shuffleKey) ||
slavePartitionLocations.containsKey(shuffleKey)
}
- def addMasterPartition(shuffleKey: String, location: PartitionLocation): Int
= {
- addPartition(shuffleKey, location, masterPartitionLocations)
- }
-
- def addSlavePartition(shuffleKey: String, location: PartitionLocation): Int
= {
- addPartition(shuffleKey, location, slavePartitionLocations)
- }
-
def addMasterPartitions(
shuffleKey: String,
locations: util.List[PartitionLocation]): Unit = {
@@ -74,27 +76,20 @@ class PartitionLocationInfo extends Logging {
getLocation(shuffleKey, uniqueId, PartitionLocation.Mode.SLAVE)
}
- def getAllMasterLocations(shuffleKey: String): util.List[PartitionLocation]
= this.synchronized {
- if (masterPartitionLocations.containsKey(shuffleKey)) {
- masterPartitionLocations.get(shuffleKey)
- .values()
- .asScala
- .flatMap(_.asScala)
- .toList
- .asJava
- } else {
- new util.ArrayList[PartitionLocation]()
- }
+ def getAllMasterLocations(shuffleKey: String): util.List[PartitionLocation]
= {
+ getAllLocations(shuffleKey, masterPartitionLocations)
}
- def getAllSlaveLocations(shuffleKey: String): util.List[PartitionLocation] =
this.synchronized {
- if (slavePartitionLocations.containsKey(shuffleKey)) {
- slavePartitionLocations.get(shuffleKey)
- .values()
- .asScala
- .flatMap(_.asScala)
- .toList
- .asJava
+ def getAllSlaveLocations(shuffleKey: String): util.List[PartitionLocation] =
{
+ getAllLocations(shuffleKey, slavePartitionLocations)
+ }
+
+ def getAllLocations(
+ shuffleKey: String,
+ partitionInfo: PartitionInfo): util.List[PartitionLocation] = {
+ val partitionMap = partitionInfo.get(shuffleKey)
+ if (partitionMap != null) {
+ new util.ArrayList(partitionMap.values())
} else {
new util.ArrayList[PartitionLocation]()
}
@@ -122,81 +117,47 @@ class PartitionLocationInfo extends Logging {
removePartitions(shuffleKey, uniqueIds, slavePartitionLocations)
}
- def getAllMasterLocationsWithMinEpoch(shuffleKey: String):
util.List[PartitionLocation] =
- this.synchronized {
- getAllMasterLocationsWithExtremeEpoch(shuffleKey, (a, b) => a < b)
- }
-
- def getAllMasterLocationsWithExtremeEpoch(
- shuffleKey: String,
- order: (Int, Int) => Boolean): util.List[PartitionLocation] =
this.synchronized {
- if (masterPartitionLocations.containsKey(shuffleKey)) {
- masterPartitionLocations.get(shuffleKey)
- .values()
- .asScala
- .map { list =>
- var loc = list.get(0)
- 1 until list.size() foreach (ind => {
- if (order(list.get(ind).getEpoch, loc.getEpoch)) {
- loc = list.get(ind)
- }
- })
- loc
- }.toList.asJava
- } else {
- new util.ArrayList[PartitionLocation]()
- }
+ def removeShuffle(shuffleKey: String): Unit = {
+ masterPartitionLocations.remove(shuffleKey)
+ slavePartitionLocations.remove(shuffleKey)
}
- def getLocationWithMaxEpoch(
- shuffleKey: String,
- partitionId: Int): Option[PartitionLocation] = this.synchronized {
- if (!masterPartitionLocations.containsKey(shuffleKey) ||
- !masterPartitionLocations.get(shuffleKey).containsKey(partitionId)) {
- return None
- }
- val locations = masterPartitionLocations.get(shuffleKey).get(partitionId)
- if (locations == null || locations.size() == 0) {
- return None
- }
- var currentEpoch = -1
- var currentPartition: PartitionLocation = null
- locations.asScala.foreach(loc => {
- if (loc.getEpoch > currentEpoch) {
- currentEpoch = loc.getEpoch
- currentPartition = loc
- }
- })
- Some(currentPartition)
+ def getAllMasterLocationsWithMinEpoch(shuffleKey: String):
util.List[PartitionLocation] = {
+ getAllMasterLocationsWithExtremeEpoch(shuffleKey, (a, b) => a < b)
}
- private def addPartition(
+ // TODO: UT
+ def getAllMasterLocationsWithExtremeEpoch(
shuffleKey: String,
- location: PartitionLocation,
- partitionInfo: PartitionInfo): Int = this.synchronized {
- if (location != null) {
- partitionInfo.putIfAbsent(shuffleKey, new util.HashMap[Int,
util.List[PartitionLocation]]())
- val reduceLocMap = partitionInfo.get(shuffleKey)
- reduceLocMap.putIfAbsent(location.getId, new
util.ArrayList[PartitionLocation]())
- val locations = reduceLocMap.get(location.getId)
- locations.add(location)
- 1
+ order: (Int, Int) => Boolean): util.List[PartitionLocation] = {
+ val partitionMap = masterPartitionLocations.get(shuffleKey)
+ if (partitionMap != null) {
+ val resMap = new util.HashMap[Int, PartitionLocation]()
+ partitionMap.values().asScala.foreach(loc => {
+ val old = resMap.get(loc.getId)
+ if (old == null) {
+ resMap.put(loc.getId, loc)
+ } else {
+ if (order(loc.getEpoch, old.getEpoch)) {
+ resMap.put(loc.getId, loc)
+ }
+ }
+ })
+ new util.ArrayList(resMap.values())
} else {
- 0
+ new util.ArrayList[PartitionLocation]()
}
}
private def addPartitions(
shuffleKey: String,
locations: util.List[PartitionLocation],
- partitionInfo: PartitionInfo): Unit = this.synchronized {
+ partitionInfo: PartitionInfo): Unit = {
if (locations != null && locations.size() > 0) {
- partitionInfo.putIfAbsent(shuffleKey, new util.HashMap[Int,
util.List[PartitionLocation]]())
- val reduceLocMap = partitionInfo.get(shuffleKey)
+ partitionInfo.putIfAbsent(shuffleKey, new ConcurrentHashMap[Long,
PartitionLocation]())
+ val partitionMap = partitionInfo.get(shuffleKey)
locations.asScala.foreach { loc =>
- reduceLocMap.putIfAbsent(loc.getId, new
util.ArrayList[PartitionLocation]())
- val locations = reduceLocMap.get(loc.getId)
- locations.add(loc)
+ partitionMap.put(encode(loc.getId, loc.getEpoch), loc)
}
}
}
@@ -210,40 +171,27 @@ class PartitionLocationInfo extends Logging {
private def removePartitions(
shuffleKey: String,
uniqueIds: util.Collection[String],
- partitionInfo: PartitionInfo): (util.Map[String, Integer], Integer) =
this.synchronized {
- if (!partitionInfo.containsKey(shuffleKey)) {
+ partitionInfo: PartitionInfo): (util.Map[String, Integer], Integer) = {
+ val partitionMap = partitionInfo.get(shuffleKey)
+ if (partitionMap == null) {
return (Map.empty[String, Integer].asJava, 0)
}
val locMap = new util.HashMap[String, Integer]()
var numSlotsReleased: Int = 0
- val reduceLocMap = partitionInfo.get(shuffleKey)
uniqueIds.asScala.foreach { id =>
- val tokens = id.split("-", 2)
- val partitionId = tokens(0).toInt
- val epoch = tokens(1).toInt
- val locations = reduceLocMap.get(partitionId)
- if (locations != null) {
- val targetLocation = locations.asScala.find(_.getEpoch == epoch).orNull
- if (targetLocation != null) {
- locations.remove(targetLocation)
- numSlotsReleased += 1
- locMap.compute(
- targetLocation.getStorageInfo.getMountPoint,
- new BiFunction[String, Integer, Integer] {
- override def apply(t: String, u: Integer): Integer = {
- if (u == null) 1 else u + 1
- }
- })
- }
- }
- if (locations == null || locations.size() == 0) {
- reduceLocMap.remove(partitionId)
+ val loc = partitionMap.remove(encodeUniqueId(id))
+ if (loc != null) {
+ numSlotsReleased += 1
+ locMap.compute(
+ loc.getStorageInfo.getMountPoint,
+ new BiFunction[String, Integer, Integer] {
+ override def apply(t: String, u: Integer): Integer = {
+ if (u == null) 1 else u + 1
+ }
+ })
}
}
- if (reduceLocMap.size() == 0) {
- partitionInfo.remove(shuffleKey)
- }
// some locations might have no disk hint
(locMap, numSlotsReleased)
}
@@ -252,9 +200,6 @@ class PartitionLocationInfo extends Logging {
shuffleKey: String,
uniqueId: String,
mode: PartitionLocation.Mode): PartitionLocation = {
- val tokens = uniqueId.split("-", 2)
- val partitionId = tokens(0).toInt
- val epoch = tokens(1).toInt
val partitionInfo =
if (mode == PartitionLocation.Mode.MASTER) {
masterPartitionLocations
@@ -262,32 +207,19 @@ class PartitionLocationInfo extends Logging {
slavePartitionLocations
}
- this.synchronized {
- if (!partitionInfo.containsKey(shuffleKey)
- || !partitionInfo.get(shuffleKey).containsKey(partitionId)) {
- return null
- }
- partitionInfo.get(shuffleKey)
- .get(partitionId)
- .asScala
- .find(loc => loc.getEpoch == epoch)
- .orNull
- }
+ val partitionMap = partitionInfo.get(shuffleKey)
+ if (partitionMap != null) {
+ partitionMap.get(encodeUniqueId(uniqueId))
+ } else null
}
private def getAllIds(
shuffleKey: String,
- partitionInfo: PartitionInfo): util.List[String] = this.synchronized {
- if (!partitionInfo.containsKey(shuffleKey)) {
- return null
- }
- partitionInfo.get(shuffleKey)
- .values()
- .asScala
- .flatMap(_.asScala)
- .map(_.getUniqueId)
- .toList
- .asJava
+ partitionInfo: PartitionInfo): util.List[String] = {
+ val partitionMap = partitionInfo.get(shuffleKey)
+ if (partitionMap != null) {
+ partitionMap.values().asScala.map(_.getUniqueId).toList.asJava
+ } else null
}
private def getAllMasterIds(shuffleKey: String): util.List[String] = {
@@ -298,11 +230,11 @@ class PartitionLocationInfo extends Logging {
getAllIds(shuffleKey, slavePartitionLocations)
}
- def isEmpty: Boolean = this.synchronized {
+ def isEmpty: Boolean = {
masterPartitionLocations.isEmpty && slavePartitionLocations.isEmpty
}
- override def toString: String = this.synchronized {
+ override def toString: String = {
s"""
| Partition Location Info:
| master: ${masterPartitionLocations.asScala}
diff --git
a/worker/src/main/scala/org/apache/celeborn/service/deploy/worker/Worker.scala
b/worker/src/main/scala/org/apache/celeborn/service/deploy/worker/Worker.scala
index aed555878..920947d63 100644
---
a/worker/src/main/scala/org/apache/celeborn/service/deploy/worker/Worker.scala
+++
b/worker/src/main/scala/org/apache/celeborn/service/deploy/worker/Worker.scala
@@ -413,6 +413,7 @@ private[celeborn] class Worker(
expiredShuffleKeys.asScala.foreach { shuffleKey =>
partitionLocationInfo.removeMasterPartitions(shuffleKey)
partitionLocationInfo.removeSlavePartitions(shuffleKey)
+ partitionLocationInfo.removeShuffle(shuffleKey)
shufflePartitionType.remove(shuffleKey)
shuffleMapperAttempts.remove(shuffleKey)
shuffleCommitInfos.remove(shuffleKey)