Хранение строк в контроле.

Тема в разделе "WASM.WIN32", создана пользователем n0name, 26 авг 2006.

  1. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    Сомневаюсь в выборе алгоритма хранения строк.
    Можно сделать как в LinePad'e, то есть выделяется один буффер с указателями на описания строк. А сами эти описатели вместе с строками хранить в куче. Однако так будет довольно трудно хранить большие объемы информации. Какие есть альтернативы?
     
  2. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    А зачем кроме строк, и указателей, ещё и описатели? Для лишнего тормоза?
    Чтобы выбрать оптимальное, нужно определиться с тем, как будет осуществляться доступ к строкам, как они будут добавляться, удаляться и т.п.
     
  3. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    В них я храню длину строки и размер выделенного буфера(выравнивание 32 байта).
     
  4. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    А почему нельзя на манер борланда, хранить длину в первом дворде перед строкой. Так же кстати, и формат bstr работает:
    StrAddr - адрес начала строки
    dword ptr[StrAddr-4] - длина строки.
    И адресуешь либо StrAddr, если нужна строка, либо StrAddr-4, если нужна длина.
     
  5. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    Ну я примерно так и делаю.
    TLine = packed record
    LineLen: DWORD;
    MemSize: DWORD;
    Str: array [0..0] of char;
    end;

    Но это мелочи, всё таки можно как то поэффективнее(чтобы побыстрее работало) хранить строки.
    У меня был вариант хранить не отдельно строки, а завести один буфер, и в массиве хранить номера первых символов строк.
     
  6. AsmGuru62

    AsmGuru62 Member

    Публикаций:
    0
    Регистрация:
    12 сен 2002
    Сообщения:
    689
    Адрес:
    Toronto
    Есть разные модели хранения строк. На мой взгляд лучше всего хранить вектор адресов, где каждый адрес указывает на описатель такого типа:
    Код (Text):
    1. typedef struct
    2. {
    3.     header, containing line information: (room, length, collapsed, bookmarked, etc.)
    4.     CHAR Text [2];
    5. }
    6. LINEDEF;
    Размер аллокации = длина текста (выровненная на 16) + sizeof (LINEDEF);

    Если сделать собственный аллокатор, чтобы уменьшить избытки от Win32 HeapAlloc() - может получиться оптимально даже для больших файлов.
     
  7. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Такой вариант: выделять сразу относительно большой (на n строк) объём памяти, когда отпадает необходимость в строке, не освобождать память, занимаемую ею, а помечать как свободный этот участок. Полное удаление всего массива - в конце работы программы одним вызовом VirtualFree.

    Сделать массив таких описателей:
    Код (Text):
    1. s STRUCT
    2.     maxLen  DWORD
    3.     len     DWORD
    4.     sPtr    DWORD
    5.     empty   DWORD
    6. s ENDS
    При "удалении" строки, просто заносить в empty -1, как индикатор.
    При добавлении просматривать массив описателей на предмет if ( empty && maxLen >= newStrLen). Если найден соответствующий - записать в него данные новой строки, а саму строку записать поверх старой. Если нет удовлетворяющего условию - выделять новый кусок.
    maxLen будет равно len при первом заполнении памяти строками, при остальных - больше.

    Думаю, на отказе от постоянного выделения и освобождения будет сэкономлено достаточно много времени.
     
  8. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    А встроенный Memory Manager так не делает (встроенный в Delphi)?
    Насколько я помню, он также помечает блок освобожденным.
    AsmGuru62 я пока так и делаю.
     
  9. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Как делает делфийский - не знаю, но на мой взгляд это много правильнее постоянных выделений/освобождений. Каждый вызов Virtual/HeapAlloc - это тысячи и десятки тысяч тактов. Поэтому логично свести количество вызовов к паре-тройке, чем вызывать для каждой строки.
     
  10. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    А не проще sPtr = 0?
     
  11. Jupiter

    Jupiter Jupiter

    Публикаций:
    0
    Регистрация:
    12 авг 2004
    Сообщения:
    532
    Адрес:
    Russia
    очевидно, что проще, но, видимо, cresta хотел выровнять структуру (4x4) или для чего-то знать значение sPtr при empty -1 (вот только зачем?)
     
  12. AsmGuru62

    AsmGuru62 Member

    Публикаций:
    0
    Регистрация:
    12 сен 2002
    Сообщения:
    689
    Адрес:
    Toronto
    Кстати, HeapAlloc() в RELEASE очень быстро работает.
    А в DEBUG-е тормозит по-страшному!