1
0
forked from 0ad/0ad

# IO thesis: add TSP measurement, lessons learned and bibliography (bibtex)

This was SVN commit r3686.
This commit is contained in:
janwas 2006-03-25 20:57:16 +00:00
parent d6abc57868
commit cc26968249

View File

@ -19,14 +19,15 @@
\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\leveltemplateid67698689\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li5040\jclisttab\tx5040\lin5040 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0
\levelstartat1\levelspace0\levelindent0{\leveltext\leveltemplateid67698691\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li5760\jclisttab\tx5760\lin5760 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0
{\leveltext\leveltemplateid67698693\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li6480\jclisttab\tx6480\lin6480 }{\listname ;}\listid2098556351}}{\*\listoverridetable{\listoverride\listid2098556351\listoverridecount0\ls1}}{\*\rsidtbl \rsid141460
\rsid202317\rsid408563\rsid615363\rsid674725\rsid799807\rsid881799\rsid1001543\rsid1010827\rsid1080261\rsid1080863\rsid1128024\rsid1337770\rsid1516560\rsid1733211\rsid1770144\rsid1847956\rsid2108982\rsid2117727\rsid2186746\rsid2424877\rsid2508185
\rsid2521923\rsid2556592\rsid2578444\rsid3160535\rsid3243975\rsid3289879\rsid3345630\rsid3422301\rsid3546591\rsid3550232\rsid3606292\rsid3629320\rsid4146695\rsid4156677\rsid4282397\rsid4351785\rsid4401489\rsid4665099\rsid4722959\rsid4916741\rsid4933345
\rsid4937740\rsid4994568\rsid5048634\rsid5467766\rsid5710756\rsid5715141\rsid5721779\rsid5791350\rsid5968267\rsid5980580\rsid6185166\rsid6191932\rsid6762521\rsid6826037\rsid6831581\rsid6842252\rsid6842857\rsid6951588\rsid7279159\rsid7351464\rsid7371675
\rsid7437835\rsid7543581\rsid7561109\rsid7733471\rsid7764402\rsid8066536\rsid8144712\rsid8264387\rsid8477628\rsid8813409\rsid8848513\rsid8874078\rsid9060782\rsid9109787\rsid9137203\rsid9206128\rsid9373790\rsid9524216\rsid9658852\rsid9779530\rsid10040624
\rsid10047242\rsid10117750\rsid10239896\rsid10249343\rsid10885058\rsid11155165\rsid11157276\rsid11279558\rsid11288483\rsid11368037\rsid11408224\rsid11472464\rsid11472636\rsid11491946\rsid11684990\rsid11994078\rsid12070557\rsid12124230\rsid12480624
\rsid12547006\rsid12675798\rsid12716889\rsid12808527\rsid12870649\rsid13000184\rsid13180669\rsid13388513\rsid13582553\rsid13723102\rsid13724273\rsid13779256\rsid13977746\rsid14045424\rsid14093323\rsid14308065\rsid14363947\rsid14433699\rsid14619881
\rsid14696977\rsid14962633\rsid15159648\rsid15160866\rsid15301494\rsid15489891\rsid15548533\rsid15672389\rsid15688925\rsid15952639\rsid16131725\rsid16411143\rsid16475960\rsid16678464}{\*\generator Microsoft Word 11.0.6359;}{\info{\title Introduction}
{\author Jan Wassenberg}{\operator Jan Wassenberg}{\creatim\yr2006\mo3\dy23\hr13\min57}{\revtim\yr2006\mo3\dy25\hr2\min44}{\version14}{\edmins354}{\nofpages20}{\nofwords6969}{\nofchars39727}{\*\company a}{\nofcharsws46603}{\vern24703}}
\rsid202317\rsid408563\rsid615363\rsid674725\rsid799807\rsid881799\rsid1001543\rsid1010827\rsid1080261\rsid1080863\rsid1128024\rsid1337770\rsid1516560\rsid1733211\rsid1770144\rsid1847956\rsid1911773\rsid2108982\rsid2117727\rsid2186746\rsid2424877
\rsid2508185\rsid2521923\rsid2556592\rsid2578444\rsid3160535\rsid3243975\rsid3289879\rsid3345630\rsid3422301\rsid3546591\rsid3550232\rsid3606292\rsid3629320\rsid4146695\rsid4156677\rsid4282397\rsid4351785\rsid4401489\rsid4665099\rsid4722959\rsid4916741
\rsid4933345\rsid4937740\rsid4994568\rsid5048634\rsid5053763\rsid5245032\rsid5467766\rsid5710756\rsid5715141\rsid5721779\rsid5791350\rsid5906787\rsid5968267\rsid5980580\rsid6185166\rsid6191932\rsid6382957\rsid6762521\rsid6826037\rsid6831581\rsid6842252
\rsid6842857\rsid6951588\rsid7279159\rsid7351464\rsid7371675\rsid7437835\rsid7543581\rsid7561109\rsid7733471\rsid7764402\rsid8066536\rsid8144712\rsid8264387\rsid8400636\rsid8477628\rsid8805545\rsid8813409\rsid8848513\rsid8874078\rsid9060782\rsid9109787
\rsid9137203\rsid9206128\rsid9373790\rsid9524216\rsid9658852\rsid9779530\rsid10040624\rsid10047242\rsid10117750\rsid10176575\rsid10239896\rsid10249343\rsid10617934\rsid10885058\rsid11155165\rsid11157276\rsid11279558\rsid11288483\rsid11368037\rsid11408224
\rsid11472464\rsid11472636\rsid11491946\rsid11684990\rsid11994078\rsid12070557\rsid12124230\rsid12262430\rsid12480624\rsid12547006\rsid12663892\rsid12675798\rsid12716889\rsid12808527\rsid12870649\rsid13000184\rsid13180669\rsid13388513\rsid13582553
\rsid13723102\rsid13724273\rsid13779256\rsid13977746\rsid14045424\rsid14093323\rsid14308065\rsid14363947\rsid14426874\rsid14433699\rsid14619881\rsid14696977\rsid14962633\rsid15098734\rsid15159648\rsid15160866\rsid15301494\rsid15489891\rsid15548533
\rsid15672389\rsid15688925\rsid15952639\rsid16060755\rsid16131725\rsid16411143\rsid16475960\rsid16678464}{\*\generator Microsoft Word 11.0.6359;}{\info{\title Introduction}{\author Jan Wassenberg}{\operator Jan Wassenberg}
{\creatim\yr2006\mo3\dy23\hr13\min57}{\revtim\yr2006\mo3\dy25\hr16\min41}{\version18}{\edmins502}{\nofpages24}{\nofwords8510}{\nofchars43917}{\*\company a}{\nofcharsws52080}{\vern24703}}
\widowctrl\ftnbj\aenddoc\noxlattoyen\expshrtn\noultrlspc\dntblnsbdb\nospaceforul\hyphcaps0\formshade\horzdoc\dgmargin\dghspace180\dgvspace180\dghorigin1701\dgvorigin1984\dghshow1\dgvshow1
\jexpand\viewkind4\viewscale100\pgbrdrhead\pgbrdrfoot\splytwnine\ftnlytwnine\htmautsp\nolnhtadjtbl\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\nobrkwrptbl\viewnobound1\snaptogridincell\allowfieldendsel
\wrppunct\asianbrkrule\rsidroot15301494\newtblstyruls\nogrowautofit \fet0\sectd \linex0\headery708\footery708\colsx708\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2
@ -42,18 +43,18 @@ by splash screens and progress bars; however, it can be done better.
\par }{\f1\insrsid15301494\charrsid12808527 Introduction
\par
\par }{\f1\insrsid615363 Motivation / }{\f1\insrsid15301494\charrsid12808527 Importance of Fast}{\f1\insrsid6842252 I/O}{\f1\insrsid15301494\charrsid12808527
\par
\par Since}{\f1\insrsid6842252 I/O}{\f1\insrsid15301494\charrsid12808527 is much slower than CPU or memory, it can }{\f1\insrsid7543581 easily }{\f1\insrsid15301494\charrsid12808527 become a bottleneck}{\f1\insrsid7543581 }{\f1\insrsid14093323 within}{
\f1\insrsid7543581 the system as a whole. }{\f1\insrsid16131725 An }{\f1\insrsid615363 estimate as of 2006}{\f1\insrsid16131725 is}{\f1\insrsid12808527\charrsid12808527 }{\f1\insrsid615363 6}{\f1\insrsid12808527\charrsid12808527 0}{\f1\insrsid16131725
}{\f1\insrsid12808527\charrsid12808527 MB/s vs}{\f1\insrsid16131725 .}{\f1\insrsid12808527\charrsid12808527 2}{\f1\insrsid615363 6}{\f1\insrsid12808527\charrsid12808527 00}{\f1\insrsid16131725 }{\f1\insrsid12808527\charrsid12808527 MB/s}{
\f1\insrsid16131725 .}{\f1\insrsid12808527\charrsid12808527 }{\f1\insrsid15301494\charrsid12808527 Many }{\f1\insrsid7543581 applications }{\f1\insrsid15301494\charrsid12808527 would therefore benefit from faster}{\f1\insrsid6842252 I/O}{
\f1\insrsid12808527\charrsid12808527 ; example scenarios include:}{\f1\insrsid15301494\charrsid12808527
\par }{\f1\insrsid15301494
\par }{\f1\insrsid15301494\charrsid12808527 Since}{\f1\insrsid6842252 I/O}{\f1\insrsid15301494\charrsid12808527 is much slower than CPU or memory, it can }{\f1\insrsid7543581 easily }{\f1\insrsid15301494\charrsid12808527 become a bottleneck}{
\f1\insrsid7543581 }{\f1\insrsid14093323 within}{\f1\insrsid7543581 the system as a whole. }{\f1\insrsid16131725 An }{\f1\insrsid615363 estimate as of 2006}{\f1\insrsid16131725 is}{\f1\insrsid12808527\charrsid12808527 }{\f1\insrsid615363 6}{
\f1\insrsid12808527\charrsid12808527 0}{\f1\insrsid16131725 }{\f1\insrsid12808527\charrsid12808527 MB/s vs}{\f1\insrsid16131725 .}{\f1\insrsid12808527\charrsid12808527 2}{\f1\insrsid615363 6}{\f1\insrsid12808527\charrsid12808527 00}{\f1\insrsid16131725
}{\f1\insrsid12808527\charrsid12808527 MB/s}{\f1\insrsid16131725 .}{\f1\insrsid12808527\charrsid12808527 }{\f1\insrsid15301494\charrsid12808527 Many }{\f1\insrsid7543581 applications }{\f1\insrsid15301494\charrsid12808527
would therefore benefit from faster}{\f1\insrsid6842252 I/O}{\f1\insrsid12808527\charrsid12808527 ; example scenarios include:}{\f1\insrsid15301494\charrsid12808527
\par }{\f1\insrsid12808527\charrsid12808527 - slow startup time. The user is inconvenienced by waiting for }{\f1\insrsid12808527 required files to load}{\f1\insrsid7543581 ; splash screens }{\f1\insrsid4933345 are one attempt to mitigate this by }{
\f1\insrsid7543581 distracting the user}{\f1\insrsid12808527\charrsid12808527 .}{\f1\insrsid12808527
\par }{\f1\insrsid15489891 For a}{\f1\insrsid16131725 rather extreme}{\f1\insrsid15489891 }{\f1\insrsid4933345 illustration }{\f1\insrsid15489891 of th}{\f1\insrsid4933345 e}{\f1\insrsid15489891 problem, see }{\field{\*\fldinst {\f1\insrsid15489891
HYPERLINK "}{\f1\insrsid15489891\charrsid15489891 http://www.break.com/index/patiencechild.html}{\f1\insrsid15489891 " }{\f1\insrsid4916741\charrsid10249343 {\*\datafield
HYPERLINK "}{\f1\insrsid15489891\charrsid15489891 http://www.break.com/index/patiencechild.html}{\f1\insrsid15489891 " }{\f1\insrsid16060755\charrsid10249343 {\*\datafield
00d0c9ea79f9bace118c8200aa004ba90b02000000170000002e00000068007400740070003a002f002f007700770077002e0062007200650061006b002e0063006f006d002f0069006e006400650078002f00700061007400690065006e00630065006300680069006c0064002e00680074006d006c000000e0c9ea79f9ba
ce118c8200aa004ba90b5c00000068007400740070003a002f002f007700770077002e0062007200650061006b002e0063006f006d002f0069006e006400650078002f00700061007400690065006e00630065006300680069006c0064002e00680074006d006c00000000650067}}}{\fldrslt {
ce118c8200aa004ba90b5c00000068007400740070003a002f002f007700770077002e0062007200650061006b002e0063006f006d002f0069006e006400650078002f00700061007400690065006e00630065006300680069006c0064002e00680074006d006c0000000065006700}}}{\fldrslt {
\cs15\f1\ul\cf2\insrsid15489891\charrsid10249343 http://www.break.com/index/patiencechild.html}}}{\f1\insrsid15489891 .}{\f1\insrsid15489891\charrsid15489891
\par }{\f1\insrsid12808527\charrsid12808527 - }{\f1\insrsid12808527 on-demand loading. If the data set is too large to fit in memory, it must be loaded }{\f1\insrsid615363 in increments }{\f1\insrsid12808527 as needed. This can cause \lquote freezes\rquote
in the application while waiting for the}{\f1\insrsid6842252 I/O}{\f1\insrsid12808527 to finish.
@ -182,8 +183,8 @@ over the PCI bus became the norm. Here, the disk controller writes directly to m
\par - aio }{\f1\insrsid3160535 places pending read requests in a queue so }{\f1\insrsid9109787 that the disk controller can proceed immediately with the next}{\f1\insrsid6842252 I/O}{\f1\insrsid9109787 ; the disk is always busy. With threaded blocking}{
\f1\insrsid6842252 I/O}{\f1\insrsid9109787 , the OS would have to return from and then reenter kernel mode before relaying the }{\f1\insrsid1337770 application\rquote s }{\f1\insrsid9109787 next}{\f1\insrsid6842252 I/O}{\f1\insrsid9109787
request to the disk. This overhead reduces throughput.
\par - parallelism between computation and}{\f1\insrsid6842252 I/O}{\f1\insrsid9109787 is ach
ieved without having to worry about the OS correctly scheduling all participating threads. Additionally, behavior is predictable and thread-switch overhead is avoided.
\par - parallelism between computation and}{\f1\insrsid6842252 I/O}{\f1\insrsid9109787
is achieved without having to worry about the OS correctly scheduling all participating threads. Additionally, behavior is predictable and thread-switch overhead is avoided.
\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid3160535 {\f1\insrsid3160535
\par }{\f1\insrsid1337770 Note: Linux used to emulate aio by spawning threads, which led to less than stellar performance. This is no longer the case; indeed a decent aio implementation should not fare worse than the threaded blocking I/O approach.
\par In fact, asynchronous I/O performs better on Windows due to the abovementioned issues.
@ -230,8 +231,8 @@ read. Indeed the current 0ad dataset has been compressed down to 46% of the orig
{\f1\insrsid6842252 I/O}{\f1\insrsid5721779 read }{\f1\insrsid11157276 time.
\par }{\f1\insrsid5721779
\par }{\f1\insrsid11157276 Throughput can be much improved by arranging files on disk in order of access}{\f1\insrsid5721779 , thus avoiding seeks}{\f1\insrsid11157276 . Since we wish to use a standard File System (}{\f1\insrsid5721779
whose placement strategy we cannot control}{\f1\insrsid11157276 ) for simplicity, files will have to be combined into one large OS-visible file \endash an archive.}{\f1\insrsid5721779 As mentioned above, we prefer the Zip format for easy interoperabil
ity.}{\f1\insrsid11157276
whose placement strategy we cannot control}{\f1\insrsid11157276 ) for simplicity, files will have to be combined into one large OS-visible file \endash an archive.}{\f1\insrsid5721779
As mentioned above, we prefer the Zip format for easy interoperability.}{\f1\insrsid11157276
\par }{\f1\insrsid5721779
\par Incidentally, storing files in archives has an additional advantage. The FS needs to store metadata and typically sector-aligns files; since sectors are 512 bytes or }{\f1\insrsid13977746 more}{\f1\insrsid5721779
, this is very costly for tiny files. (NB: ReiserFS4 is the only known exception, able to pack several files into one sector.)
@ -246,8 +247,8 @@ BC...AC...BC. It would seem that 50% of \lquote C\rquote accesses must incur a
\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid11157276 {\f1\insrsid11157276
\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid2578444 {\f1\insrsid2578444 Now back to the issue of finding an ordering for files. Our strategy is as follows:
\par 1) view all files to be added as nodes in a DAG}{\f1\insrsid6831581 (Directed Acyclic Graph)}{\f1\insrsid2578444 ; edges indicate that 2 files are immediate neighbors in the archive.
\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid11157276 {\f1\insrsid2578444 2) }{\f1\insrsid12480624 record a}{\f1\insrsid2578444 \'93trace\'94 of all}{\f1\insrsid12480624
file accesses over one or more program runs (recall that access patterns may differ}{\f1\insrsid2578444 between runs}{\f1\insrsid12480624 )}{\f1\insrsid15159648 .}{\f1\insrsid2578444
\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid11157276 {\f1\insrsid2578444 2) }{\f1\insrsid12480624 record a}{\f1\insrsid2578444 \'93trace\'94 of all}{\f1\insrsid12480624 file accesses over one or mo
re program runs (recall that access patterns may differ}{\f1\insrsid2578444 between runs}{\f1\insrsid12480624 )}{\f1\insrsid15159648 .}{\f1\insrsid2578444
\par }{\f1\insrsid15159648 3) construct from this a list of possible edges sorted by their frequency (i.e. how often they occurred in the trace).
\par 4) generate a set of \lquote }{\f1\insrsid2521923 chains}{\f1\insrsid15159648 \rquote by committing the above edges as long as no cycle results. These }{\f1\insrsid2521923 chains}{\f1\insrsid15159648
are connected portions of the DAG that are known to have been accessed in that order.
@ -257,8 +258,8 @@ BC...AC...BC. It would seem that 50% of \lquote C\rquote accesses must incur a
\par
\par }{\f1\insrsid6831581 1: Prepare DAG of Files
\par
\par Each node holds all required information about the file. This includes its filename and the nodes that have been chosen to come before and after it in the final layout. All of these are stored as 16-bit IDs to reduce size and t
herefore improve locality; mapping from filename to ID is accomplished in logarithmic time via tree.
\par Each node holds all required information about the file. This includes its filename and the nodes that have been chosen to come before and after it in the
final layout. All of these are stored as 16-bit IDs to reduce size and therefore improve locality; mapping from filename to ID is accomplished in logarithmic time via tree.
\par
\par }{\f1\insrsid15159648 2: }{\f1\insrsid2521923 Record }{\f1\insrsid15159648 Trace
\par }{\f1\insrsid12480624
@ -272,8 +273,8 @@ because seeks are incurred by accessing any part of the file. Also, we assume th
\f1\insrsid6842252 I/O}{\f1\insrsid12716889 parts.}{\f1\insrsid674725
\par
\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid674725 {\f1\insrsid674725 Note}{\f1\insrsid12716889 s}{\f1\insrsid674725 :}{\f1\insrsid12716889
\par - }{\f1\insrsid674725 we are careful to ensure that recording a trace does not incur any}{\f1\insrsid6842252 I/Os}{\f1\insrsid674725
, which would skew performance measurements. Records are stored in binary format within an expandable array (no copying or memory waste due to pre-reserved virtual address space).
\par - }{\f1\insrsid674725 we are careful to ensure that recording a trace does not incur any}{\f1\insrsid6842252 I/Os}{\f1\insrsid674725 , which would skew performance measurements. Records are stored in binary format within an expandable array
(no copying or memory waste due to pre-reserved virtual address space).
\par }{\f1\insrsid12716889 - trace files may log accesses over several program runs. This will be useful in the following steps because several mutual-exclusive but equally probably access patterns may exist, each of which should be equally considered.
\par Program runs are differentiated by examining the timestamp, which starts at 0 on each run.
\par
@ -302,22 +303,23 @@ because seeks are incurred by accessing any part of the file. Also, we assume th
\f1\insrsid6842252 by an edge}{\f1\insrsid2521923 (unless a cycle were to result). For simplicity, committed edges are never removed, this being a greedy heuristic.}{\f1\insrsid14363947
\par
\par }{\f1\insrsid2521923 We check for cycles}{\f1\insrsid14363947 via }{\f1\insrsid2521923 \'93}{\f1\insrsid14363947 DFS}{\f1\insrsid2521923 \'94}{\f1\insrsid14363947 , which }{\f1\insrsid2521923 actually }{\f1\insrsid14363947 simplifies to a list walk }{
\f1\insrsid2521923 here }{\f1\insrsid14363947 since n
odes have only one previous and next link. These are typically quite short and overall run time of this entire step is not a problem in practice (7ms for 5000 files), so we do not attempt more efficient and sophisticated cycle detection schemes. One such
approach would be to store a pointer to the current end of list for each node and perform list jumping.}{\f1\insrsid2186746
\f1\insrsid2521923 here }{\f1\insrsid14363947
since nodes have only one previous and next link. These are typically quite short and overall run time of this entire step is not a problem in practice (7ms for 5000 files), so we do not attempt more efficient and sophisticat
ed cycle detection schemes. One such approach would be to store a pointer to the current end of list for each node and perform list jumping.}{\f1\insrsid2186746
\par }{\f1\insrsid14363947
\par The result of this step is a set of disjoint }{\f1\insrsid2521923 chains}{\f1\insrsid14363947 , which are each a series of files that are to be stored immediately after one another. Due to the na
ture of the edge list, the files that are most frequently accessed after one another are grouped together. As such, we have attained a }{\f1\insrsid2186746 good }{\f1\insrsid2521923 a}{\f1\insrsid2186746 pproximation of an optimal tour.
\par The result of this step is a set of disjoint }{\f1\insrsid2521923 chains}{\f1\insrsid14363947 , which are each a series of files that are to be stored immedi
ately after one another. Due to the nature of the edge list, the files that are most frequently accessed after one another are grouped together. As such, we have attained a }{\f1\insrsid2186746 good }{\f1\insrsid2521923 a}{\f1\insrsid2186746
pproximation of an optimal tour.
\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid11157276 {\f1\insrsid12716889
\par }{\f1\insrsid14363947 Note: now the reason for the most-recent-first program run ordering becomes clear
. All but the most frequent edges are placed into the list in the order that they occurred in the trace (due to stable sort). Since they are also committed in the DAG}{\f1\insrsid2521923 in this order, they end up mostly as observed}{\f1\insrsid14363947
}{\f1\insrsid2521923 from the trace. Since the most recent trace is assumed to be the most accurate and reflective of current behavior, it is given the most weight (by allowing all edges that ensued from it to be committed first).}{\f1\insrsid14363947
\par }{\f1\insrsid14363947 Note: now the reason for the most-recent-fi
rst program run ordering becomes clear. All but the most frequent edges are placed into the list in the order that they occurred in the trace (due to stable sort). Since they are also committed in the DAG}{\f1\insrsid2521923
in this order, they end up mostly as observed}{\f1\insrsid14363947 }{\f1\insrsid2521923 from
the trace. Since the most recent trace is assumed to be the most accurate and reflective of current behavior, it is given the most weight (by allowing all edges that ensued from it to be committed first).}{\f1\insrsid14363947
\par }{\f1\insrsid12716889
\par }{\f1\insrsid2521923 5: Stitch Chain}{\f1\insrsid2556592 s}{\f1\insrsid2521923 together}{\f1\insrsid12716889
\par
\par }{\f1\insrsid2521923 The final step is to stitch together the disjoint chains and
output them into the final ordered list. File nodes will be marked once they have been output. We iterate over all nodes and output the entire chain of which it is a part; this is done by following the node\rquote
\par }{\f1\insrsid2521923 The final step is to st
itch together the disjoint chains and output them into the final ordered list. File nodes will be marked once they have been output. We iterate over all nodes and output the entire chain of which it is a part; this is done by following the node\rquote
s previous link until at beginning of the chain.
\par Incidentally, this iteration ensures all files appear in the output list, even if they were not included in the trace.
\par }{\f1\insrsid12716889
@ -326,9 +328,9 @@ s previous link until at beginning of the chain.
\par }{\f1\insrsid6831581 This is an approximation to a variant of the Traveling Salesman Problem; the question as to its quality (i.e. how many seeks are avoided) is interesting and will be examined in }{\f1\insrsid12547006 <<}{\f1\insrsid6831581 section 3}{
\f1\insrsid12547006 >>}{\f1\insrsid6831581 .
\par }{\f1\insrsid4994568
\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid4994568 {\f1\insrsid4994568 Rough complexity analysis: except for the cycle d
etermination, none of these steps require more than O(logN) work per file. Expected case is therefore O(N*logN), with O(N^2) work in the worst case (if DFS always scans through very long chains). However, as mentioned above, this is an offline process; pe
rformance is entirely adequate, so we do not delve into a complete analysis or optimize the cycle determination step.
\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid4994568 {\f1\insrsid4994568 Rough compl
exity analysis: except for the cycle determination, none of these steps require more than O(logN) work per file. Expected case is therefore O(N*logN), with O(N^2) work in the worst case (if DFS always scans through very long chains). However, as mentioned
above, this is an offline process; performance is entirely adequate, so we do not delve into a complete analysis or optimize the cycle determination step.
\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid1770144 {\f1\insrsid1770144
\par }{\f1\insrsid4994568
\par }{\f1\insrsid1770144 Splitting Into Blocks
@ -368,7 +370,7 @@ ally split into blocks (of aligned start position and length) and issued asynchr
\par }{\f1\insrsid12675798 Caching}{\f1\insrsid1770144
\par }{\f1\insrsid12675798
\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid15489891 {\f1\insrsid15489891\charrsid15489891 It's not true that life is one damn thing after another; it is one damn thing over and over.
\par - Edna St. Vincent Millay
\par -}{\f1\insrsid10617934 -}{\f1\insrsid15489891\charrsid15489891 Edna St. Vincent Millay
\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid11157276 {\f1\insrsid15489891
\par }{\f1\insrsid12675798 The final step we take in optimizing}{\f1\insrsid6842252 I/O}{\f1\insrsid12675798 is caching. By keeping commonly used files in memory, some }{\f1\insrsid15489891 repeated}{\f1\insrsid6842252 I/Os}{\f1\insrsid12675798
can be avoided outright.
@ -502,16 +504,16 @@ e-sorted after an item is accessed, which increases its credit. Due to limitatio
\par }{\f1\insrsid9206128 Methodology
\par
\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid9206128 {\f1\insrsid6762521 The basis for our I/O throughput measurement is}{\f1\insrsid9206128
a trace file recorded from the startup of 0ad encompassing ~500 file loads. Using the trace simulation feature described above, we issue these}{\f1\insrsid6842252 I/Os}{\f1\insrsid9206128
as fast as possible; this removes the influence of other system-specific conditions such as graphics card performance etc.
a trace file recorded from the startup of 0ad encompassing ~500 file loads. Using the trace simulation feature described above, we issue these}{\f1\insrsid6842252 I/Os}{\f1\insrsid9206128 as }{\f1\insrsid8400636 quickly}{\f1\insrsid9206128
as possible; this removes the influence of other system-specific conditions such as graphics card performance etc.
\par
\par What is actually measured is the total amount of time elapsed between start and end of}{\f1\insrsid6842252 I/Os}{\f1\insrsid9206128 ; this together with the amount of user data transferred yields effective throughput (\'93effective\'94
because it differs from the actual disk throughput due to compression).
\par }{\f1\insrsid2424877
\par }{\f1\insrsid9206128 This was chosen as the benchmark measure because it reflects real-world performance of the entire system.
\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid12675798 {\f1\insrsid9206128
\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid6762521 {\f1\insrsid6762521 Note: if a cache is involved, we ensure it is empty so as not to skew results; in the case of the OS file cache, testing takes place after
a clean reboot.
\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid6762521 {\f1\insrsid6762521 Note: if a cache i
s involved, we ensure it is empty so as not to skew results; in the case of the OS file cache, testing takes place after a clean reboot.
\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid12675798 {\f1\insrsid6762521
\par }{\f1\insrsid9206128 Results and Discussion
\par
@ -528,8 +530,8 @@ e-sorted after an item is accessed, which increases its credit. Due to limitatio
\par }{\f1\insrsid16475960 When archives are disabled entirely and}{\f1\insrsid6842252 I/O}{\f1\insrsid16475960 is from loose }{\f1\insrsid12547006 files }{\f1\insrsid16475960 (stored in the }{\f1\insrsid12547006 normal files}{\f1\insrsid16475960
ystem), performance drops to }{\f1\insrsid4937740 2.62 MB/s. The immediate conclusion is that reduced locality (due to poor FS ordering and extra headers) induces many costly seeks.
\par }{\f1\insrsid16475960 We }{\f1\insrsid4937740 also }{\f1\insrsid16475960 notice that }{\f1\insrsid4937740 performance is worse }{\f1\insrsid16475960 than th}{\f1\insrsid4937740 at}{\f1\insrsid16475960
measured for the synchronous API; this could be explained by increased overhead of the aio APIs. Indeed, }{\f1\insrsid4937740 they do not support the Windows FastIO entry points that avoid needing to create a driver request packet.}{\f1\insrsid16475960
measured for the synchronous API; this could be explained by increased overhead of the aio APIs. Indeed, }{\f1\insrsid4937740 they do not support the Windows FastIO }{\f1\insrsid8400636 driver }{\f1\insrsid4937740 entry points}{\f1\insrsid8400636
that avoid needing to build an I/O }{\f1\insrsid4937740 request packet.}{\f1\insrsid16475960
\par }{\f1\insrsid4937740
\par Finally, we revisit the question of file block size. The initial choice of 16 KiB was not optimal; based on the following results, we go with 32 KiB.
\par Block Size (KiB)\tab Th}{\f1\insrsid9206128 r}{\f1\insrsid4937740 oughput (MB/s)
@ -538,32 +540,66 @@ ystem), performance drops to }{\f1\insrsid4937740 2.62 MB/s. The immediate concl
\par 32\tab \tab \tab 29.3
\par 64\tab \tab \tab 29.1
\par 128\tab \tab \tab 23.3}{\f1\insrsid4937740
\par It is interesting that performance }{\f1\insrsid2424877 begins to}{\f1\insrsid4937740 falls off }{\f1\insrsid2424877 starting with }{\f1\insrsid4937740
64 KiB blocks. This might be explained by transfers needing to be split due to the previously mentioned scatter-gather list limit, but this is speculation.}{\f1\insrsid4937740\charrsid4937740
\par It is interesting that performance }{\f1\insrsid2424877 begins to}{\f1\insrsid4937740 falls off }{\f1\insrsid2424877 starting with }{\f1\insrsid4937740 64 KiB blocks. }{\f1\insrsid12262430 An explanation might be that }{\f1\insrsid4937740 transfers }{
\f1\insrsid12262430 are }{\f1\insrsid4937740 split }{\f1\insrsid12262430 up }{\f1\insrsid4937740 due to the previously mentioned scatter-gather list limit, but this is speculation.}{\f1\insrsid4937740\charrsid4937740
\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid12675798 {\f1\insrsid9206128
\par In summary, we have found that bundling files into archives is the most worthwhile improvement, due to reducing seeks. Once these are eliminated, the increased throughput afforded by the (free) data compression step contributes an additional 23 % speedup.
\par }{\f1\insrsid5980580
\par }{\f1\insrsid14426874 Ordering Quality
\par
\par The above result indirectly shows that storing files in archives manages to avoid numerous seeks; else throughput would not be so high. We now examine exactly how many are incurred, thus evaluating the
quality of the archive ordering and its TSP heuristic.
\par
\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid1911773 {\f1\insrsid5245032 To measure total seek impact, we must first define their cost}{\f1\insrsid1911773 .}{\f1\insrsid5245032 S}{\f1\insrsid1911773
hort seeks may actually be free because the HD controller has already read the target data into its cache. Also, long seeks may be more expensive due to physical limitations of the disk head (it must accelerate/decelerate to/from
maximum velocity and then }{\f1\insrsid5245032 settle on the target track).
\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid12675798 {\f1\insrsid1911773 A }{\f1\insrsid5245032 good }{\f1\insrsid1911773 model}{\f1\insrsid5245032 for }{\f1\insrsid1911773 this
would be a constant overhead plus cost proportional to the seek distance}{\f1\insrsid5245032 , plus rotational latency}{\f1\insrsid1911773 .}{\f1\insrsid5245032 However, this is quite disk-dependent and difficult to determine. For simplic
ity, we currently assume uniform cost and try to avoid all seeks.
\par
\par }{\f1\insrsid5906787 Our }{\f1\insrsid14426874 first step in measuring }{\f1\insrsid5906787 them is }{\f1\insrsid14426874 to record a trace of 3 different 0ad startup sequences, each loading a separate map
(which share some files but differ in others, e.g. environment textures). This }{\f1\insrsid8805545 large }{\f1\insrsid14426874 trace }{\f1\insrsid8805545 consisting of ~2300 loads }{\f1\insrsid14426874 is used to guide creation of an archive. We then
count the seeks incurred by each of the individual sequences }{\f1\insrsid6382957 \endash this is }{\f1\insrsid14426874 easily done in our code by comparing current }{\f1\insrsid8805545 I/O }{\f1\insrsid14426874 file and offset with the last known values
.
\par }{\f1\insrsid1911773
\par }{\f1\insrsid14426874 For the combined trace, }{\f1\insrsid6382957 no }{\f1\insrsid14426874 seeks are }{\f1\insrsid6382957 observed}{\f1\insrsid5906787 }{\f1\insrsid14426874 (}{\f1\insrsid1911773 2}{\f1\insrsid14426874 ). This is }{\f1\insrsid6382957
as expected }{\f1\insrsid14426874 because the archive was specifically ordered for that sequence.
\par }{\f1\insrsid5053763 The individual \'93Cantabrian Highlands\'94 and \'93Neareastern\'94 map sequences incur }{\f1\insrsid6382957 only }{\f1\insrsid12663892 49}{\f1\insrsid5053763 (}{\f1\insrsid12663892 9.4}{\f1\insrsid5053763 % of total I/O requests)
and 6}{\f1\insrsid12663892 0}{\f1\insrsid5053763 (1}{\f1\insrsid12663892 0.6}{\f1\insrsid5053763 %) seeks, respectively.}{\f1\insrsid8805545 (}{\f1\insrsid1911773 3}{\f1\insrsid8805545 )}{\f1\insrsid5053763
\par }{\f1\insrsid8805545
\par }{\f1\insrsid5053763 These positive results justify our decision to use }{\f1\insrsid12262430 a }{\f1\insrsid5053763 heuristic}{\f1\insrsid12262430 to approximate TSP}{\f1\insrsid5053763 . Because the access patterns
induced by separate maps differ widely, insisting on }{\f1\insrsid12663892 an optimal ordering for one particular pattern does not make sense. Instead, this heuristic produces good results for a variety of maps.}{\f1\insrsid5053763
\par
\par }{\f1\insrsid1911773 2}{\f1\insrsid6382957 )}{\f1\insrsid14426874 we have excluded }{\f1\insrsid5906787 4 }{\f1\insrsid14426874 unavoidable seeks that are unrelated to the archive ordering, namely 1 during the course of opening the Zi
p file (reading ECDR and then Central Directory) and 3 due to files that cannot be added to an archive.
\par
\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid8805545 {\f1\insrsid1911773 3}{\f1\insrsid6382957 )}{\f1\insrsid8805545 it may be surprising that subsequences of the trace incur seeks, while the whole does not. }{
\f1\insrsid12262430 The explanation is that }{\f1\insrsid5906787 our }{\f1\insrsid12262430 file cache also serves to avoid seeks. To see this, consider the following simple example:}{\f1\insrsid8805545
\par }{\f1\insrsid12262430 trace = AB|AC|AD, optimal ordering = ABCD. For the entire trace, the file cache will absorb the latter two A accesses, whereas the subsequences AC }{\f1\insrsid5906787 and AD }{\f1\insrsid12262430 each incur a seek.
\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid12675798 {\f1\insrsid8805545
\par }{\f1\insrsid6382957
\par }{\f1\insrsid6762521 Caching Efficacy
\par
\par We now appraise the effectiveness of the cache replacement policy, i.e. its tendency to keep items in memory that will be needed later. To measure this, }{\f1\insrsid1516560 we record a }{\f1\insrsid6762521 trace of 3 different 0ad startup sequences
, each loading a separate map (which share some files but differ in others, e.g. environment textures).}{\f1\insrsid1516560 It comprises 57 MB of data, of which 14 are repeated and therefore potentially cacheable.}{\f1\insrsid6762521
\par We now appraise the effectiveness of the cache replacement policy, i.e. its tendency to keep }{\f1\insrsid12663892 files }{\f1\insrsid6762521 in memory that will be needed later. }{\f1\insrsid12663892 To measure this, we simulate cache operation over the
combined trace mentioned above. }{\f1\insrsid1516560 It comprises 57 MB of data, of which 14 are repeated and therefore potentially cacheable.}{\f1\insrsid6762521
\par
\par S}{\f1\insrsid1516560 ince this trace and the}{\f1\insrsid6762521 0ad dataset }{\f1\insrsid1516560 are}{\f1\insrsid6762521 }{\f1\insrsid1516560 as }{\f1\insrsid6762521 yet relatively small}{\f1\insrsid1516560 (real-world cache sizes may well be larger)
}{\f1\insrsid6762521 , we have artificially }{\f1\insrsid7279159 limited}{\f1\insrsid6762521 the cache size to ensure that items will have to be evicted from the cache}{\f1\insrsid1516560 . Without this, the cache replacement policy would be irrelevant.
A size of 10 MB has been chosen arbitrarily.}{\f1\insrsid6762521
\par S}{\f1\insrsid1516560 ince the}{\f1\insrsid6762521 0ad dataset }{\f1\insrsid5906787 is }{\f1\insrsid1516560 as }{\f1\insrsid6762521 yet relatively small}{\f1\insrsid1516560 (real-world cache sizes may well be larger)}{\f1\insrsid6762521
, we have artificially }{\f1\insrsid7279159 limited}{\f1\insrsid6762521 the cache size to ensure that items will have to be evicted from the cache}{\f1\insrsid1516560 . Without this}{\f1\insrsid12262430 }{\f1\insrsid5906787 action}{\f1\insrsid1516560
, the cache replacement policy would be irrelevant. A size of 10 MB has been chosen arbitrarily.}{\f1\insrsid6762521
\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid2424877 {\f1\insrsid1516560
\par We first }{\f1\insrsid9524216 evaluate the }{\f1\insrsid1516560 well-known LRU algorithm}{\f1\insrsid9524216 under these conditions}{\f1\insrsid1516560 . }{\f1\insrsid9524216 The cache h}{\f1\insrsid1516560 it rate is }{\f1\insrsid9524216
determined to be }{\f1\insrsid1516560 19 % (473 hits totaling 6.18 MB vs. 1915 misses totaling 51.22 MB).
\par }{\f1\insrsid9524216 Our Landlord implementation more }{\f1\insrsid1516560 than doubles }{\f1\insrsid9524216 this }{\f1\insrsid1516560 to 39 % (}{\f1\insrsid1516560\charrsid1516560 945 }{\f1\insrsid1516560 hits totaling }{
\f1\insrsid1516560\charrsid1516560 8.88}{\f1\insrsid1516560 }{\f1\insrsid1516560\charrsid1516560 MB}{\f1\insrsid1516560 vs. }{\f1\insrsid1516560\charrsid1516560 1443 }{\f1\insrsid1516560 misses totaling }{\f1\insrsid1516560\charrsid1516560 48.52 MB)}{
\f1\insrsid9524216 .}{\f1\insrsid1516560
\par }{\f1\insrsid9524216 A more intuitive view of these numbers is that the percentage of non-compulsory misses (i.e. items that were evicted but referenced later) drops from 26 % to 2 %.}{\f1\insrsid9524216\charrsid1516560
\par }{\f1\insrsid9524216 A more intuitive view of these numbers is that the percentage of non-compulsory misses (i.e. }{\f1\insrsid12663892 files}{\f1\insrsid9524216 that were evicted but }{\f1\insrsid12663892 needed }{\f1\insrsid9524216
later) drops from 26 % to 2 %.}{\f1\insrsid9524216\charrsid1516560
\par }{\f1\insrsid1516560
\par }{\f1\insrsid9524216 We are pleasantly surprised by this favorable result. Since our implementation does not yet take advantage of file cost hints from the application, the difference }{\f1\insrsid7279159 in performance }{\f1\insrsid9524216 is due }{
\f1\insrsid7279159 solely }{\f1\insrsid9524216 to the Landlord algorithm\rquote s awareness of item size. This apparently leads to more efficient handling of the cache memory}{\f1\insrsid7279159 : fewer files need
be evicted to make enough room for the next item.
\par Another factor is that the repeated files in this trace are spaced widely apart (e.g. at the start of all 3 map loads constituting the trace); LRU would tend to remove exactly these items.
\f1\insrsid7279159 solely }{\f1\insrsid9524216 to the Landlord algorithm\rquote s awareness of item size. This apparently leads to more efficient handling of the cache memory}{\f1\insrsid7279159 : fewer files
need be evicted to make enough room for the next item.
\par Another factor is that the repeated files in this trace are spaced widely apart (e.g. at the start of }{\f1\insrsid12663892 each of the }{\f1\insrsid7279159 3 map loads constituting the trace); LRU would tend to remove exactly these items.
\par }{\f1\insrsid1516560
\par }{\f1\insrsid2424877 Cache Manager Optimizations
\par
@ -593,31 +629,12 @@ at this result is heavily dependent on the relative frequency of add and remove
\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid12675798 {\f1\insrsid15160866
\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid5048634 {\f1\insrsid5048634 Allocator Fragmentation
\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid12675798 {\f1\insrsid2424877
\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid5048634 {\f1\insrsid5048634 The important question of allocator fragmentation is next. We gauge it in the course of simulating the previous 500-file trace. A sim
ple and adequate measure is to compare the total requested size with how much of the total file cache is actually occupied.}{\f1\insrsid1847956
The result is a total memory waste of 14 %, which is in line with the findings of [Johnstone and Wilson]. While not great, this is acceptable.}{\f1\insrsid5048634
\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid5048634 {\f1\insrsid5048634 The important
question of allocator fragmentation is next. We gauge it in the course of simulating the previous 500-file trace. A simple and adequate measure is to compare the total requested size with how much of the total file cache is actually occupied.}{
\f1\insrsid1847956 The result is a total memory waste of 1}{\f1\insrsid12262430 2}{\f1\insrsid1847956 %, which is in line with the findings of [Johnstone and Wilson]. While not great, this is acceptable.}{\f1\insrsid5048634
\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid12675798 {\f1\insrsid5048634
\par }{\f1\insrsid9206128
\par }{\f1\insrsid5980580 Ordering Quality
\par
\par .. seeks (seen in}{\f1\insrsid6842252 I/O}{\f1\insrsid5980580 throughput results)
\par
\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid13779256 {\f1\insrsid13779256\charrsid13779256 paging volume; # disk hits (decides quality of cache); # seeks (decides quality of ordering)
\par #seeks is interesting, but may be more interesting to count total jump distance (short seeks cheap?)
\par remember disk prefetcher! 8mb cache; may already have read ahead! cost = const overhead+ constant
\par accel up to max speed; slow down; the move exactly to track position (constant) AND THEN rotational delay
\par \tab this is more for prefetching - blows the scope.}{\f1\insrsid5980580
\par }{\f1\insrsid13779256
\par
\par }{\f1\insrsid13779256\charrsid13779256 count total weight of TSP weights * their cost; compare to total weights; that is savings in seeks
\par does that apply to runs that weren't trained?
\par split into 2 halves; train with one, test with other. not only one instance
\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid12675798 {\f1\insrsid8848513 obviously performance }{\f1\insrsid16411143 will }{\f1\insrsid8848513
suffer because current scheme is 100% dependent *on having seen* the correct ordering before.}{\f1\insrsid1847956
\par
\par
\par
\par }{\f1\insrsid13779256 Conclusion}{\f1\insrsid1847956
\par }{\f1\insrsid1911773 C}{\f1\insrsid13779256 onclusion}{\f1\insrsid1847956
\par }{\f1\insrsid3546591
\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid5968267 {\f1\insrsid5968267 Waiting for slow}{\f1\insrsid6842252 I/O}{\f1\insrsid5968267
is the bane of many a computer user; we have shown that this need not be and can be mitigated to a large degree.
@ -633,7 +650,7 @@ synchronous access maximizes read throughput and (together with block-splitting)
\par }{\f1\insrsid5968267
\par Other applications can build on our work and easily speed up their load times and file accesses.
\par
\par }{\f1\insrsid3546591
\par }{\f1\insrsid6382957
\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid6826037 {\f1\insrsid6826037 Implementation
\par
\par Our}{\f1\insrsid6842252 I/O}{\f1\insrsid6826037 code has been developed in C++ and also contains a few time-critical assembly language subroutines. It encompasses about 12000 lines of code, about 7K of which are new; the
@ -641,6 +658,22 @@ synchronous access maximizes read throughput and (together with block-splitting)
\par Unfortunately there are dependencies on another ~30KLOC, so releasing and integrating into other applications is not as easy as it could be; this is being worked upon.
\par }{\f1\insrsid5710756 Eventually releasing the code }{\f1\insrsid6826037 under the GNU General Public License (Free Software)}{\f1\insrsid5710756 is planned}{\f1\insrsid6826037 .
\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid12675798 {\f1\insrsid3546591
\par }{\f1\insrsid6382957
\par }{\f1\insrsid10617934 Lessons Learned
\par
\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid10617934 {\f1\insrsid10617934\charrsid10617934 Experience is what you get when you don't get what you want.
\par }{\f1\insrsid10617934 -- }{\f1\insrsid10617934\charrsid10617934 Dan Stanford}{\f1\insrsid10617934\charrsid10617934
\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid12675798 {\f1\insrsid10617934
\par Despite application of Software Engineering best-practices such as careful modularization, built-in self tests and pre/postcondition guards, the defect rate was unpleasantly high. This may be the norm for low-level C++
codebases of the above size, but was a problem given that file loading is a critical part of the application.
\par The takeaway is that more self-tests and condition checking can be recommended }{\f1\insrsid10176575 unreservedly \endash they exposed many bugs.}{\f1\insrsid10617934
\par
\par The trace functionality (recording all I/Os) was }{\f1\insrsid10176575 found to be }{\f1\insrsid10617934 quite valuable. }{\f1\insrsid10176575 Besides its immediate application of ordering files, i}{\f1\insrsid10617934
t allows testing I/O performance under repeatable conditions}{\f1\insrsid10176575 and}{\f1\insrsid10617934 reproducing bugs}{\f1\insrsid10176575 .}{\f1\insrsid10617934
\par }{\f1\insrsid10176575
\par On a final positive note, }{\f1\insrsid6382957 much room for improvement was to be had with I/O! The gains achieved were surprising.}{\f1\insrsid10176575
\par }{\f1\insrsid10617934
\par
\par }{\f1\insrsid13779256 Future Direction}{\f1\insrsid3546591 s}{\f1\insrsid13779256
\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid13779256 {\f1\insrsid3546591
\par }{\f1\insrsid5710756 We have further ideas for improvement that could not yet be implemented due to time constraints.
@ -661,19 +694,127 @@ is stored, anyway).
\par }{\f1\insrsid16678464
\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid13779256 {\f1\insrsid13779256 Bibliography}{\f1\insrsid13779256\charrsid13779256
\par }{\f1\insrsid13779256
\par }{\f1\insrsid13779256\charrsid13779256 online file caching
\par survey of web replacement strategies
\par 3level caching for efficient query processing in large web search engines
\par new results on web caching with request reordering
\par The Memory Fragmentation Problem - Solved
\par Dynamic Storage Allocation - A Survey and Critical Review
\par description of the TLSF memory allocator
\par a performance study of sequential I/O on windows NT 4
\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid15098734 {\f1\insrsid15098734\charrsid15098734 0 A.D. www.wildfiregames.com/0ad
\par
\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid12675798 {\f1\insrsid1847956
\par @Article\{SleTar85,
\par author ="Sleator and Tarjan",
\par title ="Amortized Efficiency of List Update and Paging Rules",
\par journal ="CACM: Communications of the ACM",
\par volume ="28",
\par year = "1985",
\par \}
\par
\par @Article\{Irani02,
\par author ="Irani",
\par title ="Page Replacement with Multi-Size Pages and
\par Applications to Web Caching",
\par journal ="ALGRTHMICA: Algorithmica",
\par volume ="33",
\par year = "2002",
\par \}
\par
\par @InProceedings\{conf/soda/Young98,
\par title ="On-Line File Caching",
\par author ="Neal E. Young",
\par year = "1998",
\par bibdate ="2002-12-09",
\par bibsource ="DBLP,
\par http://dblp.uni-trier.de/db/conf/soda/soda98.html#Young98",
\par booktitle ="SODA",
\par pages ="82--86",
\par \}
\par
\par @InProceedings\{conf/iwmm/WilsonJNB95,
\par title ="Dynamic Storage Allocation: \{A\} Survey and Critical
\par Review",
\par author ="Paul R. Wilson and Mark S. Johnstone and Michael Neely
\par and David Boles",
\par year = "1995",
\par bibdate ="2002-12-18",
\par bibsource ="DBLP,
\par http://dblp.uni-trier.de/db/conf/iwmm/iwmm95.html#WilsonJNB95",
\par booktitle ="IWMM",
\par crossref ="conf/iwmm/95",
\par pages ="1--116",
\par \}
\par
\par }{\f1\insrsid3629320
\par @Article\{JohWil99,
\par author ="Johnstone and Wilson",
\par title ="The Memory Fragmentation Problem: Solved?",
\par journal ="SPNOTICES: ACM SIGPLAN Notices",
\par volume ="34",
\par year = "1999",
\par \}
\par
\par @InProceedings\{conf/ecrts/MasmanoRCR04,
\par title ="\{TLSF\}: \{A\} New Dynamic Memory Allocator for Real-Time
\par Systems",
\par author ="Miguel Masmano and Ismael Ripoll and Alfons Crespo and
\par Jorge Real",
\par year = "2004",
\par bibdate ="2004-12-06",
\par bibsource ="DBLP,
\par http://dblp.uni-trier.de/db/conf/ecrts/ecrts2004.html#MasmanoRCR04",
\par booktitle ="ECRTS",
\par crossref ="conf/ecrts/2004",
\par }{\f1\lang1031\langfe1033\langnp1031\insrsid15098734\charrsid15098734 pages ="79--86",
\par URL = "http://doi.ieeecomputersociety.org/10.1109/ECRTS.2004.35",
\par }{\f1\insrsid15098734\charrsid15098734 \}
\par
\par DIMACS TSP Challenge http://public.research.att.com/~dsj/chtsp/
\par
\par @Article\{SW,
\par author ="D. B. Shmoys and D. P. Williamson",
\par title ="Analyzing the Held-Karp \{TSP\} bound: a monotonicity
\par property with application",
\par journal ="Information Processing Letters",
\par year = "1991",
\par volume ="37",
\par pages ="281--285",
\par \}
\par
\par PIO http://www.pcguide.com/ref/hdd/if/ide/modes_PIO.htm
\par
\par @TechReport\{P117,
\par author ="Jim Gray and Erik Riedel and Catharine Van Ingen",
\par title ="A Study of Windows \{NT\} Sequential \{IO\} Perforamnce",
\par institution = "Microsoft Research (MSR)",
\par number ="P117",
\par year = "1997",
\par month =sep,
\par URL = "http://research.microsoft.com/barc/Sequential_IO/default.htm",
\par \}
\par
\par @Misc\{oai:CiteSeerPSU:290934,
\par title ="Windows 2000 Disk \{IO\} Performance",
\par author ="Jim Gray and Bruce Worthington and Robert Horst",
\par year = "2000",
\par month =jun # "~05",
\par annote ="Jim Gray (Microsoft Research; Advanced Technology
\par Division; Microsoft Corporation; One Microsoft; Way;
\par Redmond , WA. 98052; Windows 2000 Disk IO Performance);
\par Bruce Worthington (Microsoft Research; Advanced
\par Technology Division; Microsoft Corporation; One
\par Microsoft; Way; Redmond , WA. 98052; Windows 2000 Disk
\par IO Performance); Robert Horst (Microsoft Research;
\par Advanced Technology Division; Microsoft Corporation;
\par One Microsoft; Way; Redmond , WA. 98052; Windows 2000
\par Disk IO Performance);",
\par bibsource ="OAI-PMH server at cs1.ist.psu.edu",
\par language ="en",
\par oai = "oai:CiteSeerPSU:290934",
\par rights ="unrestricted",
\par URL = "http://citeseer.ist.psu.edu/290934.html;
\par http://research.microsoft.com/~gray/papers/Win2K_IO_MSTR_2000_55.pdf",
\par \}
\par
\par RFC1951 http://rfc.net/rfc1951.html
\par
\par ZipAppNote http://www.pkware.com/business_and_developers/developer/appnote/
\par
\par ZipBenchmark http://archive.gamespy.com/hardware/june02/p45331/index2.shtm
\par
\par IO benchmark www.storagereview.com
\par
\par ASPI FAQ http://www.eetkorea.com/ARTICLES/2000APR/2000APR05_CT_ID_AN.PDF}{\f1\insrsid3629320\charrsid15098734
\par }}