Можно ли сделать переключение контекста библиотеки в пределах процесса?
От: alexraynepe196  
Дата: 14.11.20 10:47
Оценка:
1) есть некая библиотека моделирующая некое устройство — длл, или sharedobject (собирается как native-код вызываемый из java)
2) в среде эмулятора (на жабе) надо загрузить и смоделировать множество экземпляров устройств — больше 100 или 1000 скажем.
3) в текущей реализации загружается библиотека, а для каждого экземпляра хранится копия области данных используемая библиотекой. Исполняемый код остается общим. Для выполнения кода над конкретным экземпляром — область данных библиотеки перезаписывается из контейнера экземпляра.

Сейчас переключение экземпляра очень затратно — скопировать 30-60кБ данных надо, чтобы выполнить кода на сотню тактов. более 95% времени занимает это копирование.

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

MMU современных процессоров с другой стороны просто предназначено для решения подобных задач — достаточно создать несколько сегментов данных — по одному на каждое устройство, и переключать эти сегменты при исполнении одного общего сегмента кода. Но как это сделать реально?
Вродебы это операционная система проделывает при использовании разделяемой библиотеки для разных процессов. НО как это сделать в рамках одного процесса? Это вообще реально в существующей среде, на линухе?
Re: Можно ли сделать переключение контекста библиотеки в пределах процесса?
От: a7d3  
Дата: 14.11.20 11:27
Оценка:
Здравствуйте, alexraynepe196, Вы писали:

A>MMU современных процессоров с другой стороны просто предназначено для решения подобных задач — достаточно создать несколько сегментов данных — по одному на каждое устройство, и переключать эти сегменты при исполнении одного общего сегмента кода. Но как это сделать реально?

A>Вродебы это операционная система проделывает при использовании разделяемой библиотеки для разных процессов. НО как это сделать в рамках одного процесса? Это вообще реально в существующей среде, на линухе?

Нет, потому что MMU работает с контекстами виртуальных адресных пространств. Транслируя адреса из нескольких совершенно разных адресных пространств в одно пространство — реальные адреса физических страниц памяти.
Выполняется это посредством ассоциативного кэша в виде TLB (который как правило ещё и двух-уровневый).

Т.е. средства ОС не помогут в данном случае избежать необходимости ломать реализацию проблемной библиотеки — таки придётся её переделывать.
Чтобы библиотека в явной форме позволяла управлять контекстами — теми экземплярами объектной модели (областями данных), которые предоставляет для изменения клиентским кодом.
Фактически исполняемому коду библиотеки надо будет принимать некий токен/хэндл, являющийся индексом в таблице контекстов.
Re[2]: Можно ли сделать переключение контекста библиотеки в пределах процесса?
От: alexraynepe196  
Дата: 14.11.20 18:15
Оценка:
Здравствуйте, a7d3, Вы писали:

A>Нет, потому что MMU работает с контекстами виртуальных адресных пространств. Транслируя адреса из нескольких совершенно разных адресных пространств в одно пространство — реальные адреса физических страниц памяти.

A>Выполняется это посредством ассоциативного кэша в виде TLB (который как правило ещё и двух-уровневый).
Собственно я про это и говорил, коментируя ММУ — имея один общий сегмент кода, можно передавать ей разный сегмент данных.

A>Т.е. средства ОС не помогут в данном случае избежать необходимости ломать реализацию проблемной библиотеки — таки придётся её переделывать.

A>Чтобы библиотека в явной форме позволяла управлять контекстами — теми экземплярами объектной модели (областями данных), которые предоставляет для изменения клиентским кодом.
A>Фактически исполняемому коду библиотеки надо будет принимать некий токен/хэндл, являющийся индексом в таблице контекстов.

У меня нет возможности переделывать структуру клиентской библиотеку — собственно задача среды как раз есть смоделировать работу клиентского кода таким какой он есть.
Re[2]: Можно ли сделать переключение контекста библиотеки в
От: ononim  
Дата: 14.11.20 18:17
Оценка:
A>Нет, потому что MMU работает с контекстами виртуальных адресных пространств. Транслируя адреса из нескольких совершенно разных адресных пространств в одно пространство — реальные адреса физических страниц памяти.
A>Выполняется это посредством ассоциативного кэша в виде TLB (который как правило ещё и двух-уровневый).
A>Т.е. средства ОС не помогут в данном случае избежать необходимости ломать реализацию проблемной библиотеки — таки придётся её переделывать.
Строго говоря промапить файл в АП одного процесса дважды двумя вызовами MapViewOfFile в два отображения по разным адресам — не проблема. Проблема в том что LoadLibrary* так не умеют (в отличии от юниксового dlmopen, например).
Как много веселых ребят, и все делают велосипед...
Отредактировано 14.11.2020 18:18 ononim . Предыдущая версия .
Re: Можно ли сделать переключение контекста библиотеки в пре
От: ononim  
Дата: 14.11.20 18:24
Оценка:
Даже если вы этого и добьетесь (или уже добились путем memcpy), то все равно такое решение будет иметь кучу потенциальных проблем, ведь контекст бибилиотеки в общем случае это не только сегмент данных:
1) DllMain(DLL_PROCESS/THREAD_ATTACH/DETACH) и прочие там FLS callback-и будут исполняться с текущим "контекстом" — альтернативные "контексты" могут оказаться недоинициализированными или напротив — могут вызвать утечку памяти и прочих ресурсов. Впрочем, учитывая что у вас там java, последним наверное можно пренебречь
2) если длл использует именованные объекты, привязанные к PID текущего процесса (зачем — отдальный вопрос, но такое бывает) — с ними будут проблемы
3) если длл создает окна/классы окон — опять же возможны проблемы, так как HINSTANCE общий, а классы — разные. Не факт что все срастется.
4) если длл юзается из разных потоков или сама порождает потоки (возможно даже неявно) — будут редкие рандомные проблемы.
..) ...
Вобщем, или делать реально отдельные инстансы длл, или (если во-взрослому) переписывать код длл на возможность использования многих устройств с одной длл.
Как много веселых ребят, и все делают велосипед...
Отредактировано 14.11.2020 18:27 ononim . Предыдущая версия .
Re[3]: Можно ли сделать переключение контекста библиотеки в
От: a7d3  
Дата: 14.11.20 18:31
Оценка:
Здравствуйте, ononim, Вы писали:

A>>Нет, потому что MMU работает с контекстами виртуальных адресных пространств. Транслируя адреса из нескольких совершенно разных адресных пространств в одно пространство — реальные адреса физических страниц памяти.

A>>Выполняется это посредством ассоциативного кэша в виде TLB (который как правило ещё и двух-уровневый).
A>>Т.е. средства ОС не помогут в данном случае избежать необходимости ломать реализацию проблемной библиотеки — таки придётся её переделывать.
O>Строго говоря промапить файл в АП одного процесса дважды двумя вызовами MapViewOfFile в два отображения по разным адресам — не проблема. Проблема в том что LoadLibrary* так не умеют (в отличии от юниксового dlmopen, например).

Это если либа без рантайма и не использует глобальных переменных, создаваемых — инициализируемых и размещаемых этим самым рантаймом.
Re[3]: Можно ли сделать переключение контекста библиотеки в пределах процесса?
От: a7d3  
Дата: 14.11.20 18:34
Оценка:
Здравствуйте, alexraynepe196, Вы писали:

A>Здравствуйте, a7d3, Вы писали:


A>>Нет, потому что MMU работает с контекстами виртуальных адресных пространств. Транслируя адреса из нескольких совершенно разных адресных пространств в одно пространство — реальные адреса физических страниц памяти.

A>>Выполняется это посредством ассоциативного кэша в виде TLB (который как правило ещё и двух-уровневый).
A>Собственно я про это и говорил, коментируя ММУ — имея один общий сегмент кода, можно передавать ей разный сегмент данных.

Чтобы использовать в этих целях MMU надо располагать эти сегменты в разных адресных пространствах, разделяемых на аппаратном уровне процессора
Лезть грязными руками в ту часть ядра ОС, которая отвечает за организацию работы виртуальной памяти.
Re[4]: Можно ли сделать переключение контекста библиотеки в
От: ononim  
Дата: 14.11.20 19:45
Оценка:
O>>Строго говоря промапить файл в АП одного процесса дважды двумя вызовами MapViewOfFile в два отображения по разным адресам — не проблема. Проблема в том что LoadLibrary* так не умеют (в отличии от юниксового dlmopen, например).
A>Это если либа без рантайма и не использует глобальных переменных, создаваемых — инициализируемых и размещаемых этим самым рантаймом.
Ась? Причем тут рантайм, речь о том что dlmopen позволяет загружать одну и ту же библиотеку в процесс в изолированных dynamic-linker namespaces', а винда так не умеет.
Но гипотетически можно предположить LoadLibraryEx с флагом DLL_FORCE_UNIQUE_LOAD которая бы загрузила еще одну копию длл в АП с того же файла, но по новому адресу. И оно бы работало (более того, когда то я своими кривыми руками такого поведения даже добивался от обычной LoadLibraryEx, но это был у меня баг).
Как много веселых ребят, и все делают велосипед...
Отредактировано 14.11.2020 19:54 ononim . Предыдущая версия .
Re: Можно ли сделать переключение контекста библиотеки в пределах процесса?
От: Pzz Россия https://github.com/alexpevzner
Дата: 14.11.20 20:16
Оценка:
Здравствуйте, alexraynepe196, Вы писали:

A>Единственное решение обойти это место, я пока нашел — скопировать файл библиотеки в несколько независимых, и загружать эти библиотеки как независимые, получится одна библиотека/одоно устройство.


А неужели загрузка библиотеки, которая сама по себе является достаточно затратным процессом, исполняется быстрее, чем копирование 30-60 кб данных?

A>MMU современных процессоров с другой стороны просто предназначено для решения подобных задач — достаточно создать несколько сегментов данных — по одному на каждое устройство, и переключать эти сегменты при исполнении одного общего сегмента кода. Но как это сделать реально?


A>Вродебы это операционная система проделывает при использовании разделяемой библиотеки для разных процессов. НО как это сделать в рамках одного процесса? Это вообще реально в существующей среде, на линухе?


Ну, теоретически ты мог бы не линковаться с библиотекой, а загружать ее вручную через dlmopen. Тогда ты сможешь загрузить в один процесс несколько экземпляров одной и той же библиотеки, причем у каждого экземпляра будет свое "пространство имен", т.е., они будут независимыми друг от друга.

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

Насколько это трудозатратно, и сколько ты при этом огребешь нюансов, не попробовав трудно предсказать.
Re[2]: Можно ли сделать переключение контекста библиотеки в пределах процесса?
От: alexraynepe196  
Дата: 14.11.20 20:32
Оценка:
Здравствуйте, Pzz, Вы писали:


Pzz>Ну, теоретически ты мог бы не линковаться с библиотекой, а загружать ее вручную через dlmopen. Тогда ты сможешь загрузить в один процесс несколько экземпляров одной и той же библиотеки, причем у каждого экземпляра будет свое "пространство имен", т.е., они будут независимыми друг от друга.


Можно немного подробнее что такое пространство имен? где про это вкурить мануаль?
Re[5]: Можно ли сделать переключение контекста библиотеки в
От: alexraynepe196  
Дата: 14.11.20 20:34
Оценка:
Здравствуйте, ononim, Вы писали:

O>>>Строго говоря промапить файл в АП одного процесса дважды двумя вызовами MapViewOfFile в два отображения по разным адресам — не проблема. Проблема в том что LoadLibrary* так не умеют (в отличии от юниксового dlmopen, например).

A>>Это если либа без рантайма и не использует глобальных переменных, создаваемых — инициализируемых и размещаемых этим самым рантаймом.
O>Ась? Причем тут рантайм, речь о том что dlmopen позволяет загружать одну и ту же библиотеку в процесс в изолированных dynamic-linker namespaces', а винда так не умеет.
У меня линь. Вопрос возникает — можно ли получить доступ к этим "dynamic-linker namespaces" из жабы?
Re[2]: Можно ли сделать переключение контекста библиотеки в пределах процесса?
От: alexraynepe196  
Дата: 14.11.20 20:37
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>Здравствуйте, alexraynepe196, Вы писали:


A>>Единственное решение обойти это место, я пока нашел — скопировать файл библиотеки в несколько независимых, и загружать эти библиотеки как независимые, получится одна библиотека/одоно устройство.


Pzz>А неужели загрузка библиотеки, которая сама по себе является достаточно затратным процессом, исполняется быстрее, чем копирование 30-60 кб данных?


библиотека загружается один раз, а моделирование идет доооолго.

копирование такого куска памяти полностью выносит кеш данных L0. и вызывает инвалидацию остальных кещшей. А после копирования жаба еще выполняет синхронизацию своих примитивов с кешем натив-кода.

вобчем профайлер показывает что весь остальной код (а там дофига всего) исполняется менее 10% времени.
Re[6]: Можно ли сделать переключение контекста библиотеки в
От: ononim  
Дата: 14.11.20 20:45
Оценка: +1
O>>Ась? Причем тут рантайм, речь о том что dlmopen позволяет загружать одну и ту же библиотеку в процесс в изолированных dynamic-linker namespaces', а винда так не умеет.
A>У меня линь. Вопрос возникает — можно ли получить доступ к этим "dynamic-linker namespaces" из жабы?
скорее всего напрямую никак, но можно сделать so-прослойку, которая будет предоставлять жавашному коду функцию "OpenXXX", которая будет загружать нужную so через dlmopen(LM_ID_NEWLM, ...) и получать ее функции через dlsym, а возвращать будет некий контекст. Далее предоставлять жаве набор функций аналогичных функциям "той" библиотеки, но каждая функция будет иметь дополнительный параметр "контекст" по которому она будет знать какую именно библиотеку дергать.
Как много веселых ребят, и все делают велосипед...
Re[3]: Можно ли сделать переключение контекста библиотеки в пределах процесса?
От: Pzz Россия https://github.com/alexpevzner
Дата: 14.11.20 21:09
Оценка:
Здравствуйте, alexraynepe196, Вы писали:

Pzz>>Ну, теоретически ты мог бы не линковаться с библиотекой, а загружать ее вручную через dlmopen. Тогда ты сможешь загрузить в один процесс несколько экземпляров одной и той же библиотеки, причем у каждого экземпляра будет свое "пространство имен", т.е., они будут независимыми друг от друга.


A>Можно немного подробнее что такое пространство имен? где про это вкурить мануаль?


ну по-моему, в man dlmopen все достаточно ясно написано
Re[5]: Можно ли сделать переключение контекста библиотеки в
От: a7d3  
Дата: 14.11.20 21:11
Оценка:
Здравствуйте, ononim, Вы писали:

O>>>Строго говоря промапить файл в АП одного процесса дважды двумя вызовами MapViewOfFile в два отображения по разным адресам — не проблема. Проблема в том что LoadLibrary* так не умеют (в отличии от юниксового dlmopen, например).

A>>Это если либа без рантайма и не использует глобальных переменных, создаваемых — инициализируемых и размещаемых этим самым рантаймом.
O>Ась? Причем тут рантайм, речь о том что dlmopen позволяет загружать одну и ту же библиотеку в процесс в изолированных dynamic-linker namespaces', а винда так не умеет.
O>Но гипотетически можно предположить LoadLibraryEx с флагом DLL_FORCE_UNIQUE_LOAD которая бы загрузила еще одну копию длл в АП с того же файла, но по новому адресу. И оно бы работало (более того, когда то я своими кривыми руками такого поведения даже добивался от обычной LoadLibraryEx, но это был у меня баг).

Эти неймспейсы являются абстракциями для резолва символов. Каждый из них пустой, а значит загружая в него либу надо будет в него же загружать и Си-шный рантайм тоже.
Проделали эту процедуру, получив до 16 экземпляров объектов одной и той же либы в процессе. Каждый рантайм убеждёт что монопольно владеет кучей в процессе и на своё усмотрение начинает выделять арены памяти, обеспечивать многопоточный доступ к своим структурам служебным, чтобы можно было выделять динамическую память из разных тредов.
Re[6]: Можно ли сделать переключение контекста библиотеки в
От: ononim  
Дата: 14.11.20 21:22
Оценка:
A>Эти неймспейсы являются абстракциями для резолва символов. Каждый из них пустой, а значит загружая в него либу надо будет в него же загружать и Си-шный рантайм тоже.
Он при этом сам загружается, как и все остальное

A>Проделали эту процедуру, получив до 16 экземпляров объектов одной и той же либы в процессе. Каждый рантайм убеждёт что монопольно владеет кучей в процессе и на своё усмотрение начинает выделять арены памяти, обеспечивать многопоточный доступ к своим структурам служебным, чтобы можно было выделять динамическую память из разных тредов.

Ну, вообще говоря это плохой тон в сишном апи возвращать поинтеры которые надо освобождать, и не предоставлять освобождалку. ВпрочемЮ даже если это имеет место быть в данном случае — проблема технически решаемая путем получения libc-шного объекта в нужном namespace'е и далее получения из него нужных malloc/free
Как много веселых ребят, и все делают велосипед...
Re: Можно ли сделать переключение контекста библиотеки в пределах процесса?
От: SaZ  
Дата: 14.11.20 22:38
Оценка: 3 (1)
Здравствуйте, alexraynepe196, Вы писали:


A>1) есть некая библиотека моделирующая некое устройство — длл, или sharedobject (собирается как native-код вызываемый из java)

A>2) в среде эмулятора (на жабе) надо загрузить и смоделировать множество экземпляров устройств — больше 100 или 1000 скажем.
A>3) в текущей реализации загружается библиотека, а для каждого экземпляра хранится копия области данных используемая библиотекой. Исполняемый код остается общим. Для выполнения кода над конкретным экземпляром — область данных библиотеки перезаписывается из контейнера экземпляра.

A>Сейчас переключение экземпляра очень затратно — скопировать 30-60кБ данных надо, чтобы выполнить кода на сотню тактов. более 95% времени занимает это копирование.


A>Единственное решение обойти это место, я пока нашел — скопировать файл библиотеки в несколько независимых, и загружать эти библиотеки как независимые, получится одна библиотека/одоно устройство.


A>MMU современных процессоров с другой стороны просто предназначено для решения подобных задач — достаточно создать несколько сегментов данных — по одному на каждое устройство, и переключать эти сегменты при исполнении одного общего сегмента кода. Но как это сделать реально?

A>Вродебы это операционная система проделывает при использовании разделяемой библиотеки для разных процессов. НО как это сделать в рамках одного процесса? Это вообще реально в существующей среде, на линухе?

Сделайте процесс-обвёртку вокруг вашей .dll и запускайте столько инстансов, сколько надо. Общайтесь через любой IPC. Да, производительность чуть просядет, но для эмулятора должно подойти.
Re[4]: Можно ли сделать переключение контекста библиотеки в пределах процесса?
От: alexraynepe196  
Дата: 15.11.20 10:18
Оценка:
Здравствуйте, Pzz, Вы писали:

A>>Можно немного подробнее что такое пространство имен? где про это вкурить мануаль?


Pzz>ну по-моему, в man dlmopen все достаточно ясно написано


читаю такое: "В реализации glibc поддерживается до 16 пространств имён."
Насколько это радикальное ограничение? библиотека использует sprintf из libc. вроде больше ничего.
Re[2]: Можно ли сделать переключение контекста библиотеки в пределах процесса?
От: alexraynepe196  
Дата: 15.11.20 10:22
Оценка:
Здравствуйте, SaZ, Вы писали:

A>>Единственное решение обойти это место, я пока нашел — скопировать файл библиотеки в несколько независимых, и загружать эти библиотеки как независимые, получится одна библиотека/одоно устройство.


SaZ>Сделайте процесс-обвёртку вокруг вашей .dll и запускайте столько инстансов, сколько надо. Общайтесь через любой IPC. Да, производительность чуть просядет, но для эмулятора должно подойти.


важный нюанс в том чтобы избавиться от копирования области данных, а иметь прямой доступ к ней ведь. А в Вашем варианте придется это же и делать но уже не простым копированием, а через IPC
Re[4]: Можно ли сделать переключение контекста библиотеки в пределах процесса?
От: alexraynepe196  
Дата: 15.11.20 10:32
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>Здравствуйте, alexraynepe196, Вы писали:


Pzz>>>Ну, теоретически ты мог бы не линковаться с библиотекой, а загружать ее вручную через dlmopen. Тогда ты сможешь загрузить в один процесс несколько экземпляров одной и той же библиотеки, причем у каждого экземпляра будет свое "пространство имен", т.е., они будут независимыми друг от друга.


A>>Можно немного подробнее что такое пространство имен? где про это вкурить мануаль?


Pzz>ну по-моему, в man dlmopen все достаточно ясно написано


нифига мне не ясно что там написано. Есть ли у Вас какойто пример использования, близко к сабжу, чтобы на нем посмотреть как это работает?
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.