Производительность функции Replace LibreOffice Basic

Автор sokol92, 24 апреля 2020, 20:27

0 Пользователи и 1 гость просматривают эту тему.

sokol92

Добрый день! У меня проблема со скоростью работы функции Replace LibreOffice Basic.

Sub TestReplace
  Dim s as String, i as Long, n as Long, t as Long
  n=100000
  s=Space(n) & "1"
  i=InStr(s, "1")   ' мгновенно даже при n=4000000
  t=GetSystemTicks
  s=Replace(s, " ", "*") 
  Msgbox "n=" & n &  " time=" & (GetSystemTicks-t)
End Sub


При значениях n>=100000 время работы функции увеличивается пропорционально квадрату числа n. При этом функция InStr отрабатывает мгновенно.
Можно, разумеется, воспользоваться соответствующими UNO, но хотелось бы эфффективной работы "родных" функций Basic.

Моя версия: Win 10, LO 6.3.3.2 (x64).
Владимир.

mikekaganski

Ну, SbRtl_Replace оптимизировать-непереоптимизировать.
С уважением,
Михаил Каганский

rami

Цитата: sokol92 от 24 апреля 2020, 20:27У меня проблема со скоростью работы функции Replace LibreOffice Basic.
Цитата: sokol92 от 24 апреля 2020, 20:27При этом функция InStr отрабатывает мгновенно.
Ну, вы сравнили... две большие разницы. Функция InStr находит подстроку в строке (в вашем примере последний символ в строке состоящей из 100001 символа), а функция Replace заменяет 100000 пробелов на звёздочки.

Для честного сравнения если InStr ищет только один последний символ, то и Replace должна искать и заменять только один последний символ. В этом случае поиск и замена в 2 — 3 раза медленней чем только поиск, что нормально. Проверьте:

Sub TestReplace
  Dim s as String, i as Long, n as Long, t as Long
  n=100000000
  s=Space(n) & "1"
  t=GetSystemTicks
  i=InStr(s, "1")            'при n = 100 000 000 у меня time=112
  Msgbox "i=" & n &  " time=" & (GetSystemTicks-t)

  t=GetSystemTicks
  s=Replace(s, "1", "*")     'при n = 100 000 000 у меня time=293
  Msgbox "n=" & n &  " time=" & (GetSystemTicks-t)
End Sub

kompilainenn

Поддержать разработчиков LibreOffice можно тут, а наш форум вот тут

mikekaganski

Это исправление сделает функцию мгновенной.

А пока можете значительно ускорить её, если зададите ей чувствительность к регистру.
С уважением,
Михаил Каганский

sokol92

#5
Добрый день, коллеги. Спасибо за ответы, и, особенно, за впечатляющую конструктивную реакцию! Подождем версии 7.

Еще пара замечаний в части Replace.

1. Ограничение на максимальное значение 65535 параметра Start,  указанное в документации, выглядит явным атавизмом. Правда, этот параметр используется редко.

2. О регистре символов. Тестировал на:

msgbox Replace("Default is binary compare", "BINARY", "Text")

Если присутствует оператор Option VBASUPPORT 1, то производится сравнение с учетом регистра символов (бинарное), иначе без учета регистра символов (текстовое), что, на мой взгляд, логично (соответствует умолчанию VBA). Было бы неплохо указать об этом в документации по функции Replace.

Проверил на вчерашней тест-системе кузину Replace - SUBSTITUTE из семьи Sheet.FunctionAccess.Callfunction. Те же симптомы. Может быть, ее тоже вылечить?



Владимир.

mikekaganski

Цитата: sokol92 от 25 апреля 2020, 13:29
1. Ограничение на максимальное значение 65535 параметра Start,  указанное в документации, выглядит явным атавизмом. Правда, этот параметр используется редко.

Добавил в tdf#132390.

Цитата: sokol92 от 25 апреля 2020, 13:29
2. О регистре символов. Тестировал на:

msgbox Replace("Default is binary compare", "BINARY", "Text")

Если присутствует оператор Option VBASUPPORT 1, то производится сравнение с учетом регистра символов (бинарное), иначе без учета регистра символов (текстовое), что, на мой взгляд, логично (соответствует умолчанию VBA). Было бы неплохо указать об этом в документации по функции Replace.

Напишите отдельный баг.

Цитата: sokol92 от 25 апреля 2020, 13:29
Проверил на вчерашней тест-системе кузину Replace - SUBSTITUTE из семьи Sheet.FunctionAccess.Callfunction. Те же симптомы. Может быть, ее тоже вылечить?

И этот баг напишите.
С уважением,
Михаил Каганский

sokol92

#7
Очередное cпасибо! Писать про баги пока еще Заратустра статус не позволяет. ;)
Владимир.

kompilainenn

Цитата: sokol92 от 25 апреля 2020, 14:31
Очередное cпасибо! Писать про баги пока еще Заратустра статус не позволяет. ;)
чего чего? Какой ещё статус? вот адрес bugs.documentfoundation.org , заводите учетку и пишите (только на английском пожалуйста). Баг трекер всегда открыт для всех, ни про какие "статусы" я никогда не слышал
Поддержать разработчиков LibreOffice можно тут, а наш форум вот тут

sokol92

Спасибо! И еще вопрос:

s=replace("ABCD","A","B",,,1)

устанавливает в s значение !!br0ken!!

Это - какое-то соглашение разработчиков об обработке исключительных ситуаций, связанных с синтаксисом Basic?

В то же время запись:

s=replace("ABCD","A","B", Compare:=1)

работает штатно.
Владимир.

mikekaganski

А это повод для третьего (вашего) бага про эту функцию (я уже свои три написал).

Реально это ошибка неправильной проверки типа переданной переменной. Вы указали ,,, - все пропущенные параметры передаются как объект "ошибка - отсутствующий именованный параметр" (ошибка 448). Функция этого не проверяет, и пытается этот объект превратить в число (получается 448). Попытка вернуть подстроку четырёхсимвольной строки начиная с 448 позиции выдаёт такую ошибку (до моего исправления выше) или пустую строку (после того исправления) вместо того, чтобы эту ошибку считать "используй значение по умолчанию" (1).
С уважением,
Михаил Каганский

sokol92

#11
 Спасибо, как всё, оказывается, интересно! :)
Владимир.

sokol92

#12
Поменял версию на Win10 LO Версия: 6.4.3.2 (x64).

Третий отмеченный Михаилом баг - некорректная работа с символами юникода из страницы 01 и далее (в частности, с буквами кириллицы).
Посмотрел по ссылке код функции SbRtl_Replace. В строках 1286 и 1287 используется функция (toAsciiUpperCase), которая про юникод ничего не знает (поскольку значительно старше по возрасту). Эта же старушка не дает корректно работать функциям Basic InStr, InStrRev, Strconv (нет в документации), Curdir.

В том же модуле C++ есть функции SbRtl_LCase, SbRtl_UCase, SbRtl_StrComp, которые с юникодом обращаются корректно.

Проверяем корректность работы Instr и InstrRev(только с поддержкой VBA) при работе с кириллицей по сравнению с латынью:

Option VBASUPPORT 1
Sub TestInstr
 Dim v
 For each v In array("s", "ш")  
   Msgbox "Instr: text1=" & Ucase(v) & " text2=" & v & " compare=1" & " result=" & _
          Instr(1, Ucase(v), v, 1) & chr(10) &  _
          "InstrRev: text1=" & Ucase(v) & " text2=" & v & " compare=1" & " result=" & _
          InstrRev(Ucase(v), v, 1, 1) &  chr(10)
 Next v
End Sub


Вывод: результаты работы с кириллицей некорректны.

В реализации других функций Basic использование toAsciiUpperCase (toAsciiLowerCase), на мой взгляд, не опасно, поскольку эти функции (обработка даты, времени...) не взаимодействуют с  текстом, содержащий символы юникода с кодами >=U+0100
Владимир.

mikekaganski

Цитата: sokol92 от 26 апреля 2020, 13:42Третий отмеченный Михаилом баг - некорректная работа с символами юникода из страницы 01 и далее (в частности, с буквами кириллицы).

Вы про tdf#132389?

Цитата: sokol92 от 26 апреля 2020, 13:42В строках 1286 и 1287 используется функция (toAsciiUpperCase)

... после исправления - в строках 1282 и 1283.

Цитата: sokol92 от 26 апреля 2020, 13:42В реализации других функций Basic использование toAsciiUpperCase (toAsciiLowerCase), на мой взгляд, не опасно, поскольку эти функции (обработка даты, времени...) не взаимодействуют с  текстом, содержащий символы юникода с кодами >=U+0100

Ой не факт. Обработка дат вида "5 октября" вполне себе возможна. Ну, и для полноты занудствования - "с кодами >= U+0080".

Вы вполне можете попробовать это всё поправить. Я готов Вам помочь с развёртыванием среды разработки и вопросами по патчам. Мне так кажется, что у Вас всё получится.
С уважением,
Михаил Каганский

sokol92

Владимир.