Назад | Перейти на главную страницу

Отслеживание медленного ввода-вывода Java в Solaris 10

У нас есть приложение Java, которое на сервере Solaris 10 работает значительно медленнее, чем на ПК с Windows.

Мы профилировали (-Xprof) приложение и заметили, что метод UnixFileSystem.getBooleanAttributes0 потребляет около 40% процессорного времени с собственными вызовами.

Как мы можем проследить наш поиск, чтобы определить, что является причиной медленного поведения?

Обновить:

Мы выполнили dtrace и мы наблюдаем, что время процессора составляет 0,489 секунды, в то время как time результаты


real 0m40.759s
user 0m47.669s
sys 0m2.287s

Кажется, время тратится не на процессор, а в другое место. Как мы можем продолжить расследование, имея это dtrace полученные результаты? Можем ли мы использовать другой dtrace варианты, чтобы показать больше информации?

Большое спасибо.


# /dtrace-toolkit/DTraceToolkit-0.99/procsystime -aTp 5695
Tracing... Hit Ctrl-C to end...
dtrace: 1032 dynamic variable drops with non-empty dirty list
^C

Elapsed Times for PID 5695,

         SYSCALL          TIME (ns)
           gtime               7799
       sysconfig               8018
        lwp_kill              10105
     getsockname              10215
      systeminfo              10984
       getrlimit              11093
        lwp_self              20210
        schedctl              26361
    lwp_continue              27349
     priocntlsys              33390
          unlink              53050
     lwp_sigmask             136303
      setcontext             143447
   so_socketpair             202427
      lwp_create             223626
             brk             227141
       so_socket             263276
         memcntl             461091
           ioctl            1094955
lwp_cond_broadcast            1946728
lwp_mutex_wakeup            2579492
 lwp_cond_signal            2903277
            mmap            3082973
          access            4446250
        mprotect            4534229
      getdents64            5713309
          mmap64            6272480
            fsat            6925239
            stat            6926115
            open            8324983
           fcntl            8840868
           close           11264404
          llseek           11678791
          munmap           11867401
         fstat64           17852129
        lwp_park           22098570
          open64           23549922
          stat64           39673214
            read           41876097
     resolvepath           81905859
           yield          175946072
           write          225507878
lwp_mutex_timedlock          887174392
         pollsys        20393318412
   lwp_cond_wait       345099369278
          TOTAL:       367108549202

CPU Times for PID 5695,

         SYSCALL          TIME (ns)
           gtime               1208
       sysconfig               1647
        lwp_self               2198
      systeminfo               2856
        lwp_kill               3186
     getsockname               3625
       getrlimit               4613
    lwp_continue              13839
        schedctl              14059
     priocntlsys              14498
     lwp_sigmask              20541
          unlink              45801
      setcontext              96874
             brk             121804
        lwp_park             158601
   so_socketpair             195178
      lwp_create             209017
       so_socket             241199
         memcntl             365972
           ioctl             606397
lwp_cond_broadcast            1367556
lwp_mutex_wakeup            1561103
 lwp_cond_signal            1803831
          access            1885436
            mmap            2655710
          llseek            3266410
            open            3614795
            fsat            4043369
      getdents64            4253373
        mprotect            4345864
           close            4547395
           fcntl            4871095
            stat            5183012
          mmap64            5308789
         fstat64            8141116
          munmap           10774529
         pollsys           11928811
lwp_mutex_timedlock           19212980
          open64           19443958
   lwp_cond_wait           23144761
            read           28043647
          stat64           31710269
     resolvepath           70641662
           yield           77731698
           write          137678654
          TOTAL:          489282936

Syscall Counts for PID 5695,

         SYSCALL              COUNT
       getrlimit                  1
     getsockname                  1
           gtime                  1
        lwp_kill                  1
           rexit                  1
   so_socketpair                  1
       sysconfig                  1
      systeminfo                  1
          unlink                  1
    lwp_continue                  2
      lwp_create                  2
        schedctl                  2
        lwp_self                  3
     priocntlsys                  3
       so_socket                  3
        lwp_exit                  4
      setcontext                  7
        lwp_park                 11
         memcntl                 14
             brk                 16
     lwp_sigmask                 19
        mprotect                 25
            mmap                 56
          access                 67
lwp_cond_broadcast                 86
           ioctl                 87
            open                100
            fsat                129
          mmap64                133
lwp_mutex_wakeup                148
          munmap                153
 lwp_cond_signal                162
      getdents64                224
            stat                283
         pollsys                348
   lwp_cond_wait                537
lwp_mutex_timedlock                558
          open64                590
           fcntl                625
           close                777
          stat64               1146
          llseek               1368
            read               1404
         fstat64               1559
     resolvepath               1644
           yield              10049
           write              13416
          TOTAL:              35769

Обновление 2:

Вот исходный код Java-приложения dtraced. Он просто загружает несколько тысяч классов из одного файла .jar, воспроизводя то же поведение, что и в большом приложении.

import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.Properties;
public class TestCL {
    public static void main(String[] args) {
        Properties properties = new Properties();
        InputStream in = TestCL.class.getClassLoader().getResourceAsStream("TestCL.properties");
        if (in == null) {
            System.err.println("TestCL.properties not found");
            System.exit(-1);
        }
        try {
            properties.load(in);
        } catch (IOException e) {
            System.err.println("TestCL.properties loading error");
            e.printStackTrace();
            System.exit(-2);
        } finally {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        Enumeration e = properties.keys();
        while (e.hasMoreElements()) {
            String className = (String) e.nextElement();
            try {
                Class.forName(className);
                System.out.println("OK " + className);
            } catch (Throwable t) {
               System.err.println("KO " + className + " " + t.getClass().getName() + " " + t.getMessage());
            }
        }
    }
}

Обновление 3:

Все классы упакованы в один файл .jar. Мы также запустили тест со всеми распакованными классами, и существенного улучшения производительности не произошло.

java -cp library.jar:. TestCL

Если вы используете Solaris, вам повезло, что вы можете использовать dtrace. Это позволит вам профилировать уровень ядра и получить больше подсказок о том, как jvm взаимодействует с ядром.

Больше информации здесь

http://www.devx.com/Java/Article/33943

Если вы хотите узнать, что делает jvm, запустите dtrace с зондами jvm.

http://java.sun.com/javase/6/docs/technotes/guides/vm/dtrace.html

http://www.solarisinternals.com/wiki/index.php/DTrace_Topics_Java#DTrace_Topics:_Java

это даст вам гораздо более значимый результат по отношению к вашей программе. Взгляните на раздел «Время приема».

http://www.princeton.edu/~unix/Solaris/troubleshoot/diskio.html

- отличное руководство для поиска узких мест ввода-вывода.

это также может помочь http://prefetch.net/blog/index.php/2007/03/03/viewing-busy-code-paths-with-dtrace/

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

Вы можете использовать jprofiler http://www.ej-technologies.com/products/jprofiler/overview.html

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

Вам также следует запустить виртуальную машину Java и приложение с полным ведением журнала отладки. Если у вас есть доступ к журналам ядра, проверьте их на наличие необычных событий.

Удачи.

Есть ли у кого-нибудь еще по ошибке сервера несколько советов ниндзя по поиску неисправностей, таких как эта. У меня есть свой способ отладки, но было бы интересно узнать, что думают другие?

-----------------ОБНОВИТЬ--------------

Я снова посмотрел на трассировку, кажется, вы делаете много путей разрешения.

Это нужно исправить. Вы используете очень длинный путь или работаете из каталога с символической ссылкой? Попробуйте удалить символические ссылки или использовать жесткие ссылки и посмотрите, добьетесь ли вы лучших результатов.

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

Опять же, просто идея: «Я съела сырный пирог. Запустите dtrace с java-зондами, которые должны быть достаточно детализированы, чтобы увидеть, какой java-класс / методы занимают больше всего времени.

Удачи (снова). Не сдавайтесь сейчас, я думаю, мы очень близки к решению.

В вашей системе Solaris просто запустите sys_diag -G -I1 -l -v и он будет собирать всю информацию о производительности (CPU / Memory / Network / Disk IO / Dtrace / kernel ...) и анализировать вывод с помощью одного цветного отчета в формате .html о находках / узких местах, характеризующих рабочую нагрузку по подсистемам. Это покажет все узкие места, а также возможные блокировки (lockstat, ..). Последняя версия - v8.1 HTH.

Ваш dtrace вывод показывает, что ваши приложения большую часть времени тратят на пишет. Вы должны проверить (используя dtrace конечно :-)) где эти записи идут. Если они переходят в файловую систему solaris, вам следует проверить, не является ли файловая система узким местом.

Просто чтобы опубликовать окончательный результат.

Сервер (Sun T Series) настолько медленный для однопоточного Java-приложения. Иди разберись.

Спасибо всем за ответы и поддержку.

Возможно, стоит взглянуть на iostat, чтобы узнать, есть ли проблема, из-за которой доступ к вашему диску медленнее, чем ожидалось. Загрузка нескольких тысяч классов не должна потреблять много дискового ввода-вывода, особенно если вы запускали ее несколько раз, чтобы блоки находились в кеше.

Пытаться

iostat -nxtcmpz 3

во время выполнения теста и посмотрите, есть ли у каких-либо устройств особенно высокий процент занятости / ожидания или особенно велико ли среднее время обслуживания. Вполне возможно, что у вас умирающий диск или не отвечающее на запросы монтирование NFS, убивающее производительность.