Multiple user problem -- C# MapScript Web Application (Is mapserver thread safe?)

Benedikt Rothe umn-ms at HYDROTEC.DE
Wed Aug 9 02:47:56 EDT 2006


Tamas, Umberto

Umberto wrote about good experience with Mapserver-Multithreading in Java.
This is not my experience. In our "Mapserver-Servlet" we had to use a 
global synchronizing around
mapserver-calls  (i.e. disabling multithreading) to avoid crashes. 

Benedikt

UMN MapServer Developers List <MAPSERVER-DEV at LISTS.UMN.EDU> schrieb am 
08.08.2006 17:42:22:

> Tamas,
> I have a few applications built with Java mapscript (shape and raster,
> so not much really) and they seem to work very well. Years ago (when
> mapscript was in its infancy) I performed massive load testing and at
> that time I did not experience problems at all.
> 
> More recently I have been running the thread test in mapscript/java
> against both the standard test map and a map built against oracle
> without any problem. Performance was not taken into account, only
> correctness.
> 
> Umberto
> 
> On 8/8/06, Tamas Szekeres <szekerest at gmail.com> wrote:
> > Steve,
> >
> > As digging into the problem increasingly i am getting more and more
> > disappointed. By now i am not sure whether mapscript is safe for
> > multithreading at all (even if thread support is switched on).
> > For example the most essential gd library uses a number of static
> > variables without using any protection when accessing them. The proj
> > library also has a number of static variables an we have protection
> > only against pj_init in the mapserver code. For example i am
> > considering pj_transform is unsafe  as well (as using static pj_errno
> > for example).
> >
> > The problems existing in the libraries cause the same issues as if
> > they were in the mapserver code directly. Each of the dll is loaded
> > into the process "globally" so any static variable becomes processwide
> > global variable.
> > Has anyone reviewed the libraries with this regard?
> >
> > I have collected the potential problems of the two libraries mentioned
> > before. Some of the variables might be const static not causing such
> > problems, apologies for those.
> >
> > In the gd library:
> >
> > gd-2.0.33\gd_gif_in.c(12):static int verbose_set = 0;
> > gd-2.0.33\gd_gif_in.c(13):static int verbose;
> > gd-2.0.33\gd_gif_in.c(68):} Gif89 = { -1, -1, -1, 0 };
> > gd-2.0.33\gd_gif_in.c(244):       static unsigned char     buf[256];
> > gd-2.0.33\gd_gif_in.c(308):       static unsigned char    buf[280];
> > gd-2.0.33\gd_gif_in.c(309):       static int              curbit,
> > lastbit, done, last_byte;
> > gd-2.0.33\gd_gif_in.c(360):       static int      fresh = FALSE;
> > gd-2.0.33\gd_gif_in.c(362):       static int      code_size, 
set_code_size;
> > gd-2.0.33\gd_gif_in.c(363):       static int      max_code, 
max_code_size;
> > gd-2.0.33\gd_gif_in.c(364):       static int      firstcode, oldcode;
> > gd-2.0.33\gd_gif_in.c(365):       static int      clear_code, 
end_code;
> > gd-2.0.33\gd_gif_in.c(366):       static int      table[2][(1<< 
MAX_LWZ_BITS)];
> > gd-2.0.33\gd_gif_in.c(367):       static int      stack[STACK_SIZE], 
*sp;
> > gd-2.0.33\gd_png.c(50):static jmpbuf_wrapper gdPngJmpbufStruct;
> > gd-2.0.33\gdft.c(31):static int fontConfigFlag = 0;
> > gd-2.0.33\gdft.c(777):static gdCache_head_t *fontCache;
> > gd-2.0.33\gdft.c(778):static FT_Library library;
> > gd-2.0.33\gdkanji.c(120):  static int whatcode = ASCII;
> > gd-2.0.33\gdkanji.c(499):  static unsigned char tmp[BUFSIZ];
> > gd-2.0.33\gdkanji.c(595):  static unsigned char tmp_dest[BUFSIZ];
> >
> > In the proj library:
> >
> > proj-4.4.9\src\biveval.c(7):    static projUV
> > proj-4.4.9\src\cs2cs.c(69):static projPJ   fromProj, toProj;
> > proj-4.4.9\src\cs2cs.c(71):static int
> > proj-4.4.9\src\cs2cs.c(76):     static char
> > proj-4.4.9\src\cs2cs.c(83):static struct FACTORS facs;
> > proj-4.4.9\src\cs2cs.c(84):static double (*informat)(const char *,
> > proj-4.4.9\src\geod.c(15):      static int
> > proj-4.4.9\src\geod.c(20):      static char
> > proj-4.4.9\src\geod.c(129):static char *pargv[MAX_PARGS];
> > proj-4.4.9\src\geod.c(130):static int   pargc = 0;
> > proj-4.4.9\src\geod.c(135):     static int eargc = 0, c;
> > proj-4.4.9\src\geod_for.c(7):   static double
> > proj-4.4.9\src\geod_for.c(9):   static int
> > proj-4.4.9\src\nad2nad.c(16):   static int
> > proj-4.4.9\src\nad2nad.c(19):   static char
> > proj-4.4.9\src\nad2nad.c(54):} input = {
> > proj-4.4.9\src\nad2nad.c(58):}, output = {
> > proj-4.4.9\src\pj_apply_gridshift.c(79):    static int debug_count = 
0;
> > proj-4.4.9\src\pj_gridinfo.c(66):static int  byte_order_test = 1;
> > proj-4.4.9\src\pj_gridlist.c(50):static PJ_GRIDINFO *grid_list = NULL;
> > proj-4.4.9\src\pj_gridlist.c(54):static int last_nadgrids_max = 0;
> > proj-4.4.9\src\pj_gridlist.c(55):static int last_nadgrids_count = 0;
> > proj-4.4.9\src\pj_gridlist.c(56):static PJ_GRIDINFO 
**last_nadgrids_list = NULL;
> > proj-4.4.9\src\pj_gridlist.c(57):static char         *last_nadgrids = 
NULL;
> > proj-4.4.9\src\pj_init.c(71):static paralist *start;
> > proj-4.4.9\src\PJ_mod_ster.c(102):      static COMPLEX /* Miller 
Oblated
> > Stereographic */
> > proj-4.4.9\src\PJ_mod_ster.c(116):      static COMPLEX /* Lee Oblated
> > Stereographic */
> > proj-4.4.9\src\PJ_mod_ster.c(130):      static COMPLEX /* 48 United 
States */
> > proj-4.4.9\src\PJ_mod_ster.c(147):      static COMPLEX
> > proj-4.4.9\src\PJ_mod_ster.c(177):      static COMPLEX
> > proj-4.4.9\src\PJ_nzmg.c(48):   static COMPLEX
> > proj-4.4.9\src\PJ_nzmg.c(56):   static double
> > proj-4.4.9\src\pj_open_lib.c(51):static int path_count = 0;
> > proj-4.4.9\src\pj_open_lib.c(52):static char **search_path = NULL;
> > proj-4.4.9\src\pj_open_lib.c(53):static char * proj_lib_name =
> > proj-4.4.9\src\PJ_robin.c(10):static struct COEFS {
> > proj-4.4.9\src\pj_strerrno.c(61):    static char note[50];
> > proj-4.4.9\src\proj.c(26):      static PJ
> > proj-4.4.9\src\proj.c(28):      static projUV
> > proj-4.4.9\src\proj.c(30):      static int
> > proj-4.4.9\src\proj.c(43):      static char
> > proj-4.4.9\src\proj.c(49):      static struct FACTORS
> > proj-4.4.9\src\proj.c(51):      static double
> > proj-4.4.9\src\rtodms.c(13):    static double
> > proj-4.4.9\src\rtodms.c(17):    static char
> > proj-4.4.9\src\rtodms.c(19):    static int
> > proj-4.4.9\src\pj_datums.c(73):C_NAMESPACE struct PJ_DATUMS 
pj_datums[] = {
> > proj-4.4.9\src\pj_datums.c(98):C_NAMESPACE struct PJ_PRIME_MERIDIANS
> > pj_prime_meridians[] = {
> > proj-4.4.9\src\pj_ellps.c(8):C_NAMESPACE struct PJ_ELLPS
> > proj-4.4.9\src\pj_errno.c(8):C_NAMESPACE int pj_errno = 0;
> > proj-4.4.9\src\PJ_goode.c(10):  C_NAMESPACE PJ
> > proj-4.4.9\src\pj_units.c(10):C_NAMESPACE struct PJ_UNITS
> >
> >
> > I wonder if mapscript can safely be used in a real multithreaded
> > environment regardless of the performance problems. Are there any
> > further experiences about this issue? Which architecture can be used?
> > I cannot step beyond the "one process handles one request at a time"
> > model.
> >
> >
> > Best Regards,
> >
> > Tamas
> >
> >
> > 2006/8/8, Steve Lime <Steve.Lime at dnr.state.mn.us>:
> > > Tamas: What happened to the talk of thread specific globals that
> > > was started on mapserver-dev awhile back? Now's the time to move
> > > on such things...
> > >
> > > Steve
> > >
> > > >>> Tamas Szekeres <szekerest at GMAIL.COM> 8/7/2006 3:22:16 PM >>>
> > > Hi,
> > >
> > > Many of the mapserver components use globally allocated data so
> > > multiple threads within the executable (inside libmap.dll in this
> > > case) share the same data.
> > > Moreover the .dll is loaded into the host application (eg.
> > > aspnet_wp.exe or w3wp.exe) and the global variable will be shared
> > > among the threads within the overall worker process.
> > > The process may host multiple appdomains so the variables is shared
> > > among multiple web applications in this case. Lastly, the ASP
> > > application model implies the various requests are handled by 
multiple
> > > threads taken out of a pool of threads.
> > >
> > > It seems terrible compared to the architecture of a windows
> > > application, isn't it?
> > >
> > > If mapserver is compiled with thread support the global data in some
> > > of the components are protected by locks to provide synchronized
> > > access by multiple threads. The access will take place sequentially 
so
> > > the threads will wait for each
> > > other. For example if you are creating mapObj from a .map file
> > > multiple requests will wait for each other when parsing the file. 
This
> > > kind of thread interaction may be slightly decreased if the 
protected
> > > critical sections could be made smaller.
> > >
> > > The issue mentioned previously makes some of us frustrated.
> > > Maintaining locks kills the performance of the application, it would
> > > be preferable to avoid the global data at all when possible.
> > > Unfortunately to achieve this level much of the code should be
> > > reconsidered ( a better sort of collaboration should be made between
> > > the developers ).
> > >
> > > I consider this problem is critical and will manifest itself more 
and
> > > more obviously. I wonder the other mapscript languages are living
> > > happily without it ;-)
> > >
> > > Getting back to your question this time i would prefer establishing
> > > the mapping functionality in the middleware if possible. The drawing
> > > request should be queued and a pool of multiple processes should be
> > > spawned to handle the requests. The result may be dispatched back to
> > > the client using HTTP. The MONO XSP implementation may also help to
> > > establish the required functionality.
> > >
> > > Best Regards,
> > >
> > >
> > > Tamas Szekeres
> > >
> > >
> > >
> > >
> > > 2006/8/7, Zhonghai Wang <zhonghaiw at gmail.com>:
> > > >
> > > > Hi All,
> > > >
> > > > I've developed a windows application with the C# MapScript, and 
this
> > > > application works well with all the common mapping functions. I am
> > > very
> > > > happy with the performance of MapServer. So I am now trying to
> > > migrate the
> > > > windows application to  a web application, here I have some doubts
> > > with the
> > > > migration:
> > > >
> > > > 1. for the windows application I use a singelton class to return 
the
> > > mapobj
> > > > for all the mapping API --  I've programmed a mapping class for
> > > mapping
> > > > functionalities, and this works well to store all the changes of a
> > > mapobj
> > > > during the mapping process. But if I migrate the mapping class to
> > > web
> > > > application, this singelton class should not be used, since there 
may
> > > be
> > > > hundred users, who are accessing MapServer at the same time. I am
> > > just
> > > > wondering how to solve this problem in MapServer?
> > > >
> > > > In MapXtreme, this problem is solved with the use of MapXBroker,
> > > which is a
> > > > shared pool of MapX objects, does MapServer has any similar
> > > component?
> > > >
> > > > 2. Thread-Safety, I know this is not a new question, but it's
> > > important. In
> > > > the .NET application, how to solve this problem? use thread lock? 
(I
> > > am
> > > > programming with VB.NET)
> > > >
> > > > thanks for any information about this topic.
> > > >
> > > >
> > > > zhonghai
> > >
> >
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.osgeo.org/pipermail/mapserver-dev/attachments/20060809/87d8eff2/attachment.html


More information about the mapserver-dev mailing list