Uh oh!
There was an error while loading. Please reload this page.
[SPARK-19112][CORE] Support for ZStandard codec - #18805
Conversation
sitalkedia
commented
Aug 2, 2017
cc - @srowen, @tgravescs, @rxin, @sameeragarwal |
sitalkedia
commented
Aug 2, 2017
Old PR - #17303 |
rxin
commented
Aug 2, 2017
Any benchmark data? |
SparkQA
commented
Aug 2, 2017
Test build #80140 has finished for PR 18805 at commit
|
SparkQA
commented
Aug 2, 2017
Test build #80141 has finished for PR 18805 at commit
|
4ee4d2b to
287a9daCompareSparkQA
commented
Aug 2, 2017
Test build #80142 has finished for PR 18805 at commit
|
HyukjinKwon
commented
Aug 2, 2017
cc @dongjinleekr too. |
sitalkedia
commented
Aug 2, 2017
@rxin - Updated with benchmark data on our production workload. |
Please note that few minor improvements I have made as comapred to old PR - #17303
|
sitalkedia
commented
Aug 2, 2017
jenkins retest this please. |
SparkQA
commented
Aug 2, 2017
Test build #80144 has finished for PR 18805 at commit
|
sitalkedia
commented
Aug 2, 2017
Any idea what is the build failure about? |
| "lzf" -> classOf[LZFCompressionCodec].getName, | ||
| "snappy" -> classOf[SnappyCompressionCodec].getName) | ||
| "snappy" -> classOf[SnappyCompressionCodec].getName, | ||
| "zstd" -> classOf[SnappyCompressionCodec].getName) |
There was a problem hiding this comment.
you mean ZStandardCompressionCodec ?
| /** | ||
| * :: DeveloperApi :: | ||
| * ZStandard implementation of [[org.apache.spark.io.CompressionCodec]]. |
There was a problem hiding this comment.
would be good to add this link pointing to more details : http://facebook.github.io/zstd/
| class ZStandardCompressionCodec(conf: SparkConf) extends CompressionCodec { | ||
| override def compressedOutputStream(s: OutputStream): OutputStream = { | ||
| val level = conf.getSizeAsBytes("spark.io.compression.zstandard.level", "1").toInt |
There was a problem hiding this comment.
please add a comment explaining the reason why we chose level 1 over other levels
| override def compressedOutputStream(s: OutputStream): OutputStream = { | ||
| val level = conf.getSizeAsBytes("spark.io.compression.zstandard.level", "1").toInt | ||
| val compressionBuffer = conf.getSizeAsBytes("spark.io.compression.lz4.blockSize", "32k").toInt |
There was a problem hiding this comment.
- wondering if we should share this config value OR have a new one.
- do you want to set the default to something higher like 1mb or 4mb ?
There was a problem hiding this comment.
You are right, we should not share the config with lz4, created a new one.
Lets keep the default to 32kb which is aligned with the block size used by other compressions.
tejasapatil
commented
Aug 2, 2017
In |
tejasapatil
commented
Aug 2, 2017
re build failure: you can repro that locally by running "./dev/test-dependencies.sh". Its failing due to introducing a new dep... you need to add it to |
rxin
commented
Aug 2, 2017
How big is the dependency that's getting pulled in? If we are adding more compression codecs maybe we should retire some old ones, or move them into a separate package so downstream apps can optionally depend on them. |
SparkQA
commented
Aug 2, 2017
Test build #80148 has finished for PR 18805 at commit
|
srowen
commented
Aug 2, 2017
Why does this need to be in Spark? and what are the licensing terms of the native code underneath (just suspicious because it's often GPL)? can a user not just add this with their app? I tend to think we support what Hadoop supports for us here. Doesn't a later Hadoop pull this in? |
@srowen you already asked that question and it has been answered on the jira as well as the old pr. A user cannot add zstd compression to the internal spark parts: spark.io.compression.codec. In this particular case he is saying its the shuffle output where its making a big difference. |
srowen
commented
Aug 2, 2017
Got it, thanks for the reminder. I think the question is mostly about license and dependency weight then. I think we'd want to use whatever Hadoop provides. |
| <code>org.apache.spark.io.LZ4CompressionCodec</code>, | ||
| <code>org.apache.spark.io.LZFCompressionCodec</code>, | ||
| and <code>org.apache.spark.io.SnappyCompressionCodec</code>. | ||
| <code>org.apache.spark.io.SnappyCompressionCodec</code>. |
| <tr> | ||
| <td><code>spark.io.compression.zstd.level</code></td> | ||
| <td>1</td> | ||
| <td> |
| // Default compression level for zstd compression to 1 because it is | ||
| // fastest of all with reasonably high compression ratio. | ||
| val level = conf.getSizeAsBytes("spark.io.compression.zstd.level", "1").toInt | ||
| val bufferSize = conf.getSizeAsBytes("spark.io.compression.zstd.bufferSize", "32k").toInt |
There was a problem hiding this comment.
Would it be better to have this variable as a private variable to get this property only once?
There was a problem hiding this comment.
Agree, it's simpler and cleaner, as it avoids duplicating this property in this file
There was a problem hiding this comment.
Sorry somehow missed these comments. Will address.
rxin
commented
Aug 2, 2017
Our compression codec is actually completely decoupled from Hadoops, but dependency management (and licensing) can be annoying to deal with. |
SparkQA
commented
Oct 11, 2017
Test build #82644 has finished for PR 18805 at commit
|
vanzin
commented
Oct 11, 2017
Same test failed, so looks like there's a real non-infra-related issue... |
hvanhovell
commented
Oct 13, 2017
retest this please |
SparkQA
commented
Oct 13, 2017
Test build #82729 has finished for PR 18805 at commit
|
vanzin
commented
Oct 13, 2017
I haven't been able to reproduce the issue locally, but looking at the jenkins logs I see a bunch of exceptions like these: And: Note that the first error mentions the app name used by |
vanzin
commented
Oct 13, 2017
(I'll file a bug and send a PR for it separately, btw.) |
vanzin
commented
Oct 13, 2017
Turns out that's caused by SparkContext failing to clean up after itself when the |
hvanhovell
commented
Oct 13, 2017
This seems to be caused by a issue in the |
Yeah but that would also cause it to fail locally if it were the cause, and it passes for me. I can't really figure out from the rest of the logs if something obvious is wrong, so I guess the best bet now is to ask for changes in the |
vanzin
commented
Oct 13, 2017
Good news is that I can reproduce it on the amplab machine, so I'll try to play around with the zstd-jni code a bit. |
vanzin
commented
Oct 13, 2017
Mystery solved; library is compiled with a newer glibc requirement than the amplab machines have. Can we ask them to tweak their compilation to support older Linux distros? |
sitalkedia
commented
Oct 19, 2017
Created luben/zstd-jni#47. |
SparkQA
commented
Oct 19, 2017
Test build #82911 has finished for PR 18805 at commit
|
sitalkedia
commented
Oct 26, 2017
ping. |
srowen
left a comment
There was a problem hiding this comment.
Aside from one minor question from an old comment that's looking good. The licenses seem in order.
| // Default compression level for zstd compression to 1 because it is | ||
| // fastest of all with reasonably high compression ratio. | ||
| val level = conf.getSizeAsBytes("spark.io.compression.zstd.level", "1").toInt | ||
| val bufferSize = conf.getSizeAsBytes("spark.io.compression.zstd.bufferSize", "32k").toInt |
| override def compressedOutputStream(s: OutputStream): OutputStream = { | ||
| // Default compression level for zstd compression to 1 because it is | ||
| // fastest of all with reasonably high compression ratio. | ||
| val level = conf.getSizeAsBytes("spark.io.compression.zstd.level", "1").toInt |
There was a problem hiding this comment.
Is this getInt instead of getSizeAsBytes?
SparkQA
commented
Oct 30, 2017
Test build #83204 has finished for PR 18805 at commit
|
| @DeveloperApi | ||
| class ZStdCompressionCodec(conf: SparkConf) extends CompressionCodec { | ||
| val bufferSize = conf.getSizeAsBytes("spark.io.compression.zstd.bufferSize", "32k").toInt |
There was a problem hiding this comment.
This should be private. The intent was to lift both config values out of the method, so level can do here too.
SparkQA
commented
Nov 1, 2017
Test build #83282 has finished for PR 18805 at commit
|
hvanhovell
commented
Nov 1, 2017
Merging to master. Thanks for seeing this through! |
What changes were proposed in this pull request?
Using zstd compression for Spark jobs spilling 100s of TBs of data, we could reduce the amount of data written to disk by as much as 50%. This translates to significant latency gain because of reduced disk io operations. There is a degradation CPU time by 2 - 5% because of zstd compression overhead, but for jobs which are bottlenecked by disk IO, this hit can be taken.
Benchmark
Please note that this benchmark is using real world compute heavy production workload spilling TBs of data to disk
How was this patch tested?
Tested by running few jobs spilling large amount of data on the cluster and amount of intermediate data written to disk reduced by as much as 50%.