Search code examples
c++c++11cachingboost

Caching images in c++. Using buffer_body or other things instead of file_body?


I have slightly modified version of this https://www.boost.org/doc/libs/develop/libs/beast/example/http/server/async/http_server_async.cpp.

What it does: According to the correctness of the request it returns the required image or an error.

What I'm going to do: I want to keep frequently requesting images in local cache like an LRU cache to decrease response time

What I've tried:

  1. I wanted to use buffer_body instead of file_body but some difficulties occurred with respond part, so I discarded this idea.
  2. I tried to decode an png image to std::string, I thought this way I could keep it in std::unordered_map easier, but again problems arose with response part of the code

Here is the response part:

http::response<http::file_body> res {                  
    std::piecewise_construct,                          
    std::make_tuple(std::move(body)),                  
    std::make_tuple(http::status::ok, req.version()) };
res.set(http::field::content_type, "image/png");       
res.content_length(size);                              
res.keep_alive(req.keep_alive());                      
                                                       
return send(std::move(res));

If doing it by encoding and decoding the image as string is ok I provide below the code where I read it to a string:

std::unordered_map<std::string, std::string> cache;

std::string load_file_contents(const std::string& filepath)
{
    static const size_t MAX_LOAD_DATA_SIZE = 1024 * 1024 * 8 ; // 8 Mbytes.
    std::string result;
    static const size_t BUFF_SIZE = 8192; // 8 Kbytes
    char buf[BUFF_SIZE];
    FILE* file = fopen( filepath.c_str(), "rb" ) ;

    if ( file != NULL )
    {
        size_t n;
        while( result.size() < MAX_LOAD_DATA_SIZE )
        {
            n = fread( buf, sizeof(char), BUFF_SIZE, file);
            if (n == 0)
                break;

            result.append(buf, n);
        }
        fclose(file);

    }
    return result;
}

template<class Body, class Allocator, class Send>
void handle_request(
    beast::string_view doc_root,
    http::request<Body, http::basic_fields<Allocator>>&& req,
    Send&& send)
{
.... // skipping this part not to paste all the code

    if(cache.find(path) == cache.end())
    {
        // if not in cache
        std::ifstream image(path.c_str(), std::ios::binary);
        // not in the cache and could open, so get it and decode it as a binary file
        cache.emplace(path, load_file_contents(path));
    }
.... // repsonse part (provided above) response should take from cache
}

ANY HELP WILL BE APPRECIATED! THANK YOU!


Solution

  • Sometimes there is no need to cache these files, for example, in my case changing file_body to vector_body or string_body were enough to speed up respond time almost twice