Showing posts with label pragma. Show all posts
Showing posts with label pragma. Show all posts

Monday, November 25, 2013

PRAGMA SERIALLY_REUSABLE in ORACLE


PRAGMA SERIALLY_REUSABLE:
The SERIALLY_REUSABLE Pragma specifies that the package state is needed for only one call to the server (for example, an OCI call to the database or a stored procedure invocation through a database link). After this call, the storage for the package variables can be reused, reducing the memory overhead for long-running sessions.
This Pragma is appropriate for packages that declare large temporary work areas that are used once in the same session.
The SERIALLY_REUSABLE Pragma can appear in the declare_section of the specification of a bodiless package, or in both the specification and body of a package, but not in only the body of a package.
The state of a serially reusable package persists only for the lifetime of a CALL to the server. On a subsequent call to the server, if a reference is made to the serially reusable package, Oracle creates a new instantiation (described below) of the serially reusable package and initializes all the global variables to NULL or to the default values provided. Any changes made to the serially reusable package state in the previous CALLs to the server are not visible.

Note: Creating a new instantiation of a serially reusable package on a CALL to the server does not necessarily imply that Oracle allocates memory or configures the instantiation object. Oracle simply looks for an available instantiation work area (which is allocated and configured) for this package in a least-recently used (LRU) pool in SGA. At the end of the CALL to the server this work area is returned back to the LRU pool. The reason for keeping the pool in the SGA is that the work area can be reused across users who have requests for the same package.

Why Serially Reusable Packages?
Since the state of a non-reusable package persists for the lifetime of the session, this locks up UGA memory for the whole session. In applications such as Oracle Office a log-on session can typically exist for days together. Applications often need to use certain packages only for certain localized periods in the session and would ideally like to de-instantiate the package state in the middle of the session once they are done using the package.

With SERIALLY_REUSABLE packages the application developers have a way of modelling their applications to manage their memory better for scalability. Package state that they care about only for the duration of a CALL to the server should be captured in SERIALLY_REUSABLE packages.
Example-1: Examine the package with & without SERIALLY_REUSABLE
Create two packages with & without SERIALLY_REUSABLE
sql_11g> create or replace package without_serially_reusable_pkg as
  2  v_without_sr int := 0;
  3  end;
  4  /
Package created.

sql_11g> create or replace package with_serially_reusable_pkg as
  2  pragma serially_reusable;
  3  v_with_sr int := 0;
  4  end;
  5  /
Package created.
Now, let us assign values to packaged variables

sql_11g> begin
  2   without_serially_reusable_pkg.v_without_sr := 100;
  3  with_serially_reusable_pkg.v_with_sr := 100;
  4  end;
  5  /
PL/SQL procedure successfully completed.

Now, let us display the values of packaged variables
sql_11g> begin
  2  dbms_output.put_line ('without_serially_reusable_pkg.v_without_sr value is -> ' || without_serially_reusable_pkg.v_without_sr );

  3   dbms_output.put_line ('with_serially_reusable_pkg.v_with_sr values is ->' || with_serially_reusable_pkg.v_with_sr );
  4  end;
  5  /

without_serially_reusable_pkg.v_without_sr value is -> 100
with_serially_reusable_pkg.v_with_sr values is ->0

PL/SQL procedure successfully completed.

with_serially_reusable_pkg.v_with_sr is showing 0 because the package is marked as serially_reusable which resets the packaged variable global values to default immediately after its call.
Now, clubbing assignment of variables & displaying the values of variables in single plsql block.

sql_11g> begin
  2   without_serially_reusable_pkg.v_without_sr := 100;
  3  with_serially_reusable_pkg.v_with_sr := 100;
  4   dbms_output.put_line ('without_serially_reusable_pkg.v_without_sr value is -> ' || without_serially_reusable_pkg.v_without_sr );
  5    dbms_output.put_line ('with_serially_reusable_pkg.v_with_sr values is ->' || with_serially_reusable_pkg.v_with_sr );
  6  end;
  7  /

without_serially_reusable_pkg.v_without_sr value is -> 100
with_serially_reusable_pkg.v_with_sr values is ->100
PL/SQL procedure successfully completed.

PRAGMA INLINE in ORACLE 11G


   PRAGMA INLINE:

The INLINE pragma specifies whether a subprogram invocation is to be inlined. Inlining replaces a subprogram invocation with a copy of the invoked subprogram (if the invoked and invoking subprograms are in the same program unit).

Every call to a procedure or function causes a slight, but measurable, performance overhead, which is especially noticeable when the subprogram is called within a loop. Avoiding procedures and functions is not an option, as it goes against the concept of modular programming, making programs bulky and difficult to manage. Automatic subprogram inlining can reduce the overheads associated with calling subprograms, whilst leaving your original source code in its normal modular state. This is done by replacing the subprogram calls with a copy of the code in the subprogram at compile time.

The process of subprogram inlining is controlled by the PLSQL_OPTIMIZE_LEVEL parameter and the INLINE pragma. When PLSQL_OPTIMIZE_LEVEL=2 (the default), the INLINE pragma determines whether the following statement or declaration should be inlined or not. When PLSQL_OPTIMIZE_LEVEL=3, the optimizer may inline code automatically. In this case the INLINE pragma can turn it off inlining for a statement, or increase the likelihood that the optimizer will choose to inline a statement. The relationship is easier to understand when you see the following example.

With PLSQL_OPTIMIZE_LEVEL=2, you must specify each subprogram to be inlined with the INLINE pragma:
PRAGMA INLINE (subprogram, 'YES')

If subprogram is overloaded, then the preceding pragma applies to every subprogram with that name.
With PLSQL_OPTIMIZE_LEVEL=3, the PL/SQL compiler seeks opportunities to inline subprograms. You need not specify subprograms to be inlined. However, you can use the INLINE pragma (with the preceding syntax) to give a subprogram a high priority for inlining, and then the compiler inlines it unless other considerations or limits make the inlining undesirable.
These tests use an anonymous block with a function defined in the declaration block. The function is then called repeatedly in a loop. The settings for PLSQL_OPTIMIZE_LEVEL and the INLINE pragma are altered to switch subprogram inlining on and off. First, we make sure PLSQL_OPTIMIZE_LEVEL=2 and run the code with no INLINE pragma set. With these settings we would not expect to see subprogram inlining taking place.

PLSQL_OPTIMIZE_LEVEL:
  • Level 0: no compiler optimizations (PL/SQL compiled as is);
  • Level 1: high-level optimizations (such as moving constants out of loops);
  • Level 2: default level. Aggressive optimizations (such as rewriting cursor-for-loops as array fetches) and in 11g, also inlining any subprograms that we request with PRAGMA INLINE;
  • Level 3: most aggressive level: New in 11g, these will inline all subprograms where possible (excluding those contained in built-in packages).
Example-1:  with PLSQL_OPTIMIZE_LEVEL=2 & with out using Pragma inline

With plsql_optimize_level=2 and without using Pragma inline the following code taken 446 hsecs in ORACLE 11G R2
sql_11g> ALTER SESSION SET PLSQL_OPTIMIZE_LEVEL=2;

Session altered.

sql_11g> SET SERVEROUTPUT ON
sql_11g> DECLARE
  2    l_loops  NUMBER := 10000000;
  3    l_start  NUMBER;
  4    l_return NUMBER;
  5 
  6    FUNCTION add_numbers (p_1 IN NUMBER,
  7                          p_2 IN NUMBER)
  8      RETURN NUMBER AS
  9    BEGIN
 10      RETURN p_1 + p_2;
 11    END add_numbers;
 12 
 13  BEGIN
 14    l_start := DBMS_UTILITY.get_time;
 15 
 16    FOR i IN 1 .. l_loops LOOP
 17      --PRAGMA INLINE (add_numbers, 'YES');
 18      l_return := add_numbers(1, i);
 19    END LOOP;
 20 
 21    DBMS_OUTPUT.put_line('Elapsed Time: ' || (DBMS_UTILITY.get_time - l_start) || ' hsecs');
 22  END;
 23  /

Elapsed Time: 446 hsecs

PL/SQL procedure successfully completed.
Example-2:  with PLSQL_OPTIMIZE_LEVEL=2 & with Pragma inline

sql_11g> ALTER SESSION SET PLSQL_OPTIMIZE_LEVEL=2;
Session altered.
sql_11g>
sql_11g> SET SERVEROUTPUT ON
sql_11g> DECLARE
  2    l_loops  NUMBER := 10000000;
  3    l_start  NUMBER;
  4    l_return NUMBER;
  5 
  6    FUNCTION add_numbers (p_1 IN NUMBER,
  7                          p_2 IN NUMBER)
  8      RETURN NUMBER AS
  9    BEGIN
 10      RETURN p_1 + p_2;
 11    END add_numbers;
 12 
 13  BEGIN
 14    l_start := DBMS_UTILITY.get_time;
 16    FOR i IN 1 .. l_loops LOOP
 17      PRAGMA INLINE (add_numbers, 'YES');
 18      l_return := add_numbers(1, i);
 19    END LOOP;
 20 
 21    DBMS_OUTPUT.put_line('Elapsed Time: ' || (DBMS_UTILITY.get_time - l_start) || ' hsecs');
 22  END;
 23  /
Elapsed Time: 167 hsecs
PL/SQL procedure successfully completed.
From the above it is proven that use of Pragma inline reduces the time required for execution.
Example-3:  with PLSQL_OPTIMIZE_LEVEL=3 & without Pragma inline

sql_11g> ALTER SESSION SET PLSQL_OPTIMIZE_LEVEL=3;
Session altered.

sql_11g>
sql_11g> SET SERVEROUTPUT ON
sql_11g> DECLARE
  2    l_loops  NUMBER := 10000000;
  3    l_start  NUMBER;
  4    l_return NUMBER;
  5
  6    FUNCTION add_numbers (p_1 IN NUMBER,
  7                          p_2 IN NUMBER)
  8      RETURN NUMBER AS
  9    BEGIN
 10      RETURN p_1 + p_2;
 11    END add_numbers;
 12 
 13  BEGIN
 14    l_start := DBMS_UTILITY.get_time;
 15 
 16    FOR i IN 1 .. l_loops LOOP
 17      --PRAGMA INLINE (add_numbers, 'YES');
 18      l_return := add_numbers(1, i);
 19    END LOOP;
 20 
 21    DBMS_OUTPUT.put_line('Elapsed Time: ' || (DBMS_UTILITY.get_time - l_start) || ' hsecs');
 22  END;
 23  /

Elapsed Time: 162 hsecs

PL/SQL procedure successfully completed.

PLSQL_OPTIMIZE_LEVEL=3 by default inline the sub programs and hence the elapsed time is lesser when compare with settings in first example i.e. PLSQL_OPTIMIZE_LEVEL=2
Example-4:  with PLSQL_OPTIMIZE_LEVEL=3 & with Pragma inline as NO

sql_11g> ALTER SESSION SET PLSQL_OPTIMIZE_LEVEL=3;
Session altered.

sql_11g>
sql_11g> SET SERVEROUTPUT ON
sql_11g> DECLARE
  2    l_loops  NUMBER := 10000000;
  3    l_start  NUMBER;
  4    l_return NUMBER;
  5 
  6    FUNCTION add_numbers (p_1 IN NUMBER,
  7                          p_2 IN NUMBER)
  8      RETURN NUMBER AS
  9    BEGIN
 10      RETURN p_1 + p_2;
 11    END add_numbers;
 12 
 13  BEGIN
 14    l_start := DBMS_UTILITY.get_time;
 15 
 16    FOR i IN 1 .. l_loops LOOP
 17      PRAGMA INLINE (add_numbers, 'NO');
 18      l_return := add_numbers(1, i);
 19    END LOOP;
 20 
 21    DBMS_OUTPUT.put_line('Elapsed Time: ' || (DBMS_UTILITY.get_time - l_start) || ' hsecs');
 22  END;
 23  /

Elapsed Time: 505 hsec
PL/SQL procedure successfully completed
This gives elapsed time as 505 hsecs which means inlining has not taken place as expected.
The INLINE pragma only affects the following types of statements.
·         Assignment
·         Cal
·         Conditional
·         CASE
·         CONTINUE-WHEN
·         EXECUTE IMMEDIATE
·         EXIT-WHEN
·         LOOP
·         RETURN
In each case, it affects every call to specified subprogram from the statement.