Showing posts with label Autodesk Infrastructure MapServer. Show all posts
Showing posts with label Autodesk Infrastructure MapServer. Show all posts

Friday, 4 August 2017

Uploading MapGuide package - Exception

Uploading MapGuide package - Exception

If you modify a MapGuide package make sure that you zip the correct files and folders afterwards.
I unzipped a MapGuide package, changed some values and zipped the folder but received the following error message when trying to upload the file:


Maestro error message:

value cannot be nul
Parametername: entry

System.ArgumentNullException:  value cannot be nul
Parametername: entry
   bei ICSharpCode.SharpZipLib.Zip.ZipFile.GetInputStream(ZipEntry entry)
   bei Maestro.Packaging.PackageBuilder.UploadPackageNonTransactional(String sourceFile, UploadPackageResult result) in C:\working\JenkinsCI\home\slave_win\jobs\Maestro trunk\workspace\Maestro.Packaging\PackageBuilder.cs:Zeile 217.
   
MapGuide error message:

   ERROR_MESSAGE:    An exception occurred in DWF component. File not found in archive
STACK_TRACE:    - MgLibraryRepositoryManager.LoadResourcePackage() line 183 file c:\working\build_area\mapguide\2.5.2\x64\mgdev\server\src\services\resource\LibraryRepositoryManager.cpp - MgResourcePackageLoader.Start() line 150 file c:\working\build_area\mapguide\2.5.2\x64\mgdev\server\src\services\resource\ResourcePackageLoader.cpp - MgResourcePackageLoader.CreateByteReader() line 108 file c:\working\build_area\mapguide\2.5.2\x64\mgdev\server\src\services\resource\ResourcePackageLoader.cpp - MgZipFileReader.ExtractArchive() line 61 file c:\working\build_area\mapguide\2.5.2\x64\mgdev\server\src\services\resource\ZipFileReader.cpp


My mistake was to zip the top level folder - which I got when I unzipped the package. But you need to zip the content of the top level folder, not the top level folder itself. 

AIMS 2017

Thursday, 2 March 2017

MapGuide log file

It is good practice to monitor log files. Unfortunately MapGuide log files are not easy to read:
- StackTrace details take up more space then the message itself, it is difficult to see when an error message starts and ends
- certain messages might appear very often although there are not really indicating an issue (such as "Session expired" message).

Here is Python3 script which reads MapGuide logs files and gets rid of StackTrace details and also filters out uninteresting messages. It adds a line number so that you can find the message in the original log file quickly. It also creates a simple summary for messages and their frequency. As we have two MapGuide servers the script is configured to read two different log file folders.  

If you want to use it you need to configure:
- the path for the MapGuide log files
- the path for saving the shortened log file 
- error messages you want to exclude
- the number of most recent log files you want to process (such as the 3 most recent ones)

I haven't done much in Python yet - the script doesn't do much error handling and has other shortcomings as well.

Thats how the result might look like:

****************
**************** Logfile: //wsstadt529/logfiles/MapGuide\Error.log
****************


<start>
3   DATE_TIME 2017-03-02 / 01:50:19
4    Success: Server stopped.

<end>
<start>
DATE_TIME 2017-03-02 / 01:51:23
6    Success: Server started.

<end>
<start>
DATE_TIME 2017-03-02 / 07:27:12
444    Error: An exception occurred in FDO component.
445           Error occurred in Feature Source (Library://FS_BEAR/WT_PO_BW_B/Data/TopobaseDefault.FeatureSource): Zeichenfolge ist kein gültiger Filter.  (Cause: Zeichenfolge ist nicht korrekt formatiert. , Root Cause: Zeichenfolge ist nicht korrekt formatiert. )
446    
<end>

...

<start>
DATE_TIME 2017-03-02 / 13:35:34
953    Error: An exception occurred in FDO component.
954           Error occurred in Feature Source (Library://FS_BEAR/WT_PO_BW_B/Data/TopobaseDefault.FeatureSource): Zeichenfolge ist kein gültiger Filter.  (Cause: Zeichenfolge ist nicht korrekt formatiert. , Root Cause: Zeichenfolge ist nicht korrekt formatiert. )
955    
<end>

*********************************************
************* Summary ***********************
*********************************************

# 3 :: Error: Failed to stylize layer: ZIM_Anlageobjekte_DynaS_GeoRest_MBR
# 36 :: Error: Failed to stylize layer: ZH_Orthofoto2015
# 1 :: Success: Server started.
# 1 :: Success: Server stopped.
# 27 :: Error: An exception occurred in FDO component.

************* File(s) ***********************
File processed: //wsstadt529/logfiles/MapGuide\Error.log
# of messages:68
# of messages excluded: 51

Here is the script:



 import os  
 import sys  
 from collections import Counter  
   
   
 """ extract date and time from logfile line """  
 def extractdatetime(a_text_line):  
   #DateTime Format in MapGuide-LogFile:  
   #<2016-12-15T11:00:34> <2015-07-05T12:39:55>  
   date = a_text_line[1:11]  
   time = a_text_line[12:20]  
   return (date, time)  
   
 """ checks whether a certain error message should be ignored / excluded from further processing """  
 def isErrorMessagesToExclude(a_message):    
   for text_to_find in errormessage_to_exclude:  
     if text_to_find in a_message:  
       return True  
   return False  
   
 """ removes the StackTrace details from an error message """  
 def removeStackTrace(a_message):    
   pos = a_message.find('StackTrace:')  
   if pos > -1:  
     return a_message[0:pos]  
   else:  
     return a_message  
   
 """ saves file """  
 def saveFile(text, filename, mode):  
   f = open(filename, mode)  
   f.write(text)  
   f.close()  
   
   
 """ returns a sorted list of files for a given directory , sorted by date  
   see: http://stackoverflow.com/questions/4500564/directory-listing-based-on-time  
 """    
 def sorted_ls(path):  
   mtime = lambda f: os.stat(os.path.join(path, f)).st_mtime  
   result = list(sorted(os.listdir(path), key=mtime))    
   return result  
     
 """ keeps only MapGuide Logfiles and filters out all other files """  
 def filterLogfiles(files_in_dir):  
   filtered_files = []  
   for filename in files_in_dir:  
     if filename.endswith(".log") and filename.startswith("Error"):   
       filtered_files.append(filename)  
   return filtered_files  
         
 """ processes a single MG log file and simplifies content """  
 def processLogFile(logfile):    
   # counter for line number in log file  
   line_number = 0  
   # counter for number of messages processed  
   counter_messages = 0  
   # counter for messages we exclude from processing  
   counter_messages_ingnored = 0  
   # internal counter  
   count_opening_tag = 0    
   message = ''  
   message_part = ''  
   # encoding utf-8, ascii : returns error message while reading a certain character/bytes  
   with open(logfile, encoding='“latin-1') as a_file:  
     for a_line in a_file:                    
       line_number += 1        
       # all messages start with '<' and first line also contains date&time  
       if '<' in a_line:  
         count_opening_tag +=1  
         #get date and time  
         str_date, str_time = extractdatetime(a_line)  
         a_line = 'DATE_TIME ' + str_date + ' / ' + str_time + '\n'                  
       # we processing the first line of the current message  
       if count_opening_tag == 1:  
         # line number and date/time information in one new line  
         message_part += str(line_number) + '  ' + a_line          
       # we have reached the first line of the following message - now we need tp process the previous message       
       if count_opening_tag == 2:          
         #first we check whether the message can be ignored  
         if isErrorMessagesToExclude(message_part) is False:  
           # we remove the StackTrace details  
           message_part = removeStackTrace(message_part)            
           counter_messages += 1  
           # we wrap the message text in <start><end> tags  
           message += '\n<start>\n'  
           # we add the processed message to the result  
           message += message_part  
           message += '\n<end>'  
         else:  
           counter_messages_ingnored += 1  
         #as this is the first line of the "next" message already a_line contains the DATE_TIME for it  
         message_part = a_line  
         # reset counter - the current line is the first line of the next message  
         count_opening_tag = 1  
     # last line reached - last message block is not yet fully processed  
     # code from above is repeated here to close the processing of last message in logfile  
     if isErrorMessagesToExclude(message_part) is False:  
       message_part = removeStackTrace(message_part)                  
       message += '\n<start>\n'  
       message += message_part  
       message += '\n<end>'    
       counter_messages += 1  
     else:  
       counter_messages_ingnored += 1  
     temp = ["File processed: "+logfile, "# of messages:"+str(counter_messages), "# of messages excluded:\t "+str(counter_messages_ingnored) ]  
     summary_files.append(temp)      
     print("File processed: "+logfile)  
     print("# of messages:"+str(counter_messages))    
     print("# of messages excluded:\t "+str(counter_messages_ingnored))      
     return message  
   
 """ converts the newly created log file(s) summary into a list """  
 def convertToList(processedlogfile):  
   with open(processedlogfile, encoding='“latin-1') as a_file:  
     error_message = False  
     list_final = []  
     date_temp =''  
     time_temp = ''  
     error1_temp = ''  
     error2_temp = ''  
     line_counter = 0  
     for a_line in a_file:        
       line_counter += 1  
       if '<start>' in a_line:          
         line_counter = 1   
         error_message = True  
       if '<end>' in a_line:  
         error_message = False  
         line_counter = 0  
         list_temp = [date_temp, time_temp, error1_temp, error2_temp]  
         list_final.append(list_temp)  
       if error_message:           
         if line_counter == 2:  
           date_temp = a_line[10:20]  
           time_temp = a_line[23:]  
         if line_counter == 3:  
           error1_temp = a_line[5:].strip()  
         if line_counter == 4:  
           error2_temp = a_line[5:].strip()  
   return list_final  
   
 """ iterates over all relevant files and creates summary"""  
 def processLogfiles(logfile_dir, saveLogFileName, number_of_most_recent_files):     
   # create a new file for the results  
   saveFile('', saveLogFileName, 'w')    
   # get all files from directory with MapGuide logs  
   files_in_directory = sorted_ls(logfile_dir)    
   # filter out all non MapGuide log files  
   files_in_directory = filterLogfiles(files_in_directory)  
   # only process the most recent files   
   if(number_of_most_recent_files > 0):    
     index = ((number_of_most_recent_files ) * -1)  
     files_in_directory = files_in_directory[index:]    
   # interate over relevant log files  
   for filename in files_in_directory:      
       fn = os.path.join(logfile_dir, filename)  
       # process single log file  
       log_file_short = processLogFile(fn)  
       # create header      
       header = "\n\n****************"  
       header += "\n**************** Logfile: " + fn  
       header += "\n****************\n\n"        
       # write to file  
       saveFile(header, saveLogFileName, 'a')  
       saveFile(log_file_short, saveLogFileName, 'a')  
   # all files have been processed and relevant information has been written into one file          
   # now we want to get a summary of logged issues  
   resultList = convertToList(saveLogFileName)      
   '''  
   resultList is list of lists, lists have 4 items each   
   items 3 and 4 are equal to line 1 and 2 of a message    
   now we just count item 3 and get a Dictionary where frequency of message is key and message itself is value    
   '''    
   res = (Counter(mysublist[2] for mysublist in resultList))  
   text = "\n\n*********************************************"  
   text += "\n************* Summary ***********************"  
   text += "\n*********************************************\n\n"  
   for message, number in res.items():  
     text += "# " + str(number)+ "\t :: " + message +'\n'    
   # append summary    
   saveFile(text, saveLogFileName, 'a')    
   summ = "\n************* File(s) ***********************\n"  
   for alist in summary_files:  
     summ += "\n".join(alist)+"\n"  
   # append summary    
   saveFile(summ, saveLogFileName, 'a')    
   
     
 if __name__ == ("__main__"):  
     
     
   """ add any message you want to ignore when processing the log files"""  
   errormessage_to_exclude = [  
                 'Session has expired',   
                 'Resource was not found: Session:',   
                 'Die Sitzung (',   
                 'Error: Authentication failed'                  
                 ]    
   # number of most recent log files to process  
   # 0 - for all files to be processed  
   # can be overwritten when python script is called with parameter  
   number_most_recent_files = 3  
                   
   #if argument is provided we assume its a number  
   if len (sys.argv) == 2 :  
     number_most_recent_files = int(sys.argv[1])  
     
   # path to MapGuide error log directory       
   logfile_dir1 = '//wsstadt529/logfiles/MapGuide'    
   logfile_dir2 = '//wsstadt516/logfiles/MapGuide'    
   # file name for result - simplified log file:  
   saveLogFileName1 = 'c:/temp/aims_log_processed_529.txt'  
   saveLogFileName2 = 'c:/temp/aims_log_processed_516.txt'  
     
   # start processing  
   summary_files = []  
   processLogfiles(logfile_dir1, saveLogFileName1, number_most_recent_files)        
   summary_files = []  
   processLogfiles(logfile_dir2, saveLogFileName2, number_most_recent_files)      
     
   # open file(s) in Editor  
   os.startfile(saveLogFileName1)  
   os.startfile(saveLogFileName2)  
     

Tuesday, 14 February 2017

MapGuide Logfile - two warnings and what they mean


MapGuide log file contains the following warnings:

<2017-02-14T08:54:36> 4712 Ajax Viewer 10.99.66.2 Administrator
 Warning: An exception occurred in FDO component.
        Beim Abrufen eines Eigenschaftenwerts stimmte der Eigenschaftentyp nicht überein. 
 StackTrace:
  - MgStylizationUtil.ExceptionTrap() line 813 file StylizationEngine.cpp
  
the error message translates roughly as 
  "property value and property typ do not match"
  
The message was caused by the following filter definition:  

W_ID_TYPE  = 1 AND  (   W_ID_TYPE_IP  NULL    OR   NOT  W_ID_TYPE_IP  IN ( '1') )

W_ID_TYPE_IP is numeric but the value is given as string.  
  
 The second one:
  
<2017-02-14T12:19:44> 3444 10.99.66.65 Anonymous
 Warning: An exception occurred in FDO component.
        Die Kennung 'w_id_type' wurde nicht erkannt. 
 StackTrace:
  - MgStylizationUtil.ExceptionTrap() line 813 file StylizationEngine.cpp  
  
the error message translates roughly as 
  "property 'w_id_type' not found."

The message was caused by the following filter definition:  

w_id_type  IN ( 11)   AND NOT  ID_SITE_TYPE  IN (2007)

Property names as case-sensitive. The feature class does not contain 'w_id_type' but 'W_ID_TYPE'.


Unfortunately for both warnings no further information is given to where exactly the issues occur. I stumbled across the cause of the first warning by looking for the cause of the second warning. The second warning tells you exactly what the problem is - unfortunately I only realized that after I had spent several hours looking for it. 'w_id_type' is an attribute we use in many feature classes and 71 layers reference the attribute in filter expressions. It was somehow obvious that there is a problem in one of the layers but not in all of them as the warning did not appear all the time. Took me quite some time to figure out what was going on - despite the warning being clear about it.

AIMS 2017





  
  

Saturday, 30 July 2016

Why you should restart AIMS/MapGuide when testing ....

I noticed by chance that a few layers - which are all based on one Oracle view - were significantly slower in our production system but no performance issue occurred in our test environment. Whilst investigating the issue I made a few mistakes which made the whole process of finding and fixing the issue more time consuming than necessary. Here are the details:

After noticing the issue I asked my colleagues if they had any idea why this is and whether anything had changed recently. None of them had an explanation so I spent some time checking / testing:

- running performance reports in MapGuide/AIMS noticing that time spent on "Layer" is 20times slower in production
- comparing view definitions but only cursorily (looking at WHERE clause only) : mistake #1
- re-creating spatial index for base table : no change
- running 1-click maintenance in Map-Administrator : no change
- copy a layer definition from production to test environment : no change
- trying to load view into other applications to see whether the issue is related to application or to view but GeoRaptor couldn't add layer to map due to rowid issue, QGIS rejected view complaining that view didn't have a proper spatial index and TatukGIS Viewer basically saying something similar (first the message about the spatial index issue made me re-re-create the spatial index but testing further views in QGIS/TatukGISViewer I got the same messages for all other views as well).
- running a few spatial SQL queries in SQLDeveloper but there wasn't any significant difference between test and production : mistake # 2 (this result caused quite some confusion as I did not have an explanation, it did not fit and even contradicted other findings!)

After spending some time on running these tests a colleague came back to me and told me, that the view had changed recently but when he applied the change he didn't notice any performance issue whilst generating graphics in Map. The change was made by adding a subquery to the SELECT clause. He asked if the change should be removed but I replied that I will do some tests now taking the new information into account : mistake # 3.

As the change to the view definition had only been applied in the production system I applied the change in the test system as well - here mistake # 4 occurred. I then ran the MapGuide/AIMS performance report again but the performance had not decreased. Performance was good as before. Then I changed the data source of the Oracle user I was testing with and pointed it to our production database. When I ran the test again performance was slow. I stopped any further testing for the day and did something else.

At this point my theory was that the same query has different execution plans in Oracle (production and test) therefore different execution times due to different Oracle settings. What didn't really fit was that when I ran the spatial queries in SQLDeveloper I didn't see any significant difference in performance. But I didn't have anything else to test so finally I decided to replace the view definition in production with the previous view definition - basically removing the change which had been applied recently. I re-ran the performance report in MapGuide/AIMS and suddenly I got an error message:

Failed to stylize layer: DP_xxx
An exception occurred in FDO component.
ORA-00904: "G"."OWNER_OBJTYP": invalid identifier
...

Now I realised one of my mistakes. MapGuide/AIMS caches certain settings/definitions. I don't know how it works in detail but probably roughly like that:
- when AIMS/MapGuide starts it reads the Oracle schema and caches some information
- (SELECT) statements are being build based on the cached information and used against Oracle

For a view MapGuide/AIMS seems to read the view definition and then creates a SELECT statement which includes all columns of the view. 
If the view definition in Oracle changes and new columns are added to the view MapGuide can still run the SELECT statement against the new view definition - basically just ignoring all newly added columns.  But when columns have been removed from the view the SELECT statement still includes those columns and Oracle will response with ora-00904.

Mistake 4 - when I applied the change to view definition in the test system I did not restart MapGuide/AIMS. MapGuide was still using the SELECT statement which did not include the newly added column in the view. But exactly that new column had a negative impact on performance.
If I had restarted MapGuide/AIMS at this point in time I could have avoided further testing and head-scratching.

Mistake 3 - if I had listened to my colleague who offered to remove the change in production I might have noticed the cause of the problem earlier (because even without restarting MapGuide/AIMS we would have seen the Ora-00904 message in the log file).

Mistake 2 - my spatial query was simplified, the select clause included only "fid, geom". As it did not include the column which caused the performance issue there is really no surprise that performance in both production and test were nearly the same. Conclusion: always use (if possible) exactly the same (SELECT) statement as the application when you do testing!

Mistake 1 - I should have noticed the difference in view definitions myself just by copying the view definitions from production and test into an editor and then noticing the different numbers of lines....

So at the end a trivial issue but it took longer then necessary to get it fixed.

Why you should restart AIMS/MapGuide when testing ....

I noticed by chance that a few layers - which are all based on one Oracle view - were significantly slower in our production system but no performance issue occurred in our test environment. Whilst investigating the issue I made a few mistakes which made the whole process of finding and fixing the issue more time consuming than necessary. Here are the details:

After noticing the issue I asked my colleagues if they had any idea why this is and whether anything had changed recently. None of them had an explanation so I spent some time checking / testing:

- running performance reports in MapGuide/AIMS noticing that time spent on "Layer" is 20times slower in production
- comparing view definitions but only cursorily (looking at WHERE clause only) : mistake #1
- re-creating spatial index for base table : no change
- running 1-click maintenance in Map-Administrator : no change
- copy a layer definition from production to test environment : no change
- trying to load view into other applications to see whether the issue is related to application or to view but GeoRaptor couldn't add layer to map due to rowid issue, QGIS rejected view complaining that view didn't have a proper spatial index and TatukGIS Viewer basically saying something similar (first the message about the spatial index issue made me re-re-create the spatial index but testing further views in QGIS/TatukGISViewer I got the same messages for all other views as well).
- running a few spatial SQL queries in SQLDeveloper but there wasn't any significant difference between test and production : mistake # 2

After spending some time on running these tests a colleague came back to me and told me, that the view had changed recently but when he applied the change he didn't notice any performance issue whilst generating graphics in Map. The change was made by adding a subquery to the SELECT clause. He asked if the change should be removed but I replied that I will do some tests now taking the new information into account : mistake # 3.

As the change to the view definition had only been applied in the production system I applied the change in the test system as well - here mistake # 4 occurred. I then ran the MapGuide/AIMS performance report again but the performance had not decreased. Performance was good as before. Then I changed the data source of the Oracle user I was testing with and pointed it to our production database. When I ran the test again performance was slow. I stopped any further testing for the day and did something else.

At this point my theory was that the same query has different execution plans in Oracle (production and test) therefore different execution times due to different Oracle settings. What didn't really fit was that when I ran the spatial queries in SQLDeveloper I didn't see any significant difference in performance. But I didn't have anything else to test so finally I decided to replace the view definition in production with the previous view definition - basically removing the change which had been applied recently. I re-ran the performance report in MapGuide/AIMS and suddenly I got an error message:

Failed to stylize layer: DP_xxx
An exception occurred in FDO component.
ORA-00904: "G"."OWNER_OBJTYP": invalid identifier
...

Now I realised one of my mistakes. MapGuide/AIMS caches certain settings/definitions. I don't know how it works in detail but probably roughly like that:
- when AIMS/MapGuide starts it reads the Oracle schema and caches some information
- (SELECT) statements are being build based on the cached information and used against Oracle

For a view MapGuide/AIMS seems to read the view definition and then creates a SELECT statement which includes all columns of the view. 
If the view definition in Oracle changes and new columns are added to the view MapGuide can still run the SELECT statement against the new view definition - basically just ignoring all newly added columns.  But when columns have been removed from the view the SELECT statement still includes those columns and Oracle will response with ora-00904.

Mistake 4 - when I applied the change to view definition in the test system I did not restart MapGuide/AIMS. MapGuide was still using the SELECT statement which did not include the newly added column in the view. But exactly that new column had a negative impact on performance.
If I had restarted MapGuide/AIMS at this point in time I could have avoided further testing and head-scratching.

Mistake 3 - if I had listened to my colleague who offered to remove the change in production I might have noticed the cause of the problem earlier (because even without restarting MapGuide/AIMS we would have seen the Ora-00904 message in the log file).

Mistake 2 - my spatial query was simplified, the select clause included only "fid, geom". As it did not include the column which caused the performance issue there is really no surprise that performance in both production and test were nearly the same. Conclusion: always use (if possible) exactly the same (SELECT) statement as the application when you do testing!

Mistake 1 - I should have noticed the difference in view definitions myself just by copying the view definitions from production and test into an editor and then noticing the different numbers of lines....

So at the end a trivial issue but it took longer then necessary to get it fixed.

Friday, 10 July 2015

MapGuide / AIMS - show number of sessions

As shown in Jackie's blog one can easily count the number of current sessions. I put such a counter on our internal web site where we keep links to different web interfaces and scripts related to our AIMS/MapGuide installations:




The script is written in PHP:

 <?php  
 // for remote server  
 //  
 // (1) INLCUDE ../vaw_settings.php;  
 //  
 // for local server  
 //  
 // (1) INLCUDE Verweis mit ./vaw_settings.php;  
 //  
 include './vaw_settings.php';  
 $fi = new FilesystemIterator($pathSessionRepository, FilesystemIterator::SKIP_DOTS);  
 //  
 $number = (iterator_count($fi)-1)/2 ;   
 // for remote server  
 //  
 // (2) echo $number;  
 //  
 // for local server  
 //  
 // (2) return $number;  
 //   
 return $number;  
 ?>  

The vaw_settings.php file contains only the path to MapGuide session repository ($pathSessionRepository).

The script for counting current sessions is called from within another PHP script which runs on one of the AIMS servers. It also calls the slightly modified version of the script on the remote server:

 ...  
 $script_number_users = 'misc/count_logged_users.php';  
 ...  
 //local server  
 //only relative path to script  
 $request_url = $script_number_users;  
 echo "# of users logged in ($label_server1):____".include($request_url).".";  
 //remote server  
 //complete url  
 $request_url = $basis_url_server3.$url_vaw_scripte.$script_number_users;  
 echo "# of users logged in ($label_server3):____".file_get_contents($request_url).".";  

Depending on whether the script runs locally or remotely it needs to be modified slightly (see comments in scripts) and the way the script is called varies as well (relative path vs. complete URL, include vs. file_get_contents). 


AIMS/MapGuide 2013

Tuesday, 30 June 2015

MapGuide / AIMS - performance, file access

We run AIMS on virtualized W2008R2 machines with 6 GB RAM. Most data displayed as maps comes directly from Oracle Spatial. Only for one job enabled Map industry model  we decided to export 40+ feature classes and views to an SDF file. File size is roughly 200MB.

In order to speed things up I created a RAM Disk on the server and did some performance tests:
- hard disk access (read/write) was already much better then on my physical machine
- depending on RAM disk driver and test performed read access was faster by up to factor 6 compared to hard disk access

Surprisingly moving the SDF file to the RAM disk did not help improving performance in AIMS/MapGuide. 

Conclusion seems to be that W2008R2 has already cached the SDF file and no further improvement is possible here. As the SDF file is used in all web mapping projects and layers based on file are visible by default I assume that the file will be cached all the time. 


Here are a few screenshots related to the testing:

- hard disk performance, local machine:



- hard disk performance, virtualized 2008r2 server




- ram disk performance, local machine (imdisk)




- ram disk performance, w 2008r2 (softperfect)





- AIMS/MapGuide performance test with sdf based map - sdf file on disk on virtualized w2008r2 server




- AIMS/MapGuide performance test with sdf based map - sdf file on ram disk on virtualized w2008r2 server



AIMS 2013