views:

736

answers:

4

I have tried to implement different caching-implementations in a classic ASP site in order to offload the database during heavy traffic.

My approach was this:

Create a global HashTable object in global.asa where I later on store jscript-objects within

<object id="SIZE_LIST" progid="System.Collections.HashTable" runat="Server" scope="Application"></object>

This gives me a global HashTable-object that I at certain time-intervals replace the content of the HashTable. The size will only vary slightly, but I however do .Remove() and .Add() all objects, each time.

This works very well, besides from the fact that after a certain time, the memoryallocation of the app gets to high, giving irrational behaviour of the sessions. It will "forget" sessions, but not invoke OnSessionStart() in global.asa. Therefor, leaving visitors with an empty Session-collection.

Can I somehow improve the memory-reallocation-process? Is there any better approach for object-caching?

I have tried using plain textfiles with json-serialized data, but the deserialization of that is to much overhead. I thought about binary-serialization, but I'm not sure if it's even possible in classic ASP.

+1  A: 

What are the reasons for using a .NET HashTable over a regular "Scripting.Dictionary"?

When you do classic ASP, why would a normal COM object not be enough?

Tomalak
afaik both Scripting.Dictionary and IISSample.LookupTable are bound to the fact that they can only store primitive datatypes (strings and numbers). That would leave me with the need for serialization once again. of course, I wouldn't need to deserialize everything. LookupTable also doesn't support dynamic changes (and I know we've had problems with Scripting.Dictionary, but I can't say for sure)
jishi
I guess this was the issue: http://www.4guysfromrolla.com/aspfaqs/ShowFAQ.asp?FAQID=129
jishi
Scripting.Dictionary can store any value you like. Object references *and* primitive values. Only limitation: Keys must be strings.
Tomalak
Also note that the linked MS KB article "Scripting.Dictionary Object Fails in ASP Application Scope" does not at all apply to you.
Tomalak
And I can store it in Application? I'll check it out.
jishi
Sure. As long as you check for threading issues and thoroughly call `Application.Lock` to protect write access this should be no problem.
Tomalak
A: 

don't try to reinvent the wheel. Use memcache. It's free and easy to setup. As a bonus is has ttl(time to live) and works beyond server boundaries

Toad
From what I have learned, memcached requires atleast 2 individual servers. Thats a pretty big setup for a simple task like this. It is also network-based, meaning more overhead than storing it in RAM. Of course, as you say, much more scalable and if I create 1 setup I can use it for several sites, but I'm not sure if I have that need in the near future, not even in the long run.
jishi
memcache can run on the same machine. You're right there is a bit of overhead. But it's small compared to the gain of not having to do your queries everytime again.
Toad
A: 

This is just a guess but it could be that because you are stashing JScript objects into a .net Hash that you could still be keeping a reference to the object so Garbage collection never gets a chance to do its job properly.

I've used Application with JSON strings before, works a treat and eval in lightening fast at re-hydrating the data.

If you are worried about your data getting out of date you could use a XMLHTTPRequest server side (which is suprisingly fast) to call a aspx page which will do the search and return a JSON string for you. The aspx page can handle caching for you with .net's fantastic caching and can even zip up the JSON string using SharpZipLib before stashing it in cache to reduce memory foot print even more. Which is also a great trick for stashing XML files in cache too (600K down to 25K in 0.0016 of a second!)

We've used all the above on projects before, not perfect but a good enough solution based on the limitations and legacy code at the time. And they are all very very fast (ok not by .net standards but for scripting its real fast).

Pete Duncanson
Well, we had the same memory-issue when trying to store json-strings in Application. even though the eval is pretty fast, it's also pretty intense on the CPU. And we also got this strange behavior with the SessionStart thing. It all depended on the amount of data we stored in Application in that case, so it doesn't seem bulletproof, or we do something wrong. When w3wp.exe starts using up around 300MB we start to get this intermittent issue for some visitors.
jishi
Intensive on the CPU is ok if its just the odd spike here and there it not then yes you are doing too much work and you will have to revisit this solution. Could be that you are trying to do just too much with your Caching. Do you really need to cache everything? If you do then you might have to go the route of building custom functions to rebuild your objects from Application rather than evaling them (see http://stackoverflow.com/questions/1196525/classic-asp-store-objects-in-the-session-object/1206639#1206639). I know you said you did not want to do that but you options are limited now
Pete Duncanson
A: 

I would opt for a more low tech approach and store each object separately (with string keys) in the Application object. That way you don't just have a single huge object from the scripting engine's point of view. Do you think that would help at all?

mike nelson
tried it, and messing with Application wasn't such a great idea. Writing/reading from Application continuosly tended to use up all memory and trouble with session trashing.
jishi