SlideShare a Scribd company logo
Кеширование данных вне Java Heap
и работа с разделяемой памятью в Java



Андрей Паньгин
ведущий разработчик
проекта Одноклассники
Содержание


1.   О кешировании в Java
2.   Работа с памятью вне Java Heap
3.   Использование разделяемой памяти в Java
4.   Пример алгоритма кеширования




                                               1
Что кешировать?
• Результаты вычислений
• Данные из медленного хранилища (БД)
                 Numbers everyone should know
      L1 cache reference                             0.5 ns
      Main memory reference                          100 ns
      Compress 1K bytes w/ cheap algorithm         3,000 ns
      Send 2K bytes over 1 Gbps network           20,000 ns
      Read 1 MB sequentially from memory         250,000 ns
      Round trip within same datacenter          500,000 ns
      Read 1 MB sequentially from network     10,000,000 ns
      Read 1 MB sequentially from disk        30,000,000 ns
      Send packet CA->Netherlands->CA        150,000,000 ns

                                                              2
Где кешировать?


• В оперативной памяти
  – Java Heap
  – Off-heap memory
• На диске или флеш-накопителе




                                 3
Решения для кеширования в Java

• Apache Java Caching System
 http://commons.apache.org/jcs/

• Terracota Ehcache
 http://ehcache.org/

• JBoss Cache
 http://www.jboss.org/jbosscache/




                                    4
Стандартизация

• JSR 107: Java Temporary Caching API
  – javax.cache
  – Войдет в Java EE 7


• Реализации
  – Terracota Ehcache
  – Oracle Coherence




                                        5
Содержание


1.   О кешировании в Java
2.   Работа с памятью вне Java Heap
3.   Использование разделяемой памяти в Java
4.   Пример алгоритма кеширования




                                               6
Off-heap

• Почему вне Java Heap?
  – Большие объемы
  – Не оказывает влияния на GC


• Как?
  –   Native код
  –   Direct ByteBuffer
  –   Memory-mapped files
  –   Unsafe


                                 7
Native

• JNI или JNA обертки
• malloc / free
• Платформозависимый код
JNIEXPORT jlong JNICALL
Java_org_test_allocateMemory(JNIEnv* env, jclass cls, jlong size) {
    return (jlong) (intptr_t) malloc((size_t) size);
}

JNIEXPORT void JNICALL
Java_org_test_freeMemory(JNIEnv* env, jclass cls, jlong addr) {
    free((void*) (intptr_t) addr);
}


                                                                  8
Direct ByteBuffer

• Выделение
  – ByteBuffer buf = ByteBuffer.allocateDirect(size);
• Освобождение
  – Автоматически: GC
  – Вручную: ((sun.nio.ch.DirectBuffer) buf).cleaner().clean();
• Размер буфера ≤ 2 GB
• Ограничение на общий объем Direct буферов
  – -XX:MaxDirectMemorySize=



                                                                  9
Memory-mapped file

• FileChannel.map()
• Использование и освобождение
  – Аналогично Direct ByteBuffer
• Размер буфера ≤ 2 GB
• Подходит для персистентных кешей
 RandomAccessFile f =
     new RandomAccessFile("/tmp/cache", "rw");
 ByteBuffer buf = f.getChannel().
     map(FileChannel.MapMode.READ_WRITE, 0, f.length());




                                                       10
Unsafe

• Получение экземпляра sun.misc.Unsafe
  – (Unsafe) getField(Unsafe.class, "theUnsafe").get(null);
• Выделение / освободжение
  – unsafe.allocateMemory(), unsafe.freeMemory()
• Использование
  – unsafe.putByte(), putInt(), putLong() …
  – unsafe.getByte(), getInt(), getLong() …
  – unsafe.copyMemory()
• Нет ограничений
• Зависит от JVM, но есть почти везде

                                                              11
Cache persistence

• Решает проблему «холодного» старта

• Кеш в памяти?
  – Нужны снимки (snapshots)


• Загрузка снимков может занимать время
  – Читать с диска лучше последовательно




                                           12
Snapshots

• Должны быть целостными

• Способы создания снимков
  –   «Stop-the-world» snapshot
  –   Разбивка на сегменты
  –   Memory-mapped files: MappedByteBuffer.force()
  –   Shared memory objects
  –   Copy-on-write



                                                      13
Fork trick

• Метод создания снимков в Tarantool

• fork() создает копию процесса
  –   Практически мгновенно
  –   Страницы памяти помечаются copy-on-write
  –   Родительский процесс продолжает обслуживание
  –   Дочерний процесс делает снимок


• Применимо в POSIX-совместимых ОС

                                                     14
Содержание


1.   О кешировании в Java
2.   Работа с памятью вне Java Heap
3.   Использование разделяемой памяти в Java
4.   Пример алгоритма кеширования




                                               15
Shared Memory

• Механизм IPC
  – POSIX: shm_open + mmap
  – Windows: CreateFileMapping + MapViewOfFile
  – Скорость доступа к оперативной памяти


• Linux
  – /dev/shm
  – shm_open("name", ...) ↔ open("/dev/shm/name", ...)
  – Можно работать как с обычными файлами


                                                         16
Shared Memory в Java/Linux

• Создание / открытие объекта Shared Memory
  RandomAccessFile f =
      new RandomAccessFile("/dev/shm/cache", "rw");
  f.setLength(1024 * 1024 * 1024L);


• read() / write() работает, но медленно
  – в 50 раз медленнее прямого доступа к памяти

• Предпочтительней отобразить разделяемую
  память в адресное пространство процесса

                                                      17
Mapping: легальный способ

• Java NIO API
  – FileChannel.map()


• MappedByteBuffer
• Ограничение ≤ 2 GB




                            18
Mapping: хитрый способ

• Private Oracle API
  – sun.nio.ch.FileChannelImpl
  – Методы map0, unmap0


• Адрес в виде long
• Нет ограничения в 2 GB
• Работает как в Linux, так и в Windows




                                          19
Mapping: пример

// Mapping
Method map0 = FileChannelImpl.class.getDeclaredMethod(
    "map0", int.class, long.class, long.class);
map0.setAccessible(true);
long addr = (Long) map0.invoke(f.getChannel(), 1, 0L, f.length());



// Unmapping
Method unmap0 = FileChannelImpl.class.getDeclaredMethod(
    "unmap0", long.class, long.class);
unmap0.setAccessible(true);
unmap0.invoke(null, addr, length);




                                                                20
Проблема абсолютных адресов

• Только относительная адресация
  – Хранение смещений вместо адресов


• mmap() с фиксированным базовым адресом
  – Возможно в ОС, но не поддерживается в Java


• Relocation
  – Сдвиг всех абсолютных адресов на старте



                                                 21
Malloc

• Распределение памяти в непрерывной области
• Doug Lea's Malloc, tcmalloc...


     16   24        32   48   …   256   384   …    1G




    sz         sz        sz        sz   sz        sz




                                                        22
ByteBuffer vs. Unsafe memory access

• Unsafe.getX, Unsafe.putX – JVM intrinsics
• ByteBuffer несет дополнительные проверки
  – Range check
  – Alignment check
  – Byte order check
• JNIEnv::GetDirectBufferAddress
  public static long getByteBufferAddress(ByteBuffer buffer) {
      Field f = Buffer.class.getDeclaredField("address");
      f.setAccessible(true);
      return f.getLong(buffer);
  }


                                                                 23
Содержание


1.   О кешировании в Java
2.   Работа с памятью вне Java Heap
3.   Использование разделяемой памяти в Java
4.   Пример алгоритма кеширования




                                               24
Постановка задачи

• Задача
  – Кеширование изображений для Download сервера
• Характеристики
  – 2 x Intel Xeon E5620
  – 64 GB RAM
• Нагрузка
  – 70 тыс. запросов в секунду
  – 3 Gbps исходящий трафик



                                               25
Требования

• Требования к системе кеширования
  –   Ключ – 64-bit long, значение – байтовый массив
  –   In-process, in-memory
  –   Эффективное использование RAM (~64 GB)
  –   FIFO или LRU
  –   100+ одновременных потоков
  –   Персистентность
  –   Cache HIT > 90%




                                                       26
Способ реализации

• Непрерывная область памяти с собственным
  аллокатором
• FIFO
• sun.misc.Unsafe
• Shared Memory (/dev/shm)
• Сегментирование ключей по хеш-коду
• Блокировка сегмента через ReadWriteLock



                                         27
Сегменты

• Корзины хеш-таблицы
  – Segment s = segments[key % segments.length];
  – Одинаковый размер (~1 MB)
  – До 50 тыс. сегментов


• Синхронизация через ReadWriteLock
  – Проблема в JDK6: Bug 6625723
  – Альтернатива: Semaphore



                                                   28
Структура сегментов




                      29
Индекс




• Ключи отсортированы
  – бинарный поиск
• Ключи сосредоточены в одной области
  – размещение индекса в кеше процессора



                                           30
Алгоритм GET

1. hash(key) → сегмент
2. Бинарный поиск key в индексе сегмента
3. key найден → offset(value) + length(value)




                                                31
Алгоритм PUT

1. hash(key) → сегмент
2. Сегмент → адрес следующего блока данных
3. Адрес следующего блока += length(value)
4. Линейный поиск по массиву ссылок
   для удаления ключей, чьи данные будут
   перезаписаны
5. Копирование value в область данных
6. Вставка key в индекс


                                         32
Сравнение производительности

• Условия
  – Linux JDK 7u4 64-bit
  – 1 млн. операций
  – 0 – 8 KB values




                               33
Спасибо!

• Примеры
  – https://github.com/odnoklassniki/one-nio
• Статья
  – http://habrahabr.ru/company/odnoklassniki/blog/148139/


• Контакты
  – andrey.pangin@odnoklassniki.ru
• Работа в Одноклассниках
  – http://v.ok.ru



                                                             34

More Related Content

What's hot (20)

PDF
Практика совместного использования Lua и C в opensource спам-фильтре Rspamd /...
Ontico
 
PPTX
Multithreading in java past and actual
Yevgen Levik
 
PPTX
Mysql vs postgresql
Daniel Podolsky
 
PDF
Современная операционная система: что надо знать разработчику / Александр Кри...
Ontico
 
PPTX
Жизнь проекта на production советы по эксплуатации / Николай Сивко (okmeter.io)
Ontico
 
PDF
"Почему язык Lua — это интересно?", Ник Заварицкий, (Mail.ru Group)
Badoo Development
 
PDF
nginx.CHANGES.2015 / Игорь Сысоев, Валентин Бартенев (Nginx)
Ontico
 
PPTX
Java threads - part 2
Nakraynikov Oleg
 
PPTX
Java 8. Thread pools
Nakraynikov Oleg
 
PDF
Реализация восстановления после аварий / Сергей Бурладян (Avito)
Ontico
 
PDF
Очереди и блокировки. Теория и практика / Александр Календарев (ad1.ru)
Ontico
 
PDF
Thread
Alexander Rusin
 
PPT
Проект «Одноклассники» Mail.Ru Group, Андрей Паньгин
EYevseyeva
 
PPTX
Евгений Потапов (Сумма Айти)
Ontico
 
PDF
Производительность запросов в PostgreSQL - шаг за шагом / Илья Космодемьянски...
Ontico
 
PDF
Денис Иванов
CodeFest
 
PDF
noBackend, или Как выжить в эпоху толстеющих клиентов / Самохвалов Николай
Ontico
 
PDF
Владимир Алаев "Разработка на Node.js: инструменты, библиотеки, сервисы"
Yandex
 
PDF
Анатомия веб-сервиса (РИТ-2014)
Andrey Smirnov
 
PPTX
Java threads - part 3
Nakraynikov Oleg
 
Практика совместного использования Lua и C в opensource спам-фильтре Rspamd /...
Ontico
 
Multithreading in java past and actual
Yevgen Levik
 
Mysql vs postgresql
Daniel Podolsky
 
Современная операционная система: что надо знать разработчику / Александр Кри...
Ontico
 
Жизнь проекта на production советы по эксплуатации / Николай Сивко (okmeter.io)
Ontico
 
"Почему язык Lua — это интересно?", Ник Заварицкий, (Mail.ru Group)
Badoo Development
 
nginx.CHANGES.2015 / Игорь Сысоев, Валентин Бартенев (Nginx)
Ontico
 
Java threads - part 2
Nakraynikov Oleg
 
Java 8. Thread pools
Nakraynikov Oleg
 
Реализация восстановления после аварий / Сергей Бурладян (Avito)
Ontico
 
Очереди и блокировки. Теория и практика / Александр Календарев (ad1.ru)
Ontico
 
Проект «Одноклассники» Mail.Ru Group, Андрей Паньгин
EYevseyeva
 
Евгений Потапов (Сумма Айти)
Ontico
 
Производительность запросов в PostgreSQL - шаг за шагом / Илья Космодемьянски...
Ontico
 
Денис Иванов
CodeFest
 
noBackend, или Как выжить в эпоху толстеющих клиентов / Самохвалов Николай
Ontico
 
Владимир Алаев "Разработка на Node.js: инструменты, библиотеки, сервисы"
Yandex
 
Анатомия веб-сервиса (РИТ-2014)
Andrey Smirnov
 
Java threads - part 3
Nakraynikov Oleg
 

Similar to Caching data outside Java Heap and using Shared Memory in Java (20)

PDF
CodeFest 2013. Иванов В. — Уменьшение расхода оперативной памяти в Java-прило...
CodeFest
 
PDF
андрей паньгин
kuchinskaya
 
PDF
"Optimizing Memory Footprint in Java" @ JEEConf 2013, Kiev, Ukraine
Vladimir Ivanov
 
PDF
BigMemory - работа с сотнями миллионов бизнес-объектов / Дмитрий Хмаладзе (Ag...
Ontico
 
PPT
Nio java
Alexey Bovanenko
 
PPT
Куда уходит память?
Dmitriy Dumanskiy
 
PDF
Управление памятью в Java: Footprint
Vladimir Ivanov
 
PDF
Блеск и нищета распределённых кэшей
aragozin
 
PDF
Purely practical data structures
Евгений Лазин
 
PDF
Евгений Лазин. Неизменяемая структура данных HAMT для создания БД в памяти
FProg
 
PDF
Java осень 2014 занятие 6
Technopark
 
PPTX
Programming Java - Lection 01 - Basics - Lavrentyev Fedor
Fedor Lavrentyev
 
PDF
Память в Java. Garbage Collector
Olexandra Dmytrenko
 
PPT
An internal look at HotSpot JVM
Ecommerce Solution Provider SysIQ
 
PPTX
Dz Java Hi Load 0.4
HighLoad2009
 
PDF
Реактивный кэш в Android, Андрей Мельников, Rambler&Co, Москва
it-people
 
PPTX
Распределённый кэш или хранилище данных. Что выбрать?
aragozin
 
PDF
Новые возможности распределенной обработки данных в памяти (Coherence)
Andrey Akulov
 
PDF
Базы данных. Hash & Cache
Vadim Tsesko
 
PPT
phpConf 2010 Классификация систем хранения
Slach
 
CodeFest 2013. Иванов В. — Уменьшение расхода оперативной памяти в Java-прило...
CodeFest
 
андрей паньгин
kuchinskaya
 
"Optimizing Memory Footprint in Java" @ JEEConf 2013, Kiev, Ukraine
Vladimir Ivanov
 
BigMemory - работа с сотнями миллионов бизнес-объектов / Дмитрий Хмаладзе (Ag...
Ontico
 
Куда уходит память?
Dmitriy Dumanskiy
 
Управление памятью в Java: Footprint
Vladimir Ivanov
 
Блеск и нищета распределённых кэшей
aragozin
 
Purely practical data structures
Евгений Лазин
 
Евгений Лазин. Неизменяемая структура данных HAMT для создания БД в памяти
FProg
 
Java осень 2014 занятие 6
Technopark
 
Programming Java - Lection 01 - Basics - Lavrentyev Fedor
Fedor Lavrentyev
 
Память в Java. Garbage Collector
Olexandra Dmytrenko
 
An internal look at HotSpot JVM
Ecommerce Solution Provider SysIQ
 
Dz Java Hi Load 0.4
HighLoad2009
 
Реактивный кэш в Android, Андрей Мельников, Rambler&Co, Москва
it-people
 
Распределённый кэш или хранилище данных. Что выбрать?
aragozin
 
Новые возможности распределенной обработки данных в памяти (Coherence)
Andrey Akulov
 
Базы данных. Hash & Cache
Vadim Tsesko
 
phpConf 2010 Классификация систем хранения
Slach
 
Ad

Caching data outside Java Heap and using Shared Memory in Java

  • 1. Кеширование данных вне Java Heap и работа с разделяемой памятью в Java Андрей Паньгин ведущий разработчик проекта Одноклассники
  • 2. Содержание 1. О кешировании в Java 2. Работа с памятью вне Java Heap 3. Использование разделяемой памяти в Java 4. Пример алгоритма кеширования 1
  • 3. Что кешировать? • Результаты вычислений • Данные из медленного хранилища (БД) Numbers everyone should know L1 cache reference 0.5 ns Main memory reference 100 ns Compress 1K bytes w/ cheap algorithm 3,000 ns Send 2K bytes over 1 Gbps network 20,000 ns Read 1 MB sequentially from memory 250,000 ns Round trip within same datacenter 500,000 ns Read 1 MB sequentially from network 10,000,000 ns Read 1 MB sequentially from disk 30,000,000 ns Send packet CA->Netherlands->CA 150,000,000 ns 2
  • 4. Где кешировать? • В оперативной памяти – Java Heap – Off-heap memory • На диске или флеш-накопителе 3
  • 5. Решения для кеширования в Java • Apache Java Caching System http://commons.apache.org/jcs/ • Terracota Ehcache http://ehcache.org/ • JBoss Cache http://www.jboss.org/jbosscache/ 4
  • 6. Стандартизация • JSR 107: Java Temporary Caching API – javax.cache – Войдет в Java EE 7 • Реализации – Terracota Ehcache – Oracle Coherence 5
  • 7. Содержание 1. О кешировании в Java 2. Работа с памятью вне Java Heap 3. Использование разделяемой памяти в Java 4. Пример алгоритма кеширования 6
  • 8. Off-heap • Почему вне Java Heap? – Большие объемы – Не оказывает влияния на GC • Как? – Native код – Direct ByteBuffer – Memory-mapped files – Unsafe 7
  • 9. Native • JNI или JNA обертки • malloc / free • Платформозависимый код JNIEXPORT jlong JNICALL Java_org_test_allocateMemory(JNIEnv* env, jclass cls, jlong size) { return (jlong) (intptr_t) malloc((size_t) size); } JNIEXPORT void JNICALL Java_org_test_freeMemory(JNIEnv* env, jclass cls, jlong addr) { free((void*) (intptr_t) addr); } 8
  • 10. Direct ByteBuffer • Выделение – ByteBuffer buf = ByteBuffer.allocateDirect(size); • Освобождение – Автоматически: GC – Вручную: ((sun.nio.ch.DirectBuffer) buf).cleaner().clean(); • Размер буфера ≤ 2 GB • Ограничение на общий объем Direct буферов – -XX:MaxDirectMemorySize= 9
  • 11. Memory-mapped file • FileChannel.map() • Использование и освобождение – Аналогично Direct ByteBuffer • Размер буфера ≤ 2 GB • Подходит для персистентных кешей RandomAccessFile f = new RandomAccessFile("/tmp/cache", "rw"); ByteBuffer buf = f.getChannel(). map(FileChannel.MapMode.READ_WRITE, 0, f.length()); 10
  • 12. Unsafe • Получение экземпляра sun.misc.Unsafe – (Unsafe) getField(Unsafe.class, "theUnsafe").get(null); • Выделение / освободжение – unsafe.allocateMemory(), unsafe.freeMemory() • Использование – unsafe.putByte(), putInt(), putLong() … – unsafe.getByte(), getInt(), getLong() … – unsafe.copyMemory() • Нет ограничений • Зависит от JVM, но есть почти везде 11
  • 13. Cache persistence • Решает проблему «холодного» старта • Кеш в памяти? – Нужны снимки (snapshots) • Загрузка снимков может занимать время – Читать с диска лучше последовательно 12
  • 14. Snapshots • Должны быть целостными • Способы создания снимков – «Stop-the-world» snapshot – Разбивка на сегменты – Memory-mapped files: MappedByteBuffer.force() – Shared memory objects – Copy-on-write 13
  • 15. Fork trick • Метод создания снимков в Tarantool • fork() создает копию процесса – Практически мгновенно – Страницы памяти помечаются copy-on-write – Родительский процесс продолжает обслуживание – Дочерний процесс делает снимок • Применимо в POSIX-совместимых ОС 14
  • 16. Содержание 1. О кешировании в Java 2. Работа с памятью вне Java Heap 3. Использование разделяемой памяти в Java 4. Пример алгоритма кеширования 15
  • 17. Shared Memory • Механизм IPC – POSIX: shm_open + mmap – Windows: CreateFileMapping + MapViewOfFile – Скорость доступа к оперативной памяти • Linux – /dev/shm – shm_open("name", ...) ↔ open("/dev/shm/name", ...) – Можно работать как с обычными файлами 16
  • 18. Shared Memory в Java/Linux • Создание / открытие объекта Shared Memory RandomAccessFile f = new RandomAccessFile("/dev/shm/cache", "rw"); f.setLength(1024 * 1024 * 1024L); • read() / write() работает, но медленно – в 50 раз медленнее прямого доступа к памяти • Предпочтительней отобразить разделяемую память в адресное пространство процесса 17
  • 19. Mapping: легальный способ • Java NIO API – FileChannel.map() • MappedByteBuffer • Ограничение ≤ 2 GB 18
  • 20. Mapping: хитрый способ • Private Oracle API – sun.nio.ch.FileChannelImpl – Методы map0, unmap0 • Адрес в виде long • Нет ограничения в 2 GB • Работает как в Linux, так и в Windows 19
  • 21. Mapping: пример // Mapping Method map0 = FileChannelImpl.class.getDeclaredMethod( "map0", int.class, long.class, long.class); map0.setAccessible(true); long addr = (Long) map0.invoke(f.getChannel(), 1, 0L, f.length()); // Unmapping Method unmap0 = FileChannelImpl.class.getDeclaredMethod( "unmap0", long.class, long.class); unmap0.setAccessible(true); unmap0.invoke(null, addr, length); 20
  • 22. Проблема абсолютных адресов • Только относительная адресация – Хранение смещений вместо адресов • mmap() с фиксированным базовым адресом – Возможно в ОС, но не поддерживается в Java • Relocation – Сдвиг всех абсолютных адресов на старте 21
  • 23. Malloc • Распределение памяти в непрерывной области • Doug Lea's Malloc, tcmalloc... 16 24 32 48 … 256 384 … 1G sz sz sz sz sz sz 22
  • 24. ByteBuffer vs. Unsafe memory access • Unsafe.getX, Unsafe.putX – JVM intrinsics • ByteBuffer несет дополнительные проверки – Range check – Alignment check – Byte order check • JNIEnv::GetDirectBufferAddress public static long getByteBufferAddress(ByteBuffer buffer) { Field f = Buffer.class.getDeclaredField("address"); f.setAccessible(true); return f.getLong(buffer); } 23
  • 25. Содержание 1. О кешировании в Java 2. Работа с памятью вне Java Heap 3. Использование разделяемой памяти в Java 4. Пример алгоритма кеширования 24
  • 26. Постановка задачи • Задача – Кеширование изображений для Download сервера • Характеристики – 2 x Intel Xeon E5620 – 64 GB RAM • Нагрузка – 70 тыс. запросов в секунду – 3 Gbps исходящий трафик 25
  • 27. Требования • Требования к системе кеширования – Ключ – 64-bit long, значение – байтовый массив – In-process, in-memory – Эффективное использование RAM (~64 GB) – FIFO или LRU – 100+ одновременных потоков – Персистентность – Cache HIT > 90% 26
  • 28. Способ реализации • Непрерывная область памяти с собственным аллокатором • FIFO • sun.misc.Unsafe • Shared Memory (/dev/shm) • Сегментирование ключей по хеш-коду • Блокировка сегмента через ReadWriteLock 27
  • 29. Сегменты • Корзины хеш-таблицы – Segment s = segments[key % segments.length]; – Одинаковый размер (~1 MB) – До 50 тыс. сегментов • Синхронизация через ReadWriteLock – Проблема в JDK6: Bug 6625723 – Альтернатива: Semaphore 28
  • 31. Индекс • Ключи отсортированы – бинарный поиск • Ключи сосредоточены в одной области – размещение индекса в кеше процессора 30
  • 32. Алгоритм GET 1. hash(key) → сегмент 2. Бинарный поиск key в индексе сегмента 3. key найден → offset(value) + length(value) 31
  • 33. Алгоритм PUT 1. hash(key) → сегмент 2. Сегмент → адрес следующего блока данных 3. Адрес следующего блока += length(value) 4. Линейный поиск по массиву ссылок для удаления ключей, чьи данные будут перезаписаны 5. Копирование value в область данных 6. Вставка key в индекс 32
  • 34. Сравнение производительности • Условия – Linux JDK 7u4 64-bit – 1 млн. операций – 0 – 8 KB values 33
  • 35. Спасибо! • Примеры – https://github.com/odnoklassniki/one-nio • Статья – http://habrahabr.ru/company/odnoklassniki/blog/148139/ • Контакты – [email protected] • Работа в Одноклассниках – http://v.ok.ru 34