у меня есть dll
приложение, которое написано в Visual Studio 2008 VC++
, В основном он имеет два интерфейса для внешних приложений.
Один из них для писателя:
class writer_interface
{
virtual void write (myData data, unsigned long id) = 0;
}
а другой для приложений для чтения:
class reader_interface
{
virtual select(unsigned long id) = 0;
virtual select(time_t insertionTime) = 0;
}
поэтому я храню свои метаданные в контейнере в общей памяти, которую я использую boost managed_shared_memory
,
Проблема заключается в том, что внешнее приложение записи вызывает мою функцию записи примерно 15 раз в секунду, а читатели делают запрос в мой контейнер с общей памятью примерно 5 раз в секунду одновременно.
Таким образом, для каждого вызова функции Write для моего метода Write я должен открыть разделяемую память & найди мой контейнер вот так:
//Open the managed segment
managed_shared_memory segment(open_only, "MySharedMemory");
//Find the vector using the c-string name
MyVector *myvector = segment.find<MyVector>("MyVector").first;
но этот слишком дорог, когда у меня есть такие частые данные. Потому что каждое открытие разделяет память & нахождение контейнера в нем операция занимает почти 100 milliseconds
, Это означает, что существует узкое место из-за операций с общей памятью.
Та же самая проблема узкого места происходит и для приложений для чтения.
У меня вопрос, как я могу сделать эти операции с общей памятью быстрее?
Есть ли способ предотвратить открытие и повторное обнаружение контейнера каждый раз в общей памяти?
Спасибо.
Кэшировать недавно открытые сегменты в памяти — хорошая идея. Предположим, что вы будете кэшировать последние 10 открытых сегментов. Создайте одноэлементный класс, который будет содержать словарь, который отображает строку в объект сегмента. Каждый раз, когда вам нужно читать / писать из любого сегмента, вы будете проверять, включает ли этот синглтон его уже (по некоторому идентификатору — например, по имени). Если да — вы получите его ссылку / указатель и прочитаете / запишите его. В противном случае вы откроете новый сегмент и сохраните его в этом синглтоне.
Singleton — это класс, который может иметь только один экземпляр, обычно создаваемый при первом использовании. Смотрите следующую ссылку http://forums.codeguru.com/showthread.php?423850-how-to-implement-a-singleton-in-c-c.
Я бы сделал это так
В заголовочном файле:
class Singleton {
public:
static Singleton* instance();
void write (myData data, unsigned long id);
void select(unsigned long id);
void select(time_t insertionTime);
private:
Singleton();
static Singleton* m_singleton; // singleton instance
managed_shared_memory m_segment;
};
В файле cpp:
Синглтон * Синглтон :: m_singleton = NULL;
Singleton::Singleton()
: segment(open_only, "MySharedMemory")
{
// do init stuff
}
Singleton* Singleton::instance()
{
if (m_singleton== NULL)
m_singleton = new Singleton();
return m_singleton;
}
void Singleton::write (myData data, unsigned long id)
{
//Find the vector using the c-string name
MyVector *myvector = m_segment.find<MyVector>("MyVector").first;
// add code here
}
void Singleton::select(unsigned long id)
{
// your code here
}
void Singleton::select(time_t insertionTime)
{
// your code here
}
Использование в конструкторе write_interface:
Singleton::instance().write (data, id);
Решение обеспечивает только один экземпляр, поскольку программа запускается до ее завершения.
Кэшировать недавно открытые сегменты в памяти — хорошая идея.
Предположим, что вы будете кэшировать последние 10 открытых сегментов.
Создайте одноэлементный класс, который будет содержать словарь, который отображает строку в объект сегмента.
Каждый раз, когда вам нужно читать / писать из любого сегмента, вы будете проверять, включает ли этот синглтон его уже (по некоторому идентификатору — например, по имени). Если да — вы получите его ссылку / указатель и прочитаете / запишите его. В противном случае вы откроете новый сегмент и сохраните его в этом синглтоне.