Форум поддержки пользователей. LibreOffice, Apache OpenOffice, OpenOffice.org

Форум поддержки пользователей. LibreOffice, Apache OpenOffice, OpenOffice.org

9 Декабрь 2019, 15:57 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
Новости: Доступно и просто о работе в офисных пакетах
 
   Начало   Помощь Поиск Войти Регистрация    задать вопрос  
Страниц: 1 2 »   Вниз
  Печать  
Автор Тема: Деградация скорости у функции setDataArray()  (Прочитано 343 раз)
0 Пользователей и 1 Гость смотрят эту тему.
zmeishe
Участник
**
Offline Offline

Пол: Мужской
Расположение: Нижний Новгород
Сообщений: 8



« Стартовое сообщение: 3 Декабрь 2019, 11:54 »

Необходимо из приложения средствами api LibreOffice передать в Calc значения 900 тыс строк и 20 столбцов.
Если всё это выгрузить в файл CSV, а затем открыть Calc`ом, то он потратит около 5 минут времени.

Если использовать функцию setDataArray, то сначала скорость высокая - порядка 100 тыс записей в минуту, затем скорость деградирует(сильно снижается). В итоге все данные можно передать только за 30-40 минут, вместо 8-10 мин.

Как ускорить работу функции setDataArray, чтобы скорость не снижалась?

Подробности:
LibreOffice 5.2.7.7
Debian 9
Весь массив вывожу частями по 50 тыс строк (так чтобы не более 1 млн ячеек за шаг)
После каждой порции сбрасываю флаг
         Reference < XModifiable > xModifiable( xCalcComponent, UNO_QUERY );
         xModifiable->setModified( sal_False );

Экспериментировал с разным количеством строк за один шаг: от 1 тыс до 100 тыс. Результат одинаковый. Сначала быстро, затем медленно.
Единственное, что прибавило скорости, это передача даты и времени не строками, а числовым преставлением.

Как будто Calc накапливает, что-то, что мешает ему. Как это "что-то" отключить, сбросить или очистить, чтобы он не тратил время и скорость приблизилась к скорости открытия файла CSV ?
Записан
Bigor
Опытный пользователь
***
Offline Offline

Пол: Мужской
Сообщений: 771


« Ответ #1: 3 Декабрь 2019, 12:25 »

900 тыс строк и 20 столбцов.
Если всё это выгрузить в файл CSV, а затем открыть Calc`ом, то он потратит около 5 минут

setDataArray, то сначала скорость высокая - порядка 100 тыс записей в минуту
Т.е. на 900 тыс уйдет 9 минут, в чем выйгрыш по сравнению с csv?
Записан
zmeishe
Участник
**
Offline Offline

Пол: Мужской
Расположение: Нижний Новгород
Сообщений: 8



« Ответ #2: 3 Декабрь 2019, 12:59 »

в чем выйгрыш по сравнению с csv?

Выигрыш в том, что пользователю не надо мышетыканием заниматься. И копипастить тоже ничего не надо.
Таблицы выходят с многоуровневыми заголовками. С замороженными заголовками. Лист подогнан по ширине страницы. Страница повёрнута Ландшафт/Портрет в зависимости от количества столбцов. Числа форматированы с нужным количеством знаков после запятой и с разделением разрядов. Нулевые значения отключены(ячейка с нулями выглядит пустой).
Некоторые отчёты на разных листах одной книги Calc.
Отчёты 300 тыс строк и до 6-ти столбцов со всей этой красотой  setDataArray выгружает за 40 сек.

Количество столбцов около 10 существенно снижает скорость.

В этом конкретном отчёте столбцов 20 и вся красота пока отключена.
У заказчиков есть возможность воспользоваться CSV, но они хотят то, к чему привыкли. И никто не хочет ждать.

Записан
mikekaganski
Мастер
*****
Offline Offline

Пол: Мужской
Расположение: Хабаровск -> Москва
Сообщений: 1 621


« Ответ #3: 3 Декабрь 2019, 13:06 »

Насколько я понимаю, Bigor предлагает программно импортировать CSV и отформатировать результат для достижения того же?
Записан

С уважением,
Михаил Каганский
zmeishe
Участник
**
Offline Offline

Пол: Мужской
Расположение: Нижний Новгород
Сообщений: 8



« Ответ #4: 3 Декабрь 2019, 13:17 »

Оно, конечно, можно.
Но хотелось бы понять - у открытия файла и setDataArray разные алгоритмы? И зачем это разработчикам Open/Libre Office ?
Я ещё могу понять разный подход для xCell->setValue(...) и xCellRange->setDataArray(...).
Но для setDataArray() и открытием файла, думаю механизм один.
Просто мы не знаем, что он там ещё делает и что там можно программно отключить.
Записан
mikekaganski
Мастер
*****
Offline Offline

Пол: Мужской
Расположение: Хабаровск -> Москва
Сообщений: 1 621


« Ответ #5: 3 Декабрь 2019, 13:20 »

Так соберите отладочную сборку ЛО и посмотрите Улыбка На самом деле никак иначе не ответить на Ваш вопрос.
Записан

С уважением,
Михаил Каганский
zmeishe
Участник
**
Offline Offline

Пол: Мужской
Расположение: Нижний Новгород
Сообщений: 8



« Ответ #6: 3 Декабрь 2019, 13:29 »

Ещё заметил.
Например, отчёт содержит 1.7млн строк и 6 столбцов.
Вывожу на разные листы одной книги Calc приблизительно по 280 тыс строк. Где-то больше, где-то меньше. Всего 9 листов.
На всё, вместе с красотой, уходит 12-15 мин.

Таким образом, деградация скорости происходит при выводе 900 тыс строк на один лист. Первые 200-300 тыс выгружает быстро, а дальше на что-то теряет время. То есть по мере удаления вставляемых диапазонов ячеек от начала листа, скорость падает.
Записан
zmeishe
Участник
**
Offline Offline

Пол: Мужской
Расположение: Нижний Новгород
Сообщений: 8



« Ответ #7: 3 Декабрь 2019, 13:32 »

Так соберите отладочную сборку ЛО

Это крайний случай. Пока надеюсь на помощь. Может кто-то уже догадался куда копать.
Записан
kompilainenn
Мастер
*****
Offline Offline

Сообщений: 2 777



« Ответ #8: 3 Декабрь 2019, 15:56 »

В исходный код копать и отладку:’(
Записан

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

Пол: Мужской
Расположение: Нижний Новгород
Сообщений: 8



« Ответ #9: 3 Декабрь 2019, 20:39 »

Я его поборол.

Вывел 900 тыс строк в 20 столбцов меньше чем за минуту. Причём, вывел со всеми прибамбасами форматирования.
И заметьте, это много быстрее чем через файл CSV.

Стал выводить не блоками в несколько тысяч строк и в 20 столбцов, а блоками в 900 тыс строк и в один столбец.
Заметил следующее.
Он уходит в "даун" на пустых ячейках. Столбцы, где каждая ячейка имеет значение он выводит за 1-2 сек на 900 тыс строк.
Пустым ячейкам с числами, датами и временем  я присвоил значение 0.
Пустым ячейкам со строками я присвоил значение "-".
А до этого я присваивал пустые кавычки "". Вот тут-то он и начинал "дурить" более часа.

Сейчас такое неудобство. Нулевые даты выглядят 30.12.1899. Нулевое время 00:00:00.

Подскажите, что следует присвоить элементу массива для функции setDataArray, чтобы ячейка была пустой для дат, времени, строк?

У элемента массива есть функция clear(), но тогда для этой ячейки Calc выведет что-то вроде #N/A или #Н/Д. Это некрасиво. Что ему присвоить, чтобы было пусто?

« Последнее редактирование: 3 Декабрь 2019, 20:56 от zmeishe » Записан
mikekaganski
Мастер
*****
Offline Offline

Пол: Мужской
Расположение: Хабаровск -> Москва
Сообщений: 1 621


« Ответ #10: 3 Декабрь 2019, 20:54 »

Не могу воспроизвести.

Код:
sub DataArray
  doc = ThisComponent
  range = doc.Sheets(0).getCellRangeByPosition(0,0,0,900000-1)
  dim data(0 to 900000-1)
  for i = 0 to 900000 - 1
    data(i) = array("")
  next i
  t = now()
  range.setDataArray(data())
  MsgBox Format(now() - t, "ss "" s""")
end sub

даёт на чистом листе 3 с (естественно, я не учитываю начальный этап по заполнению массива - в Basic это значительное время, но тоже в пределах 3-4 с).

Замена "" на empty не меняет картину.
Записан

С уважением,
Михаил Каганский
zmeishe
Участник
**
Offline Offline

Пол: Мужской
Расположение: Нижний Новгород
Сообщений: 8



« Ответ #11: 3 Декабрь 2019, 21:14 »

У меня SDK C++. Пустые кавычки или пробел в кавычках сносят Calc`y башню.
У меня там массив массивов или массив перечислений.
Выглядит это так
 Sequence<Sequence< Any >> aRowsArray( rowCount );
 Sequence< Any  > aRowValues( columnCount );

Для эксперимента с выводом блоками по одному столбцу
 Sequence<Sequence< Any >> aRowsArray( rowCount );
 Sequence< Any  > aRowValues( 1 );

У этого типа данных Any есть функция clear(), но она не подходит из-за вывода в ячейки значений #N/A или #Н/Д - не комильфо.
Вот что ему присвоить, чтобы было и быстро и пусто?




Записан
Bigor
Опытный пользователь
***
Offline Offline

Пол: Мужской
Сообщений: 771


« Ответ #12: 3 Декабрь 2019, 21:47 »

Не могу воспроизвести.
Вот так воспроизводится

Код:
sub DataArray
  doc = ThisComponent
  range = doc.Sheets(0).getCellRangeByPosition(0,0,0,500000-1)
  dim data(0 to 500000-1)
  for i = 0 to 500000 - 1
     If i mod 10 = 0 Then
     data(i) = array("")
     Else
     data(i) = array(i)
     End if
  next i
  Print "Go"
  t = now()
  range.setDataArray(data())
  MsgBox Format(now() - t, "ss "" s""")
end sub

в данном виде 28 с
если data(i) = array("") заменить на data(i) = array(i)
то около 3 с

зы формат первого столбца дата
« Последнее редактирование: 3 Декабрь 2019, 21:48 от Bigor » Записан
mikekaganski
Мастер
*****
Offline Offline

Пол: Мужской
Расположение: Хабаровск -> Москва
Сообщений: 1 621


« Ответ #13: 3 Декабрь 2019, 21:56 »

Bigor: Спасибо!
Записан

С уважением,
Михаил Каганский
mikekaganski
Мастер
*****
Offline Offline

Пол: Мужской
Расположение: Хабаровск -> Москва
Сообщений: 1 621


« Ответ #14: 3 Декабрь 2019, 22:49 »

Замедление вижу, надо поковыряться.

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

Код:
sub DataArray
  doc = ThisComponent

  range = doc.Sheets(0).getCellRangeByPosition(0,0,0,900000-1)
  cell = range.GetCellByPosition(0, 0)
  locale = doc.NumberFormats.getByKey(cell.NumberFormat).Locale
  nFmtId = doc.NumberFormats.queryKey("0;-0;", locale, False)
  if nFmtId = -1 then _
    nFmtId = ThisComponent.NumberFormats.addNew("0;-0;", locale)
  range.NumberFormat = nFmtId

  dim data(0 to 900000-1)
  for i = 0 to 900000 - 1
    if (i mod 10 = 0) Then data(i) = array(0) else data(i) = array(i)
  next i
  t = now()
  range.setDataArray(data())
  MsgBox Format(now() - t, "[ss] "" s""")
end sub
Записан

С уважением,
Михаил Каганский
Страниц: 1 2 »   Вверх
  Печать  
 
Перейти в:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.21 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!