I have to create a mechanism to store and read preferences (controls default values and settings) per user. I have a problem related to network traffic, as the database can be accessed over the internet and the application server sometimes is connected to a poor 512Kbps internet connection.
My application can have around 50 simultaneous users and each page/form can have up to 50 items (preferences). The amount of pages is around 80.
So, considering a performance perspective, which should I choose to decrease network traffic? Session or cache?
UPDATE
I've created two sample pages, one using cache and another using session.
Load test 90 users
Stored content 1000 elements 20 characters on each element's value
Here are the results from each test case:
MemoryCache 330,725,246 total bytes allocated
Functions Allocating Most Memory
Name Bytes % System.Runtime.Caching.MemoryCache.Set(string,object,class System.Runtime.Caching.CacheItemPolicy,string) 34,74 System.Web.UI.Page.ProcessRequest(class System.Web.HttpContext) 18,39 System.String.Concat(string,string) 12,65 System.String.Join(string,string[]) 5,31 System.Collections.Generic.Dictionary`2.Add(!0,!1) 4,42
Source code:
protected void Page_Load(object sender, EventArgs e)
{
outputPanel.Text = String.Join(System.Environment.NewLine, ReadEverything().ToArray());
}
private IEnumerable<String> ReadEverything()
{
for (int i = 0; i < 1000; i++)
{
yield return ReadFromCache(i);
}
}
private string ReadFromCache(int p)
{
String saida = String.Empty;
ObjectCache cache = MemoryCache.Default;
Dictionary<int, string> cachedItems = cache["user" + Session.SessionID] as Dictionary<int, string>;
if (cachedItems == null)
{
cachedItems = new Dictionary<int, string>();
}
if (!cachedItems.TryGetValue(p, out saida))
{
saida = Util.RandomString(20);
cachedItems.Add(p, saida);
CacheItemPolicy policy = new CacheItemPolicy();
policy.AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(30);
cache.Set("user" + Session.SessionID, cachedItems, policy);
}
return saida;
}
Session 111,625,747 total bytes allocated
Functions Allocating Most Memory
Name Bytes % System.Web.UI.Page.ProcessRequest(class System.Web.HttpContext) 55,19 System.String.Join(string,string[]) 15,93 System.Collections.Generic.Dictionary`2.Add(!0,!1) 6,00 System.Text.StringBuilder.Append(char) 5,93 System.Linq.Enumerable.ToArray(class System.Collections.Generic.IEnumerable`1) 4,46
Source code:
protected void Page_Load(object sender, EventArgs e)
{
outputPanel.Text = String.Join(System.Environment.NewLine, ReadEverything().ToArray());
}
private IEnumerable<String> ReadEverything()
{
for (int i = 0; i < 1000; i++)
{
yield return ReadFromSession(i);
}
}
private string ReadFromSession(int p)
{
String saida = String.Empty;
Dictionary<int, string> cachedItems = Session["cachedItems"] as Dictionary<int, string>;
if (cachedItems == null)
{
cachedItems = new Dictionary<int, string>();
}
if (!cachedItems.TryGetValue(p, out saida))
{
saida = Util.RandomString(20);
cachedItems.Add(p, saida);
Session["cachedItems"] = cachedItems;
}
return saida;
}
I forgot to mention that I'm creating a solution to work with ASP.Net and WPF projects, however, if the Session is far better than the MemoryCache option, I can have different solutions for each platform.
both are really the same, they are in memory... If you are using DB session and you have a poor connection then you should use cache if present, load from DB if not and then cache.