 <?xml-stylesheet type="text/css" href="https://www.esdm.co.uk/Data/style/rss1.css" ?> <?xml-stylesheet type="text/xsl" href="https://www.esdm.co.uk/Data/style/rss1.xsl" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd">
  <channel>
    <title>The knowledge base blog</title>
    <link>https://www.esdm.co.uk/knowledge</link>
    <description />
    <docs>http://www.rssboard.org/rss-specification</docs>
    <generator>mojoPortal Blog Module</generator>
    <language>en-GB</language>
    <ttl>120</ttl>
    <atom:link href="https://www.esdm.co.uk/Blog/RSS.aspx?p=138~108~45" rel="self" type="application/rss+xml" />
    <itunes:owner />
    <itunes:explicit>no</itunes:explicit>
    <item>
      <title>How to remove .png files recursively from a folder tree without removing .png8 files too</title>
      <description><![CDATA[<p>We have some large GeoWebCache caches of Ordnance Survey map tiles in .png8 format. Unfortunately a few million .png files have crept into the caches too (accidental bad config at some point), duplicating the .png8 tiles and using up a lot more space. I wanted to delete these.</p>

<p>At first I thought "simple:-&nbsp;do a search in Windows Explorer for .png and delete". Ah no, that selects all the .png8 files as well, plus my number of folders and files were far too large.</p>

<p>Then I thought... <code>del /S *.png</code></p>

<p>But no, this deletes the .png8 files as well, grrr.</p>

<p>So I wrote a simple python script, that I will lodge here for future reference. It's Python 2.7, but I imagine would work in 3.* with little or no change. The final print statement probably slows things down, but I wanted to be able to see what was going on.</p>

<pre>
import os
indir = 'M:\\MyVeryLargeCachePath'
for root, dirs, filenames in os.walk(indir):
    for f in filenames:
        if os.path.splitext(f)[1] == '.png':
            os.remove(os.path.join(root, f))
            print('deleted ' + os.path.join(root, f))</pre>

<p>Assuming you have Python installed, simply save this as a file with a .py extension, modify the path and the file extensions to suit, then run it.</p>

<p>This same technique would work for other combinations of file extensions, e.g. to remove *.doc but not *.docx, or to remove *.xls while retaining *.xslx</p>
<br /><a href='https://www.esdm.co.uk/how-to-remove-png-files-recursively-from-a-folder-tree-without-removing-png8-files-too'>Crispin Flower</a>&nbsp;&nbsp;<a href='https://www.esdm.co.uk/how-to-remove-png-files-recursively-from-a-folder-tree-without-removing-png8-files-too'>...</a>]]></description>
      <link>https://www.esdm.co.uk/how-to-remove-png-files-recursively-from-a-folder-tree-without-removing-png8-files-too</link>
      <author>crispin.flower@idoxgroup.com (Crispin Flower)</author>
      <comments>https://www.esdm.co.uk/how-to-remove-png-files-recursively-from-a-folder-tree-without-removing-png8-files-too</comments>
      <guid isPermaLink="true">https://www.esdm.co.uk/how-to-remove-png-files-recursively-from-a-folder-tree-without-removing-png8-files-too</guid>
      <pubDate>Wed, 27 May 2020 09:09:00 GMT</pubDate>
    </item>
    <item>
      <title>A Guide to the Ordnance Survey Archaeological Records</title>
      <description><![CDATA[<p>Our <a href="https://www.esdm.co.uk/hbsmr-historic-environment">HBSMR </a>application is for collecting and managing Historic Environment Record (HER) data, usually as the permanent inventory for an area, and sometimes for short-term data collection or research initiatives.</p>

<p>Historic Environment Records evolved from the County "Sites and Monuments Records" that developed in the 1970s and 1980s, often pioneering the use of the emerging database technologies of the day. These "SMRs" in turn owe their origins to the records collected by the Ordnance Survey ("OS"), driven by <a href="https://en.wikipedia.org/wiki/O._G._S._Crawford" target="_blank">O.G.S. Crawford in the 1920s and 1930s</a>, which used a systematic method of cataloguing sites on index cards and 1:10,000 (or earlier 1 mile=6") map sheets.&nbsp;</p>

<p>This fascinating guide to the Ordnance Survey records was recently found in the records of the Somerset Archaeological Society. It was presumably distributed by Ordnance Survey whenever they sent out copies of the cards.</p>

<h2>The guide</h2>

<blockquote>
<h4>THE ORDNANCE SURVEY'S ARCHAEOLOGICAL RECORDS</h4>

<p>A. INTRODUCTION</p>

<p>The records consist of 8" x 5" index cards ('Record Cards') which give information about antiquities, and 1:10,000/1:10,560 maps ('Record Sheets') on which the sites of the antiquities are marked. The Record Card is described under B, the Record Sheet under C, and under D is a Glossary of the common abbreviations used on both cards and sheets.</p>

<p>B. THE RECORD CARD</p>

<p>The component parts of the current record card are as in Fig 1 below. There were some differences on older cards though the same purposes were served. The main differences are noted in the explanation.</p>

<p><img alt="" height="295" src="https://www.esdm.co.uk/Data/Sites/1/media/oscard_fig1.jpg" width="761" /></p>

<figure>
<figcaption><em>Fig 1</em></figcaption>
</figure>

<p>&nbsp;</p>

<p>1. ANTIQUITY NUMBER</p>

<p>This consists of the National grid number of the 1:10,000/10,560 sheet within which the antiquity falls (eg TQ 37 SW) plus a serial number within that sheet (eg TQ 37 SW 4), and used in its full form identifies the antiquity uniquely. The serial numbers are simply allotted consecutively as each record is compiled, and consequently have no bearing on where the site falls within the sheet, nor any typological significance.</p>

<p>There can also be subsidiary number (eg TQ 37 SW 4.1), used when a component part of an antiquity is allotted a card to itself.</p>

<p>There can in addition be a 'Miscellaneous Information card' for any sheet. This gives very brief information on items of marginal interest which fall on the sheet, and there is only one such card (or card series) for each sheet. It is identified by the sheet number plus a bracketed 'M' (e.g. TQ 37 SW (M)).</p>

<p>2. COUNTY</p>

<p>The name of the county at the date of the last entry. Abbreviations are those adopted by the Ordnance Survey.</p>

<p>3. PARISH</p>

<p>The name of the civil parish at the date of the last entry.</p>

<p>4. CLASSIFICATION</p>

<p>Abbreviations of the archaeological period(s) within which the subject(s) of a card falls, and also abbreviations to show that the period is unestablished, or that the subject of the record not an antiquity (within OS specification). The abbreviations and their meanings are given in the glossary under D below.</p>

<p>5. SPARE</p>

<p>Reserved for future extension of the classification.</p>

<p>6. PAGE NUMBER</p>

<p>The card side number whenever the record extends over than one card side.</p>

<p>7. SCHEDULING</p>

<p>The letter 'S' is entered when the antiquity is scheduled as an Ancient Monument by the Department Of the Environment. On old cards, scheduling was mentioned as text information and authorized. 'S's have not been comprehensively entered, and the lack of an 'S' is no guarantee that the antiquity is unscheduled.</p>

<p>8. SITING SUMARY</p>

<p>A Map-reference of the latest established site or find-spot of the antiquity, whenever this is known to at least a six-figure accuracy (i.e. to within about 100 metres). When siting is less precisely known, the name of the town, village or other place associated with it is entered with a four-figure reference. On old cards the siting summary was in the space serving for both purposes.</p>

<p>9. TYPOLOGY SUMMARY</p>

<p>A brief summary of the (latest established) nature of the antiquity in modern terms, taken from the information recorded, and accounting for each item in the record which has a different period classification.</p>

<p>10. PUBLICATION DIRECTION</p>

<p>Direction (for internal use) as to whether the antiquity is to be published on standard basic scale map, and if so the form the name should take and the type character to be used.</p>

<p>11. TEXT</p>

<p>The information necessary to demonstrate the siting, nature and condition of the antiquity (or to give as much as possible towards those ends), taken from whatever sources provide it, these sources being shown in the adjoining 'Authorities' part - see 12 below. The information can be entered either 'objectively' (i.e. by separate precis from each source) or 'subjectively' (i.e. by a single entry compiled from as many sources as are necessary), or by a mixture of these methods.</p>

<p>Normally the record will start with the objective entry of an Ordnance Survey publication. In subjective entries references are given to the various sources by use of the author's name or bracketed numbers. In objective entries the whole of the text is attributed to a single authority. The recorder can himself make interpolated comments, or even a separate entry of his own opinions. Field reports are always attributable to the Field Investigator himself unless otherwise stated.</p>

<p>12. AUTHORITIES</p>

<p>Each authority (source) consulted and used is given a number. With objective recording this number, with the title of the authority concerned, is positioned opposite the top line of the relevant text entry. With subjective recording, the numbers and authority titles are listed in sequence without interval, the first being opposite the first line of the text entry.</p>

<p>Secondary authorities (or sub-references) are lettered in lower case, and this lettering is in sequence throughout any one record (i.e. letters are not repeated even though under a different primary authority). Secondary authorities are only noted when they make necessary contributions but do not need to be used as primary authorities; it should therefore be appreciated that the primary authorities contain references which are not noted on the record cards. Secondary authorities may in fact have been consulted by the recorder, but the implication of the identification by lower case letters is that they have not. The recorder responsible for entries is identified by R1, R2 etc, with his initials and date, entered opposite the line of the last entry. The Field Investigator is similarly identified by F1, F2 etc, entered opposite the top line of his field report (and covering any recording between that entry and the last recorder's ascription). In the field reports informants are usually treated as secondary authorities, but they can be given separate entries as primary authorities. On old cards Recorders were designated 'OR' and Field Investigators FI and full names were given.</p>

<p>References dealing with relevant typology, but not with the specific antiquity which is the subject of a record, are mentioned in the text, not the Authorities compartment.</p>

<p>13. ILLUSTRATIONS</p>

<p>Illustrations are mounted on separate 'Illustration Cards' numbered in the same way as the record cards. The illustrations may be air photographs, ground photographs, diagrams, plans, or surveys, and they are folded to size if necessary. The photographs do not reproduce.</p>

<p>All Archaeology Division field surveys are ultimately included as illustrations, but there is delay in annexing them, as they have to pass through drawing stage (for the production of new OS maps) before becoming available.</p>

<p>C. THE RECORD SHEET</p>

<p>An example of the current record sheet marking is given in Fig 2 below. The essential ingredients are:</p>

<p>a. a convention marking the site</p>

<p>b. the antiquity number</p>

<p>c. a typological summary.</p>

<p>There were some differences on older record sheets though the same purposes were served. The main differences are noted in the explanations.</p>

<figure><img alt="Ordnance Survey Archaeology Record Sheet Fig2" src="https://www.esdm.co.uk/Data/Sites/1/media/knowledgebase/blog/os_archaeology_fig2.jpg" />
<figcaption><em>Fig 2 (Examples fictitious)</em></figcaption>
</figure>

<p>&nbsp;</p>

<p>1. SITE MARKING</p>

<p>Various markings are used, and on the master copy record sheets different colours are also employed for further refinement. But the main purposes of the record sheets are to serve as indices to the record cards and to record the sites of antiquities topographically, and these purposes are just as well served by monochrome copies. All that is lost are certain nuances of siting and typology useful for quick reference but fully covered on the record cards.</p>

<p>The markings are: Crosses, Published detail, Sketched outline, Bands, Linear markings and Broken linear markings.</p>

<p>The following explanations deal with their monochrome fom only, so more than one meaning sometimes attaches to a single convention. The separate implications however can be readily clarified by reference to the record cards.</p>

<p>Crosses</p>

<p>a. Accurate find-spot or site, whether or not extant (Ex 5).</p>

<p>b. Inaccurate site or find spot (Ex 1).</p>

<p>c. Centre of an extensive antiquity when the outline cannot be properly recovered (Ex 11).&nbsp;</p>

<p>Published detail</p>

<p>This is normally left to stand by itself (Exs 9, 2.1) but it can be shaded or blocked in when it is necessary to distinguish it from adjacent features (Ex 12).&nbsp;</p>

<p>Sketched outline</p>

<p>This is used in preference to a cross for large antiquities which are not published on the record sheet (Ex 10).</p>

<p>Bands</p>

<p>a. Defining a group of antiquities treated on a single record card (Ex 4).</p>

<p>b. Defining the known outline of a feature or site with no perimeter feature (eg a DMV) (Ex 2).</p>

<p>c. Defining the area within which an antiquity occurs, when that area is already defined by published detail, such as hedges (Ex 7).</p>

<p>Linear Markings</p>

<p>The course of a linear antiquity; including extensive enclosure banks etc such as park pales (Exs RR46, Lin 21).</p>

<p>Broken linear markings</p>

<p>The course of a linear antiquity when uncertain (Ex RR46).</p>

<p>2. ANTIQUITY NUMBERS</p>

<p>A plain number in a circle is the number allotted to the record card. It should be noted that to identify the antiquity uniquely the sheet number must be added to this (Exs 1-12).</p>

<p>A decimalised number in a circle refers to a subsidiary record (cf B 1 above) (Ex 2.1).</p>

<p>A smaller number in brackets applies to miscellaneous information (cf B 1 above) (Ex (1)).</p>

<p>The entry of a number in the east margin of the sheet conveys that the antiquity concerned probably falls on that sheet but cannot be sited with any accuracy (Exs 6, 8).</p>

<p>A full number in brackets entered in the margin adjacent to the marking of an antiquity which extends over the edge shows that the card is allotted to the adjacent sheet (Ex (TQ 37 NW6), in north margin).</p>

<p>Linear antiquities are numbered according to a separate Linear system, which is not controlled by sheets. Roman Roads are given the Margary numbers ('Roman Roads in Britain'), otherwise the numbering system is the Ordnance Survey's. Linear numbering is entered on the sheets in brackets, normally along the axis of the Linear (Exs RR46, Lin 21).</p>

<p>3. TYPOLOGICAL SUMMARIES</p>

<p>These are similar to the typological summaries on the record cards (cf B9 above), though they need not be exactly the same.&nbsp; They are entered on the sheets for convenience and as a safeguarding connection with the record card, additional to the number.</p>

<p>D. GLOSSARY OF ABBREVIATIONS&nbsp;USED ON THE ORDNANCE SURVEY'S ARCHAEOLOGICAL RECORD CARDS AND SHEETS</p>

<p>This is not comprehensive, but should account for the majority of the abbreviations which might be puzzling. It does not account for the book title abbreviations used in the 'Authorities' part of the record card, which should be easily understood, nor for the initials of the compiling staff (see B 12 above) Which are irrelevant to the understanding of the records.</p>

<table border="1" cellpadding="2" cellspacing="0">
	<thead>
		<tr>
			<th class="text-center" scope="col">ABBREVIATION</th>
			<th class="text-center" scope="col">MEANING</th>
			<th class="text-center" scope="col">AREA OF OCCURRENCE<br />
			<span class="font-small">(Number of component<br />
			part of record card,<br />
			as in Fig 1, or 'S')</span></th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td>AAO</td>
			<td><span style="display: inline !important; float: none; background-color: transparent; color: rgb(51, 51, 51); font-family: &quot;Open Sans&quot;,sans-serif; font-size: 19px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; -webkit-text-stroke-width: 0px; white-space: normal; word-spacing: 0px;">Assistant Archaeology Officer</span></td>
			<td>12</td>
		</tr>
		<tr>
			<td>Acc No</td>
			<td>Museum Accession number</td>
			<td>11</td>
		</tr>
		<tr>
			<td>Accn No</td>
			<td>" &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; " &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; "&nbsp;</td>
			<td>11</td>
		</tr>
		<tr>
			<td>AO</td>
			<td>Archaeology Officer</td>
			<td>12</td>
		</tr>
		<tr>
			<td>"</td>
			<td>Archaeology Division</td>
			<td>12</td>
		</tr>
		<tr>
			<td>AP</td>
			<td>Air photograph</td>
			<td>11, 12</td>
		</tr>
		<tr>
			<td>AS</td>
			<td>Anglo-Saxon</td>
			<td>9, 11, S</td>
		</tr>
		<tr>
			<td>AT</td>
			<td>Antiquity Tpe character</td>
			<td>10, 11</td>
		</tr>
		<tr>
			<td>Authy</td>
			<td>Authority</td>
			<td>11</td>
		</tr>
		<tr>
			<td>BA</td>
			<td>Bronze Age</td>
			<td>4, 9, 11, S</td>
		</tr>
		<tr>
			<td>BM</td>
			<td>British Museum</td>
			<td>11</td>
		</tr>
		<tr>
			<td>C or c</td>
			<td>Century</td>
			<td>9, 11</td>
		</tr>
		<tr>
			<td>c</td>
			<td>Circa</td>
			<td>11</td>
		</tr>
		<tr>
			<td>Corr</td>
			<td>Ordnance Survey arch. correspondent&nbsp;</td>
			<td>12</td>
		</tr>
		<tr>
			<td>Corr 6"</td>
			<td>Correspondent's annotated 6" sheet</td>
			<td>12</td>
		</tr>
		<tr>
			<td>Crem</td>
			<td>Cremation</td>
			<td>9, 11</td>
		</tr>
		<tr>
			<td>DA</td>
			<td>Dark Ages</td>
			<td>9, 11, S</td>
		</tr>
		<tr>
			<td>DOE</td>
			<td>Department of the Environment</td>
			<td>12</td>
		</tr>
		<tr>
			<td>DMV</td>
			<td>Deserted medieval village</td>
			<td>9, 11, S</td>
		</tr>
		<tr>
			<td>diss</td>
			<td>Dissolved (monasteries)</td>
			<td>11</td>
		</tr>
		<tr>
			<td>EBA</td>
			<td>Early Bronze Age</td>
			<td>9, 11, S</td>
		</tr>
		<tr>
			<td>EI</td>
			<td>Early Industrial</td>
			<td>4, S</td>
		</tr>
		<tr>
			<td>EIA</td>
			<td>Early Iron Age</td>
			<td>9, 11, S</td>
		</tr>
		<tr>
			<td>Ewk</td>
			<td>Earthwork</td>
			<td>9, 11, S</td>
		</tr>
		<tr>
			<td>Ed</td>
			<td>Editor</td>
			<td>11, 12</td>
		</tr>
		<tr>
			<td>Ed</td>
			<td>Edition</td>
			<td>11, 12</td>
		</tr>
		<tr>
			<td>F1, F2 etc</td>
			<td>First, second, etc OS Arch fd investigator&nbsp;</td>
			<td>12</td>
		</tr>
		<tr>
			<td>fd</td>
			<td>Found</td>
			<td>11, S</td>
		</tr>
		<tr>
			<td>"</td>
			<td>Founded</td>
			<td>11, S</td>
		</tr>
		<tr>
			<td>GP</td>
			<td>Ground photograph</td>
			<td>11, 12</td>
		</tr>
		<tr>
			<td>GS</td>
			<td>Gil Sans type character</td>
			<td>10, 11</td>
		</tr>
		<tr>
			<td>GT</td>
			<td>German Text type character</td>
			<td>10, 11</td>
		</tr>
		<tr>
			<td>HHR</td>
			<td>DOE Historic Houses record</td>
			<td>12</td>
		</tr>
		<tr>
			<td>IA</td>
			<td>Iron Age</td>
			<td>4, 9, 11, S</td>
		</tr>
		<tr>
			<td>IAM</td>
			<td>DOE Inspectorate of Ancient Monuments</td>
			<td>11, 12</td>
		</tr>
		<tr>
			<td>Inf</td>
			<td>Informant, or Information from</td>
			<td>12</td>
		</tr>
		<tr>
			<td>Inhum</td>
			<td>Inhumation</td>
			<td>9, 11</td>
		</tr>
		<tr>
			<td>LB</td>
			<td>Lutheran Black type character (Obs)</td>
			<td>11</td>
		</tr>
		<tr>
			<td>LB</td>
			<td>Long Barrow</td>
			<td>11</td>
		</tr>
		<tr>
			<td>LBA</td>
			<td>Late Bronze Age</td>
			<td>9, 11, S</td>
		</tr>
		<tr>
			<td>Lin</td>
			<td>Class name for linear feature other than a Roman road&nbsp;</td>
			<td>11, S</td>
		</tr>
		<tr>
			<td>(M)</td>
			<td>Miscellaneous Information card</td>
			<td>1</td>
		</tr>
		<tr>
			<td>MBA</td>
			<td>Middle Bronze Age</td>
			<td>9, 11, S</td>
		</tr>
		<tr>
			<td>Md</td>
			<td>Medieval</td>
			<td>9, 11, S</td>
		</tr>
		<tr>
			<td>Me</td>
			<td>Mesolithic</td>
			<td>4, 9, 11, S</td>
		</tr>
		<tr>
			<td>MHLG</td>
			<td>Ministry of Housing &amp; Local Govt (Obs)</td>
			<td>12</td>
		</tr>
		<tr>
			<td>MOW</td>
			<td>Ministry of Works (Obs)</td>
			<td>12</td>
		</tr>
		<tr>
			<td>MPBW</td>
			<td>Ministry of Pub Works &amp; Buildings (Obs)</td>
			<td>12</td>
		</tr>
		<tr>
			<td>Mus 6"</td>
			<td>Annotated Museum 6" sheet</td>
			<td>12</td>
		</tr>
		<tr>
			<td>NAT</td>
			<td>Non-antiquity type character</td>
			<td>10, 11</td>
		</tr>
		<tr>
			<td>Ne</td>
			<td>Neolithic</td>
			<td>4, 9, 11, S</td>
		</tr>
		<tr>
			<td>NMR</td>
			<td>National Monument Record</td>
			<td>11, 12</td>
		</tr>
		<tr>
			<td>NR</td>
			<td>Non-Roman Type character</td>
			<td>10, 11</td>
		</tr>
		<tr>
			<td>Occ</td>
			<td>Occupation</td>
			<td>9, 11, S</td>
		</tr>
		<tr>
			<td>ONB</td>
			<td>Ordnance Survey 'Object Name Book'</td>
			<td>11, 12</td>
		</tr>
		<tr>
			<td>OR</td>
			<td>Office Recorder (OS staff) (Obs)</td>
			<td>12</td>
		</tr>
		<tr>
			<td>OS</td>
			<td>Ordnance Survey</td>
			<td>11, 12</td>
		</tr>
		<tr>
			<td>P</td>
			<td>Continue to publish in same form</td>
			<td>10</td>
		</tr>
		<tr>
			<td>Pa</td>
			<td>Palaeolithic</td>
			<td>4, 9, 11, S</td>
		</tr>
		<tr>
			<td>Poss</td>
			<td>Possible</td>
			<td>9, 11, S</td>
		</tr>
		<tr>
			<td>PN</td>
			<td>Post-Norman</td>
			<td>4</td>
		</tr>
		<tr>
			<td>PR</td>
			<td>Post-Roman</td>
			<td>4</td>
		</tr>
		<tr>
			<td>Prob</td>
			<td>Probably</td>
			<td>9, 11, S</td>
		</tr>
		<tr>
			<td>Pte 6"</td>
			<td>Private 6" sheet, annotated</td>
			<td>12</td>
		</tr>
		<tr>
			<td>R1, R2 etc</td>
			<td>First, second, etc OS Arch recorder</td>
			<td>12</td>
		</tr>
		<tr>
			<td>Rec 6"</td>
			<td>Records 6" (obsolete annotated sheet)</td>
			<td>12</td>
		</tr>
		<tr>
			<td>Rems</td>
			<td>Remains of</td>
			<td>9, 11, S</td>
		</tr>
		<tr>
			<td>RB</td>
			<td>Romano-British</td>
			<td>9, 11, S</td>
		</tr>
		<tr>
			<td>R &amp; F</td>
			<td>Ridge and furrow</td>
			<td>9, 11</td>
		</tr>
		<tr>
			<td>Ro</td>
			<td>Roman</td>
			<td>4, 9, 11, S</td>
		</tr>
		<tr>
			<td>RR</td>
			<td>Roman Road with Margary number</td>
			<td>1, 9, 11, S</td>
		</tr>
		<tr>
			<td>RRX</td>
			<td>Roman Road without Margary number</td>
			<td>1, 9, 11, S</td>
		</tr>
		<tr>
			<td>S</td>
			<td>Scheduled by IAM (qv)</td>
			<td>7</td>
		</tr>
		<tr>
			<td>SS Rev</td>
			<td>OS Small Scales reviser</td>
			<td>12</td>
		</tr>
		<tr>
			<td>S/Svyr</td>
			<td>Senior Surveyor (Archaeology Division)</td>
			<td>12</td>
		</tr>
		<tr>
			<td>TI</td>
			<td>Times Italic type character</td>
			<td>11</td>
		</tr>
		<tr>
			<td>TU</td>
			<td>Times Upright type character</td>
			<td>11</td>
		</tr>
		<tr>
			<td>U</td>
			<td>Period unestablished</td>
			<td>4, 9</td>
		</tr>
		<tr>
			<td>X</td>
			<td>Not an antiquity</td>
			<td>4</td>
		</tr>
		<tr>
			<td>X</td>
			<td>Do not publish on standard maps</td>
			<td>10</td>
		</tr>
		<tr>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
		</tr>
	</tbody>
</table>

<p>&nbsp;</p>
</blockquote>
<br /><a href='https://www.esdm.co.uk/a-guide-to-the-ordnance-survey-archaeological-records'>Crispin Flower</a>&nbsp;&nbsp;<a href='https://www.esdm.co.uk/a-guide-to-the-ordnance-survey-archaeological-records'>...</a>]]></description>
      <link>https://www.esdm.co.uk/a-guide-to-the-ordnance-survey-archaeological-records</link>
      <author>crispin.flower@idoxgroup.com (Crispin Flower)</author>
      <comments>https://www.esdm.co.uk/a-guide-to-the-ordnance-survey-archaeological-records</comments>
      <guid isPermaLink="true">https://www.esdm.co.uk/a-guide-to-the-ordnance-survey-archaeological-records</guid>
      <pubDate>Sun, 07 Apr 2019 17:58:00 GMT</pubDate>
    </item>
    <item>
      <title>MapServer and GeoServer (and tilecache) comparison serving Ordnance Survey raster maps</title>
      <description><![CDATA[<p>
	With two WMS running off identical data on the same server, I thought it would be interesting to compare speeds and the map output. So I lined up a map request with identical parameters to both services and ran them through Fiddler a few times (to get an idea of the response times).</p>
<h3>
	Output quality and performance</h3>
<table border="1" cellpadding="2" cellspacing="0" width="600">
	<tbody>
		<tr>
			<td valign="top" width="200">
				&nbsp;</td>
			<td valign="top" width="200">
				<strong>GeoServer</strong></td>
			<td valign="top" width="200">
				<strong>MapServer</strong></td>
		</tr>
		<tr>
			<td valign="top" width="200">
				Response time</td>
			<td valign="top" width="200">
				0.8 to 1.0 seconds with USE_JAI_IMAGEREAD=true<br />
				0.6 to 1.3 seconds with<br />
				USE_JAI_IMAGEREAD=false</td>
			<td valign="top" width="200">
				0.4 to 0.6 seconds</td>
		</tr>
		<tr>
			<td valign="top" width="200">
				Image size</td>
			<td valign="top" width="200">
				63,574 bytes</td>
			<td valign="top" width="200">
				78,327 bytes</td>
		</tr>
		<tr>
			<td valign="top" width="200">
				The map</td>
			<td valign="top" width="200">
				<a href="https://www.esdm.co.uk/Data/Sites/1/media/wlw/esdm_uk_basemaps-50krastercolour%5B4%5D.png"><img alt="ESDM_UK_BaseMaps-50KRasterColour[4]" border="0" height="516" src="https://www.esdm.co.uk/Data/Sites/1/media/wlw/esdm_uk_basemaps-50krastercolour%5B4%5D_thumb.png" style="border-width: 0px; margin: 0px; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="ESDM_UK_BaseMaps-50KRasterColour[4]" width="276" /></a></td>
			<td valign="top" width="200">
				<a href="https://www.esdm.co.uk/Data/Sites/1/media/wlw/mapserv%5B4%5D.png"><img alt="mapserv[4]" border="0" height="516" src="https://www.esdm.co.uk/Data/Sites/1/media/wlw/mapserv%5B4%5D_thumb.png" style="border-width: 0px; margin: 0px; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="mapserv[4]" width="276" /></a></td>
		</tr>
		<tr>
			<td valign="top" width="200">
				Quality</td>
			<td valign="top" width="200">
				Adequate, but quite fractured</td>
			<td valign="top" width="200">
				Lovely</td>
		</tr>
		<tr>
			<td valign="top" width="200">
				Comments</td>
			<td valign="top" width="200">
				A significantly slower response than MapServer, and a worse image.<br />
				I couldn’t find any difference between the different re-sampling methods, perhaps suggesting that the settings were not taking effect (I’ve seen GeoServer GUI issues like this a couple of times now, requiring diving into the XML config files). Later – yes the settings were present in the XML config, but seem to make no difference to the output.</td>
			<td valign="top" width="200">
				Faster and much nicer image.<br />
				If we turn off bilinear re-sampling, then the response time improves to around 0.3 seconds and the image deteriorates slightly as shown below (becoming similar in quality to the GeoServer map).<br />
				<a href="https://www.esdm.co.uk/Data/Sites/1/media/wlw/mapservca53l4zs_thumb%5B3%5D.png"><img alt="mapservCA53L4ZS_thumb[3]" border="0" height="516" src="https://www.esdm.co.uk/Data/Sites/1/media/wlw/mapservca53l4zs_thumb%5B3%5D_thumb.png" style="border-width: 0px; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="mapservCA53L4ZS_thumb[3]" width="276" /></a></td>
		</tr>
	</tbody>
</table>
<p>
	Oh dear this is not looking good for GeoServer. But is it the whole story? Next I compared them in a more realistic scenario, as base maps in OpenLayers, trying both single tile and multi-tile modes. I configured the map to view the 1:50,000 mapping at a scale where no re-sampling could occur.</p>
<table border="1" cellpadding="2" cellspacing="0" width="671">
	<tbody>
		<tr>
			<td valign="top" width="256">
				&nbsp;</td>
			<td valign="top" width="144">
				<strong>GeoServer</strong></td>
			<td valign="top" width="269">
				<strong>MapServer</strong></td>
		</tr>
		<tr>
			<td valign="top" width="256">
				Response time multi-tile (30 tiles each 256x256 pixels)</td>
			<td valign="top" width="144">
				0.2 to 1.2 seconds, but on average a shade faster</td>
			<td valign="top" width="269">
				0.3 to 0.7 seconds</td>
		</tr>
		<tr>
			<td valign="top" width="256">
				Response time single-tile (1725 x 1173 pixels)</td>
			<td valign="top" width="144">
				4 to 6 seconds</td>
			<td valign="top" width="269">
				3 to 5 seconds</td>
		</tr>
		<tr>
			<td valign="top" width="256">
				Image size (typical 256x256 tile)</td>
			<td valign="top" width="144">
				30,447 bytes</td>
			<td valign="top" width="269">
				22,674 seconds</td>
		</tr>
		<tr>
			<td valign="top" width="256">
				Image size (1725 x 1173 pixels)</td>
			<td valign="top" width="144">
				646,681 bytes</td>
			<td valign="top" width="269">
				690,494 bytes</td>
		</tr>
		<tr>
			<td valign="top" width="256">
				The map (256x256 tile)</td>
			<td valign="top" width="144">
				<a href="https://www.esdm.co.uk/Data/Sites/1/media/wlw/geoserv_256tile.png"><img alt="geoserv_256tile" border="0" height="260" src="https://www.esdm.co.uk/Data/Sites/1/media/wlw/geoserv_256tile_thumb.png" style="border-width: 0px; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="geoserv_256tile" width="260" /></a></td>
			<td valign="top" width="269">
				<a href="https://www.esdm.co.uk/Data/Sites/1/media/wlw/mapserv_256tile.png"><img alt="mapserv_256tile" border="0" height="260" src="https://www.esdm.co.uk/Data/Sites/1/media/wlw/mapserv_256tile_thumb.png" style="border-width: 0px; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="mapserv_256tile" width="260" /></a></td>
		</tr>
		<tr>
			<td valign="top" width="256">
				Quality</td>
			<td valign="top" width="144">
				Very good</td>
			<td valign="top" width="269">
				Very good (pretty much identical)</td>
		</tr>
	</tbody>
</table>
<p>
	OK so now it is looking better for GeoServer; when there is no re-sampling it can return identical images to MapServer, though slightly larger, and performance is pretty similar and possibly quicker.</p>
<h3>
	Output quality and performance when re-projecting</h3>
<p>
	Now time to see how they cope with serving the maps into a different coordinate system, and in particular the global spherical Mercator used in Google and Bing Maps.</p>
<table border="1" cellpadding="2" cellspacing="0" width="671">
	<tbody>
		<tr>
			<td valign="top" width="256">
				&nbsp;</td>
			<td valign="top" width="144">
				<strong>GeoServer</strong></td>
			<td valign="top" width="269">
				<strong>MapServer</strong></td>
		</tr>
		<tr>
			<td valign="top" width="256">
				Response time multi-tile (30 tiles each 256x256 pixels)</td>
			<td valign="top" width="144">
				0.2 to 1.2 seconds</td>
			<td valign="top" width="269">
				0.1 to 0.5 seconds</td>
		</tr>
		<tr>
			<td valign="top" width="256">
				Response time single-tile (1725 x 1173 pixels)</td>
			<td valign="top" width="144">
				10 seconds</td>
			<td valign="top" width="269">
				6 seconds</td>
		</tr>
		<tr>
			<td valign="top" width="256">
				Image size (typical 256x256 tile)</td>
			<td valign="top" width="144">
				29,169 bytes</td>
			<td valign="top" width="269">
				37,261 seconds</td>
		</tr>
		<tr>
			<td valign="top" width="256">
				Image size (1725 x 1173 pixels)</td>
			<td valign="top" width="144">
				1,041,098 bytes</td>
			<td valign="top" width="269">
				982,050 bytes</td>
		</tr>
		<tr>
			<td valign="top" width="256">
				The map (256x256 tile)</td>
			<td valign="top" width="144">
				<a href="https://www.esdm.co.uk/Data/Sites/1/media/wlw/geoserv_900913.png"><img alt="geoserv_900913" border="0" height="260" src="https://www.esdm.co.uk/Data/Sites/1/media/wlw/geoserv_900913_thumb.png" style="border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="geoserv_900913" width="260" /></a></td>
			<td valign="top" width="269">
				<p>
					<a href="https://www.esdm.co.uk/Data/Sites/1/media/wlw/mapserv_900913.png"><img alt="mapserv_900913" border="0" height="260" src="https://www.esdm.co.uk/Data/Sites/1/media/wlw/mapserv_900913_thumb.png" style="border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="mapserv_900913" width="260" /></a></p>
			</td>
		</tr>
		<tr>
			<td valign="top" width="256">
				Quality</td>
			<td valign="top" width="144">
				Pretty horrible</td>
			<td valign="top" width="269">
				Very good</td>
		</tr>
	</tbody>
</table>
<p>
	With default settings, GeoServer produces horrible output when re-projecting the raster maps. But this does need more investigation when I found out how to make it use different re-sampling algorithms.</p>
<h3>
	Performance under load</h3>
<p>
	Now time to see how they perform under load using multi-mechanize. I chose to compare MapServer, GeoServer and a tilecache at returning a 256x256 tile in EPSG:900913 (i.e. re-projecting on-the-fly). Each test ran for 100 seconds, starting with 10 virtual users, increasing by 10 every 10 seconds. The tilecache image was of course cached and simply being retrieved from disk. All tests were using the same web server, with files on the same drive.</p>
<p>
	<em>Note: the vertical scale differs in each graph to fit the observed values.</em></p>
<table border="1" cellpadding="2" cellspacing="0" width="600">
	<tbody>
		<tr>
			<td valign="top" width="150">
				&nbsp;</td>
			<td valign="top" width="150">
				<strong>GeoServer</strong></td>
			<td valign="top" width="150">
				<strong>MapServer</strong></td>
			<td valign="top" width="150">
				<strong>Tilecache</strong></td>
		</tr>
		<tr>
			<td valign="top" width="150">
				Transactions</td>
			<td valign="top" width="150">
				381</td>
			<td valign="top" width="150">
				556</td>
			<td valign="top" width="150">
				2188</td>
		</tr>
		<tr>
			<td valign="top" width="150">
				Errors</td>
			<td valign="top" width="150">
				57</td>
			<td valign="top" width="150">
				0</td>
			<td valign="top" width="150">
				0</td>
		</tr>
		<tr>
			<td valign="top" width="150">
				Average response time</td>
			<td valign="top" width="150">
				6.1</td>
			<td valign="top" width="150">
				6.5</td>
			<td valign="top" width="150">
				2.3</td>
		</tr>
		<tr>
			<td valign="top" width="150">
				95% response time</td>
			<td valign="top" width="150">
				26.8</td>
			<td valign="top" width="150">
				17.6</td>
			<td valign="top" width="150">
				5.1</td>
		</tr>
		<tr>
			<td valign="top" width="150">
				Response graph</td>
			<td valign="top" width="150">
				<a href="https://www.esdm.co.uk/Data/Sites/1/media/wlw/all_transactions_response_times.png"><img alt="All_Transactions_response_times" border="0" height="103" src="https://www.esdm.co.uk/Data/Sites/1/media/wlw/all_transactions_response_times_thumb.png" style="border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="All_Transactions_response_times" width="244" /></a></td>
			<td valign="top" width="150">
				<a href="https://www.esdm.co.uk/Data/Sites/1/media/wlw/all_transactions_response_times_1.png"><img alt="All_Transactions_response_times" border="0" height="103" src="https://www.esdm.co.uk/Data/Sites/1/media/wlw/all_transactions_response_times_thumb_1.png" style="border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="All_Transactions_response_times" width="244" /></a></td>
			<td valign="top" width="150">
				<a href="https://www.esdm.co.uk/Data/Sites/1/media/wlw/all_transactions_response_times_2.png"><img alt="All_Transactions_response_times" border="0" height="103" src="https://www.esdm.co.uk/Data/Sites/1/media/wlw/all_transactions_response_times_thumb_2.png" style="border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="All_Transactions_response_times" width="244" /></a></td>
		</tr>
		<tr>
			<td valign="top" width="150">
				Transactions per second</td>
			<td valign="top" width="150">
				<a href="https://www.esdm.co.uk/Data/Sites/1/media/wlw/all_transactions_throughput.png"><img alt="All_Transactions_throughput" border="0" height="103" src="https://www.esdm.co.uk/Data/Sites/1/media/wlw/all_transactions_throughput_thumb.png" style="border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="All_Transactions_throughput" width="244" /></a></td>
			<td valign="top" width="150">
				<a href="https://www.esdm.co.uk/Data/Sites/1/media/wlw/all_transactions_throughput_1.png"><img alt="All_Transactions_throughput" border="0" height="103" src="https://www.esdm.co.uk/Data/Sites/1/media/wlw/all_transactions_throughput_thumb_1.png" style="border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="All_Transactions_throughput" width="244" /></a></td>
			<td valign="top" width="150">
				<a href="https://www.esdm.co.uk/Data/Sites/1/media/wlw/all_transactions_throughput_2.png"><img alt="All_Transactions_throughput" border="0" height="103" src="https://www.esdm.co.uk/Data/Sites/1/media/wlw/all_transactions_throughput_thumb_2.png" style="border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="All_Transactions_throughput" width="244" /></a></td>
		</tr>
		<tr>
			<td valign="top" width="150">
				Comments</td>
			<td valign="top" width="150">
				Completely broken after about 80 seconds – had to re-start GeoServer</td>
			<td valign="top" width="150">
				No errors, but significantly disrupted performance</td>
			<td valign="top" width="150">
				Slight slow-down under high load, but very reassuring performance</td>
		</tr>
	</tbody>
</table>
<p>
	GeoServer clearly could not stand up to more than about 30 virtual users when re-projecting the maps, and ultimately the service stalled completely requiring a re-start.</p>
<p>
	I tried the tests again requesting the maps in OSGB so that the service did not involve re-projection. I also reduced the number of virtual users to 50. The results were quite surprising…</p>
<table border="1" cellpadding="2" cellspacing="0" width="602">
	<tbody>
		<tr>
			<td valign="top" width="150">
				&nbsp;</td>
			<td valign="top" width="150">
				<strong>GeoServer</strong></td>
			<td valign="top" width="150">
				<strong>MapServer</strong></td>
			<td valign="top" width="150">
				<strong>Tilecache</strong></td>
		</tr>
		<tr>
			<td valign="top" width="150">
				Transactions</td>
			<td valign="top" width="150">
				2018</td>
			<td valign="top" width="150">
				1114</td>
			<td valign="top" width="150">
				2197</td>
		</tr>
		<tr>
			<td valign="top" width="150">
				Errors</td>
			<td valign="top" width="150">
				0</td>
			<td valign="top" width="150">
				0</td>
			<td valign="top" width="150">
				0</td>
		</tr>
		<tr>
			<td valign="top" width="150">
				Average response time</td>
			<td valign="top" width="150">
				1.3</td>
			<td valign="top" width="150">
				2.4</td>
			<td valign="top" width="150">
				1.1</td>
		</tr>
		<tr>
			<td valign="top" width="150">
				95% response time</td>
			<td valign="top" width="150">
				2.4</td>
			<td valign="top" width="150">
				9.1</td>
			<td valign="top" width="150">
				2.5</td>
		</tr>
		<tr>
			<td valign="top" width="150">
				Response graph</td>
			<td valign="top" width="150">
				<a href="https://www.esdm.co.uk/Data/Sites/1/media/wlw/all_transactions_response_times_3.png"><img alt="All_Transactions_response_times" border="0" height="103" src="https://www.esdm.co.uk/Data/Sites/1/media/wlw/all_transactions_response_times_thumb_3.png" style="border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="All_Transactions_response_times" width="244" /></a></td>
			<td valign="top" width="150">
				<a href="https://www.esdm.co.uk/Data/Sites/1/media/wlw/all_transactions_response_times_4.png"><img alt="All_Transactions_response_times" border="0" height="103" src="https://www.esdm.co.uk/Data/Sites/1/media/wlw/all_transactions_response_times_thumb_4.png" style="border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="All_Transactions_response_times" width="244" /></a></td>
			<td valign="top" width="150">
				<a href="https://www.esdm.co.uk/Data/Sites/1/media/wlw/all_transactions_response_times_5.png"><img alt="All_Transactions_response_times" border="0" height="103" src="https://www.esdm.co.uk/Data/Sites/1/media/wlw/all_transactions_response_times_thumb_5.png" style="border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="All_Transactions_response_times" width="244" /></a></td>
		</tr>
		<tr>
			<td valign="top" width="150">
				Transactions per second</td>
			<td valign="top" width="150">
				<a href="https://www.esdm.co.uk/Data/Sites/1/media/wlw/all_transactions_throughput_3.png"><img alt="All_Transactions_throughput" border="0" height="103" src="https://www.esdm.co.uk/Data/Sites/1/media/wlw/all_transactions_throughput_thumb_3.png" style="border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="All_Transactions_throughput" width="244" /></a></td>
			<td valign="top" width="150">
				<a href="https://www.esdm.co.uk/Data/Sites/1/media/wlw/all_transactions_throughput_4.png"><img alt="All_Transactions_throughput" border="0" height="103" src="https://www.esdm.co.uk/Data/Sites/1/media/wlw/all_transactions_throughput_thumb_4.png" style="border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="All_Transactions_throughput" width="244" /></a></td>
			<td valign="top" width="150">
				<a href="https://www.esdm.co.uk/Data/Sites/1/media/wlw/all_transactions_throughput_5.png"><img alt="All_Transactions_throughput" border="0" height="103" src="https://www.esdm.co.uk/Data/Sites/1/media/wlw/all_transactions_throughput_thumb_5.png" style="border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="All_Transactions_throughput" width="244" /></a></td>
		</tr>
		<tr>
			<td valign="top" width="150">
				Comments</td>
			<td valign="top" width="150">
				Impeccable!</td>
			<td valign="top" width="150">
				Much better than when re-projecting, but only half as good as GeoServer.</td>
			<td valign="top" width="150">
				Only fractionally better than GeoServer</td>
		</tr>
	</tbody>
</table>
<p>
	This is a hugely impressive result for GeoServer. My guess is that it is employing server-side in-memory caching, and because all my requests were identical the responses were very fast. MapServer on the other hand has to start a CGI process of each request and presumably cannot benefit from an in-memory cache.</p>
<p>
	When re-projecting on the other hand, perhaps it does not use a cache. And because all the GeoServer operations are running as one process, it is restricted to one virtual processor on our server whereas each MapServer exe can grab one for itself. Certainly when running these tests the server was running at about 40-80% CPU with MapServer, compared to 7% with GeoServer.</p>
<p>
	I ran this test again with the number of virtual users doubled back to 100, and GeoServer came through almost unscathed, this time processing 2072 transactions though with 3 errors.</p>
<table border="1" cellpadding="2" cellspacing="0" width="602">
	<tbody>
		<tr>
			<td valign="top" width="150">
				&nbsp;</td>
			<td valign="top" width="150">
				<strong>GeoServer</strong></td>
			<td valign="top" width="150">
				<strong>MapServer</strong></td>
			<td valign="top" width="150">
				<strong>Tilecache</strong></td>
		</tr>
		<tr>
			<td valign="top" width="150">
				Transactions</td>
			<td valign="top" width="150">
				2072</td>
			<td valign="top" width="150">
				907</td>
			<td valign="top" width="150">
				2234</td>
		</tr>
		<tr>
			<td valign="top" width="150">
				Errors</td>
			<td valign="top" width="150">
				3</td>
			<td valign="top" width="150">
				0</td>
			<td valign="top" width="150">
				0</td>
		</tr>
		<tr>
			<td valign="top" width="150">
				Average response time</td>
			<td valign="top" width="150">
				2.4</td>
			<td valign="top" width="150">
				5.9</td>
			<td valign="top" width="150">
				2.3</td>
		</tr>
		<tr>
			<td valign="top" width="150">
				95% response time</td>
			<td valign="top" width="150">
				5.9</td>
			<td valign="top" width="150">
				25.6</td>
			<td valign="top" width="150">
				4.8</td>
		</tr>
		<tr>
			<td valign="top" width="150">
				Response graph</td>
			<td valign="top" width="150">
				<a href="https://www.esdm.co.uk/Data/Sites/1/media/wlw/all_transactions_response_times_6.png"><img alt="All_Transactions_response_times" border="0" height="103" src="https://www.esdm.co.uk/Data/Sites/1/media/wlw/all_transactions_response_times_thumb_6.png" style="border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="All_Transactions_response_times" width="244" /></a></td>
			<td valign="top" width="150">
				<a href="https://www.esdm.co.uk/Data/Sites/1/media/wlw/all_transactions_response_times_7.png"><img alt="All_Transactions_response_times" border="0" height="103" src="https://www.esdm.co.uk/Data/Sites/1/media/wlw/all_transactions_response_times_thumb_7.png" style="border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="All_Transactions_response_times" width="244" /></a></td>
			<td valign="top" width="150">
				<a href="https://www.esdm.co.uk/Data/Sites/1/media/wlw/all_transactions_response_times_8.png"><img alt="All_Transactions_response_times" border="0" height="103" src="https://www.esdm.co.uk/Data/Sites/1/media/wlw/all_transactions_response_times_thumb_8.png" style="border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="All_Transactions_response_times" width="244" /></a></td>
		</tr>
		<tr>
			<td valign="top" width="150">
				Transactions per second</td>
			<td valign="top" width="150">
				<a href="https://www.esdm.co.uk/Data/Sites/1/media/wlw/all_transactions_throughput_6.png"><img alt="All_Transactions_throughput" border="0" height="103" src="https://www.esdm.co.uk/Data/Sites/1/media/wlw/all_transactions_throughput_thumb_6.png" style="border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="All_Transactions_throughput" width="244" /></a></td>
			<td valign="top" width="150">
				<a href="https://www.esdm.co.uk/Data/Sites/1/media/wlw/all_transactions_throughput_7.png"><img alt="All_Transactions_throughput" border="0" height="103" src="https://www.esdm.co.uk/Data/Sites/1/media/wlw/all_transactions_throughput_thumb_7.png" style="border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="All_Transactions_throughput" width="244" /></a></td>
			<td valign="top" width="150">
				<a href="https://www.esdm.co.uk/Data/Sites/1/media/wlw/all_transactions_throughput_8.png"><img alt="All_Transactions_throughput" border="0" height="103" src="https://www.esdm.co.uk/Data/Sites/1/media/wlw/all_transactions_throughput_thumb_8.png" style="border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="All_Transactions_throughput" width="244" /></a></td>
		</tr>
		<tr>
			<td valign="top" width="150">
				Comments</td>
			<td valign="top" width="150">
				Wow</td>
			<td valign="top" width="150">
				Suffering, but no errors</td>
			<td valign="top" width="150">
				The best as expected</td>
		</tr>
	</tbody>
</table>
<p>
	I suspect this test may not predict real-world behaviour with lots of users requesting different WMS maps, where I suspect GeoServer would lose its advantage, but it is interesting anyway.</p>
<p>
	NB I had GeoServer running with AllowMultithreading=true</p>
<h3>
	Summary</h3>
<p>
	If the maps need to be re-projected then use MapServer – both performance and output quality are vastly superior. In a site that is going to get any significant load it is unwise to re-project raster mapping on-the-fly anyway, and it should definitely be cached. In this case the&nbsp;WMS performance doesn’t matter so much but output quality is paramount, so MapServer it is.&nbsp; If I find a way of making GeoServer produce nice looking output I’ll come back and revise this post!</p>
<p>
	If no re-projection is required, then simple observation has the two roughly equal under light load. The maps looked almost identical, and performance was close. GeoServer had the advantage for me in that it didn’t suffer from MapServer’s tendency to choke on some requests; in practice this meant I went over my entire OSGB cache again with a GeoServer WMS as the source, to plug the gaps left by the MapServer service.</p>
<p>
	Under heavy (albeit contrived) load, the crucial factor was whether or not there was any re-projection involved. Without re-projection GeoServer produced astonishing performance, thrashing MapServer and nearly matching a tilecache. Introduce re-projection however, and GeoServer collapses to the extent that it can crash entirely – not good when it is running all your mapping services. MapServer never broke, and despite some gaps and slow responses, it managed to struggle through all tests without a single error.</p>
<p>
	So out of this experience I think we need to be using both, depending on the purpose.</p>
<p>
	Next to test performance on vector layers, including file based GIS formats and spatial databases…</p>
<br /><a href='https://www.esdm.co.uk/mapserver-and-geoserver-and-tilecache-comparison-serving-ordnance-survey-raster-maps'>Crispin Flower</a>&nbsp;&nbsp;<a href='https://www.esdm.co.uk/mapserver-and-geoserver-and-tilecache-comparison-serving-ordnance-survey-raster-maps'>...</a>]]></description>
      <link>https://www.esdm.co.uk/mapserver-and-geoserver-and-tilecache-comparison-serving-ordnance-survey-raster-maps</link>
      <author>crispin.flower@idoxgroup.com (Crispin Flower)</author>
      <comments>https://www.esdm.co.uk/mapserver-and-geoserver-and-tilecache-comparison-serving-ordnance-survey-raster-maps</comments>
      <guid isPermaLink="true">https://www.esdm.co.uk/mapserver-and-geoserver-and-tilecache-comparison-serving-ordnance-survey-raster-maps</guid>
      <pubDate>Sat, 21 Jan 2012 17:53:00 GMT</pubDate>
    </item>
    <item>
      <title>Some notes about setting up ​Tilecache for the Ordnance S​urvey Open Data</title>
      <description><![CDATA[<h3>
	Background</h3>
<p>
	Increasingly we are using Ordnance Survey Open Data as a background map option in web sites, and also in desktop systems where no other mapping is available. We have so far served this as a MapServer WMS. This puts a significant load on the web server, and will not scale beyond a few concurrent users. Making this scale requires converting the datasets into a cache of image tiles that can be accessed without running a GIS engine on the server. The most widely used tool for this is Tilecache from Metacarta <a href="http://tilecache.org/docs/README.html"><font color="#0066cc">http://tilecache.org</font></a></p>
<p>
	Usually OS mapping is used in a map in OSGB coordinate system, however my first two applications requiring faster mapping are a) the <a href="http://www.anglingdiary.org.uk" target="_blank" title="Angling Diary"><font color="#0066cc">Angling Diary</font></a>, and b) <a href="http://ramblersroutes.org" target="_blank" title="Ramblers Routes"><font color="#0066cc">Ramblers Routes</font></a>, both of which work in the spherical Mercator projection (EPSG:900913). These make it even more imperative to cache the data, as there is on-the-fly reprojection involved in using them as a WMS directly. Re-projection can also make the maps look bad, mitigated only by finding the best resampling settings (see below about MapServer resampling).</p>
<h4>
	Information</h4>
<p>
	<a href="http://tilecache.org/docs/README.html"><font color="#0066cc">http://tilecache.org/docs/README.html</font></a></p>
<p>
	which gives general instructions (but misleading about Windows), and this blog post which explains in more detail how to set up tilecache on IIS (but relates to IIS5 &amp; Server 2000):</p>
<p>
	<a href="http://viswaug.wordpress.com/2008/02/03/setting-up-tilecache-on-iis/"><font color="#0066cc">http://viswaug.wordpress.com/2008/02/03/setting-up-tilecache-on-iis/</font></a></p>
<h4>
	Python</h4>
<p>
	Tilecache requires Python. Check whether the server is 32/64-bit and get the appropriate download from here: <a href="http://www.python.org/download/"><font color="#0066cc">http://www.python.org/download/</font></a></p>
<p>
	For our web7 server I am using the x64 version: python-2.7.2.amd64.msi</p>
<p>
	I accepted all defaults, and installed to here: C:\Python27\</p>
<p>
	This path needs to be added to the PATH environment variable. I have a feeling this does not take effect until a restart, but I'm not 100% sure.</p>
<h4>
	Python Imaging Library</h4>
<p>
	Then we also need the Python Imaging Library, from here <a href="http://www.pythonware.com/products/pil/"><font color="#0066cc">http://www.pythonware.com/products/pil/</font></a></p>
<p>
	Again, select the correct version for the version of Python used above, though there seems to be no 64-bit version. I used file PIL-1.1.7.win32-py2.7.exe</p>
<p>
	Running this installer failed because it said Python was not installed - missing registry settings. A reboot did not fix this.</p>
<p>
	A bit of Binging leads to this page <a href="http://www.lfd.uci.edu/~gohlke/pythonlibs/"><font color="#0066cc">http://www.lfd.uci.edu/~gohlke/pythonlibs/</font></a> where we can find a 64-bit installer:</p>
<p>
	PIL-1.1.7.win-amd64-py2.7.exe</p>
<p>
	This installed fine.</p>
<h4>
	Tilecache</h4>
<p>
	Download Tilecache from here <a href="http://tilecache.org/"><font color="#0066cc">http://tilecache.org/</font></a></p>
<p>
	This gives us tilecache-2.11.tar.gz</p>
<p>
	I used 7-zip to extract from the gz to a folder that contains the .tar file. Then I extracted the files from .tar to end up with a folder: \tilecache-2.11</p>
<p>
	I don't think the "PaxHeader" folder parallel to this folder is needed, but I hung onto it anyway, and put both folders under a single Tilecache folder.</p>
<p>
	This folder has to be located somewhere CGI scripts can run, I put it below a Mapserver "scripts" folder that was already operational within a web site. Depending on where you put it, it may be necessary to create a virtual directory for Tilecache.</p>
<h4>
	IIS stuff (the miserable bit)</h4>
<p>
	Now we need to setup IIS to run Python scripts.</p>
<p>
	Web site &gt; Handler mappings &gt; Add Script Map</p>
<p>
	Request Path = *.py</p>
<p>
	Executable = "C:\Python27\python.exe" %s %s</p>
<p>
	Name = Python27 (or whatever you like)</p>
<p>
	I did not change anything in Request Restrictions.</p>
<p>
	&nbsp;</p>
<p>
	I'm not yet sure whether this is strictly needed, but at the root level in IIS I also added the same path under "ISAPI and CGI Restrictions" &gt; Add &gt;</p>
<p>
	ISAPI or CGI path = "C:\Python27\python.exe" %s %s</p>
<p>
	Description = Python27</p>
<p>
	Tick to allow the path to execute.</p>
<p>
	&nbsp;</p>
<p>
	Vish's article describes another step...</p>
<blockquote>
	<p>
		Open up the command prompt and change directory to ‘C:\Inetpub\AdminScripts’. Execute the following:</p>
	<p>
		adsutil set w3svc/AllowPathInfoForScriptMappings True</p>
	<p>
		adsutil set w3svc/1/AllowPathInfoForScriptMappings True</p>
</blockquote>
<p>
	However on our server there was no AdminScripts folder in C:\Inetpub. Therefore it was necessary to install IIS6 Script Services, like this:</p>
<p>
	Server manager &gt; Roles &gt; Web Server &gt; Add Role Services &gt; Management Tools &gt; IIS 6 Scripting Tools (which in turn requires adding others which it selects for you automatically).</p>
<p>
	Once this had been done, I was able to run the two command lines above. While in the role services area, check that CGI is enabled in IIS as well, because none of this will work without CGI; but if MapServer is working, then CGI must already be enabled.</p>
<h4>
	Permissions</h4>
<p>
	I initially gave the Internet Guest Account (IIS_IUSRS) modify permissions on the "Cache" folder. However I took these permissions off again, and it still worked. Vish said this was required, but it cannot be really, as it is not the web site user creating the tiles, it is the python process.</p>
<h4>
	Tilecache itself</h4>
<p>
	Rename tilecache.cgi to tilecache.py</p>
<p>
	Edit tilecache.py and remove the first line in it that reads '<span style="color: rgb(128, 0, 0);">#!/usr/bin/env python'</span>. Also, change the 'Service.Load'’ parameter to point at the correct path to tilecache.cfg (and be sure to use double back-slashes in the path).</p>
<p>
	Tilecache includes a web page with an OpenLayers map, that serves to check whether things are configured correctly, and also allows you to manually start caching tiles. This is index.html, which by default loads and caches the OpenLayers base map WMS. I copy this file to e.g. indexOS.html then edit as required.</p>
<p>
	This page requests maps from tilecache.py which in turn uses tilecache.cfg configuration. So to work with a different data source it is necessary to add the relevant configuration to both files.</p>
<h5>
	Tilecache.cfg</h5>
<p>
	Configure the type and location of the cache. Here we are using a local file cache on disk:</p>
<p>
	[cache]<br />
	type=Disk<br />
	base=D:\mypath\tilecache\tilecache-2.11\Cache</p>
<p>
	Configure the layer you want to cache, in this case our OS Open Data WMS. These settings were arrived at after much blood and sweat.</p>
<p>
	[OSOpenSphMerc]<br />
	type=WMS<br />
	layers=OSOpenData<br />
	url=http://mywebsite/scripts/mapserv.exe?map=D:\Websites\UKBaseMap\map\UKBaseMap.map<br />
	extension=png<br />
	extent_type=loose<br />
	srs=EPSG:900913<br />
	# this definitely required when calling in 900913<br />
	spherical_mercator=true<br />
	bbox=-20037508.34,-20037508.34,20037508.34,20037508.34<br />
	resolutions=78271.51695,39135.758475,19567.8792375,9783.93961875,4891.969809375,2445.9849046875,1222.99245234375,611.496226171875,305.7481130859375,152.87405654296876,76.43702827148438,38.21851413574219,19.109257067871095,9.554628533935547,4.777314266967774,2.388657133483887,1.1943285667419434,0.5971642833709717,0.29858214168548586</p>
<p>
	The "spherical_mercator=true" setting is supposed to remove the need for a resolutions setting, but in practice I got errors if it was not there. The settings above are basically the entire world in spherical mercator.</p>
<p>
	My matching OpenLayers code was:</p>
<pre>
        function init(){
            map = new OpenLayers.Map( $('map'), {
                projection: new OpenLayers.Projection("EPSG:900913"),
       	        units: "m",
               maxExtent: new OpenLayers.Bounds(-20037508.34, -20037508.34, 20037508.34, 20037508.34),
               resolutions: [78271.51695, 39135.758475, 19567.8792375, 9783.93961875, 4891.969809375, 2445.9849046875, 1222.99245234375, 611.496226171875, 305.7481130859375, 152.87405654296876, 76.43702827148438, 38.21851413574219, 19.109257067871095, 9.554628533935547, 4.777314266967774, 2.388657133483887, 1.1943285667419434, 0.5971642833709717, 0.29858214168548586],
               controls: [new OpenLayers.Control.Navigation(),
                                new OpenLayers.Control.PanZoomBar()],
                  }
            );</pre>
<pre>
            OSOpenSphMerc = new OpenLayers.Layer.WMS( "OSOpenSphMerc",
                    "tilecache.py?", {layers: 'OSOpenSphMerc', format: 'image/png' },
                    {isBaseLayer: true}
            );</pre>
<p>
	However, when browsing the map I kept getting errors on some tiles, along these lines:</p>
<p>
	"An error occurred: Current y value 7983694.728100 is too far from tile corner y 7944558.969625"</p>
<p>
	This problem got worse the further I zoomed in, and the further north in the UK. However, it was intermittent in the sense that one band of tiles might draw (north-south or east-west bands) then the next might not - a checkerboard effect. The exact same WMS requests going directly to the OSOpenData WMS worked fine - i.e. the BBOXes in the requests were good.</p>
<h4>
	Seeding the cache</h4>
<p>
	Therefore I tried seeding the cache directly using a command-line like:</p>
<p>
	D:\Websites\UKBaseMap\scripts\tilecache\tilecache-2.11\tilecache_seed.py -f --bbox=-1060000,6405978,242016,8700250 OSOpenSphMerc 1 11</p>
<p>
	(this bounding box being a rather unscientific box that includes the OS mapping and is divisible by 256 in both directions - whether the latter is important or not I do not know).</p>
<p>
	This seeding worked without any tile failures. Therefore, after much searching the web and head-scratching, I have concluded that the errors when used from OpenLayers may be down to Tilecache bugs.</p>
<p>
	Note about seeding: Level 0 raised an error about a zero length image and would not complete seeding, so I had to skip this and start at 1. Level 0 equates to looking at the earth from a long way away, so no big deal.</p>
<p>
	Another note about seeding: each run tended to produce a few errors. There were a lot of "Cache miss" entries coming back in the command window, plus some more serious errors occasionally (HTTP 502 Bad Gateway - which causes the seeding operation to bail out). Therefore I tended to run each level twice (or more if it had bailed out). The first time in, I used the "-f" flag to force re-creation of all tiles (in case I had any left over from testing and setting up resolutions). The second time I omitted this flag, so it would only re-create any missing tiles. I don't really know whether this was necessary, except in the few cases where caching a layer totally aborted.</p>
<h4>
	Managing the cache</h4>
<p>
	I'm now part way through seeding the cache - on level 16. The size of the cache grows exponentially with each level, so disk space may become an issue. With a small part of level 16 done (this being StreetView) we have over 3 million files and 20GB of space used.</p>
<p>
	There is a cache cleaning utility in Tilecache, which removes the tiles accessed least recently in order to reduce the cache to a specifified size. However, this would only be beneficial where all map requests are going through tilecache.py, so that tiles can be recreated where needed from the datasource. Maximum benefit is gained by pre-caching the entire dataset, and accessing it as a tile service, therefore no cleaning is possible.</p>
<h4>
	Caching in GB National Grid</h4>
<p>
	Once I was happy that the 900913 cache was building OK, I turned attention to a GB National Grid cache, which should in theory be much simpler.</p>
<p>
	The bounding box is 0,0,700000,1300000 though out respect for the many people on the web who have said it should be a multiple of 256, I altered this slightly (in OpenLayers map and tilecache.cfg) to 0,0,699904,1299968. Actually later I found this was missing edge tiles at large scales, and I then found the BBOX when seeding had no effect on the tiling behaviour - it simply governed the area of seeding; therefore I changed this to something like 0,0,800000,1400000 at large scales, and back to 0,0,700000,1300000 for lower ones.</p>
<p>
	But what about the resolutions? One technique I have found is to set the OpenLayers map to</p>
<p>
	maxResolution: 'auto', numZoomLevels: &lt;some sensible number like 14&gt;</p>
<p>
	Then try to start caching, and you quickly get errors back associated with the dreaded pink boxes in the map (you see the errors in Fiddler), which says that the required resolution was not found, and gives an array of available resolutions (I don't know the basis for the values it gives). These can then be used in the cfg and map settings.</p>
<p>
	This worked pretty well for the OS data, except that after 1:14000 it gave 1:7029, which shows StreetView rather too zoomed out and looking rubbish. Also, scales like 1:1757 are not user friendly, and although on-screen scale is not entirely meaningful, users still prefer a round scale like 1:2500 (in cases where scale is displayed). So perhaps we need to define our own array of scales, and reverse engineer an array of resolutions from them. How?</p>
<p>
	OpenLayers has a control that can shows the map scale (map.addControl(new OpenLayers.Control.Scale());), but does not have one to show the resolution (AFAIK). So we have to do this ourselves, as follows. Add a handler for the move event onto the (uncached) WMS layer:</p>
<pre>
  OSOpenDirect.events.on({
                 moveend: function(e) {
                     if (e.zoomChanged) {
                       showResolution();
                     }
                   }
        });
        }</pre>
<p>
	which calls this function:</p>
<pre>
        function showResolution() {
            document.getElementById("res").innerHTML = map.getResolution();
        }</pre>
<p>
	which requires a div like this on the page:</p>
<pre>
&lt;div id="res"&gt;the resolution will be shown here&lt;/div&gt;</pre>
<p>
	Then simply set your map scales array to whatever you fancy, and the corresponding resolution will be shown.</p>
<p>
	On doing this however, we quickly find that the VectorMap and StreetMap datasets only look decent at a very confined range of scales. In the end I abandoned the quest for user friendly scales, because VectorMap only looks decent when unscaled, i.e. giving a map scale of 1:7087.</p>
<p>
	I ended up with this resolutions array, which prioritizes nice-looking maps over friendly scales:</p>
<p>
	resolutions=3000,2000,1000,500,250,150,100,50,25,12.5,5,2.5,1</p>
<p>
	Of course the maps you get also depend on how the layers are set up in the WMS, i.e. what scale thresholds are set for each layer. I had to tweak ours a bit.</p>
<h4>
	Aside - re-sampling in MapServer</h4>
<p>
	The smaller scale OS maps do not mind being scaled if there is good resampling being done at the MapServer end - in fact this is crucial for making the maps look decent, and the performance hit doesn't matter once the data is cached. I've achieved this with this directive on each layer:</p>
<p>
	PROCESSING "RESAMPLE=BILINEAR"</p>
<p>
	along with this output format:</p>
<p>
	OUTPUTFORMAT<br />
	NAME png<br />
	DRIVER "AGG/PNG"<br />
	MIMETYPE "image/png"<br />
	IMAGEMODE RGBA<br />
	EXTENSION "png"<br />
	TRANSPARENT ON<br />
	# these setting greatly reduce the size of the PNG image<br />
	FORMATOPTION "QUANTIZE_FORCE=on"<br />
	FORMATOPTION "QUANTIZE_COLORS=256"<br />
	END</p>
<p>
	An example of how much worse the maps look without this can be seen here:</p>
<p>
	<a href="http://andrewl.net/map/ordnance-survey-rasters-mapserver-tilecache"><font color="#0066cc">http://andrewl.net/map/ordnance-survey-rasters-mapserver-tilecache</font></a></p>
<p>
	(which is otherwise another helpful resource for anyone using tilecache and OS OpenData on a Unix platform).</p>
<h4>
	How long does it take, and how much disk space is required</h4>
<p>
	Well of course this depends on the precise resolutions chosen. I have no exact figures on time, because several runs bombed out and needed re-starting. Essentially, levels 0 to 5 take only seconds to build. Levels 6 to 8 take minutes (in 27700 level 9 took around 20 minutes, with level 10 taking a few hours). Level 13 in 900913 took less than 5 hours, while level 14 took something like 20 hours. Levels 16 (900913) and 12 (27700) are looking like they will take days. The 27700 cache rate was higher than the 900913, presumably because MapServer was not having to reproject the maps.</p>
<p>
	Some directory sizes (along with scale and resolution) for my 900913 and 27700 caches:</p>
<p>
	&nbsp;</p>
<table border="1" cellpadding="2" cellspacing="0">
	<caption>
		&nbsp;</caption>
	<tbody>
		<tr>
			<td>
				Level</td>
			<td>
				Scale<br />
				(approx)</td>
			<td>
				Resolution</td>
			<td>
				Size on disk</td>
			<td>
				Files</td>
		</tr>
		<tr>
			<td colspan="5">
				Spherical Mercator (EPSG:900913) Early layers omitted</td>
		</tr>
		<tr>
			<td>
				05</td>
			<td style="text-align: left;">
				1:7M</td>
			<td>
				2445.9849046875</td>
			<td style="text-align: right;">
				1.34 MB</td>
			<td style="text-align: right;">
				300</td>
		</tr>
		<tr>
			<td>
				06</td>
			<td style="text-align: left;">
				1:3M</td>
			<td>
				1222.99245234375</td>
			<td style="text-align: right;">
				1.33 MB</td>
			<td style="text-align: right;">
				175</td>
		</tr>
		<tr>
			<td>
				07</td>
			<td>
				1:2M</td>
			<td>
				611.496226171875</td>
			<td style="text-align: right;">
				4.19 MB</td>
			<td style="text-align: right;">
				400</td>
		</tr>
		<tr>
			<td>
				08</td>
			<td>
				1:867K</td>
			<td>
				305.7481130859375</td>
			<td style="text-align: right;">
				14.3 MB</td>
			<td style="text-align: right;">
				975</td>
		</tr>
		<tr>
			<td>
				09</td>
			<td>
				1:433K</td>
			<td>
				152.87405654296876</td>
			<td style="text-align: right;">
				47.7 MB</td>
			<td style="text-align: right;">
				2,700</td>
		</tr>
		<tr>
			<td>
				10</td>
			<td>
				1:217K</td>
			<td>
				76.43702827148438</td>
			<td style="text-align: right;">
				151 MB</td>
			<td style="text-align: right;">
				9,600</td>
		</tr>
		<tr>
			<td>
				11</td>
			<td>
				1:108K</td>
			<td>
				38.21851413574219</td>
			<td style="text-align: right;">
				439 MB</td>
			<td style="text-align: right;">
				33,725</td>
		</tr>
		<tr>
			<td>
				12</td>
			<td>
				1:54K</td>
			<td>
				19.109257067871095</td>
			<td style="text-align: right;">
				1.54 GB</td>
			<td style="text-align: right;">
				130,700</td>
		</tr>
		<tr>
			<td>
				13</td>
			<td>
				1:27K</td>
			<td>
				9.554628533935547</td>
			<td style="text-align: right;">
				2.88 GB</td>
			<td style="text-align: right;">
				510,300</td>
		</tr>
		<tr>
			<td>
				14</td>
			<td>
				1:14K</td>
			<td>
				4.777314266967774</td>
			<td style="text-align: right;">
				10.3 GB</td>
			<td style="text-align: right;">
				2,017,100</td>
		</tr>
		<tr>
			<td>
				15</td>
			<td>
				1:6771</td>
			<td>
				2.388657133483887</td>
			<td style="text-align: right;">
				53.9 GB</td>
			<td style="text-align: right;">
				8,027,650</td>
		</tr>
		<tr>
			<td>
				16</td>
			<td>
				1:3386</td>
			<td>
				1.1943285667419434</td>
			<td style="text-align: right;">
				211 GB</td>
			<td style="text-align: right;">
				32,051,575</td>
		</tr>
		<tr>
			<td>
				&nbsp;</td>
			<td>
				&nbsp;</td>
			<td>
				TOTAL</td>
			<td style="text-align: right;">
				280 GB</td>
			<td style="text-align: right;">
				42,785,884</td>
		</tr>
		<tr>
			<td colspan="5">
				GB National Grid (EPSG:27700)</td>
		</tr>
		<tr>
			<td>
				00</td>
			<td>
				1:9M</td>
			<td>
				3000</td>
			<td style="text-align: right;">
				61,136</td>
			<td style="text-align: right;">
				2</td>
		</tr>
		<tr>
			<td>
				01</td>
			<td>
				1:6M</td>
			<td>
				2000</td>
			<td style="text-align: right;">
				129,385</td>
			<td style="text-align: right;">
				6</td>
		</tr>
		<tr>
			<td>
				02</td>
			<td>
				1:3M</td>
			<td>
				1000</td>
			<td style="text-align: right;">
				264,569</td>
			<td style="text-align: right;">
				15</td>
		</tr>
		<tr>
			<td>
				03</td>
			<td>
				1:1M</td>
			<td>
				500</td>
			<td style="text-align: right;">
				1,220,288</td>
			<td style="text-align: right;">
				150</td>
		</tr>
		<tr>
			<td>
				04</td>
			<td>
				1:709K</td>
			<td>
				250</td>
			<td style="text-align: right;">
				6,144,271</td>
			<td style="text-align: right;">
				600</td>
		</tr>
		<tr>
			<td>
				05</td>
			<td>
				1:425K</td>
			<td>
				150</td>
			<td style="text-align: right;">
				16,132,572</td>
			<td style="text-align: right;">
				1,125</td>
		</tr>
		<tr>
			<td>
				06</td>
			<td>
				1:283K</td>
			<td>
				100</td>
			<td style="text-align: right;">
				43,106,957</td>
			<td style="text-align: right;">
				2,100</td>
		</tr>
		<tr>
			<td>
				07</td>
			<td>
				1:142K</td>
			<td>
				50</td>
			<td style="text-align: right;">
				67,469,260</td>
			<td style="text-align: right;">
				7,475</td>
		</tr>
		<tr>
			<td>
				08</td>
			<td>
				1:71K</td>
			<td>
				25</td>
			<td style="text-align: right;">
				115,948,919</td>
			<td style="text-align: right;">
				28,125</td>
		</tr>
		<tr>
			<td>
				09</td>
			<td>
				1:35K</td>
			<td>
				12.5</td>
			<td style="text-align: right;">
				494,478,612</td>
			<td style="text-align: right;">
				106,800</td>
		</tr>
		<tr>
			<td>
				10</td>
			<td>
				1:14K</td>
			<td>
				5</td>
			<td style="text-align: right;">
				1,958,013,298</td>
			<td style="text-align: right;">
				649,000</td>
		</tr>
		<tr>
			<td>
				11</td>
			<td>
				1:7087</td>
			<td>
				2.5</td>
			<td style="text-align: right;">
				6,023,812,744</td>
			<td style="text-align: right;">
				2,244,000</td>
		</tr>
		<tr>
			<td>
				12</td>
			<td>
				1:2835</td>
			<td>
				1</td>
			<td style="text-align: right;">
				<p>
					23,706,682,416</p>
				<p>
					58.9 GB on disk</p>
			</td>
			<td style="text-align: right;">
				<p>
					13,919,200</p>
				<p>
					21,924 folders</p>
			</td>
		</tr>
		<tr>
			<td>
				&nbsp;</td>
			<td>
				&nbsp;</td>
			<td>
				TOTAL</td>
			<td style="text-align: right;">
				<p>
					32,433,464,427</p>
				<p>
					75.1 GB on disk</p>
			</td>
			<td>
				<p style="text-align: right;">
					16,958,598</p>
				<p style="text-align: right;">
					31,400 folders</p>
			</td>
		</tr>
	</tbody>
</table>
<h4>
	&nbsp;</h4>
<h4>
	Some time later...</h4>
<p>
	I've stopped caching level 16 in 900913 as the lowest priority, and I'm attacking level 15 as well as level 12 in 27700 with multiple processes (with the min/max Y of the BBOX set to have each process caching a slice of the country). With 7 processes running, our server is working like this:</p>
<p>
	<img alt="Server taking everything in its stride" src="https://www.esdm.co.uk/Data/Sites/1/media/knowledgebase/hardworkingserver.jpg" style="width: 550px; height: 410px;" title="Server taking everything in its stride" /></p>
<p>
	Which is just fine, leaving plenty of ooomph free for running web sites etc. The pressure point is probably on physical RAM.</p>
<p>
	The server spec is:</p>
<p>
	CPU 2 x E5520 Xeon (quad core) + hyper-threading, meaning in effect 16 processors</p>
<p>
	Memory: 8 GB</p>
<p>
	OS: Windows Server 2008 x64 SP2</p>
<p>
	Disks: 1.2TB as 2 x SAS drives in RAID 5 I think.</p>
<h4>
	Accessing the cache in OpenLayers</h4>
<p>
	There are two ways of accessing the cache. The first is as a WMS with tilecache.py as the address. In this case, python will check whether the image tiles exists in the cache, and build any missing ones from the original data source. As time goes on, and more tiles are cached, the faster it gets. However, in 900913 I was getting frequent tile failures, and I'm not sure this method gives any real benefit over direct calls to MapServer.</p>
<p>
	The second is as a "tilecache", where the client (OpenLayers) requests the tiles individually as images, with no checks as to whether or not they exist. This is faster, as it avoids the IIS/python overhead, but obviously requires a pre-built and complete cache.</p>
<p>
	I therefore included in my OpenLayers map a layer that pointed at the resulting cache as a tile service, to check the results:</p>
<pre>
            OSOpenSphMercCached = new OpenLayers.Layer.TileCache( "OSOpenSphMercCached",
                    ["<a href="http://mywebsite/scripts/tilecache/tilecache-2.11/Cache"><font color="#0066cc">http://mywebsite/scripts/tilecache/tilecache-2.11/Cache</font></a>"], "OSOpenSphMerc", {'format': 'image/png'},
                    {isBaseLayer: true}
            );</pre>
<p>
	On panning around the map, this causes tile requests like this:</p>
<p>
	<a href="http://mywebsite/scripts/tilecache/tilecache-2.11/Cache/OSOpenSphMerc/15/000/032/032/000/043/439.png"><font color="#0066cc">http://mywebsite/scripts/tilecache/tilecache-2.11/Cache/OSOpenSphMerc/15/000/032/032/000/043/439.png</font></a></p>
<p>
	This will only work if the map is configured with resolutions exactly matching those in the table above for either 27700 or 900913. But it is not necessary to use every resolution; for example we may have a map where the user cannot zoom out beyond level 4 (in 27700).</p>
<p>
	Demonstration pages:</p>
<p>
	<a href="http://www.esdmwms.no-ip.co.uk/scripts/tilecache/tilecache-2.11/indexOS27700.html"><font color="#0066cc">http://www.esdmwms.no-ip.co.uk/scripts/tilecache/tilecache-2.11/indexOS27700.html</font></a></p>
<p>
	<a href="http://www.esdmwms.no-ip.co.uk/scripts/tilecache/tilecache-2.11/indexOS.html"><font color="#0066cc">http://www.esdmwms.no-ip.co.uk/scripts/tilecache/tilecache-2.11/indexOS.html</font></a></p>
<p>
	(both have a direct WMS as default base layer, with the cached layer as another option in the layer switcher).</p>
<p>
	Next we should put a handler page in front of these services to restrict access to specified domains.</p>
<h4>
	Caching overlays</h4>
<p>
	Having cracked the OS Open Data, I thought it worth trying an overlay, so I chose the Norfolk HER archaeological monuments layers from HBSMR. These are quite slow to draw as WMS from our web4 server, with about 60,000 point, line and polygon features stored in MapInfo tables in WGS84.</p>
<p>
	I used the same resolutions etc as the OS 27700 data. Caching levels 0 to 11 took a few minutes; level 12 is taking perhaps an hour or two. The cache is about 1GB.</p>
<p>
	The one small gotcha is how to use a tilecache layer as an overlay in OpenLayers - on my first attempt it refused to budge from the base layers collection.</p>
<p>
	Working syntax was thus:</p>
<pre>
            NHECached = new OpenLayers.Layer.TileCache( "NHECached",
                    "http://www.esdmwms.no-ip.co.uk/scripts/tilecache/tilecache-2.11/Cache", "NHE",
                    {'format': 'image/png', reproject: false, isBaseLayer: false}
            );</pre>
<p>
	The results are fantastic. Of course a cache is broken if the data changes, but given the speed of creating this cache, it would be perfectly realistic to have this as a scheduled job to rebuild a cache automatically every night, or whatever is appropriate depending on how the source data is managed.</p>
<h4>
	Preventing pink tiles</h4>
<p>
	Where a dataset does not cover the entire map extent, Open Layers will still request tiles from a tilecache layer, giving the pink tiles where no image is returned. To prevent this, add this JavaScript function:</p>
<pre>
        OpenLayers.Util.onImageLoadError = function() {</pre>
<pre>
            this.src = "../tilecache-2.11/blank256.png";
            this.style.display = "";
        };</pre>
<p>
	And make sure there is an appropriate 256x256 image in place.</p>
<h4>
	Multiple URLs for the Cache</h4>
<p>
	The bottlecks with a tilecache prepared and accessed as shown above are a) disk access and b) http throttling. The second of these is likely to be significant before the first - AFAIK IIS limits to two concurrent requests to the same domain. With any one map operation potentially requests perhaps 20 tiles, this will be a pinch point.</p>
<p>
	Fortunately OpenLayers allows a tilecache (or in fact any grid based layer) to be accessed from multiple URLs. It then requests some tiles from each defined address.</p>
<pre>
            OSOpen27700Cached = new OpenLayers.Layer.TileCache( "OSOpen27700Cached",
                    [
                    "http://www.anglingdiary.org.uk/Data/Sites/3/userfiles/gisdata",
                    "http://www.esdmwms.no-ip.co.uk/scripts/tilecache/tilecache-2.11/Cache"
                    ],
                    "OSOpen27700", {'format': 'image/png'},
                    {isBaseLayer: true}
            );</pre>
<p>
	I don't know whether it is possible to kid IIS into allowing multiple addresses that in fact point to the same web server (i.p.) and file cache. I have demonstrated that OpenLayers does its bit, but it may be that we would have to clone the cache onto two virtual servers with different i.p. addresses to obtain the true benefits. This would only become necessary once the cache is under heavy load.</p>
<h4>
	Accessing a subset of ​the resolutions in OpenLayers</h4>
<p>
	Sometimes we want a map that has a tilecached layer, but we do not want all of the resolutions. For example we may want the Spherical Mercator OS Open Data, but start viewing at a UK scale rather than global. Unfortunately you cannot just knock off a few resolutions in the OpenLayers layer definition and expect it to work. OpenLayers equates the first resolution with folder "0", the next with "1", etc. So knocking off a resolution has it looking for the wrong image tiles. There is a neat solution: in your web site set up symbolic links to the real cache folders using mklink, mapping a folder called "0" to the real folder "5" (or whatever is appropriate) - this means you now have a new level 0 at the appropriate scale for the OpenLayers layer. This is not a complete write-up of the solution - but we have implemented this in the Lincolnshire Heritage @ Risk web site (October 2011).</p>
<p>
	Example: in a folder for the new pseudo tilecache, run a command like this for each resolution:</p>
<p>
	mklink /D 0 D:\PathToMyCache\MyCacheName\5</p>
<p>
	The same technique allows composite caches to be constructed, for example containing one specific dataset that has been cached at one scale with others for other scales.</p>
<p>
	&nbsp;</p>
<br /><a href='https://www.esdm.co.uk/some-notes-about-setting-up-​tilecache-for-the-ordnance-s​urvey-open-data'>Crispin Flower</a>&nbsp;&nbsp;<a href='https://www.esdm.co.uk/some-notes-about-setting-up-​tilecache-for-the-ordnance-s​urvey-open-data'>...</a>]]></description>
      <link>https://www.esdm.co.uk/some-notes-about-setting-up-​tilecache-for-the-ordnance-s​urvey-open-data</link>
      <author>crispin.flower@idoxgroup.com (Crispin Flower)</author>
      <comments>https://www.esdm.co.uk/some-notes-about-setting-up-​tilecache-for-the-ordnance-s​urvey-open-data</comments>
      <guid isPermaLink="true">https://www.esdm.co.uk/some-notes-about-setting-up-​tilecache-for-the-ordnance-s​urvey-open-data</guid>
      <pubDate>Sun, 15 Jan 2012 18:22:00 GMT</pubDate>
    </item>
  </channel>
</rss>