-
Barloggg (18.06.09 16:01) [0]хорошая вещь как оказалось. теперь я многие свои файлы держу в текстовом формате чем-то напоминающем ini файлы. заголовок строки - знак разделитель - значение строки.
Прелесть.
ну вот например
ItemType=MixerItem
ItemOptions=MasterVolume||50|0|108|35|1|0|0|0|0|0|0||0|0||||||||||||0|112|0|0|0| 0|1|0|50|0|108|35|
ItemFontOptionsV2=Arial Baltic|0|10|0|0|0||0|0|0|2|0|0||0|0|0|0|0|
в одной строке хранится куча данных и изменение формата одной строчки не нарушает обратную совместимость с предыдущими файлами.
пока одна такая строка не оказалась размером в 500 килобайт.
и тут случилось неизбежное. ввиду конкретного зависания мне пришлось лезть в код и увидел я в методе Stream.ReadStr зловещий текстREPEAT
C := #0;
Read( C, 1 );
...
if C <> #13 then
Result := Result + C;
эмм.
есть какие-нибудь готовые решения для ускорения этого процесса?
я увидел у Thaddy модуль kolstream.pas а если быть точным то BufferedStream.
не очень четко представляю как этим пользоваться, но вот такая записьstrm:= NewReadFileStream(fname);
strm:= NewbufferedStream(strm,16000);
loadfromstream(strm);
strm.free;
быстродействия не прибавила.
похоже собака порылась именно в записи видаResult := Result + C;
что с этим можно сделать???
можно ли в потоке заниматься чисто поиском конца строки прежде чем?
спасайте люди добрые. -
У Вас что, смого духу не хватит написать несложную буферизацию загрузки строки своей процедурой, строк на 20? Я что-то уже совсем не понимаю. Базовая функциональность в предоставлена в ReadStrZ и иже с ними. Но на все потребности и все случаи все равно не напасешься. Тем более когда большая часть таких потребностей редко востребована, добавлять море кода для решения не возникающих каждодневно задач, тем более в библиотеку, стремящуюся к компактности - это неправильно.
П.С. Достаточно читать в глобавльный статический буфер на ~4K, хранить в нем позицию, при наличии данных в буфере брать из него, при недостатке читать очередную порцию. Прям задача для мозгового гиганта. -
Barloggg (19.06.09 09:25) [2]нет нет.
буферизованное чтение - для этого есть работа Thaddy. я с этим разобрался - приятная вещь.
на мой взгляд собака порылась именно в многодесятитысячном повторенииif C <> #13 then
Result := Result + C;
в рамках одного единственного вызова
а править код библиотеки - это моветон. -
Igor_123 (19.06.09 10:29) [3]Ну, если моветон, тогда терпеть как есть или писать свою библиотеку, в которой правка кода будет не моветон ;)
-
QAZ (19.06.09 10:29) [4]Stream.WriteStrEx
Stream.ReadStrEx
не судьба? -
Если в библиотеке чего-то не хватает, всегда можно написать свою процедуру. И вовсе необязательно всовывать её в библиотеку.
-
Barloggg (29.06.09 17:58) [6]да, попробую использовать readstrlen ну и иже с ним.
QAZ, спасибо.
Я сказал "моветон". вот что я имел ввиду. Ну, допустим внесу свои исправления в библиотеку, а потом выйдет новая версия и что я сделаю? скопирую файл поверх :)
и все мои изменения пойдут...
придется следить за изменениями и что самое важное - всегда таскать с собой измененную библиотеку при переходе с компа на комп. запара одним словом.
вот потому я не вношу изменения в библиотеку.
а писать свой метод для чтения и держать его у себя - это надо моск напрягать :) а это целое событие, к которому надо как следует готовиться, закупать пиво, готовить холодильник, подтаскивать его поближе к компу.
В общем для начала стоит спросить совета.
теперь задача номер два.
загрузил я строку быстро.
строка представляет собой вот такую записьColorPicturePixels=328|248|1189190,1189190,1189190,1189190,1254983,1254983 ,1254983
и так пятьсот килобайт такой мути. В цельной строке.
Это надо парсить.
сколько-то десятков тысяч вызовов Parse(str,',');
и что я вижу в kol.parse?Result := Copy( S, 1, Pos-1 );
Delete( S, 1, Pos );
и IndexOfCharsMin который тоже представляет собой нехилую процедурку.
чтение занимало раза в три больше времени чем распарсивание, а все вместе занимает время как попить чайку с пирожками. этак литра на полтора кружечку. В общем parse тоже нуждается в оптимизации.
эхх...
есть готовое решение теперь уже этой задачки? -
D[u]fa (29.06.09 18:40) [7]ну понятное дело что нету)) надо парсить "на лету" без Copy\Delete подобных функций
-
Barloggg (01.07.09 09:05) [8]ладно, ладно, всем спасибо.
сделал.
докладываю:
итак коль скоро мне не надо укорачивать мегастроку доставая из нее значения, то parse заменился на
parseresult:='';
while (megastr[pos]<>',')and(megastr[pos]<>#0) do inc(pos);
if (pos<>lastpos)and(megastr[pos]<>#0) then begin
parseresult:=copy(megastr,lastpos,pos-lastpos);
lastpos:=pos+1;inc(pos);
end else begin
megastr:='';exit;
end;
здесь сделано допущение, что string всегда оканчивается завершающим нулем посему всякие там length даже не вызываются - крутим до нуля, так быстрее.
второй тормоз как оказался - записать такую строку в поток.
поток создался как newmemorystream. десятки тысяч writestr(int2str()) занимают секунд пятнадцать.
однако запись в отдельную строку с предварительным setlength сразу на всю потребную длину этот вопрос решил. правда эту самую потребную длину пришлось сначала вычислить не прибегая к length(int2str()) для каждого значения.
итого классика жанра - либо расход памяти, либо расход проца.
в общем и целом теперь запись и чтение этой мегастроки занимают намного меньше времени. чаек попить уже не успеешь. успеешь разве что глазом моргнуть.
всем спасибо.
QAZ в особенности.