-
Notifications
You must be signed in to change notification settings - Fork 1.6k
PARQUET-1533: TestSnappy() throws OOM exception with Parquet-1485 change #622
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 1 commit
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -27,21 +27,14 @@ | |
| import org.apache.parquet.Preconditions; | ||
|
|
||
| public class SnappyDecompressor implements Decompressor { | ||
| private static final int initialBufferSize = 64 * 1024 * 1024; | ||
|
|
||
| // Buffer for uncompressed output. This buffer grows as necessary. | ||
| private ByteBuffer outputBuffer = ByteBuffer.allocateDirect(initialBufferSize); | ||
| private ByteBuffer outputBuffer = ByteBuffer.allocateDirect(0); | ||
|
|
||
| // Buffer for compressed input. This buffer grows as necessary. | ||
| private ByteBuffer inputBuffer = ByteBuffer.allocateDirect(initialBufferSize); | ||
| private ByteBuffer inputBuffer = ByteBuffer.allocateDirect(0); | ||
|
|
||
| private boolean finished; | ||
|
|
||
| public SnappyDecompressor() { | ||
| inputBuffer.limit(0); | ||
| outputBuffer.limit(0); | ||
| } | ||
|
|
||
| /** | ||
| * Fills specified buffer with uncompressed data. Returns actual number | ||
| * of bytes of uncompressed data. A return value of 0 indicates that | ||
|
|
@@ -142,18 +135,6 @@ public synchronized boolean needsInput() { | |
|
|
||
| @Override | ||
| public synchronized void reset() { | ||
| if (inputBuffer.capacity() > initialBufferSize) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above comments. |
||
| ByteBuffer oldBuffer = inputBuffer; | ||
| inputBuffer = ByteBuffer.allocateDirect(initialBufferSize); | ||
| CleanUtil.clean(oldBuffer); | ||
| } | ||
|
|
||
| if (outputBuffer.capacity() > initialBufferSize) { | ||
| ByteBuffer oldBuffer = outputBuffer; | ||
| outputBuffer = ByteBuffer.allocateDirect(initialBufferSize); | ||
| CleanUtil.clean(oldBuffer); | ||
| } | ||
|
|
||
| finished = false; | ||
| inputBuffer.rewind(); | ||
| outputBuffer.rewind(); | ||
|
|
||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
May be we can keep these codes in the reset call and lower the initialBufferSize to 4MiB or else, as event without the preallocation of 128MiB, the inputBuffer and writeBuffer can grow very large if we just see it from the API itself, because the setInput can be called many times.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I cannot see why the buffers would grow that much. We compress/decompress one page at a time so it should not grow much larger than the largest page which is usually much smaller than
64M. By default it is1M.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still don't know 4M is a good number to be. If multiple compressors/decompressors are instantiated in parallel, the number can go up. Let's say 20 decompressors and each initialized with 2*4M, that results in 160M direct memory. That could be a problem for some applications. I agree with liupc that "keep the reset logic and remove the preallocation codes" unless we see a huge penalty for not doing that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you instantiates 20 decompressors then you probably tries to read 20 parquet files in the same time in the same jvm. It means you'll need tons of memory to keep 20 row-groups in the memory. Comparing to that 160M would not be too much I guess.
Meanwhile, I am not against keeping the reset logic but what would be the size to be reset to?
0?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about vectorized parquet reader? Does it instantiate the decompressor per column? I am not an expert of Parquet, so I could be wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@shangxinli
I think it's up to the implementation, either instantiating the decompressor per column or not can do this work. If you keep so many column compressor/decompressor in memory, then the memory consumed by the column data itself is much larger than 4MiB.
What's more, I suggest
4MiBhere because the compress/decompress buffer size is 4MiB now. so I think it's ok.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the default page size is 1M(assume the typical usage is default), 4M still seems too large. It will be adjusted later anyway if it is smaller than needs. I would prefer low over high.