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