Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cache (large and static) data with class variables

First, let me explain the situation, I've got following:

A "Node" Class with following attributes:

  • node_id (unique)
  • node_name (unique)

And a "NodeConnection" Class with following attributes:

  • node_from
  • node_to

We'll have around 1 to 3 million nodes and something around 3 to 10 million NodeConnections.

After the nodes and connections are imported once, they won't change.

On each request to the Rails-Application, we'll have to look up around 10 to 100 node_ids by possible node_names. And we have to lookup a few hundred to a few thousands node_connections.

We currently prototyped this without any caching (so, a LOT of database-queries) and response times were horrible (like 2 Minutes). So we switched over to cache the nodes and connections via memcached.

Got a performance boost, but still lacking of performance. (Because we're calling Cache.read for every NodeConnection, that's a few thousand calls per request)

Now, we tried caching via Classvariable and got a huge performance boost. (Response times within a few hundred ms)

# Pseudocode below
class Node
  def nodes
    @@nodes ||= get_nodes
  end
  def node_connections
    @@node_connections ||= get_node_connections
  end
end

So, I'd like to ask about Pros and Cons of this solution.

Cons I've got yet:

  • Every Rails instance has to build up its own cache (it's own ClassVariables) -> higher total memory usage
  • Initializing the cache is time consuming (1-3 minutes), so we can't do this within a request

Any other solutions out there to cache large (>100MB) and static (data won't change during applications lifetime) data efficiently, so all rails instances within the same machine can access this cache very fast (!)?

like image 681
Deradon Avatar asked Sep 10 '26 15:09

Deradon


1 Answers

It sounds like a very specific situation, but in order to avoid the need for a per-process in-memory cache (i.e. your class variables) to naturally warm up, I'd be investigating the feasibility of scripting the warm-up process and running it from inside an initializer... your app may take longer to start up, but your users would not have to wait.

EDIT | Note that if you were using something like Unicorn, which supports pre-loading application code before forking worker processes, you could minimize the impact of such initialization.

like image 114
d11wtq Avatar answered Sep 12 '26 04:09

d11wtq



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!