Гость
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Тест скорости получения данных из ХП, функций и RDB$GET_CONTEXT / 2 сообщений из 2, страница 1 из 1
29.08.2018, 09:16
    #39694677
CyberMax
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Тест скорости получения данных из ХП, функций и RDB$GET_CONTEXT
FB 3.0. Начал делать перевод некоторых ХП, возвращающих одно значение, во внутренние функции. Ради интереса решил померить их производительность.
Что тестируется:
1. Получение одной строки и одного параметра из ХП, которая берет данные из RDB$GET_CONTEXT - SP$GET_ID_USER.
2. Получение одной строки и одного параметра из ХП, которая возвращает одно и то же число - SP$GET_ID_USER_CONST.
3. Функция без флага DETERMINISTIC, возвращающая значение из RDB$GET_CONTEXT - CONNECT_ID_USER_NOT_DETER.
4. Функция без флага DETERMINISTIC, возвращающая одно и то же число - CONNECT_ID_USER_CONST_NOT_DETER.
5. Функция c флагом DETERMINISTIC, возвращающая значение из RDB$GET_CONTEXT - CONNECT_ID_USER_DETER.
6. Функция c флагом DETERMINISTIC, возвращающая одно и то же число - CONNECT_ID_USER_CONST_DETER.
7. Получение значения из RDB$GET_CONTEXT.
8. Прямое присвоение значения.

Скрипт метаданных:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
SET TERM ^ ;

CREATE OR ALTER PROCEDURE SP$GET_ID_USER
RETURNS (
    RESULT INTEGER)
AS
BEGIN
    RESULT = RDB$GET_CONTEXT('USER_SESSION', 'ID_USER');

    SUSPEND;
END^

CREATE OR ALTER PROCEDURE SP$GET_ID_USER_CONST
RETURNS (
    RESULT INTEGER)
AS
BEGIN
    RESULT = 1;

    SUSPEND;
END^

CREATE OR ALTER FUNCTION CONNECT_ID_USER_DETER
RETURNS INTEGER DETERMINISTIC AS
BEGIN
    RETURN RDB$GET_CONTEXT('USER_SESSION', 'ID_USER');
END^

CREATE OR ALTER FUNCTION CONNECT_ID_USER_CONST_DETER
RETURNS INTEGER DETERMINISTIC AS
BEGIN
    RETURN 1;
END^

CREATE OR ALTER PROCEDURE SP$GET_ID_USER_CONST
RETURNS (
    RESULT INTEGER)
AS
BEGIN
    RESULT = 1;

    SUSPEND;
END^

CREATE OR ALTER FUNCTION CONNECT_ID_USER_NOT_DETER
RETURNS INTEGER AS
BEGIN
    RETURN RDB$GET_CONTEXT('USER_SESSION', 'ID_USER');
END^

CREATE OR ALTER FUNCTION CONNECT_ID_USER_CONST_NOT_DETER
RETURNS INTEGER AS
BEGIN
    RETURN 1;
END^

SET TERM ; ^



Тест:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
EXECUTE BLOCK
RETURNS (NAME VARCHAR(60), DIFF_WITH_LOOP INTEGER, DIFF_CLEAR INTEGER)
AS
DECLARE VARIABLE CNT INTEGER;
DECLARE VARIABLE I INTEGER;
DECLARE VARIABLE ID INTEGER;
DECLARE VARIABLE TIMESTAMP_START TIMESTAMP;
DECLARE VARIABLE TIMESTAMP_END TIMESTAMP;
DECLARE VARIABLE TIME_EMPTY_LOOP INTEGER;
BEGIN
    CNT = 10000000;
    
    --
    I = :CNT;

    TIMESTAMP_START = 'NOW';
    WHILE (I > 0) DO
    BEGIN
        :I = :I - 1;
    END

    TIMESTAMP_END = 'NOW';
    DIFF_WITH_LOOP = DATEDIFF(MILLISECOND, :TIMESTAMP_START, :TIMESTAMP_END);
    DIFF_CLEAR = 0;
    NAME = 'EMPTY LOOP';
    SUSPEND;
    TIME_EMPTY_LOOP = :DIFF_WITH_LOOP;

    --
    I = :CNT;

    TIMESTAMP_START = 'NOW';
    WHILE (I > 0) DO
    BEGIN
        ID = (SELECT RESULT FROM SP$GET_ID_USER);

        :I = :I - 1;
    END

    TIMESTAMP_END = 'NOW';
    DIFF_WITH_LOOP = DATEDIFF(MILLISECOND, :TIMESTAMP_START, :TIMESTAMP_END);
    DIFF_CLEAR = :DIFF_WITH_LOOP - :TIME_EMPTY_LOOP;
    NAME = 'SELECT FROM SP AS RDB$GET_CONTEXT';
    SUSPEND;

    --
    I = :CNT;

    TIMESTAMP_START = 'NOW';
    WHILE (I > 0) DO
    BEGIN
        ID = (SELECT RESULT FROM SP$GET_ID_USER_CONST);

        :I = :I - 1;
    END

    TIMESTAMP_END = 'NOW';
    DIFF_WITH_LOOP = DATEDIFF(MILLISECOND, :TIMESTAMP_START, :TIMESTAMP_END);
    DIFF_CLEAR = :DIFF_WITH_LOOP - :TIME_EMPTY_LOOP;
    NAME = 'SELECT FROM SP AS CONST';
    SUSPEND;

    --
    I = :CNT;

    TIMESTAMP_START = 'NOW';
    WHILE (I > 0) DO
    BEGIN
        ID = CONNECT_ID_USER_NOT_DETER();

        :I = :I - 1;
    END

    TIMESTAMP_END = 'NOW';
    DIFF_WITH_LOOP = DATEDIFF(MILLISECOND, :TIMESTAMP_START, :TIMESTAMP_END);
    DIFF_CLEAR = :DIFF_WITH_LOOP - :TIME_EMPTY_LOOP;
    NAME = 'GET FROM NOT DETERM INTERNAL FUNCTION AS RDB$GET_CONTEXT';
    SUSPEND;

    --
    I = :CNT;

    TIMESTAMP_START = 'NOW';
    WHILE (I > 0) DO
    BEGIN
        ID = CONNECT_ID_USER_CONST_NOT_DETER();

        :I = :I - 1;
    END

    TIMESTAMP_END = 'NOW';
    DIFF_WITH_LOOP = DATEDIFF(MILLISECOND, :TIMESTAMP_START, :TIMESTAMP_END);
    DIFF_CLEAR = :DIFF_WITH_LOOP - :TIME_EMPTY_LOOP;
    NAME = 'GET FROM NOT DETERM INTERNAL FUNCTION AS CONSTANT';
    SUSPEND;

    --
    I = :CNT;

    TIMESTAMP_START = 'NOW';
    WHILE (I > 0) DO
    BEGIN
        ID = CONNECT_ID_USER_DETER();

        :I = :I - 1;
    END

    TIMESTAMP_END = 'NOW';
    DIFF_WITH_LOOP = DATEDIFF(MILLISECOND, :TIMESTAMP_START, :TIMESTAMP_END);
    DIFF_CLEAR = :DIFF_WITH_LOOP - :TIME_EMPTY_LOOP;
    NAME = 'GET FROM DETERM INTERNAL FUNCTION AS RDB$GET_CONTEXT';
    SUSPEND;

    --
    I = :CNT;

    TIMESTAMP_START = 'NOW';
    WHILE (I > 0) DO
    BEGIN
        ID = CONNECT_ID_USER_CONST_DETER();

        :I = :I - 1;
    END

    TIMESTAMP_END = 'NOW';
    DIFF_WITH_LOOP = DATEDIFF(MILLISECOND, :TIMESTAMP_START, :TIMESTAMP_END);
    DIFF_CLEAR = :DIFF_WITH_LOOP - :TIME_EMPTY_LOOP;
    NAME = 'GET FROM DETERM INTERNAL FUNCTION AS CONSTANT';
    SUSPEND;

    --
    I = :CNT;

    TIMESTAMP_START = 'NOW';
    WHILE (I > 0) DO
    BEGIN
        ID = RDB$GET_CONTEXT('USER_SESSION', 'ID_USER');

        :I = :I - 1;
    END

    TIMESTAMP_END = 'NOW';
    DIFF_WITH_LOOP = DATEDIFF(MILLISECOND, :TIMESTAMP_START, :TIMESTAMP_END);
    DIFF_CLEAR = :DIFF_WITH_LOOP - :TIME_EMPTY_LOOP;
    NAME = 'GET FROM RDB$GET_CONTEXT';
    SUSPEND;

    --
    I = :CNT;

    TIMESTAMP_START = 'NOW';
    WHILE (I > 0) DO
    BEGIN
        ID = 1;

        :I = :I - 1;
    END

    TIMESTAMP_END = 'NOW';
    DIFF_WITH_LOOP = DATEDIFF(MILLISECOND, :TIMESTAMP_START, :TIMESTAMP_END);
    DIFF_CLEAR = :DIFF_WITH_LOOP - :TIME_EMPTY_LOOP;
    NAME = 'DIRECT SET';
    SUSPEND;
END



Результаты теста:
NAMEDIFF_WITH_LOOPDIFF_CLEAREMPTY LOOP24220SELECT FROM SP AS RDB$GET_CONTEXT3586033438SELECT FROM SP AS CONST2979827376GET FROM NOT DETERM INTERNAL FUNCTION AS RDB$GET_CONTEXT1915716735GET FROM NOT DETERM INTERNAL FUNCTION AS CONSTANT1426611844GET FROM DETERM INTERNAL FUNCTION AS RDB$GET_CONTEXT2875453GET FROM DETERM INTERNAL FUNCTION AS CONSTANT2828406GET FROM RDB$GET_CONTEXT55783156DIRECT SET2766344

Из статистики видно, что:
1. Выборка из ХП медленнее выборки из функции примерно в 2 раза.
2. Флаг DETERMINISTIC реально ускоряет присвоение, по скорости почти равняясь прямому присвоению.
3. Получение значения из RDB$GET_CONTEXT примерно в 10 раз медленнее прямого присвоения.
4. Получение значения из RDB$GET_CONTEXT через обертку в виде функции медленнее примерно в 5 раз.
5. Получение значения из RDB$GET_CONTEXT быстрее получения значения из функции примерно в 4 раза.
...
Рейтинг: 0 / 0
29.08.2018, 09:47
    #39694702
Симонов Денис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Тест скорости получения данных из ХП, функций и RDB$GET_CONTEXT
CyberMax,

это Таблоид тестировал года 3-4 назад. Правда тест у него случайно вышел, он всё таки за RDB$DATABASE aka DUAL боролся.

Я такие вещи в пакеты складываю. Там есть процедуры и функции для присвоения и возврата констант/переменных. Заодно бонусом получаем типизацию переменных. Для функций возврата делаю DETERMINISTIC
...
Рейтинг: 0 / 0
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Тест скорости получения данных из ХП, функций и RDB$GET_CONTEXT / 2 сообщений из 2, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]