Skip to content

[SPARK-3294][SQL] Eliminates boxing costs from in-memory columnar storage - #2327

Closed
liancheng wants to merge 13 commits into
apache:masterfrom
liancheng:prevent-boxing/unboxing
Closed

[SPARK-3294][SQL] Eliminates boxing costs from in-memory columnar storage#2327
liancheng wants to merge 13 commits into
apache:masterfrom
liancheng:prevent-boxing/unboxing

Conversation

@liancheng

Copy link
Copy Markdown
Contributor

This is a major refactoring of the in-memory columnar storage implementation, aims to eliminate boxing costs from critical paths (building/accessing column buffers) as much as possible. The basic idea is to refactor all major interfaces into a row-based form and use them together with SpecificMutableRow. The difficult part is how to adapt all compression schemes, esp. RunLengthEncoding and DictionaryEncoding, to this design. Since in-memory compression is disabled by default for now, and this PR should be strictly better than before no matter in-memory compression is enabled or not, maybe I'll finish that part in another PR.

UPDATE This PR also took the chance to optimize HiveTableScan by

  1. leveraging SpecificMutableRow to avoid boxing cost, and
  2. building specific Writable unwrapper functions a head of time to avoid per row pattern matching and branching costs.

TODO

  • Benchmark
  • Eliminate boxing costs in RunLengthEncoding (left to future PRs)
  • Eliminate boxing costs in DictionaryEncoding (seems not easy to do without specializing DictionaryEncoding for every supported column type) (left to future PRs)

Micro benchmark

The benchmark uses a 10 million line CSV table consists of bytes, shorts, integers, longs, floats and doubles, measures the time to build the in-memory version of this table, and the time to scan the whole in-memory table.

Benchmark code can be found here. Script used to generate the input table can be found here.

Speedup:

  • Hive table scanning + column buffer building: 18.74%

    The original benchmark uses 1K as in-memory batch size, when increased to 10K, it can be 28.32% faster.

  • In-memory table scanning: 7.95%

Before:

BuildingScanning
116472525
216168530
316386529
416184538
516209521
Average16283.8528.6

After:

BuildingScanning
113124458
213260529
312981463
413214483
513583500
Average13232.4486.6

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change is submitted separately in #2325 as this PR may take longer time to finish.

@SparkQA

Copy link
Copy Markdown

QA tests have started for PR 2327 at commit 269bd78.

  • This patch merges cleanly.

@SparkQA

Copy link
Copy Markdown

QA tests have finished for PR 2327 at commit 269bd78.

  • This patch fails unit tests.
  • This patch merges cleanly.
  • This patch adds the following public classes (experimental):
    • class Encoder[T <: NativeType](columnType: NativeColumnType[T]) extends compression.Encoder[T]
    • class Encoder[T <: NativeType](columnType: NativeColumnType[T]) extends compression.Encoder[T]
    • class Encoder[T <: NativeType](columnType: NativeColumnType[T]) extends compression.Encoder[T]
    • class Encoder extends compression.Encoder[IntegerType.type]
    • class Decoder(buffer: ByteBuffer, columnType: NativeColumnType[IntegerType.type])
    • class Encoder extends compression.Encoder[LongType.type]
    • class Decoder(buffer: ByteBuffer, columnType: NativeColumnType[LongType.type])

@aarondav

Copy link
Copy Markdown
Contributor

Out of curiosity, does this also eliminate boxing for nested data types?

@liancheng

Copy link
Copy Markdown
ContributorAuthor

No, unlike Parquet, currently our in-memory columnar format doesn't support complex nested objects well. They are just serialized by Kryo and stored as opaque byte arrays.

@marmbrus

Copy link
Copy Markdown
Contributor

@aarondav to expand on that, as soon as there is any nesting all of our clever tricks for eliminating allocations go out the window. We can probably improve this in future releases.

@liancheng
lianchengforce-pushed the prevent-boxing/unboxing branch from 5cacd9a to 97bbc4eCompareSeptember 10, 2014 02:13
@SparkQA

Copy link
Copy Markdown

QA tests have started for PR 2327 at commit 97bbc4e.

  • This patch merges cleanly.

@SparkQA

Copy link
Copy Markdown

QA tests have finished for PR 2327 at commit 97bbc4e.

  • This patch fails unit tests.
  • This patch merges cleanly.
  • This patch adds no public classes.

@liancheng

Copy link
Copy Markdown
ContributorAuthor

ok to test

@SparkQA

Copy link
Copy Markdown

QA tests have started for PR 2327 at commit 489f97b.

  • This patch merges cleanly.

@SparkQA

Copy link
Copy Markdown

QA tests have finished for PR 2327 at commit 489f97b.

  • This patch fails unit tests.
  • This patch merges cleanly.
  • This patch adds the following public classes (experimental):
    • class Encoder[T <: NativeType](columnType: NativeColumnType[T]) extends compression.Encoder[T]
    • class Encoder[T <: NativeType](columnType: NativeColumnType[T]) extends compression.Encoder[T]
    • class Encoder[T <: NativeType](columnType: NativeColumnType[T]) extends compression.Encoder[T]
    • class Encoder extends compression.Encoder[IntegerType.type]
    • class Decoder(buffer: ByteBuffer, columnType: NativeColumnType[IntegerType.type])
    • class Encoder extends compression.Encoder[LongType.type]
    • class Decoder(buffer: ByteBuffer, columnType: NativeColumnType[LongType.type])

@liancheng

Copy link
Copy Markdown
ContributorAuthor

test this please

@SparkQA

Copy link
Copy Markdown

QA tests have started for PR 2327 at commit e5d2cf2.

  • This patch merges cleanly.

@SparkQA

Copy link
Copy Markdown

QA tests have started for PR 2327 at commit e5d2cf2.

  • This patch merges cleanly.

@SparkQA

Copy link
Copy Markdown

QA tests have finished for PR 2327 at commit e5d2cf2.

  • This patch passes unit tests.
  • This patch merges cleanly.
  • This patch adds the following public classes (experimental):
    • class Encoder[T <: NativeType](columnType: NativeColumnType[T]) extends compression.Encoder[T]
    • class Encoder[T <: NativeType](columnType: NativeColumnType[T]) extends compression.Encoder[T]
    • class Encoder[T <: NativeType](columnType: NativeColumnType[T]) extends compression.Encoder[T]
    • class Encoder extends compression.Encoder[IntegerType.type]
    • class Decoder(buffer: ByteBuffer, columnType: NativeColumnType[IntegerType.type])
    • class Encoder extends compression.Encoder[LongType.type]
    • class Decoder(buffer: ByteBuffer, columnType: NativeColumnType[LongType.type])

@SparkQA

Copy link
Copy Markdown

Tests timed out after a configured wait of 120m.

@liancheng

Copy link
Copy Markdown
ContributorAuthor

@marmbrus Please help review this one. HiveTableScan is also optimized BTW.

@SparkQA

Copy link
Copy Markdown

QA tests have started for PR 2327 at commit e5d2cf2.

  • This patch merges cleanly.

@SparkQA

Copy link
Copy Markdown

QA tests have finished for PR 2327 at commit e5d2cf2.

  • This patch passes unit tests.
  • This patch merges cleanly.
  • This patch adds the following public classes (experimental):
    • class Encoder[T <: NativeType](columnType: NativeColumnType[T]) extends compression.Encoder[T]
    • class Encoder[T <: NativeType](columnType: NativeColumnType[T]) extends compression.Encoder[T]
    • class Encoder[T <: NativeType](columnType: NativeColumnType[T]) extends compression.Encoder[T]
    • class Encoder extends compression.Encoder[IntegerType.type]
    • class Decoder(buffer: ByteBuffer, columnType: NativeColumnType[IntegerType.type])
    • class Encoder extends compression.Encoder[LongType.type]
    • class Decoder(buffer: ByteBuffer, columnType: NativeColumnType[LongType.type])

@marmbrus

Copy link
Copy Markdown
Contributor

I need to look this over still, but want to remove WIP?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This style is going to go away in 2.12 or 2.13 I think. Should be :Unit =

@marmbrus

Copy link
Copy Markdown
Contributor

Nice speed ups. I think they might be even more pronounced when there are multiple threads fighting for the GC.

Minor comments only. Will merge after they are addressed.

@lianchengliancheng changed the title [SPARK-3294][SQL] WIP: eliminates boxing costs from in-memory columnar storage[SPARK-3294][SQL] Eliminates boxing costs from in-memory columnar storageSep 11, 2014
@SparkQA

Copy link
Copy Markdown

QA tests have started for PR 2327 at commit 4419fe4.

  • This patch merges cleanly.

@SparkQA

Copy link
Copy Markdown

QA tests have finished for PR 2327 at commit 4419fe4.

  • This patch passes unit tests.
  • This patch merges cleanly.
  • This patch adds the following public classes (experimental):
    • class Encoder[T <: NativeType](columnType: NativeColumnType[T]) extends compression.Encoder[T]
    • class Encoder[T <: NativeType](columnType: NativeColumnType[T]) extends compression.Encoder[T]
    • class Encoder[T <: NativeType](columnType: NativeColumnType[T]) extends compression.Encoder[T]
    • class Encoder extends compression.Encoder[IntegerType.type]
    • class Decoder(buffer: ByteBuffer, columnType: NativeColumnType[IntegerType.type])
    • class Encoder extends compression.Encoder[LongType.type]
    • class Decoder(buffer: ByteBuffer, columnType: NativeColumnType[LongType.type])

@marmbrus

Copy link
Copy Markdown
Contributor

Thanks! I've merged this to master.

@liancheng
liancheng deleted the prevent-boxing/unboxing branch September 24, 2014 00:04
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@liancheng@SparkQA@aarondav@marmbrus