OberonCore
https://forum.oberoncore.ru/

Абстракция Files.File и её реализации
https://forum.oberoncore.ru/viewtopic.php?f=23&t=4214
Страница 1 из 3

Автор:  Евгений Темиргалеев [ Воскресенье, 13 Январь, 2013 20:52 ]
Заголовок сообщения:  Абстракция Files.File и её реализации

Иван Денисов в viewtopic.php?p=77096#p77096 писал(а):
Пожалуйста, поделитесь опытом, как это делать? Вопрос насущный. Даже для маленьких временных файлов создаваемых через Files.dir.New(), как я понял, идет обращение к диску. А очень бы хотелось, как вы говорите "над памятью".
Никакого секрета тут нет: как реализуете абстракцию, так "она" и будет работать.

1) Ограниченная реализация файлов в памяти, насколько помню, есть в подсистеме Dbu (http://www.zinnamturm.eu/downloadsDH.htm#Dbu)
2) Простейший пример: http://oberoncore.ru/library/temir_srav ... _ble_kboks
Код:
MODULE PrivFixedMemFiles;
(*
File
Reader
Writer
*)
  IMPORT Files;
 
  TYPE
    File* = POINTER TO RECORD (Files.File)
      len-: INTEGER;
      data-: ARRAY 4096 OF BYTE
    END;

    Reader* = POINTER TO RECORD (Files.Reader)
      base: File;
      pos: INTEGER
    END;
   
    Writer* = POINTER TO RECORD (Files.Writer)
      base: File;
      pos: INTEGER
    END;


  (* File *)

  PROCEDURE (f: File) Close*;
  BEGIN
    HALT(100)
  END Close;
 
  PROCEDURE (f: File) Flush*;
  BEGIN
    HALT(100)
  END Flush;

  PROCEDURE (f: File) Length* (): INTEGER;
  BEGIN
    RETURN f.len
  END Length;

  PROCEDURE (f: File) NewReader* (old: Files.Reader): Files.Reader;
    VAR  res: Reader;
  BEGIN
    IF (old # NIL) & (old IS Reader) THEN res := old(Reader) ELSE NEW(res) END;
    IF res.base # f THEN
      res.base := f; res.SetPos(0)
    END;
    res.eof := FALSE;
    RETURN res
  END NewReader;

  PROCEDURE (f: File) NewWriter* (old: Files.Writer): Files.Writer;
    VAR  res: Writer;
  BEGIN
    IF (old # NIL) & (old IS Writer) THEN res := old(Writer) ELSE NEW(res) END;
    IF res.base # f THEN
      res.base := f; res.SetPos(f.len)
    END;
    RETURN res
  END NewWriter;
   
  PROCEDURE (f: File) Register* (name: Files.Name; type: Files.Type; ask: BOOLEAN; OUT res: INTEGER);
  BEGIN
    HALT(100)
  END Register;


  (* Reader *)

  PROCEDURE (r: Reader) Base* (): Files.File;
  BEGIN
    RETURN r.base
  END Base;
 
  PROCEDURE (r: Reader) Pos* (): INTEGER;
  BEGIN
    RETURN r.pos
  END Pos;

  PROCEDURE (r: Reader) SetPos* (pos: INTEGER);
  BEGIN
    ASSERT(0 <= pos, 20); ASSERT(pos <= r.base.len, 21);
    r.pos := pos;
    r.eof := FALSE
  END SetPos;

  PROCEDURE (r: Reader) ReadByte* (OUT x: BYTE);
    VAR  f: File;
  BEGIN
    f := r.base;
    IF r.pos < f.len THEN
      x := f.data[r.pos];
      INC(r.pos);
      r.eof := FALSE
    ELSE
      x := 0;
      r.eof := TRUE
    END
  END ReadByte;

  PROCEDURE (r: Reader) ReadBytes* (VAR x: ARRAY OF BYTE; beg, len: INTEGER);
    VAR  f: File; i, j: INTEGER;
  BEGIN
    ASSERT(0 <= beg, 20); ASSERT(0 <= len, 21); ASSERT(beg + len <= LEN(x), 22);
    f := r.base;
    i := beg; j := r.pos;
    WHILE (j < f.len) & (len > 0) DO
      x[i] := f.data[j];
      INC(i); INC(j);
      DEC(len)
    END;
    r.eof := len > 0;
    r.pos := j
  END ReadBytes;


  (* Writer *)

  PROCEDURE (w: Writer) Base* (): Files.File;
  BEGIN
    RETURN w.base
  END Base;
 
  PROCEDURE (w: Writer) Pos* (): INTEGER;
  BEGIN
    RETURN w.pos
  END Pos;

  PROCEDURE (w: Writer) SetPos* (pos: INTEGER);
  BEGIN
    ASSERT(0 <= pos, 20); ASSERT(pos <= w.base.len, 21);
    w.pos := pos;
  END SetPos;

  PROCEDURE (w: Writer) WriteByte* (x: BYTE);
    VAR  f: File;
  BEGIN
    f := w.base;
    ASSERT(f.len + 1 <= LEN(f.data), 100);
    f.data[w.pos] := x;
    INC(w.pos);
    IF w.pos > f.len THEN f.len := w.pos END
  END WriteByte;

  PROCEDURE (w: Writer) WriteBytes* (IN x: ARRAY OF BYTE; beg, len: INTEGER);
    VAR  f: File; i: INTEGER;
  BEGIN
    ASSERT(0 <= beg, 20); ASSERT(0 <= len, 21); ASSERT(beg + len <= LEN(x), 22);
    f := w.base;
    ASSERT(f.len + len <= LEN(f.data), 100);
    i := beg;
    WHILE len > 0 DO
      f.data[w.pos] := x[i];
      INC(w.pos); INC(i);
      DEC(len)
    END;
    IF w.pos > f.len THEN f.len := w.pos END
  END WriteBytes;


  (* Программный интерфейс *)

  PROCEDURE New* (): File;
    VAR  res: File;
  BEGIN
    NEW(res);
    res.len := 0;
    RETURN res
  END New;

END PrivFixedMemFiles.

Автор:  Пётр Кушнир [ Воскресенье, 13 Январь, 2013 22:13 ]
Заголовок сообщения:  Re: Абстракция Files.File и её реализации

По поводу строк - всё равно придётся юзать NEW (хотя бы для каждого нового куска буфера), или ограничивать себя конкретной длиной строки.

А по поводу файлов - было бы интересно описать в этом треде механизм взаимодействия двух ББ через совместные области памяти, кажется, Илья Ермаков как-то раз упоминал о таком приёме, насколько я понимаю, там тоже использовались файловые абстракции.

Автор:  Илья Ермаков [ Воскресенье, 13 Январь, 2013 23:25 ]
Заголовок сообщения:  Re: Абстракция Files.File и её реализации

Во-первых, можно брать память из кучи ОС, во-вторых, можно делать NEW страницами фиксированного размера и просто кэшировать эти страницы глобально в модуле-реализации. Т.е. освободившиеся внутри одного объекта-буфера страницы сохранять в списке свободных, для повторного использования, не соря.

Ну а для общения двух ББ нужно использовать свою работу с логическими страницами внутри некоторого куска памяти, который отображен между ББ (через memory mapping), определить untagged-структуры для такого файла в памяти, чтобы объект Files.File был просто обёрткой над ними.

Я бы повыкладывал конкретный код, не жалко, если бы он не был сильно завязан на свои библиотеки - да и "постарел" код за 4 года, сейчас уже есть намерения переделать с высоты сегодняшнего понимания :)

Автор:  Илья Ермаков [ Воскресенье, 13 Январь, 2013 23:36 ]
Заголовок сообщения:  Re: Абстракция Files.File и её реализации

Иван Денисов в viewtopic.php?p=77096#p77096 писал(а):
Пожалуйста, поделитесь опытом, как это делать? Вопрос насущный. Даже для маленьких временных файлов создаваемых через Files.dir.New(), как я понял, идет обращение к диску. А очень бы хотелось, как вы говорите "над памятью".


Кстати, HostFiles неплохо кэширует в памяти (не говоря про ОС). Так что для прикладных задач нет ничего страшного в том, чтобы использовать Files.dir.New() или Files.dir.Temp().
Т.е. если какая-то настольная программа что-то получает/передаёт из сети, ей нужны буферы, то это вполне подходит (для настольной-то программы).
Я сам это использую, если тянуть зависимости от своего хозяйства нельзя (например, в учебных примерах).

Автор:  Борис Рюмшин [ Воскресенье, 13 Январь, 2013 23:48 ]
Заголовок сообщения:  Re: Абстракция Files.File и её реализации

Илья Ермаков писал(а):
Кстати, HostFiles неплохо кэширует в памяти (не говоря про ОС). Так что для прикладных задач нет ничего страшного в том, чтобы использовать Files.dir.New() или Files.dir.Temp().

Для последнего, как показывает вскрытие, даже запись на диск не происходит при сносных объёмах. Так что как буфер катит.

Автор:  Пётр Кушнир [ Понедельник, 14 Январь, 2013 00:14 ]
Заголовок сообщения:  Re: Абстракция Files.File и её реализации

Илья Ермаков писал(а):
Я бы повыкладывал конкретный код, не жалко, если бы он не был сильно завязан на свои библиотеки - да и "постарел" код за 4 года, сейчас уже есть намерения переделать с высоты сегодняшнего понимания :)
Ну да, интереснее сразу про реализацию говорить, потому что в принципе механизм ясен.

Автор:  Иван Денисов [ Понедельник, 14 Январь, 2013 15:36 ]
Заголовок сообщения:  Re: Абстракция Files.File и её реализации

Илья Ермаков писал(а):
Кстати, HostFiles неплохо кэширует в памяти (не говоря про ОС). Так что для прикладных задач нет ничего страшного в том, чтобы использовать Files.dir.New() или Files.dir.Temp().

Т.е. если какая-то настольная программа что-то получает/передаёт из сети, ей нужны буферы, то это вполне подходит (для настольной-то программы).
Я сам это использую, если тянуть зависимости от своего хозяйства нельзя (например, в учебных примерах).
Спасибо за эту информацию! Поскольку так и сделал для приема файлов по HTTP и переживал, что при этом диск используется. Теперь чаще буду пользоваться этим приемом значит :) И длинные строки безразмерные тоже значит можно через Files делать? Такое часто надо для биоинформатики, например, где строки очень большие. И для приема данных с прибора...

А можно ли в HostFiles менять параметры:
Код:
nofbufs = 4;   (* max number of buffers per file *)
bufsize = 2 * 1024;   (* size of each buffer *)

? Кто пробовал?

Оперативной памяти ведь теперь на компах много, а вот обращение к жесткому диску хотелось бы пореже совершать, при использовании Files.

Автор:  Борис Рюмшин [ Понедельник, 14 Январь, 2013 17:20 ]
Заголовок сообщения:  Re: Абстракция Files.File и её реализации

Илья Ермаков писал(а):
Т.е. если какая-то настольная программа что-то получает/передаёт из сети, ей нужны буферы, то это вполне подходит (для настольной-то программы).

От задачи идти надо. Бывает, что и «серверная программа» настолько тихо работает, что может файлы использовать спокойно. А бывает, что и «настольная» обрабатывает гигабайты...

Автор:  Евгений Темиргалеев [ Понедельник, 14 Январь, 2013 18:16 ]
Заголовок сообщения:  Re: Абстракция Files.File и её реализации

Иван Денисов писал(а):
А можно ли в HostFiles менять параметры:
Код:
nofbufs = 4;   (* max number of buffers per file *)
bufsize = 2 * 1024;   (* size of each buffer *)

? Кто пробовал?

Оперативной памяти ведь теперь на компах много, а вот обращение к жесткому диску хотелось бы пореже совершать, при использовании Files.
Эти цифры долежали тут с оригинальной системы Оберон... Вопрос же не в том --- можно ли, а в точном описании эффекта...
Иван Денисов писал(а):
И длинные строки безразмерные тоже значит можно через Files делать? Такое часто надо для биоинформатики, например, где строки очень большие. И для приема данных с прибора...
... и когда дело идёт о конкретной специфической задаче рекомендовал бы уповать не на готовые библиотеки, а на свою голову. Так и так её напрягать: либо разбираясь со спецификой реализации и допиливая её, либо изучая соотв. алгоритмы и структуры данных (и т.п.) для собственной, ориентированной на задачу, реализации. Последнее полезнее.

Автор:  Info21 [ Понедельник, 14 Январь, 2013 20:14 ]
Заголовок сообщения:  Re: Абстракция Files.File и её реализации

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

Автор:  ilovb [ Понедельник, 14 Январь, 2013 20:43 ]
Заголовок сообщения:  Re: Абстракция Files.File и её реализации

Иван Денисов писал(а):
А можно ли в HostFiles менять параметры:
Код:
nofbufs = 4;   (* max number of buffers per file *)
bufsize = 2 * 1024;   (* size of each buffer *)

? Кто пробовал?

Оперативной памяти ведь теперь на компах много, а вот обращение к жесткому диску хотелось бы пореже совершать, при использовании Files.

Самое оптимальное вроде под размер кластера (4 * 1024)
Больший размер не должен давать существенного ускорения. Но на всякий случай можно попробовать разные варианты. :)

Автор:  ilovb [ Понедельник, 14 Январь, 2013 21:43 ]
Заголовок сообщения:  Re: Абстракция Files.File и её реализации

Цитата:
Однако для обеспечения максимальной скорости обмена данными следует задавать длину, которая была бы кратна длине физического сектора дискового носителя информации (512 байт). Более того, фактически пространство на диске выделяется любому файлу порциями - кластерами, которые в зависимости от типа диска могут занимать 2 и более смежных секторов. Как правило, кластер может быть прочитан или записан за один оборот диска, поэтому наивысшую скорость обмена данными можно получить, если указать длину записи, равную длине кластера.
http://borlpasc.narod.ru/docym/Faronov/gl5/gl5_8.html

Про особенности работы подсистемы ввода-вывода Windows можно почитать у Марка Руссиновича:
http://royallib.ru/read/russinovich_mar ... tml#113321
Там несколько разных способов описано. В BlackBox используется самый простой.

Автор:  Илья Ермаков [ Понедельник, 14 Январь, 2013 22:50 ]
Заголовок сообщения:  Re: Абстракция Files.File и её реализации

Это в теории кратно размеру сектора. Реально не подгадаете - между Вами и диском есть файловая система с её структурами. Вы считали блок в 1024 байта, он в реальности хрен знает как и во сколько кластеров ФС был отображён, а к каждому кластеру хрен знает сколько байт служебной информации могло быть. И вышло уже не 1024 байта, а 1124, и не в одном секторе диска, а в трёх... (условно говоря).
Также с ОЗУ - Вы в своём любимом языке делаете new массива длиной 4096 байт, думая, что это совпадает с размером страницы процессора, а сколько служебной информации держит на этот массив язык и менеджер кучи....
Правильнее не задумываться о таких особенностях, ибо они слишком преходящи.

-- пардон, у Вас в цитате как раз про размер кластера тоже сказано. Ну дык - и какой на Вашей ФС размер кластера? :) А если она, например, в VDS, в виртуальной файловой системе, что для серверов почти норма сегодня - сколько там отображений до уровня НЖМД? :)

Автор:  Info21 [ Понедельник, 14 Январь, 2013 23:04 ]
Заголовок сообщения:  Re: Абстракция Files.File и её реализации

Илья Ермаков писал(а):
Правильнее не задумываться о таких особенностях, ибо они слишком преходящи.
Притом, что усилия на их использование велики.

Не окупается.

Логика своей задачи -- вот что мощно окупается.

Автор:  ilovb [ Понедельник, 14 Январь, 2013 23:05 ]
Заголовок сообщения:  Re: Абстракция Files.File и её реализации

Можно не гадать, а просто проверить.
Думаю, что разработчики BB тоже делали под размер кластера (подозреваю что в те времена именно такой размер чаще всего и был).

Автор:  Пётр Кушнир [ Понедельник, 14 Январь, 2013 23:09 ]
Заголовок сообщения:  Re: Абстракция Files.File и её реализации

про витуальные общие файлы, про виртуальные общие файлы экземпляров ББ расскажите пжалуйста :)

Автор:  ilovb [ Понедельник, 14 Январь, 2013 23:30 ]
Заголовок сообщения:  Re: Абстракция Files.File и её реализации

А еще можно почитать "Проект Оберон" 7.3 Реализация файлов на диске.
И станет понятно, что Вирт тоже делал буфер по размеру кластера. И тоже ради максимальной производительности.

Автор:  Илья Ермаков [ Вторник, 15 Январь, 2013 00:07 ]
Заголовок сообщения:  Re: Абстракция Files.File и её реализации

Пётр Кушнир писал(а):
про витуальные общие файлы, про виртуальные общие файлы экземпляров ББ расскажите пжалуйста :)


Эх...
Жила-была такая абстракция - страничный буфер. Она была внутри построена над неуправляемой памятью (выделяемой средствами ОС) и хранила все заголовочные данные в этой памяти. Т.е. если другому страничному буферу давали тот же адрес начальной страницы, что использовался другим буфером, то он начинал работать с той же памятью. Плюс была секция критическая.
Т.е. два ББ, загруженные в общее адресное пространство, могли работать с общими страницами памяти через такие объекты.
Ну и дальше была реализация Files.File над таким страничным буфером.

Автор:  Пётр Кушнир [ Вторник, 15 Январь, 2013 00:12 ]
Заголовок сообщения:  Re: Абстракция Files.File и её реализации

Через неё бы шину сообщений пропустить и будет счастье. Такой чудесный компонент должен стать достоянием общественности :)
Насколько я понимаю из http://ru.wikipedia.org/wiki/Mmap, совместная память это кроссплатформенная концепция, то есть, при разработке линакс-версий, понадобится только переписать реализацию страничного буфера
эрлангеры, кстати, гордятся своей кластеризацией искаропки, чем мы хуже

Автор:  Илья Ермаков [ Вторник, 15 Январь, 2013 00:57 ]
Заголовок сообщения:  Re: Абстракция Files.File и её реализации

Илья Ермаков писал(а):
Я бы повыкладывал конкретный код, не жалко, если бы он не был сильно завязан на свои библиотеки - да и "постарел" код за 4 года, сейчас уже есть намерения переделать с высоты сегодняшнего понимания :)

Страница 1 из 3 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/