Продолжается подписка на наши издания! Вы не забыли подписаться?

Производительность PL/SQL

Автор: Аруп Нанда
Источник: серия Oracle Database 11g: The Top New Features for DBAs and Developers ( "Новые возможности для администраторов БД и разработчиков Oracle Database 11g). Впервые на русском языке статья опубликована в Oracle Magazine, 12’2008
Опубликовано: 12.07.2010
Версия текста: 1.1

Real Native Compilation
Новый тип данных: Simple_Integer
Intra-unit Inlining
Время компиляции
Эксперименты
Заключение

Native compilation – это не совсем новая возможность, однако теперь нет «узких» мест её использования, таких, например, как установка компилятора C (Oracle назвал эту замечательную возможность "Real Native Compilation"). Кроме того, новый тип данных simple_integer при Native compilation увеличивает производительность кода. Intra-unit inlining – это техника оптимизации, применяемая к PL/SQL-коду во время компиляции для повышения эффективности кода. В данной статье будут рассмотрены некоторые случаи использования этих новых возможностей. Будет также проверена их производительность при различных сценариях: при использовании Native compilation, типа simple_integer, Intra-unit inlining и их различных комбинаций.

Real Native Compilation

Вспомните Native compilation в Oracle9i Database Release 2; она существенно ускоряла выполнение PL/SQL-программ по сравнению с интерпретируемыми формами. С другой стороны, освоение было медленным, так как многие системные администраторы сопротивлялись установке необходимого компилятора C на производственный сервер БД. Кроме того, такие компиляторы требуют установки параметра plsql_na­ti­ve_libra­ry_dir с директорией для промежуточных файлов OС. В Oracle Database 11g можно выполнять Native com­pilation без компилятора C на сервере и без установки упомянутого параметра. Всё, что необходимо сделать, это установить параметр сессии перед созданием или перекомпиляцией хранимого кода:

alter session set plsql_code_type = native;
... здесь выполняется компиляция ...

Native compilation выполняется дольше, чем interpreted compilation, но поскольку сам этот процесс в Oracle Database 11g намного быстрее, то разница может оказаться незаметной. Лучше всего применять interpreted compilation во время обычного цикла разработки и Native compilation, когда разработка завершена.

Как часть миграции на 11g, я выполнил эксперимент с реальным кодом из диагностического приложения над очень большим пакетом из 5 827 строк. Я скомпилировал его в режиме Native compilation на существующей базе данных 10g и сделал то же самое на 11g, а затем повторил эти действия в режиме interpreted compilation. Каждая из этих компиляций была выполнена с параметром plsql_optimize_level, равным 2. Я измерил время компиляции для каждого случая, оно показано ниже (в секундах).

10g

11g

Interpreted

1.66

1.64

Native

4.66

2.81

Результаты говорят сами за себя. При interpreted compilation время компиляции почти одинаковое. Однако при Native compilation время компиляции в Oracle 11g меньше примерно на 60% по сравнению с версией 10g, а это существенное улучшение. Итак, хотя Native com­pi­la­tion в 11g требует дополнительного времени, она намного быстрее, чем Native compilation в 10g.

Чтобы найти объекты, скомпилированные с помощью NATIVE, смотрите представление USER_PL­SQL_OB­JECT_SETTINGS:

SQL> select name, PLSQL_code_type
  2> from user_plsql_object_settings;
 
NAME                 PLSQL_CODE_TYPE
-------------------- ---------------
DO_CALC              NATIVE
PERFECT_TRIANGLES    NATIVE
PRIME_NUMBERS        NATIVE
PRIME_NUMBERS        NATIVE
SOME_MATH            INTERPRETED
TR_BOOKINGS_TRACK    INTERPRETED
TR_SALGRADE_COMP     INTERPRETED
UPD_INT              NATIVE

Есть и похожее представление для всех объектов, DBA_PLSQL_OBJECT_SETTINGS.

Новый тип данных: Simple_Integer

Достоинства Native compilation ещё более очевидны при использовании нового типа данных, simple_integer. Технически это не настоящий тип данных, а скорее подтип pls_integer. Этот подтип создан для улучшения машинных вычислений по сравнению с программными вычислениями. Когда simple_integer используется одновременно с Native compilation, производительность будет намного лучше. В эксперименте, который будет показан дальше, вы увидите, почему.

Так как simple_integer является подтипом pls_integer, он наследует его свойства как 32-битного целого числа со знаком и может быть целым числом от -2,147,483,648 до 2,147,483,647. Однако он отличается от pls_integer следующим: он не допускает значения null, но допускает переполнение — когда значение превышает максимум, оно сбрасывается, а ошибка не появляется.

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

Давайте проверим несколько потенциальных задач, где следовало бы заменить pls_integer на simple_integer:

num1    simple_integer:= 1;

а написать так:

num1    simple_integer;

то будет получена ошибка компиляции:

PLS-00218: a variable declared NOT NULL must have an initialization assignment

Если установить значение переменной в NULL внутри программы, например, так:

num1 := NULL;

будет получена ошибка компиляции:

PLS-00382: expression is of wrong type

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

declare
v1 pls_integer := 2147483647;
begin
v1 := v1 + 1;
dbms_output.put_line('v1='||v1);
end;
/

Будет получена ошибка:

declare
*
ERROR at line 1:
ORA-01426: numeric overflow
ORA-06512: at line 4

Ошибка очевидна и вполне уместна; вы попытались превысить максимальное значение, допустимое для типа данных. Если вместо pls_integer использовать simple_integer:

declare
v1 simple_integer := 2147483647;
begin
v1 := v1 + 1;
dbms_output.put_line('v1='||v1);
end;
/

Результат будет следующим:

v1=-2147483648

Заметьте, что значение (-2147483648), это минимальное значение simple_integer. Когда вы прибавляете к максимальному значению (2147483647), значение просто сбрасывается до минимального — это особенность simple_integer. Помните об этом поведении.

Как видите, simple_integer не могут использоваться в любом месте; при использовании этого типа необходимо внимательно учитывать дополнительные условия (особенно возможный сброс значений). Поэтому sim­ple_integer создан для Native compilation. В режиме in­terpreted compilation эффекта производительности может не быть (но и вреда нет, как будет показано дальше). В режиме Native compilation выигрыш в производительности от использования sim­ple_in­teger намного существеннее.

Большинство бизнес-приложений на PL/SQL жестко связаны с SQL, поэтому эти приложения не увидят значительного изменения производительности при Native compilation. В "прошлой жизни " я разрабатывал инструмент для планирования базы данных с использованием PL/SQL, включающего много числовых и статистических вычислений в несколько тысяч строк кода. При Native compilation было видно существенное увеличение в производительности. Числа типа Simple_integer не были доступны в то время, но если бы были, то они добавили бы производительности.

Intra-unit Inlining

Intra-unit inlining представляет собой подмену вызова подпрограммы на копию кода этой подпрограммы. В результате модифицированный код выполняется быстрее. В Oracle Database 11g компилятор PL/SQL способен идентифицировать вызовы подпрограммы, которую необходимо скопировать (другими словами, подменить на неё) и вносит изменения, повышающие производительность.

Лучше всего это объяснить на примере. Код, показанный ниже, изменяет таблицу BALANCES, вычислив значения на основании баланса счёта. Код проходит по всем записям таблицы, вычисляет результат, и изменяет столбец таблицы с балансом.

create or replace procedure upd_int is
/* original version */
    l_rate_type     balances.rate_type%type;
    l_bal           balances.balance%type;
    l_accno         balances.accno%type;
    l_int_rate      number;
    procedure calc_int (
        p_bal in out balances.balance%type,
        p_rate  in number
    ) is
    begin
        if (p_rate >= 0) then
            p_bal := p_bal * (1+(p_rate/12/100));
        end if;
    end;
begin
    for ctr in 1..10000 loop
        l_accno := ctr;
        select balance, rate_type
        into l_bal, l_rate_type
        from balances
        where accno = l_accno;
        select decode(l_rate_type,
            'C', 1, 'S', 3, 'M', 5, 0)
        into l_int_rate
        from dual;
        for mth in 1..12 loop
            calc_int (l_bal, l_int_rate);
            update balances
            set balance = l_bal
            where accno = l_accno;
        end loop;
    end loop;
end;
/

Фактически, вычисление результата одинаково для всех типов записей, и я поместил логику в отдельную процедуру calc_int() внутри основной процедуры. Это повышает читаемость и сопровождаемость кода, но, к сожалению, это неэффективно.

Однако если заменить вызов calc_int() на код calc_int(), получится более быстрая программа, как показано ниже:

create or replace procedure upd_int is
/* revised version */
    l_rate_type     balances.rate_type%type;
    l_bal           balances.balance%type;
    l_accno         balances.accno%type;
    l_int_rate      number;
begin
    for ctr in 1..10000 loop
        l_accno := ctr;
        select balance, rate_type
        into l_bal, l_rate_type
        from balances
        where accno = l_accno;
        select decode(l_rate_type,
            'C', 1, 'S', 3, 'M', 5, 0)
        into l_int_rate
        from dual;
        for mth in 1..12 loop
            -- this is the int calc routine
            if (l_int_rate >= 0) then
                l_bal := l_bal * (1+(l_int_rate/12/100));
            end if;
            update balances
            set balance = l_bal
            where accno = l_accno;
        end loop;
    end loop;
end;
/

Этот переделанный код отличается от исходного только в части кода для вычисления баланса, который теперь внутри цикла, а не в процедуре calc_int().

Заметьте, что новая версия может быть быстрее, но это пример не очень хорошей практики кодирования. Часть кода, выполняющая вычисление баланса, выполняется один раз для каждой итерации цикла для месяцев, а затем и для каждого номера счёта. Так как эта часть кода повторяется, она более удобна для размещения отдельно, как показано в предыдущей версии upd_int, в процедуре (calc_int). Этот подход делает код модульным, легким в поддержке, и реально читаемым — но также менее эффективным.

Поэтому как можно достичь примирения конфликтующих способов создания кода, сделав код модульным и одновременно быстрым? Так, а можно ли написать код, используя модульный подход (как в первой версии upd_int), а затем позволить компилятору PL/SQL "оптимизировать" его, чтобы он стал выглядеть, как во второй версии кода?

Это можно сделать в Oracle Database 11g. Всё, что требуется сделать – перекомпилировать процедуру с более высоким уровнем оптимизации PL/SQL. Этого можно достичь двумя способами:

SQL> alter session set plsql_optimize_level = 3;
 
Session altered.

Команда, показанная выше, инструктирует компилятор PL/SQL, чтобы он переписал код во встроенный код.

SQL> alter procedure upd_int
  2  compile
  3  plsql_optimize_level = 3
  4  reuse settings;
 
Procedure altered.

На любую другую процедуру, компилируемую в этой же сессии, это не повлияет. Этот метод лучше применять для обработки inlining, если есть много процедур, которые необходимо скомпилировать в одной сессии.

Можно также использовать директиву компилятора pragma:

create or replace procedure upd_int is
    l_rate_type     varchar2(1);
...
...
begin
    pragma inline (calc_int, 'YES');
    for ctr in 1..10000 loop
...
...
end;

Я добавил строку pragma inline (calc_int, 'YES'); для указания компилятору подменить в коде эту процедуру. Таким же образом можно указать "NO" в этом же месте, чтобы передать компилятору, что не надо подменять эту процедуру, даже если plsql_optimizer_level установлен в значение 3.

Inlining ускоряет выполнение кода. Точная степень улучшения будет зависеть, конечно же, от количества подмен, которые будут сделаны компилятором. В конце этой статьи мы рассмотрим пример с использованием inlining и увидим улучшение производительности в результате его применения.

Время компиляции

Конечно, этот процесс оптимизации затрудняет работу компилятора. Но насколько?

Чтобы ответить на этот вопрос, я взял код реального приложения, показанный выше, и скомпилировал его в различных комбинациях с inlining/без inlining и inter­preted/native. Вот время компиляции:

Inlined

Not inlined

Interpreted

1.70

1.64

Native

3.15

2.81

Результаты говорят сами за себя. При компиляции с использованием inline, время компиляции выше совсем чуть-чуть (около 4%) в режиме interpreted. В режиме native, оно выше, но и разница больше — около 12%. Таким образом, целесообразно компилировать приложение в режиме inline/interpreted во время разработки, а затем в режиме native на стадии окончания. Использование inlining несущественно увеличивает время компиляции, при разработке такое увеличение несущественно.

Теперь мы подошли к важному вопросу: Раз код не менялся, как можно подтвердить, что код был подменён? Это можно сделать с помощью переменной сессии:

      alter session set plsql_warnings = 'enable:all';

Теперь, после пересоздания процедуры:

SQL> @upd_int
 
SP2-0804: Procedure created with compilation warnings

Обратите внимание на последнюю строку. Эта строка подтверждает, что процедура calc_int была подменена.

SQL> show error
Errors for PROCEDURE UPD_INT:
 
LINE/COL ERROR
-------- -----------------------------------------------------------------
7/5      PLW-06006: uncalled procedure "CALC_INT" is removed.
28/13    PLW-06005: inlining of call of procedure 'CALC_INT' was done

Если вы хотите найти объекты, которые были скомпилированы с этим уровнем оптимизации, можно выполнить запрос к представлению USER_PLSQL_OB­J­ECT_SET­TINGS:

sql> select name, plsql_optimize_level
  2> from user_plsql_object_settings;
 
NAME                 PLSQL_OPTIMIZE_LEVEL
-------------------- --------------------
DO_CALC                                 2
PERFECT_TRIANGLES                       2
TR_BOOKINGS_TRACK                       2
TR_SALGRADE_COMP                        2
UPD_INT                                 3
... и так далее ...

Есть и похожее представление для всех объектов: DBA_PLSQL_OBJECT_SETTINGS.

Помните, intra-unit inlining означает, что подменяются только те процедуры, которые расположены внутри блока. Внешние подпрограммы не подменяются.

Эксперименты

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

Сначала реализуем алгоритм Евклида для поиска наибольшего общего делителя для двух чисел. Вот логика функции, со страницы Wiki:

function gcd(a, b)
     if a = 0 return b
     while b ? 0
         if a > b
             a := a - b
         else
             b := b - a
     return a

Замерим процессорное время выполнения пакета при различных комбинациях этих модификаций и сохраним затраченное время. Итак, создаём таблицу для сохранения процессорного времени:

create table times(
  native        char(1) check (native    in ('Y', 'N')) enable,
  simple        char(1) check (simple    in ('Y', 'N')) enable,
  inlining      char(1) check (inlining  in ('Y', 'N')) enable,
  centiseconds  number not null,
  constraint times_pk primary key (simple, inlining, native))
/

Создадим три столбца — native, simple и inlining — для обозначения Native compilation, чисел типа simple_integer, и inlined-кода, соответственно. "Y" в столбце означает, что код скомпилирован с использованием этой возможности. Итак, получается запись, которая выглядит следующим образом:

NATIVE SIMPLE INLINING CENTISECONDS
------ ------ -------- ------------
Y      N      N                 100

Она показывает, что программа была скомпилирована в режиме Native compilation, но числа типа simple_integer не использовались, inlining не применялось, и что эта компиляция заняла 100 сёнтисекунд процессорного времени.

Чтобы использовать только одну копию пакета, для модификации пакета применим условную компиляцию (появилась в Oracle Database 10g Release 2). Ниже показано, как создать пакет:

-- подавляем следующие ожидаемые предупреждения:
--   inlining of call of procedure 'gcd' was done
--   uncalled procedure "gcd" is removed.
--   unreachable code
--   keyword "native" used as a defined name
alter session set plsql_warnings = 
  'enable:all, disable:06002, disable:06005, disable:06006, disable:06010'
/
alter session set plsql_ccflags = 'simple:false'
/
create package gcd_test is
  procedure time_it;
end gcd_test;
/
create package body gcd_test is
  $if $$simple $then
    subtype my_integer is simple_integer;
    simple constant times.simple%type := 'y';
  $else
    subtype my_integer is pls_integer not null;
    simple constant times.simple%type := 'n';
  $end

  function gcd(p1 in my_integer, p2 in my_integer) return my_integer is
    v1 my_integer := p1; v2 my_integer := p2;
  begin
    while v2 > 0 loop
      if v1 > v2 then
        v1 := v1 - v2;
      else
        v2 := v2 - v1;
      end if;
    end loop;
    return v1;
  end gcd;

  function exercise_gcd return number is
   -- ожидается значение, зависящее от no_of_iterations.
    expected_checksum my_integer := 74069926; -- 2475190;
    no_of_iterations constant my_integer := 5000; -- 1000;
    checksum my_integer := 0; 
    v my_integer := 0;
    t0 number; t1 number;
  begin
    for warmup in 1..2 loop
      checksum := 0;
      t0 := dbms_utility.get_cpu_time();

      for j in 1..no_of_iterations loop
        v := gcd(j, j);
        if v <> j then
          raise_application_error(-20000, 'logic error: gcd(j, j) <> j');
        end if;
        checksum := checksum + v;

        for k in (j + 1)..no_of_iterations loop
          v := gcd(j, k);
          if gcd(k, j) <> v then
            raise_application_error(
              -20000, 'logic error: gcd(j, k) <> gcd(k, j)');
          end if;
          checksum := checksum + v;
        end loop;
      end loop;

      if checksum <> expected_checksum then
        raise_application_error(
          -20000, 'checksum <> expected_checksum: '||checksum);
      end if;

      t1 := dbms_utility.get_cpu_time();
    end loop;
   return t1 - t0;
  end exercise_gcd;

  procedure time_it is
    inlining times.inlining%type;
    native times.native%type;
    centiseconds constant times.centiseconds%type := exercise_gcd();
  begin
    if lower($$plsql_code_type) = 'native' then
      native := 'y';
    else
      native := 'n';
    end if;

    if $$plsql_optimize_level = 3 then
      inlining := 'y';
    else
      inlining := 'n';
    end if;

    insert into times(native, simple, inlining, centiseconds)
      values(
        time_it.native, gcd_test.simple, 
        time_it.inlining, time_it.centiseconds);
    commit;
  end time_it;
end gcd_test;
/
show errors

Пакет имеет достаточно однострочных комментариев для самодокументации кода, поэтому здесь подробные объяснения не требуются. А в общем, функция GCD() имеет два входных параметра и возвращает наибольший общий делитель. Функция exercise_gcd() вызывает функцию GCD() и возвращает время работы процессора (CPU time) в сотых долях секунды. Наконец, public-процедура TIME_IT() вызывает функцию EXER­CI­SE_GCD() и вставляет запись в таблицу TIMES.

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

truncate table times
/

-- Interpreted ---------------------------------------------
-- Simple:false
-- No Inlining
alter package GCD_Test compile body
  PLSQL_Code_Type = interpreted
  PLSQL_CCFlags = 'Simple:false'
  PLSQL_Optimize_Level = 2 /* no inlining */
  reuse settings
/
begin GCD_Test.Time_It(); end;
/

-- inlining
alter package GCD_Test compile body
  PLSQL_Code_Type = interpreted
  PLSQL_CCFlags = 'Simple:false'
  PLSQL_Optimize_Level = 3 /* inlined */
  reuse settings
/
begin GCD_Test.Time_It(); end;
/

-- Числа типа simple_integer: используются
-- Без inlining

alter package GCD_Test compile body
  PLSQL_Code_Type = interpreted
  PLSQL_CCFlags = 'Simple:true'
  PLSQL_Optimize_Level = 2
  reuse settings
/
begin GCD_Test.Time_It(); end;
/

-- inlined
alter package GCD_Test compile body
  PLSQL_Code_Type = interpreted
  PLSQL_CCFlags = 'Simple:true'
  PLSQL_Optimize_Level = 3
  reuse settings
/
begin GCD_Test.Time_It(); end;
/

-- Native -------------------------------------------------
-- Числа типа simple_integer: не используются
-- Без inlining
alter package GCD_Test compile body
  PLSQL_Code_Type = native
  PLSQL_CCFlags = 'Simple:false'
  PLSQL_Optimize_Level = 2
  reuse settings
/
begin GCD_Test.Time_It(); end;
/

-- inlined
alter package GCD_Test compile body
  PLSQL_Code_Type = native
  PLSQL_CCFlags = 'Simple:false'
  PLSQL_Optimize_Level = 3
  reuse settings
/
begin GCD_Test.Time_It(); end;
/

-- Числа типа simple_integer: используются
-- Без linlining

alter package GCD_Test compile body
  PLSQL_Code_Type = native
  PLSQL_CCFlags = 'Simple:true'
  PLSQL_Optimize_Level = 2
  reuse settings
/
begin GCD_Test.Time_It(); end;
/

-- inlined
alter package GCD_Test compile body
  PLSQL_Code_Type = native
  PLSQL_CCFlags = 'Simple:true'
  PLSQL_Optimize_Level = 3
  reuse settings
/
begin GCD_Test.Time_It(); end;
/

Для определения, насколько повышается производительность при каждом из этих сценариев, используем следующий код:

spool timings.txt
<<b>>declare
  Interp_Pls_Integer_Noinline     Times.Centiseconds%type;
  Interp_Pls_Integer_Inline       Times.Centiseconds%type;
  Interp_Simple_Integer_Noinline  Times.Centiseconds%type;
  Interp_Simple_Integer_Inline    Times.Centiseconds%type;

  Native_Pls_Integer_Noinline     Times.Centiseconds%type;
  Native_Pls_Integer_Inline       Times.Centiseconds%type;
  Native_Simple_Integer_Noinline  Times.Centiseconds%type;
  Native_Simple_Integer_Inline    Times.Centiseconds%type;

  procedure Show_Caption(Caption in varchar2) is
  begin
    DBMS_Output.Put_Line(
      Chr(10)||Rpad('-', 60, '-')||Chr(10)||Chr(10)||Caption||Chr(10));
  end Show_Caption;

  procedure Show_Ratio(Var1 in varchar2, Var2 in varchar2, Ratio in number) is
  begin
    DBMS_Output.Put_Line(Rpad(
      Var1, 15)||'and '||Rpad(Var2, 14)||To_Char(Ratio, '99.99'));
  end Show_Ratio;
begin
  select  a.Centiseconds
  into    b.Interp_Pls_Integer_Noinline
  from    Times a
  where   a.Native = 'N' and a.Simple = 'N' and a.Inlining = 'N';

  select  a.Centiseconds
  into    b.Interp_Pls_Integer_Inline
  from    Times a
  where   a.Native = 'N' and a.Simple = 'N' and a.Inlining = 'Y';

  select  a.Centiseconds
  into    b.Interp_Simple_Integer_Noinline
  from    Times a
  where   a.Native = 'N' and a.Simple = 'Y' and a.Inlining = 'N';

  select  a.Centiseconds
  into    b.Interp_Simple_Integer_Inline
  from    Times a
  where   a.Native = 'N' and a.Simple = 'Y' and a.Inlining = 'Y';

  select  a.Centiseconds
  into    b.Native_Pls_Integer_Noinline
  from    Times a
  where   a.Native = 'Y' and a.Simple = 'N' and a.Inlining = 'N';

  select  a.Centiseconds
  into    b.Native_Pls_Integer_Inline
  from    Times a
  where   a.Native = 'Y' and a.Simple = 'N' and a.Inlining = 'Y';

  select  a.Centiseconds
  into    b.Native_Simple_Integer_Noinline
  from    Times a
  where   a.Native = 'Y' and a.Simple = 'Y' and a.Inlining = 'N';

  select  a.Centiseconds
  into    b.Native_Simple_Integer_Inline
  from    Times a
  where   a.Native = 'Y' and a.Simple = 'Y' and a.Inlining = 'Y';

  Show_Caption(' Преимущества simple_integer ');
  Show_Ratio(' Интерпретирующая ',    'no inlining', Interp_Pls_Integer_Noinline / Interp_Simple_Integer_Noinline);
  Show_Ratio(' Интерпретирующая ',    'inlining',    Interp_Pls_Integer_Inline   / Interp_Simple_Integer_Inline);
  Show_Ratio('Native',         'no inlining', Native_Pls_Integer_Noinline / Native_Simple_Integer_Noinline);
  Show_Ratio('Native',         'inlining',    Native_Pls_Integer_Inline   / Native_Simple_Integer_Inline);

  Show_Caption(' Преимущества  inlining ');
  Show_Ratio(' Интерпретирующая ',    'pls_integer',       Interp_Pls_Integer_Noinline    / Interp_Pls_Integer_Inline);
  Show_Ratio(' Интерпретирующая ',    'simple_integer',    Interp_Simple_Integer_Noinline / Interp_Simple_Integer_Inline);
  Show_Ratio('Native',         'pls_integer',       Native_Pls_Integer_Noinline    / Native_Pls_Integer_Inline);
  Show_Ratio('Native',         'simple_integer',    Native_Simple_Integer_NoInline / Native_Simple_Integer_Inline);

  Show_Caption(' Преимущества Native compilation ');
  Show_Ratio('pls_integer',    'no inlining',    Interp_Pls_Integer_Noinline    / Native_Pls_Integer_Noinline);
  Show_Ratio('pls_integer',    'inlining',       Interp_Pls_Integer_Inline      / Native_Pls_Integer_Inline);
  Show_Ratio('simple_integer', 'no inlining',    Interp_Simple_Integer_Noinline / Native_Simple_Integer_Noinline);
  Show_Ratio('simple_integer', 'inlining',       Interp_Simple_Integer_Inline   / Native_Simple_Integer_Inline);

end b;
/
spool off

Ниже показан результат. Он показывает рейтинг процессорного времени по сравнению со значением по умолчанию: без inlining, interpreted compilation, и использование pls_integer.

------------------------------------------------------------

Преимущества simple_integer

Интерпретирующая    и без inlining      1.00
Интерпретирующая    и c inlining        1.00
Native              и без inlining      2.19
Native              и с inlining        2.79

------------------------------------------------------------

Преимущества  inlining

Интерпретирующая    и pls_integer     1.07
Интерпретирующая    и simple_integer  1.07
Native              и pls_integer     1.16
Native              и simple_integer  1.48


------------------------------------------------------------

Преимущества Native compilation

pls_integer       и без inlining      4.78
pls_integer       и inlining          5.18
simple_integer    и без inlining     10.53
simple_integer    и inlining         14.49

Из показанных выше результатов видно, что процессорное время, потраченное на выполнение, было 14.49 для значения по умолчанию по сравнению с Native com­pilation с inlining и simple_integer — очень впечатляющий выигрыш по любым меркам.

Заключение

Теперь вы можете оценить важность и полезность этих новых возможностей. Итог:

?


Продолжается подписка на наши издания! Вы не забыли подписаться?


Продолжается подписка на наши издания! Вы не забыли подписаться?

Половину доходов Oracle принесло сопровождение ПО

Корпорация Oracle опубликовала результаты III квартала 2009 финансового года. Совокупный доход (по GAAP) вырос на 2% и составил 5,5 млрд. долларов, в то время как чистая прибыль сократилась на 1% до 1,3 млрд. долларов.

Доходы от программного обеспечения выросли на 5% и составили 4,4 млрд. долларов, включая доходы от продажи лицензий, которые составили 1,5 млрд. долларов (что на 6% ниже, чем в третьем квартале прошлого года). При этом продажи лицензий на бизнес-приложения упали на 12% до 396 млн. долларов, а продажи лицензий на СУБД и промежуточное ПО понизились на 3% и составили 1,12 млрд. долларов.

Доходы от оказания услуг снизились на 8% до 1 млрд. долларов. Обновление и сопровождение программных продуктов принесло разработчику 2,9 млрд. долларов, т.е. на 11% больше, чем год назад. Это направление деятельности обеспечило Oracle  более половины доходов за квартал. 

Комментируя финансовые итоги третьего квартала, Ларри Эллисон (Larry Ellison), CEO Oracle, назвал их большим достижением в условиях серьезного спада в мировой экономике. По утверждению руководства Oracle, на не слишком позитивные результаты существенно повлияли невыгодные для компании курсы валют. По словам Чарльза Филлипса (Charles Phillips), президента Oracle, без учета влияния валютных курсов доходы Oracle от продажи лицензий на ПО в завершившемся квартале превысили бы результаты аналогичного периода прошлого года.

Представляя финансовые результаты компании г-н Эллисон подтвердил, что разработку нового поколения бизнес-приложений Fusion Applications планируется завершить к 2010 году.


Продолжается подписка на наши издания! Вы не забыли подписаться?


Продолжается подписка на наши издания! Вы не забыли подписаться?

Новая версия Oracle Enterprise Manager

Корпорация Oracle выпустила новую версию Oracle Enterprise Manager, включающую расширенные средства управления для Oracle WebLogic Server и других компонентов Oracle Fusion Middleware.

Компаниям, использующим Oracle WebLogic Server, теперь предоставляется единое решение для управления приложениями, исключающее потребность в применении множества инструментов. Компании, планирующие развернуть этот сервер приложений и использующие Oracle Application Server, теперь могут применять привычный набор инструментов в Oracle Enterprise Manager для ускоренного внедрения Oracle WebLogic Server.

Кроме того, Oracle Enterprise Manager 10gR5 включает решение Composite Application Monitor and Modeler for SOA для управления производительностью приложений на базе моделей, новые средства управления для Oracle Service Bus, Oracle Coherence и Oracle Beehive, а также более совершенные функции управления для Oracle BPEL Process Manager.


Продолжается подписка на наши издания! Вы не забыли подписаться?



Copyright © 1994-2016 ООО "К-Пресс"