FireFenix писал(а):написать прослойку, где контролы в различных средах/os/редакторах выглядели бы одинаково, ну и слизать Win стили
Так речь не о VB, оказывается. Правильно?
FireFenix писал(а):А вот это интересно, не расскажешь?
Ну всё довольно просто устроено. (Особенно если вспомнить, что новые строки и их фрагменты только добавляются, а никакого редактирования/удаления нет.)
Хранилище строк у меня огранизовано как массив блоков, где каждый блок — это массив строк, где каждая строка — это массив фрагментов. Такой подход (массив массивов aka блочный список) выбран потому, что, если рассмотреть весь функционал, который вовлечён в добавление новых строк и их фрагментов, то оказывается, что самое времязатратное в этом — это итеративное увеличение массива на 1 элемент. И по этой причине от подхода, когда по факту добавления каждого нового элемента нужно realloc-чить/ReDim-ить массив на 1 элемент — надо бежать.
Чуть более умные люди всегда наращивают массив сразу на
тысячи большое блок новых элементов или же каждый раз вдвое. Но и от этого надо надо бежать в нашем случае (с миллионами лог-записей), потому что массив гарантирует непрерывность элементов в памяти, а ради этого, если при росте массива он своим концом упирается в занятый участок адресного пространства, приходится целиком переносить массив в другое место в АП. И в лучшем случае его приходится целиком копировать в новое место, а в худшем случае АП процесса вообще фрагментировано маленькими выделениями так, что во всём АП не найдётся одного протяжённого, достаточно длинного и непрерывного свободного участка под новый массив увеличенной длины. И тогда мы получим Out of memory при очередном увеличении. В общем, непрерывность массива в памяти в нашем случае нисколько не полезная, а наоборот, вредная черта.
Другое дело массив массивов. В этом случае верхний массив является по сути массивом указателей (на SAFEARRAY) и занимает не слишком много места — один элемент такого массива олицетворяет целый блок, который, в свою очередь, олицетворяет тысячи строк. Так что верхнеуровневый массив (массив блоков) наращивается не так часто, и размер имеет не такой большой. Сами же блоки — это отдельные небольшие массивы, которые дорастают до определённой величины, а дальше они не растут — начинает новый блок. Эти отдельные маленькие массивы могут в каком угодно месте АП размещаться, фрагментация АП на них никаких ограничений не накладывает. И что самое главное, для таких массивов можно сразу выделять столько места, сколько нужно, не делая ReDim на каждую новую строку.
Однако, в моём случае даже с такой организацией оказалось, что всё как-то слишком медленно — выяснилось, что конкатенация фрагментов строчек при формировании лога тоже съедает кучу времени. Допустим, код, работая 2 секунды, формирует миллион лог-строчек. И каждая строчка состоит из 10 фрагментов. Ну и зачем нам нужно при формировании лога делать конкатенацию этих фрагментов? Незачем.
Поэтому у меня в блоке дочерние элементы — строки — это тоже массивы, массивы фрагментов.
Дальше возникает две проблемы: при отображении из массива фрагментов нужно делать цельную строку. Но нужно делать это только с теми строками, которые сейчас отображаются. А это обычно 50 строчек из пары миллионов. Другой момент — это поиск по логу. Встроенная в VB реализация поиска по строке (InStr) всё равно быстрее, чем мы можем написать свою, а для InStr необходимо, чтобы строки были в цельном виде (т.е. склеены, а не в в иде массива фрагментов). Причём для поиска по логу нужно склеить как раз фрагменты всех строк, а не только тех, которые сейчас видимы.
Поэтому у меня использован подход с отложной (on-demand) дефрагментацией: после того, как наполнение лога закончено (или вышло из активной фазы), запускается таймер, которые проходит по всему логу и небольшими порциями проводит дефрагментацию. Кроме того, немедленной дефрагментации подвергаются те строки, которые попадают в текущую зону отображения (а это значит, что быстро поскроллив окошко с миллионами записей можно вызвать насильную дефрагментацию всего хранилища строк). Ну и запуск поиска принудительно дефрагментирует всё хранилище, при условии, что к моменту запуска поиска оно ещё не было дефрагментировано скроллингом или таймером.
FireFenix писал(а):1) сли ogl/dx/etc это GAPI, команды которых, драйвер "интерпретирует" на железе (видео карте), то с GDI всё как-то сложно. Если когда-то давно GDI был софтвраным, то сейчас там сложная развязка на WDDM и Direct[какой-то].
Я не задумывался над этим совершенно. Зачем? Если скорости вывода текста силами GDI совершенно хватает, а никакого сглаживания, никакой векторной графики и никаких причуд мне не надо. К тому же не совсем правильно говорить, что GDI был софтверным. Он всегда исполнение команд отдавал на откуп драйверу, а там уже дело за разработчиком драйвера.
По поводу п.2 — я не писал под X11, так что ничего не могу сказать.
По поводу п.3 — не очень понял конкретной подоплёки вопроса, но в общем случае это является фичей, если сообщения будут обрабатываться квази-асинхронно (PostMessage в случае с Windows). Обмен сообщениями — это ведь разновидность ООП, и при таком подходе обрабатывающую сторону не должно волновать, откуда пришло сообщение: если пришло, надо обработать как полагается.
По повоу п.4 — не понял вообще, возможно по причине несогласованности предложения.