Общая память без блокировки в C++ для записей переменной длины
Я новичок в IPC. Процесс Writer записывает данные в общую память, Многие процессы чтения считывают данные. Данные, которые должны быть записаны, имеют уникальный идентификатор, должны быть проиндексированы по уникальному ключу для более быстрого доступа (например, STL::map или hashmap для поиска). Также данные представляют собой запись переменной длины ( XML) (средняя длина составляет 200-250 байт). ОС Solaris 10 (i86pc) на четырехъядерном сервере Intel Xeon.
Общий размер данных составляет более 200G. Но мы будем хранить только последние данные в общей памяти. Исторические данные хранятся в файле. размер разделяемой памяти будет около 4G~6G.
Нет доступных внешних библиотек, таких как Boost::interprocess
У меня есть пара вопросов, может быть много
- Что более эффективно: shared_memory или mmap (файлы с отображением в памяти)
- Как построить индексы для записи переменной длины. [Понятия не имею, может быть какое-то хеширование?].
- Будет ли это хорошо, если XML преобразуется в структуру с фиксированным размером (компромисс - размер структуры будет огромным, около 300+ возможных полей)
- Можем ли мы поместить любой STL в shared_memory, предоставив пользовательский распределитель.
- Возможно ли реализовать без семафоров (реализация без блокировки с использованием CAS).
Спасибо
Как насчет этого.
|--------------------------|
| start_id | end_id | -> range of msg id present in the segment
|--------------------------|
| id1 | start_mem | length | ->
|--------------------------| ->
| id2 | start_mem | length | -> table of index for the actual data
|--------------------------| ->
| id3 | start_mem | length | ->
|--------------------------| ->
| id4 | start_mem | length | ->
|--------------------------| ->
| |
| |
| |
| data segment |
| varibale length |
| xml are stored |
| |
| |
|--------------------------|
Когда поступают новые данные и сегмент полон. самые старые данные стираются по кругу. Может быть возможность удаления более 1 записи.
2 ответа
Самое простое решение, если вам требуется сложная индексация и другие подобные вещи, вам следует рассмотреть сервис-ориентированную архитектуру, а не разделяемую память. Просто назначьте один процесс как ваш основной процесс кэширования, и пусть он принимает локальные соединения (через сокеты домена unix, или сокеты TCP, или что-то еще) от других процессов, которым требуются данные. Это делает вещи намного, намного проще.
Если вы не выберете этот маршрут, имейте в виду, что совместно используемая память трудна. То, что вы спрашиваете, безусловно, выполнимо в общей памяти - вы можете создать распределитель кучи в этом блоке shmem и т. Д. И т. Д. Распределители STL могут работать, но не ожидайте, что какие-либо сторонние библиотеки будут довольны распределителями STL, использующими пользовательские типы указателей. Вам понадобятся замки (если вы сообразительны, вы можете избежать их в некоторых случаях, но не во всех, и в этом случае определенно попрощаетесь с STL), и вам придется восстанавливать все, что вы обычно принимаете как должное.
Опять же, я настоятельно рекомендую вам начать с простого демона кэша. В большинстве случаев это прекрасно масштабируется, просто добавляет немного больше времени ожидания.
Возможно ли реализовать без семафоров (реализация без блокировки с использованием CAS).
Поскольку реализации без блокировок (без блокировок) сложно спроектировать, и мы можем оказаться в хаосе, прежде чем переходить к решению без блокировок, вам следует рассмотреть следующие аспекты и альтернативы:
- Если в системе много потоков, так что планировщик, вероятно, будет вытеснять поток, удерживающий блокировку, следовательно, все остальные потоки будут ожидать блокировки (если не блокировка не даст существенного улучшения).
- Если это можно решить с помощью блокировки читателей-писателей. (писателей значительно меньше, чем читателей).
- Если конфликт блокировок менее вероятен, тогда вы можете рассмотреть спин-блокировки, которые будут равны производительности без блокировок.