Оптимизация производительности Java в AIX: Часть 4. Устранение узких мест ввода/вывода и сети

В этой серии из пяти статей даются советы и описываются приемы, которые обычно используются при настройке Java™-приложений для достижения оптимальной производительности на AIX®. Эта статья посвящена ситуации, когда подсистема ввода/вывода (I/O) или сеть могут стать узким местом.

Амит Матюр, ведущий технический консультант и менеджер по реализации решений, IBM

Амит Матюр (Amit Mathur) работает в группе IBM Solutions Development, занимаясь в основном IBM ISV и возможностями/производительностью приложений на платформе IBM eServer, а также оказывая поддержку пользователям ISV. Пишет статьи и учебные пособия для developerWorks. Амит имеет более чем 14-летний опыт по поддержке разработчиков программного обеспечения и программирования на C/C++, Java, а также баз данных в UNIX и Linux. Он получил степень бакалавра технических наук в области электроники и телекомунникаций в Индии. Связаться с ним можно по адресу amitmat@us.ibm.com.



Сумит Чаула, сертифицированный IT-архитектор IBM и руководитель технической группы, Java Enablement, IBM

Самит Чаула (Sumit Chawla) руководит инициативной группой Java Enablement для IBM eServer (для AIX, Windows и Linux), а также работает консультантом в организации Independent Software Vendors по направлению серверов IBM. Самит имеет степень магистра в области вычислительной техники, обладает более чем 10-летним опытом работы в IT-индустрии, сертифицирован IBM по курсу Application Architect. Он часто пишет статьи для раздела developerWorks eServer. С ним можно связаться по адресу sumitc@us.ibm.com.



28.09.2009

Введение

Это четвертая статья из серии статей о настройке производительности Java на AIX, состоящей из пяти частей. Прежде чем продолжить чтение этой статьи, настоятельно рекомендуется еще раз просмотреть предыдущие статьи этой серии.

В этой статье рассказывается еще о двух областях, которые могут стать узким местом в производительности:

  • сеть;
  • дисковый ввод/вывод (I/O).

Как правило, рассматриваемые проблемы специфичны для AIX и должны быть настроены независимо от приложения Java, поэтому в этой статье, в отличие от двух предыдущих (второй и третьей частей), основное внимание уделяется тому, как получить информацию, требующуюся для процесса настройки. В этой статье содержится всего лишь несколько советов, но общее обсуждение эффективности инструментов в сочетании с этими советами даст достаточно информации для настройки производительности.


Ввод/вывод и сеть как узкое место

В этой статье рассматриваются ситуации, когда узким местом становятся ввод/вывод или сеть.

Из предыдущих статей этой серии можно было узнать, как каждый небольшой компонент вписывается в общую картину. Была сделана попытка разбить советы по областям применения, но эта классификация ни в коей мере не является всеобъемлющей. Для сети и ввода/вывода трудно найти источники проблем, но всё же можно оценить, как они влияют на производительность приложения. Только хорошее знание приложения позволит решить проблему. Например, ранее в этой серии обсуждалась важность проверки того, что куча не разбивается на страницы. Максимальный размер кучи, устанавливаемый переключателем –Xmx, должен быть меньше общего объема физической памяти, установленной в системе (определяется с помощью bootinfo -r или lsattr -El sys0 -a realmem, см. статью AIX Commands you should not leave home without).

Инструменты (например, topas и iostat) могут отобразить активность использования различных дисков, но в большинстве случаев виновником возникновения узкого места является цикл GC или какой-либо известный фрагмент функционального кода, поэтому если вы хорошо знаете приложение, то сможете легко найти узкое место. Инструменты типа filemon подскажут, к каким файлам осуществлялся доступ, позволяя избежать настройки "вслепую". Если производительность Java-приложения упала из-за неправильной конфигурации системы, то надо оценить производительность системы в целом. Например, для устранения узкого места дисковой подсистемы может потребоваться правильно распределить данные или приобрести более быстрые диски. Эта тема, выходящая за рамки этой статьи, подробно раскрывается в книгах из серии IBM Redbooks, например, Understanding IBM eServer pSeries Performance and Sizing.

Настройка сетевых буферов и других параметров сети может существенно повлиять на приложения, активно использующие сеть. Хорошим источником информации по настройке сетевых параметров является раздел Network Tunable Parameters руководства Performance Management Guide. Часто для настройки используются thewall, socketthresh, sbmax, somaxconnect, tcp_sendspace, tcp_recvspace, rfc1323 и т. д. Выдаваемая этими инструментами информация относится не только к AIX или Java, но и к любому приложению, интенсивно использующему сеть, поэтому их использование должно быть первым шагом при настройке производительности.

Далее в этом разделе дается краткое введение в некоторые общие инструменты и в обнаружение проблем, специфичных для Java. Дополнительную информацию можно получить в справочниках AIX 5L Performance Tools Handbook и Understanding IBM eServer pSeries Performance and Sizing.

vmstat

Вы наверняка уже пользовались универсальной командой vmstat. Для информации о вводе/выводе просмотрите значение столбца wa (I/O Wait) в разделе cpu. Если это значение большое, то, скорее всего, диски являются узким местом, и для вывода подробной информации о их вводе/выводе следует запустить iostat.

iostat

Утилита iostat является идеальным инструментом для определения узкого места в подсистеме ввода/вывода. Она отображает процессы чтения и записи для всех дисков. Это прекрасный инструмент для определения ситуации, когда нужно распределить ввод/вывод между несколькими дисками. Кроме того, этот инструмент генерирует такие же отчеты об активности центрального процессора, как и vmstat.

Для начала следует выяснить, что делает система. Для этого введите простую команду iostat -s в момент, когда работает приложение. Пример вывода этой команды:

    tty:      tin         tout   avg-cpu:  % user    % sys     % idle    % iowait
              0.3        232.9              13.8     19.1       27.4      39.6     

    Disks:        % tm_act     Kbps      tps    Kb_read   Kb_wrtn
    hdisk0          28.7     291.4      35.0     176503   2744795
    hdisk1           0.0       0.4       0.0       3537         0
    hdisk7           1.7      34.9       9.8       8920    341112
    hdisk14         24.5     1206.1      36.2    1188404  10904509
    hdisk18          0.0       1.2       0.1      10052      2046
    hdisk8           2.1      36.8      10.5      10808    357910

Чтобы увидеть, долго ли система ожидает выполнения операций ввода/вывода, достаточно посмотреть на значение %iowait. Если система использует страничную подкачку файлов, то это будет видно, но одного этого значения недостаточно для определения того, что происходит с системой. Например, если приложением выполняется последовательная запись файлов, то большое значение %iowait является нормой.

%tm_act показывает процент времени активного использования диска. Трассировка, приведенная выше, показывает очень интересный сценарий – показатель %iowait был близок к 40%, но tm_acts был намного меньше 100%, находясь в районе 30%. К системе, на которой был проведен опыт, был подключен дисковый массив Fibre Channel, и узким местом оказался маршрут до системы хранения SAN. Как только были получены конкретные цифры, все это стало очевидным!

Также можно использовать # iostat -at <interval> <count> или iostat -sat ... которые выводят tps и KBps (а также скорость чтения и записи) для адаптеров. Флаг -s означает, что нужно выдавать общую статистику системы.

netstat

При настройке сети netstat является идеальным инструментом для начала исследования. Команда netstat -m может применяться для мониторинга использования памяти mbuf, что может служить индикатором использования памяти сокетами и сетью. Если используется no -o extendednetstats=1, то команда netstat -m отобразит более подробную информацию, но это может повлиять на производительность, поэтому такой вариант следует использовать только для диагностики. При использовании netstat -m наиболее ценная информация выводится в начале отчета, например:

      67 mbufs in use:
      64 mbuf cluster pages in use
      272 Kbytes allocated to mbufs
      0 requests for mbufs denied
      0 calls to protocol drain routines
      0 sockets not created because sockthresh was reached

и в конце отчета, например:

      Streams mblk statistic failures:
      0 high priority mblk failures
      0 medium priority mblk failures
      0 low priority mblk failures

В AIX 5L Performance Tools Handbook дается хорошее описание параметров, которые следует настроить при обнаружении сбоев в отчете netstat -m. Можно попробовать команду netstat -i x (x необходимо заменить значением интервала сбора данных), чтобы проследить за использованием сети и возможной потерей пакетов. Для приложений, интенсивно использующих сеть, это является первым шагом для проверки отсутствия сбоев.

netpmon

netpmon использует трассировку для получения подробной картины сетевой активности в течение определенного интервала времени. Он также отображает статистику процессов CPU, в которую входят:

  • общее количество процессорного времени, используемого процессом;
  • использование CPU процессом в виде процентной доли общего времени;
  • общее время, в течение которого процесс использовал код, связанный с сетевой работой.

Для начала нужно ввести команду:

netpmon -o /tmp/netpmon.log; sleep 20; trcstop

Эта команда запустит netpmon на 20 секунд, затем остановит ее, используя команду trcstop, и запишет вывод в /tmp/netpmon.log. Из анализа отчета видно, что этот пример является хорошей иллюстрацией для одной из статей "Java Performance tuning":

      Process CPU Usage Statistics:
      -----------------------------
                                                         Network
      Process (top 20)             PID  CPU Time   CPU %   CPU %
      ----------------------------------------------------------
      java                       12192    2.0277   5.061   1.370
      UNKNOWN                    13758    0.8588   2.144   0.000
      gil                         1806    0.0699   0.174   0.174
      UNKNOWN                    18136    0.0635   0.159   0.000
      dtgreet                     3678    0.0376   0.094   0.000
      swapper                        0    0.0138   0.034   0.000
      trcstop                    18460    0.0121   0.030   0.000
      sleep                      18458    0.0061   0.015   0.000

Другая полезная часть трассировки – это использование адаптера:

                            ----------- Xmit -----------   -------- Recv ---------
    Device                   Pkts/s  Bytes/s  Util  QLen   Pkts/s  Bytes/s   Demux
    ------------------------------------------------------------------------------
    token ring 0             288.95    22678  0.0%518.498   552.84    36761  0.0222
    ...
    DEVICE: token ring 0
    recv packets:           11074
      recv sizes (bytes):   avg 66.5    min 52      max 1514    sdev 15.1   
      recv times (msec):    avg 0.008   min 0.005   max 0.029   sdev 0.001  
      demux times (msec):   avg 0.040   min 0.009   max 0.650   sdev 0.028  
    xmit packets:           5788
      xmit sizes (bytes):   avg 78.5    min 62      max 1514    sdev 32.0   
      xmit times (msec):    avg 1794.434 min 0.083   max 6443.266 sdev 2013.966

Здесь слишком много информации, поэтому трудно понять конкретные детали. Попробуем следующую команду:

      netpmon -O so -o /tmp/netpmon_so.txt; sleep 20; trcstop

Флаг "-O so" сосредоточит внимание netpmon на трафике на уровне сокета. Также можно увеличить количество информации о java-процессе:

    PROCESS: java   PID: 12192
    reads:                  2700
      read sizes (bytes):   avg 8192.0  min 8192    max 8192    sdev 0.0    
      read times (msec):    avg 184.061 min 12.430  max 2137.371 sdev 259.156
    writes:                 3000
      write sizes (bytes):  avg 21.3    min 5       max 56      sdev 17.6   
      write times (msec):   avg 0.081   min 0.054   max 11.426  sdev 0.211

Полезно? Сделаем шаг вперед и выясним активность на уровне потока. Для этого нужно добавить ключ "-t" к команде, например:

      netpmon -O so -t -o /tmp/netpmon_so_thread.txt; sleep 20; trcstop

Теперь генерируемый вывод содержит информацию, специфичную для потоков:

            THREAD TID: 114559
    reads:                  9
      read sizes (bytes):   avg 8192.0  min 8192    max 8192    sdev 0.0    
      read times (msec):    avg 988.850 min 19.082  max 2106.933 sdev 810.518
    writes:                 10
      write sizes (bytes):  avg 21.3    min 5       max 56      sdev 17.6   
      write times (msec):   avg 0.389   min 0.059   max 3.321   sdev 0.977

Теперь можно выполнить javadump, выяснить, что это за поток и решить, работает ли он так, как ожидалось, или нет. netpmon особенно полезен для приложений, которые имеют несколько сетевых подключений, – эта команда дает полную картину операций.

filemon

filemon может использоваться для выявления файлов, к которым обращение происходит наиболее часто. Этот инструмент дает весьма полное представление о доступе к файлам и может пригодиться для глубокого исследования после того как vmstat/iostat подтвердили наличие узких мест, связанных с дисками. Это средство также использует трассировку, поэтому оно используется подобно netpmon:

filemon -o /tmp/filemon.log; sleep 60; trcstop

При этом генерируется крайне много информации. Некоторыми разделами, которые могут быть полезны, являются:

    Most Active Files
    ------------------------------------------------------------------------
      #MBs  #opns   #rds   #wrs  file                 volume:inode
    ------------------------------------------------------------------------
      25.7     83   6589      0  unix                 /dev/hd2:147514
      16.3      1   4175      0  vxe102               /dev/mailv1:581
      16.3      1      0   4173  .vxe102.pop          /dev/poboxv:62
      15.8      1      1   4044  tst1                 /dev/mailt1:904
       8.3   2117   2327      0  passwd               /dev/hd4:8205
       3.2    182    810      1  services             /dev/hd4:8652
    ...
    ------------------------------------------------------------------------
    Detailed File Stats
    ------------------------------------------------------------------------

    FILE: /var/spool/mail/v/vxe102  volume: /dev/mailv1 (/var/spool2/mail/v)  inode: 581
    opens:                  1
    total bytes xfrd:       17100800
    reads:                  4175    (0 errs)
      read sizes (bytes):   avg  4096.0 min    4096 max    4096 sdev     0.0
      read times (msec):    avg   0.543 min   0.011 max  78.060 sdev   2.753
    ...

Этот инструмент уже упоминался ранее, а его более подробный обзор выходит за рамки этой статьи.

Советы, специфичные для Java

Общие советы для обнаружения узких мест ввода/вывода и сетевого взаимодействия в Java-приложениях сводятся к хорошему дизайну, и уже довольно хорошо были описаны в других статьях цикла. Например, можно посмотреть советы NI004 и NI005.


Советы по настройке, основанные на характеристиках приложения

Рассмотрим различные характеристики типичных приложений. Необходимо определить поведение приложения (исходя из его архитектуры или путем наблюдения) и применить соответствующие советы.


Приложения, интенсивно использующие сеть

Для приложений, интенсивно использующих сеть, нужно с помощью netstat убедиться в том, что что пакеты не отбрасываются и т. д. Разделы netstat и netpmon в AIX 5L Performance Tools Handbook описывают различные хитрости, которые можно применить, если наблюдаются сбои в ходе мониторинга, поэтому эта информация здесь не повторяется.

Если есть подозрение, что пропускная способность сети является узким местом, то можно использовать NI001 для поиска проблем. Если IPv6 не используется, то также может быть полезен NI002.

Если наблюдается разница в производительности приложения на платформе AIX и других платформах и есть подозрение, что это обусловлено некоторыми особенностями настройки сокетов, то нужно обратить внимание на NI004.

RMI-приложения

Если приложение является RMI-клиентом или сервером, можно заметить несколько строк, которые не учитываются в выводе verbosegc. Например, это часть вывода verbosegc RMI-приложения:

<GC(4057): GC cycle started Thu Apr 15 11:14:28 2004
<GC(4057): freed 254510616 bytes, 55% free (453352000/810154496), in 1189 ms>
  <GC(4057): mark: 991 ms, sweep: 198 ms, compact: 0 ms>
  <GC(4057): refs: soft 0 (age >= 32), weak 2, final 330, phantom 0>
 <GC(4057): stop threads time: 10, start threads time: 260>
<GC(4058): GC cycle started Thu Apr 15 11:15:29 2004
<GC(4058): freed 267996504 bytes, 56% free (454445800/810154496), in 1243 ms>
  <GC(4058): mark: 1041 ms, sweep: 202 ms, compact: 0 ms>
  <GC(4058): refs: soft 0 (age >= 32), weak 0, final 253, phantom 0>
<GC(4059): GC cycle started Thu Apr 15 11:16:31 2004
<GC(4059): freed 248113752 bytes, 56% free (455754152/810154496), in 1386 ms>
  <GC(4059): mark: 1095 ms, sweep: 291 ms, compact: 0 ms>
  <GC(4059): refs: soft 0 (age >= 32), weak 0, final 263, phantom 0>

Циклы GC вызываются почти через каждые 60 секунд, но не вызываются из-за неправильного размещения (Allocation Failure). После того как будет установлено, что приложение не вызывает System.gc() напрямую, можно применить NI003.

Для приложений, интенсивно использующих RMI, следует рассмотреть NI005, но с учетом примечания, приведенного для этого совета.


Приложения, интенсивно использующие диски

Использование iostat и filemon дает возможность найти причины узких мест. Решение, как правило, заключается либо в изменении дизайна приложения так, чтобы оно не зависело от доступа к диску, либо в настройке системы для оптимизации доступа к диску. Поскольку оба эти приема выходят за рамки этой статьи, рекомендуется ознакомиться с инструментами iostat и filemon. Информации, содержащейся в предыдущем разделе, должно быть достаточно для начала исследования.


Общие советы

Приведенный ниже текст ссылается на аргументы командной строки Java (указываются перед именем класса или JAR-файла), известные как "ключи". Например, строка java -mx2g hello имеет один ключ, -mx2g.

NIO001 проверка скорости сетевого соединения

Иногда необходимо провести анализ скорости соединения FTP-сессии, установленной между двумя системами, поэтому можно выполнить следующие команды:

ftp> put "|dd if=/dev/zero bs=32k count=1000" /dev/null
200 PORT command successful.
150 Opening data connection for /dev/null.
1000+0 records in.
1000+0 records out.
226 Transfer complete.
32768000 bytes sent in 130.4 seconds (245.4 Kbytes/s)
local: |dd if=/dev/zero bs=32k count=1000 remote: /dev/null

Выше приведен пример теста скорости с попыткой передать 1000 блоков нулей, каждый размером в 32 КБ, который предоставляет простой способ определить пропускную способность соединения между двумя AIX-компьютерами. Приведенный выше пример показывает, что пропускная способность равна 245,4 Кбит/с, что указывает на проблемы с сетью, поскольку оба компьютера AIX оборудованы сетевыми адаптерами 100 Mbps Full-duplex. Если приведенный выше тест показал бы, например, скорость 1.140 E+4 Kbytes/s, то, значит, проблема узких мест в самом приложении. Размер и число блоков можно менять для более точного моделирования поведения Java-приложения.

NI002 стек IPv4

Если в приложении не используется Ipv6, можно установить свойство preferIPv4Stack в true следующим образом:

java -Djava.net.preferIPv4Stack=true <classname>

NIO003 удаленный GC

Если приложение является RMI-клиентом или сервером, можно использовать свойства sun.rmi.dgc.client.gcInterval и/или sun.rmi.dgc.server.gcInterval, описанные в документе http://java.sun.com/j2se/1.4.2/docs/guide/rmi/sunrmiproperties.html и доступные в реализации Java от IBM. Значение этих свойств по умолчанию равно 60 секундам, но в зависимости от потребностей программы интервал может быть увеличен до уровня, обеспечивающего снижение избыточности циклов GC.

Примечание. Предупреждение, расположенное в начале упомянутого выше документа, а также риски, связанные с неосвобожденными распределенными объектами, также применимы и к Java от IBM.

NI004 Размер буфера сокета

Если размеры исходящего и входящего буферов задаются явно, то следует помнить, что вызов setSendBufferSize(int) используется только для поиска (hint) источника проблемы. Например, если наблюдается разница в производительности между платформами, нужно добавить вызов getSendBufferSize() и убедиться в том, что hint сработал именно на данной платформе. В последнее время были зафиксированы проблемы производительности приложений на платформе AIX, в коде которых вызывается метод setSendBufferSize(4096). AIX использовала hint, и размер буфера устанавливался в запрошенном размере, в то время как другие платформы просто игнорировали этот вызов, в результате чего производительность приложения на AIX оказывалась низкой. Удаление этого вызова из кода повысила производительность более чем в 4 раза при выполнении приложения на AIX.

В общем, можно не включать вызовы, оптимизирующие стек TCP/IP в приложение, так как сетевой стек AIX прекрасно настроен изначально.

NI005 организация пула соединений

Для приложений, интенсивно использующих RMI, есть возможность объединять потоки в пул для повторного использования существующих подключений вместо создания новых для каждого вызова RMI. Для использования пула потоков нужно установить следующее свойство:

java -Dsun.rmi.transport.tcp.connectionPool=true <classname>

и так же можно отключить следующим образом:

java -Dsun.rmi.transport.tcp.noConnectionPool=true <classname>

Примечание. Желательно использовать пул потоков только для приложений, интенсивно использующих RMI. В последних версиях Java на AIX (1.3.1 SR7 и 1.4.1 SR2) по умолчанию пул потоков отключен.


Заключение

В этой статье описаны общие средства и методы устранения узких мест в сети и в дисковом вводе/выводе.

Следующая статья завершает серию общими наблюдениями и ссылками на используемые источники информации.

Ресурсы

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Профиль создается, когда вы первый раз заходите в developerWorks. Информация в вашем профиле (имя, страна / регион, название компании) отображается для всех пользователей и будет сопровождать любой опубликованный вами контент пока вы специально не укажите скрыть название вашей компании. Вы можете обновить ваш IBM аккаунт в любое время.

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=AIX и UNIX
ArticleID=431430
ArticleTitle=Оптимизация производительности Java в AIX: Часть 4. Устранение узких мест ввода/вывода и сети
publish-date=09282009