LINUX.ORG.RU

1c очень долго открывает файлы на NFS, CIFS

 , ,


1

2

По сути вопрос мало касается самой 1с.
Открываю в конфигураторе 1С 8.3 файл конфигурации (*.cf). Размером он около 200-300 Мб.

Если открывать с локальной фс, то открытие происходит за несколько секунд.
Если открывать с nfs или cifs то открытие занимает минут 10 (sic!).

Моя машина и NAS с файлами находятся в сети 100Mbit/s.
Копирование файла с NFS на локальную фс идёт со скоростью близкой к 80-90Mbit/s.

Далее рассматриваем открытие файла на nfs3:
С помощью strace -cw выясняем что очень долго выполняется read:

% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 57.41 2007.728556      478600      4195      1538 futex
 28.74 1005.053317      434900      2311           epoll_wait
 13.04  455.978200         596    764976        25 read
  0.41   14.455605          14   1038231           lseek
(Насколько я понял futex и epoll_wait тут вообще не причём, они похоже не связаны с тормозами и время исполнения у них слишком большое)

Если просто сделать strace и посмотреть что делается с нашим файловым дескриптором то можно увидеть что-то такое:

open("/mnt/nas/foo/bar/1Cv8.cf", O_RDONLY) = 83 <0.000631>
fcntl(83, F_GETFD)                = 0 <0.000004>
fcntl(83, F_SETFD, FD_CLOEXEC)    = 0 <0.000004>
flock(83, LOCK_SH|LOCK_NB)        = 0 <0.000007>
open("/mnt/nas/foo/bar/1Cv8.cf", O_RDWR) = 84 <0.000616>
fcntl(84, F_GETFD)                = 0 <0.000017>
fcntl(84, F_SETFD, FD_CLOEXEC)    = 0 <0.000004>
fcntl(84, F_SETLK, {type=F_WRLCK, whence=SEEK_SET, start=4294967296, len=1}) = 0 <0.000012>
Целых два дескриптора на один файл.
На кой чёрт открывается второй с O_RDWR я понятия не имею, ибо менять файл 1С-ка всё равно не может.

И потом идёт куча таких вызовов:

lseek(83, 0, SEEK_END)            = 211404996 <0.000005>
lseek(83, 16, SEEK_SET)           = 16 <0.000004>
read(83, "\r\n00057a80 00057a80 7fffffff \r\n", 31) = 31 <0.000007>
lseek(83, 47, SEEK_SET)           = 47 <0.000004>
read(83, "\257z\5\0.{\5\0\377\377\377\177", 12) = 12 <0.000004>
lseek(83, 0, SEEK_END)            = 211404996 <0.000004>
lseek(83, 359087, SEEK_SET)       = 359087 <0.000003>
read(83, "\r\n00000060 00000060 7fffffff \r\n", 31) = 31 <0.001051>

Т.е. мы постоянно прыгаем в разные места файла и делаем read небольшими порциями (32 байта и меньше).
Таким образом читается весь файл (200-300 мегабайт).

Насколько я понимаю сетевые фс NFS/CIFS на такое не рассчитаны?

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

Чтобы всё работало почти так же быстро как работает локально делаем следующее:

  1. Настраиваем FS-Cache
  2. Монтируем NFS со следующими опциями: vers=4,fsc,ro

fsc - включаем кэширование через FS-Cache
vers=4 - на третьей кэширование с нашим файлом не работает, по-видимому из-за того что 1с открывает дескриптор на чтение/запись; в документации по FS-Cache написано что на NFSv3 кэш на файле отрубается пока открыт R/W дескриптор, а на NFSv4 всё ок.
ro - связано с одним тупым багом, из-за которого нельзя из 1с открывать файлы на NFSv4 если она смонтирована в r/w, к сабжу не относится.

С CIFS я ничего не придумал, хотя мне он особо и не нужен.
С NFSv3 тоже ничего не получается из-за того что файл открывается r/w и кэширование не работает.

★★★★★

nfs + flock

Думаю проблема в ненормальных блокировках файлов для 1С. Так как 1С блокирует не только используя fcntl но перед этим он использует flock! Т.е. 1С использует два типа блокировок на один файл. В следствии чего 1С скорее всего коверкает каждый раз блокировку fcntl из за того что не стоит для других машин блокировка на весь файл flock функцией, так как flock не работает нормально для nfs. А вот fcntl хорошо работает на nfs дело в семантике двух реализаций.

frooty_box ()
Ответ на: nfs + flock от frooty_box

Про проблему с блокировками я знаю, она происходит из-за того что на NFS блокировки flock эмулируются через блокировки fcntl.

man 2 flock

Since Linux 2.6.12, NFS clients support flock() locks by
emulating them as byte-range locks on the entire file.
This means that fcntl(2) and flock() locks do interact with one another over NFS.

Это приводит к тому что эти два вида блокировок на NFS взаимодействуют с друг-другом (и блокируют).

Отключить такое поведение на NFSv3 я могу несколькими разными способами, например такими опциями монтирования:
vers=3,local_lock=flock
или вообще такими:
vers=3,nolock

Но с версией 3 не работает FS-Cache (для открытых на r/w дескрипторов)!
А на версии 4 нельзя отключить блокировки :)

Nao ★★★★★ ()
Ответ на: nfs + flock от frooty_box

Вообще мой изначальный вопрос про ускорение работы с сетевой фс при таком насиловании её lseek'ами и мелкими read.


Один вариант решения я нашёл (через FS-Cache) и он работает, но выглядит не очень удобно в настройке: надо выделять место под кэш, приходится держать две точки монтирования (одна в ro с кэшем, другая в rw без кэша).

Nao ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.