Блочное сохранение в типизированный файл


#1

@Admin, похоже произошло недопонимание, из за того что вы не всё прочитали… Ниже идёт краткий обзор того о чём я говорил по этой теме. Постарайтесь в этот раз всё же прочитать всё, я и так сократил то что можно было, чтоб не терять смысла:

  • Я изначально считал file of T очередной старой плюшкой, которая в теперешних системах не даёт ничего, но после того как @RAlex объяснил мне для чего они и как работают - стало понятно что у них есть своя ниша из за скорости сохранения и загрузки (больше чем если через System.IO на прямую по 1 полю!), а так же того, что с ними сложнее сделать ошибку, чем если использовать System.IO на прямую.

    Но только если они будут сохранять блоками. Так как они сейчас работают - у них нет ни 1 преимущества. Хотя и сохранение по 1 полю имеет свои преимущества, к примеру его можно было бы реализовать как метод безтипового файла (file, без of T) и расширить возможности. Потому что таким способом можно сохранять и загружать любые объекты, даже классы. Что касается преимуществ над другими типами сериализации - этот находится под носом, и прост в использовании, в отличии от всяких библиотек. Но опять же, так как реализовано сейчас - эти преимущества не вступают в силу.

  • Сейчас string[5] при компиляции заменяется на string, которая класс, поэтому надо сделать свою строку на value-типе, чтоб блочное сохранение было возможно. Это не сложно, у меня получилось сделать это без сильной костылезации: MyShortString.pas.

    Увеличение размера исходников для коротких строк компенсируется уменьшением размера исходников типизированных файлов, которые будут с этими строками работать. И проблемы производительности с неэффективным доступом к символам - тоже компенсируется через скорость работы блочных типизированных файлов, ещё и с приростом скорости.

  • Я реализовал сохранение блоками, успешно протестировал его на правильность записи и загрузки (в том числе и коротких строк) и увидел прирост скорости в Release версии в 5-6 раз, по отношение к вашим file of T. Это считая что сейчас короткие строки реализованы не идеально, как минимум перевод в string и назад можно и надо улучшить. Это должно дать ещё прирост скорости в несколько раз.

    Я в любом случае буду встраивать подобный тип в свои программы, из за того на сколько он имбовый. Но я так же предложил добавить его как замену текущему file of T, он больше совместим со старыми паскалями (а точнее на 100%, потому что реализован по тому же принципу), даже на уровне бинарного кода получаемых файлов + превосходит по скорости текущую реализацию.

    Но вы ответили на это “нет, давайте сначала приделаем ещё несколько костылей к текущей реализации, чтоб этот мертвец, от которого ожидали человеческую речь, но пока что мог только мычать - смог ещё и гавкать. А потом уже, через несколько месяцев мы просто забудем про это подумаем, над тем чтоб полностью выкинуть текущие костыли (в том числе и те что сейчас добавляем) и заменить на реализацию у которой есть хоть какие то применения”.

Извиняюсь, за то что вставил кусок своих эмоций ближе к концу, но, по моему, моя мысль более понятна с ним, чем без него.


Я создал отдельную тему, чтоб то что идёт по этому поводу не смешивалось со всем остальным в теме под ошибки, потому что это уже произошло.

Ожидается, что тут будут сначала обсуждать чем блочное сохранение хуже чем по 1 полю (если такие пункты вообще можно найти, не высосав из пальца).
И потом, если всё же когда то дойдёт то того чтоб применить это как замену текущей реализации, обсуждать проблемы которые возникнут.


#2

А почему бы Вам не сделать для начала полную реализацию всего что Вы хотите в отдельном модуле с типом MyTypedFile ? Если это окажется удачным, то включим как стандартный модуль. Те, кому нужна скорость, будут пользоваться вашим модулем?


#3

@Admin, я продолжу настаивать, прочитайте до конца. Потому что я это уже сделал и написал об этом выше. Вы даже не попробовали потыкать на ссылки которые я привёл, мне ведь показывает что никто на них не тыкал.

Но, вы всё же говорите про то, чтоб сделать это как что то отдельное. Почему вы так не хотите заменить эту кривую реализацию на что то что работает как задумывал Вирт, даже если эта реализация не будет ни в чём уступать?


#4

FileStream и так буферизуется. Зачем нужны все эти костыли? И вы забыли про множества, которые тоже классы.


#5

Другое дело - запись конвертировать в массив байтов и писать в поток (если это быстрее будет). Но для не нужно никаких размерных строк.


#6

Я продолжу настаивать на своём предложении. Сделайте модуль. Добавьте в класс Reset, Seek и всё что считаете нужным. Напишите справку. Включу модуль в инсталлят.


#7

Да, вот только это не добавляет столько же производительности.

И это я тоже объяснил. Преимущества file of T состоят в Seek и скорости. Конвертация в массив байт тоже займёт время, когда это делается через указатели - это происходит на много быстрее.

Для начала, всё же, ответьте на мой вопрос - почему вы не хотите заменить свою реализацию моей? Назовите хоть 1 преимущество вашей реализации, что ли.

Сделал.Вторая ссылка в первом сообщение, попробуйте наконец всё же посмотреть на то что я вам кидал. Посмотрите как вам, проведите на своём компьютере тест скорости который я там собрал в файле test.pas. По крайней мере чтоб убедится что вас там всё устраивает. А может и чтоб увидеть что в вашей реализации нет преимуществ.


#8

какие указатели? запись имеет например поле типа класс (множества) или статический массив, или строка. не будут тут указатели работать. выигрыш три копейки


#9
  1. Множество имеет произвольную длину, как оно вообще может быть в типизированных файлах?
  2. Вот поэтому и надо сделать строку на value-типе. Посмотрите на тест производительности - это всё равно быстрее получается, хоть такая строка сама по себе не очень эффективна. И совсем не три копейки выйгрыш, а 5-6 раз.

#10

Я смотрел, не волнуйтесь так. У меня разница в скорости - примерно в 8 раз. С полем set of integer := [2…5] - в полтора раза хуже наоборот.

Есть простой принцип. Не менять то, что уже работает.


#11

Ваш способ не сохраняет приватные поля. Так что нет, он не работает. Точнее не всегда. Способ который закладывал Вирт - сохраняет приватные поля. Я это не кидаю в issue только потому что это невозможно исправить в вашем способе, никак.

Если так уж боитесь что будут баги у того что работало - зря, потому что я сразу сделаю все необходимые тесты, а не тогда когда эти баги появятся. И - в таком способе меньше проблем возникает. К примеру, те же статичные и константные поля правильно обрабатывает по умолчанию.

Или есть какая то другая причина? Процитирую, пожалуй, тут вас:

Правило ради правила ничего не стоит, в этом то вы со мной согласны? Так же, как и правило, которое именно в этой ситуации не работает.

Подождите, а как вы его вообще протестировали, с ним вообще должно не правильно сохранятся, set of T ведь ссылочный, нет?


#12

set of byte и set of char в файл сохраняются (сериализуются в битовую строку), как в старом паскале. по-моему, этого достаточно.


#13

А, понятно. Но это не объясняет - как @Admin сравнил это с моим способом))


#14

Ну, я вашу логику насчёт этого не понимаю, но ладно.

Но если делать отдельным модулем - есть несколько проблем. К примеру, когда я делал короткие строки на value-типе - я расчитывал что их будет штопать компилятор паскаля, по шаблону что я дам. Дело в том, что у них бывает разная длина, не делать же 256 типов у которых будет отличаться только название и 1 значение (константа, объявленная в самом начале типа).

Как насчёт сделать что то такое:

type
  t1[l:integer]=class
  where l > 5;
  where l < 10;
    
    procedure p1 := writeln(l);
    
  end;

begin
  (new t1[7]).p1;
  (new t1[9]).p1;
  //var a := new t1[100];//Ошибка из за where
end.

Ожидается что развернётся в следующее:

type
  t1$7=class
    const l:integer = 7;
    
    procedure p1 := writeln(l);
    
  end;
  t1$9=class
    const l:integer = 9;
    
    procedure p1 := writeln(l);
    
  end;

begin
  (new t1$7).p1;
  (new t1$9).p1;
end.

Подобные вещи ведь уже есть, должно быть не сложно реализовать? То есть, вот, к примеру типы делегатов создаёт когда видит их упоминание в коде. Так же и тут.

Модуль BlockFileOfT я, конечно, соберу вскоре, но без своих BlockValueString, BlockValueArray и т.п. - он теряет половину своей полезности. Кстати, BlockValueArray уже не реализуешь, через кучу классов, просто потому, сколько значений может быть (9.22337203470729E+18).


#15

Ну, добавить это поле в ваш код и посмотреть :))


#16

А разве set of integer не ссылочный тип?

type
  r1=record
    s:set of word := [5..100];
  end;

begin
  writeln(sizeof(r1));
end.

У меня выводит 8, то есть поле s это ссылка. Это должно сохранять ссылку а не сам сет, что, хоть и не правильно, но должно быть только быстрее.
У меня если добавить поле типа set of byte в запись - ваш file of T выдаёт ошибку при компиляции, аля запись неправильная.

И всё же, как насчёт добвить шаблоны - не_типы, как показано выше? Это наверняка пригодится и вне блочных файлов. Но именно строки и массивы для блочных файлов - не знаю как по другому реализовать.


#17

Нет, это какое-то катастрофическое усложнение языка в стиле C++. Вы даже не представляете, как грамматика замусоривается от обилия конструкций, что приводит потом к невозможности расширять язык в другом месте. Уж не говоря о том, что там надо очень тщательно продумывать семантику.


#18

Тогда что вы предлагаете, как реализовать короткие строки, которые можно будет сохранить в блочный файл?


#19

Предлагаю сконцентрироваться на более полезных вопросах :slight_smile:


#20

А вы продолжаете называть блочное сохранение бесполезным, хотя оно может быть полезно. Чем оно вам так не угодило?