Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.128.199.88] |
|
Сообщ.
#1
,
|
|
|
Хз в тот ли раздел пишу - модеры поправьте, если что.
Суть такая, есть приложение в виде одного екзешника/бинарника весом под 200Мб. Приложение лежит на сетевом диске откуда и запускается юзверями. Естесно это приводит к тому, что приложение скачивается с сетевого диска. И все бы ничего, да вот только приложение при своей работе активно форкается, а это уже приводит к существенным сетевым нагрузкам и увеличивает время работы. Приложение написано на С++/Qt, проблема актуальна как для винды так и для линукса. Есть ли какой-нибудь способ/механизм "объяснить" приложению/системе, что не обязательно при каждом форке качать копию по сети? |
Сообщ.
#2
,
|
|
|
Странно, что она качается.
Я на сколько знаю, команда fork вызывает копирование процесса в памяти и один процесс пускается по одной ветке, другой по другой. При этом, уже обученный до форка процесс является уникальным, поэтому и копируется, полностью, а не запускается новый. Вытягивать его с диска в общем-то не логично. Может что с кодом не так? Он точно после форка содержит память родительского процесса? Может просто по ошибке вылетает и перезапускается, вследствие чего и тянет файлик заново..? |
Сообщ.
#3
,
|
|
|
Цитата _lcf_ @ Есть ли какой-нибудь способ/механизм "объяснить" приложению/системе, что не обязательно при каждом форке качать копию по сети? Копируй его на локальный диск перед каждым запуском и все. Хотя в линуксе форк не должен тормозить в любом случае. Скорее всего там проблема в чем–то другом. |
Сообщ.
#4
,
|
|
|
Цитата simsergey @ Странно, что она качается. ничего странного так и работает. при форке нужен физический файл. Цитата simsergey @ Может просто по ошибке вылетает и перезапускается, вследствие чего и тянет файлик заново..? форк так контролируемый, как раз чтобы снизить негативные последствия возможных падений. Цитата Олег М @ Копируй его на локальный диск перед каждым запуском и все. это определяется системной политикой каждой конторы, использующей наш софт, где-то могут быть заблокированы локальные диски на запись. и да, в линуксе проблема менее ощутима, но это не избавляет от решения проблемы в целом. Добавлено по большому счёту проблема на винде из-за тупого кэша, да... |
Сообщ.
#5
,
|
|
|
Стойте-ка.
1. А проблема на винде? Именно при форке? 2. И оправдан ли такой объём бинарника? Может стоит посмотреть в сторону того, чтоб вытащить из него отладочные символы и положить рядышком? |
Сообщ.
#6
,
|
|
|
Цитата negram @ 1. А проблема на винде? Именно при форке? ну да, процесс слегка эээ подвисает, пока качает 200 метров по сети, с учетом того, что пользователей могут быть десятки - нагрузка на сеть становится не кислой, так как форкается приложение довольно часто. Цитата negram @ 2. И оправдан ли такой объём бинарника? политика компании - один екзешник, никаких либ и зависимостей, ноу айти реквест а в последнем релизе туда еще и все мануалы запихали, что увеличило объем в два раза |
Сообщ.
#7
,
|
|
|
Хм...
Вроде бы тема к сетевому программированию никаким боком. Ну да ладно, попробую свои пять копеек положить на кон... Цитата negram @ 1. А проблема на винде? Именно при форке? Я что то помню, вроде fork() в винде отсутствует ваще...как класс. Аналогом всегда была CreateProcess(). Цитата _lcf_ @ Приложение написано на С++/Qt, проблема актуальна как для винды так и для линукса. Цитата _lcf_ @ Естесно это приводит к тому, что приложение скачивается с сетевого диска. И все бы ничего, да вот только приложение при своей работе активно форкается, а это уже приводит к существенным сетевым нагрузкам и увеличивает время работы. Интересная постановка проблемы. 1. Оригинал екзешника лежит на сетевом диске. 2. Пользователь скачивает экзешник и запускает. 3. В винде создается процесс и работает автономно. Где то внутри работающего процесса есть код, который должен создать копию этого процесса. CreateProcess это и должен сделать, и обращения к сетевому диску не требуется 4. В никсах пользователь скачивает экзкшник к себе. Shell оригинальной машины пользователя форкает процесс и таким образом запускает его. Внутри запущенного процесса новая копия создается тем форком, который внутри родительского кода. Никакого обращения к сетевому диску не требуется. По логике нигде не нужны повторные обращения к сетевому диску. Где ошибка в этих рассуждениях? M Тему все таки перемещу Пусть спецы посмотрят |
Сообщ.
#8
,
|
|
|
Цитата Oleg2004 @ Аналогом всегда была CreateProcess А в чем там аналогия? Добавлено Цитата Oleg2004 @ Где ошибка в этих рассуждениях? Насколько я понял, пользователь не скачивает exe–шник, а запускает его с удаленнго диска. Немного разные вещи |
Сообщ.
#9
,
|
|
|
Олег М
Цитата _lcf_ @ Приложение лежит на сетевом диске откуда и запускается юзверями. Естесно это приводит к тому, что приложение скачивается с сетевого диска. Написано - скачивается... Понятно, что запустить чужое приложение на ЧУЖОЙ машине - это одно. Но ТС ясно пишет - скачивает. Вот я и пытаюсь понять, как это ДОЛЖНО!приводить к повышенной сетевой активности. Цитата Олег М @ А в чем там аналогия? В создании нового процесса. В винде форка нет, чтобы его создать. |
Сообщ.
#10
,
|
|
|
Цитата Oleg2004 @ В создании нового процесса. В винде форка нет, чтобы его создать. Никакой аналогии там нет. Fork копирует существующий процесс, CreateProcess создает новый, с нуля. Соответственно, требуется загрузка файла |
Сообщ.
#11
,
|
|
|
ну говоря скачивается имелось ввиду что в оперативку. файл физически естесно на сетевом диске.
ну и да в винде createprocess, а не форк, да и... в линуксе тоже. просто там кеш для сетевых дисков адекватно работает. в общем, пришли к выводу что на винде при первом запуске копировать приложение во временную папку. |
Сообщ.
#12
,
|
|
|
Короче, дело такое.
Код процесса -- выгружаемая память. И выгружается он не в своп, а просто нафиг. Если что, можно снова с exe-шника подгрузить. Так вот, что в линуксе, что в винде возможна ситуация, что форкнутый процесс полезет на диск за кодом. Но если форк честный и проблем с памятью нет, то диск в общем-то не нужен, и странички памяти могут хоть копиорваться, хоть реюзатся до посинения. Другое дело, что насколько я знаю, в винде форк реализован через тот же CreateProcess (поправьте меня). И он всегда загружает образ с диска (ну либо с кеша файловой системы, хотя сомнительно что все 200 метров останутся в этом самом кеше). |
Сообщ.
#13
,
|
|
|
в винде кэшируется только локальная память, с сетевых источником ничего не кэшируется ибо не гарантируется, что файл не был изменен.
|
Сообщ.
#14
,
|
|
|
Цитата Олег М @ Никакой аналогии там нет. Fork копирует существующий процесс, CreateProcess создает новый, с нуля. Соответственно, требуется загрузка файла Проблема в таргеттинге. Т.е. в семантике. Форк не копирует родительский процесс, а разветвляет его с созданием нового процесса. Вот вам простой пример /*Тут куча инклюдов, опускаем*/ #define MYPORT 3490 /* Порт, на который будет идти соединение*/ #define BACKLOG 10 /* Сколько подключений может быть в очереди */ int main() { int sd, newsd; /* Слушаем на сокете sd, новое подключение на сокете newsd */ struct sockaddr_in my_addr;/* Серверная адресная информация */ struct sockaddr_in their_addr; /* Адресная информация запрашивающей стороны (клиента) */ int sin_size; /* Создаем Интернет-сокет, ориентированный на соединение*/ if ((sd = socket (AF_INET, SOCK_STREAM, 0)) == -1) {perror ("socket");exit (1); } my_addr.sin_family = AF_INET; /* В порядке байтов хоста */ my_addr.sin_port = htons (MYPORT);/* short, в порядке байтов сети */ /* Авто-заполнение IP-адресом серверного сетевого интерфейса */ my_addr.sin_addr.s_addr = INADDR_ANY; bzero(&(my_addr.sin_zero), 8);/* Обнуляем остальную часть struct */ /* Связываем только-что созданный сокет с его локальным адресом */ if (bind(sd, (struct sockaddr *)&my_addr, sizeof (struct sockaddr)) == -1) {perror ("bind");exit (1); } /* Организуем очередь прослушивания сети на порту MYPORT */ if (listen (sd, BACKLOG) == -1) {perror ("listen");exit (1);} while(1) /* Главный цикл accept()*/ { sin_size = sizeof (struct sockaddr_in); if ((newsd = accept (sd, (struct sockaddr *)&their_addr, &sin_size)) == -1) { perror ("accept"); continue; /* продолжаем прием*/ } /* Приняли запрос на соединение и принимаем решение ответить на него*/ printf (" сервер: Принял соединение от %s\n ", inet_ntoa (their_addr.sin_addr)); if(!fork()) [B]{/* Мы находимся в дочернем порожденном процессе */ close (sd); /* Закрываем дескриптор слушающего сокета, он потомку не нужен */ /* Потомок наследует все файловые дескрипторы родителя, а значит, и newsd */ /* Теперь таких сокетов два - в каждом процессе по одному */ /* Шлем клиенту 14 байтов */ if (send(newfd, " Привет, мир! \n", 14, 0) == -1)perror ("send"); close(newsd);/* Закрываем сокет newsd в порожденном процессе */ exit (0);/* Завершаем передачу данных из процесса потомка */ } /* Здесь заканчивается текст процесса программы-потомка*/[/B] close (newsd); /* Закрываем сокет newsd – родитель в нем не нуждается */ while (waitpid (-1, NULL, WNOHANG) > 0); /* Очищаем порожденные процессы */ }/*Конец цикла accept()*/ return 0; }/* Завершаем процесс сервера */ Так вот, то что болдом - (Блин, болд не работает в срр) это и есть текст программы нового дочернего процесса. И - ВСЕ. С вызова форка одновременно исполняются теперь два процесса одновременно. И говорить о копировании тут смысла нет. Ваще. Просто процесс-потомок наследует большую часть атрибутов своего родителя, и в частности, открытые файлы (порожденный процесс обладает копией дескрипторов файлов, открытых его родителем). Однако порожденный процесс после вызова fork() с помощью функции exec() может запустить совершенно новый исполнимый файл, при этом его предыдущее "родительское" содержание в памяти заменяется текстом нового файла. Так что вопрос в семантике форка. Это - не копирование, а разветвление. Потому и говорим, что Винда и никсы обладают совершенно разными подходами к вопросам запуска новых процессов. |
Сообщ.
#15
,
|
|
|
Цитата Oleg2004 @ Форк не копирует родительский процесс, а разветвляет его с созданием нового процесса. Что значит разветвляет? Процесс - это исполняемый код и память, ну и какие-то ресурсы, типа хэндлов. Насколько я понимаю, линукс, в fork() ничего этого не копирует, а просто увеличивает счётчики или типа того. Windows так не умеет. |
Сообщ.
#16
,
|
|
|
Цитата _lcf_ @ Проблема решается технологией BranchCache.в винде кэшируется только локальная память, с сетевых источником ничего не кэшируется ибо не гарантируется, что файл не был изменен. Краткое описание, взял с хабра: Цитата BranchCache – технология кэширования, встроенная в Windows 7 и Windows Server 2008 R2, и призванная оптимизировать (сократить) сетевой трафик, передаваемый по WAN-каналам связи. Соответственно, основная сфера применения BranchCache – организации с филиалами и удаленными офисами, которые связаны между собой и центральным офисом сравнительно медленными линиями передачи данных. BranchCache поддерживает кэширование HTTP- и SMB-трафика. При этом на клиентских компьютерах должна быть установлена Windows 7 (редакции Ultimate или Enterprise, в других редакциях BranchCache не работает), а на серверах – Windows Server 2008 R2. Таким образом, BranchCache работает только в связке Windows 7 + Windows Server 2008 R2. Глупо это, хранить вообще все в одном исполнительном файле и потом форкаться. Нафиг? По нормальному тогда уж если все с собой тягается, то и форкающийся код стоит вынести в отдельный exe, порождать его форкать на здоровье. А связь с основным exe уж через pipe поддерживать.. В таком случае форкаться будет только то что нужно, весь хлам будет висеть в оперативной памяти, и вдобавок к этому, если еще и не все форкается функцией, не придется заново воссоздавать объекты (там вам виднее, конечно же). |
Сообщ.
#17
,
|
|
|
Цитата Олег М @ Что значит разветвляет? Fork - это вилка, или разветвление. Я вам привел пример Цитата Олег М @ Насколько я понимаю, линукс, в fork() ничего этого не копирует, а просто увеличивает счётчики или типа того. Windows так не умеет. Все по сути сложнее. Вы же видели пример - текст программы - один но содержит код родителя и код потомка. И когда в коде родителя выполнен форк, с этого момента в системе уже два одновременно работающих процесса. Насчет счетчиков каких таких? В никсах основной процесс имеет свои таблицы файлов. В них много всего. В том числе и сокеты к примеру - они рассматриваются как псевдофайлы. Потомок делает копию таблицы родителя и работает с ней. В примере все четко показано - как родитель уничтожает указатель на сокет в своей таблице, ему с этим сокетом не надо работать. Тогда как у потомка эта запись о сокете остается. В его копии. Ну это про файлы и прочая. Есть много чего еще что копируется в процесс потомка... Почитайте "Управление процессами в UNIX" Р. Стивенса...Классика. |
Сообщ.
#18
,
|
|
|
Цитата Oleg2004 @ Насчет счетчиков каких таких? В никсах основной процесс имеет свои таблицы файлов. В них много всего. В том числе и сокеты к примеру - они рассматриваются как псевдофайлы. Потомок делает копию таблицы родителя и работает с ней. В примере все четко показано - как родитель уничтожает указатель на сокет в своей таблице, ему с этим сокетом не надо работать. Тогда как у потомка эта запись о сокете остается. В его копии. Ну это про файлы и прочая. Есть много чего еще что копируется в процесс потомка... Счётчики использования страниц памяти, использования хэндлов. Т.е. когда ты создаёшь копию процесса, зачем тебе копировать его код? Он read-only, поэтому достаточно увеличить счётчик соответствующих страниц памяти и пользоваться ими. Цитата Oleg2004 @ Fork - это вилка, или разветвление. Я вам привел пример Я знаю как переводится слово fork. Чтобы дублировать процесс, нужно скопировать его код и память и запустить поток. Чтобы этот процесс продолжил работать с того же места нужно ещё скопировать регистры потока. |
Сообщ.
#19
,
|
|
|
Цитата simsergey @ Проблема решается технологией BranchCache. ни черта она не решается, у нас поддержка вынь 7,8 и 10 Цитата simsergey @ Глупо это, хранить вообще все в одном исполнительном файле и потом форкаться. Нафиг? я уже все описывал в теме Олег М, simsergey, Oleg2004 вы можете и дальше за форк ченить поговорить Цитата _lcf_ @ ну и да в винде createprocess, а не форк, да и... в линуксе тоже. подразумевалось, что конкретно у нас форк не используется, просто так все говорят... |
Сообщ.
#20
,
|
|
|
Цитата _lcf_ @ То есть, почему?ни черта она не решается Единственное, этот компонент надо поставить, он по умолчанию не установлен, и доступен правда не во всех редакциях. |
Сообщ.
#21
,
|
|
|
simsergey
Цитата simsergey @ Таким образом, BranchCache работает только в связке Windows 7 + Windows Server 2008 R2. это раз. хотя может сейчас и есть поддержка новых версий винды. ну а второе, это значит мы своим клиентам должны сказать - ну вы там админов своих пните, чтобы они тулзу какую-то настроили |
Сообщ.
#22
,
|
|
|
Цитата _lcf_ @ Олег М, simsergey, Oleg2004 вы можете и дальше за форк ченить поговорить Да уж нет, увольте. Основная проблема принципиально ясна, и как решить ее вы уже предложили. Одно правда я так и не допонял Ваши юзвери пользуют и винду и никсы? |
Сообщ.
#23
,
|
|
|
Цитата _lcf_ @ ну а второе, это значит мы своим клиентам должны сказать - ну вы там админов своих пните, чтобы они тулзу какую-то настроили Не, ну вы можете им, клиентам, сказать, что это у вашей компании политика такая, чтоб всё тормозило, надо потерпеть. Они поймут. |
Сообщ.
#24
,
|
|
|
Цитата _lcf_ @ Это нормальная практика, выставить системные требования для ОС.ну а второе, это значит мы своим клиентам должны сказать - ну вы там админов своих пните, чтобы они тулзу какую-то настроили С другой стороны - это плата за упрямство держать все в одном .exe, другое дело, как я писал выше, стартовать свою систему, вытаскивать все что есть в память, а там уже стартовать другие свои exe, связываться с ними и т.д., если есть такая необходимость форкать процессы в винде, зная что они не форкаются, а создаются заново. Почему потоки не использовать? Приложению требуется работать в распределенных системах с поддержкой миграции процессов (без поддержки миграции по нодам потоков) ? Впрочем, для вашей задачи я предложил решение - BranchCache, exe будет стартовать из кэша на конечной машине, второй раз. Это в общем-то решение "из коробки", остальное - это переделка вашего кода. Это изначально не ровное решение. |
Сообщ.
#25
,
|
|
|
Цитата Oleg2004 @ Ваши юзвери пользуют и винду и никсы? в основном винда. но есть пользователи кластеров - узлы на никсах, терминалы на винде. разработчики все на никсах (почти). Цитата Олег М @ Они поймут. решение уже реализовано, тут хоть кто-нибудь читать умеет? Добавлено Цитата simsergey @ Почему потоки не использовать? Цитата _lcf_ @ форк так контролируемый, как раз чтобы снизить негативные последствия возможных падений. Цитата simsergey @ остальное - это переделка вашего кода. это несравнимо проще, чем пытаться напрячь людей по всему миру |
Сообщ.
#26
,
|
|
|
Цитата _lcf_ @ решение уже реализовано, тут хоть кто-нибудь читать умеет? Звучит примерно как - мы уже привинтили к своему велосипеду квадратные колёса и нам нужно только чтоб он поехал. Здесь единственным решением скорее всего будет сохранять файл на локальном диске. Как это сделать - другой вопрос. Наверняка есть возможность в обоих системах настроить кэширование файла или какой-нибудь оффлайн доступ для расшаренных папок. Ну и в любом случае что-то придётся настраивать на клиентах. |
Сообщ.
#27
,
|
|
|
Олег М, ну вы явно не читаете что я пишу.
Цитата Олег М @ Здесь единственным решением скорее всего будет сохранять файл на локальном диске. так и сделано. Цитата Олег М @ Как это сделать - другой вопрос. в никсах положен болт, там прекрасно кешируются сетевые данные. для винды проверяется сетевой ли файл (PathIsNetworkPath), если сетевой и номер ревизии не совпадает(он в имени локальном отображен), то тянется на диск. Цитата Олег М @ Ну и в любом случае что-то придётся настраивать на клиентах. ничего не придется. будут папочку темп раз в год чистить. много жалоб будет, будем сами чистить, если файлов больше 5, например. |
Сообщ.
#28
,
|
|
|
Цитата _lcf_ @ его не придется. будут папочку темп раз в год чистить. много жалоб будет, будем сами чистить, если файлов больше 5, например Т.е. проблемы уже нет? |
Сообщ.
#29
,
|
|
|
Цитата _lcf_ @ в основном винда. но есть пользователи кластеров - узлы на никсах, терминалы на винде. разработчики все на никсах (почти). Понятно. Вопросов больше нет... |
Сообщ.
#30
,
|
|
|
в общем да, проблему можно считать решенной. но если найдется способ программно объяснить системе, что неплохо бы кешировать сетевые данные...
но я так понимаю, что это уже задача ФС, как у NFS, например. |
Сообщ.
#31
,
|
|
|
Цитата _lcf_ @ с сетевых источником ничего не кэшируется ибо не гарантируется, что файл не был изменен А покурим-ка маны по smbfs (mount.cifs): Цитата cache= Cache mode. See the section below on CACHE COHERENCY for details. Allowed values are: • none: do not cache file data at all • strict: follow the CIFS/SMB2 protocol strictly • loose: allow loose caching semantics The default in kernels prior to 3.7 was "loose". As of kernel 3.7 the default is "strict". И видим, что SMB2 всеж как-то кэширование поддерживает. Для *nix SMB реализован в виде обычной файловой системы (smbfs). А вот дальше, как именно реализовано кеширование - рекомендую погуглить самостоятельно. |