• Save
How to improve java performance
Upcoming SlideShare
Loading in...5
×

Like this? Share it with your network

Share

How to improve java performance

  • 557 views
Uploaded on

мастер-класс Devexperts: «Оптимизация на халяву, или как повысить производительность Java»

мастер-класс Devexperts: «Оптимизация на халяву, или как повысить производительность Java»

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
    Be the first to like this
No Downloads

Views

Total Views
557
On Slideshare
484
From Embeds
73
Number of Embeds
1

Actions

Shares
Downloads
0
Comments
0
Likes
0

Embeds 73

http://www.devexperts.com 73

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide
  • Всем привет! Меня зовут Сергей Ляджин, я ведущий разработчик компании Devexperts и в ближайший час я расскажу вам о нескольких несложных трюках разработки высокопроизводительных систем на Java и не только. Мы делали этот доклад с моим коллегой Алексеем Николаенковым в прошлом году, получили положительные отзывы и по просьбам трудящихся выступаем на бис. Правда, Алексея сегодня, к сожаления, нету, но я постараюсь его заменить.
  • Прежде чем мы перейдем к сути нашего доклада, позвольте вам немного рассказать о нашей компании. Компания Devexperts существует уже больше десяти лет. Мы специализируемся на разработке ПО для финансового рынка: брокеров и бирж. На наших продуктах работают крупнейшие американские и российские игроки этого рынка. Мы делаем десктопные, мобильные и веб GUI приложения, сложные распределенные и многопоточные серверные системы. Используем наиболее адекватные и современные технологии, постоянно обучаясь чему то новому и делясь опытом с коллегами.
  • В нашей компании работает более 300 профессионалов своего дела. Это, конечно же, разработчики, тестировщики и специалисты по поддержке и внедрению. У нас дружный коллектив: мы вместе работаем и вместе отдыхаем – играем в настольные игры, воллейбол, футбол, теннис, катаемся на великах, ну и просто ходим пить пиво.
  • Наш главный офис расположен, конечно же, в Санкт-Петебурге на Петроградке, но кроме того у нас есть офис в Ростове-на-Дону и офисы продаж в разных городах мира.
  • Мы предлагаем нашим сотрудникам отличные условия работы. В наш соц. пакет входят, разумеется, полностью белая ЗП, своя столовая, ДМС, свободный график работы, удобные рабочие места. Мы поддерживаем студентов, предлагая им возможность учебных отпусков и поддержку в написании работ. В конце доклада я еще немного расскажу об открытых у нас на данный момент вакансиях, а наши дорогие HR -ы с удовольствием ответят на все ваши вопросы о компании и вакансии, если такие появятся.
  • Ну что же. Давайте теперь перейдем к делу. Сейчас я расскажу вам о трех небольших оптимизационных трюках, покажу и объясню как и почему они работают. Можете мне задавать вопросы по ходу дела. Лучше каверзные, на которые я не знаю ответа, так будет веселее, и я тоже узнаю что-нибудь новенькое =)
  • Первое с чего бы хотелось начать – это с двух простых правил оптимизации. На этом слайде представлены два известных правила оптимизации Майкла Джексона (нет, не того, о котором вы вероятно подумали). Первое правило оптимизации - не занимайтесь ей. Второе, если вы эксперт – не занимайтесь ей пока. Почему не заниматься и почему пока? Если вы еще не знаете, то подумайте до конца доклада, а в конце я вам расскажу =)
  • И так, наша первая тема - казалось бы, простая и банальная задача, до боли знакомая любому Java , и не только, программисту – обход списков. У вас есть список объектов, вам надо перебрать все или часть его элементов, чтобы что-то найти или посчитать.
  • Надеюсь, что вы все хорошо знаете интерфейс List из Java API и его реализации . Значит, наша цель – имея объект – список элементов, реализующий интерфейс List, максимально быстро обойти его. Берем две реализации интерфейса списка List, доступные в Java API изпокон веков – ArrayList и LinkedList. Внутри ArrayList находится массив ссылок на объекты – элементы списка, а внутри LinkedList находится двойной связный список, представленный набором объектов внутреннего класса LinkedList.Node , ссылающихся друг на друга и на элементы списка. Вначале мы последовательно заполним списки числами, а затем будем последовательно итерироваться по элементам этих списков, используя объект Iterator . Из теории известно, что обе реализации позволяют нам сделать обход списка за O(N) операций. Внимание, вопрос – есть ли разница на практике? Поднимите руки кто считает, что LinkedList проявит себя быстрее, а кто считает, что ArrayList? А остальные? ... << Демонстрируем код. Создаем список, заполняем 5М элементами, дальше итерируемся по списку с помощью итератора. Делаем 100 раз, чтобы получить усредненное время выполнения. Выводим среднее время в миллисекундах. Первым в гонке участвует LinkedList. Затем ArrayList. Получаем в 2 раза быстрее. >>
  • На диаграмме видим разницу во времени выполнения в зависимости от количества элементов в списке. Разница в 2-4 раза. На 20М элементов итерация по LinkedList занимает более четверти секунды, что может оказаться крайне существенным при обработке транзакции в высоконагруженной системе.
  • Если посмотреть еще раз внимательно на код, то видно, что в список мы добавляем не числа примитивного типа int , а объекты класса Integer. Каждый раз когда добавляем – создаем новый объект. В структурах списков хранятся не числа, а ссылки на объекты. В случае ArrayList ссылки хранятся в массиве, в случае LinkedList ссылка хранится в поле объекта класса Node. Соотвественно при итерации по массиву мы читаем ссылку из элемента массива и достаем объект по ссылке. В случае LinkedList мы читаем ссылку на следующий элемент списка, достаем элемент списка по ссылке из него читаем ссылку на наш объект и только после этого достаем объект. Чуть больше операций. Но только ли в этом дело или может быть здесь есть чтото еще?
  • Давайте попробуем немного усложнить наш эксперимент. До этого мы заполняли списки последовательно. Давайте теперь попробуем перемешать списки. В Java Collections API для этого есть стандартный метод Collections.shuffle(). Воспользуемся им и посмотрим что получается. LinkedList , а потом ArrayList. < переключаемся на код > Видим, что все замедлилось в 4 раза.
  • Вернемся к нашим картинкам. При последовательно заполненных списках, каждый последующий элемент списка указывает на объект, который был создан в памяти сразу после текущего объекта. Что же произошло после того как мы вызвали shuffle? Теперь элементы списка указывают на объекты расположенные в случайном порядке. Как это может влиять на производительность обхода списка? Для ответа на этот вопрос давайте немного отойдем от списков в сторону и посмотрим на устройство памяти современного компьютера.
  • В современнных компьютерах есть разные виды памяти с разными свойствами, есть регистры центрального процессора, его кэши, оперативная память и дисковая подсистема. Все эти виды памяти можно выстроить вот в такую пирамиду. Скорость доступа к памяти падает по мере спуска вниз по ней. Самыми быстрыми являются регистры центрального процессора, расположенные на том же кристалле, дальше идут кэши процессора и. А объем памяти наоброт увеличивается, регистры имеют разбер 64бита , кэши исчисляются мебагабайтами, оперативная память гигабайтами, а объемы жестких дисков уже терабайтами. Это всё замечательно скажете вы, но причем тут списки. Дело все в том, что данные с одного уровня памяти на другой подгружаются блоками, т.е. когда мы запрашиваем из оперативной памяти какой то элемент массива то мы подгружаем в кэш сразу кусок массива и при следующем обращении велика вероятность того, что нам не придется обращаться к оперативной памяти.
  • Вернемся к нашим картинкам. При последовательно заполненных списках, каждый последующий элемент списка указывает на объект, который был создан в памяти сразу после текущего объекта. Что же произошло после того как мы вызвали shuffle? Теперь элементы списка указывают на объекты расположенные в случайном порядке. Как это может влиять на производительность обхода списка? Для ответа на этот вопрос давайте немного отойдем от списков в сторону и посмотрим на устройство памяти современного компьютера.
  • Какие выводы из всего этого? Во-первых, мы увидели, что при любых обстоятельствах итерирование по ArrayList происходит в 2-4 раза быстрее. Во-вторых, если вы хотите выжать максимум, то добивайтесь локальности объектов – элементов ArrayList в памяти, т.е. добивайтесь того, что память под них была выделена в одном месте. Как это сделать? Создавать объекты единомоменты
  • Программа представлена большим-большим графом и в каждой точке выполнения устройству нужно определить куда же выполнение пойдет дальше, чтобы прочитать вперед, чтобы конвеер хорошо работал. Для определения используются схемы предсказания переходов, они могут как совсем простыми (например, считать что переход всегда осуществиться), так и более сложными (например, собирающие и использующие статистику выполненных переходов) << Давайте посмотрим на код и я попытаюсь объяснить на примере что же происходило >> << А теперь давайте вспоним с чего мы начали говорить об этой задаче, а начали мы с того, что хорошее решение задачи может лежать совсем в другой плоскости, нежели вам кажется на первый взгляд >>
  • Работая с TCP соединением, мало кто задумывается, что приходится иметь дело с “ наглым ” алгоритмом. Рассмотрим пример : установка сокетного соединения и отправка по нему сообщения – массива байт. Как вы знаете, данные по TCP отправляются пачками, так называемыми TCP- сегментами. Может показаться, что наши байтики полетят по сети сразу же после этого действия (write) – но это может оказаться и не так, ведь в действие вступает Nagle алгоритм (придуман by John Nagle ) который будет ждать полного заполнения сегмента данными (его default размер обычно 536 байт ) пока не получено подтверждение от принимающей стороны ( ACK- acknowledgement ) о получении отправленных ранее сегментов. После того, как подтверждение получено, наши данные отправляются по сети. Помните, что в java Nagle алгоритм включен по дефолту. Но не всех такой подход может устраивать, ведь если вам нужно отправить небольшие сообщения с минимальной задержкой (например котировки – очень важно каждую котировку доставить быстрее), хотелось бы такой алгоритм отключить. _____________________________________________________________________________________________________________ Важные моменты: Если в network pipe нет пакетов по которым еще не пришел ACK, то первый TCP сегмент отправится без задержки Сегмент отправляется без задержки при его полном заполнении By default наглый алгоритм включен ! Что делать если приходы сообщений происходит Упростить метрики измерений. Коммент о том что делает код, убрать время. + мысль о том как на халяву можно ускорить
  • Java API по работе с сокетами предлагает нам метод для отключения Nagle алгоритма – называется setTcpNoDelay.
  • Этот слайд нужно проскочить, если тест сработал. Давайте рассмотрим На хорошем соединении, число сообщений пришедших в одну миллисекунду меньше в 3 раза, а время обработки почти такое же. _______________________________________________________________________ Параметры доступа к серверу [email_address] pass: X7RRDvyv6vch Зайдя сказать java TcpServer Это запустит сервер, который будет слушать на порту 10000 Если процесс остался работать с прошлого раза, сервер не запустится сетуя на то что на порту 10000 уже кто-то слушает. Нужно грокнуть процесс найдя его через ps aux и kill pid _______________________________________________________________________
  • _______________________________________________________________________ Параметры доступа к серверу [email_address] pass: X7RRDvyv6vch Зайдя сказать java TcpServer Это запустит сервер, который будет слушать на порту 10000 Если процесс остался работать с прошлого раза, сервер не запустится сетуя на то что на порту 10000 уже кто-то слушает. Нужно грокнуть процесс найдя его через ps aux и kill pid _______________________________________________________________________
  • Даже если Вы не видите подходящей вакансии, все равно звоните/пишите и указывайте, что узнали о нас на ярмарке вакансий.

Transcript

  • 1. Сергей Ляджинlyadzhin@devexperts.comОптимизация на халяву,или как повысить производительность Java
  • 2. Мы создаем качественное и эффективное ПО длякомплексной автоматизации брокерской, биржевой и финансовойдеятельностиDevexperts
  • 3. Наша команда – это 300 профессионалов в области программирования,тестирования и поддержки ПО
  • 4. Офисы разработки расположены в Санкт-Петербурге и Ростове-на-Дону!Офисы
  • 5. - свободный график работы- своя столовая- комфортные рабочие места- корпоративные мероприятия- командировки по всему миру- курсы английского языка- неполная занятость и поддержкав написании научных работОтличные условия работы!
  • 6. План
  • 7. The First Rule of Optimization:Dont do it.The Second Rule of Optimization (for experts only!):Dont do it yet.Michael A. Jackson
  • 8. Кто быстрее?
  • 9. • Задача – максимально быстро обойтисписок объектов• Участвуют:• Заполняем числами последовательно• Сложность обхода – O(N) операциймассив двойной-связный списокArrayList LinkedListЗадача: Обход списка
  • 10. • Обход ArrayList быстрее в 2-4 разаРезультаты тестов
  • 11. • В списках хранятся не числа, а ссылки на объектыInteger• ArrayList - элемент массива + объект по ссылке• LinkedList - ссылка на след. элемент + элемент поссылке + ссылка на объект + объект по ссылкеРеализация
  • 12. • Collections.shuffle()• Замедление в 5-10 раз• В случае перемешанного LinkedListполучаем уже 1.5с20M ArrayList LinkedListИсходный 0.07с 0.27сПеремешанный 0.61с 1.50сПеремешиваем списки
  • 13. • Объекты расположены последовательно• Объекты расположены хаотичноПроанализируем
  • 14. • Объем увеличивается, а скорость доступауменьшается• Данные подгружаются блокамиоченьбыстрооченьмедленноИерархия памяти
  • 15. • Последующие элементы попадают в кэш CPU• Элементы в кэш не попадаютКэширование
  • 16. • Итерирование по ArrayList в 2-4 разабыстрее LinkedList• Для ускорения итерации по ArrayListдобивайтесь локальности объектов-элементов в памятиВыводы: ArrayList vs. LinkedList
  • 17. TALK IS CHEAP. SHOW ME THECODE.
  • 18. Схема вычислений
  • 19. ABСA B CПрограмма:Вычислительное устройствоПоследовательное выполнение
  • 20. ABСB CПрограмма:Вычислительное устройствоAAПоследовательное выполнение
  • 21. CABСBПрограмма:Вычислительное устройствоBAПоследовательное выполнение
  • 22. CABСBПрограмма:Вычислительное устройствоCAПоследовательное выполнение
  • 23. CABСBПрограмма:Вычислительное устройствоAПоследовательное выполнение
  • 24. ABСA B CПрограмма:Вычислительное устройствоКонвейерКонвейерЕщё в начале XX века с помощьюконвейера Г. Форд в разыувеличивал производительностьтруда.Вычислительная техника дошладо этого только в 80х.
  • 25. ABСПрограмма:Вычислительное устройствоКонвейерACBAКонвейер
  • 26. CABСA BПрограмма:Вычислительное устройствоКонвейерB AКонвейер
  • 27. ABСA B CПрограмма:Вычислительное устройствоКонвейерC B AКонвейер
  • 28. ABСA B CПрограмма:Вычислительное устройствоКонвейерC B AКонвейер
  • 29. ABСA B CПрограмма:Вычислительное устройствоКонвейерC B AКонвейер
  • 30. ABСB CПрограмма:Вычислительное устройствоКонвейерC BAКонвейер
  • 31. ABСCПрограмма:Вычислительное устройствоКонвейерCA BКонвейер
  • 32. ABСCПрограмма:Вычислительное устройствоКонвейерA BКонвейерПрограмма выполнена!•Время выполнения одной командыпрежнее•Общее количество выполненныхкоманд больше!
  • 33. ВремяВремяA B CABCПоследовательное выполнениеВыполнение с использованием конвейераАнализ•Время выполнения одной командыпрежнее•Общее количество выполненныхкоманд больше!
  • 34. ABСA B CПрограмма:Вычислительное устройствоКонвейерA B CДва прохода
  • 35. ABСПрограмма:Вычислительное устройствоКонвейерCABACBAДва прохода
  • 36. ABСAПрограмма:Вычислительное устройствоКонвейерCB ABACBДва прохода
  • 37. ABСA BПрограмма:Вычислительное устройствоКонвейерCC B ABACДва прохода
  • 38. ABСA B CПрограмма:Вычислительное устройствоКонвейерCA C B ABAДва прохода
  • 39. ABСA B CПрограмма:Вычислительное устройствоКонвейерA CB A C B ABДва прохода
  • 40. ABСB CПрограмма:Вычислительное устройствоКонвейерA CC B A C BBAДва прохода
  • 41. ABСB CПрограмма:Вычислительное устройствоКонвейерA CC B A C BBAn < 0!Два прохода
  • 42. ABСCПрограмма:Вычислительное устройствоКонвейерA CC B A C BBAn < 0!BРабота проделана впустую!Необходимо пересмотретьпорядок выполнения команд.Два прохода
  • 43. ABСAПрограмма:Вычислительное устройствоКонвейерB CA BПрограмма изменена.Выполнение надо начинать заново.Два прохода
  • 44. ABСПрограмма:Вычислительное устройствоКонвейерCA BABAДва прохода
  • 45. ABСAПрограмма:Вычислительное устройствоКонвейерCA BB ABДва прохода
  • 46. ABСAПрограмма:Вычислительное устройствоКонвейерB CA BC B AДва прохода
  • 47. ABСAПрограмма:Вычислительное устройствоКонвейерB CA BC B AДва прохода
  • 48. ABСAПрограмма:Вычислительное устройствоКонвейерB CA BC B AДва прохода
  • 49. ABСAПрограмма:Вычислительное устройствоКонвейерB CA BC BДва прохода
  • 50. ABСAПрограмма:Вычислительное устройствоКонвейерB CA BCДва прохода
  • 51. ABСAПрограмма:Вычислительное устройствоКонвейерB CA BДва проходаПрограмма выполнена!•Часть работы была сделанавпустую•Как бороться? (позже)
  • 52. ВремяВремяA B CABCПоследовательное выполнениеВыполнение с использованием конвейераABCАнализ
  • 53. CABCВремяВремяA B CABПоследовательное выполнениеВыполнение с использованием конвейераВыяснили, что порядоквыполнения будет другимАнализ
  • 54. CABCВремяВремяA B CABПоследовательное выполнениеВыполнение с использованием конвейераВыполнять команды надобыло в другом порядке!Анализ
  • 55. ВремяВремяA B CABПоследовательное выполнениеВыполнение с использованием конвейераНачнем выполнять сначала вправильном порядке!CABABCМожно былоделатьполезнуюработуАнализ
  • 56. if(condition) {A, C, F;} else {B;if(condition) {D, C, F;} else {E, G;}}Возможны пути:•S-ACF-E•S-BDCF-E•S-BEG-EПредсказание переходов?
  • 57. • Микрооптимизацияиногда оправдана• Запаспроизводительностиможет находитсяза границами платформыВыводы
  • 58. Наглый алгоритмNagle’s алгоритм: ожидание подтверждениядоставки предыдущего сегмента перед отправкойновогоwrite(1,2,3) write(4,5) write(6,7,8)TCP Segment1 2 3TCP Segment4 5TCP ACKfor 1,2,3TCP Segment4 5 6 7 8Network Pipet
  • 59. Включаем TCP_NO_DELAYsetTcpNoDelay(true) выключает Nagle алгоритмwrite(1,2,3) write(4,5) write(6,7,8)Network PipeTCP Segment1 2 3TCP Segment4 5TCP Segment6 7 8t
  • 60. Тест: Получение TCP сегментовсерверомtMessage4Message 5Message1Message 2Message 3tMessage 4Message1 Message2 Message 3Nagle isonNagle isoff1 ms 2 ms1 ms 2 ms
  • 61. Nagle isonNagle is offТест на быстром соединении
  • 62. •Используйте TCP_NO_DELAY когда нужноминимизировать задержки отправки каждогосообщенияLatency vs Throughput•Если требуется добиться максимальнойпропускной способности или медленная сеть,лучше держать опцию TCP_NO_DELAYвыключенной
  • 63. "We should forget about small efficiencies, say about 97%of the time: premature optimization is the root of all evil"Donald Knuth
  • 64. Если Вам захотелось присоединиться к команде Devexperts,пишите и звоните нам:Тел.: (812) 438-16-26E-mail: job@devexperts.comВакансии: hh.ru и itmozg.ru.Наши новости: devexperts.com и ВКонтакте.Контакт
  • 65. СпасибоСергей Ляджинlyadzhin@devexperts.com