Увеличить IPC managed_memory_segment bad_alloc

Статья в wikipedia в r-squareds предполагает, что она может использоваться для подгонки общей модели, а не только для линейной регрессии.

1
задан nm_tp 22 January 2019 в 09:09
поделиться

2 ответа

После некоторых исследований и испытаний я нашел решение, приведенное ниже. Ключевым моментом здесь является использование boost::move (или, возможно, std :: move, не знаю, будет ли здесь разница). Поскольку мы используем boost::move, не будет копий объектов IPCString и, следовательно, не нужно умножать на 2. Помните, из-за того, как мы определили IPCString, он будет размещен внутри сегмента разделяемой памяти.

Необходимы дополнительные издержки (возможно, из-за выравнивания или других добавленных накладных расходов, или обоих), но всегда остается некоторое пространство. Поскольку я мог посылать несколько мегабайт, служебные данные 500 байтов довольно малы.

Я использую метод std::string size(), потому что он возвращает размер строки в байтах .

Код выглядит следующим образом:

shared_memory.h:

#pragma once

#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/containers/string.hpp>

#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/sync/named_mutex.hpp>

#include <string>
#include <vector>
#include <exception>

namespace apl_shared_memory
{
  typedef boost::interprocess::allocator<char, boost::interprocess::managed_shared_memory::segment_manager> CharAllocator;
  typedef boost::interprocess::basic_string<char, std::char_traits<char>, CharAllocator> IPCString;
  typedef boost::interprocess::allocator<IPCString, boost::interprocess::managed_shared_memory::segment_manager> StringAllocator;
  typedef boost::interprocess::vector<IPCString, StringAllocator> ShmVector;

  bool write_to_memory(std::string wsuid, std::string loop_val, std::string should_intercept, std::string post_data) ;


  const std::string shm_prefix = "shm_";
  const std::string mutex_prefix = "mtx_";
}

shared_memory.cpp:

#include "shared_memory.h"

#include "logger.h"



namespace apl_shared_memory

{
    bool write_to_memory(std::string wsuid, std::string loop_val, std::string should_intercept, std::string post_data)
    {
        bool ret_val;
        std::string shm_name = shm_prefix + wsuid;
        std::string mtx_name = mutex_prefix + wsuid;

        boost::interprocess::named_mutex named_mtx{ boost::interprocess::open_or_create, mtx_name.c_str() };

        // Add the size of all the structures we're putting in the shared memory region and add some for the overhead.
        size_t size = (3*sizeof(IPCString) + loop_val.size() + should_intercept.size() + post_data.size() + sizeof(ShmVector)) + 500;

        try
        {
            named_mtx.lock();
            boost::interprocess::shared_memory_object::remove(shm_name.c_str());
            boost::interprocess::managed_shared_memory segment(boost::interprocess::create_only, shm_name.c_str(), size);

            CharAllocator     charallocator(segment.get_segment_manager());
            StringAllocator   stringallocator(segment.get_segment_manager());

            IPCString shm_loop_val(charallocator);
            IPCString shm_should_intercept(charallocator);
            IPCString shm_intercepted_data(charallocator);

            shm_loop_val = loop_val.c_str();
            shm_should_intercept = should_intercept.c_str();
            shm_intercepted_data = post_data.c_str();

            segment.destroy<ShmVector>("ShmVector");
            ShmVector *shmVector = segment.construct<ShmVector>("ShmVector")(stringallocator);
            shmVector->clear();
            shmVector->reserve(3);

            // push_back will call a copy-constructor. But, if we send a rvalue reference (i.e. if we move it), there will be no copying.
            shmVector->push_back(boost::move(shm_loop_val));
            shmVector->push_back(boost::move(shm_should_intercept));
            shmVector->push_back(boost::move(shm_intercepted_data));

            ret_val = true;
        }

        catch (const std::exception& ex)

        {
            ret_val = false;
            boost::interprocess::shared_memory_object::remove(shm_name.c_str());
        }

        named_mtx.unlock();

        return ret_val;
    }
}
[1117 ] Если кто-то считает, что я сделал что-то не так, пожалуйста, прокомментируйте.

0
ответ дан nm_tp 22 January 2019 в 09:09
поделиться

Вы делаете много предположений об эквивалентности размеров шрифта. Использование памяти строки AC не совпадает с использованием памяти std :: string, которое не совпадает с использованием памяти IPCString, которая на самом деле является вектором , так что вас это не интересует по размеру или длине, но вместимости.

Оцените свои компоненты изо рта лошади: возьмите sizeof из переменных IPCString вместо std::string переменных, а также возьмите shm_loop_val.capacity() + shm_should_intercept.capacity() + shm_intercepted_data.capacity() вместо определения размера std::strings!

Вы должно быть ближе к:

size_t size = (3 * sizeof(IPCString) + sizeof(ShmVector) + shm_loop_val.capacity() +
              shm_should_intercept.capacity() + shm_intercepted_data.capacity();

Реализация Boost может также выровнять ваши данные по словам, но я начинаю понимать, что это очень маловероятно. Это выглядит как сериализованное. Мы можем посмотреть, что у вас все еще есть проблемы.

0
ответ дан okovko 22 January 2019 в 09:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: