SlideShare a Scribd company logo
1 of 35
Download to read offline
Кеширование данных вне 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

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

What's hot (20)

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

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

андрей паньгин
андрей паньгинандрей паньгин
андрей паньгинkuchinskaya
 
Как мы храним и анализируем большой социальный граф, Максим Бартенев (Норси-т...
Как мы храним и анализируем большой социальный граф, Максим Бартенев (Норси-т...Как мы храним и анализируем большой социальный граф, Максим Бартенев (Норси-т...
Как мы храним и анализируем большой социальный граф, Максим Бартенев (Норси-т...Ontico
 
Hosting for forbes.ru_
Hosting for forbes.ru_Hosting for forbes.ru_
Hosting for forbes.ru_drupalconf
 
Вячеслав Бирюков - Как Linux работает с памятью
Вячеслав Бирюков - Как Linux работает с памятьюВячеслав Бирюков - Как Linux работает с памятью
Вячеслав Бирюков - Как Linux работает с памятьюYandex
 
Егор Львовский — «Кеширование на клиенте и сервере»
Егор Львовский — «Кеширование на клиенте и сервере»Егор Львовский — «Кеширование на клиенте и сервере»
Егор Львовский — «Кеширование на клиенте и сервере»Yandex
 
ekbpy'2012 - Данила Штань - Распределенное хранилище
ekbpy'2012 - Данила Штань - Распределенное хранилищеekbpy'2012 - Данила Штань - Распределенное хранилище
ekbpy'2012 - Данила Штань - Распределенное хранилищеit-people
 
CodeFest 2013. Иванов В. — Уменьшение расхода оперативной памяти в Java-прило...
CodeFest 2013. Иванов В. — Уменьшение расхода оперативной памяти в Java-прило...CodeFest 2013. Иванов В. — Уменьшение расхода оперативной памяти в Java-прило...
CodeFest 2013. Иванов В. — Уменьшение расхода оперативной памяти в Java-прило...CodeFest
 
TMPA-2013 Sartakov: Genode
TMPA-2013 Sartakov: GenodeTMPA-2013 Sartakov: Genode
TMPA-2013 Sartakov: GenodeIosif Itkin
 
Как Linux работает с памятью — Вячеслав Бирюков
Как Linux работает с памятью — Вячеслав БирюковКак Linux работает с памятью — Вячеслав Бирюков
Как Linux работает с памятью — Вячеслав БирюковYandex
 
Безопасность без антивирусов 4
Безопасность без антивирусов 4Безопасность без антивирусов 4
Безопасность без антивирусов 4Positive Hack Days
 
Оптимизация программ для современных процессоров и Linux, Александр Крижановс...
Оптимизация программ для современных процессоров и Linux, Александр Крижановс...Оптимизация программ для современных процессоров и Linux, Александр Крижановс...
Оптимизация программ для современных процессоров и Linux, Александр Крижановс...Ontico
 
Ускоряем и разгружаем веб-сервер, прозрачно кэшируя на SSD, Станислав Николов...
Ускоряем и разгружаем веб-сервер, прозрачно кэшируя на SSD, Станислав Николов...Ускоряем и разгружаем веб-сервер, прозрачно кэшируя на SSD, Станислав Николов...
Ускоряем и разгружаем веб-сервер, прозрачно кэшируя на SSD, Станислав Николов...Ontico
 
Java Platform Performance BoF
Java Platform Performance BoFJava Platform Performance BoF
Java Platform Performance BoFDmitry Buzdin
 
Multithreading in JS. Myth or reality?
Multithreading in JS. Myth or reality?Multithreading in JS. Myth or reality?
Multithreading in JS. Myth or reality?Alexander Syrotenko
 
Лекция 4: Оптимизация доступа к памяти (Memory access optimization, caches)
Лекция 4: Оптимизация доступа к памяти (Memory access optimization, caches)Лекция 4: Оптимизация доступа к памяти (Memory access optimization, caches)
Лекция 4: Оптимизация доступа к памяти (Memory access optimization, caches)Mikhail Kurnosov
 
20100307 virtualization igotti_lecture04
20100307 virtualization igotti_lecture0420100307 virtualization igotti_lecture04
20100307 virtualization igotti_lecture04Computer Science Club
 
Спасение 6 миллионов файлов в условиях полного Хецнера
Спасение 6 миллионов файлов в условиях полного ХецнераСпасение 6 миллионов файлов в условиях полного Хецнера
Спасение 6 миллионов файлов в условиях полного ХецнераDaniel Podolsky
 
Smirnov Memcached High Load 2008
Smirnov Memcached High Load 2008Smirnov Memcached High Load 2008
Smirnov Memcached High Load 2008Ontico
 

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

андрей паньгин
андрей паньгинандрей паньгин
андрей паньгин
 
Как мы храним и анализируем большой социальный граф, Максим Бартенев (Норси-т...
Как мы храним и анализируем большой социальный граф, Максим Бартенев (Норси-т...Как мы храним и анализируем большой социальный граф, Максим Бартенев (Норси-т...
Как мы храним и анализируем большой социальный граф, Максим Бартенев (Норси-т...
 
Hosting for forbes.ru_
Hosting for forbes.ru_Hosting for forbes.ru_
Hosting for forbes.ru_
 
Вячеслав Бирюков - Как Linux работает с памятью
Вячеслав Бирюков - Как Linux работает с памятьюВячеслав Бирюков - Как Linux работает с памятью
Вячеслав Бирюков - Как Linux работает с памятью
 
Егор Львовский — «Кеширование на клиенте и сервере»
Егор Львовский — «Кеширование на клиенте и сервере»Егор Львовский — «Кеширование на клиенте и сервере»
Егор Львовский — «Кеширование на клиенте и сервере»
 
ekbpy'2012 - Данила Штань - Распределенное хранилище
ekbpy'2012 - Данила Штань - Распределенное хранилищеekbpy'2012 - Данила Штань - Распределенное хранилище
ekbpy'2012 - Данила Штань - Распределенное хранилище
 
CodeFest 2013. Иванов В. — Уменьшение расхода оперативной памяти в Java-прило...
CodeFest 2013. Иванов В. — Уменьшение расхода оперативной памяти в Java-прило...CodeFest 2013. Иванов В. — Уменьшение расхода оперативной памяти в Java-прило...
CodeFest 2013. Иванов В. — Уменьшение расхода оперативной памяти в Java-прило...
 
TMPA-2013 Sartakov: Genode
TMPA-2013 Sartakov: GenodeTMPA-2013 Sartakov: Genode
TMPA-2013 Sartakov: Genode
 
Как Linux работает с памятью — Вячеслав Бирюков
Как Linux работает с памятью — Вячеслав БирюковКак Linux работает с памятью — Вячеслав Бирюков
Как Linux работает с памятью — Вячеслав Бирюков
 
An internal look at HotSpot JVM
An internal look at HotSpot JVMAn internal look at HotSpot JVM
An internal look at HotSpot JVM
 
Безопасность без антивирусов 4
Безопасность без антивирусов 4Безопасность без антивирусов 4
Безопасность без антивирусов 4
 
Оптимизация программ для современных процессоров и Linux, Александр Крижановс...
Оптимизация программ для современных процессоров и Linux, Александр Крижановс...Оптимизация программ для современных процессоров и Linux, Александр Крижановс...
Оптимизация программ для современных процессоров и Linux, Александр Крижановс...
 
Ускоряем и разгружаем веб-сервер, прозрачно кэшируя на SSD, Станислав Николов...
Ускоряем и разгружаем веб-сервер, прозрачно кэшируя на SSD, Станислав Николов...Ускоряем и разгружаем веб-сервер, прозрачно кэшируя на SSD, Станислав Николов...
Ускоряем и разгружаем веб-сервер, прозрачно кэшируя на SSD, Станислав Николов...
 
Java Platform Performance BoF
Java Platform Performance BoFJava Platform Performance BoF
Java Platform Performance BoF
 
Multithreading in JS. Myth or reality?
Multithreading in JS. Myth or reality?Multithreading in JS. Myth or reality?
Multithreading in JS. Myth or reality?
 
Лекция 4: Оптимизация доступа к памяти (Memory access optimization, caches)
Лекция 4: Оптимизация доступа к памяти (Memory access optimization, caches)Лекция 4: Оптимизация доступа к памяти (Memory access optimization, caches)
Лекция 4: Оптимизация доступа к памяти (Memory access optimization, caches)
 
20100307 virtualization igotti_lecture04
20100307 virtualization igotti_lecture0420100307 virtualization igotti_lecture04
20100307 virtualization igotti_lecture04
 
Спасение 6 миллионов файлов в условиях полного Хецнера
Спасение 6 миллионов файлов в условиях полного ХецнераСпасение 6 миллионов файлов в условиях полного Хецнера
Спасение 6 миллионов файлов в условиях полного Хецнера
 
Cache in web (Secon 2008)
Cache in web (Secon 2008)Cache in web (Secon 2008)
Cache in web (Secon 2008)
 
Smirnov Memcached High Load 2008
Smirnov Memcached High Load 2008Smirnov Memcached High Load 2008
Smirnov Memcached High Load 2008
 

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/ • Контакты – andrey.pangin@odnoklassniki.ru • Работа в Одноклассниках – http://v.ok.ru 34