30
1/30

Ivan mamontov and Mikhail Khuldnev Present : Fast Decompression Lucene Codec

Embed Size (px)

Citation preview

Page 1: Ivan mamontov and Mikhail Khuldnev Present : Fast Decompression Lucene Codec

1/30

Page 2: Ivan mamontov and Mikhail Khuldnev Present : Fast Decompression Lucene Codec

2/30

About me

I Software engineer at Grid Dynamics

I I am interested in low-level system programming

Page 3: Ivan mamontov and Mikhail Khuldnev Present : Fast Decompression Lucene Codec

3/30

Table of Contents

Compression in Lucene

Scalar vs. Vectors

Java Critical Native

Benchmarks

Page 4: Ivan mamontov and Mikhail Khuldnev Present : Fast Decompression Lucene Codec

4/30

Compression in Lucene

Page 5: Ivan mamontov and Mikhail Khuldnev Present : Fast Decompression Lucene Codec

5/30

Requirements of a search index

I compress index as possibleI minimize I/OI minimize index sizeI FS/Memory/CPU cache friendly

I avoid disc seeksI disc seek is ≈ 10ms

Page 6: Ivan mamontov and Mikhail Khuldnev Present : Fast Decompression Lucene Codec

6/30

The numbers every engineer should know

I L1 cache reference 0.5 ns

I Branch mispredict 5 ns

I L2 cache reference 7 ns

I Main memory reference 100 ns

I Read 1 MB sequentially from memory 250,000 ns

I Disk seek 10,000,000 ns

I Read 1 MB sequentially from disk 30,000,000 ns

Page 7: Ivan mamontov and Mikhail Khuldnev Present : Fast Decompression Lucene Codec

7/30

Codec API

Page 8: Ivan mamontov and Mikhail Khuldnev Present : Fast Decompression Lucene Codec

8/30

4D Codec API

Page 9: Ivan mamontov and Mikhail Khuldnev Present : Fast Decompression Lucene Codec

9/30

Postings lists

I Encoded using modified FOR delta

1. uses delta2. splits into block of N=128 values3. bit packing per block4. remaining docs, encode with vint

Example with N=4 1,3,4,6,8,20,22,26,30,1581,2,1,2,2,12,2,4,4,128[1,2,1,2] [2,12,2,4] 4,128

Page 10: Ivan mamontov and Mikhail Khuldnev Present : Fast Decompression Lucene Codec

10/30

What is FOR encoding?

To encode the following 4 numbers 1, 2, 1, 2:

10 0 1 1 0 0 1 1 0

1 bytenumber of bitsper value

FOR requires 1 byte instead of 4 ∗ 4 = 16 bytes!

Page 11: Ivan mamontov and Mikhail Khuldnev Present : Fast Decompression Lucene Codec

11/30

What is FOR encoding?

I prosI great compression rateI fast decoding speedI can be vectorized

I consI no random access within the blockI the cost is determined by the largest delta in a block

Page 12: Ivan mamontov and Mikhail Khuldnev Present : Fast Decompression Lucene Codec

12/30

Scalar vs. Vectors

Page 13: Ivan mamontov and Mikhail Khuldnev Present : Fast Decompression Lucene Codec

13/30

Scalar vs. Vectors

float a[4], b[4], c[4];

...

for (int i = 0; i < 4; i++) {

c[i] = a[i] + b[i];

}

I JIT ≈ 32 machine instructions

I gcc ≈ 24 machine scalar instructions

I gcc – 4 machine instructions with SSE2

Page 14: Ivan mamontov and Mikhail Khuldnev Present : Fast Decompression Lucene Codec

14/30

Scalar vs. Vectors

A0 + B0 = C0

A1 + B1 = C1

A2 + B2 = C2

A3 + B3 = C3

A0

A1

A2

A3

B0

B1

B2

B3

C0

C1

C2

C3

+ =

Page 15: Ivan mamontov and Mikhail Khuldnev Present : Fast Decompression Lucene Codec

15/30

Scalar vs. Vectors

I 75% fewer loads

I 75% fewer adds

I 75% fewer stores

Page 16: Ivan mamontov and Mikhail Khuldnev Present : Fast Decompression Lucene Codec

16/30

Vectorization in HotSpot

I auto-vectorization – vector arithmetic is not supported yet.Only array initialization and array copy.

I http://bugs.java.com/view_bug.do?bug_id=6340864I http://bugs.java.com/view_bug.do?bug_id=7192383

I explicit vectorization – JVM does not provide interfaces

Page 17: Ivan mamontov and Mikhail Khuldnev Present : Fast Decompression Lucene Codec

17/30

Workaround

I write kernel code in C/C++

I call via JNI

The cost of the JNI call can be significant.

Page 18: Ivan mamontov and Mikhail Khuldnev Present : Fast Decompression Lucene Codec

17/30

Workaround

I write kernel code in C/C++

I call via JNI

The cost of the JNI call can be significant.

Page 19: Ivan mamontov and Mikhail Khuldnev Present : Fast Decompression Lucene Codec

18/30

What makes JNI calls slow?

I Wrap object references to JNI handles.

I Obtain JNIEnv*, jclass/jobject and pass them as parameters.

I Lock an object monitor if the method is synchronized.

I Call the native function.

I Check if safepoint is needed.

I Unlock monitor if locked.

I Unwrap object result and reset JNI handles block.

I Handle JNI exceptions.

Page 20: Ivan mamontov and Mikhail Khuldnev Present : Fast Decompression Lucene Codec

19/30

Java Critical Native

Page 21: Ivan mamontov and Mikhail Khuldnev Present : Fast Decompression Lucene Codec

20/30

JDK-7013347 Critical Native

Critical native looks like JNI method:

I static and not synchronized

I not throw exceptions

I does not use wrappers

I works with primitives

See details in JDK-7013347

Page 22: Ivan mamontov and Mikhail Khuldnev Present : Fast Decompression Lucene Codec

21/30

Benchmarks

Page 23: Ivan mamontov and Mikhail Khuldnev Present : Fast Decompression Lucene Codec

22/30

Native FOR

A simple C library for compressing lists of integershttps://github.com/lemire/simdcomp (thanks to DanielLemire, Leonid Boytsov)

I supports SSE2, SSE4.1, AVX

I uses C99 syntax

I uses SIMD intrinsics

Page 24: Ivan mamontov and Mikhail Khuldnev Present : Fast Decompression Lucene Codec

23/30

Microbenchmark

I java codeI java vint – classic vint implementationI java FOR – classic FOR implementation

I JNI + native FOR implementationI normal JNI – usual JNI callI critical JNI – critical native call

Environment

I i5-4300M CPU @ 2.60GHz (Haswell)I fedora 21 (kernel 3.17.4)I JRE 1.8.0 40I gcc 4.9.2

Decodes blocks with fixed sizeEvery block contains random elements with fixed density

Page 25: Ivan mamontov and Mikhail Khuldnev Present : Fast Decompression Lucene Codec

24/30

Microbenchmark

128 256 512 1024 2048 4096 8192 16384

60

120

240

480

960

1920

3840

7680

15360

30720

Block size

Dec

od

ing

late

ncy

,n

s/op

critical JNInormal JNIjava FORjava vbyte

Page 26: Ivan mamontov and Mikhail Khuldnev Present : Fast Decompression Lucene Codec

25/30

SIMD codec

I based on Lucene50 codec

I uses https://github.com/lemire/simdcomp as nativeFOR implementation

I still in progress so it does not supportI freqsI positionsI offsetsI payloads

Source code available at http://git.io/vkY1o

Page 27: Ivan mamontov and Mikhail Khuldnev Present : Fast Decompression Lucene Codec

26/30

Lucene benchmark

I indexes all of Wikipedia’s English XML exportI only documents are indexed: term frequencies and positions

are omittedI one large segment is used(about 1GB)

I measures how long it takes to search top 10K frequent termsI environment

I i5-4300M CPU @ 2.60GHz (Haswell)I fedora 21 (kernel 3.17.4)I JRE 1.8.0 40I gcc 4.9.2

I ant run-task -Dtask.alg=conf/searchOnlyWiki.alg-Dtask.mem=8G

Page 28: Ivan mamontov and Mikhail Khuldnev Present : Fast Decompression Lucene Codec

27/30

Benchmark results

49sSIMDCodec

60sLucene50

30s 35s 40s 45s 50s 55s 60s 65s

Page 29: Ivan mamontov and Mikhail Khuldnev Present : Fast Decompression Lucene Codec

28/30

Future work

I Fast compression and intersection of lists of sorted integershttps://github.com/lemire/

SIMDCompressionAndIntersection

I Fast decoder for VByte-compressed integershttps://github.com/lemire/MaskedVByte

I Native roaring codec

I Native facet component

I Native docvalues decoder

Page 30: Ivan mamontov and Mikhail Khuldnev Present : Fast Decompression Lucene Codec

29/30

Thank you!