среда, 21 августа 2019 г.

ToDo. Заменить где возможно memoryChain на TReadOnlyBuffer

Заменить где возможно memoryChain на TReadOnlyBuffer.

ToDo. Сделать константные буфера

Сделать константные буфера.
Которые пишутся только при чтении из файла. А потом "закрываются" через VirtualProtect.
Чтобы пользователь буфера не смог его испортить.
По аналогии с sharedConstString.

Типа:

var
 Buffer : TBuffer;
 Processor: TSomeMemPoolProcessor;
 aStream: IStream;
While true do
Buffer := TBuffer.Create(aStream);
// - создаётся буфер с фреймом из файла.
// там внутри VirtualAlloc и VirtualProtect.
// которые делают mem_readOnly
If Buffer = nil then Exit;
// - если ничего не прочитали, то выходим
Processor.DoBuffer(Buffer.AsPointer);
// - там буфер доступен только на чтение
Buffer.Free;
// - освобождаем буфер
end;// - переходим к следующему фрейму

Там естественно try..finally, чтобы буфер не тёк.

четверг, 15 августа 2019 г.

Хоккей с памятью и методами

Научился сегодня делать интерфейсы "на лету" для классов, которые не поддерживают интерфейсы "стандартным образом".

Получилось что-то типа TVirtualInterface.

Только со связыванием в Compile-Time.
Почти. Но On Demand.

Про реализацию - чуть позже напишу.

Побочным эффектом получилось, что можно отдавать класс "как интерфейс", но без лишнего подсчёта ссылок. Делегат что ли это называется.

Грубо говоря у класса получаются ДВЕ реализации IUnknown, одна с подсчётом ссылок, а другая - БЕЗ оного.

Чем то схоже с Protocol в Objective-C.

Ну и DuckTyping там где-то рядом.

Класс может выдать себя в качестве "утки, которая умеет махать крыльями".

При этом он не является IDuck или TDuck.

Построено всё на перекрытии NewInstance и распределении дополнительной памяти "за объектом". И в этой дополнительной памяти "варим" виртуальные таблицы для каждого из "интерфейсов"/protocol'ов. По образу и подобию того как это в Delphi сделано, только эта таблица инициализируется "на лету" из метода FillProtocolVMT. Туда пихаются указатели на методы нашего объекта.

Можно в принципе вообще "на лету" варить такие таблицы, совсем "onDemand". Например в QueryInterface. Только я пока не придумал зачем.

Ну и пока у меня есть ограничения на типы и количество параметров. Таких методов.

Попутно я научился цеплять к каждому классу свой менеджер памяти. С возможностью кеширования только определённого количества экщемпляров. Ну и попутно научился делать память экземпляров immutable, через virtualAlloc и virtualProtect. Экземпляры таких классов реально immutable. Они могут модифицироваться только в конструкторах и деструкторах. А во всё остальное время жизни экщемпляров - они readOnly. Доступ к полям на запись, даже "случайный" вызывает pageFault.

То есть можно делать реально константные кешируемые объекты.

Ну это функциональными языками "навеяло".

Дальше можно делать expressionOnDemand. Выражения, вычисляемые и кеширумые по мере необходимости.

Правда вся эта конструкция пока несколько "шаткая" и до конца не отлажена, но ничего. Отлажу.

Для начала могу опубликовать реализацию реально константных кешируемых строк. Эта конструкция уже отлажена. Она в производстве уже год как.

пятница, 9 августа 2019 г.

Просто о сложном. О жизни и оптимизации. И получении от этого драйва и удовольствия

А ещё я ускорил работу нашего хранилища. И его копирование вместо 3х НЕДЕЛЬ (!) стало занимать 4 часа.
Поправил буквально 5 строчек кода. Но это вряд ли интересно.
Алгоритм маляра конечно же.
Я бы написал на эту тему. Но это вряд ли уже интересно.