Автор Тема: Буферизация ввода/вывода  (Прочитано 26320 раз)

ilovb

  • Hero Member
  • *****
  • Сообщений: 2538
  • just another nazi test
    • Просмотр профиля
    • Oberon systems
Re: Буферизация ввода/вывода
« Ответ #60 : Январь 17, 2013, 06:18:48 pm »
А как ты отключал системный буфер? Через WinAPI?
И почему 16 байт?

ilovb

  • Hero Member
  • *****
  • Сообщений: 2538
  • just another nazi test
    • Просмотр профиля
    • Oberon systems
Re: Буферизация ввода/вывода
« Ответ #61 : Январь 17, 2013, 07:56:51 pm »

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Буферизация ввода/вывода
« Ответ #62 : Январь 17, 2013, 08:18:21 pm »
А как ты отключал системный буфер? Через WinAPI?
И почему 16 байт?
16 байт, потому что иначе программа будет работать слишком быстро на мегабайтном файле. :-)

Как отключил - я же написал все подробно. fsync.
Y = λf.(λx.f (x x)) (λx.f (x x))

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Буферизация ввода/вывода
« Ответ #63 : Январь 17, 2013, 08:26:55 pm »
Код (буфер 16 + fsync):
func main() {
file,err := os.Create("100Mb.txt")
if err!= nil {
fmt.Print(err)
return
}
w := bufio.NewWriterSize(file,16)
for i:=0; i<1000000; i++ {
w.WriteByte(byte(32))
file.Sync() // fsync
}
}

Строчку file.Sync() если закомментить - будет с системным буфером. Грубо говоря.
Y = λf.(λx.f (x x)) (λx.f (x x))

ilovb

  • Hero Member
  • *****
  • Сообщений: 2538
  • just another nazi test
    • Просмотр профиля
    • Oberon systems
Re: Буферизация ввода/вывода
« Ответ #64 : Январь 17, 2013, 08:29:51 pm »
А file.Sync() делает обмен с диском только если буфер заполнен? Или как?

ps И с чего ты взял что оно в обход системного буфера работает?

ilovb

  • Hero Member
  • *****
  • Сообщений: 2538
  • just another nazi test
    • Просмотр профиля
    • Oberon systems
Re: Буферизация ввода/вывода
« Ответ #65 : Январь 17, 2013, 08:37:10 pm »
Вот пример прямого обмена с диском в винде:
http://www.codeproject.com/Articles/51678/Improve-responsiveness-in-Windows-with-the-FILE_FL

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Буферизация ввода/вывода
« Ответ #66 : Январь 17, 2013, 08:52:17 pm »
А file.Sync() делает обмен с диском только если буфер заполнен? Или как?

ps И с чего ты взял что оно в обход системного буфера работает?
Я ничего ниоткуда не взял. fsync заставляет систему если что и было в буфере, скинуть из буфера это дело на диск. Если там ничего не было, то конечно ничего скинуто и не будет (но время на syscall конечно все равно будет потрачено).

Соответственно что происходит - кладем байт в системный буфер, затем говорим системе - сбрось все из буфера на диск. Этот байт пишется на диск. Это если без нашего буфера работать.

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

Факт, что система, когда её буфер пуст, при вызове fsync не обращается к диску, виден в отношении времен 4 и 2 строчки таблицы. Отношение равно 12,7, что хорошо согласуется (по порядку величины) с теоретическим отношением равным 16.

Понятно что с FILE_FLAG_NO_BUFFERING, но без fsync результаты будут несколько лучше. Но совсем немного. Не на порядок.
Y = λf.(λx.f (x x)) (λx.f (x x))

ilovb

  • Hero Member
  • *****
  • Сообщений: 2538
  • just another nazi test
    • Просмотр профиля
    • Oberon systems
Re: Буферизация ввода/вывода
« Ответ #67 : Январь 17, 2013, 09:00:37 pm »
Я наверно торможу, но из твоего сообщения так и не понял... fsync сбрасывает пользовательский буфер в системный или системный на диск?

ilovb

  • Hero Member
  • *****
  • Сообщений: 2538
  • just another nazi test
    • Просмотр профиля
    • Oberon systems
Re: Буферизация ввода/вывода
« Ответ #68 : Январь 17, 2013, 09:05:31 pm »
Оно?
http://msdn.microsoft.com/ru-ru/library/windows/desktop/aa364439(v=vs.85).aspx

PROCEDURE CloseFile (f: File; VAR res: INTEGER);
        VAR s: INTEGER;
    BEGIN
        IF f.state = exclusive THEN
            f.Flush;
            res := WinApi.FlushFileBuffers(f.ref)
         END;
        s := f.state; f.state := closed;
        CloseFileHandle (f, res);
        IF (s IN {temp, new, hidden}) & (f.name # "") THEN
            res := WinApi.DeleteFileW(f.name)
        END
    END CloseFile;

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Буферизация ввода/вывода
« Ответ #69 : Январь 17, 2013, 09:07:15 pm »
Я наверно торможу, но из твоего сообщения так и не понял... fsync сбрасывает пользовательский буфер в системный или системный на диск?
Системный на диск, если он не пуст. Если пуст, то обращения к диску не будет.

А содержимое пользовательского буфера будет насильно сброшено в системный с помощью fflush (в данном случае w.Flush())

Две забавные штучки fflush и fsync :-) Советую таки посмотреть видео доклада Аксенова по MySql - он это все очень хорошо описывает.
Y = λf.(λx.f (x x)) (λx.f (x x))

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Буферизация ввода/вывода
« Ответ #70 : Январь 17, 2013, 09:12:52 pm »
Оно?
http://msdn.microsoft.com/ru-ru/library/windows/desktop/aa364439(v=vs.85).aspx

PROCEDURE CloseFile (f: File; VAR res: INTEGER);
        VAR s: INTEGER;
    BEGIN
        IF f.state = exclusive THEN
            f.Flush;
            res := WinApi.FlushFileBuffers(f.ref)
         END;
        s := f.state; f.state := closed;
        CloseFileHandle (f, res);
        IF (s IN {temp, new, hidden}) & (f.name # "") THEN
            res := WinApi.DeleteFileW(f.name)
        END
    END CloseFile;

Да, оно.

func (f *File) Sync() (err error) {
if f == nil {
return syscall.EINVAL
}
if e := syscall.Fsync(f.fd); e != nil {
return NewSyscallError("fsync", e)
}
return nil
}

...

func Fsync(fd Handle) (err error) {
return FlushFileBuffers(fd)
}

...

func FlushFileBuffers(handle Handle) (err error) {
r1, _, e1 := Syscall(procFlushFileBuffers.Addr(), 1, uintptr(handle), 0, 0)
if int(r1) == 0 {
if e1 != 0 {
err = error(e1)
} else {
err = EINVAL
}
}
return
}

...

procFlushFileBuffers                 = modkernel32.NewProc("FlushFileBuffers")
Y = λf.(λx.f (x x)) (λx.f (x x))

ilovb

  • Hero Member
  • *****
  • Сообщений: 2538
  • just another nazi test
    • Просмотр профиля
    • Oberon systems
Re: Буферизация ввода/вывода
« Ответ #71 : Январь 17, 2013, 09:14:06 pm »
Теперь вроде понятно.  :)

ps Делись ссылкой

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Буферизация ввода/вывода
« Ответ #72 : Январь 17, 2013, 09:18:30 pm »
Теперь вроде понятно.  :)

ps Делись ссылкой
Дык я делился же уже :-)
Вот: http://addconf.ru/event.sdf/ru/add_3/authors/AndrewAksyonoff/732
Y = λf.(λx.f (x x)) (λx.f (x x))

ilovb

  • Hero Member
  • *****
  • Сообщений: 2538
  • just another nazi test
    • Просмотр профиля
    • Oberon systems
Re: Буферизация ввода/вывода
« Ответ #73 : Январь 17, 2013, 09:27:10 pm »
Сенкс.

На всякий случай, чтобы избежать недоразумений:
http://oberspace.dyndns.org/index.php/topic,431.msg13629.html#msg13629
Картинка с цитатой из "Проект Оберон" - это конкретно про файлы в памяти (MFiles). Но думаю понятно что - это в равной степени справедливо и для файлов на диске. Тем более что реализация файлов на диске отличается лишь способом транспортировки байтов  :) Для файлов в памяти SYSTEM.MOVE, а для файлов на диске Kernel.PutSector

ilovb

  • Hero Member
  • *****
  • Сообщений: 2538
  • just another nazi test
    • Просмотр профиля
    • Oberon systems
Re: Буферизация ввода/вывода
« Ответ #74 : Январь 18, 2013, 04:24:56 pm »
Вот: http://addconf.ru/event.sdf/ru/add_3/authors/AndrewAksyonoff/732
Прикольный чувак. Спасибо. Интересный доклад.