Добрый день!
Есть 2-3 удфки которые обрабатывают стринг-массивы, типа 1.2.3.4., например
DECLARE EXTERNAL FUNCTION ARRAYLEFT CSTRING(200), CSTRING(1), INTEGER RETURNS CSTRING(200) FREE_IT ENTRY_POINT 'ArrayLeft' MODULE_NAME 'warrays';
Замечал что если параметры большие, то очень сильно влияют на производительность. Например если длина 200 то запрос выполнялся в среднем за 800мс если 1000 то за 3с 600мс на тех же данных, железе.
Сам код удф-ок оптимизирован на максиме, данные в обеях случаех те же. Подозреваю что тормоза в менеджере памяти, тоесть на выделение по 1000байт на каждую запись. Хотя, возврат например той же функции я выделяю память через ib_malloc из удфки, и я аллокирую реальную длина строки, а не 1000 каждый раз. в 90% он не доходит до 200 символов, но хочется какбы страховатся потому что теоретически длинны могут быть больше.
Кстати по резултатам этим удфок идет групировка, тоесть например
select
arrayleft(C.CHILD_ROOTS, '.', 2), D.KIND,
sum(D.Dt) as Dt,
sum(D.Ct) as Ct
from TS_FORMDET D
join TS_ACCOUNT_CHILD C on (C.CHILD_ID = D.ACCOUNT_ID)
where (C.ACCOUNT_ID = 1) and (D.FDATE BETWEEN '1900-01-01' AND '2009-12-31')
group by 1, 2
На 2.5 есть заметное ускоренее, но всеже.
Вот и возникли некоторые вопросы/замыслы.
Все входные параметры CSTRING в принципе могут быть и без длинны, зачем их лимитировать? В дллке они же попадают как PChar, так пусть передают только поинтер к начале стрига и все, не так ли?
Результат функции как-бы должен быть лимитирован в длинну, чтоб движок знал сколько зарезервировать под каждую запись, но возникает вопрос, как же встроенный substring работает, сколько выделяет, вижу
select substring('aaaaaa' from 2 for 1) from RDB$DATABASE
union all
select substring('aaaaaaaaaaaaaaaaaaa' from 3 for 6) from RDB$DATABASE
обрабатывает без проблем.
Или попытатся как блоб их отправить/получать, но подозреваю это будет изващенство.
Хотелось бы услышать Ваши советы.
UDF и большие cstring параметры
Re: UDF и большие cstring параметры
Тормоза живут в аллокаторе, по крайней мере часть их.
При каждом выполнении UDF
а) выделяется память для всех вх. пар-ров
б) выделяется память под возврат. значения FREE_IT
в) освобождается память для всех вх. пар-ров
г) освобождается память для возврат. значения
Для (а), если памяти нужно немного, то она выделяется в стеке - это максимально быстро. В 2.5 из стека берётся до 800 байт (не спрашивайте, почему именно столько). Соотв. твоя строка в 1000 байт уже выделяется аллокатором движка, это медленнее.
До 2.5 (б) и (г) делала CRT (malloc), в 2.5 это делается с помощью пулов движка, отсюда ускорение.
По идее, (б) и (г) можно вообще избежать, если использовать механизм RETURNS PARAMETER N
При каждом выполнении UDF
а) выделяется память для всех вх. пар-ров
б) выделяется память под возврат. значения FREE_IT
в) освобождается память для всех вх. пар-ров
г) освобождается память для возврат. значения
Для (а), если памяти нужно немного, то она выделяется в стеке - это максимально быстро. В 2.5 из стека берётся до 800 байт (не спрашивайте, почему именно столько). Соотв. твоя строка в 1000 байт уже выделяется аллокатором движка, это медленнее.
До 2.5 (б) и (г) делала CRT (malloc), в 2.5 это делается с помощью пулов движка, отсюда ускорение.
По идее, (б) и (г) можно вообще избежать, если использовать механизм RETURNS PARAMETER N
Re: UDF и большие cstring параметры
Влад, спасибо за внятный ответ!
С RETURN PARAMETER есть прирост ~15%. В принципе это меня устраивает, не такие уж тормознутые эти удфки
Сам запрос, даже без них тяжеловатый, сервер наверное шустрее надо будет ставить.
-
D.
С RETURN PARAMETER есть прирост ~15%. В принципе это меня устраивает, не такие уж тормознутые эти удфки
Сам запрос, даже без них тяжеловатый, сервер наверное шустрее надо будет ставить.
-
D.