> In a multi-threaded application I need to keep track of request-counts
> for various "users". That is, when a user makes a request to my
[quoted text clipped - 15 lines]
>
> Any ideas to how I can implement a counter for user requests?
Rather than *worry* about locking the entire hashtable badly affecting
performance, *measure* it. You only need to lock for the amount of time
it takes to fetch the entry and update it.
Unless you are processing hundreds of thousands of requests per second,
I doubt it will actually affect performance that badly.

Signature
Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
World class .NET training in the UK: http://iterativetraining.co.uk
> I don't want to lock the entire Hashtable, because I am worried that
> will badly affect performance - as if several different users are
> calling simultaneously then they will have to wait for each other.
They'd only need to be synchronized while logging that a request happened -
not for the actual duration of the request. In most cases I would imagine
that this won't create a bottleneck (compared to everything else going on),
so until profiling *shows* that you have a problem, I'd use synchronized
access to a dictionary<something, int> where something relates to your user
id.
Something like (off the cuff code):
static class UserCounters
{
private static readonly Dictionary<string, int> counter =
new
Dictionary<string,int>(StringComparer.InvariantCultureIgnoreCase);
public static void LogAccess(string cn)
{
lock (counter)
{
int value;
if (counter.TryGetValue(cn, out value))
{
counter[cn] = value + 1;
}
else
{
counter.Add(cn, 1);
}
}
}
public static KeyValuePair<string, int>[] Dump(bool reset)
{
lock (counter)
{
KeyValuePair<string, int>[] data = new KeyValuePair<string,
int>[counter.Count];
int index = 0;
foreach (KeyValuePair<string, int> pair in counter)
{
data[index++] = pair;
}
if (reset)
{
counter.Clear();
}
return data;
}
}
}
Peter - 25 Mar 2008 13:42 GMT
> They'd only need to be synchronized while logging that a request
> happened - not for the actual duration of the request.
> public static KeyValuePair<string, int>[] Dump(bool reset)
> {
[quoted text clipped - 13 lines]
> }
> }
OK, thanks for the answer (and to Jon), and for the code - which is
similar to what I had.
It touches on another problem though, because in my system I also need
to store data besides the simple int count. So I made a simple data
object to hold all the user-request-count data I needed, but soon
discovered that with a method like your Dump, the client receives a
data object which it could then alter - upsetting the values stored in
the hashtable.
Is the way to avoid this to return data-objects which only have getters
(no setters) - and/or to actually return copies of the real
data-objects from the hashtable?
/Peter
Lasse Vågsæther Karlsen - 25 Mar 2008 14:33 GMT
>> They'd only need to be synchronized while logging that a request
>> happened - not for the actual duration of the request.
[quoted text clipped - 32 lines]
>
> /Peter
What exactly is in this "counter" of yours?
If you want precise and helpful answers, you need to give precise and
helpful information as well. A simple counter can be done like the other
posts here have indicated, but something more advanced might need
something more advanced.
Do you need realtime up to date statistics about something? Or do you
just need to know at some later date? If so, perhaps a simple log could
do that wouldn't necessarily need to interfere with previous data at
all, and then some sort of program that tallied up the results when
needed...

Signature
Lasse Vågsæther Karlsen
mailto:lasse@vkarlsen.no
http://presentationmode.blogspot.com/
PGP KeyID: 0xBCDEA2E3