Re: Thread-safe Collection



Thanks for all this Olaf.

You're right about the Application object. I hadn't even considered that
because all the Microsoft documentation is adamant that it should not be
used for storing STA objects because of cross-thread issues, and the
supposed serious impact on the performance of the web server.

In my most important case, the dictionary is a global read-only cache.
Obviously it would have to be populated by one of the threads during
startup, but after that it would only be supporting multiple readers. Hence,
it would still need read-locks and write-locks to be safe but the write-lock
contention would be almost non-existent.

Ideally, I wanted the dictionary items in a common memory store (to avoid
the VM size getting multiplied per thread), but still allow multiple
concurrent readers for maximum performance

I'll investigate your suggestions as soon as I can

Tony Proctor

"Schmidt" <sss@xxxxxxxxx> wrote in message
news:%23MnHBDt9HHA.5160@xxxxxxxxxxxxxxxxxxxxxxx

"Tony Proctor" <tony_proctor@xxxxxxxxxxxxxxxxxxxxxxxxxxxxx> schrieb im
Newsbeitrag news:udOcLNi9HHA.5404@xxxxxxxxxxxxxxxxxxxxxxx

I thought about this a little more Olaf.
You cannot guarantee the performance of these objects
since it depends to some extent on how their
memory is spread out, and how you access it.
What do you mean with "these Objects".
If you pin a singleton somewhere, then this singleton-
class implements only one (private) Collection internally.
And the marshaled performance I've measured is
of course only related to access-attempts to the
*interface* of this singleton-object.
The additional time needed for accessing the internal
dictionary-based Cache-Object would have to be
respected/added of course - but these "extra-costs" would
you see even in an unmarshaled approach, wich uses
CriticalSections instead of the builtin "serialized access to
a shared resource", wich OLE-Marshalling offers "for free".

A different story would be, if your shared resource is more
static regarding its content and should allow parallel reading
from multiple STAs - but that's what Databases are built for.
If you want to have fast parallel reads from multiple STAs,
and secure, serialized writes you can use e.g. SQLite, wich
has low memory-footprint and offers optimized search-strategies
on indexed Data and even full-text-table-searches.

In my thinking about a fast, singleton-internal Dictionary-Object
I would lock even the Read-Direction for security-reasons,
because a parallel Adding, whilst another STA reads Data
could cause inpredictable results.

You would have to decide/measure, if a fast, but serialized
Dictionary-Access performs better, than access against
a DataBase-Connection, wich could process Read-Requests
in parallel from multiple STAs, but has somewhat more
overhead compared with a "Singleton-Dictionary".

Performance isn't bad using
only hashing (up to a limit) but indexing is very bad.
You could use e.g. my much (regarding indexed access)
faster Sorted-Dictionary implementation as the private
Object inside your Singleton-Class.

Also, the type of singleton I would have to use would
have to be process-specific, not machine-wide, and
not specific only to the class being instantiated.
You mean, the shared singleton-object would have to
be hosted inside the IIS-Process. IIRC you can "pin"
such an singleton-object using ASP in the global
Application-Cache:
Application.Lock
Set Application("YourKey") = CreateObject("My.SingletonCache")
Application.UnLock

or better yet in
Application_OnStart of the Global.asa
Cleanup/Shutdown then in:
Application_OnEnd

retrieving the marshaled Singleton:
Set MySingletonCache = Application("YourKey")

Since "transactions" only work on Call-Basis with
Ole-Marshalling you should take that into respect
and avoid multiple interface-calls.
E.g. something like this should be avoided:
If Not MySingletonCache.EntryExists(Key) Then
MySingletonCache.AddEntry Key, Entry
End If
Or even worse: For Each-Enumerations...
All those multiple calls have to be encapsulated internally.

Instead you will have to handle it in one single call:
MySingletonCache.AddEntryIfNotExists Key, Entry
Only this way you can be sure, that the Marshaller
blocks other STAs - meaning: you have Transaction-safety -
but only at "Single-Call-Level".

With a normal VB project you'd do this via static data in a
Module, but there is no shared data in a multithreaded VB
context.
You can share memory relative easy between threaded
STAs in VB using SafeArray-Pointers.
Of course you have to regulate the access to such shared
memory-Resources with your own Locking-mechanisms
using CriticalSections then.
If you want, I can write an example for you, wich shares
a SortedDictionary-Instance between multiple STAs
in a standard VB-Exe, but regarding your IIS-host I'd
recommend the *marshaled* Singleton-approach
(or alternatively a lightweight DB-Engine) anyway.

Olaf




.



Relevant Pages

  • Re: Global variables
    ... > (generally from external file), that need to be shared in the application. ... I think using Singleton may be a different issue. ... the behavior doing the creating may be invoked multiple times. ... sending emails before I speculate on where to glue the SMTP server ...
    (comp.object)
  • Re: Utility classes?
    ... I don't want to duplicate code in multiple places. ... > (singleton) classes created to encapsulate related operations in one class. ...
    (comp.lang.cpp)
  • Re: Singleton Pattern
    ... one should /only/ use Singleton when the problem solution has multiple paths that could lead to violating the problem space referential integrity requirement in. ...
    (comp.object)
  • Re: Static Methods in DAO
    ... methods, or a single shared object (i.e. singleton), how can multiple ... code in a method at the exact same time if there is one shared object ...
    (comp.lang.java.programmer)