1

Well, I think I should have asked this question, before starting development my Android application, but I believe with your help, guys, I can still make things right with my project.

In my project I'm going to look for shortest paths in a graph. I'm going to store nodes and edges in my SQLite database. However, when it comes to looking for shortest path, I'm going to fetch all entries from database and map them to objects shown below.

public class NodeBean {
    private int nodeId;
    private String nodeName;
    private int nodeType;
    private int scannedTotal;
    private int scannedSinceLastSync;
    // + getters and setters
}

public class ConnectionBean{
    private int connectionId;
    private BigDecimal connectionWeight;
    private NodeBean firstNode;
    private NodeBean secondNode;
    private boolean someFlag;
    // + getters and setters
}

As I have the records mapped to objects, I'm going to store these two kinds of objects in collections (HashMap<Integer, NodeBean> for NodeBean, ArrayList<ConnectionBean> or an array for ConnectionBean). Next, I'm going to use these to populate a proper graph using JGraphT and look for shortest path.
Different approach, which could spare me some RAM (as I would create only one collection instead of two) is "fetch all results from database and during mapping them to objects, put them instantly into graph". This way I wouldn't have to store ConnectionBean in a Collection - as I don't really need it. Still, I have to deal with big collection of NodeBeans.

I tried to estimate how much memory I would use. If my calculations are corrected, my NodeBean would use about 25B (4 * 32 bits (4 int fields) + ~72-80 bits (String field containing about 10-15 characters, formula taken from here) and my ConnectionBean would use about 75-80B (4B for int + ~40B for BigDecimal (pattern from here) + 2 * 64 bits (for NodeBean references) + 64 bits (for boolean - taken from here) implying I have 64-bit VM).

In the beginning, when I started development I though I would have about 400-500 NodeBeans and about 750-1000 ConnectionBeans. This way I would not use even 100kB (25B * 500 + 80B * 1000 = 92.5kB) of memory (assuming my calculations are fine). However, my application should be scalable so I assume I can have even 10k Nodes and 20k Connections - but even in case of that quite big graph, that's pretty unlike to occur - that's not even 2MB!


So, now when we know what my problem is, here are my questions:

  1. (Most important) How bad habit is to map ALL rows from database to the objects and keep it in RAM? I feel in my gut that it's not good, but on the other hand - probably my UI would use more RAM than these objects.
  2. Are my calculations more or less accurate? Do my object take as much memory as all it fields or am I missing something here?
  3. Let's say I have this a thousand of objects. They use some memory. I put them in a Map. Do I use about two times the memory I used before or am I just storing 1000 * 32/64-bit references in a Map?
Community
  • 1
  • 1
spoko
  • 783
  • 1
  • 10
  • 24

1 Answers1

0
  1. As you have already figured out, it's a problem if doing so will use more memory than you wish. Not so bad if the upper limit of the number of items is controlled, and you know that doing this will not crash the app.

  2. It's difficult to calculate the amount of memory used. The best thing to do is to try it, and see how it actually behaves.

  3. Storing items in a map does not duplicated their memory footprint. However, it is more than just a reference - you're adding the overhead of a Map.Entry for each one. Again, try it out, and profile it to see how it behaves. Try the worst case.

GreyBeardedGeek
  • 29,460
  • 2
  • 47
  • 67