Cовременные процессоры очень и очень быстры, но вместе с тем, работая на крупном предприятии, всё время сталкиваешься с невероятной тормознутостью программного обеспечения. Никуда не годится, когда процедура закрытия месяца в бухгалтерии идёт больше суток и если что-то где то не так, то расчёт приходится запускать заново.
В статье рассмотрены фундаментальные причины медлительности приложений и даны опорные цифры, которые послужат опорой для выбора архитектуры будущих программ.
Рассмотрим типовую схему современного приложения
Общая скорость работы приложения обуславливается двумя категориями:
1) скоростью работы каждого из звеньев приложения;
2) скоростью взаимодействия между звеньями приложения.
По первому пункту, слабым звеном может быть только база данных, поскольку мы всегда можем поставить рядом ещё один сервер и распараллелить сервера приложений и веб-сервера.
Разберём второй пункт. Разные звенья приложения работают как минимум в разных процессах операционной системы, поэтому для взаимодействия двух звеньев между собой операционной системе нужно, как минимум, два раза переключится между процессами. Значит, даже если сервер приложений и база данных находятся на одном компьютере, то из-за накладных расходов времени, мы не можем рассчитывать на выполнение более 8000 SQL-запросов за секунду. В сетевом взаимодействии задействовано ещё больше процессов, соответственно и число запросов уменьшается практически до 1000. Взаимодействие между веб-сервером, веб-клиентом и сервером приложений обычно гораздо менее интенсивное, чем между сервером приложений и базой данных. Единственное, связь между пользователем и веб-сервером характеризуется относительно большим временем отклика, особенно на спутниковых каналах. Так что тучу ajax-запросов устраивать тоже не стоит (чем часто грешили первые ajax-приложения). Но вернёмся к базе данных.
В нормальном режиме работы, тысячи запросов в секунду вполне хватает. Проблемы начинаются, при какой-либо массовой обработке данных. Но особенно критичным данное ограничение становится при использовании объектных надстроек, в том числе и такой популярной, как система 1С. Особенность применения ООП в том, что оно порождает кучу мелких обращений к базе данных. И из этой ситуации сейчас существует два выхода:
а) разместить логику приложения внутри базы данных;
б) кэшировать данные внутри сервера приложений.
Выбрав вариант «а», вы сможете увеличить скорость примерно на два порядка порядок: до 100 000 запросов в секунду. Неудобство в том, что при этом мы вынуждены логику реализовывать на встроенном языке базы данных. Вариант с С# или Java –процедурами не подходит, т.к. такие процедуры выполняются в виртуальной машине, которая фактически является отдельным процессом и по времени взаимодействия практически не отличается от внешнего сервера приложений. И хотя встроенный язык программирования не очень приспособлен для реализации логики приложения, во многих банках используется именно такой подход. В основном в таком случае используется, конечно же, Oracle со своим встроенным PL/SQL.
Рассмотрим далее вариант «б». Если «на пальцах», то реализация логики при данном варианте выглядит следующим образом: загружаем большими блоками все данные, которые могут понадобиться в массивы в памяти. Обрабатываем. Выгружаем результаты обработки в базу данных. Из базы данных строки загружаются очень быстро – порядка миллиона штук в секунду. Обрабатываются данные тоже очень быстро. Проблема в загрузке данных в базу. Здесь у нас опять 1000 строк в секунду. Нестандартными приёмами можно загружать до 100 000 строк в секунду. Для очень крупных предприятий такой метод не подходит, т.к. объёмы данных таковы, что не помещаются в оперативной памяти. Вместе с тем, такой способ наиболее подходит для оптимизации 1С, не нужно только забывать, что линейный поиск очень медленен даже в оперативной памяти и вам придётся делать собственную реализацию индексов.
Откуда же взялась граница в 100 000 строк в секунду, которую мы никак не можем преодолеть, используя базу данных. Ответ прост – это примерная средняя скорость построения индексов в базе данных. Да, несмотря на то, что современный процессор может отсортировать 100 млн строк за полсекунды, Oracle тратит около 20 секунд на построения индекса в 1 млн элементов. Это надо иметь ввиду при разработке приложения. И даже этих 100 тысяч строк в секунду можно добиться только благодаря процедурам на строенном языке либо массовой загрузкой данных из файла. При использовании SQL-комманд, мы получим максимум 10 000 запросов в секунду. Можно повысить общую скорость путём кластеризации, но время отклика повысить очень и очень сложно.
Напомню, что речь идёт о массовой обработке данных, например закрытия месяца или закрытия года. В повседневном режиме обычной скорости работы вполне хватает.
Теперь поговорим о перспективах. Сейчас тихо и незаметно происходит настоящая революция в компьютерной технике – переход на 64-бита. И это не просто возможность установить больше 4 гигабайт памяти – такая возможность была ещё на Pentium II путём использования расширенных режимов процессора. 64 бита, это возможность включить любой объём данных в адресное пространство процессора. Вкупе с развитием твёрдотельных дисков, которые по своей сути больше похожи на оперативную память, нежели на классические жёсткие диски, это кардинально меняет облик будущих систем обработки данных. По всей видимости, в скором будущем мы увидим объединение сервера приложения и базы данных. Первые шаги сделаны: Oracle купила технологию Java, а Microsoft уже встраивает SQL-запросы в язык C#. Т.е. они стараются засунуть логику внутрь своей СУБД. Недостатком данного подхода является то, что логика, строящаяся на принципах ООП не очень хорошо ложиться на реляционную модель данных – при этом на порядок увеличивается число запросов к базе данных. Впрочем, крупные банки, которые будут использовать данный подход, могут себе позволить вообще не переходить на новые технологии разработки. Так, ИТ-департамент Сбербанка по численности сопоставим с общей численностью персонала. В компаниях же производственного сектора программистов гораздо меньше и новые технологии здесь, как ни странно, более востребованы.
Другой подход противоположный – встраивание базы данных внутрь сервера приложений. Из существующих технологий наиболее близкими являются NoSQL-базам данных. При таком подходе, мы можем использовать всю мощь современного процессора. Производительность приложений сходу повышается в тысячи, в миллионы раз. Но, при таком подходе используется ООП, главной особенностью которого является необходимость в быстром доступе к случайным областям базы данных. Наиболее эффективно это можно реализовать путём маппирования файла базы данных в адресное пространство сервера приложений. Необходимо отметить, что, такие популярные языки программирования, как C#, 1C, Java, не имеют средств, для прямой работы с памятью, и, поэтому, для них необходимо создавать дополнительные прослойки unsafe-кода, для возможности такой работы.
Оценим объём необходимой оперативной памяти. Повсеметное использование мультимедиа-технологий даёт немного не правильные представления об объёмах памяти, занимаемой информацией. Сейчас возможно прозвучит неожиданно, но 1 мегабайт может уместить в себе томик Войны и Мира. В этом легко убедится, перемножив количество страниц в книге, число строк текста на старанице и число букв в строке. Мы получим примерно 1 млн символов. Далеко не каждый пользователь, не владеющий навыками слепой печати, «вбивает» в компьютер по несколько томов Толстого ежегодно. Даже продовщица, непрерывно сканирующая продукты в магазине порождает всего порядка 10 мегабайт информации за год. Для офисных же пользователей, мы можем смело ставить 1 мегабайт в год на человека. Да, есть вордовские файлы, скан-копии документов, фото, музыка, фильмы — но, согласитесь, все эти виды информации лежат в базе данных «как есть» и никак не обрабатываются (за исключением полнотекстового индексирования), поэтому и в оперативной памяти они не нуждаются.
Выводы. ООП, доказавшее, за 30 лет своего существаования, свою эффективность, не может использоваться нами полностью, т.к. оно плохо совместимо с реляционными базами данных. В топике даны ориентировочные цифры, используя которые, можно выбрать оптимальную глубину внедрения ООП, и знать границы возможностей будущего приложения.
В статье рассмотрены фундаментальные причины медлительности приложений и даны опорные цифры, которые послужат опорой для выбора архитектуры будущих программ.
Рассмотрим типовую схему современного приложения
Общая скорость работы приложения обуславливается двумя категориями:
1) скоростью работы каждого из звеньев приложения;
2) скоростью взаимодействия между звеньями приложения.
По первому пункту, слабым звеном может быть только база данных, поскольку мы всегда можем поставить рядом ещё один сервер и распараллелить сервера приложений и веб-сервера.
Разберём второй пункт. Разные звенья приложения работают как минимум в разных процессах операционной системы, поэтому для взаимодействия двух звеньев между собой операционной системе нужно, как минимум, два раза переключится между процессами. Значит, даже если сервер приложений и база данных находятся на одном компьютере, то из-за накладных расходов времени, мы не можем рассчитывать на выполнение более 8000 SQL-запросов за секунду. В сетевом взаимодействии задействовано ещё больше процессов, соответственно и число запросов уменьшается практически до 1000. Взаимодействие между веб-сервером, веб-клиентом и сервером приложений обычно гораздо менее интенсивное, чем между сервером приложений и базой данных. Единственное, связь между пользователем и веб-сервером характеризуется относительно большим временем отклика, особенно на спутниковых каналах. Так что тучу ajax-запросов устраивать тоже не стоит (чем часто грешили первые ajax-приложения). Но вернёмся к базе данных.
В нормальном режиме работы, тысячи запросов в секунду вполне хватает. Проблемы начинаются, при какой-либо массовой обработке данных. Но особенно критичным данное ограничение становится при использовании объектных надстроек, в том числе и такой популярной, как система 1С. Особенность применения ООП в том, что оно порождает кучу мелких обращений к базе данных. И из этой ситуации сейчас существует два выхода:
а) разместить логику приложения внутри базы данных;
б) кэшировать данные внутри сервера приложений.
Выбрав вариант «а», вы сможете увеличить скорость примерно на два порядка порядок: до 100 000 запросов в секунду. Неудобство в том, что при этом мы вынуждены логику реализовывать на встроенном языке базы данных. Вариант с С# или Java –процедурами не подходит, т.к. такие процедуры выполняются в виртуальной машине, которая фактически является отдельным процессом и по времени взаимодействия практически не отличается от внешнего сервера приложений. И хотя встроенный язык программирования не очень приспособлен для реализации логики приложения, во многих банках используется именно такой подход. В основном в таком случае используется, конечно же, Oracle со своим встроенным PL/SQL.
Рассмотрим далее вариант «б». Если «на пальцах», то реализация логики при данном варианте выглядит следующим образом: загружаем большими блоками все данные, которые могут понадобиться в массивы в памяти. Обрабатываем. Выгружаем результаты обработки в базу данных. Из базы данных строки загружаются очень быстро – порядка миллиона штук в секунду. Обрабатываются данные тоже очень быстро. Проблема в загрузке данных в базу. Здесь у нас опять 1000 строк в секунду. Нестандартными приёмами можно загружать до 100 000 строк в секунду. Для очень крупных предприятий такой метод не подходит, т.к. объёмы данных таковы, что не помещаются в оперативной памяти. Вместе с тем, такой способ наиболее подходит для оптимизации 1С, не нужно только забывать, что линейный поиск очень медленен даже в оперативной памяти и вам придётся делать собственную реализацию индексов.
Откуда же взялась граница в 100 000 строк в секунду, которую мы никак не можем преодолеть, используя базу данных. Ответ прост – это примерная средняя скорость построения индексов в базе данных. Да, несмотря на то, что современный процессор может отсортировать 100 млн строк за полсекунды, Oracle тратит около 20 секунд на построения индекса в 1 млн элементов. Это надо иметь ввиду при разработке приложения. И даже этих 100 тысяч строк в секунду можно добиться только благодаря процедурам на строенном языке либо массовой загрузкой данных из файла. При использовании SQL-комманд, мы получим максимум 10 000 запросов в секунду. Можно повысить общую скорость путём кластеризации, но время отклика повысить очень и очень сложно.
Напомню, что речь идёт о массовой обработке данных, например закрытия месяца или закрытия года. В повседневном режиме обычной скорости работы вполне хватает.
Теперь поговорим о перспективах. Сейчас тихо и незаметно происходит настоящая революция в компьютерной технике – переход на 64-бита. И это не просто возможность установить больше 4 гигабайт памяти – такая возможность была ещё на Pentium II путём использования расширенных режимов процессора. 64 бита, это возможность включить любой объём данных в адресное пространство процессора. Вкупе с развитием твёрдотельных дисков, которые по своей сути больше похожи на оперативную память, нежели на классические жёсткие диски, это кардинально меняет облик будущих систем обработки данных. По всей видимости, в скором будущем мы увидим объединение сервера приложения и базы данных. Первые шаги сделаны: Oracle купила технологию Java, а Microsoft уже встраивает SQL-запросы в язык C#. Т.е. они стараются засунуть логику внутрь своей СУБД. Недостатком данного подхода является то, что логика, строящаяся на принципах ООП не очень хорошо ложиться на реляционную модель данных – при этом на порядок увеличивается число запросов к базе данных. Впрочем, крупные банки, которые будут использовать данный подход, могут себе позволить вообще не переходить на новые технологии разработки. Так, ИТ-департамент Сбербанка по численности сопоставим с общей численностью персонала. В компаниях же производственного сектора программистов гораздо меньше и новые технологии здесь, как ни странно, более востребованы.
Другой подход противоположный – встраивание базы данных внутрь сервера приложений. Из существующих технологий наиболее близкими являются NoSQL-базам данных. При таком подходе, мы можем использовать всю мощь современного процессора. Производительность приложений сходу повышается в тысячи, в миллионы раз. Но, при таком подходе используется ООП, главной особенностью которого является необходимость в быстром доступе к случайным областям базы данных. Наиболее эффективно это можно реализовать путём маппирования файла базы данных в адресное пространство сервера приложений. Необходимо отметить, что, такие популярные языки программирования, как C#, 1C, Java, не имеют средств, для прямой работы с памятью, и, поэтому, для них необходимо создавать дополнительные прослойки unsafe-кода, для возможности такой работы.
Оценим объём необходимой оперативной памяти. Повсеметное использование мультимедиа-технологий даёт немного не правильные представления об объёмах памяти, занимаемой информацией. Сейчас возможно прозвучит неожиданно, но 1 мегабайт может уместить в себе томик Войны и Мира. В этом легко убедится, перемножив количество страниц в книге, число строк текста на старанице и число букв в строке. Мы получим примерно 1 млн символов. Далеко не каждый пользователь, не владеющий навыками слепой печати, «вбивает» в компьютер по несколько томов Толстого ежегодно. Даже продовщица, непрерывно сканирующая продукты в магазине порождает всего порядка 10 мегабайт информации за год. Для офисных же пользователей, мы можем смело ставить 1 мегабайт в год на человека. Да, есть вордовские файлы, скан-копии документов, фото, музыка, фильмы — но, согласитесь, все эти виды информации лежат в базе данных «как есть» и никак не обрабатываются (за исключением полнотекстового индексирования), поэтому и в оперативной памяти они не нуждаются.
Выводы. ООП, доказавшее, за 30 лет своего существаования, свою эффективность, не может использоваться нами полностью, т.к. оно плохо совместимо с реляционными базами данных. В топике даны ориентировочные цифры, используя которые, можно выбрать оптимальную глубину внедрения ООП, и знать границы возможностей будущего приложения.