Гость
Форумы / PowerBuilder [игнор отключен] [закрыт для гостей] / ArrayToString / 25 сообщений из 25, страница 1 из 1
07.05.2010, 14:14
    #36617395
armblg
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ArrayToString
Всех приветствую!
Задача вроде простая - преобразовать строковый массив в одну строку, но наиболее быстрым способом. (ПБ8)
Имеем массив порядка неск. сотен строк (100 метровый файл), на выхлопе нужна строка (нюансы обработки опущены).
1.PFC функция inv_string.of_ArrayToString() - жуткие тормоза;
2.Тупой цикл по элементам массива и сложение в результирующую строку - совсем немного быстрее (с увеличением строки все медленнеее цикл. Видимо менеджер памяти ПБ далеко не эталон);
3.Использование буферной переменной длиной 50000 символов (значение получено опытным путем) дает выигрыш в скорости раз в пять.
Пока работает третий вариант, но нужно еще быстрее, Вопрос - как?
Буду рад любым вариантам, (хоть через dw, хоть через диск, хоть на C вызовом из ПБ, хоть как, но надо быстрее) т.к. собственные мысли на исходе.
Хелп. Спасибо.
ЗЫ
Двухядерный проц загружен на половину - есть мысли распараллелить, но это не панацея
...
Рейтинг: 0 / 0
07.05.2010, 14:22
    #36617425
ono ?
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ArrayToString
через ДВ
dw1.object.data = sArray
string sLine = dw1.object.data

не помню уже синтакс (давно на ПБ уже писал)
но мы примерно так делали

правдо не уверен если это быстрее
...
Рейтинг: 0 / 0
07.05.2010, 14:29
    #36617449
Ikir
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ArrayToString
armblg,

Если сервер базы позволяет, то может он вернет уже сформированную строку?
...
Рейтинг: 0 / 0
07.05.2010, 14:41
    #36617490
armblg
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ArrayToString
Ikir,

нет сервера в данном случае, просто работа с текстовыми файлами средствами ПБ ((
...
Рейтинг: 0 / 0
07.05.2010, 14:48
    #36617515
Ikir
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ArrayToString
armblg
нет сервера в данном случае, просто работа с текстовыми файлами средствами ПБ ((

То есть вы хотите ускорить операцию чтения из файла?
А приведите код, формирующий буферную переменную.
...
Рейтинг: 0 / 0
07.05.2010, 15:19
    #36617650
armblg
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ArrayToString
Ikirarmblg
нет сервера в данном случае, просто работа с текстовыми файлами средствами ПБ ((

То есть вы хотите ускорить операцию чтения из файла?
А приведите код, формирующий буферную переменную.
Нет. Чтение из файла выполняю при помощи ImportFile в дастору, что достаточно быстро. Именно массив в строку тормозит.
Кода сию минуту под рукой нет, но примерно так;
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
...
lds.ImportFile(....)
lsa_body[] = lds.Object.имя_столбца.Primary.Current
....
//Обработка строк
....
ll_ub = UpperBound(lsa_body[])
For i =  1  To ll_ub
  ls_buff += lsa_body[i]
  If Length(ls_buff) >  50000  or i = ll_ub Then
     ls_return += ls_buff
     ls_buff = ''
  End If
Next

Return ls_return
...
Рейтинг: 0 / 0
07.05.2010, 16:03
    #36617766
spas2001
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ArrayToString
В string нормально умещается 32 Kb так что делать Length лучше как-то убрать, возможно будет быстрее, вы же не будете каждый раз высчитывать длину строки
И может быть просто в цикле пройти по datastore не загоняя в промежуточный массив
...
Рейтинг: 0 / 0
07.05.2010, 16:14
    #36617805
armblg
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ArrayToString
spas2001В string нормально умещается 32 Kb так что делать Length лучше как-то убрать, возможно будет быстрее, вы же не будете каждый раз высчитывать длину строки
И может быть просто в цикле пройти по datastore не загоняя в промежуточный массив
Согласен, вычислять длину нужно к примеру раз в 1000 итераций (код сокращен), но скорости это не прибавляет почти((
Цикл по датасторе и считывание из каждой ячейки медленнее работы с массивом, данные в который загоняются одной командой, это проверено. Причем GetItemString() быстрее чем dot notation, хотя в книжках обычно утверждается обратное.
...
Рейтинг: 0 / 0
07.05.2010, 16:18
    #36617816
armblg
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ArrayToString
Добавлю еще что изменение размера буфера с 30000 до 60000 особых результатов так же не дает, за этими границами скорость падает((
...
Рейтинг: 0 / 0
07.05.2010, 16:34
    #36617862
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ArrayToString
Скорость деградирует из-за того что при каждом добавлении строки результат получается копированием из старой строки, а она постоянно растет.

Попробуйте следующий прием.
1) Пройтись в цикле по массиву и рассчитать суммарную длину строк
2) Выделить blob таким размером: lbb = blob(space(ll_total_len))
3) Пройтись в цикле по массиву и используя BlobEdit вставить каждую строку в ее позицию в блобе.
4) Преобразовать блоб в конечную строку ls_res = string(lbb)
...
Рейтинг: 0 / 0
07.05.2010, 16:37
    #36617867
spas2001
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ArrayToString
Вариант интересный, должно работать быстрее
...
Рейтинг: 0 / 0
07.05.2010, 16:46
    #36617886
armblg
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ArrayToString
Anatoly Moskovsky,

Спасиб за свежую идею, обязательно попробую и отпишусь, но вероятно уже после праздников.
...
Рейтинг: 0 / 0
07.05.2010, 16:54
    #36617904
Ikir
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ArrayToString
Anatoly MoskovskyСкорость деградирует из-за того что при каждом добавлении строки результат получается копированием из старой строки, а она постоянно растет.


+1

Я бы попробовал:
1.Каким-нибудь sed-ом убрал из файла символ конец строки
2.Fileread-ом в режиме !Stream загнал бы в блоб по максимальным порциям( в PB6 32К)
3.Преобразовал блоб в string.
...
Рейтинг: 0 / 0
07.05.2010, 17:00
    #36617920
Локшин Марк
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ArrayToString
Anatoly MoskovskyСкорость деградирует из-за того что при каждом добавлении строки результат получается копированием из старой строки, а она постоянно растет.

Попробуйте следующий прием.
1) Пройтись в цикле по массиву и рассчитать суммарную длину строк
2) Выделить blob таким размером: lbb = blob(space(ll_total_len))
3) Пройтись в цикле по массиву и используя BlobEdit вставить каждую строку в ее позицию в блобе.
4) Преобразовать блоб в конечную строку ls_res = string(lbb)
Я пробовал аналогичную идею с Replace'ом - у меня получилось дольше чем тупо склеить. К тому же с такими объемами данных PB начинает клинить. Можно было бы склеивать как-то таким образом - склеить 2 строки в 1, оставшиеся (в 2 раза меньше) склеить 2 в 1 и т.д. (таким образом минимизируем количество склеек больших строк), но PB от такого у меня просто валится...
...
Рейтинг: 0 / 0
07.05.2010, 17:04
    #36617930
armblg
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ArrayToString
IkirAnatoly MoskovskyСкорость деградирует из-за того что при каждом добавлении строки результат получается копированием из старой строки, а она постоянно растет.


+1

Я бы попробовал:
1.Каким-нибудь sed-ом убрал из файла символ конец строки
2.Fileread-ом в режиме !Stream загнал бы в блоб по максимальным порциям( в PB6 32К)
3.Преобразовал блоб в string.
Зря смеетесь, с памятью действительно так и есть((
Чтение из файла в любом случае получается медленне чем Импортфайл в датастору, и потом мне обязательно нужна обработка строк, поэтому массив или датастора необходимы, а строка нужна только на выходе.
...
Рейтинг: 0 / 0
07.05.2010, 17:42
    #36617982
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ArrayToString
Быстрее всего будет модификация моего предыдущего варианта с использованием внешних функций.

1) Рассчитать суммарную длину строк во внешней ф-и №1
2) Выделить строку с таким размером
3) Во внешней ф-и №2 заполнить эту строку из массива

Вот примерный код этих внешних ф-й
Код: plaintext
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.
// на С++

#define EXPORT extern "C" __declspec(dllexport)
#define PBCALL __stdcall

EXPORT size_t PBCALL calcTotalSize(TCHAR* arr[], size_t arraySize)
{
  size_t totalSize =  0 ;
  for (size_t i =  0 ; i < arraySize; i ++) {
    totalSize += _tcslen(arr[i]);
  }
  return totalSize;
}

EXPORT void PBCALL copyArr(TCHAR* arr[], size_t arraySize, TCHAR res[])
{
  size_t pos =  0 ;
  for (size_t i =  0 ; i < arraySize; i ++, pos += len) {
    size_t len = _tcslen(arr[i]);
    memcpy(&res[pos], arr[i], len * sizeof(TCHAR));
  }
}

// В PB
Function ulong calcTotalSize(readonly string arr[], ulong size) alias for "_calcTotalSize@8" library "utils.dll"
Subroutine copyArr(readonly string arr[], ulong size, ref string res) alias for "_copyArr@12" library "utils.dll"

ll_tot_size = calcTotalSize(ls_arr[], UpperBound(ls_arr[]));
ls_res = space(ll_tot_size) 
copyArr(ls_arr[], UpperBound(ls_arr[]), ref ls_res)

...
Рейтинг: 0 / 0
07.05.2010, 18:30
    #36618026
Филипп
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ArrayToString
armblg
Чтение из файла в любом случае получается медленне чем Импортфайл в датастору, и потом мне обязательно нужна обработка строк, поэтому массив или датастора необходимы, а строка нужна только на выходе.
С учётом этого, и того факта, что строковые операции в РВ - самые медленные, я бы развил идею Анатолия ещё дальше, а именно - после вышеуказанной обработки строк в датасторе (обязательно нужна :-)), делать datastore.SaveAS в файл, а уже этот файл обрабатывать специально написанной DLLкой, которая и выдаст склеенную строку.
...
Рейтинг: 0 / 0
07.05.2010, 19:09
    #36618056
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ArrayToString
Филиппделать datastore.SaveAS в файл, а уже этот файл обрабатывать специально написанной DLLкой, которая и выдаст склеенную строку.
Ну в данном случае думаю что получение строкового столбца DS через DOT нотацию в массив строк будет существенно быстрее чем SaveAs + чтение из файла в DLL.
Код: plaintext
1.
2.
3.
4.
ls_arr = lds.object.text_col[ 1 , lds.RowCount()]
ll_tot_size = calcTotalSize(ls_arr[], UpperBound(ls_arr[]));
ls_res = space(ll_tot_size) 
copyArr(ls_arr[], UpperBound(ls_arr[]), ref ls_res)
...
Рейтинг: 0 / 0
07.05.2010, 19:50
    #36618088
armblg
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ArrayToString
Имхо, вариант с внешними функциями довольно перспективен. Очень надеюсь на достойную скорость. Проверю, как уже говорил, позже.
...
Рейтинг: 0 / 0
11.05.2010, 18:08
    #36621703
armblg
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ArrayToString
Сравнил три варианта для контрастности оценки: 1 - через BlobEdit, 2 - через внешние С функции, 3 - как былО. Загонял два файла 44М и 88М в массив, потом массив в строку. Время засекал только для преобразования массива в строку. Итак:
44М
1) 1.9 сек;
2) 0.25 сек;
3) 45 сек.

88М
1) 3.9 сек;
2) 0.5 сек;
3) 175 сек + жуткий своп.

Налицо преимущество использования внешних функций, но вариант с BlobEdit тоже порадовал скоростью, не ожидал. К сожалению последнее преобразование ls_res = string(lbb) для 88М файла валит програму - приходится преобразовывать частями что замедляет.

В общем, всем спасибо за участие. Anatoly Moskovsky спешиал сенкс за идеи и примеры С-шных функций, при моем довольно слабом С они были кстати.
...
Рейтинг: 0 / 0
11.05.2010, 19:28
    #36621867
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ArrayToString
armblgК сожалению последнее преобразование ls_res = string(lbb) для 88М файла валит програму - приходится преобразовывать частями что замедляет.

Скорее всего это связано с тем что к тому моменту память процесса уже фрагментирована настолько что невозможно выделить непрерывный кусок нужного размера.

Само преобразование ls_res = string(lbb) при достаточной памяти работает и на сотнях МБ
...
Рейтинг: 0 / 0
12.05.2010, 00:25
    #36622167
AIS
AIS
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ArrayToString
armblg ,
а что вы имеете ввиду под " обработкой строк "? Предчувствую, что там тормоза должны быть намного круче, чем процесс который их собирает потом в одну строку.
...
Рейтинг: 0 / 0
12.05.2010, 07:32
    #36622288
armblg
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ArrayToString
AIS armblg ,
а что вы имеете ввиду под " обработкой строк "? Предчувствую, что там тормоза должны быть намного круче, чем процесс который их собирает потом в одну строку.
К счастью, в данном случае когда такой большой объем, обработка минимальна - некоторые строки пропустить, вырезать какие-то символы, в общем мелочевка по сравнению с временем формирования строки, которое было первоначально. При более сложных обработках размер результирующей строки мал и Пб приемлимо быстро ее выполняет.
...
Рейтинг: 0 / 0
12.05.2010, 11:41
    #36622708
armblg
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ArrayToString
Anatoly Moskovsky,
Возможно что и так, хотя с чего бы вдруг? Память выделена одним куском, и запись идет по определенным адресам, при преобразовании в строку достаточно еще раз выделить сравнимый объем. Это много дешевле сложения огромных строк в памяти когда там наверняка каша, однако ничего не валится.
Может это в старенькой восьмерке ограничения или баги.
...
Рейтинг: 0 / 0
12.05.2010, 12:09
    #36622823
Локшин Марк
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ArrayToString
armblgAnatoly Moskovsky,
Возможно что и так, хотя с чего бы вдруг? Память выделена одним куском, и запись идет по определенным адресам, при преобразовании в строку достаточно еще раз выделить сравнимый объем. Это много дешевле сложения огромных строк в памяти когда там наверняка каша, однако ничего не валится.
Может это в старенькой восьмерке ограничения или баги.
Не умеет PB нормально работать с памятью. Криво все работает и постоянно падает в любом месте. 11 например падает при выражении s1 = s + s + s + s + ... + s, когда в s строка в 1 МБ а количество сложений порядка 50-60.
...
Рейтинг: 0 / 0
Форумы / PowerBuilder [игнор отключен] [закрыт для гостей] / ArrayToString / 25 сообщений из 25, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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