Безопасный способ обновления пакетов R - возможна ли «горячая замена»? - PullRequest
8 голосов
/ 27 января 2012

Я сталкивался с этой проблемой несколько раз и не могу найти ни одного решения, кроме тривиального (см. Ниже).

Предположим, что на компьютере запущено более 2 экземпляров R из-за2+ пользователя или 1 пользователь, выполняющий несколько процессов, и один экземпляр выполняет update.packages().У меня было несколько раз, когда другой экземпляр мог запутаться.Обновляемые пакеты никоим образом не изменяют функциональность, которая влияет на вычисления, но почему-то возникает большая проблема.

Тривиальное решение (Решение 0) - завершить все экземпляры R, пока выполняется update.packages().Это имеет 2+ проблемы.Сначала нужно завершить R экземпляров.Во-вторых, можно даже не определить, где запущены эти экземпляры (см. Обновление 1).

Предполагая, что поведение исполняемого кода не изменится (например, обновления пакетов полезны - они толькоисправлять ошибки, улучшать скорость, уменьшать объем оперативной памяти и предоставлять единорогов), есть ли способ горячей замены новой версии пакета с меньшим влиянием на другие процессы?

У меня есть еще два варианта решения, кроме R:

Решение 1 - использовать временный путь к библиотеке, а затем удалить старую старую библиотеку и переместить новую на место.Недостатком этого является то, что удаление + ходы может занять некоторое время, в течение которого ничего не доступно.

Решение 2 - использовать символические ссылки для указания на библиотеку (или иерархию библиотеки) и просто перезаписать символическую ссылку указателем нановая библиотека, в которой находится обновленный пакет.Похоже, это приводит к еще меньшему времени простоя пакетов - времени, которое требуется ОС для перезаписи символической ссылки.Недостатком этого является то, что он требует гораздо большего внимания при управлении символическими ссылками и зависит от платформы.

Я подозреваю, что решение № 1 можно изменить так, чтобы оно было похоже на # 2, путем умного использования .libPaths(), но кажется, что нужно не вызывать update.packages() и вместо этого написать новый модуль обновления, который находит устаревшие пакеты, устанавливает их во временную библиотеку, а затем обновляет пути к библиотекам.Преимуществом этого является то, что можно ограничить существующий процесс до .libPaths(), который был у него при запуске (т. Е. Изменение путей к библиотекам, о которых знает R, может не распространяться на те экземпляры, которые уже запущены, без какого-либо явного вмешательства в этом экземпляре).).


Обновление 1. В примере сценария два конкурирующих экземпляра R находятся на одном компьютере.Это не является обязательным требованием: насколько я понимаю обновления, если эти две библиотеки используют одни и те же библиотеки, то есть одни и те же каталоги на общем диске, обновление может по-прежнему вызывать проблемы, даже если другой экземпляр R находится на другом компьютере.,Таким образом, можно случайно убить процесс R и даже не увидеть его.

Ответы [ 3 ]

4 голосов
/ 27 января 2012

В производственной среде вы, вероятно, захотите сохранить как минимум две версии, текущую и предыдущую, чтобы иметь возможность быстро переключиться на старую в случае возникновения проблемы. Ничто не будет перезаписано или удалено. Это проще сделать для всей экосистемы R: у вас будет несколько каталогов, скажем, "R-2.14.1-2011-12-22", "R-2.14.1-2012-01-27" и т. Д., каждый из которых содержит все (исполняемые файлы R и все пакеты). Эти каталоги никогда не будут обновлены: если потребуется обновление, будет создан новый каталог. (Некоторые файловые системы предоставляют «снимки», которые позволят вам иметь много очень похожих каталогов без чрезмерного использования дискового пространства.)

Переключение с одной версии на другую может быть выполнено на стороне пользователя, когда пользователи запускают R, либо заменяя исполняемый файл R скриптом, который будет использовать правильную версию, либо устанавливая переменную среды PATH для указания на желаемая версия. Это гарантирует, что данный сеанс всегда видит одну и ту же версию всего.

3 голосов
/ 27 января 2012

Мое сильное предположение, что нет никакого способа обойти это.

Особенно, когда пакет включает в себя скомпилированный код, вы не можете удалить и заменить DLL, пока она используется, и ожидать, что она все еще будет работать. Все указатели на DLL, используемые R-вызовами этих функций, будут запрашивать определенную область памяти и обнаружат, что она необъяснимым образом исчезла. (Примечание: хотя я использую здесь термин «DLL», я имею в виду его не в специфическом для Windows смысле, как он используется, например, в файле справки для ?getLoadedDLLs. «Общая библиотека», возможно, лучше общий термин.)

(Некоторое подтверждение моих подозрений приходит от FAQ по R для Windows , который сообщает, что «Windows блокирует библиотеку [a] пакета во время загрузки», что может вызвать сбой update.packages().)

Я не совсем уверен, как реализован механизм отложенной загрузки R, но представьте, что он тоже может быть испорчен удалением объектов, которые он ожидает найти по определенным адресам в машине.

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

1 голос
/ 09 февраля 2012

Вот сценарий, с которым я столкнулся вчера в Windows 7.

  1. Я запускаю сеанс R.
  2. Откройте PDF-файл руководства по пакету.
  3. Закройте все сеансы R.Забудьте закрыть руководство по пакету PDF.
  4. Откройте новый экземпляр R, запустите update.packages ()

Конечно, установка завершается неудачно, потому что в Windows по-прежнему открыт pdf, и он можетперезаписать это ....

...