You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@celeborn.apache.org by "onebox-li (via GitHub)" <gi...@apache.org> on 2023/11/09 08:26:25 UTC
[PR] [CELEBORN-1121] Improve WorkerInfo#hashCode method [incubator-celeborn]
onebox-li opened a new pull request, #2086:
URL: https://github.com/apache/incubator-celeborn/pull/2086
### What changes were proposed in this pull request?
Change WorkerInfo#hashCode() from map+foldLeft to while and cache.
Test the each way to calculate, code and result show as below:
```
val state = Seq(host, rpcPort, pushPort, fetchPort, replicatePort)
// origin
val originHash = state.map(_.hashCode()).foldLeft(0)((a, b) => 31 * a + b)
// for
var forHash = 0
for (i <- state) {
forHash = 31 * forHash + i.hashCode()
}
// while
var whileHash = 0
var i = 0
while (i < state.size) {
whileHash = 31 * whileHash + state(i).hashCode()
i = i + 1
}
```
Result:
```
java version "1.8.0_261"
origin hash result = -831724440, costs 1103914 ns
for hash result = -831724440, costs 444588 ns (2.5x)
while hash result = -831724440, costs 46510 ns (23x)
```
### Why are the changes needed?
The current WorkerInfo's hashCode() is a little time-consuming. Since it is widely used in lots of hash maps, it needs to be improved.
### Does this PR introduce _any_ user-facing change?
No.
### How was this patch tested?
Added UT.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@celeborn.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [CELEBORN-1121] Improve WorkerInfo#hashCode method [incubator-celeborn]
Posted by "cfmcgrady (via GitHub)" <gi...@apache.org>.
cfmcgrady commented on PR #2086:
URL: https://github.com/apache/incubator-celeborn/pull/2086#issuecomment-1805342745
> I found Objects.hash is even several times faster
this is because `Seq` is an implementation of `List`
```scala
// while
startTime = System.nanoTime()
var whileHash = 1
var i = 0
while (i < 5) {
whileHash = 31 * whileHash + state(i).hashCode()
i = i + 1
}
var endTime = System.nanoTime()
println(endTime - startTime)
// while 2
startTime = System.nanoTime()
whileHash = 1
i = 0
while (i < state.length) {
whileHash = 31 * whileHash + state(i).hashCode()
i = i + 1
}
endTime = System.nanoTime()
println(endTime - startTime)
startTime = System.nanoTime()
val objectHash = java.util.Objects.hash(host, rpcPort, pushPort, fetchPort, replicatePort)
endTime = System.nanoTime()
println(endTime - startTime)
```
3924 vs 1821 vs 29459
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@celeborn.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [CELEBORN-1121] Improve WorkerInfo#hashCode method [incubator-celeborn]
Posted by "mridulm (via GitHub)" <gi...@apache.org>.
mridulm commented on code in PR #2086:
URL: https://github.com/apache/incubator-celeborn/pull/2086#discussion_r1392987698
##########
common/src/main/scala/org/apache/celeborn/common/meta/WorkerInfo.scala:
##########
@@ -232,8 +235,21 @@ class WorkerInfo(
}
override def hashCode(): Int = {
- val state = Seq(host, rpcPort, pushPort, fetchPort, replicatePort)
- state.map(_.hashCode()).foldLeft(0)((a, b) => 31 * a + b)
+ var h = hash
+ if (h == 0 || isZeroHash) {
+ val state = Array(host, rpcPort, pushPort, fetchPort, replicatePort)
+ var i = 0
+ while (i < state.length) {
+ h = 31 * h + state(i).hashCode()
+ i = i + 1
+ }
+ if (h == 0) {
+ isZeroHash = true
+ } else {
+ hash = h
+ }
+ }
+ h
Review Comment:
Couple of points:
* For microbenchmarks, please use JMH - not sure if you did.
* Any implementation which does memoization will typically be faster - since it is if condition + field lookup when result has been memoized - the additional complexity of adding that should be worth it: in this case, how many misses, additional synchronization to ensure visibility of update in a MT safe manner, etc.
From a pure perf pov, you can ofcourse avoid the synchronization overhead by simply pushing the computation to the constructor - then `hashCode` will be simply be returning the computed hash - that will be the fastest :-)
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@celeborn.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [CELEBORN-1121] Improve WorkerInfo#hashCode method [incubator-celeborn]
Posted by "onebox-li (via GitHub)" <gi...@apache.org>.
onebox-li commented on PR #2086:
URL: https://github.com/apache/incubator-celeborn/pull/2086#issuecomment-1805390352
> btw, we have a benchmark framework introduced in #1657
Get it.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@celeborn.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [CELEBORN-1121] Improve WorkerInfo#hashCode method [incubator-celeborn]
Posted by "AngersZhuuuu (via GitHub)" <gi...@apache.org>.
AngersZhuuuu commented on code in PR #2086:
URL: https://github.com/apache/incubator-celeborn/pull/2086#discussion_r1395465230
##########
common/src/main/scala/org/apache/celeborn/common/meta/WorkerInfo.scala:
##########
@@ -232,8 +232,12 @@ class WorkerInfo(
}
override def hashCode(): Int = {
- val state = Seq(host, rpcPort, pushPort, fetchPort, replicatePort)
- state.map(_.hashCode()).foldLeft(0)((a, b) => 31 * a + b)
+ var result = host.hashCode()
+ result = 31 * result + rpcPort.hashCode()
+ result = 31 * result + pushPort.hashCode()
+ result = 31 * result + fetchPort.hashCode()
+ result = 31 * result + replicatePort.hashCode()
+ result
Review Comment:
Can we cache the hashCode value? seems this method called many times
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@celeborn.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [CELEBORN-1121] Improve WorkerInfo#hashCode method [incubator-celeborn]
Posted by "codecov[bot] (via GitHub)" <gi...@apache.org>.
codecov[bot] commented on PR #2086:
URL: https://github.com/apache/incubator-celeborn/pull/2086#issuecomment-1803377784
## [Codecov](https://app.codecov.io/gh/apache/incubator-celeborn/pull/2086?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) Report
> :exclamation: No coverage uploaded for pull request base (`main@02cea04`). [Click here to learn what that means](https://docs.codecov.io/docs/error-reference?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#section-missing-base-commit).
> The diff coverage is `100.00%`.
```diff
@@ Coverage Diff @@
## main #2086 +/- ##
=======================================
Coverage ? 46.80%
=======================================
Files ? 166
Lines ? 10703
Branches ? 979
=======================================
Hits ? 5009
Misses ? 5373
Partials ? 321
```
| [Files](https://app.codecov.io/gh/apache/incubator-celeborn/pull/2086?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) | Coverage Δ | |
|---|---|---|
| [...a/org/apache/celeborn/common/meta/WorkerInfo.scala](https://app.codecov.io/gh/apache/incubator-celeborn/pull/2086?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#diff-Y29tbW9uL3NyYy9tYWluL3NjYWxhL29yZy9hcGFjaGUvY2VsZWJvcm4vY29tbW9uL21ldGEvV29ya2VySW5mby5zY2FsYQ==) | `48.86% <100.00%> (ø)` | |
:mega: Codecov offers a browser extension for seamless coverage viewing on GitHub. Try it in [Chrome](https://chrome.google.com/webstore/detail/codecov/gedikamndpbemklijjkncpnolildpbgo) or [Firefox](https://addons.mozilla.org/en-US/firefox/addon/codecov/) today!
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@celeborn.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [CELEBORN-1121] Improve WorkerInfo#hashCode method [incubator-celeborn]
Posted by "onebox-li (via GitHub)" <gi...@apache.org>.
onebox-li commented on PR #2086:
URL: https://github.com/apache/incubator-celeborn/pull/2086#issuecomment-1815662280
Thanks for all your help!
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@celeborn.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [CELEBORN-1121] Improve WorkerInfo#hashCode method [incubator-celeborn]
Posted by "onebox-li (via GitHub)" <gi...@apache.org>.
onebox-li commented on PR #2086:
URL: https://github.com/apache/incubator-celeborn/pull/2086#issuecomment-1805367190
Thanks for @waitinfuture @cfmcgrady suggestions. I will optimize the code and test again.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@celeborn.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [CELEBORN-1121] Improve WorkerInfo#hashCode method [incubator-celeborn]
Posted by "cfmcgrady (via GitHub)" <gi...@apache.org>.
cfmcgrady commented on PR #2086:
URL: https://github.com/apache/incubator-celeborn/pull/2086#issuecomment-1804944666
Per https://github.com/databricks/scala-style-guide#traversal-and-zipwithindex, we need to use `while` loop for performance-sensitive code
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@celeborn.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [CELEBORN-1121] Improve WorkerInfo#hashCode method [incubator-celeborn]
Posted by "onebox-li (via GitHub)" <gi...@apache.org>.
onebox-li commented on code in PR #2086:
URL: https://github.com/apache/incubator-celeborn/pull/2086#discussion_r1388798668
##########
common/src/test/scala/org/apache/celeborn/common/meta/WorkerInfoSuite.scala:
##########
@@ -303,4 +303,34 @@ class WorkerInfoSuite extends CelebornFunSuite {
}
}
}
+
+ test("Test WorkerInfo hashcode") {
+ val host = "127.0.0.1"
+ val rpcPort = 9082
+ val pushPort = 9092
+ val fetchPort = 9093
+ val replicatePort = 9094
+ val workerInfo = new WorkerInfo(host, rpcPort, pushPort, fetchPort, replicatePort)
+
+ // origin hashCode()
+ var now = System.nanoTime()
+ val state = Seq(host, rpcPort, pushPort, fetchPort, replicatePort)
+ val originHash = state.map(_.hashCode()).foldLeft(0)((a, b) => 31 * a + b)
+ var after = System.nanoTime()
+ println("WorkerInfo origin hash result = " + originHash + ", costs " + (after - now))
Review Comment:
Thanks. I find no need to print logs. Remove done.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@celeborn.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [CELEBORN-1121] Improve WorkerInfo#hashCode method [incubator-celeborn]
Posted by "mridulm (via GitHub)" <gi...@apache.org>.
mridulm commented on code in PR #2086:
URL: https://github.com/apache/incubator-celeborn/pull/2086#discussion_r1391962579
##########
common/src/main/scala/org/apache/celeborn/common/meta/WorkerInfo.scala:
##########
@@ -232,8 +235,21 @@ class WorkerInfo(
}
override def hashCode(): Int = {
- val state = Seq(host, rpcPort, pushPort, fetchPort, replicatePort)
- state.map(_.hashCode()).foldLeft(0)((a, b) => 31 * a + b)
+ var h = hash
+ if (h == 0 || isZeroHash) {
+ val state = Array(host, rpcPort, pushPort, fetchPort, replicatePort)
+ var i = 0
+ while (i < state.length) {
+ h = 31 * h + state(i).hashCode()
+ i = i + 1
+ }
+ if (h == 0) {
+ isZeroHash = true
+ } else {
+ hash = h
+ }
+ }
+ h
Review Comment:
Instead, why not simply unroll the loop ?
```
override def hashCode: Int = {
var result = if (host != null) host.hashCode else 0
result = 31 * result + rpcPort
result = 31 * result + pushPort
result = 31 * result + fetchPort
result = 31 * result + replicatePort
result
}
```
Since java already caches the hashCode for String, that should be fine.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@celeborn.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [CELEBORN-1121] Improve WorkerInfo#hashCode method [incubator-celeborn]
Posted by "onebox-li (via GitHub)" <gi...@apache.org>.
onebox-li commented on code in PR #2086:
URL: https://github.com/apache/incubator-celeborn/pull/2086#discussion_r1388798245
##########
common/src/main/scala/org/apache/celeborn/common/meta/WorkerInfo.scala:
##########
@@ -47,6 +47,8 @@ class WorkerInfo(
JavaUtils.newConcurrentHashMap[UserIdentifier, ResourceConsumption](_userResourceConsumption)
else null
var endpoint: RpcEndpointRef = null
+ // Cache the hash code for WorkerInfo
+ var hash = 0
Review Comment:
Done
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@celeborn.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [CELEBORN-1121] Improve WorkerInfo#hashCode method [incubator-celeborn]
Posted by "onebox-li (via GitHub)" <gi...@apache.org>.
onebox-li closed pull request #2086: [CELEBORN-1121] Improve WorkerInfo#hashCode method
URL: https://github.com/apache/incubator-celeborn/pull/2086
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@celeborn.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [CELEBORN-1121] Improve WorkerInfo#hashCode method [incubator-celeborn]
Posted by "cfmcgrady (via GitHub)" <gi...@apache.org>.
cfmcgrady commented on PR #2086:
URL: https://github.com/apache/incubator-celeborn/pull/2086#issuecomment-1808235436
> These calculations are sensitive to performance(within milliseconds) and it may be biased when using current benchmark framework.
This is not as expected, can you elaborate more? or show your benchmark code?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@celeborn.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [CELEBORN-1121] Improve WorkerInfo#hashCode method [incubator-celeborn]
Posted by "onebox-li (via GitHub)" <gi...@apache.org>.
onebox-li commented on code in PR #2086:
URL: https://github.com/apache/incubator-celeborn/pull/2086#discussion_r1392079035
##########
common/src/main/scala/org/apache/celeborn/common/meta/WorkerInfo.scala:
##########
@@ -232,8 +235,21 @@ class WorkerInfo(
}
override def hashCode(): Int = {
- val state = Seq(host, rpcPort, pushPort, fetchPort, replicatePort)
- state.map(_.hashCode()).foldLeft(0)((a, b) => 31 * a + b)
+ var h = hash
+ if (h == 0 || isZeroHash) {
+ val state = Array(host, rpcPort, pushPort, fetchPort, replicatePort)
+ var i = 0
+ while (i < state.length) {
+ h = 31 * h + state(i).hashCode()
+ i = i + 1
+ }
+ if (h == 0) {
+ isZeroHash = true
+ } else {
+ hash = h
+ }
+ }
+ h
Review Comment:
Thanks @mridulm. I actually thought about that before and have a test shown as below.
```
val host = generateRandomIPv4Address
val rpcPort: Integer = Random.nextInt(65535)
val pushPort: Integer = Random.nextInt(65535)
val fetchPort: Integer = Random.nextInt(65535)
val replicatePort: Integer = Random.nextInt(65535)
val infoSeq = Seq(host, rpcPort, pushPort, fetchPort, replicatePort)
val infoArray = Array(host, rpcPort, pushPort, fetchPort, replicatePort)
// origin
var startTime = System.nanoTime()
infoSeq.map(_.hashCode()).foldLeft(0)((a, b) => 31 * a + b)
var endTime = System.nanoTime()
val originTime = endTime - startTime
println("origin costs %d ns, %.2fx".format(originTime, originTime.toDouble / originTime))
System.gc()
// for seq
startTime = System.nanoTime()
var forHash1 = 0
for (element <- infoSeq) {
forHash1 = 31 * forHash1 + element.hashCode()
}
endTime = System.nanoTime()
val forSeqTime = endTime - startTime
println("for seq costs %d ns, %.2fx".format(forSeqTime, originTime.toDouble / forSeqTime))
System.gc()
// for array
startTime = System.nanoTime()
var forHash2 = 0
for (element <- infoArray) {
forHash2 = 31 * forHash2 + element.hashCode()
}
endTime = System.nanoTime()
val forArrayTime = endTime - startTime
println("for array costs %d ns, %.2fx".format(forArrayTime, originTime.toDouble / forArrayTime))
System.gc()
// while Seq
startTime = System.nanoTime()
var whileHash1 = 0
var i = 0
while (i < infoSeq.size) {
whileHash1 = 31 * whileHash1 + infoSeq(i).hashCode()
i = i + 1
}
endTime = System.nanoTime()
val whileSeqTime = endTime - startTime
println("while seq costs %d ns, %.2fx".format(whileSeqTime, originTime.toDouble / whileSeqTime))
System.gc()
// while array
startTime = System.nanoTime()
var whileHash2 = 0
i = 0
while (i < infoArray.length) {
whileHash2 = 31 * whileHash2 + infoArray(i).hashCode()
i = i + 1
}
endTime = System.nanoTime()
val whileArrayTime = endTime - startTime
println("while array costs %d ns, %.2fx".format(whileArrayTime, originTime.toDouble / whileArrayTime))
System.gc()
// objects hash
startTime = System.nanoTime()
Objects.hash(host, rpcPort, pushPort, fetchPort, replicatePort)
endTime = System.nanoTime()
val objectHashTime = endTime - startTime
println("object hash costs %d ns, %.2fx".format(objectHashTime, originTime.toDouble / objectHashTime))
System.gc()
// direct hash
startTime = System.nanoTime()
var result = host.hashCode()
result = 31 * result + rpcPort.hashCode()
result = 31 * result + pushPort.hashCode()
result = 31 * result + fetchPort.hashCode()
result = 31 * result + replicatePort.hashCode()
endTime = System.nanoTime()
val directHashTime = endTime - startTime
println("directly hash costs %d ns, %.2fx".format(directHashTime, originTime.toDouble / directHashTime))
System.gc()
// direct hash2
startTime = System.nanoTime()
var result2 = 31 * (31 * (31 * (31 * host.hashCode() + rpcPort.hashCode()) + pushPort.hashCode()) + fetchPort.hashCode()) + replicatePort.hashCode()
endTime = System.nanoTime()
val directHashTime2 = endTime - startTime
println("directly hash2 costs %d ns, %.2fx".format(directHashTime2, originTime.toDouble / directHashTime2))
```
And I get the following result:
```
origin costs 1762813 ns, 1.00x
for seq costs 1158450 ns, 1.52x
for array costs 5844185 ns, 0.30x
while seq costs 95599 ns, 18.44x
while array costs 8210 ns, 214.72x
object hash costs 37889 ns, 46.53x
directly hash costs 40092 ns, 43.97x
directly hash2 costs 6498 ns, 271.29x
```
The way mentioned here is called `directly hash`, seems it is worse than that of while array. For the best performance `directly hash2` which expand all calculations, it is a little better than while array. I am also a little confused about the reason here. I think it may be some compiler optimization. And between `directly hash2` and `while array` , I prefer while array because it's more readable.
> we dont need to cache WorkerInfo's hashCode (it is just a few cheap arithmetic computations)
I also think the cache can be removed. The calculation here is really cheap. Introducing the if branch may be worse here.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@celeborn.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [CELEBORN-1121] Improve WorkerInfo#hashCode method [incubator-celeborn]
Posted by "onebox-li (via GitHub)" <gi...@apache.org>.
onebox-li commented on code in PR #2086:
URL: https://github.com/apache/incubator-celeborn/pull/2086#discussion_r1392094713
##########
common/src/main/scala/org/apache/celeborn/common/meta/WorkerInfo.scala:
##########
@@ -232,8 +235,21 @@ class WorkerInfo(
}
override def hashCode(): Int = {
- val state = Seq(host, rpcPort, pushPort, fetchPort, replicatePort)
- state.map(_.hashCode()).foldLeft(0)((a, b) => 31 * a + b)
+ var h = hash
+ if (h == 0 || isZeroHash) {
+ val state = Array(host, rpcPort, pushPort, fetchPort, replicatePort)
+ var i = 0
+ while (i < state.length) {
+ h = 31 * h + state(i).hashCode()
+ i = i + 1
+ }
+ if (h == 0) {
+ isZeroHash = true
+ } else {
+ hash = h
+ }
+ }
+ h
Review Comment:
I have tested WorkerInfo#hashCode() with and without cache.
```
hashCode() with cache 1 cost 3665 ns
hashCode() with cache 2 cost 472 ns
hashCode() with cache 3 cost 390 ns
hashCode() without cache 1 cost 3389 ns
hashCode() without cache 2 cost 1872 ns
hashCode() without cache 3 cost 1915 ns
```
Since the time unit is small, the improvement is not large in nature, but the cost does not seem to be large. Maybe we can retain the cache?
##########
common/src/main/scala/org/apache/celeborn/common/meta/WorkerInfo.scala:
##########
@@ -232,8 +235,21 @@ class WorkerInfo(
}
override def hashCode(): Int = {
- val state = Seq(host, rpcPort, pushPort, fetchPort, replicatePort)
- state.map(_.hashCode()).foldLeft(0)((a, b) => 31 * a + b)
+ var h = hash
+ if (h == 0 || isZeroHash) {
+ val state = Array(host, rpcPort, pushPort, fetchPort, replicatePort)
+ var i = 0
+ while (i < state.length) {
+ h = 31 * h + state(i).hashCode()
+ i = i + 1
+ }
+ if (h == 0) {
+ isZeroHash = true
+ } else {
+ hash = h
+ }
+ }
+ h
Review Comment:
I have tested WorkerInfo#hashCode() with and without cache.
```
hashCode() with cache 1 cost 3665 ns
hashCode() with cache 2 cost 472 ns
hashCode() with cache 3 cost 390 ns
hashCode() without cache 1 cost 3389 ns
hashCode() without cache 2 cost 1872 ns
hashCode() without cache 3 cost 1915 ns
```
Since the time unit is small, the improvement is not large in nature, but the cost does not seem to be large. Maybe we can retain the cache?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@celeborn.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [CELEBORN-1121] Improve WorkerInfo#hashCode method [incubator-celeborn]
Posted by "cfmcgrady (via GitHub)" <gi...@apache.org>.
cfmcgrady commented on PR #2086:
URL: https://github.com/apache/incubator-celeborn/pull/2086#issuecomment-1815654043
thanks, @onebox-li @waitinfuture @mridulm @AngersZhuuuu
merging to main(v0.4.0)/branch-0.3(v0.3.2).
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@celeborn.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [CELEBORN-1121] Improve WorkerInfo#hashCode method [incubator-celeborn]
Posted by "cfmcgrady (via GitHub)" <gi...@apache.org>.
cfmcgrady closed pull request #2086: [CELEBORN-1121] Improve WorkerInfo#hashCode method
URL: https://github.com/apache/incubator-celeborn/pull/2086
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@celeborn.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [CELEBORN-1121] Improve WorkerInfo#hashCode method [incubator-celeborn]
Posted by "onebox-li (via GitHub)" <gi...@apache.org>.
onebox-li commented on code in PR #2086:
URL: https://github.com/apache/incubator-celeborn/pull/2086#discussion_r1395465323
##########
common/src/main/scala/org/apache/celeborn/common/meta/WorkerInfo.scala:
##########
@@ -232,8 +235,21 @@ class WorkerInfo(
}
override def hashCode(): Int = {
- val state = Seq(host, rpcPort, pushPort, fetchPort, replicatePort)
- state.map(_.hashCode()).foldLeft(0)((a, b) => 31 * a + b)
+ var h = hash
+ if (h == 0 || isZeroHash) {
+ val state = Array(host, rpcPort, pushPort, fetchPort, replicatePort)
+ var i = 0
+ while (i < state.length) {
+ h = 31 * h + state(i).hashCode()
+ i = i + 1
+ }
+ if (h == 0) {
+ isZeroHash = true
+ } else {
+ hash = h
+ }
+ }
+ h
Review Comment:
Thanks @mridulm for suggestion, I did a benchmark, warmed up, and used avg time for comparison.
```
Origin 1.0X
For with Seq 1.1X
For with Array 4.0X
While with Seq 1.6X
While with Array 4.2X
Objects hash 2.1X
Directly hash1 6.9X
Directly hash2 8.1X
No Op 8.5X
```
According to the results, the cost of direct calculation is very cheap. So here remove cache.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@celeborn.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [CELEBORN-1121] Improve WorkerInfo#hashCode method [incubator-celeborn]
Posted by "mridulm (via GitHub)" <gi...@apache.org>.
mridulm commented on code in PR #2086:
URL: https://github.com/apache/incubator-celeborn/pull/2086#discussion_r1392987698
##########
common/src/main/scala/org/apache/celeborn/common/meta/WorkerInfo.scala:
##########
@@ -232,8 +235,21 @@ class WorkerInfo(
}
override def hashCode(): Int = {
- val state = Seq(host, rpcPort, pushPort, fetchPort, replicatePort)
- state.map(_.hashCode()).foldLeft(0)((a, b) => 31 * a + b)
+ var h = hash
+ if (h == 0 || isZeroHash) {
+ val state = Array(host, rpcPort, pushPort, fetchPort, replicatePort)
+ var i = 0
+ while (i < state.length) {
+ h = 31 * h + state(i).hashCode()
+ i = i + 1
+ }
+ if (h == 0) {
+ isZeroHash = true
+ } else {
+ hash = h
+ }
+ }
+ h
Review Comment:
Couple of points:
* For microbenchmarks, please use JMH - not sure if you did.
* Any implementation which does memoization will typically be faster - since it is if condition + field lookup when result has been memoized - the additional complexity of adding that should be worth it: in this case, synchronization to ensure visibility of update in a MT safe manner.
You can ofcourse avoid the synchronization overhead by simply pushing the computation to the constructor - then `hashCode` will be simply be returning the computed hash - that will be the fastest :-)
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@celeborn.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [CELEBORN-1121] Improve WorkerInfo#hashCode method [incubator-celeborn]
Posted by "cfmcgrady (via GitHub)" <gi...@apache.org>.
cfmcgrady commented on code in PR #2086:
URL: https://github.com/apache/incubator-celeborn/pull/2086#discussion_r1388776573
##########
common/src/main/scala/org/apache/celeborn/common/meta/WorkerInfo.scala:
##########
@@ -47,6 +47,8 @@ class WorkerInfo(
JavaUtils.newConcurrentHashMap[UserIdentifier, ResourceConsumption](_userResourceConsumption)
else null
var endpoint: RpcEndpointRef = null
+ // Cache the hash code for WorkerInfo
+ var hash = 0
Review Comment:
```suggestion
private var hash = 0
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@celeborn.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [CELEBORN-1121] Improve WorkerInfo#hashCode method [incubator-celeborn]
Posted by "waitinfuture (via GitHub)" <gi...@apache.org>.
waitinfuture commented on PR #2086:
URL: https://github.com/apache/incubator-celeborn/pull/2086#issuecomment-1805300355
I found the following code is even several times faster: 1187677ns vs. 513241ns vs. 32007ns vs. 9436ns
```
val host = generateRandomIPv4Address
val rpcPort: Integer = Random.nextInt(65535)
val pushPort: Integer = Random.nextInt(65535)
val fetchPort: Integer = Random.nextInt(65535)
val replicatePort: Integer = Random.nextInt(65535)
var startTime = System.nanoTime()
val state = Seq(host, rpcPort, pushPort, fetchPort, replicatePort)
// origin
val originHash = state.map(_.hashCode()).foldLeft(1)((a, b) => 31 * a + b)
var endTime = System.nanoTime()
println(endTime - startTime)
// for
startTime = System.nanoTime()
var forHash = 1
for (i <- state) {
forHash = 31 * forHash + i.hashCode()
}
endTime = System.nanoTime()
println(endTime - startTime)
// while
startTime = System.nanoTime()
var whileHash = 1
var i = 0
while (i < state.size) {
whileHash = 31 * whileHash + state(i).hashCode()
i = i + 1
}
endTime = System.nanoTime()
println(endTime - startTime)
startTime = System.nanoTime()
val objectHash = Objects.hash(host, rpcPort, pushPort, fetchPort, replicatePort)
endTime = System.nanoTime()
println(endTime - startTime)
```
But we need to explicitly set type of `rpcPort, pushPort, fetchPort, replicatePort` to `Integer`, or use `Integer.valueOf(rpcPort` int the hash method. In addition, the behavior changes a bit that `Objects.hash` default use 0. IMO it's OK because it only affects the process.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@celeborn.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [CELEBORN-1121] Improve WorkerInfo#hashCode method [incubator-celeborn]
Posted by "onebox-li (via GitHub)" <gi...@apache.org>.
onebox-li commented on code in PR #2086:
URL: https://github.com/apache/incubator-celeborn/pull/2086#discussion_r1388864241
##########
common/src/test/scala/org/apache/celeborn/common/meta/WorkerInfoSuite.scala:
##########
@@ -303,4 +303,25 @@ class WorkerInfoSuite extends CelebornFunSuite {
}
}
}
+
+ test("Test WorkerInfo hashcode") {
+ val host = "127.0.0.1"
+ val rpcPort = 9082
Review Comment:
Sounds good. Done.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@celeborn.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [CELEBORN-1121] Improve WorkerInfo#hashCode method [incubator-celeborn]
Posted by "cfmcgrady (via GitHub)" <gi...@apache.org>.
cfmcgrady commented on code in PR #2086:
URL: https://github.com/apache/incubator-celeborn/pull/2086#discussion_r1388779635
##########
common/src/test/scala/org/apache/celeborn/common/meta/WorkerInfoSuite.scala:
##########
@@ -303,4 +303,34 @@ class WorkerInfoSuite extends CelebornFunSuite {
}
}
}
+
+ test("Test WorkerInfo hashcode") {
+ val host = "127.0.0.1"
+ val rpcPort = 9082
+ val pushPort = 9092
+ val fetchPort = 9093
+ val replicatePort = 9094
+ val workerInfo = new WorkerInfo(host, rpcPort, pushPort, fetchPort, replicatePort)
+
+ // origin hashCode()
+ var now = System.nanoTime()
+ val state = Seq(host, rpcPort, pushPort, fetchPort, replicatePort)
+ val originHash = state.map(_.hashCode()).foldLeft(0)((a, b) => 31 * a + b)
+ var after = System.nanoTime()
+ println("WorkerInfo origin hash result = " + originHash + ", costs " + (after - now))
Review Comment:
avoid call `println` in UTs
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@celeborn.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [CELEBORN-1121] Improve WorkerInfo#hashCode method [incubator-celeborn]
Posted by "cfmcgrady (via GitHub)" <gi...@apache.org>.
cfmcgrady commented on code in PR #2086:
URL: https://github.com/apache/incubator-celeborn/pull/2086#discussion_r1388815651
##########
common/src/test/scala/org/apache/celeborn/common/meta/WorkerInfoSuite.scala:
##########
@@ -303,4 +303,25 @@ class WorkerInfoSuite extends CelebornFunSuite {
}
}
}
+
+ test("Test WorkerInfo hashcode") {
+ val host = "127.0.0.1"
+ val rpcPort = 9082
Review Comment:
I think we can randomize this unit test
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@celeborn.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [CELEBORN-1121] Improve WorkerInfo#hashCode method [incubator-celeborn]
Posted by "mridulm (via GitHub)" <gi...@apache.org>.
mridulm commented on code in PR #2086:
URL: https://github.com/apache/incubator-celeborn/pull/2086#discussion_r1391962579
##########
common/src/main/scala/org/apache/celeborn/common/meta/WorkerInfo.scala:
##########
@@ -232,8 +235,21 @@ class WorkerInfo(
}
override def hashCode(): Int = {
- val state = Seq(host, rpcPort, pushPort, fetchPort, replicatePort)
- state.map(_.hashCode()).foldLeft(0)((a, b) => 31 * a + b)
+ var h = hash
+ if (h == 0 || isZeroHash) {
+ val state = Array(host, rpcPort, pushPort, fetchPort, replicatePort)
+ var i = 0
+ while (i < state.length) {
+ h = 31 * h + state(i).hashCode()
+ i = i + 1
+ }
+ if (h == 0) {
+ isZeroHash = true
+ } else {
+ hash = h
+ }
+ }
+ h
Review Comment:
Instead, why not simply unroll the loop ?
```
override def hashCode: Int = {
var result = if (host != null) host.hashCode else 0
result = 31 * result + rpcPort
result = 31 * result + pushPort
result = 31 * result + fetchPort
result = 31 * result + replicatePort
result
}
```
Since java already caches the hashCode for String, that should be fine and we dont need to cache WorkerInfo's hashCode (it is just a few cheap arithmetic computations)
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@celeborn.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [CELEBORN-1121] Improve WorkerInfo#hashCode method [incubator-celeborn]
Posted by "onebox-li (via GitHub)" <gi...@apache.org>.
onebox-li commented on PR #2086:
URL: https://github.com/apache/incubator-celeborn/pull/2086#issuecomment-1807862778
These calculations are sensitive to performance(within milliseconds) and it may be biased when using current benchmark framework. So I tested them locally and the results are more intuitive, shown below.
```
java version "1.8.0_261"
=====================
origin costs 1026147 ns, 1.00x
for seq costs 791501 ns, 1.30x
for array costs 336341 ns, 3.05x
while seq costs 36436 ns, 28.16x
while array costs 1082 ns, 948.38x
object hash costs 9595 ns, 106.95x
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@celeborn.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [CELEBORN-1121] Improve WorkerInfo#hashCode method [incubator-celeborn]
Posted by "cfmcgrady (via GitHub)" <gi...@apache.org>.
cfmcgrady commented on code in PR #2086:
URL: https://github.com/apache/incubator-celeborn/pull/2086#discussion_r1388782549
##########
common/src/test/scala/org/apache/celeborn/common/meta/WorkerInfoSuite.scala:
##########
@@ -303,4 +303,34 @@ class WorkerInfoSuite extends CelebornFunSuite {
}
}
}
+
+ test("Test WorkerInfo hashcode") {
+ val host = "127.0.0.1"
+ val rpcPort = 9082
+ val pushPort = 9092
+ val fetchPort = 9093
+ val replicatePort = 9094
+ val workerInfo = new WorkerInfo(host, rpcPort, pushPort, fetchPort, replicatePort)
+
+ // origin hashCode()
+ var now = System.nanoTime()
+ val state = Seq(host, rpcPort, pushPort, fetchPort, replicatePort)
+ val originHash = state.map(_.hashCode()).foldLeft(0)((a, b) => 31 * a + b)
+ var after = System.nanoTime()
+ println("WorkerInfo origin hash result = " + originHash + ", costs " + (after - now))
Review Comment:
use `log` or `assert(condition: Boolean, clue: Any)` instead of `println`.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@celeborn.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [CELEBORN-1121] Improve WorkerInfo#hashCode method [incubator-celeborn]
Posted by "cfmcgrady (via GitHub)" <gi...@apache.org>.
cfmcgrady commented on PR #2086:
URL: https://github.com/apache/incubator-celeborn/pull/2086#issuecomment-1805377388
btw, we have a benchmark framework introduced in https://github.com/apache/incubator-celeborn/pull/1657
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@celeborn.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [CELEBORN-1121] Improve WorkerInfo#hashCode method [incubator-celeborn]
Posted by "cfmcgrady (via GitHub)" <gi...@apache.org>.
cfmcgrady commented on code in PR #2086:
URL: https://github.com/apache/incubator-celeborn/pull/2086#discussion_r1391162601
##########
common/src/main/scala/org/apache/celeborn/common/meta/WorkerInfo.scala:
##########
@@ -232,8 +235,21 @@ class WorkerInfo(
}
override def hashCode(): Int = {
- val state = Seq(host, rpcPort, pushPort, fetchPort, replicatePort)
- state.map(_.hashCode()).foldLeft(0)((a, b) => 31 * a + b)
+ var h = hash
+ if (h == 0 || isZeroHash) {
+ val state = Array(host, rpcPort, pushPort, fetchPort, replicatePort)
+ var i = 0
+ while (i < state.length) {
+ h = 31 * h + state(i).hashCode()
+ i = i + 1
+ }
+ if (h == 0) {
+ isZeroHash = true
+ } else {
+ hash = h
Review Comment:
it's not thread-safe, shall we need to cache the hash code?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@celeborn.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [CELEBORN-1121] Improve WorkerInfo#hashCode method [incubator-celeborn]
Posted by "mridulm (via GitHub)" <gi...@apache.org>.
mridulm commented on code in PR #2086:
URL: https://github.com/apache/incubator-celeborn/pull/2086#discussion_r1391962579
##########
common/src/main/scala/org/apache/celeborn/common/meta/WorkerInfo.scala:
##########
@@ -232,8 +235,21 @@ class WorkerInfo(
}
override def hashCode(): Int = {
- val state = Seq(host, rpcPort, pushPort, fetchPort, replicatePort)
- state.map(_.hashCode()).foldLeft(0)((a, b) => 31 * a + b)
+ var h = hash
+ if (h == 0 || isZeroHash) {
+ val state = Array(host, rpcPort, pushPort, fetchPort, replicatePort)
+ var i = 0
+ while (i < state.length) {
+ h = 31 * h + state(i).hashCode()
+ i = i + 1
+ }
+ if (h == 0) {
+ isZeroHash = true
+ } else {
+ hash = h
+ }
+ }
+ h
Review Comment:
Instead, why not simply unroll the loop ?
```
override def hashCode: Int = {
var result = if (host != null) host.hashCode else 0
result = 31 * result + rpcPort
result = 31 * result + pushPort
result = 31 * result + fetchPort
result = 31 * result + replicatePort
result
}
```
Since java already caches the hashCode for String, that should be fine and we dont need to cache WorkerInfo's hashCode (it is just a few cheap arthithematic computations)
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@celeborn.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] [CELEBORN-1121] Improve WorkerInfo#hashCode method [incubator-celeborn]
Posted by "onebox-li (via GitHub)" <gi...@apache.org>.
onebox-li commented on code in PR #2086:
URL: https://github.com/apache/incubator-celeborn/pull/2086#discussion_r1395497213
##########
common/src/main/scala/org/apache/celeborn/common/meta/WorkerInfo.scala:
##########
@@ -232,8 +232,12 @@ class WorkerInfo(
}
override def hashCode(): Int = {
- val state = Seq(host, rpcPort, pushPort, fetchPort, replicatePort)
- state.map(_.hashCode()).foldLeft(0)((a, b) => 31 * a + b)
+ var result = host.hashCode()
+ result = 31 * result + rpcPort.hashCode()
+ result = 31 * result + pushPort.hashCode()
+ result = 31 * result + fetchPort.hashCode()
+ result = 31 * result + replicatePort.hashCode()
+ result
Review Comment:
The calculation here is relatively cheap, and the cache will not be much improved, so we may make it simpler.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@celeborn.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org