![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
DeleteStr & PChar
nice © (2004-05-11 09:19:00)Народ подскажите, а то уже четвертый день борюсь.
Пишу парсер, и когда дело доходит до файлов >400KB с частым вхождением удаляемой/заменяемой строки, моя процедура работает оочень медленно~15сек.
До этого использовал string, но система вообще не выносимо тормозила, перевёл проект на PChar, но работал с ним мало :( посмотрите, что ни так в процедуре(может по pchar статейки какие есть):
procedure DeleteStr(var src:PChar;const DelStr:PChar);
var
posInStr,lenText,lenDelSTR:dword;
strTemp:PChar;
begin
lenText:=StrLen(src);lenDelSTR:=StrLen(DelStr);GetMem(strTemp,lenText);
posInStr:=StrPosInt(StrLower(src),DelStr);// Поиск первого вхождения
while posInStr>0 do begin // разбиваем строку
lenText:=StrLen(src);
strCopy(strTemp,@src[posInStr]);
src[posInStr-lenDelSTR]:=#0; // обрезаем оригинал
StrLCat(src,strTemp,lenText); // складываем
posInStr:=StrPosInt(StrLower(src),DelStr);// Поиск следующего вхождения
if posInStr>=lenText then break;
end;
Freemem(strTemp);
end;
StrPosInt -это аналог strPos на ассемблере, только заставил возвращать положение в строке, может зря?
Yury Sidorov (2004-05-17 10:48:00) [1]Функции для работы с PChar начинают трормозить при длинных строках, т.к. эти функции сначала ищут конец строки, а потом делают свое действие. Для длинных строк лучше использовать свои функции, которые в одном цикле сразу проверяют конец строки и выполняют действие. Кстати, для обычных строк для определения длины строки никакого поиска делать не нужно. Функция Length() возвращает длину, записанную в заголовке строки. Исходя из этого, для поиска символа в строке максимально эффективно нужно определить длину строки через Length(), а потом делать поиск с помощью REPNE SCASB по буферу известной длины.
nice (2004-05-17 01:22:00) [2]Вот что я наклепал, работает 2,5сек на файле в 450Кб с частым вхождением :)
Для меня это большой прогресс.
Посмотрите пожайлуста, может я чего лишнего намудрил
function DeleteStrDoChar(const src,DelStr:PChar;const DoChar:Char):PChar;assembler;
asm
PUSH EAX
PUSH EDI
PUSH ECX
OR EAX,EAX // eax=src
JE @@BAD
OR EDX,EDX // edx=DelStr
JE @@BAD
PUSH EDX // edx v stek
MOV ESI,EAX // запомнили eax
XOR ECX,ECX // с нулевой позиции
CALL StrPos // делаем поиск
CMP EAX,-1
JZ @@NoStr // строка не найдена? прыжок
XOR EBX,EBX
@@nextPos:
CLD // очищаем флаг направления
ADD EAX,EBX
PUSH EAX // posStr
LEA EDI,[ESI+EAX] // EDi -> src[posStr]
PUSH ESI // запомнили src[0]
SUB ECX,EAX // ecx=кол-во итераций
MOV EAX,EDI
MOV dl,DoChar
CALL StrScan // Находим последний символ удаляемой подстроки
MOV ESI,EAX // <span..... !>!
INC ESI
REP MOVSB // Обрезали
POP EAX // Востановили src[0]
MOV ESI,EAX
POP ECX // Востановили счетчик
POP EDX // Востановили DelStr
PUSH EDX
MOV EBX,ECX
CALL StrPos // ищем очередное вхождение
CMP EAX,-1
jnz @@nextPos
@@NoStr:
POP EDX
@@BAD:
POP ECX
POP EDI
POP EAX
end;
Gandalf (2004-05-16 23:39:00) [3]KOL - один большой пример
nice (2004-05-16 21:50:00) [4]Ф-ия вернет в Eax указатель на выделенный диапазон?
У неё вроде 2 параметра...
У вас нет примерчика какого-нибудь???
Vladimir Kladov (2004-05-16 21:45:00) [5]если хотите скорости, надо избавляться от выделения/освобождения памяти - это и есть основной тормоз при парсинге.
MOV EAX, size
CALL System.@GetMem
nice (2004-05-16 21:30:00) [6]Хотел спросить как в асмовской подпрограмме выделить память для строки PChar?
Как правильно вызвать GetMem?
И можно использовать var?
function DeleteStr(src:PChar;strDel:PChar):PChar;assembler;
var
tempStr:PChar; ????????
SPeller (2004-05-16 17:33:00) [7]Во-во, не зря kol.pas в двух версиях идёт.
nice (2004-05-16 16:30:00) [8]Delphi5.01
проверил я твой метод хешей, работает он медленне чем простым прохождением по строке, может это на String верно, но на PChar точно проигрывает. Переписал несколько процедур на асм, производительность выросла на порядок, до тестю выложу на ftp если интересно кому.
Viman (2004-05-12 10:21:00) [9]Угу. Либо по-русский, либо natural english. А то этот псевдоиврит(псевдотранслит) очень тяжко читать... Тем более, что для транслита тоже есть свои правила.
SPeller (2004-05-12 02:48:00) [10]2 Delphi5.01
Начинай писать на русском, иначе твои посты на транслитерации будут удаляться.
nice (2004-05-11 16:55:00) [11]Delphi5.01 ©
Пасибо брат, вполне логично, буду переделывать.
Delphi5.01 (2004-05-11 16:35:00) [12]http://www.delphimaster.ru/cgi-bin/forum.pl?id=1080931846&n=10
Delphi5.01 (2004-05-11 16:28:00) [13]Vo eto slishkom lamerski poisk!
posInStr:=StrPosInt(StrLower(src),DelStr);// Поиск следующего вхождения
Podskaju StrPosInt kajdi raz s samogo nachala nachinaet poisk, a znachit esli str do 2mb to poluchaem chto dla nahojdenia poslednego simvola on doljen proitis po vsemu tekstu!!! Ludshe organizovivat for i:=1 to Length() do ili while do!
raznica gdeto 150 raz!!!! :-)))
Sorry za translit.
Da esli nujen bisti metod to, ia uje otvechal na etot vopros na forume est. Poishite poisk metobom hesha on daje bistrei for i:=1 to Length() do okolo 20 raz! Odnim slovom zdes nujni algoritmi bistrogo poiska a eto uje ne v etom forume eto nado zadachi po olimpiade iskat i ih reshenia!
Jelau udachi
sorry za translit!
Delphi5.01 (2004-05-11 16:25:00) [14]Vo eto slishkom lamerski poisk!
posInStr:=StrPosInt(StrLower(src),DelStr);// Поиск следующего вхождения
Podskaju StrPosInt kajdi raz s samogo nachala nachinaet poisk, a znachit esli str do 2mb to poluchaem chto dla nahojdenia poslednego simvola on doljen proitis po vsemu tekstu!!! Ludshe organizovivat for i:=1 to Length() do ili while do!
raznica gdeto 150 raz!!!! :-)))
Bez (2004-05-11 12:43:00) [15]извините, заглючило что то :(
Bez (2004-05-11 12:43:00) [16]Вчера появилась проблема со событием OnResize
В этом событии пытался задавать положение элементов на форме, что бы, например, при изменении размеров кнопка находилась в нижнем правом углу и рядом сней еще одна кнопка...
Так вот, прога компилится нормально, но когда запускаешь ее на выполнение, то происходит ошибка.... (Access voilative....)
В VCL все было Ок.
Может кто что подскажет?
nice (2004-05-11 11:38:00) [17]SPeller ©
Вместо 31,8 -> 30.2sek.
Я просто пробовал в фаре этот же файл мучить, фар делает эту операцию мгновенно!
Причем не просто удаление а замену
SPeller (2004-05-11 11:07:00) [18]Для ускорения работы со строками и прочими частыми выделениями небольших блоков памяти можно надо подключить стандартный дельфийский менеджер памяти. Для этого можно сделать отдельный юнит, в его разделе initialization прописать функцию UseDelphiMemoryManager и вставить этот юнит первым в разделе uses проекта. Можно, конечно, прописать вызов этой функции и в самом начале проекта перед любымидругими действиями.