Безопасный метод обновления пакетов R — возможна ли горячая замена?

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

Предположим, на компьютере запущено 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 и даже не увидеть его.


person Iterator    schedule 26.01.2012    source источник


Ответы (3)


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

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

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

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

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

person Josh O'Brien    schedule 26.01.2012
comment
Это важный момент. Я подозреваю, что проблема с общей библиотекой является проблемой для всех операционных систем. В большинстве случаев я склонен полагать, что это убивает идею горячей замены. Самый узкий случай будет для пакетов, которые не используют внешние общие библиотеки, но я не уверен, как это работает для пакетов, полностью написанных на R. - person Iterator; 31.01.2012
comment
Я думаю, что ваш ответ в значительной степени разрушает мечту о горячей замене в целом. Даже если у меня есть чистый пакет R, который я хотел бы заменить в «горячем» режиме, просто не рекомендуется предполагать, что я могу это сделать. У Винсента есть разумный ответ о том, как можно управлять версиями, а не заменять местами, который мне придется немного адаптировать, но ясно, что это единственный способ обойти указанные вами конфликты. - person Iterator; 12.02.2012

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

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

person Vincent Zoonekynd    schedule 27.01.2012
comment
Это хорошее предложение, как для возможности отменить/отменить изменения, так и для возможности воспроизведения результатов. Мне нужно еще немного подумать о накладных расходах на передачу информации о версии. - person Iterator; 27.01.2012
comment
Я думаю, вы дали отличный ответ о передовом опыте. Ответ Джоша больше сосредоточен на том, почему не существует безопасного метода горячей замены. На основании его ответа, который я выбрал, я бы сказал, что ваш ответ касается того, что следует сделать для решения таких проблем. - person Iterator; 12.02.2012

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

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

Установка, конечно, не удалась, потому что Windows все еще имеет открытый PDF-файл и не может его перезаписать....

person Kevin Wright    schedule 09.02.2012
comment
+1 Это было бы довольно плохо в общей среде. Я не тестировал Linux с несколькими пользователями, но мне интересно, как это будет работать, скажем, в ситуации со 100 пользователями, когда кто-то читает виньетку пакета... - person Iterator; 12.02.2012
comment
В Linux это не вызовет никаких проблем: по умолчанию используемые файлы не заблокированы. Если файл PDF все еще существует после обновления, программа просмотра PDF заметит изменение, обновит и отобразит новый файл. Если файла PDF больше нет, средство просмотра PDF, вероятно, продолжит отображать старый файл (файл на самом деле не удален, он находится в подвешенном состоянии, все еще там, без имени, и действительно исчезнет только тогда, когда все приложения прочитав его, закройте файл). В худшем случае средство просмотра PDF отобразит сообщение об ошибке, но это не помешает обновлению. - person Vincent Zoonekynd; 12.02.2012