Конференция "KOL" » Stream.ReadStr
 
  • 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;


    что с этим можно сделать???
    можно ли в потоке заниматься чисто поиском конца строки прежде чем?

    спасайте люди добрые.
  • Vladimir Kladov © (18.06.09 19:27) [1]
    У Вас что, смого духу не хватит написать несложную буферизацию загрузки строки своей процедурой, строк на 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
    не судьба?
  • Vladimir Kladov © (19.06.09 16:28) [5]
    Если в библиотеке чего-то не хватает, всегда можно написать свою процедуру. И вовсе необязательно всовывать её в библиотеку.
  • 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 в особенности.
Есть новые Нет новых   [134431   +10][b:0][p:0.002]