diff options
author | Simon Marlow <simonmar@microsoft.com> | 2006-04-07 02:05:11 +0000 |
---|---|---|
committer | Simon Marlow <simonmar@microsoft.com> | 2006-04-07 02:05:11 +0000 |
commit | 0065d5ab628975892cea1ec7303f968c3338cbe1 (patch) | |
tree | 8e2afe0ab48ee33cf95009809d67c9649573ef92 /docs/storage-mgt | |
parent | 28a464a75e14cece5db40f2765a29348273ff2d2 (diff) | |
download | haskell-0065d5ab628975892cea1ec7303f968c3338cbe1.tar.gz |
Reorganisation of the source tree
Most of the other users of the fptools build system have migrated to
Cabal, and with the move to darcs we can now flatten the source tree
without losing history, so here goes.
The main change is that the ghc/ subdir is gone, and most of what it
contained is now at the top level. The build system now makes no
pretense at being multi-project, it is just the GHC build system.
No doubt this will break many things, and there will be a period of
instability while we fix the dependencies. A straightforward build
should work, but I haven't yet fixed binary/source distributions.
Changes to the Building Guide will follow, too.
Diffstat (limited to 'docs/storage-mgt')
27 files changed, 6529 insertions, 0 deletions
diff --git a/docs/storage-mgt/Makefile b/docs/storage-mgt/Makefile new file mode 100644 index 0000000000..871766d4fc --- /dev/null +++ b/docs/storage-mgt/Makefile @@ -0,0 +1,37 @@ +# General makefile for Latex stuff + +dvi: sm.dvi rp.dvi ldv.dvi +ps: sm.ps rp.ps ldv.ps + +######## General rules +.SUFFIXES: +.PRECIOUS: %.tex %.ps %.bbl + +#%.dvi: %.tex $(addsuffix .tex, $(basename $(wildcard *.verb *.fig))) $(wildcard *.bib) +%.dvi: %.tex $(addsuffix .tex, $(basename $(wildcard *.verb))) $(wildcard *.bib) + latex $< + @if grep -s "\citation" $*.aux; then bibtex $*; fi + latex $< + latex $< + +%.ps: %.dvi + dvips -f < $< > $@ + +clean: + $(RM) *.aux *.log + +distclean: clean + $(RM) *.dvi *.ps *.bbl *.blg *.gz + +maintainer-clean: distclean + +# dummy targets +all: +boot: +install: +install-docs: +html: +chm: +HxS: + +# End of file diff --git a/docs/storage-mgt/architecture.eepic b/docs/storage-mgt/architecture.eepic new file mode 100644 index 0000000000..57ffd8fc99 --- /dev/null +++ b/docs/storage-mgt/architecture.eepic @@ -0,0 +1,55 @@ +\setlength{\unitlength}{0.00054167in} +% +\begingroup\makeatletter\ifx\SetFigFont\undefined% +\gdef\SetFigFont#1#2#3#4#5{% + \reset@font\fontsize{#1}{#2pt}% + \fontfamily{#3}\fontseries{#4}\fontshape{#5}% + \selectfont}% +\fi\endgroup% +{\renewcommand{\dashlinestretch}{30} +\begin{picture}(5787,4014)(0,-10) +\path(2700,912)(5325,912)(5325,1212) + (2700,1212)(2700,912) +\path(2850,12)(5100,12)(5100,312) + (2850,312)(2850,12) +\path(2700,1812)(5325,1812)(5325,2112) + (2700,2112)(2700,1812) +\path(3825,2712)(5700,2712)(5700,3012) + (3825,3012)(3825,2712) +\path(3825,3687)(5625,3687)(5625,3987) + (3825,3987)(3825,3687) +\path(2625,3687)(3825,3687)(3825,3987) + (2625,3987)(2625,3687) +\path(3795.000,3357.000)(3825.000,3237.000)(3855.000,3357.000) +\path(3825,3237)(3825,3687) +\path(3855.000,3567.000)(3825.000,3687.000)(3795.000,3567.000) +\path(3795.000,1332.000)(3825.000,1212.000)(3855.000,1332.000) +\path(3825,1212)(3825,1812) +\path(3855.000,1692.000)(3825.000,1812.000)(3795.000,1692.000) +\path(1875,3237)(5775,3237)(5775,762) + (1875,762)(1875,3237) +\path(3855.000,642.000)(3825.000,762.000)(3795.000,642.000) +\path(3825,762)(3825,312) +\path(3795.000,432.000)(3825.000,312.000)(3855.000,432.000) +\path(2025,2712)(3525,2712)(3525,3012) + (2025,3012)(2025,2712) +\path(3195.000,2232.000)(3225.000,2112.000)(3255.000,2232.000) +\path(3225,2112)(3225,2712) +\path(3255.000,2592.000)(3225.000,2712.000)(3195.000,2592.000) +\path(4320.000,2232.000)(4350.000,2112.000)(4380.000,2232.000) +\path(4350,2112)(4350,2712) +\path(4380.000,2592.000)(4350.000,2712.000)(4320.000,2592.000) +\path(3525,2937)(3825,2937) +\path(3705.000,2907.000)(3825.000,2937.000)(3705.000,2967.000) +\path(3825,2787)(3525,2787) +\path(3645.000,2817.000)(3525.000,2787.000)(3645.000,2757.000) +\put(3225,1887){\makebox(0,0)[lb]{\smash{{{\SetFigFont{8}{9.6}{\rmdefault}{\mddefault}{\updefault}block allocator}}}}} +\put(3000,987){\makebox(0,0)[lb]{\smash{{{\SetFigFont{8}{9.6}{\rmdefault}{\mddefault}{\updefault}megablock allocator}}}}} +\put(3150,87){\makebox(0,0)[lb]{\smash{{{\SetFigFont{8}{9.6}{\rmdefault}{\mddefault}{\updefault}operating system}}}}} +\put(2700,3762){\makebox(0,0)[lb]{\smash{{{\SetFigFont{8}{9.6}{\rmdefault}{\mddefault}{\updefault}mutatator}}}}} +\put(3900,3762){\makebox(0,0)[lb]{\smash{{{\SetFigFont{8}{9.6}{\rmdefault}{\mddefault}{\updefault}runtime system}}}}} +\put(2100,2787){\makebox(0,0)[lb]{\smash{{{\SetFigFont{8}{9.6}{\rmdefault}{\mddefault}{\updefault}heap allocator}}}}} +\put(3975,2787){\makebox(0,0)[lb]{\smash{{{\SetFigFont{8}{9.6}{\rmdefault}{\mddefault}{\updefault}garbage collector}}}}} +\put(0,1962){\makebox(0,0)[lb]{\smash{{{\SetFigFont{8}{9.6}{\rmdefault}{\mddefault}{\updefault}storage manager}}}}} +\end{picture} +} diff --git a/docs/storage-mgt/architecture.fig b/docs/storage-mgt/architecture.fig new file mode 100644 index 0000000000..563da78a53 --- /dev/null +++ b/docs/storage-mgt/architecture.fig @@ -0,0 +1,59 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +65.00 +Single +-2 +1200 2 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 2400 4200 5025 4200 5025 3900 2400 3900 2400 4200 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 2550 5100 4800 5100 4800 4800 2550 4800 2550 5100 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 2400 3300 5025 3300 5025 3000 2400 3000 2400 3300 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 3525 2400 5400 2400 5400 2100 3525 2100 3525 2400 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 3525 1425 5325 1425 5325 1125 3525 1125 3525 1425 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 2325 1425 3525 1425 3525 1125 2325 1125 2325 1425 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 1 2 + 0 0 1.00 60.00 120.00 + 0 0 1.00 60.00 120.00 + 3525 1875 3525 1425 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 1 2 + 0 0 1.00 60.00 120.00 + 0 0 1.00 60.00 120.00 + 3525 3900 3525 3300 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 1575 1875 5475 1875 5475 4350 1575 4350 1575 1875 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 1 2 + 0 0 1.00 60.00 120.00 + 0 0 1.00 60.00 120.00 + 3525 4350 3525 4800 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 1725 2400 3225 2400 3225 2100 1725 2100 1725 2400 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 1 2 + 0 0 1.00 60.00 120.00 + 0 0 1.00 60.00 120.00 + 2925 3000 2925 2400 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 1 2 + 0 0 1.00 60.00 120.00 + 0 0 1.00 60.00 120.00 + 4050 3000 4050 2400 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 3225 2175 3525 2175 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 3525 2325 3225 2325 +4 0 0 50 0 0 12 0.0000 4 135 1110 2925 3225 block allocator\001 +4 0 0 50 0 0 12 0.0000 4 180 1515 2700 4125 megablock allocator\001 +4 0 0 50 0 0 12 0.0000 4 180 1305 2850 5025 operating system\001 +4 0 0 50 0 0 12 0.0000 4 105 735 2400 1350 mutatator\001 +4 0 0 50 0 0 12 0.0000 4 180 1170 3600 1350 runtime system\001 +4 0 0 50 0 0 12 0.0000 4 180 1065 1800 2325 heap allocator\001 +4 0 0 50 0 0 12 0.0000 4 180 1305 3675 2325 garbage collector\001 +4 0 0 50 0 0 12 0.0000 4 150 1260 -300 3150 storage manager\001 diff --git a/docs/storage-mgt/cacheprof_p.eps b/docs/storage-mgt/cacheprof_p.eps new file mode 100644 index 0000000000..94d3a5d0c2 --- /dev/null +++ b/docs/storage-mgt/cacheprof_p.eps @@ -0,0 +1,2083 @@ +%!PS-Adobe-2.0 EPSF-1.2 +%%Title: cacheprof_p -ghc-timing +RTS -H10m -K10m -p -hR -i1.0 -sstderr +%%Creator: Ghostscript ps2epsi from cacheprof_p.ps +%%CreationDate: Aug 23 18:51 +%%For:t-spark t-spark +%%Pages: 1 +%%DocumentFonts: Helvetica +%%BoundingBox: 72 107 505 756 +%%BeginPreview: 433 649 1 649 +% ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80 +% 80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080 +% 80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080 +% 80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080 +% 80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080 +% 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001ffffffffff080 +% 80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000000000000000000000000000000000000000108000000084000000022000000022000000008000000000000000010000100001080 +% 800000000000000000000000100000000100000001cc0000000e600000006300000006300000000e000000000000000010420103c01080 +% 800000000000000000000000100000000100000001440000000a200000004900000004900000000b000000000000000010738106601080 +% 800000000000000000000003f80000003f800000012400000009200000004900000004900000003f800000000000000010588104201080 +% 8000000000000000000000000000000000000000011800000008c00000003e00000003e000000008000000000000000010488104201080 +% 800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000104c8106601080 +% 80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010478102401080 +% 800000000000000000000006000000006000000003000000001800000000c00000000c0000000060000000000000000010000100001080 +% 800000000000002c00000001e00000001600000000f000000005800000003c00000002c00000001e000000000000000010420107201080 +% 800000000000006f000000031800000037800000018c0000000de00000006300000006f000000031800000000000000010738105a01080 +% 8000000000000045000000020800000022800000010400000008a000000041000000045000000020800000000000000010588105a01080 +% 8000000000000045000000021800000022800000010c00000008a000000043000000045000000021800000000000000010488104a01080 +% 800000000000003900000001f00000001c80000000f800000007200000003e00000003900000001f0000000000000000104c8107e01080 +% 80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010478104001080 +% 800000000000003c00000001e00000001e00000000f000000007800000003c00000003c00000001e000000000000000010000103c01080 +% 8000000000000063000000031800000031800000018c0000000c6000000063000000063000000031800000000000000011c00106601080 +% 80000000000000410000000208000000208000000104000000082000000041000000041000000020800000000000000010800104201080 +% 8000000000000043000000021800000021800000010c000000086000000043000000043000000021800000000000000010000104201080 +% 800000000000003e00000001f00000001f00000000f800000007c00000003e00000003e00000001f000000000000000010000106601080 +% 800007800000003c00000001e00000001e00000000f000000007800000003c00000003c00000001e000000000000000010010102401080 +% 80000c6000000063000000031800000031800000018c0000000c6000000063000000063000000031800000000000000010010100001080 +% 800008200000004100000002080000002080000001040000000820000000410000000410000000208000000000000000107f8107fc1080 +% 8000086000000043000000021800000021800000010c000000086000000043000000043000000021800000000000000010000100201080 +% 800007c00000003e00000001f00000001f00000000f800000007c00000003e00000003e00000001f000000000200200010000100201080 +% 80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200200010070100201080 +% 80000fe00000007f00000003f80000003f80000001fc0000000fe00000007f00000007f00000003f8000000003c8ff7c106d8107e01080 +% 800003000000001800000000c00000000c000000006000000003000000001800000001800000000c000000000225396010488101801080 +% 800003000000001800000000c00000000c000000006000000003000000001800000001800000000c0000000002253f3810488103c01080 +% 83c006800000003400000001a00000001a00000000d000000006800000003400000003400000001a0000000003273944106d8104a01080 +% 863008000000004000000002000000002000000001000000000800000000400000000400000000200000000003c23f78103f0104a01080 +% 84100000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000010000104e01080 +% 8430080000000080000000040000000020000000010000000010000000008000000004000000002000000000000c000010000102c01080 +% 83e00800000000800000000400000000200000000100000000100000000080000000040000000020000000000000000010010100001080 +% 80000800000000800000000400000000200000000100000000100000000080000000040000000020000000000000000010010100001080 +% 800008000000008000000004000000002000000001000000001000000000800000000400000000200000000000000000107f813fe01080 +% 8400fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe10000106601080 +% 83c00f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000104201080 +% 86300e80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000106601080 +% 84100f60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000103c01080 +% 84300f98000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011c00100001080 +% 83e00fd6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010800100001080 +% 80000f61800000000000000000000000000000000000000000000000000000000000000000000000000000000000000010180107e01080 +% 80000ff14000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101c0100201080 +% 80000f68300000000000000000000000000000000000000000000000000000000000000000000000000000000000000010120100201080 +% 80000fd55c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000010118103c01080 +% 80000baa0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000107fc106601080 +% 80000b7591c000000000000000000000000000000000000000000000000000000000000000000000000000000000000010100104201080 +% 80000fd2c02000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000104201080 +% 80000ff7755800000000000000000000000000000000000000000000000000000000000000000000000000000000000010180106601080 +% 80000da9b006000000000000000000000000000000000000000000000000000000000000000000000000000000000000101c0103c01080 +% 80000dd5d95180000000000000000000000000000000000000000000000000000000000000000000000000000000000010120100201080 +% 80000df46c0040000000000000000000000000000000000000000000000000000000000000000000000000000000000010118107fc1080 +% 80000ddb7755700000000000000000000000000000000000000000000000000000000000000000000000000000000000107fc100241080 +% 80000dea2b000c000000000000000000000000000000000000000000000000000000000000000000000000000000000010100100001080 +% 80000df5559113000000000000000000000000000000000000000000000000000000000000000000000000000000000010180110001080 +% 80000cfcaac000c000000000000000000000000000000000000000000000000000000000000000000000000000000000101c0110001080 +% 80000dd4d57555600000000000000000000000000000000000000000000000000000000000000000000000000000000010120110001080 +% 80000cbe42b000180000000000000000000000000000000000000000000000000000000000000000000000000000000010118110001080 +% 80000d765759511600000000000000000000000000000000000000000000000000000000000000000000000000000000107fc110001080 +% 80000c7b21ac00018000000000000000000000000000000000000000000000000000000000000000000000000000000010100110001080 +% 80000f5d15d755556000000000000000000000000000000000000000000000000000000000000000000000000000000010000110001080 +% 80000e7a906b0000100000000000000000000000000000000000000000000000000000000000000000000000000000001000013fe01080 +% 80000f558d7591111c00000000000000000000000000000000000000000000000000000000000000000000000000000010000106601080 +% 80000e3fca2ac0000300000000000000000000000000000000000000000000000000000000000000000000000000000010000104201080 +% 80000f7d4555755555c0000000000000000000000000000000000000000000000000000000000000000000000000000010000106601080 +% 80000e2ee20ab00000300000000000000000000000000000000000000000000000000000000000000000000000000000107fc103c01080 +% 80000f7f635559515158000000000000000000000000000000000000000000000000000000000000000000000000000010660100001080 +% 80000e27b122ac000006000000000000000000000000000000000000000000000000000000000000000000000000000010420100001080 +% 80000f55515757555555800000000000000000000000000000000000000000000000000000000000000000000000000010660100001080 +% 80000e1ff081ab0000006000000000000000000000000000000000000000000000000000000000000000000000000000103c0100001080 +% 80000f155855d5d11111180000000000000000000000000000000000000000000000000000000000000000000000000010000100801080 +% 80000e13b8626aa00000040000000000000000000000000000000000000000000000000000000000000000000000000010020100801080 +% 80000f5fd435755555555700000000000000000000000000000000000000000000000000000000000000000000000000121e0100801080 +% 80000f0bac201aa8000000c000000000000000000000000000000000000000000000000000000000000000000000000011f00100001080 +% 80000f1f561555555111513000000000000000000000000000000000000000000000000000000000000000000000000010700103c01080 +% 80001f0bfa122aaa0000000c000000000000000000000000000000000000000000000000000000000000000000000000101e0136601080 +% 80002d5d550d55555555555600000000000000000000000000000000000000000000000000000000000000000000000010020124201080 +% 80004d05eb0402aa8000000180000000000000000000000000000000000000000000000000000000000000000000000010020124201080 +% 80008d15f585555511111111600000000000000000000000000000000000000000000000000000000000000000000000107f813fe01080 +% 80008d07bb8223aaa00000001000000000000000000000000000000000000000000000000000000000000000000000001042011fe01080 +% 80004f55758355557555555558000000000000000000000000000000000000000000000000000000000000000000000010180100001080 +% 80002f0bee8200aab0000000060000000000000000000000000000000000000000000000000000000000000000000000103c0100001080 +% 80001f5d758355d559515151510000000000000000000000000000000000000000000000000000000000000000000000104a0107fc1080 +% 80000f0bfb81206aa8000000008000000000000000000000000000000000000000000000000000000000000000000000104a0100201080 +% 80000f5d7581555555555555556000000000000000000000000000000000000000000000000000000000000000000000104e0100201080 +% 80000f09ea81002aaa000000001000000000000000000000000000000000000000000000000000000000000000000000102c0100201080 +% 80000f1d758155755711111111180000000000000000000000000000000000000000000000000000000000000000000010000107e01080 +% 80000f0bbb80a23aab00000000060000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000f5d7580d55555d55555555500000000000000000000000000000000000000000000000000000000000000000000106e0103c01080 +% 80000f19eec0801aaa8000000000c0000000000000000000000000000000000000000000000000000000000000000000104a0106601080 +% 80000f157540d55d55515111511160000000000000000000000000000000000000000000000000000000000000000000105a0104201080 +% 80000f13fbc0602aaaa0000000001000000000000000000000000000000000000000000000000000000000000000000010720104201080 +% 80000f57754055555575555555555c00000000000000000000000000000000000000000000000000000000000000000010000106601080 +% 80000f1beac04006aab0000000000200000000000000000000000000000000000000000000000000000000000000000010000102401080 +% 80000f17554055575559111111111100000000000000000000000000000000000000000000000000000000000000000010000100801080 +% 80000f93fbc02222aaa80000000000c0000000000000000000000000000000000000000000000000000000000000000010000100801080 +% 80000fd7554035555555555555555560000000000000000000000000000000000000000000000000000000000000000010400100801080 +% 80000fabeec02001aaaa000000000010000000000000000000000000000000000000000000000000000000000000000010660100001080 +% 80000ff755403555555551515151515c0000000000000000000000000000000000000000000000000000000000000000101c0100201080 +% 80000fa3fbc01020aaab0000000000020000000000000000000000000000000000000000000000000000000000000000103c0107f81080 +% 80000ff755401555d555d55555555555000000000000000000000000000000000000000000000000000000000000000010660104201080 +% 80000fabeac010006aaac00000000000c00000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000fb5556015555555511111111111200000000000000000000000000000000000000000000000000000000000000010000107e41080 +% 80000fa7fba00a222aaaa00000000000100000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000ff555600d5575555555555555555c0000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000fcfeee008001aaab00000000000020000000000000000000000000000000000000000000000000000000000000010000107e01080 +% 80000fd555600d555555591151115111510000000000000000000000000000000000000000000000000000000000000010000100201080 +% 80000fe7fba004223aaaac000000000000c0000000000000000000000000000000000000000000000000000000000000106e0100201080 +% 80000fd5556005555d555555555555555560000000000000000000000000000000000000000000000000000000000000104a0107e01080 +% 80000fefeae004000aaaaa00000000000010000000000000000000000000000000000000000000000000000000000000105a0100201080 +% 80000fd5556005555555551111111111111c00000000000000000000000000000000000000000000000000000000000010720100201080 +% 80001fe7fba0022226aaab0000000000000200000000000000000000000000000000000000000000000000000000000010000100201080 +% 80002ed555600355575555d555555555555500000000000000000000000000000000000000000000000000000000000010180107e01080 +% 80004e8feea0020002aaaac0000000000000c00000000000000000000000000000000000000000000000000000000000103c0100001080 +% 80008edd5560035557555551515151515151600000000000000000000000000000000000000000000000000000000000104a0100001080 +% 80008eabfbb0012021aaaaa0000000000000100000000000000000000000000000000000000000000000000000000000104a0107e41080 +% 80004edd5550015555d555555555555555555c0000000000000000000000000000000000000000000000000000000000104e0100001080 +% 80002eafeaf0008000aaaaa8000000000000020000000000000000000000000000000000000000000000000000000000102c0107e01080 +% 80001fdd555000d555555559111111111111118000000000000000000000000000000000000000000000000000000000103c0100201080 +% 84200fabfbb00062226aaaac00000000000000400000000000000000000000000000000000000000000000000000000010660100201080 +% 87300fdd555800555575555755555555555555600000000000000000000000000000000000000000000000000000000010420100201080 +% 85100f8feee80040001aaaab00000000000000180000000000000000000000000000000000000000000000000000000010420107e01080 +% 84900fd5555800355555555551115111511151140000000000000000000000000000000000000000000000000000000010660100001080 +% 84600fa7fbb80022202aaaaa80000000000000020000000000000000000000000000000000000000000000000000000010240103c01080 +% 80000fd55558001555555555555555555555555580000000000000000000000000000000000000000000000000000000103c0136601080 +% 8400ffafeae800100006aaaaa0000000000000004000000000000000000000000000000000000000000000000000000010660124201080 +% 80000fd57554000d5557555551111111111111113000000000000000000000000000000000000000000000000000000010420124201080 +% 83c00fa7bbbc000a2222aaaab000000000000000080000000000000000000000000000000000000000000000000000001042013fe01080 +% 86300fd57554000d555555555d55555555555555540000000000000000000000000000000000000000000000000000001066011fe01080 +% 84100f8feeac00040000aaaaac0000000000000003000000000000000000000000000000000000000000000000000000103c0100001080 +% 84300fd5755400055555d55557515151515151515180000000000000000000000000000000000000000000000000000010000100001080 +% 83e00fa7fbba000220206aaaaa000000000000000040000000000000000000000000000000000000000000000000000010000100001080 +% 80000fd57556000355557555555555555555555555700000000000000000000000000000000000000000000000000000107e0100001080 +% 80000fafeaea000100002aaaaa800000000000000008000000000000000000000000000000000000000000000000000010020101001080 +% 80000fd5755600015555555555511111111111111116000000000000000000000000000000000000000000000000000010020101001080 +% 80000fa7bbba000122223aaaaac00000000000000001000000000000000000000000000000000000000000000000000010020101001080 +% 80000fd575550000d5555d55557555555555555555558000000000000000000000000000000000000000000000000000107e0107e01080 +% 80000f8feeef0000800006aaaab00000000000000000600000000000000000000000000000000000000000000000000010000101001080 +% 80000fd57555000055555555555951115111511151115000000000000000000000000000000000000000000000000000103c0101001080 +% 80000fa7fbbb0000602222aaaaa80000000000000000080000000000000000000000000000000000000000000000000010660101001080 +% 80000fd5555500003555555555555555555555555555560000000000000000000000000000000000000000000000000010420100001080 +% 80000daffaeb0000200001aaaaaa0000000000000000010000000000000000000000000000000000000000000000000010420107fc1080 +% 80000dd555558000155555d55555111111111111111111c000000000000000000000000000000000000000000000000010660100441080 +% 80000da7bbbb8000122222aaaaab00000000000000000020000000000000000000000000000000000000000000000000107fc100441080 +% 80000dd555558000155555555555d555555555555555555000000000000000000000000000000000000000000000000010000100441080 +% 80000d8ffeae80000800002aaaaac000000000000000000c000000000000000000000000000000000000000000000000106e0100441080 +% 80000dd5555580000d555575555571515151515151515152000000000000000000000000000000000000000000000000104a0103cc1080 +% 80001da7fbbbc0000420203aaaaaa0000000000000000001000000000000000000000000000000000000000000000000105a0107b81080 +% 80002dd55555400005555555555555555555555555555555c0000000000000000000000000000000000000000000000010720100001080 +% 80004faffaeac0000200000aaaaaa800000000000000000020000000000000000000000000000000000000000000000010000100041080 +% 80008fd5555540000355555555555511111111111111111118000000000000000000000000000000000000000000000010000100041080 +% 80008fa3bbbba00001222222aaaaaa00000000000000000004000000000000000000000000000000000000000000000010000100041080 +% 80004d575d5560000155555755555555555555555555555557000000000000000000000000000000000000000000000010000107fc1080 +% 80002d4bfeeea00000800001aaaaab00000000000000000000800000000000000000000000000000000000000000000010000100041080 +% 80001d575555500000555555d5555591511151115111511151600000000000000000000000000000000000000000000010000100041080 +% 80000d63ffbbb000006220226aaaaac00000000000000000001800000000000000000000000000000000000000000000107f0100041080 +% 80000d7555555800003555557555557555555555555555555554000000000000000000000000000000000000000000001183c101001080 +% 80000f29feeae800001000002aaaaab0000000000000000000030000000000000000000000000000000000000000000010000103381080 +% 80000f35d755540000155555555555591111111111111111111180000000000000000000000000000000000000000000100001046c1080 +% 80000fa2bbbbbc00000a22222aaaaaac0000000000000000000060000000000000000000000000000000000000000000107fc104441080 +% 80000fd5d5555400000555555555555755555555555555555555580000000000000000000000000000000000000000001003c104441080 +% 80000f9affaeee000004000002aaaaab0000000000000000000004000000000000000000000000000000000000000000101e0104cc1080 +% 80000fd5555556000003555557555555d15151515151515151515300000000000000000000000000000000000000000010700107981080 +% 80000f927bbbbb000001202021aaaaaac00000000000000000000080000000000000000000000000000000000000000010700100001080 +% 80000fdd55d555000001555555d555557555555555555555555555600000000000000000000000000000000000000000101e0100001080 +% 80000f88bfeaea8000008000006aaaaab0000000000000000000001800000000000000000000000000000000000000001003c100001080 +% 80000f9d75d5558000005555557555555911111111111111111111140000000000000000000000000000000000000000107fc100001080 +% 80000f8a3bfbbb8000006222223aaaaaa80000000000000000000003000000000000000000000000000000000000000010000100801080 +% 80000fd5555555400000355555555555555555555555555555555555800000000000000000000000000000000000000010000100801080 +% 80000f849feeaec000001000000aaaaaaa00000000000000000000006000000000000000000000000000000000000000103fc100801080 +% 80000f95557555600000155555555555551151115111511151115111580000000000000000000000000000000000000010600100001080 +% 80000f863bbbbba0000008222022aaaaaa8000000000000000000000040000000000000000000000000000000000000010400100001080 +% 80000fd75d7555500000055555555555555555555555555555555555570000000000000000000000000000000000000010400107fc1080 +% 80000f82affaeaf0000004000001aaaaaaa000000000000000000000008000000000000000000000000000000000000010400100401080 +% 80000f935d555550000003555555d555555111111111111111111111116000000000000000000000000000000000000010600100401080 +% 80000e8227bbbbb80000012222226aaaaaa8000000000000000000000018000000000000000000000000000000000000103fc100401080 +% 80000ed5555d55580000015555557555555555555555555555555555555400000000000000000000000000000000000010004100401080 +% 80000ec18ffeeeac0000008000001aaaaaaa00000000000000000000000300000000000000000000000000000000000010004100401080 +% 80001ed1555d55540000005555555555555551515151515151515151515180000000000000000000000000000000000010004107fc1080 +% 80002ec123ffbbbc0000006020202aaaaaaa800000000000000000000000600000000000000000000000000000000000107fc100001080 +% 80004dd5d75555560000003555555555555555555555555555555555555558000000000000000000000000000000000010004100001080 +% 80008dc0abfeeaea00000010000002aaaaaac0000000000000000000000004000000000000000000000000000000000010004100101080 +% 80008dd1d75555550000001555555555555571111111111111111111111112000000000000000000000000000000000010004100101080 +% 80004fc0a3bfbbbb0000000a222223aaaaaab0000000000000000000000001000000000000000000000000000000000010000107f81080 +% 80002dd5d75555550000000d555555d555555d555555555555555555555555c00000000000000000000000000000000010000100001080 +% 80001fc08bfeaeef00000008000000aaaaaaa8000000000000000000000000200000000000000000000000000000000011c3c100001080 +% 80000dd15755555500000005555555555555551151115111511151115111511000000000000000000000000000000000107f0100001080 +% 80000fc123bfbbbb000000062022206aaaaaaa000000000000000000000000080000000000000000000000000000000010000100001080 +% 80000dd5575555550000000555555575555557555555555555555555555555540000000000000000000000000000000010000103f81080 +% 80000dc1abfeeaeb000000020000002aaaaaab000000000000000000000000020000000000000000000000000000000010000106181080 +% 80000dd1575555550000000355555555555555911111111111111111111111118000000000000000000000000000000010000104081080 +% 80000fc123bfbbbb000000022222223aaaaaaa800000000000000000000000004000000000000000000000000000000010000106181080 +% 80000dd557555555000000015555555d555555555555555555555555555555556000000000000000000000000000000010000103f01080 +% 80000dc18bfeeeae800000010000000aaaaaaac00000000000000000000000001000000000000000000000000000000010000100001080 +% 80000dd1575555558000000155555555555555715151515151515151515151515800000000000000000000000000000010000107e01080 +% 80000fc223ffbbbb80000000a0202026aaaaaab00000000000000000000000000400000000000000000000000000000010000100201080 +% 80000dd75755555580000000d5555557555555555555555555555555555555555700000000000000000000000000000010000100201080 +% 80000dc2abfeeaea8000000080000002aaaaaaa80000000000000000000000000080000000000000000000000000000010000107e01080 +% 80000dd3575555558000000055555555555555551111111111111111111111111140000000000000000000000000000010000100201080 +% 80000fc223bfbbbb8000000062222223aaaaaaac0000000000000000000000000020000000000000000000000000000010000100201080 +% 80000dd7575555558000000055555555d55555575555555555555555555555555550000000000000000000000000000010000100201080 +% 80000fc28bfeaeee8000000020000000aaaaaaab0000000000000000000000000008000000000000000000000000000010000107e01080 +% 80000dd3575555558000000035555555555555555111511151115111511151115116000000000000000000000000000010000100001080 +% 80000fc223bfbbbb80000000202220226aaaaaaa8000000000000000000000000001000000000000000000000000000010000100001080 +% 80000dd5575555554000000035555555755555555555555555555555555555555555800000000000000000000000000010000100001080 +% 80000dc4abfeeaeac0000000100000002aaaaaaac000000000000000000000000000400000000000000000000000000010000100001080 +% 80000dd5575555554000000015555555555555557111111111111111111111111111200000000000000000000000000010000100001080 +% 80000fc627bfbbbbc0000000122222223aaaaaaab000000000000000000000000000180000000000000000000000000010000100801080 +% 80001dd555555555400000000d5555555d5555555555555555555555555555555555540000000000000000000000000010000100801080 +% 81002dc68ffeeeaec0000000080000000aaaaaaaa800000000000000000000000000020000000000000000000000000010000100801080 +% 81c04dd555555555400000000d555555555555555551515151515151515151515151510000000000000000000000000010000100001080 +% 81608fc627ffbbbbc00000000420202026aaaaaaac00000000000000000000000000008000000000000000000000000010000100001080 +% 87f08dd5555555554000000005555555575555555755555555555555555555555555554000000000000000000000000010000107fc1080 +% 81004dc4affeeaeac00000000400000002aaaaaaab00000000000000000000000000003000000000000000000000000010000100401080 +% 80002dd5555555556000000003555555555555555511111111111111111111111111111800000000000000000000000010000100601080 +% 80001fca27bfbbbba00000000222222223aaaaaaaa80000000000000000000000000000400000000000000000000000010000100f01080 +% 8400fddd55555555600000000155555555d555555555555555555555555555555555555600000000000000000000000010000103981080 +% 80000fc88ffeaeeea00000000100000000aaaaaaaac0000000000000000000000000000180000000000000000000000010000106041080 +% 83c00ddd555555556000000001555555555555555571511151115111511151115111511140000000000000000000000010000104001080 +% 86300fca27bfbbbba000000000a22022206aaaaaaab0000000000000000000000000000020000000000000000000000010000100001080 +% 84100ddd555555556000000000d55555557555555555555555555555555555555555555550000000000000000000000010000100101080 +% 84300dc8affeeaeae000000000800000002aaaaaaaa800000000000000000000000000000c000000000000000000000010000100101080 +% 83e00ddd555555555000000000555555555555555555111111111111111111111111111112000000000000000000000010000107f81080 +% 80000fca27bfbbbbb000000000622222223aaaaaaaaa000000000000000000000000000001000000000000000000000010000100001080 +% 80000ddd555555555000000000555555555d55555557555555555555555555555555555555800000000000000000000010000100001080 +% 80000dca8ffeeeaef000000000200000000aaaaaaaab000000000000000000000000000000600000000000000000000010000100001080 +% 80000ddd555555555000000000355555555555555555d15151515151515151515151515151500000000000000000000010000103f81080 +% 80000fd227ffbbbbb0000000002020202022aaaaaaaa800000000000000000000000000000080000000000000000000010000106181080 +% 80000dd5555555555000000000155555555755555555555555555555555555555555555555540000000000000000000010000104081080 +% 80000dd8affeeaeae8000000001000000001aaaaaaaaa00000000000000000000000000000030000000000000000000010000106181080 +% 80000dd5555555555800000000155555555555555555711111111111111111111111111111118000000000000000000010000103f01080 +% 80000fd227bfbbbbb8000000000a22222222aaaaaaaab00000000000000000000000000000004000000000000000000010000100001080 +% 80000dd55555555558000000000d55555555d55555555d5555555555555555555555555555556000000000000000000010000100001080 +% 80000fd88ffeaeeea80000000004000000006aaaaaaaa80000000000000000000000000000001800000000000000000010000107e01080 +% 80000dd5555755555800000000055555555555555555551151115111511151115111511151115400000000000000000010000100201080 +% 80000fd227bbbbbbb80000000006202220222aaaaaaaaa0000000000000000000000000000000200000000000000000010000100201080 +% 80001dd5555755555800000000035555555575555555575555555555555555555555555555555500000000000000000010000107e01080 +% 80002db8affeeaeaec0000000002000000001aaaaaaaab00000000000000000000000000000000c0000000000000000010000100201080 +% 80004df5555755555400000000035555555555555555559111111111111111111111111111111120000000000000000010000100201080 +% 80008fb227bbbbbbbc0000000001222222222aaaaaaaaac000000000000000000000000000000010000000000000000010000100201080 +% 80008df557575555540000000001555555555555555555555555555555555555555555555555555c000000000000000010000107e01080 +% 80004dba8bfeeeaeee00000000008000000002aaaaaaaaa000000000000000000000000000000002000000000000000010000100001080 +% 80002df5575555555600000000005555555557555555555151515151515151515151515151515151800000000000000010000100001080 +% 80001fb223fbbbbbba00000000006020202021aaaaaaaaa800000000000000000000000000000000400000000000000010000100001080 +% 80000dfd555555555500000000003555555555d55555555555555555555555555555555555555555600000000000000010000100001080 +% 80000da8a9ffeaeaeb000000000010000000006aaaaaaaaa00000000000000000000000000000000180000000000000010000100801080 +% 80000dfd5555d5555580000000001555555555755555555511111111111111111111111111111111140000000000000010000100801080 +% 80000faa23bbbbbbbb80000000000a222222223aaaaaaaaa80000000000000000000000000000000030000000000000010000100801080 +% 80000df555d5d5555580000000000555555555555555555555555555555555555555555555555555558000000000000010000100001080 +% 80000fa48affeeeeaec00000000004000000000aaaaaaaaaa0000000000000000000000000000000006000000000000010000100001080 +% 80000df555d55555554000000000035555555555555555555111511151115111511151115111511151100000000000001000013fe01080 +% 80000fa622bbfbbbbba000000000012220222022aaaaaaaaa8000000000000000000000000000000000c00000000000010000106601080 +% 80000df5555555555560000000000155555555555555555555555555555555555555555555555555555600000000000010000104201080 +% 80000da2a8ffeaeaeae000000000008000000000aaaaaaaaaa000000000000000000000000000000000180000000000010000106601080 +% 80000df355557555555000000000005555555555d555555555111111111111111111111111111111111140000000000010000103c01080 +% 80000fa2227bbbbbbbb0000000000022222222226aaaaaaaaa800000000000000000000000000000000030000000000010000100001080 +% 80000df7557555555558000000000035555555557555555555555555555555555555555555555555555558000000000010000100001080 +% 80000da188bffeaeeea8000000000010000000001aaaaaaaaaa00000000000000000000000000000000004000000000010000100001080 +% 80000df155755555555800000000000d555555555d55555555515151515151515151515151515151515153000000000010000100001080 +% 80000fa1223bfbbbbbbc0000000000082020202026aaaaaaaaa80000000000000000000000000000000000800000000010000100801080 +% 80000df555555d555554000000000005555555555555555555555555555555555555555555555555555555600000000010000100801080 +% 80001da1a8bffaeaeaea0000000000020000000002aaaaaaaaaa0000000000000000000000000000000000100000000010000100801080 +% 80002df1d5555d5555560000000000035555555555555555555511111111111111111111111111111111111c0000000010000100001080 +% 80004fa0a22bbfbbbbba0000000000012222222222aaaaaaaaaa8000000000000000000000000000000000020000000010000100001080 +% 80008df5d55d55555555000000000000d55555555555555555555555555555555555555555555555555555558000000010000107fc1080 +% 80008fa08a8ffeeeaeef00000000000080000000002aaaaaaaaaa000000000000000000000000000000000004000000010000100201080 +% 80004df1d55d55555555000000000000555555555575555555555111511151115111511151115111511151116000000010000100201080 +% 80002fa0a22bffbbbbbb00000000000060222022203aaaaaaaaab000000000000000000000000000000000001800000010000100201080 +% 80001df5d55d57555555800000000000355555555555555555555d55555555555555555555555555555555555400000010000107e01080 +% 80000da0a8affeeaeaea80000000000020000000000aaaaaaaaaac00000000000000000000000000000000000200000010000100001080 +% 80000df1d55d5755555580000000000035555555555d555555555511111111111111111111111111111111111100000010000100001080 +% 80000fa0a22bbbbbbbbb800000000000122222222226aaaaaaaaaa00000000000000000000000000000000000080000010000107fc1080 +% 80000df5d55d57555555800000000000155555555555555555555555555555555555555555555555555555555560000010000100441080 +% 80000da0888ffeaeeeae800000000000080000000002aaaaaaaaaa80000000000000000000000000000000000010000010000100441080 +% 80000df1d55d575555554000000000000d55555555575555555555d1515151515151515151515151515151515158000010000100441080 +% 80000fa0a22bfbbbbbbbc00000000000082020202021aaaaaaaaaac0000000000000000000000000000000000004000010000100441080 +% 80000df5d55d57555555400000000000055555555555d55555555575555555555555555555555555555555555557000010000103cc1080 +% 80000da0a8affeeaeaeac00000000000040000000000aaaaaaaaaaa0000000000000000000000000000000000000800010000107b81080 +% 80000df1d55557555555400000000000035555555555555555555551111111111111111111111111111111111111400010000100001080 +% 80000fa0a227bbbbbbbbc000000000000222222222226aaaaaaaaaa8000000000000000000000000000000000000200010000100001080 +% 80000df5d5555755555560000000000003555555555575555555555d555555555555555555555555555555555555580010000100001080 +% 80000fa08a8ffeeeaeeea000000000000100000000002aaaaaaaaaac000000000000000000000000000000000000040010000100001080 +% 80000df1d55555555555600000000000015555555555555555555557511151115111511151115111511151115111520010000100801080 +% 80000fa0a227fbbbbbbba0000000000000a2202220223aaaaaaaaaab000000000000000000000000000000000000010010000100801080 +% 80000df5d5555555555560000000000000d5555555555d555555555555555555555555555555555555555555555555c010000100801080 +% 80001da0a8afffeaeaeae000000000000080000000000aaaaaaaaaaa800000000000000000000000000000000000002010000100001080 +% 80002df1d55555555555500000000000005555555555555555555555511111111111111111111111111111111111111010000100001080 +% 80004fa0a227bbbbbbbbb0000000000000622222222222aaaaaaaaaac00000000000000000000000000000000000000810000107e41080 +% 80008df5d55555d555555800000000000035555555555755555555557d5555555555555555555555555555555555555410000100001080 +% 80008fd0688bff7eeeaeee000000000000400000000002aaaaaaaaaaabf000000000000000000000000000000000001810000100001080 +% 80004fb97d55559d555555800000000000d555555555555555555555555ff1515151515151515151515151515151516010000100101080 +% 80002ee43e22fbc3bbbbbbf0000000000120202020202aaaaaaaaaaaaaaabf800000000000000000000000000000018010000100101080 +% 80001ff57dd555407555555c000000000155555555555d55555555555555557f5555555555555555555555555555560010000107f81080 +% 80000ffa1fe8bfe00eeaeaeb000000000200000000001aaaaaaaaaaaaaaaaaaafc00000000000000000000000000080010000100001080 +% 80000fdd1f7d5d7111d55555e00000000555555555555555555555555555555557f9111111111111111111111111300010000100001080 +% 80000ffe8ffe27b0003bbbbbb80000000622222222222aaaaaaaaaaaaaaaaaaaaaafe00000000000000000000000c00010000100001080 +% 80000fd55ff7575404075555570000000d55555555557555555555555555555555555fd555555555555555555557000010000104001080 +% 80000fff27ffcbf80000eeeeaec000001000000000006aaaaaaaaaaaaaaaaaaaaaaaaabf0000000000000000000c000010000100001080 +% 80000ff5f7ff75d911113d5555700000155555555555d555555555555555555555555555ff115111511151115130000010000100001080 +% 80000ffbf3fffe7c000007bbbbbe0000202220222022aaaaaaaaaaaaaaaaaaaaaaaaaaaaabf800000000000000c0000010000100001080 +% 83c00ff57fff5776404040f55555800055555555555555555555555555555555555555555557f555555555555700000010000103f81080 +% 86f00ffff5ffffbe0000001eeaeae000800000000001aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafc0000000000c00000010000106181080 +% 84501ff56ffff77d11111113d5555c00d5555555555755555555555555555555555555555555557f111111113000000010000104081080 +% 84502ffbbbfffffb000000007bbbbb01222222222222aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafe0000004000000010000106181080 +% 83a04ffd5dfff557c40444044d5555e355555555555555555555555555555555555555555555555555fd55558000000010000103f01080 +% 80008ffffeffffff8000000003aeeeba00000000000aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaff0060000000010000100001080 +% 80008ffd577ffd75d11111111155555d555555555575555555555555555555555555555555555555555ff9780000000010000100001080 +% 8400cffbfdffffff80000000007bbbb02020202021eaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabffe007800000000010000100001080 +% 80002ff55ffff5574040404040d555d555555555575555555555555555555555555555555555fffd5555f8000000000010000100001080 +% 83c01ffff7fffffe0000000001eaeb00000000003aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabfff0000000f00000000000010000100801080 +% 86300ff5fffff77f1111111111555d5555555555d55555555555555555555555555557fff111111111f000000000000010000100801080 +% 84100ffbbffffffc0000000003bbb2222222222eaaaaaaaaaaaaaaaaaaaaaaaaaafff800000000001f0000000000000010000100801080 +% 84300fd77ffd555c040404040555d5555555557555555555555555555555555fff55555555555555e00000000000000010000100001080 +% 83e00ffefffffff80000000006ef0000000001aaaaaaaaaaaaaaaaaaaaafffe0000000000000001e000000000000000010000100001080 +% 80000fddfff77751111111111d5d555555555f555555555555555555fff9511151115111511153e0000000000000000010000106e01080 +% 80000fb7ffffffa0000000000bb2202220227aaaaaaaaaaaaaaabfff000000000000000000003c00000000000000000010000104a01080 +% 80001f7fffd55d404040404055d555555557d5555555555557ffd55555555555555555555557c000000000000000000010000105a01080 +% 80002fdfffffffc0000000002b000000001eaaaaaaaaaafff80000000000000000000000007c0000000000000000000010000107201080 +% 80004fffff777591111111113d55555555755555557fff1111111111111111111111111117800000000000000000000010000100001080 +% 80008fbfffffbb00000000007222222223aaaaafffc0000000000000000000000000000078000000000000000000000010000100001080 +% 80008d7ff555550444044404d55555555d5555fd5555555555555555555555555555555780000000000000000000000010000106e01080 +% 80004dfffffffe0000000000800000001aaaab000000000000000000000000000000001800000000000000000000000010000104a01080 +% 80002d7ff5755711111111115555555575555751515151515151515151515151515151e000000000000000000000000010000105a01080 +% 80001dfffffffa0000000003202020206aaaac000000000000000000000000000000070000000000000000000000000010000107201080 +% 80000d7ff55556404040404755555555d5555d555555555555555555555555555555780000000000000000000000000010000100001080 +% 80000dbffffffc000000000400000003aaaaa0000000000000000000000000000000c00000000000000000000000000010000100201080 +% 80000d7fff7755111111111d55555555555551111111111111111111111111111117000000000000000000000000000010000107f81080 +% 80000fbfffffbc000000001a2222222aaaaa80000000000000000000000000000038000000000000000000000000000010000104201080 +% 80000d7ffd57540404040415555555555555555555555555555555555555555555c0000000000000000000000000000010000103c01080 +% 80000dbffffff800000000300000002aaaaa00000000000000000000000000000600000000000000000000000000000010000106601080 +% 80000d7ffd7759111111117555555555555551115111511151115111511151117800000000000000000000000000000010000104201080 +% 80000dbffffff800000000e2202220aaaab80000000000000000000000000001c000000000000000000000000000000010000104201080 +% 80000d7ffd575840404040d555555755557555555555555555555555555555560000000000000000000000000000000010000106601080 +% 80000dbffffff80000000180000006aaaac000000000000000000000000000380000000000000000000000000000000010000107fc1080 +% 80000d7fff7751111111135555555d55559111111111111111111111111111c00000000000000000000000000000000010000100001080 +% 80000fbfffffb0000000032222223aaaab000000000000000000000000000e000000000000000000000000000000000010000101801080 +% 80000d5ffd5554044404475555557555575555555555555555555555555570000000000000000000000000000000000010000103c01080 +% 80000dbffffff00000000c0000006aaaac00000000000000000000000001c0000000000000000000000000000000000010000104a01080 +% 80000d5ffd757111111115555555d555595151515151515151515151515e00000000000000000000000000000000000010000104a01080 +% 80000dbfffffe000000018202022aaaaa00000000000000000000000007000000000000000000000000000000000000010000104e01080 +% 80000d5ffd5560404040755555555555555555555555555555555555558000000000000000000000000000000000000010000102c01080 +% 80000dbfffffe00000006000000aaaaa8000000000000000000000000e0000000000000000000000000000000000000010000100001080 +% 80001d5fff7551111111755555555555111111111111111111111111700000000000000000000000000000000000000010000107e01080 +% 80002fbfffffc0000000e222222aaaaa000000000000000000000003800000000000000000000000000000000000000010000100201080 +% 80004f5ffd5d44040405d5555555555d55555555555555555555555c000000000000000000000000000000000000000010000100201080 +% 80008eafffffc0000002800001aaaab0000000000000000000000070000000000000000000000000000000000000000010000100001080 +% 80008f5ffd7d91111113555557555571511151115111511151115380000000000000000000000000000000000000000010000107e01080 +% 80004eaffffb80000006202226aaaac0000000000000000000000c00000000000000000000000000000000000000000010000100201080 +% 80002f5ffd5dc040404b55555d5555d5555555555555555555557000000000000000000000000000000000000000000010000100201080 +% 80001eafffff8000000c00001aaaab00000000000000000000018000000000000000000000000000000000000000000010000100001080 +% 80000f5fff7d1111111d5555755557111111111111111111111e0000000000000000000000000000000000000000000010000100001080 +% 80000eaffffb0000002a22226aaaac00000000000000000000300000000000000000000000000000000000000000000010000100001080 +% 80000f5ffd55440444355555d5555d55555555555555555555c00000000000000000000000000000000000000000000010000100001080 +% 80000eafffff000000600001aaaab000000000000000000006000000000000000000000000000000000000000000000010000100001080 +% 80000f5ff577111111d5555755557151515151515151515158000000000000000000000000000000000000000000000010000100001080 +% 80000eaffffa000001602026aaaac0000000000000000000e0000000000000000000000000000000000000000000000010000100001080 +% 80000f57f576404041d5555d55555555555555555555555700000000000000000000000000000000000000000000000010000100001080 +% 80000eaffffe00000300002aaaaa0000000000000000001c00000000000000000000000000000000000000000000000010000100001080 +% 80000f57f77711111555555555551111111111111111116000000000000000000000000000000000000000000000000010000100001080 +% 80000eaffffc0000062222aaaaa80000000000000000038000000000000000000000000000000000000000000000000010000100001080 +% 80000f57f57404040d555555555555555555555555555c0000000000000000000000000000000000000000000000000010000100001080 +% 80000eaffffc0000180002aaaaa00000000000000000700000000000000000000000000000000000000000000000000010000100001080 +% 80000f57f55511111d55555555515111511151115111800000000000000000000000000000000000000000000000000010000100001080 +% 80000eaffff8000030222aaaaa80000000000000000e000000000000000000000000000000000000000000000000000010000100001080 +% 80000f57f55840407555555555555555555555555570000000000000000000000000000000000000000000000000000010000100001080 +% 80000eabfff80000a0002aaaae0000000000000001c0000000000000000000000000000000000000000000000000000010000100001080 +% 80000f57f7591111d555555559111111111111111600000000000000000000000000000000000000000000000000000010000100001080 +% 80000eabfff00001a223aaaab0000000000000003800000000000000000000000000000000000000000000000000000010000100001080 +% 80000f57f5d44406d55755557555555555555555c000000000000000000000000000000000000000000000000000000010000100001080 +% 80000eabfff000030006aaaac0000000000000070000000000000000000000000000000000000000000000000000000010000100001080 +% 80000f57f5d11117555d5555d1515151515151580000000000000000000000000000000000000000000000000000000010000100001080 +% 80000eabffe0000c203aaaab00000000000000e00000000000000000000000000000000000000000000000000000000010000100001080 +% 80000f57f5e0404d5575555755555555555557000000000000000000000000000000000000000000000000000000000010000100001080 +% 80001eabffe00018006aaaac0000000000001c000000000000000000000000000000000000000000000000000000000010000100001080 +% 80002f55f771113555d5555911111111111160000000000000000000000000000000000000000000000000000000000010000100001080 +% 80004eabffa0005223aaaab000000000000380000000000000000000000000000000000000000000000000000000000010000100001080 +% 80008f55f54404755755557555555555555c00000000000000000000000000000000000000000000000000000000000010000100001080 +% 80008eabffc000a006aaaac000000000003000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80004f55f55111d55d5555915111511151c000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80002faaffc001623aaaab0000000000070000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80001fd5f54041d57555575555555555580000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000faaffc001802aaaaa0000000000600000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000fd57f5113555555551111111111800000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000feaffc00322aaaaa8000000000e000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000f757dc447555555555555555570000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000efabfc00602aaaab000000000c0000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000f757dd11d575555715151515300000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000fbabfc00c26aaaac00000000c00000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000f5d5dc04d5d5555d55555557000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000feebfc0181aaaaa800000018000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000f5f5fd11d755555111111160000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000fbeafc0322aaaaa000000180000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000fd75fe435555555555555e00000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000fefafe060aaaaac000003000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000fd5dff17555555951115c000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000ffbafa061aaaab0000030000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000fd5d760d75555755555c0000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000feaefe086aaaaa0000700000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 86c00fd57771dd555551111800000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 85c00ffbbbe13aaaaa80006000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 85400ff577e755555555558000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 85400feefbe22aaaab00060000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 82400ff55df355555751780000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 83800ffbbfe6aaaaac00c00000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 87c00ff557e555555d57000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 85400ffaeeedaaaab00c000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 85400ff557ff55555170000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 87c01ffbbbfeaaaaa180000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80002ffd55fd55555600000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 83804ffeaefaaaaa9800000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 86408ffd55f55555e000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 84408ffbbbeaaaab8000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 84404ffd557555550000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 82c02ffaeaeaaaaa0000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 83801ffd55d555560000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 86400ff7bbeaaaaa0000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 84400ff555d555540000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 84400ff6efaaaaac0000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 83800ff555d555540000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000ff7bbaaaaac0000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 87c00fe5555555580000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80400fe6ebaaaaa80000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80400ff5575555580000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 87c00fe7baaaaab00000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000fe5575555500000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 83800fc6aeaaaab00000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 86400fd5575555600000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 84400fc7beaaaaa00000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 84400fc55d5555600000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 87f00f86eeaaaac00000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 86c00f955d5555400000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 85c00f87baaaaac00000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 85400f875d5555800000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 85400f82faaaaa800000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 82400f13555555800000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000f03baaaab000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000f43755555000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000f02faaaab000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000f13755555000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 8fe00e03eaaaaa000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 98300e07755556000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000e02eaaaaa000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 87f00f13d55554000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80600c03eaaaac000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 87800c43d55554000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 86000c02aaaaa8000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 81c01d13d55558000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80702c03aaaaa8000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 87f04c07555550000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80008801aaaab0000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80008913555560000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 83f04806aaab80000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 84002845555600000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 8400180aaab800000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 8400091d556000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 83f0081aab8000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000c35560000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 8010086aac0000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80100955700000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 801008aac00000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 87f009d7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 801009ac000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80100b70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 90100ec0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 98700d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 87c00e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000003fff9fffcfffe7fff1fffcfffe7fff3fff8fffe7fff3fff9fffc7fff3fff9fffcfffe3fff9fffcfffe7fff00010000100001080 +% 80000003fff95554d556555514044d556400135558d55655553fff955545555355590404d556200095554d556555500010000100001080 +% 80000003fff9fffc8a8a7fff10004eeea400120008aaaa40013fff9fffc48a93fff90004aeee200090004aaaa400100010000100001080 +% 80000003fff97574d556555511114d556400135558d55651513fff977545555355591114d556200095554d556511500010000100001080 +% 80000003fff9fffca2227bbb10004bbba400122228aaaa40013fff9fffc62233fbb90004bbba200090224aaaa400100010000100001080 +% 80000003fff95554d556555510404d556400135558d55655553fff955545555355594044d556200095554d556555500010000100001080 +% 80000003fff9fffca8aa7fff10004aeae400120008aaaa40013fff9fffc4a8b3fff90004eaea200090004aaaa400100010000100001080 +% 80000003fff97774d556555511114d556400135558d55651113fff977745555355591114d556200095554d556511100010000100001080 +% 80000003fff9fffca2227bbb10004bbba400122228aaaa40013fff9fffc62233bbb90004bbba200092224aaaa400100010000100001080 +% 80000003fff95554d556555514044d556400135558d55655553fff955545555355594404d556200095554d556555500010000100001080 +% 80000003fff9fffc888a7fff10004eaee400120008aaaa40013fff9fffc68893fff90004eeae200090004aaaa400100010000100001080 +% 80000003fff97574d556555511114d556400135558d55651513fff957545555355591114d556200095554d556551500010000100001080 +% 80000003fff9fffca2227bfb10004bbba400122028aaaa40013fff9fffc62233fbf90004bbba200090204aaaa400100010000100001080 +% 80000003fff95554d556555510404d556400135558d55655553fff955545555355594044d556200095554d556555500010000100001080 +% 80000003fff9fffcfffe7fff1fffcfffe7fff3fff8fffe7fff3fff9fffc7fff3fff9fffcfffe3fff9fffcfffe7fff00010000100001080 +% 80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000000380000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 800000004400fe003f801fc00fe007f001fc00fe007f003f800fe007f003f801fc007f003f801fc00fe003f801fc000010000100001080 +% 800000008201830060c0306018300c180306018300c18060c018300c18060c030600c18060c030601830060c0306000010000100001080 +% 80000000820000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 8000000082002c00000001c0000000000084002c00000010800000000000b000580000000f000200010000000020000010000100001080 +% 80000000c6006f0000800f200020001000e6006f0001001cc00020001001bc00de0001001bc0038001c000080038000010000100001080 +% 800000007c00450000800a200020001000a200450001001440002000100114008a000100114002c001600008002c000010000100001080 +% 80000000000045001fc00f2007f003f800920045003f80124007f003f80114008a003f8011400fe007f001fc00fe000010000100001080 +% 8000000002003900000007c000000000008c003900000011800000000000e400720000000e800200010000000020000010000100001080 +% 80000000020001000b00058003c00110001c002c0000000040000000000038008400000010800440030004040058000010000100001080 +% 80000000020041001bc00de006f0031800f2006f00010010400020001001e400e60001001cc00c6004f0061c00de000010000100001080 +% 80000000fe007900114008a00450024800a200450001001e4000200010014400a200010014400920049001f0008a000010000100001080 +% 8000000002000d00114008a00450024800f20045003f80034007f003f801e40092003f801240092004900000008a000010004100001080 +% 80000000020003000e40072003a001f0007c003900000000c00000000000f8008c000000118007c003e000800072000010004100001080 +% 80000000000000000000000000000000000000000000000000000000000000000000000000000000000001980000000010004100001080 +% 80000000fe01010040402020010001100202010100000040400010008004040202002100404020201010013402020000107fc100001080 +% 800000001001870061c030e001c00318030e018700010061c0041000e0061c030e00398061c030e018700124030e000010004100001080 +% 8000000010007c001f000f800160024800f8007c0001001f00079000b001f000f80028801f000f8007c0012400f8000010004100001080 +% 8000000010006c00ff00040007f0024800000064003f80ff0000d003f8019000d800248008000c80000001c800d8000010004100001080 +% 80000000fe005c001b000cc0010001f000f80054000000190000300080015000b800230019800a8007c0000400b8000010000100001080 +% 8000000000005400110009a01010080800080054008080110010100808015000a800808013400a800400000c00a80000107fc100001080 +% 80000000000054001100092018700c380008005400c380110018700c38015000a800c38012400a800400003000a8000010020100001080 +% 80000000fe0024001f00092007c003e000f8007c003e000e0007c003e001f00048003e0012400f8007c001e00048000010020100001080 +% 800000009201040000000e400000000000080000000000000000000000000002080000001c800000000000380208000010020100001080 +% 800000009201380019000000000000000008000000360000000000036000e002700036000000070006c0000c02700000107e0100001080 +% 800000009200e0001500002007c003e000f8007c002e001f0007c002e0019001c0002e0000400c8005c0000001c0000010000100001080 +% 8000000092003800150000600400002000c80004002a000100040002a001100070002a0000c00880054000800070000010000100001080 +% 8000000000000400150001800400002000a80004002a000e00040002a001100008002a00030008800540019800080000107e0100001080 +% 80000000000000001f000f0007c003e000a8007c0012001f0007c0012001fc00000012001e000fe0024001340000000010400100001080 +% 80000000fe007c00000001c006c0002000a80000008200150006c0082000e000f8008200038007000380012400f8000010400100001080 +% 80000000120004001f00006005c0002000f8007c009c00150005c009c001900008009c0000c00c8007c001240008000010600100001080 +% 800000001200040001000400054003e0000000040070001f00054007000110000800700008000880054001c800080000107e0100001080 +% 8000000012007c0000000cc00540032000000004001c000000054001c0011000f8001c00198008800540000000f8000010000100001080 +% 80000000f20000001b0009a0024002a000fa007c000200ff000240002001fc000000020013400fe007c000040000000010000100001080 +% 80000000ee00040017000920038002a0000000000000001900038000000000000800000012400000100000040008000010000100001080 +% 8000000000007f001500092007c002a000f80038003e00110007c003e0007000fe003e00124003801000000400fe000010000100001080 +% 800000000000440015000e40054003e000080064000200110005400020008800880002001c800440100001fc0088000010400100001080 +% 8000000000007f000900000005400000000800440002000e0005400020010400fe000200000008201000000400fe000010780100001080 +% 80000000000004000e00002007c003f800f80044003e00190007c003e001040008003e00004008201000000400080000100f0100001080 +% 80000000000004001f000020000000c000000038000200150000000020010400080002000040082010000000000800001009c100001080 +% 8000000000007c001500002001c000c000000004003f801500100003f8018c00f8003f8000400c6007f001fc00f800001009c100001080 +% 800000000000000015000fe0022001a00000007f00220015001000022000c800000022001fc006400640012400000000100f0100001080 +% 80000000000100001f00002004100200000000440000001f00100000000070020000000000400380044001240200000010780100001080 +% 800000000001000000000020041001c000000064003f800000100003f800880200003f8000400440044001240200000010400100001080 +% 800000000001000000000000041003e0000000540002000000100000200104020000020000000820038001240200000010000100001080 +% 800000000001000000000fe0063002a0000000540002001f0017f00020010402000002001fc0082007f0000002000000107e0100001080 +% 800000000001000000000920032002a000000054003e000100064003e001040200003e0012400820064001fc0200000010400100001080 +% 80000000000100000000092001c003e00000007c0000001b0004400000018c020000000012400c60044000180200000010400100001080 +% 800000000000420000000920022000e00000000000800017000440080000c8008400000012400640044001e00084000010600100001080 +% 800000000000730000000920041001100000000400800015000380080001b000e6003f8012400d800380018000e60000107e0100001080 +% 800000000000510000000000041002080000007f008000150000000800017000a200200000000b800000007000a20000103c0100001080 +% 800000000000490000000000041002080000007c008000090007f008000150009200200000000a800000001c0092000013660100001080 +% 800000000000460000000fe0063002080000007c0080000e00064008000150008c0020001fc00a80000001fc008c000012420100001080 +% 8000000000000000000000c0032003180000005400a1001f0004400a100090000000000001800480000000000000000012420100001080 +% 800000000000c00000000f00038001900000005400398015000440039804000180003e801e002000000000000000000013fe0100001080 +% 800000000000000000000c00064000e00000007c0028801500038002880400000000000018002000000000000000000011fe0100001080 +% 80000000000064000000038004400110000000000024801f000000024804000000003e0007002000000000000000000010000100001080 +% 8000000000005400000000e0044002080000010000230000000c000230040000f800020001c02000000000000000000010000100001080 +% 800000000000540000000fe007f0020800000100000000000000000000040000800002001fc02000000000000000000010000100001080 +% 8000000000005400000000000000020800000100000000000006c0000004000080003e0000002000000000000000000010000100001080 +% 8000000000007c00000018000380031800000100006000000005c00600003000f800000030000180000000000000000010420100001080 +% 80000000000038000000000007c001900000010000000000000540000001e000d8001c0000000f00000000000000000010738100001080 +% 8000000000006400000000000540000000000100003e000000054003e001c000b8003e001b000e00000000000000000010588100001080 +% 800000000000440000000f80054001c000000000000200000002400020003000a8002a0017000180000000000000000010488100001080 +% 80000000000044000000080007c003200000007d00020000001040002001e000a8002a0015000f000000000000000000104c8100001080 +% 8000000000007f000000080006c0022000000000003e000000138003e001c00048003e0015000e00000000000000000010478100001080 +% 800000000000000000000f8005c002200000007c00020000000e0000200030007000000009000180000000000000000010000100001080 +% 800000000000380000000000054003f800000004000200000003800020000000f800000041000000000000000000000010210100001080 +% 800000000000640000000d80054001c000000004003e000000004003e001f000a80000004e000f80000000000000000010718100001080 +% 800000000000440000000b80024003e00000007c000000000000000000001000a800000038000080000000000000000010408100001080 +% 800000000000440000000a80038002a00000006c003200000007c0032001fc00f80000000e000fe0000000000000000010448100001080 +% 8000000000007f0000000a80064002a00000005c002a000000004002a000600000000000010003000000000000000000104c8100001080 +% 800000000000000000000480044003e000000054002a000000004002a000600200000000000003000000000000000000103b0100001080 +% 8000000000001c00000007000440000000000054002a00000007c002a000d002000000001f000680000000000000000010000100001080 +% 800000000000220000000f8002c0036000000024003e000000000003e00100020000000001000800000000000000000010000100001080 +% 800000000000410000000a80000002e000000000003f800000004003f80000020000000001000000000000000000000010000100001080 +% 800000000000410000000a8007c002a00000007c000c00000007f000c0030002000000001f000000000000000000000010000100001080 +% 800000000000410000000f80004002a000000004000c000000044000c00000020000000000000000000000000000000010000100001080 +% 8000000000006300000020000000012000000004001a000000000001a0000000fe00000001000000000000000000000010010100001080 +% 800000000000320000002000000001c00000007c002000000007f0020001f000c80000001fc00000000000000000000010010100001080 +% 8000000000001c000000200007d0032000000000001c000000004001c001000088000000110000000000000000000000107f8100001080 +% 8000000000002200000020003fc0022000000000003e000000004003e0010000880000001fc00000000000000000000010000100001080 +% 8000000000004100000020000640022000000000002a00000007c002a001f0007000000001000000000000000000000010000100001080 +% 8000000000004100000020000440016000000000002a000000000002a0000000fe00000001000000000000000000000010000100001080 +% 800000000000410000000fe00440000000000000003e00000007f003e001b000c80000001f000000000000000000000010008100001080 +% 800000000000630000000c80038003e0000000000000000000040000000170008800000000000000000000000000000010008100001080 +% 8000000000003200000008800040002000000000000e000000040000e00150008800000040000000000000000000000010708100001080 +% 8000000000006c000000088007f000000000000000110000000400011001500070000000400000000000000000000000101c8100001080 +% 8000000000005c0000000700044003e8000000000020800000000002080090000000000040000000000000000000000010028100001080 +% 800000000000540000000fe003801fe00000000000208000000000020800e0000000000040000000000000000000000010018100001080 +% 800000000000540000000c800640032000000000002080000007d0020801f0000000000040000000000000000000000010000100001080 +% 80000000000024000000088004400220000000000031800000000003180150000000000050800000000000000000000010420100001080 +% 8000000000010000000008800440022000000000001900000007c00190015000000000001cc00000000000000000000010000100001080 +% 800000000001000000000700038001c000000000000e000000004000e001f0000000000014400000000000000000000010000100001080 +% 80000000000100000000000000000000000000000011000000004001100400000000000012400000000000000000000010210100001080 +% 8000000000010000000000000000002000000000002080000007c002080400000000000011800000000000000000000010718100001080 +% 80000000000100000000000007c003f8000000000020800000038002080400000000000000000000000000000000000010408100001080 +% 8000000000010000000000000040022000000000002080000007c002080400000000000000000000000000000000000010448100001080 +% 8000000000000c000000000006c001c00000000000318000000540031804000000000000000000000000000000000000104c8100001080 +% 80000000000078000000000005c003200000000000190000000540019004000000000000000000000000000000000000103b0100001080 +% 8000000000007000000000000540022000000000001c00000007c001c001fc000000000000000000000000000000000010008100001080 +% 8000000000000c000000000005400220000000000032000000000003200190000000000000000000000000000000000010008100001080 +% 800000000000780000000000024001c0000000000022000000000002200110000000000000000000000000000000000010708100001080 +% 800000000000700000000000000000000000000000220000000000022001100000000000000000000000000000000000101c8100001080 +% 8000000000000c0000000000000003e000000000003f800000000003f800e0000000000000000000000000000000000010028100001080 +% 800000000000000000000000000000200000000000000000000000000001fc000000000000000000000000000000000010018100001080 +% 8000000000007c00000000000000036000000000001c000000000001c00190000000000000000000000000000000000010000100001080 +% 800000000000040000000000000002e000000000003e000000000003e00110000000000000000000000000000000000010000100001080 +% 8000000000007f0000000000000002a000000000002a000000000002a00110000000000000000000000000000000000010000100001080 +% 800000000000180000000000000002a000000000002a000000000002a000e0000000000000000000000000000000000010000100001080 +% 8000000000001800000000000000012000000000003e000000000003e00000000000000000000000000000000000000010420100001080 +% 80000000000034000000000000000000000000000036000000000003600000000000000000000000000000000000000010738100001080 +% 8000000000004000000000000000000000000000002e000000000002e00000000000000000000000000000000000000010588100001080 +% 8000000000000000000000000000000000000000002a000000000002a00000000000000000000000000000000000000010488100001080 +% 8000000000000000000000000000000000000000002a000000000002a000000000000000000000000000000000000000104c8100001080 +% 80000000000000000000000000000000000000000012000000000001200000000000000000000000000000000000000010478100001080 +% 8000000000000000000000000000000000000000001c000000000001c00000000000000000000000000000000000000010000100001080 +% 80000000000000000000000000000000000000000032000000000003200000000000000000000000000000000000000010000100001080 +% 800000000000000000000000000000000000000000220000000000022000000000000000000000000000000000000000103f8100001080 +% 80000000000000000000000000000000000000000022000000000002200000000000000000000000000000000000000010618100001080 +% 80000000000000000000000000000000000000000016000000000001600000000000000000000000000000000000000010408100001080 +% 80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010618100001080 +% 8000000000000000000000000000000000000000003e000000000003e000000000000000000000000000000000000000103f0100001080 +% 80000000000000000000000000000000000000000002000000000000200000000000000000000000000000000000000010000100001080 +% 80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000103f8100001080 +% 80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010618100001080 +% 80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010408100001080 +% 80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010618100001080 +% 800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000103f0100001080 +% 80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010010100001080 +% 80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010010100001080 +% 800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000107f8100001080 +% 80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000100001080 +% 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001ffffffffff080 +% 80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080 +% 80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080 +% 80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080 +% 80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080 +% ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80 +%%EndImage +%%EndPreview +save +countdictstack +mark +newpath +/showpage {} def +/setpagedevice {pop} def +%%EndProlog +%%Page 1 1 + +-90 rotate +-756.000000 72.000000 translate +/HE10 /Helvetica findfont 10 scalefont def +/HE12 /Helvetica findfont 12 scalefont def +newpath +0 0 moveto +0 432.000000 rlineto +648.000000 0 rlineto +0 -432.000000 rlineto +closepath +0.500000 setlinewidth +stroke +newpath +5.000000 387.000000 moveto +0 40.000000 rlineto +638.000000 0 rlineto +0 -40.000000 rlineto +closepath +0.500000 setlinewidth +stroke +5.000000 407.000000 moveto +638.000000 0 rlineto +stroke +HE12 setfont +11.000000 413.000000 moveto +(cacheprof_p -ghc-timing +RTS -H10m -K10m -p -hR -i1.0 -sstderr +) show +HE12 setfont +11.000000 393.000000 moveto +(22,191,444 bytes x seconds (MUT)) +show +HE12 setfont +(Thu Aug 23 17:37 2001) +dup stringwidth pop +637.000000 +exch sub +393.000000 moveto +show +45.000000 20.000000 moveto +431.338567 0 rlineto +0.500000 setlinewidth +stroke +HE10 setfont +(seconds (MUT)) +dup stringwidth pop +476.338567 +exch sub +5.000000 moveto +show +45.000000 20.000000 moveto +0 -4 rlineto +stroke +HE10 setfont +(0.0) +dup stringwidth pop +2 div +45.000000 exch sub +5.000000 moveto +show +135.712632 20.000000 moveto +0 -4 rlineto +stroke +HE10 setfont +(2.0) +dup stringwidth pop +2 div +135.712632 exch sub +5.000000 moveto +show +226.425265 20.000000 moveto +0 -4 rlineto +stroke +HE10 setfont +(4.0) +dup stringwidth pop +2 div +226.425265 exch sub +5.000000 moveto +show +317.137897 20.000000 moveto +0 -4 rlineto +stroke +HE10 setfont +(6.0) +dup stringwidth pop +2 div +317.137897 exch sub +5.000000 moveto +show +45.000000 20.000000 moveto +0 362.000000 rlineto +0.500000 setlinewidth +stroke +gsave +HE10 setfont +(bytes) +dup stringwidth pop +382.000000 +exch sub +40.000000 exch +translate +90 rotate +0 0 moveto +show +grestore +45.000000 20.000000 moveto +-4 0 rlineto +stroke +HE10 setfont +(0k) +dup stringwidth +2 div +20.000000 exch sub +exch +40.000000 exch sub +exch +moveto +show +45.000000 56.751299 moveto +-4 0 rlineto +stroke +HE10 setfont +(500k) +dup stringwidth +2 div +56.751299 exch sub +exch +40.000000 exch sub +exch +moveto +show +45.000000 93.502598 moveto +-4 0 rlineto +stroke +HE10 setfont +(1,000k) +dup stringwidth +2 div +93.502598 exch sub +exch +40.000000 exch sub +exch +moveto +show +45.000000 130.253897 moveto +-4 0 rlineto +stroke +HE10 setfont +(1,500k) +dup stringwidth +2 div +130.253897 exch sub +exch +40.000000 exch sub +exch +moveto +show +45.000000 167.005196 moveto +-4 0 rlineto +stroke +HE10 setfont +(2,000k) +dup stringwidth +2 div +167.005196 exch sub +exch +40.000000 exch sub +exch +moveto +show +45.000000 203.756494 moveto +-4 0 rlineto +stroke +HE10 setfont +(2,500k) +dup stringwidth +2 div +203.756494 exch sub +exch +40.000000 exch sub +exch +moveto +show +45.000000 240.507793 moveto +-4 0 rlineto +stroke +HE10 setfont +(3,000k) +dup stringwidth +2 div +240.507793 exch sub +exch +40.000000 exch sub +exch +moveto +show +45.000000 277.259092 moveto +-4 0 rlineto +stroke +HE10 setfont +(3,500k) +dup stringwidth +2 div +277.259092 exch sub +exch +40.000000 exch sub +exch +moveto +show +45.000000 314.010391 moveto +-4 0 rlineto +stroke +HE10 setfont +(4,000k) +dup stringwidth +2 div +314.010391 exch sub +exch +40.000000 exch sub +exch +moveto +show +481.338567 30.238095 moveto +0 14 rlineto +14 0 rlineto +0 -14 rlineto +closepath +gsave +0.000000 setgray +fill +grestore +stroke +HE10 setfont +500.338567 32.238095 moveto +(OTHER) show +481.338567 47.476190 moveto +0 14 rlineto +14 0 rlineto +0 -14 rlineto +closepath +gsave +0.200000 setgray +fill +grestore +stroke +HE10 setfont +500.338567 49.476190 moveto +((57)synth_2,addCCs_wrk) show +481.338567 64.714286 moveto +0 14 rlineto +14 0 rlineto +0 -14 rlineto +closepath +gsave +0.600000 setgray +fill +grestore +stroke +HE10 setfont +500.338567 66.714286 moveto +((15)parse) show +481.338567 81.952381 moveto +0 14 rlineto +14 0 rlineto +0 -14 rlineto +closepath +gsave +0.300000 setgray +fill +grestore +stroke +HE10 setfont +500.338567 83.952381 moveto +((95)SYSTEM,use_bb) show +481.338567 99.190476 moveto +0 14 rlineto +14 0 rlineto +0 -14 rlineto +closepath +gsave +0.900000 setgray +fill +grestore +stroke +HE10 setfont +500.338567 101.190476 moveto +((164)useCCdescriptors) show +481.338567 116.428571 moveto +0 14 rlineto +14 0 rlineto +0 -14 rlineto +closepath +gsave +0.400000 setgray +fill +grestore +stroke +HE10 setfont +500.338567 118.428571 moveto +((133)makeCCdescriptors) show +481.338567 133.666667 moveto +0 14 rlineto +14 0 rlineto +0 -14 rlineto +closepath +gsave +1.000000 setgray +fill +grestore +stroke +HE10 setfont +500.338567 135.666667 moveto +((29)main) show +481.338567 150.904762 moveto +0 14 rlineto +14 0 rlineto +0 -14 rlineto +closepath +gsave +0.700000 setgray +fill +grestore +stroke +HE10 setfont +500.338567 152.904762 moveto +((55)annotate_insn) show +481.338567 168.142857 moveto +0 14 rlineto +14 0 rlineto +0 -14 rlineto +closepath +gsave +0.500000 setgray +fill +grestore +stroke +HE10 setfont +500.338567 170.142857 moveto +((111)synth_2,makeCCdescr) show +481.338567 185.380952 moveto +0 14 rlineto +14 0 rlineto +0 -14 rlineto +closepath +gsave +0.800000 setgray +fill +grestore +stroke +HE10 setfont +500.338567 187.380952 moveto +((27)preparse) show +481.338567 202.619048 moveto +0 14 rlineto +14 0 rlineto +0 -14 rlineto +closepath +gsave +0.000000 setgray +fill +grestore +stroke +HE10 setfont +500.338567 204.619048 moveto +((117)use_bb,synthLine) show +481.338567 219.857143 moveto +0 14 rlineto +14 0 rlineto +0 -14 rlineto +closepath +gsave +0.200000 setgray +fill +grestore +stroke +HE10 setfont +500.338567 221.857143 moveto +((114)synth_2,makeCCdescr) show +481.338567 237.095238 moveto +0 14 rlineto +14 0 rlineto +0 -14 rlineto +closepath +gsave +0.600000 setgray +fill +grestore +stroke +HE10 setfont +500.338567 239.095238 moveto +((59)addCCs_wrk,use_bb) show +481.338567 254.333333 moveto +0 14 rlineto +14 0 rlineto +0 -14 rlineto +closepath +gsave +0.300000 setgray +fill +grestore +stroke +HE10 setfont +500.338567 256.333333 moveto +((52)synth_2,use_bb) show +481.338567 271.571429 moveto +0 14 rlineto +14 0 rlineto +0 -14 rlineto +closepath +gsave +0.900000 setgray +fill +grestore +stroke +HE10 setfont +500.338567 273.571429 moveto +((112)synthLine) show +481.338567 288.809524 moveto +0 14 rlineto +14 0 rlineto +0 -14 rlineto +closepath +gsave +0.400000 setgray +fill +grestore +stroke +HE10 setfont +500.338567 290.809524 moveto +((62)SYSTEM,synth_2) show +481.338567 306.047619 moveto +0 14 rlineto +14 0 rlineto +0 -14 rlineto +closepath +gsave +1.000000 setgray +fill +grestore +stroke +HE10 setfont +500.338567 308.047619 moveto +((43)addCCs_wrk) show +481.338567 323.285714 moveto +0 14 rlineto +14 0 rlineto +0 -14 rlineto +closepath +gsave +0.700000 setgray +fill +grestore +stroke +HE10 setfont +500.338567 325.285714 moveto +((48)use_bb) show +481.338567 340.523810 moveto +0 14 rlineto +14 0 rlineto +0 -14 rlineto +closepath +gsave +0.500000 setgray +fill +grestore +stroke +HE10 setfont +500.338567 342.523810 moveto +((1)SYSTEM) show +481.338567 357.761905 moveto +0 14 rlineto +14 0 rlineto +0 -14 rlineto +closepath +gsave +0.800000 setgray +fill +grestore +stroke +HE10 setfont +500.338567 359.761905 moveto +((45)synth_2) show +45.000000 20.000000 moveto +45.000000 20.000000 lineto +88.542064 20.000000 lineto +125.280680 20.000000 lineto +160.658606 20.000000 lineto +191.954465 20.000000 lineto +221.889633 20.000000 lineto +249.556986 20.000000 lineto +275.410086 20.000000 lineto +298.541808 20.000000 lineto +316.230771 20.000000 lineto +330.291229 20.000000 lineto +356.144329 20.000000 lineto +386.533061 20.000000 lineto +421.457425 20.000000 lineto +459.556730 20.000000 lineto +476.338567 20.000000 lineto +476.338567 20.000000 lineto +476.338567 20.000000 lineto +459.556730 20.618304 lineto +421.457425 28.827368 lineto +386.533061 20.618304 lineto +356.144329 20.618304 lineto +330.291229 20.618304 lineto +316.230771 28.577459 lineto +298.541808 20.618304 lineto +275.410086 20.618304 lineto +249.556986 20.618304 lineto +221.889633 20.618304 lineto +191.954465 20.618304 lineto +160.658606 20.618304 lineto +125.280680 20.618304 lineto +88.542064 20.618304 lineto +45.000000 20.000000 lineto +closepath +gsave +0.000000 setgray +fill +grestore +stroke +45.000000 20.000000 moveto +45.000000 20.000000 lineto +88.542064 20.618304 lineto +125.280680 20.618304 lineto +160.658606 20.618304 lineto +191.954465 20.618304 lineto +221.889633 20.618304 lineto +249.556986 20.618304 lineto +275.410086 20.618304 lineto +298.541808 20.618304 lineto +316.230771 28.577459 lineto +330.291229 20.618304 lineto +356.144329 20.618304 lineto +386.533061 20.618304 lineto +421.457425 28.827368 lineto +459.556730 20.618304 lineto +476.338567 20.000000 lineto +476.338567 20.000000 lineto +476.338567 20.000000 lineto +459.556730 20.618304 lineto +421.457425 28.827368 lineto +386.533061 20.618304 lineto +356.144329 20.654467 lineto +330.291229 21.323929 lineto +316.230771 28.577459 lineto +298.541808 21.736719 lineto +275.410086 21.736719 lineto +249.556986 21.736719 lineto +221.889633 21.736719 lineto +191.954465 21.736719 lineto +160.658606 21.700556 lineto +125.280680 21.571780 lineto +88.542064 20.955240 lineto +45.000000 20.000000 lineto +closepath +gsave +0.200000 setgray +fill +grestore +stroke +45.000000 20.000000 moveto +45.000000 20.000000 lineto +88.542064 20.955240 lineto +125.280680 21.571780 lineto +160.658606 21.700556 lineto +191.954465 21.736719 lineto +221.889633 21.736719 lineto +249.556986 21.736719 lineto +275.410086 21.736719 lineto +298.541808 21.736719 lineto +316.230771 28.577459 lineto +330.291229 21.323929 lineto +356.144329 20.654467 lineto +386.533061 20.618304 lineto +421.457425 28.827368 lineto +459.556730 20.618304 lineto +476.338567 20.000000 lineto +476.338567 20.000000 lineto +476.338567 20.000000 lineto +459.556730 20.618304 lineto +421.457425 28.827368 lineto +386.533061 20.618304 lineto +356.144329 20.654467 lineto +330.291229 21.323929 lineto +316.230771 28.577459 lineto +298.541808 23.214416 lineto +275.410086 23.213534 lineto +249.556986 23.213534 lineto +221.889633 23.074761 lineto +191.954465 23.074761 lineto +160.658606 21.700556 lineto +125.280680 22.833966 lineto +88.542064 21.955757 lineto +45.000000 20.000000 lineto +closepath +gsave +0.600000 setgray +fill +grestore +stroke +45.000000 20.000000 moveto +45.000000 20.000000 lineto +88.542064 21.955757 lineto +125.280680 22.833966 lineto +160.658606 21.700556 lineto +191.954465 23.074761 lineto +221.889633 23.074761 lineto +249.556986 23.213534 lineto +275.410086 23.213534 lineto +298.541808 23.214416 lineto +316.230771 28.577459 lineto +330.291229 21.323929 lineto +356.144329 20.654467 lineto +386.533061 20.618304 lineto +421.457425 28.827368 lineto +459.556730 20.618304 lineto +476.338567 20.000000 lineto +476.338567 20.000000 lineto +476.338567 20.000000 lineto +459.556730 20.618304 lineto +421.457425 28.827368 lineto +386.533061 20.618304 lineto +356.144329 20.654467 lineto +330.291229 21.323929 lineto +316.230771 38.031951 lineto +298.541808 23.214416 lineto +275.410086 23.213534 lineto +249.556986 23.213534 lineto +221.889633 23.074761 lineto +191.954465 23.074761 lineto +160.658606 21.700556 lineto +125.280680 22.833966 lineto +88.542064 21.955757 lineto +45.000000 20.000000 lineto +closepath +gsave +0.300000 setgray +fill +grestore +stroke +45.000000 20.000000 moveto +45.000000 20.000000 lineto +88.542064 21.955757 lineto +125.280680 22.833966 lineto +160.658606 21.700556 lineto +191.954465 23.074761 lineto +221.889633 23.074761 lineto +249.556986 23.213534 lineto +275.410086 23.213534 lineto +298.541808 23.214416 lineto +316.230771 38.031951 lineto +330.291229 21.323929 lineto +356.144329 20.654467 lineto +386.533061 20.618304 lineto +421.457425 28.827368 lineto +459.556730 20.618304 lineto +476.338567 20.000000 lineto +476.338567 20.000000 lineto +476.338567 20.000000 lineto +459.556730 31.040972 lineto +421.457425 28.827368 lineto +386.533061 20.618304 lineto +356.144329 20.654467 lineto +330.291229 21.323929 lineto +316.230771 38.031951 lineto +298.541808 23.214416 lineto +275.410086 23.213534 lineto +249.556986 23.213534 lineto +221.889633 23.074761 lineto +191.954465 23.074761 lineto +160.658606 21.700556 lineto +125.280680 22.833966 lineto +88.542064 21.955757 lineto +45.000000 20.000000 lineto +closepath +gsave +0.900000 setgray +fill +grestore +stroke +45.000000 20.000000 moveto +45.000000 20.000000 lineto +88.542064 21.955757 lineto +125.280680 22.833966 lineto +160.658606 21.700556 lineto +191.954465 23.074761 lineto +221.889633 23.074761 lineto +249.556986 23.213534 lineto +275.410086 23.213534 lineto +298.541808 23.214416 lineto +316.230771 38.031951 lineto +330.291229 21.323929 lineto +356.144329 20.654467 lineto +386.533061 20.618304 lineto +421.457425 28.827368 lineto +459.556730 31.040972 lineto +476.338567 20.000000 lineto +476.338567 20.000000 lineto +476.338567 20.000000 lineto +459.556730 31.040972 lineto +421.457425 41.485985 lineto +386.533061 20.620068 lineto +356.144329 20.656231 lineto +330.291229 21.325693 lineto +316.230771 38.031951 lineto +298.541808 23.214416 lineto +275.410086 23.213534 lineto +249.556986 23.213534 lineto +221.889633 23.074761 lineto +191.954465 23.074761 lineto +160.658606 21.700556 lineto +125.280680 22.833966 lineto +88.542064 21.955757 lineto +45.000000 20.000000 lineto +closepath +gsave +0.400000 setgray +fill +grestore +stroke +45.000000 20.000000 moveto +45.000000 20.000000 lineto +88.542064 21.955757 lineto +125.280680 22.833966 lineto +160.658606 21.700556 lineto +191.954465 23.074761 lineto +221.889633 23.074761 lineto +249.556986 23.213534 lineto +275.410086 23.213534 lineto +298.541808 23.214416 lineto +316.230771 38.031951 lineto +330.291229 21.325693 lineto +356.144329 20.656231 lineto +386.533061 20.620068 lineto +421.457425 41.485985 lineto +459.556730 31.040972 lineto +476.338567 20.000000 lineto +476.338567 20.000000 lineto +476.338567 20.000000 lineto +459.556730 31.679269 lineto +421.457425 42.124282 lineto +386.533061 21.258364 lineto +356.144329 21.294528 lineto +330.291229 21.963989 lineto +316.230771 39.278849 lineto +298.541808 24.455433 lineto +275.410086 24.454551 lineto +249.556986 24.454551 lineto +221.889633 24.315779 lineto +191.954465 24.315779 lineto +160.658606 22.941574 lineto +125.280680 24.074984 lineto +88.542064 23.196775 lineto +45.000000 20.000000 lineto +closepath +gsave +1.000000 setgray +fill +grestore +stroke +45.000000 20.000000 moveto +45.000000 20.000000 lineto +88.542064 23.196775 lineto +125.280680 24.074984 lineto +160.658606 22.941574 lineto +191.954465 24.315779 lineto +221.889633 24.315779 lineto +249.556986 24.454551 lineto +275.410086 24.454551 lineto +298.541808 24.455433 lineto +316.230771 39.278849 lineto +330.291229 21.963989 lineto +356.144329 21.294528 lineto +386.533061 21.258364 lineto +421.457425 42.124282 lineto +459.556730 31.679269 lineto +476.338567 20.000000 lineto +476.338567 20.000000 lineto +476.338567 20.000000 lineto +459.556730 31.679269 lineto +421.457425 42.124282 lineto +386.533061 22.023968 lineto +356.144329 22.922757 lineto +330.291229 23.872705 lineto +316.230771 41.524501 lineto +298.541808 26.559960 lineto +275.410086 26.340334 lineto +249.556986 26.038679 lineto +221.889633 25.642353 lineto +191.954465 25.245439 lineto +160.658606 23.546647 lineto +125.280680 24.593618 lineto +88.542064 23.493137 lineto +45.000000 20.000000 lineto +closepath +gsave +0.700000 setgray +fill +grestore +stroke +45.000000 20.000000 moveto +45.000000 20.000000 lineto +88.542064 23.493137 lineto +125.280680 24.593618 lineto +160.658606 23.546647 lineto +191.954465 25.245439 lineto +221.889633 25.642353 lineto +249.556986 26.038679 lineto +275.410086 26.340334 lineto +298.541808 26.559960 lineto +316.230771 41.524501 lineto +330.291229 23.872705 lineto +356.144329 22.922757 lineto +386.533061 22.023968 lineto +421.457425 42.124282 lineto +459.556730 31.679269 lineto +476.338567 20.000000 lineto +476.338567 20.000000 lineto +476.338567 20.000000 lineto +459.556730 31.679269 lineto +421.457425 42.278637 lineto +386.533061 31.368500 lineto +356.144329 28.080582 lineto +330.291229 25.593548 lineto +316.230771 41.524501 lineto +298.541808 26.559960 lineto +275.410086 26.340334 lineto +249.556986 26.038679 lineto +221.889633 25.642353 lineto +191.954465 25.245439 lineto +160.658606 23.546647 lineto +125.280680 24.593618 lineto +88.542064 23.493137 lineto +45.000000 20.000000 lineto +closepath +gsave +0.500000 setgray +fill +grestore +stroke +45.000000 20.000000 moveto +45.000000 20.000000 lineto +88.542064 23.493137 lineto +125.280680 24.593618 lineto +160.658606 23.546647 lineto +191.954465 25.245439 lineto +221.889633 25.642353 lineto +249.556986 26.038679 lineto +275.410086 26.340334 lineto +298.541808 26.559960 lineto +316.230771 41.524501 lineto +330.291229 25.593548 lineto +356.144329 28.080582 lineto +386.533061 31.368500 lineto +421.457425 42.278637 lineto +459.556730 31.679269 lineto +476.338567 20.000000 lineto +476.338567 20.000000 lineto +476.338567 20.000000 lineto +459.556730 31.679269 lineto +421.457425 42.278637 lineto +386.533061 31.368500 lineto +356.144329 28.080582 lineto +330.291229 25.593548 lineto +316.230771 41.524501 lineto +298.541808 32.677140 lineto +275.410086 32.867659 lineto +249.556986 27.036551 lineto +221.889633 29.209581 lineto +191.954465 32.384894 lineto +160.658606 24.587738 lineto +125.280680 24.605379 lineto +88.542064 29.373933 lineto +45.000000 20.000000 lineto +closepath +gsave +0.800000 setgray +fill +grestore +stroke +45.000000 20.000000 moveto +45.000000 20.000000 lineto +88.542064 29.373933 lineto +125.280680 24.605379 lineto +160.658606 24.587738 lineto +191.954465 32.384894 lineto +221.889633 29.209581 lineto +249.556986 27.036551 lineto +275.410086 32.867659 lineto +298.541808 32.677140 lineto +316.230771 41.524501 lineto +330.291229 25.593548 lineto +356.144329 28.080582 lineto +386.533061 31.368500 lineto +421.457425 42.278637 lineto +459.556730 31.679269 lineto +476.338567 20.000000 lineto +476.338567 20.000000 lineto +476.338567 20.000000 lineto +459.556730 31.679269 lineto +421.457425 42.278637 lineto +386.533061 35.123306 lineto +356.144329 36.264949 lineto +330.291229 35.930071 lineto +316.230771 53.392818 lineto +298.541808 32.677140 lineto +275.410086 32.867659 lineto +249.556986 27.036551 lineto +221.889633 29.209581 lineto +191.954465 32.384894 lineto +160.658606 24.587738 lineto +125.280680 24.605379 lineto +88.542064 29.373933 lineto +45.000000 20.000000 lineto +closepath +gsave +0.000000 setgray +fill +grestore +stroke +45.000000 20.000000 moveto +45.000000 20.000000 lineto +88.542064 29.373933 lineto +125.280680 24.605379 lineto +160.658606 24.587738 lineto +191.954465 32.384894 lineto +221.889633 29.209581 lineto +249.556986 27.036551 lineto +275.410086 32.867659 lineto +298.541808 32.677140 lineto +316.230771 53.392818 lineto +330.291229 35.930071 lineto +356.144329 36.264949 lineto +386.533061 35.123306 lineto +421.457425 42.278637 lineto +459.556730 31.679269 lineto +476.338567 20.000000 lineto +476.338567 20.000000 lineto +476.338567 20.000000 lineto +459.556730 31.679269 lineto +421.457425 42.278637 lineto +386.533061 39.445259 lineto +356.144329 44.770669 lineto +330.291229 47.872773 lineto +316.230771 65.212036 lineto +298.541808 32.677140 lineto +275.410086 32.867659 lineto +249.556986 27.036551 lineto +221.889633 29.209581 lineto +191.954465 32.384894 lineto +160.658606 24.587738 lineto +125.280680 24.605379 lineto +88.542064 29.373933 lineto +45.000000 20.000000 lineto +closepath +gsave +0.200000 setgray +fill +grestore +stroke +45.000000 20.000000 moveto +45.000000 20.000000 lineto +88.542064 29.373933 lineto +125.280680 24.605379 lineto +160.658606 24.587738 lineto +191.954465 32.384894 lineto +221.889633 29.209581 lineto +249.556986 27.036551 lineto +275.410086 32.867659 lineto +298.541808 32.677140 lineto +316.230771 65.212036 lineto +330.291229 47.872773 lineto +356.144329 44.770669 lineto +386.533061 39.445259 lineto +421.457425 42.278637 lineto +459.556730 31.679269 lineto +476.338567 20.000000 lineto +476.338567 20.000000 lineto +476.338567 20.000000 lineto +459.556730 31.679269 lineto +421.457425 42.278637 lineto +386.533061 39.445259 lineto +356.144329 44.770669 lineto +330.291229 47.872773 lineto +316.230771 65.212036 lineto +298.541808 45.475412 lineto +275.410086 44.560452 lineto +249.556986 37.761462 lineto +221.889633 37.820558 lineto +191.954465 38.949558 lineto +160.658606 29.876397 lineto +125.280680 28.824428 lineto +88.542064 32.072361 lineto +45.000000 20.000000 lineto +closepath +gsave +0.600000 setgray +fill +grestore +stroke +45.000000 20.000000 moveto +45.000000 20.000000 lineto +88.542064 32.072361 lineto +125.280680 28.824428 lineto +160.658606 29.876397 lineto +191.954465 38.949558 lineto +221.889633 37.820558 lineto +249.556986 37.761462 lineto +275.410086 44.560452 lineto +298.541808 45.475412 lineto +316.230771 65.212036 lineto +330.291229 47.872773 lineto +356.144329 44.770669 lineto +386.533061 39.445259 lineto +421.457425 42.278637 lineto +459.556730 31.679269 lineto +476.338567 20.000000 lineto +476.338567 20.000000 lineto +476.338567 20.000000 lineto +459.556730 31.679269 lineto +421.457425 42.278637 lineto +386.533061 41.769117 lineto +356.144329 48.957965 lineto +330.291229 55.205392 lineto +316.230771 65.212036 lineto +298.541808 55.455301 lineto +275.410086 53.812665 lineto +249.556986 46.138112 lineto +221.889633 45.465122 lineto +191.954465 45.850276 lineto +160.658606 35.922721 lineto +125.280680 33.236054 lineto +88.542064 34.512353 lineto +45.000000 20.000000 lineto +closepath +gsave +0.300000 setgray +fill +grestore +stroke +45.000000 20.000000 moveto +45.000000 20.000000 lineto +88.542064 34.512353 lineto +125.280680 33.236054 lineto +160.658606 35.922721 lineto +191.954465 45.850276 lineto +221.889633 45.465122 lineto +249.556986 46.138112 lineto +275.410086 53.812665 lineto +298.541808 55.455301 lineto +316.230771 65.212036 lineto +330.291229 55.205392 lineto +356.144329 48.957965 lineto +386.533061 41.769117 lineto +421.457425 42.278637 lineto +459.556730 31.679269 lineto +476.338567 20.000000 lineto +476.338567 20.000000 lineto +476.338567 20.000000 lineto +459.556730 31.679269 lineto +421.457425 42.278637 lineto +386.533061 57.202311 lineto +356.144329 78.538645 lineto +330.291229 96.945459 lineto +316.230771 105.991277 lineto +298.541808 55.455301 lineto +275.410086 53.812665 lineto +249.556986 46.138112 lineto +221.889633 45.465122 lineto +191.954465 45.850276 lineto +160.658606 35.922721 lineto +125.280680 33.236054 lineto +88.542064 34.512353 lineto +45.000000 20.000000 lineto +closepath +gsave +0.900000 setgray +fill +grestore +stroke +45.000000 20.000000 moveto +45.000000 20.000000 lineto +88.542064 34.512353 lineto +125.280680 33.236054 lineto +160.658606 35.922721 lineto +191.954465 45.850276 lineto +221.889633 45.465122 lineto +249.556986 46.138112 lineto +275.410086 53.812665 lineto +298.541808 55.455301 lineto +316.230771 105.991277 lineto +330.291229 96.945459 lineto +356.144329 78.538645 lineto +386.533061 57.202311 lineto +421.457425 42.278637 lineto +459.556730 31.679269 lineto +476.338567 20.000000 lineto +476.338567 20.000000 lineto +476.338567 20.000000 lineto +459.556730 31.679269 lineto +421.457425 42.279519 lineto +386.533061 57.202311 lineto +356.144329 78.538645 lineto +330.291229 96.945459 lineto +316.230771 125.536500 lineto +298.541808 83.504186 lineto +275.410086 79.552981 lineto +249.556986 69.332298 lineto +221.889633 65.722732 lineto +191.954465 63.020776 lineto +160.658606 49.723863 lineto +125.280680 43.050415 lineto +88.542064 40.162351 lineto +45.000000 20.000000 lineto +closepath +gsave +0.400000 setgray +fill +grestore +stroke +45.000000 20.000000 moveto +45.000000 20.000000 lineto +88.542064 40.162351 lineto +125.280680 43.050415 lineto +160.658606 49.723863 lineto +191.954465 63.020776 lineto +221.889633 65.722732 lineto +249.556986 69.332298 lineto +275.410086 79.552981 lineto +298.541808 83.504186 lineto +316.230771 125.536500 lineto +330.291229 96.945459 lineto +356.144329 78.538645 lineto +386.533061 57.202311 lineto +421.457425 42.279519 lineto +459.556730 31.679269 lineto +476.338567 20.000000 lineto +476.338567 20.000000 lineto +476.338567 20.000000 lineto +459.556730 31.679269 lineto +421.457425 42.353610 lineto +386.533061 58.459793 lineto +356.144329 79.759964 lineto +330.291229 97.497317 lineto +316.230771 125.675567 lineto +298.541808 138.035176 lineto +275.410086 128.812658 lineto +249.556986 111.126757 lineto +221.889633 101.413535 lineto +191.954465 91.637396 lineto +160.658606 70.610949 lineto +125.280680 55.169523 lineto +88.542064 45.801764 lineto +45.000000 20.000000 lineto +closepath +gsave +1.000000 setgray +fill +grestore +stroke +45.000000 20.000000 moveto +45.000000 20.000000 lineto +88.542064 45.801764 lineto +125.280680 55.169523 lineto +160.658606 70.610949 lineto +191.954465 91.637396 lineto +221.889633 101.413535 lineto +249.556986 111.126757 lineto +275.410086 128.812658 lineto +298.541808 138.035176 lineto +316.230771 125.675567 lineto +330.291229 97.497317 lineto +356.144329 79.759964 lineto +386.533061 58.459793 lineto +421.457425 42.353610 lineto +459.556730 31.679269 lineto +476.338567 20.000000 lineto +476.338567 20.000000 lineto +476.338567 20.000000 lineto +459.556730 31.679269 lineto +421.457425 42.353610 lineto +386.533061 70.083200 lineto +356.144329 103.293144 lineto +330.291229 132.934977 lineto +316.230771 172.460852 lineto +298.541808 182.646548 lineto +275.410086 169.982933 lineto +249.556986 148.411390 lineto +221.889633 133.790548 lineto +191.954465 118.811600 lineto +160.658606 93.317371 lineto +125.280680 71.339506 lineto +88.542064 55.072500 lineto +45.000000 20.000000 lineto +closepath +gsave +0.700000 setgray +fill +grestore +stroke +45.000000 20.000000 moveto +45.000000 20.000000 lineto +88.542064 55.072500 lineto +125.280680 71.339506 lineto +160.658606 93.317371 lineto +191.954465 118.811600 lineto +221.889633 133.790548 lineto +249.556986 148.411390 lineto +275.410086 169.982933 lineto +298.541808 182.646548 lineto +316.230771 172.460852 lineto +330.291229 132.934977 lineto +356.144329 103.293144 lineto +386.533061 70.083200 lineto +421.457425 42.353610 lineto +459.556730 31.679269 lineto +476.338567 20.000000 lineto +476.338567 20.000000 lineto +476.338567 20.000000 lineto +459.556730 51.559663 lineto +421.457425 63.454442 lineto +386.533061 89.964183 lineto +356.144329 123.181477 lineto +330.291229 152.819782 lineto +316.230771 341.486250 lineto +298.541808 226.567291 lineto +275.410086 210.440821 lineto +249.556986 185.053905 lineto +221.889633 166.048486 lineto +191.954465 146.420940 lineto +160.658606 117.332434 lineto +125.280680 90.502222 lineto +88.542064 65.399909 lineto +45.000000 20.000000 lineto +closepath +gsave +0.500000 setgray +fill +grestore +stroke +45.000000 20.000000 moveto +45.000000 20.000000 lineto +88.542064 65.399909 lineto +125.280680 90.502222 lineto +160.658606 117.332434 lineto +191.954465 146.420940 lineto +221.889633 166.048486 lineto +249.556986 185.053905 lineto +275.410086 210.440821 lineto +298.541808 226.567291 lineto +316.230771 341.486250 lineto +330.291229 152.819782 lineto +356.144329 123.181477 lineto +386.533061 89.964183 lineto +421.457425 63.454442 lineto +459.556730 51.559663 lineto +476.338567 20.000000 lineto +476.338567 20.000000 lineto +476.338567 20.000000 lineto +459.556730 51.559663 lineto +421.457425 63.528532 lineto +386.533061 140.979690 lineto +356.144329 216.546240 lineto +330.291229 287.298665 lineto +316.230771 348.276126 lineto +298.541808 382.000000 lineto +275.410086 353.331635 lineto +249.556986 315.505140 lineto +221.889633 281.057412 lineto +191.954465 246.046949 lineto +160.658606 196.150446 lineto +125.280680 147.445272 lineto +88.542064 98.116209 lineto +45.000000 20.000000 lineto +closepath +gsave +0.800000 setgray +fill +grestore +stroke +84.542064 20.000000 moveto +4.000000 -4.000000 rlineto +4.000000 4.000000 rlineto +closepath +gsave +1.0 setgray +fill +grestore +stroke +121.280680 20.000000 moveto +4.000000 -4.000000 rlineto +4.000000 4.000000 rlineto +closepath +gsave +1.0 setgray +fill +grestore +stroke +156.658606 20.000000 moveto +4.000000 -4.000000 rlineto +4.000000 4.000000 rlineto +closepath +gsave +1.0 setgray +fill +grestore +stroke +187.954465 20.000000 moveto +4.000000 -4.000000 rlineto +4.000000 4.000000 rlineto +closepath +gsave +1.0 setgray +fill +grestore +stroke +217.889633 20.000000 moveto +4.000000 -4.000000 rlineto +4.000000 4.000000 rlineto +closepath +gsave +1.0 setgray +fill +grestore +stroke +245.556986 20.000000 moveto +4.000000 -4.000000 rlineto +4.000000 4.000000 rlineto +closepath +gsave +1.0 setgray +fill +grestore +stroke +271.410086 20.000000 moveto +4.000000 -4.000000 rlineto +4.000000 4.000000 rlineto +closepath +gsave +1.0 setgray +fill +grestore +stroke +294.541808 20.000000 moveto +4.000000 -4.000000 rlineto +4.000000 4.000000 rlineto +closepath +gsave +1.0 setgray +fill +grestore +stroke +312.230771 20.000000 moveto +4.000000 -4.000000 rlineto +4.000000 4.000000 rlineto +closepath +gsave +1.0 setgray +fill +grestore +stroke +326.291229 20.000000 moveto +4.000000 -4.000000 rlineto +4.000000 4.000000 rlineto +closepath +gsave +1.0 setgray +fill +grestore +stroke +352.144329 20.000000 moveto +4.000000 -4.000000 rlineto +4.000000 4.000000 rlineto +closepath +gsave +1.0 setgray +fill +grestore +stroke +382.533061 20.000000 moveto +4.000000 -4.000000 rlineto +4.000000 4.000000 rlineto +closepath +gsave +1.0 setgray +fill +grestore +stroke +417.457425 20.000000 moveto +4.000000 -4.000000 rlineto +4.000000 4.000000 rlineto +closepath +gsave +1.0 setgray +fill +grestore +stroke +455.556730 20.000000 moveto +4.000000 -4.000000 rlineto +4.000000 4.000000 rlineto +closepath +gsave +1.0 setgray +fill +grestore +stroke +showpage +%%Trailer +cleartomark +countdictstack exch sub { end } repeat +restore +%%EOF diff --git a/docs/storage-mgt/code.sty b/docs/storage-mgt/code.sty new file mode 100644 index 0000000000..f5ec2f59ee --- /dev/null +++ b/docs/storage-mgt/code.sty @@ -0,0 +1,83 @@ +
+% I have enclosed code.sty, which achieves 99% of what you want without
+% the need for a separate preprocessor. At the start of your document
+% you write "\makeatactive". From then on, inline code is written as @\x
+% -> x_1 & y@. The only difference with what you are used to, is that
+% instead of
+%
+% @
+% foo :: Int -> Int
+% foo = \n -> n+1
+% @
+%
+% you have to write
+%
+% \begin{code}
+% foo :: Int -> Int
+% foo = \n -> n+1
+% \end{code}
+%
+% and that you cannot use @ in \section{} and \caption{}. For the paper that occured twice, in which case I had to replace @...@ b y \texttt{...}.
+%
+%
+% code.sty --- nice verbatim mode for code
+
+\def\icode{%
+ \relax\ifmmode\hbox\else\leavevmode\null\fi
+ \bgroup
+ %\begingroup
+ \@noligs
+ \verbatim@font
+ \verb@eol@error
+ \let\do\@makeother \dospecials
+ \@vobeyspaces
+ \frenchspacing
+ \@icode}
+\def\@icode#1{%
+ \catcode`#1\active
+ \lccode`\~`#1%
+ \lowercase{\let~\icode@egroup}}
+\def\icode@egroup{%
+ %\endgroup}
+ \egroup}
+
+% The \makeatactive command:
+% makes @ active, in such a way that @...@ behaves as \icode@...@:
+{
+\catcode`@=\active
+\gdef\makeatactive{
+ \catcode`@=\active \def@{\icode@}
+ % Since @ becomes active, it has to be taken care of in verbatim-modes:
+ \let\olddospecials\dospecials \def\dospecials{\do\@\olddospecials}}
+}
+% \gdef\makeatother{\g@remfrom@specials{\@}\@makeother\@}
+\gdef\makeatother{\@makeother\@}
+
+\newcommand\codetabwidth{42pt}
+{\catcode`\^^I=\active%
+\gdef\@vobeytab{\catcode`\^^I\active\let^^I\@xobeytab}}
+\def\@xobeytab{\leavevmode\penalty10000\hskip\codetabwidth}
+
+\begingroup \catcode `|=0 \catcode `[= 1
+\catcode`]=2 \catcode `\{=12 \catcode `\}=12
+\catcode`\\=12 |gdef|@xcode#1\end{code}[#1|end[code]]
+|endgroup
+\def\@code{\trivlist \item\relax
+ \if@minipage\else\vskip\parskip\fi
+ \leftskip\@totalleftmargin\rightskip\z@skip
+ \parindent\z@\parfillskip\@flushglue\parskip\z@skip
+ \@@par
+ \@tempswafalse
+ \def\par{%
+ \if@tempswa
+ \leavevmode \null \@@par\penalty\interlinepenalty
+ \else
+ \@tempswatrue
+ \ifhmode\@@par\penalty\interlinepenalty\fi
+ \fi}%
+ \obeylines \verbatim@font \@noligs
+ \let\do\@makeother \dospecials
+ \everypar \expandafter{\the\everypar \unpenalty}%
+}
+\def\code{\@code \frenchspacing\@vobeytab\@vobeyspaces \@xcode}
+\def\endcode{\if@newlist \leavevmode\fi\endtrivlist}
diff --git a/docs/storage-mgt/freelist.eepic b/docs/storage-mgt/freelist.eepic new file mode 100644 index 0000000000..f87d939649 --- /dev/null +++ b/docs/storage-mgt/freelist.eepic @@ -0,0 +1,104 @@ +\setlength{\unitlength}{0.00050000in} +% +\begingroup\makeatletter\ifx\SetFigFont\undefined% +\gdef\SetFigFont#1#2#3#4#5{% + \reset@font\fontsize{#1}{#2pt}% + \fontfamily{#3}\fontseries{#4}\fontshape{#5}% + \selectfont}% +\fi\endgroup% +{\renewcommand{\dashlinestretch}{30} +\begin{picture}(9912,7369)(0,-10) +\path(1125,6067)(2100,6067) +\path(1980.000,6037.000)(2100.000,6067.000)(1980.000,6097.000) +\path(5025,6367)(6000,6367)(6000,5167) + (5025,5167)(5025,6367) +\path(4650,6367)(5025,6367)(5025,5167) + (4650,5167)(4650,6367) +\path(3675,6367)(4650,6367)(4650,5167) + (3675,5167)(3675,6367) +\path(6600,6367)(7575,6367)(7575,5167) + (6600,5167)(6600,6367) +\path(8925,6367)(9900,6367)(9900,5167) + (8925,5167)(8925,6367) +\path(7575,6367)(8550,6367)(8550,5167) + (7575,5167)(7575,6367) +\path(8550,6367)(8925,6367)(8925,5167) + (8550,5167)(8550,6367) +\path(2100,6367)(3675,6367)(3675,5167) + (2100,5167)(2100,6367) +\path(2850,6217)(2850,6667)(6600,6667)(6600,6367) +\path(6570.000,6487.000)(6600.000,6367.000)(6630.000,6487.000) +\path(4425,6217)(4425,6967)(7575,6967)(7575,6367) +\path(7545.000,6487.000)(7575.000,6367.000)(7605.000,6487.000) +\path(5700,6217)(5700,7342)(8925,7342)(8925,6367) +\path(8895.000,6487.000)(8925.000,6367.000)(8955.000,6487.000) +\path(4350,5317)(4350,4792)(2100,4792)(2100,5167) +\path(2130.000,5047.000)(2100.000,5167.000)(2070.000,5047.000) +\path(5625,5317)(5625,4492)(2100,4492)(2100,5167) +\path(2130.000,5047.000)(2100.000,5167.000)(2070.000,5047.000) +\path(3000,5917)(3000,6667) +\path(5025,2842)(6000,2842)(6000,1642) + (5025,1642)(5025,2842) +\path(4650,2842)(5025,2842)(5025,1642) + (4650,1642)(4650,2842) +\path(3675,2842)(4650,2842)(4650,1642) + (3675,1642)(3675,2842) +\path(6600,2842)(7575,2842)(7575,1642) + (6600,1642)(6600,2842) +\path(8925,2842)(9900,2842)(9900,1642) + (8925,1642)(8925,2842) +\path(7575,2842)(8550,2842)(8550,1642) + (7575,1642)(7575,2842) +\path(8550,2842)(8925,2842)(8925,1642) + (8550,1642)(8550,2842) +\path(2100,2842)(3675,2842)(3675,1642) + (2100,1642)(2100,2842) +\path(2850,2692)(2850,3142)(6600,3142)(6600,2842) +\path(6570.000,2962.000)(6600.000,2842.000)(6630.000,2962.000) +\path(4425,2692)(4425,3442)(7575,3442)(7575,2842) +\path(7545.000,2962.000)(7575.000,2842.000)(7605.000,2962.000) +\path(5700,2692)(5700,3817)(8925,3817)(8925,2842) +\path(8895.000,2962.000)(8925.000,2842.000)(8955.000,2962.000) +\path(4350,1792)(4350,1267)(2100,1267)(2100,1642) +\path(2130.000,1522.000)(2100.000,1642.000)(2070.000,1522.000) +\path(5625,1792)(5625,967)(2100,967)(2100,1642) +\path(2130.000,1522.000)(2100.000,1642.000)(2070.000,1522.000) +\path(3000,2392)(3000,3142) +\path(2250,5317)(1650,5317)(1650,2542)(2100,2542) +\path(1980.000,2512.000)(2100.000,2542.000)(1980.000,2572.000) +\path(2250,1792)(1650,1792)(1650,142)(2325,142) +\path(2205.000,112.000)(2325.000,142.000)(2205.000,172.000) +\put(0,5992){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}free\_list}}}}} +\put(8625,5917){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}...}}}}} +\put(4725,5767){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}...}}}}} +\put(3750,5242){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}link}}}}} +\put(5100,5242){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}link}}}}} +\put(2175,6142){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}start}}}}} +\put(2175,5842){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}free}}}}} +\put(3750,6142){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}start}}}}} +\put(5100,6142){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}start}}}}} +\put(7800,6442){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}block}}}}} +\put(6825,6442){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}block}}}}} +\put(9150,6442){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}block}}}}} +\put(2175,5542){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}blocks=$n_1$}}}}} +\put(3750,5842){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}free=0}}}}} +\put(5100,5842){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}free=0}}}}} +\put(8625,2392){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}...}}}}} +\put(4725,2242){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}...}}}}} +\put(3750,1717){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}link}}}}} +\put(5100,1717){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}link}}}}} +\put(2175,2617){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}start}}}}} +\put(2175,2317){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}free}}}}} +\put(3750,2617){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}start}}}}} +\put(5100,2617){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}start}}}}} +\put(7800,2917){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}block}}}}} +\put(6825,2917){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}block}}}}} +\put(9150,2917){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}block}}}}} +\put(3750,2317){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}free=0}}}}} +\put(5100,2317){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}free=0}}}}} +\put(2325,5242){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}link}}}}} +\put(2325,1717){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}link}}}}} +\put(2475,67){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}next block group}}}}} +\put(2175,2017){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}blocks=$n_2$}}}}} +\end{picture} +} diff --git a/docs/storage-mgt/freelist.fig b/docs/storage-mgt/freelist.fig new file mode 100644 index 0000000000..d8debffd7c --- /dev/null +++ b/docs/storage-mgt/freelist.fig @@ -0,0 +1,116 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +60.00 +Single +-2 +1200 2 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 5325 1725 6300 1725 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 9225 1425 10200 1425 10200 2625 9225 2625 9225 1425 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 8850 1425 9225 1425 9225 2625 8850 2625 8850 1425 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 7875 1425 8850 1425 8850 2625 7875 2625 7875 1425 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 10800 1425 11775 1425 11775 2625 10800 2625 10800 1425 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 13125 1425 14100 1425 14100 2625 13125 2625 13125 1425 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 11775 1425 12750 1425 12750 2625 11775 2625 11775 1425 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 12750 1425 13125 1425 13125 2625 12750 2625 12750 1425 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 6300 1425 7875 1425 7875 2625 6300 2625 6300 1425 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 4 + 0 0 1.00 60.00 120.00 + 7050 1575 7050 1125 10800 1125 10800 1425 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 4 + 0 0 1.00 60.00 120.00 + 8625 1575 8625 825 11775 825 11775 1425 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 4 + 0 0 1.00 60.00 120.00 + 9900 1575 9900 450 13125 450 13125 1425 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 4 + 0 0 1.00 60.00 120.00 + 8550 2475 8550 3000 6300 3000 6300 2625 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 4 + 0 0 1.00 60.00 120.00 + 9825 2475 9825 3300 6300 3300 6300 2625 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 + 7200 1875 7200 1125 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 9225 4950 10200 4950 10200 6150 9225 6150 9225 4950 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 8850 4950 9225 4950 9225 6150 8850 6150 8850 4950 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 7875 4950 8850 4950 8850 6150 7875 6150 7875 4950 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 10800 4950 11775 4950 11775 6150 10800 6150 10800 4950 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 13125 4950 14100 4950 14100 6150 13125 6150 13125 4950 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 11775 4950 12750 4950 12750 6150 11775 6150 11775 4950 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 12750 4950 13125 4950 13125 6150 12750 6150 12750 4950 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 6300 4950 7875 4950 7875 6150 6300 6150 6300 4950 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 4 + 0 0 1.00 60.00 120.00 + 7050 5100 7050 4650 10800 4650 10800 4950 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 4 + 0 0 1.00 60.00 120.00 + 8625 5100 8625 4350 11775 4350 11775 4950 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 4 + 0 0 1.00 60.00 120.00 + 9900 5100 9900 3975 13125 3975 13125 4950 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 4 + 0 0 1.00 60.00 120.00 + 8550 6000 8550 6525 6300 6525 6300 6150 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 4 + 0 0 1.00 60.00 120.00 + 9825 6000 9825 6825 6300 6825 6300 6150 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 + 7200 5400 7200 4650 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 4 + 0 0 1.00 60.00 120.00 + 6450 2475 5850 2475 5850 5250 6300 5250 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 4 + 0 0 1.00 60.00 120.00 + 6450 6000 5850 6000 5850 7650 6525 7650 +4 0 0 50 0 0 17 0.0000 4 195 825 4200 1800 free_list\001 +4 0 0 50 0 0 17 0.0000 4 30 180 12825 1875 ...\001 +4 0 0 50 0 0 17 0.0000 4 30 180 8925 2025 ...\001 +4 0 0 50 0 0 17 0.0000 4 165 390 7950 2550 link\001 +4 0 0 50 0 0 17 0.0000 4 165 390 9300 2550 link\001 +4 0 0 50 0 0 17 0.0000 4 150 435 6375 1650 start\001 +4 0 0 50 0 0 17 0.0000 4 165 390 6375 1950 free\001 +4 0 0 50 0 0 17 0.0000 4 150 435 7950 1650 start\001 +4 0 0 50 0 0 17 0.0000 4 150 435 9300 1650 start\001 +4 0 0 50 0 0 17 0.0000 4 165 540 12000 1350 block\001 +4 0 0 50 0 0 17 0.0000 4 165 540 11025 1350 block\001 +4 0 0 50 0 0 17 0.0000 4 165 540 13350 1350 block\001 +4 0 0 50 0 0 17 0.0000 4 195 1125 6375 2250 blocks=n_1\001 +4 0 0 50 0 0 17 0.0000 4 165 645 7950 1950 free=0\001 +4 0 0 50 0 0 17 0.0000 4 165 645 9300 1950 free=0\001 +4 0 0 50 0 0 17 0.0000 4 30 180 12825 5400 ...\001 +4 0 0 50 0 0 17 0.0000 4 30 180 8925 5550 ...\001 +4 0 0 50 0 0 17 0.0000 4 165 390 7950 6075 link\001 +4 0 0 50 0 0 17 0.0000 4 165 390 9300 6075 link\001 +4 0 0 50 0 0 17 0.0000 4 150 435 6375 5175 start\001 +4 0 0 50 0 0 17 0.0000 4 165 390 6375 5475 free\001 +4 0 0 50 0 0 17 0.0000 4 150 435 7950 5175 start\001 +4 0 0 50 0 0 17 0.0000 4 150 435 9300 5175 start\001 +4 0 0 50 0 0 17 0.0000 4 165 540 12000 4875 block\001 +4 0 0 50 0 0 17 0.0000 4 165 540 11025 4875 block\001 +4 0 0 50 0 0 17 0.0000 4 165 540 13350 4875 block\001 +4 0 0 50 0 0 17 0.0000 4 165 645 7950 5475 free=0\001 +4 0 0 50 0 0 17 0.0000 4 165 645 9300 5475 free=0\001 +4 0 0 50 0 0 17 0.0000 4 165 390 6525 2550 link\001 +4 0 0 50 0 0 17 0.0000 4 165 390 6525 6075 link\001 +4 0 0 50 0 0 17 0.0000 4 225 1650 6675 7725 next block group\001 +4 0 0 50 0 0 17 0.0000 4 195 1125 6375 5775 blocks=n_2\001 diff --git a/docs/storage-mgt/gen.eepic b/docs/storage-mgt/gen.eepic new file mode 100644 index 0000000000..b50d691395 --- /dev/null +++ b/docs/storage-mgt/gen.eepic @@ -0,0 +1,57 @@ +\setlength{\unitlength}{0.00050000in} +% +\begingroup\makeatletter\ifx\SetFigFont\undefined% +\gdef\SetFigFont#1#2#3#4#5{% + \reset@font\fontsize{#1}{#2pt}% + \fontfamily{#3}\fontseries{#4}\fontshape{#5}% + \selectfont}% +\fi\endgroup% +{\renewcommand{\dashlinestretch}{30} +\begin{picture}(9849,5907)(0,-10) +\path(3237,5562)(4212,5562)(4212,4062) + (3237,4062)(3237,5562) +\path(4212,5562)(5187,5562)(5187,4062) + (4212,4062)(4212,5562) +\path(5187,5562)(6162,5562)(6162,4062) + (5187,4062)(5187,5562) +\path(6162,5562)(7137,5562)(7137,4062) + (6162,4062)(6162,5562) +\put(5487,4737){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}......}}}}} +\put(4812,5712){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}step[]}}}}} +\path(7812,2712)(9837,2712)(9837,2112) + (7812,2112)(7812,2712) +\put(7887,2862){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}END\_MUT\_LIST}}}}} +\path(6687,312)(7812,2412) +\path(7781.778,2292.056)(7812.000,2412.000)(7728.889,2320.389) +\path(6687,2412)(7812,2412) +\path(7692.000,2382.000)(7812.000,2412.000)(7692.000,2442.000) +\put(6012,312){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}......}}}}} +\put(6012,2412){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}......}}}}} +\path(4662,312)(5787,312) +\path(5667.000,282.000)(5787.000,312.000)(5667.000,342.000) +\path(3237,612)(5262,612)(5262,12) + (3237,12)(3237,612) +\path(4662,2412)(5787,2412) +\path(5667.000,2382.000)(5787.000,2412.000)(5667.000,2442.000) +\path(3237,2712)(5262,2712)(5262,2112) + (3237,2112)(3237,2712) +\put(3387,237){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}mut\_link}}}}} +\put(3312,762){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}StgMutClosure}}}}} +\put(3387,2337){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}mut\_link}}}}} +\put(3312,2862){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}StgMutClosure}}}}} +\path(912,3012)(2487,3012)(2487,4887)(3237,4887) +\path(3117.000,4857.000)(3237.000,4887.000)(3117.000,4917.000) +\path(1212,2412)(3237,2412) +\path(3117.000,2382.000)(3237.000,2412.000)(3117.000,2442.000) +\path(1737,2112)(2487,2112)(2487,312)(3237,312) +\path(3117.000,282.000)(3237.000,312.000)(3117.000,342.000) +\path(12,3462)(1887,3462)(1887,1962) + (12,1962)(12,3462) +\put(87,3237){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}no}}}}} +\put(237,3612){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}generation}}}}} +\put(87,2937){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}steps}}}}} +\put(87,2637){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}n\_steps}}}}} +\put(87,2337){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}mut\_list}}}}} +\put(87,2052){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}mut\_once\_list}}}}} +\end{picture} +} diff --git a/docs/storage-mgt/gen.fig b/docs/storage-mgt/gen.fig new file mode 100644 index 0000000000..086a335819 --- /dev/null +++ b/docs/storage-mgt/gen.fig @@ -0,0 +1,71 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +60.00 +Single +-2 +1200 2 +6 5250 900 9150 2775 +6 5250 1275 9150 2775 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 5250 1275 6225 1275 6225 2775 5250 2775 5250 1275 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 6225 1275 7200 1275 7200 2775 6225 2775 6225 1275 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 7200 1275 8175 1275 8175 2775 7200 2775 7200 1275 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 8175 1275 9150 1275 9150 2775 8175 2775 8175 1275 +4 0 0 50 0 0 17 0.0000 4 30 360 7500 2100 ......\001 +-6 +4 0 0 50 0 0 17 0.0000 4 225 540 6825 1125 step[]\001 +-6 +6 5250 3750 11850 6825 +6 8025 3750 11850 6525 +6 9825 3750 11850 4725 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 9825 4125 11850 4125 11850 4725 9825 4725 9825 4125 +4 0 0 50 0 0 17 0.0000 4 195 1815 9900 3975 END_MUT_LIST\001 +-6 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 8700 6525 9825 4425 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 8700 4425 9825 4425 +4 0 0 50 0 0 17 0.0000 4 30 360 8025 6525 ......\001 +4 0 0 50 0 0 17 0.0000 4 30 360 8025 4425 ......\001 +-6 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 6675 6525 7800 6525 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 5250 6225 7275 6225 7275 6825 5250 6825 5250 6225 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 6675 4425 7800 4425 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 5250 4125 7275 4125 7275 4725 5250 4725 5250 4125 +4 0 0 50 0 0 17 0.0000 4 195 900 5400 6600 mut_link\001 +4 0 0 50 0 0 17 0.0000 4 225 1515 5325 6075 StgMutClosure\001 +4 0 0 50 0 0 17 0.0000 4 195 900 5400 4500 mut_link\001 +4 0 0 50 0 0 17 0.0000 4 225 1515 5325 3975 StgMutClosure\001 +-6 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 4 + 0 0 1.00 60.00 120.00 + 2925 3825 4500 3825 4500 1950 5250 1950 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 3225 4425 5250 4425 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 4 + 0 0 1.00 60.00 120.00 + 3750 4725 4500 4725 4500 6525 5250 6525 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 2025 3375 3900 3375 3900 4875 2025 4875 2025 3375 +4 0 0 50 0 0 17 0.0000 4 120 240 2100 3600 no\001 +4 0 0 50 0 0 17 0.0000 4 225 1035 2250 3225 generation\001 +4 0 0 50 0 0 17 0.0000 4 210 480 2100 3900 steps\001 +4 0 0 50 0 0 17 0.0000 4 210 720 2100 4200 n_steps\001 +4 0 0 50 0 0 17 0.0000 4 195 825 2100 4500 mut_list\001 +4 0 0 50 0 0 17 0.0000 4 195 1395 2100 4785 mut_once_list\001 diff --git a/docs/storage-mgt/generation.eepic b/docs/storage-mgt/generation.eepic new file mode 100644 index 0000000000..bea5a8c6ec --- /dev/null +++ b/docs/storage-mgt/generation.eepic @@ -0,0 +1,62 @@ +\setlength{\unitlength}{0.00050000in} +% +\begingroup\makeatletter\ifx\SetFigFont\undefined% +\gdef\SetFigFont#1#2#3#4#5{% + \reset@font\fontsize{#1}{#2pt}% + \fontfamily{#3}\fontseries{#4}\fontshape{#5}% + \selectfont}% +\fi\endgroup% +{\renewcommand{\dashlinestretch}{30} +\begin{picture}(8153,4017)(0,-10) +\path(5025,3687)(6375,3687) +\path(6255.000,3657.000)(6375.000,3687.000)(6255.000,3717.000) +\path(2775,3687)(4125,3687) +\path(4005.000,3657.000)(4125.000,3687.000)(4005.000,3717.000) +\path(1875,3912)(2775,3912)(2775,3462) + (1875,3462)(1875,3912) +\path(4125,3912)(5025,3912)(5025,3462) + (4125,3462)(4125,3912) +\path(6375,3912)(7275,3912)(7275,3462) + (6375,3462)(6375,3912) +\path(5025,2187)(6375,2187) +\path(6255.000,2157.000)(6375.000,2187.000)(6255.000,2217.000) +\path(2775,2187)(4125,2187) +\path(4005.000,2157.000)(4125.000,2187.000)(4005.000,2217.000) +\path(4125,2412)(5025,2412)(5025,1962) + (4125,1962)(4125,2412) +\path(6375,2412)(7275,2412)(7275,1962) + (6375,1962)(6375,2412) +\path(1875,2412)(2775,2412)(2775,1962) + (1875,1962)(1875,2412) +\path(1875,912)(2775,912)(2775,462) + (1875,462)(1875,912) +\path(7275,3687)(8025,3687)(8025,3012) + (2325,3012)(2325,2412) +\path(2295.000,2532.000)(2325.000,2412.000)(2355.000,2532.000) +\path(7275,2187)(8025,2187)(8025,1512)(5025,1512) +\path(5145.000,1542.000)(5025.000,1512.000)(5145.000,1482.000) +\path(4125,1512)(2325,1512)(2325,912) +\path(2295.000,1032.000)(2325.000,912.000)(2355.000,1032.000) +\path(2895.000,717.000)(2775.000,687.000)(2895.000,657.000) +\path(2775,687)(3525,687)(3525,12) + (2325,12)(2325,462) +\put(5550,3837){\makebox(0,0)[lb]{\smash{{{\SetFigFont{7}{8.4}{\rmdefault}{\mddefault}{\updefault}......}}}}} +\put(3225,3837){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}GC}}}}} +\put(1950,3612){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}step 0}}}}} +\put(4200,3612){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}step 1}}}}} +\put(6450,3612){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}step $S$}}}}} +\put(5550,2337){\makebox(0,0)[lb]{\smash{{{\SetFigFont{7}{8.4}{\rmdefault}{\mddefault}{\updefault}......}}}}} +\put(3225,2337){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}GC}}}}} +\put(4200,2112){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}step 1}}}}} +\put(6450,2112){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}step $S$}}}}} +\put(1950,2112){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}step 0}}}}} +\put(1950,612){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}step 0}}}}} +\put(7800,3837){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}GC}}}}} +\put(3225,837){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}GC}}}}} +\put(4500,1512){\makebox(0,0)[lb]{\smash{{{\SetFigFont{7}{8.4}{\rmdefault}{\mddefault}{\updefault}......}}}}} +\put(0,3612){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}generation 0}}}}} +\put(0,2112){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}generation 1}}}}} +\put(0,612){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}generation $G$}}}}} +\put(450,1512){\makebox(0,0)[lb]{\smash{{{\SetFigFont{7}{8.4}{\rmdefault}{\mddefault}{\updefault}......}}}}} +\end{picture} +} diff --git a/docs/storage-mgt/generation.fig b/docs/storage-mgt/generation.fig new file mode 100644 index 0000000000..e91ed6d4c6 --- /dev/null +++ b/docs/storage-mgt/generation.fig @@ -0,0 +1,65 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +60.00 +Single +-2 +1200 2 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 9150 3150 10500 3150 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 6900 3150 8250 3150 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 6000 2925 6900 2925 6900 3375 6000 3375 6000 2925 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 8250 2925 9150 2925 9150 3375 8250 3375 8250 2925 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 10500 2925 11400 2925 11400 3375 10500 3375 10500 2925 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 9150 4650 10500 4650 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 6900 4650 8250 4650 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 8250 4425 9150 4425 9150 4875 8250 4875 8250 4425 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 10500 4425 11400 4425 11400 4875 10500 4875 10500 4425 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 6000 4425 6900 4425 6900 4875 6000 4875 6000 4425 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 6000 5925 6900 5925 6900 6375 6000 6375 6000 5925 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 5 + 0 0 1.00 60.00 120.00 + 11400 3150 12150 3150 12150 3825 6450 3825 6450 4425 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 4 + 0 0 1.00 60.00 120.00 + 11400 4650 12150 4650 12150 5325 9150 5325 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 3 + 0 0 1.00 60.00 120.00 + 8250 5325 6450 5325 6450 5925 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 0 1 5 + 0 0 1.00 60.00 120.00 + 6900 6150 7650 6150 7650 6825 6450 6825 6450 6375 +4 0 0 50 0 0 12 0.0000 4 15 270 9675 3000 ......\001 +4 0 0 50 0 0 17 0.0000 4 165 345 7350 3000 GC\001 +4 0 0 50 0 0 17 0.0000 4 225 570 6075 3225 step 0\001 +4 0 0 50 0 0 17 0.0000 4 225 570 8325 3225 step 1\001 +4 0 0 50 0 0 17 0.0000 4 225 585 10575 3225 step S\001 +4 0 0 50 0 0 12 0.0000 4 15 270 9675 4500 ......\001 +4 0 0 50 0 0 17 0.0000 4 165 345 7350 4500 GC\001 +4 0 0 50 0 0 17 0.0000 4 225 570 8325 4725 step 1\001 +4 0 0 50 0 0 17 0.0000 4 225 585 10575 4725 step S\001 +4 0 0 50 0 0 17 0.0000 4 225 570 6075 4725 step 0\001 +4 0 0 50 0 0 17 0.0000 4 225 570 6075 6225 step 0\001 +4 0 0 50 0 0 17 0.0000 4 165 345 11925 3000 GC\001 +4 0 0 50 0 0 17 0.0000 4 165 345 7350 6000 GC\001 +4 0 0 50 0 0 12 0.0000 4 15 270 8625 5325 ......\001 +4 0 0 50 0 0 17 0.0000 4 225 1215 4125 3225 generation 0\001 +4 0 0 50 0 0 17 0.0000 4 225 1215 4125 4725 generation 1\001 +4 0 0 50 0 0 17 0.0000 4 225 1275 4125 6225 generation G\001 +4 0 0 50 0 0 12 0.0000 4 15 270 4575 5325 ......\001 diff --git a/docs/storage-mgt/largeobjectpool.eepic b/docs/storage-mgt/largeobjectpool.eepic new file mode 100644 index 0000000000..9c198fd279 --- /dev/null +++ b/docs/storage-mgt/largeobjectpool.eepic @@ -0,0 +1,70 @@ +\setlength{\unitlength}{0.00050000in} +% +\begingroup\makeatletter\ifx\SetFigFont\undefined% +\gdef\SetFigFont#1#2#3#4#5{% + \reset@font\fontsize{#1}{#2pt}% + \fontfamily{#3}\fontseries{#4}\fontshape{#5}% + \selectfont}% +\fi\endgroup% +{\renewcommand{\dashlinestretch}{30} +\begin{picture}(10212,4689)(0,-10) +\path(6900,4362)(10200,4362)(10200,3162) + (6900,3162)(6900,4362) +\path(7020.000,3792.000)(6900.000,3762.000)(7020.000,3732.000) +\path(6900,3762)(10050,3762) +\path(9930.000,3732.000)(10050.000,3762.000)(9930.000,3792.000) +\path(10050,4362)(10050,3162) +\put(8100,4437){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}blocks}}}}} +\put(7875,3912){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}single object}}}}} +\path(6900,2262)(10200,2262)(10200,1062) + (6900,1062)(6900,2262) +\path(7020.000,1692.000)(6900.000,1662.000)(7020.000,1632.000) +\path(6900,1662)(10050,1662) +\path(9930.000,1632.000)(10050.000,1662.000)(9930.000,1692.000) +\path(10050,2262)(10050,1062) +\put(8100,2337){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}blocks}}}}} +\put(7875,1812){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}single object}}}}} +\path(2550,4062)(3375,4062) +\path(3255.000,4032.000)(3375.000,4062.000)(3255.000,4092.000) +\path(3405.000,1182.000)(3525.000,1212.000)(3405.000,1242.000) +\path(3525,1212)(2925,1212)(2925,12)(3375,12) +\path(3255.000,-18.000)(3375.000,12.000)(3255.000,42.000) +\path(3405.000,3282.000)(3525.000,3312.000)(3405.000,3342.000) +\path(3525,3312)(2925,3312)(2925,2112)(3375,2112) +\path(3255.000,2082.000)(3375.000,2112.000)(3255.000,2142.000) +\path(3375,4362)(4950,4362)(4950,3162) + (3375,3162)(3375,4362) +\path(4275,3912)(4275,4662) +\path(4950,4362)(5400,4362)(5400,3162) + (4950,3162)(4950,4362) +\path(5400,4362)(5850,4362)(5850,3162) + (5400,3162)(5400,4362) +\path(5850,4362)(6300,4362)(6300,3162) + (5850,3162)(5850,4362) +\path(3375,2262)(4950,2262)(4950,1062) + (3375,1062)(3375,2262) +\path(4125,2112)(4125,2562)(6900,2562)(6900,2262) +\path(6870.000,2382.000)(6900.000,2262.000)(6930.000,2382.000) +\path(4275,1812)(4275,2562) +\path(4950,2262)(5400,2262)(5400,1062) + (4950,1062)(4950,2262) +\path(5400,2262)(5850,2262)(5850,1062) + (5400,1062)(5400,2262) +\path(5850,2262)(6300,2262)(6300,1062) + (5850,1062)(5850,2262) +\path(4125,4212)(4125,4662)(6900,4662)(6900,4362) +\path(6870.000,4482.000)(6900.000,4362.000)(6930.000,4482.000) +\put(3600,12){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}......}}}}} +\put(3450,4137){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}start}}}}} +\put(3450,3837){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}free}}}}} +\put(3450,3537){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}blocks=$n_1$}}}}} +\put(3600,3237){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}link}}}}} +\put(5550,3762){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}...}}}}} +\put(3450,2037){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}start}}}}} +\put(3450,1737){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}free}}}}} +\put(3600,1137){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}link}}}}} +\put(5550,1662){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}...}}}}} +\put(3450,1437){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}blocks=$n_2$}}}}} +\put(0,3987){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}g0s0-$>$large\_objects}}}}} +\end{picture} +} diff --git a/docs/storage-mgt/largeobjectpool.fig b/docs/storage-mgt/largeobjectpool.fig new file mode 100644 index 0000000000..6c49ff03f1 --- /dev/null +++ b/docs/storage-mgt/largeobjectpool.fig @@ -0,0 +1,82 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +60.00 +Single +-2 +1200 2 +6 9825 1125 13125 2625 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 9825 1425 13125 1425 13125 2625 9825 2625 9825 1425 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 1 2 + 0 0 1.00 60.00 120.00 + 0 0 1.00 60.00 120.00 + 9825 2025 12975 2025 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 + 12975 1425 12975 2625 +4 0 0 50 0 0 17 0.0000 4 165 630 11025 1350 blocks\001 +4 0 0 50 0 0 17 0.0000 4 225 1230 10800 1875 single object\001 +-6 +6 9825 3225 13125 4725 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 9825 3525 13125 3525 13125 4725 9825 4725 9825 3525 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 1 2 + 0 0 1.00 60.00 120.00 + 0 0 1.00 60.00 120.00 + 9825 4125 12975 4125 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 + 12975 3525 12975 4725 +4 0 0 50 0 0 17 0.0000 4 165 630 11025 3450 blocks\001 +4 0 0 50 0 0 17 0.0000 4 225 1230 10800 3975 single object\001 +-6 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 5475 1725 6300 1725 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 1 4 + 0 0 1.00 60.00 120.00 + 0 0 1.00 60.00 120.00 + 6450 4575 5850 4575 5850 5775 6300 5775 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 1 4 + 0 0 1.00 60.00 120.00 + 0 0 1.00 60.00 120.00 + 6450 2475 5850 2475 5850 3675 6300 3675 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 6300 1425 7875 1425 7875 2625 6300 2625 6300 1425 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 + 7200 1875 7200 1125 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 7875 1425 8325 1425 8325 2625 7875 2625 7875 1425 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 8325 1425 8775 1425 8775 2625 8325 2625 8325 1425 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 8775 1425 9225 1425 9225 2625 8775 2625 8775 1425 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 6300 3525 7875 3525 7875 4725 6300 4725 6300 3525 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 4 + 0 0 1.00 60.00 120.00 + 7050 3675 7050 3225 9825 3225 9825 3525 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 + 7200 3975 7200 3225 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 7875 3525 8325 3525 8325 4725 7875 4725 7875 3525 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 8325 3525 8775 3525 8775 4725 8325 4725 8325 3525 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 8775 3525 9225 3525 9225 4725 8775 4725 8775 3525 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 4 + 0 0 1.00 60.00 120.00 + 7050 1575 7050 1125 9825 1125 9825 1425 +4 0 0 50 0 0 17 0.0000 4 30 360 6525 5775 ......\001 +4 0 0 50 0 0 17 0.0000 4 150 435 6375 1650 start\001 +4 0 0 50 0 0 17 0.0000 4 165 390 6375 1950 free\001 +4 0 0 50 0 0 17 0.0000 4 195 1125 6375 2250 blocks=n_1\001 +4 0 0 50 0 0 17 0.0000 4 165 390 6525 2550 link\001 +4 0 0 50 0 0 17 0.0000 4 30 180 8475 2025 ...\001 +4 0 0 50 0 0 17 0.0000 4 150 435 6375 3750 start\001 +4 0 0 50 0 0 17 0.0000 4 165 390 6375 4050 free\001 +4 0 0 50 0 0 17 0.0000 4 165 390 6525 4650 link\001 +4 0 0 50 0 0 17 0.0000 4 30 180 8475 4125 ...\001 +4 0 0 50 0 0 17 0.0000 4 195 1125 6375 4350 blocks=n_2\001 +4 0 0 50 0 0 17 0.0000 4 225 2010 2925 1800 g0s0->large_objects\001 diff --git a/docs/storage-mgt/ldv.eepic b/docs/storage-mgt/ldv.eepic new file mode 100644 index 0000000000..aa41327aa5 --- /dev/null +++ b/docs/storage-mgt/ldv.eepic @@ -0,0 +1,41 @@ +\setlength{\unitlength}{0.00050000in} +% +\begingroup\makeatletter\ifx\SetFigFont\undefined% +\gdef\SetFigFont#1#2#3#4#5{% + \reset@font\fontsize{#1}{#2pt}% + \fontfamily{#3}\fontseries{#4}\fontshape{#5}% + \selectfont}% +\fi\endgroup% +{\renewcommand{\dashlinestretch}{30} +\begin{picture}(6036,3169)(0,-10) +\path(1692,3142)(1692,2692)(3342,2692) +\path(1692,2317)(1692,2692) +\path(1722.000,2572.000)(1692.000,2692.000)(1662.000,2572.000) +\path(4992,2317)(4992,2692) +\path(5022.000,2572.000)(4992.000,2692.000)(4962.000,2572.000) +\path(4992,2692)(4992,3142) +\path(3342,3142)(3342,2692)(4992,2692) +\path(3342,2317)(3342,2692) +\path(3372.000,2572.000)(3342.000,2692.000)(3312.000,2572.000) +\path(42,3142)(42,2692)(1692,2692) +\path(42,2317)(42,2692) +\path(72.000,2572.000)(42.000,2692.000)(12.000,2572.000) +\put(1992,2767){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}use}}}}} +\put(342,2767){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}lag}}}}} +\put(117,2092){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}created}}}}} +\put(3642,2767){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}drag}}}}} +\put(1767,2092){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}first used}}}}} +\put(3417,2092){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}last used}}}}} +\put(5067,2092){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}destroyed}}}}} +\path(4992,292)(4992,667) +\path(5022.000,547.000)(4992.000,667.000)(4962.000,547.000) +\path(4992,667)(4992,1117) +\path(1692,667)(3342,667)(4992,667) +\path(42,1117)(42,667)(1692,667) +\path(42,292)(42,667) +\path(72.000,547.000)(42.000,667.000)(12.000,547.000) +\put(117,67){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}created}}}}} +\put(5067,67){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}destroyed}}}}} +\put(1992,742){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}void}}}}} +\end{picture} +} diff --git a/docs/storage-mgt/ldv.fig b/docs/storage-mgt/ldv.fig new file mode 100644 index 0000000000..772411c289 --- /dev/null +++ b/docs/storage-mgt/ldv.fig @@ -0,0 +1,53 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +60.00 +Single +-2 +1200 2 +6 3600 3375 9675 4500 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 3 + 5325 3375 5325 3825 6975 3825 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 5325 4200 5325 3825 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 8625 4200 8625 3825 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 0 0 2 + 8625 3825 8625 3375 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 3 + 6975 3375 6975 3825 8625 3825 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 6975 4200 6975 3825 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 3 + 3675 3375 3675 3825 5325 3825 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 3675 4200 3675 3825 +4 0 0 50 0 0 17 0.0000 4 120 315 5625 3750 use\001 +4 0 0 50 0 0 17 0.0000 4 225 300 3975 3750 lag\001 +4 0 0 50 0 0 17 0.0000 4 165 705 3750 4425 created\001 +4 0 0 50 0 0 17 0.0000 4 225 435 7275 3750 drag\001 +4 0 0 50 0 0 17 0.0000 4 165 915 5400 4425 first used\001 +4 0 0 50 0 0 17 0.0000 4 165 840 7050 4425 last used\001 +4 0 0 50 0 0 17 0.0000 4 225 945 8700 4425 destroyed\001 +-6 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 8625 6225 8625 5850 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 0 0 2 + 8625 5850 8625 5400 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 3 + 5325 5850 6975 5850 8625 5850 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 3 + 3675 5400 3675 5850 5325 5850 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 3675 6225 3675 5850 +4 0 0 50 0 0 17 0.0000 4 165 705 3750 6450 created\001 +4 0 0 50 0 0 17 0.0000 4 225 945 8700 6450 destroyed\001 +4 0 0 50 0 0 17 0.0000 4 165 435 5625 5775 void\001 diff --git a/docs/storage-mgt/ldv.tex b/docs/storage-mgt/ldv.tex new file mode 100644 index 0000000000..936407c701 --- /dev/null +++ b/docs/storage-mgt/ldv.tex @@ -0,0 +1,695 @@ +\documentclass{article} +\usepackage{code,a4wide} + +\usepackage{graphics,epsfig,epic,eepic,epsfig} + +\setlength{\parskip}{0.25cm} +\setlength{\parsep}{0.25cm} +\setlength{\topsep}{0cm} +\setlength{\parindent}{0cm} +\renewcommand{\textfraction}{0.2} +\renewcommand{\floatpagefraction}{0.7} + + +% Terminology +\newcommand{\block}{block} +\newcommand{\Block}{Block} +\newcommand{\segment}{segment} +\newcommand{\Segment}{Segment} +\newcommand{\step}{step} +\newcommand{\Step}{Step} + +\newcommand{\note}[1]{{\em $\spadesuit$ #1}} + +\begin{document} +\title{Implementation of Lag/Drag/Void/Use Profiling} +\author{Sungwoo Park \\ Simon Marlow} + +\makeatactive +\maketitle + +\section{Lag/Drag/Void/Use Profiling} + +\emph{Lag/Drag/Void/Use} (LDVU) profiling~\cite{RR} is a profiling technique +which yields a summary of the biography of all the dynamic closures created +during program execution. +In this profiling scheme, +the biography of a closure is determined by four important events associated +with the closure: \emph{creation}, \emph{first use}, +\emph{last use}, and \emph{destruction} (see Figure~\ref{fig-ldv}). +The intervals between these successive events correspond to three phases +for the closure: \emph{lag} (between creation and first use), +\emph{use} (between first use and last use), and +\emph{drag} (between last use and destruction). +If the closure is never used, it is considered to remain in the \emph{void} +phase all its lifetime. + +\begin{figure}[ht] +\begin{center} +\input{ldv.eepic} +\caption{The biography of a closure} +\label{fig-ldv} +\end{center} +\end{figure} + +The LDVU profiler regularly performs heap censuses during program execution. +Each time a heap census is performed, the LDVU profiler increments a global +time, which is used for timing all the events (such as creation and destruction +of a closure) occurring during program execution. +Hence, for instance, all closures creating between two successive heap censuses +have the same creation time and belong to the same \emph{generation}.\footnote{In +this document, a generation is related with heap censuses, not garbage collections +as in other profiling schemes.} +After the program terminates, it yields a post-mortem report on how much +of the \emph{live} graph is in one of the four phases at the moment of each +heap census. + +It must be emphasized that the LDVU profiler considers only live closures; +it should not take into consideration dead closures which do not constitute +the graph. Therefore, the result of LDVU profiling does not depend on the +frequency of garbage collections. + +This document describes the implementation of LDVU profiling on the Glasgow +Haskell Compiler runtime system.\footnote{Unless otherwise noted, all identifiers +are defined in @LdvProfile.c@}. + +\section{An Overview of the Implementation} + +Every closure is augmented with an additional word in its profiling header +to accommodate three additional pieces of information: +1) state flag indicating whether the closure has been used at least once or not. +2) creation time; 3) time of most recent use if any so far. +We refer to such a word as an LDV word. + +The LDVU profiler maintains a global time, stored in @ldvTime@. +It is incremented each time a heap census is performed. +During a heap census, the profiler scans all live closures and computes the +following: +1) the total size of all closures which have never been used; +2) the total size of all closures which have been used at least once +in the past.\footnote{There is another category of closures, namely, +\emph{inherently used} closures. We will explain +in Section~\ref{sec-heap-censuses}.} +It is not until the whole program execution finishes that the profiler +can actually decide the total size corresponding to each of the four phases for +a particular heap census. It is only when a closure is destroyed that the profiler +can determine how long the closure has been in a specific phase. +Therefore, it is not sufficient to perform heap censuses periodically in order to +compute the profiling statistics: the runtime system needs to intercept +all events associated with any closures and update necessary information. + +All events associated with closures are handled by one of the three +macros defined +in @includes/StgLdv.h@: @LDV_recordCreate()@, @LDV_recordUse()@, and +@LDV_recordDead()@. + +\begin{itemize} +\item{@LDV_recordCreate()@} is called when a closure is created and updates its +creation time field. + +\item{@LDV_recordUse()@} is called when a closure is used and updates its most recent +use time field. + +\item{@LDV_recordDead()@} is called when a closure @c@ is removed from the graph. +It does not update its LDV word (because @c@ is about to be destroyed). +Instead, it updates the statistics on LDVU profiling according to the following +observation: +if @c@ has never been used (which is indicated by the state flag in its LDV +word), +@c@ contributes to the void phase from its creation time to the last census +time; if @c@ was used at least once (which is also indicated by the state flag), +@c@ contributes to the @drag@ phase after its last use time. +\end{itemize} + +At the end of the program execution, the profiler performs a last census during +which all closures in the heap are declared to be dead and @LDV_recordDead()@ +is invoked on each of them. +Then, the profiler computes the final statistics. + +\section{LDV Words} + +We choose to share the LDV word for both retainer profiling and LDVU +profiling, which cannot take place simultaneously. +This is the reason why there is a +union structure inside the @StgProHeader@ structure. +The field @hp.ldvw@ in the @StgProfHeader@ structure corresponds to the LDV +word: +\begin{code} +typedef struct { + ... + union { + retainerSet *rs; // Retainer Set + StgWord ldvw; // Lag/Drag/Void Word + } hp; +} StgProfHeader; +\end{code} +For instance, the LDV word of a closure @c@ can now be accessed with +@c->header.prof.hp.ldvw@ (or by @LDVW(c)@ where @LDVW()@ is a macro in +@includes/StgLdvProf.h@). + +An LDV word is divided into three fields, whose position is specified +by three constants in @includes/StgLdvProf.h@: +\begin{itemize} +\item{@LDV_STATE_MASK@} corresponds to the state flag. +\item{@LDV_CREATE_MASK@} corresponds to the creation time. +\item{@LDV_LAST_MASK@} corresponds to the most recent use time. +\end{itemize} +The constant @LDV_SHIFT@ specifies how many bits are allocated for +creation time or most recent use time. +For instance, the creation time of a closure @c@ can be obtained by +@(LDVW(c) & LDV_CREATE_MASK) >> LDV_SHIFT@. + +The creation time field and the most recent use time field can be set only by the +macros @LDV_recordCreate()@ and @LDV_recordUse()@. +@LDV_recordCreate()@ must be called whenever a new dynamic closure is created, +and this is handily accomplished by rewriting the macro @SET_PROF_HDR()@ +(in @includes/ClosureMacros.h@) (we do not need to change @SET_STATIC_PROF_HDR()@ +because static closures are not involved in LDVU profiling at all): + +\begin{code} +#define SET_PROF_HDR(c,ccs_) \ + ((c)->header.prof.ccs = ccs_, \ + LDV_recordCreate((c))) +\end{code} + +There are a few cases in which the info table of a closure changes through +an explicit invocation of @SET_INFO()@ or a direct assignment to its @header.info@ +field: 1) an indirection closure is replaced by an old-generation +indirection closure; 2) a thunk is replaced by a blackhole; 3) a thunk is replaced +by an indirection closure when its evaluation result becomes available. + +\emph{We regard such a situation as +the destruction of an old closure followed by the creation of a new closure +at the same memory address.}\footnote{This would be unnecessary if the two closures +are of the same size, but it is not always the case. We choose to distinguish +the two closures for the sake of consistency.} +For instance, when an @IND_PERM@ closure is replaced by an @IND_OLDGEN_PERM@ +closures (during scavenging in @GC.c@), we wrap the invocation of @SET_INFO()@ with +the invocations of @LDV_recordDead()@ and @LDV_recordCreate()@ as follows +(@LDV_recordDead()@ requires the actual size of the closures being destroyed): + +\begin{code} + LDV_recordDead((StgClosure *)p, sizeofW(StgInd) - sizeofW(StgProfHeader)); + SET_INFO(((StgClosure *)p), &stg_IND_OLDGEN_PERM_info); + LDV_recordCreate((StgClosure *)p); +\end{code} + +\textbf{To do:} +A direct assignment to the @header.info@ field implies that its cost centre +field is not initialized. This is no problem in the case of @EVACUATED@ closures +because they will +not be used again after a garbage collection. However, I am not sure if this is safe +for @BLACKHOLE_BQ@ closures (in @StgMiscClosures.hc@) when retainer profiling, +which employs cost centre stacks, is going on. +If it is safe, please leave a comment there. + +@LDV_recordUse()@ is called on a closure whenever it is used, or \emph{entered}. +Its state flag changes if necessary to indicate that it has been used, and +the current global time is stored in its last use time field. + +\section{Global Time \texttt{ldvTime} and Retainer Profiling} + +The global time, stored in @ldvTime@, records the current time period. +It is initialized to $1$ and incremented after each time a heap census +is completed through an invocation of @LdvCensus()@. Note that each +value of @ldvTime@ represents a time \emph{period}, not a point in +time. + +All closures created between two successive invocations of +@LdvCensus()@ have the same creation time. If a closure is used at +least once between two successive heap censuses, we consider the +closure to be in the use phase during the corresponding time period +(because we just set its last use time field to the current value of +@ldvTime@ whenever it is used). Notice that a closure with a creation +time $t_c$ may be destroyed before the actual heap census for time +$t_c$ and thus may \emph{not} be observed during the heap census for +time $t_c$. Such a closure does not show up in the profile at all. + +In addition, the value of @ldvTime@ indicates which of LDVU profiling +and retainer profiling is currently active: during LDVU profiling, it +is initialized to $1$ in @initLdvProfiling()@ and then increments as +LDVU profiling proceeds; during retainer profiling, however, it is +always fixed to $0$. Thus, wherever a piece of code shared by both +retainer profiling and LDVU profiling comes to play, we usually need +to first examine the value of @ldvTime@ if necessary. For instance, +consider the macro @LDV_recordUse()@: + +\begin{code} +#define LDV_recordUse(c) \ + if (ldvTime > 0) \ + LDVW((c)) = (LDVW((c)) & LDV_CREATE_MASK) | ldvTime | LDV_STATE_USE; +\end{code} + +If retainer profiling is being performed, @ldvTime@ is equal to $0$, +and @LDV_recordUse()@ causes no side effect.\footnote{Due to this +interference with LDVU profiling, retainer profiling slows down a bit; +for instance, checking @ldvTime@ against $0$ in the above example +would always evaluate to @rtsFalse@ during retainer profiling. +However, this is the price to be paid for our decision not to employ a +separate field for LDVU profiling.} + +As another example, consider @LDV_recordCreate()@: + +\begin{code} +#define LDV_recordCreate(c) \ + LDVW((c)) = (ldvTime << LDV_SHIFT) | LDV_STATE_CREATE +\end{code} + +The above definition of @LDV_recordCreate()@ works without any problem +even for retainer profiling: during retainer profiling, +a retainer set field (@hp.ldvw@) must be initialized to a null pointer. +Since @ldvTime@ is fixed to $0$, @LDV_recordCreate()@ initializes +retainer set fields correctly. + +\section{Heap Censuses} +\label{sec-heap-censuses} + +The LDVU profiler performs heap censuses periodically by invoking the +function @LdvCensus()@. Because we need to know exactly which +closures in the heap are live at census time, we always precede the +census with a major garbage collection. + +During a census, we examine each closure one by one and compute the +following three quantities: + +\begin{enumerate} +\item the total size of all \emph{inherently used} closures. +\item the total size of all closures which have not been used (yet). +\item the total size of all closures which have been used at least once. +\end{enumerate} + +For most closures, a \emph{use} consists of entering the closure. For +unlifted objects which are never entered (eg. @ARR_WORDS@), it would +be difficult to determine their points of use because such points are +scattered around the implementation in various primitive operations. +For this reason we consider all unlifted objects as ``inherently +used''. The following types of closures are considered to be +inherently used: @TSO@, @MVAR@, @MUT_ARR_PTRS@, @MUT_ARR_PTRS_FROZEN@, +@ARR_WORDS@, @WEAK@, @MUT_VAR@, @MUT_CONS@, @FOREIGN@, @BCO@, and +@STABLE_NAME@. + +The three quantities are stored in an @LdvGenInfo@ array @gi[]@. +@gi[]@ is indexed by time period. For instance, @gi[ldvTime]@ stores +the three quantaties for the current global time period. The +structure @LdvGenInfo@ is defined as follows: + +\begin{code} +typedef struct { + ... + int inherentlyUsed; // total size of 'inherently used' closures + int notUsed; // total size of 'not used yet' closures + int used; // total size of 'used at least once' closures + ... +} LdvGenInfo; +\end{code} + +The above three quantities account for mutually exclusive sets of closures. +In other words, if a closure is not inherently used, it belongs to +either the second or the third. + +\subsection{Taking a Census of the Live Heap} + +During a heap census, we need to visit every live closure once, so we +perform a linear scan of the live heap after a major GC. We can take +advantage of the following facts to implement a linear scan for heap +censuses: + +\begin{itemize} +\item The nursery is empty. The small object pool and the large object pool, + however, may \emph{not} be empty. This is because the garbage collector + invokes @scheduleFinalizer()@ after removing dead closures, and + @scheduleFinalizer()@ may create new closures through @allocate()@. +\item @IND@, @IND_OLDGEN@, and @EVACUATED@ closures do not appear in +the live heap. +\end{itemize} + +There is one small complication when traversing the live heap: the +garbage collector may have replaced @WEAK@ objects with @DEAD_WEAK@ +objects, which have a smaller size and hence leave some space before +the next object. To avoid this problem we change the size of +@DEAD_WEAK@ objects to match that of @WEAK@ objects when profiling is +enabled (see @StgMiscClosures.hc@). + +\section{Destruction of Closures} + +In order to compute the total size of closures for each of the four +phases, we must report the destruction of every closure (except +inherently used closures) to the LDVU profiler by invoking +@LDV_recordDead()@. @LDV_recordDead()@ must not be called on any +inherently used closure because any invocation of @LDV_recordDead()@ +affects the statistics regarding void and drag phases, which no +inherently used closure can be in. + +@LDV_recordDead()@ updates two fields @voidNew@ and @dragNew@ in the +@LdvGenInfo@ array @gi[]@: + +\begin{code} +typedef struct { + ... + int voidNew; + int dragnew; + ... +} LdvGenInfo; +\end{code} + +@gi[ldvTime].voidNew@ accumulates the size of all closures satisfying +the following two conditions: 1) observed during the heap census at +time @ldvTime@; 2) now known to have been in the void phase at time +@ldvTime@. It is updated when a closure which has never been used is +destroyed. Suppose that a closure @c@ which has never been used is +about to be destroyed. If its creation time is $t_c$, we judge that +@c@ has been in the void phase all its lifetime, namely, from time +$t_c$ to @ldvTime@. Since @c@ will not be observed during the next +heap census, which corresponds to time @ldvTime@, @c@ contributes to +the void phase of times $t_c$ through @ldvTime@ - 1. Therefore, we +increase the @voidNew@ field of @gi[@$t_c$@]@ through @gi[ldvTime - 1]@ + by the size of @c@.\footnote{In the actual implementation, we +update @gi[$t_c$]@ and @gi[ldvTime]@ (not @gi[ldvTime@$ - $1@]@) only: +@gi[$t_c$]@ and @gi[ldvTime]@ are increased and decreased by the size +of @c@, respectively. After finishing the program execution, we can +correctly adjust all the fields as follows: @gi[$t_c$]@ is computed as +$\sum_{i=0}^{t_c}$@gi[$i$]@. } + +@gi[ldvTime].dragNew@ accumulates the size of all closures satisfying the following +two conditions: 1) observed during the heap census at time @ldvTime@; +2) now known to have been in the drag phase at time @ldvTime@. +It is updated when a closure which has been used at least once is destroyed. +Suppose that a closure @c@ which has been used last at time $t_l$ is about to +be destroyed. +We judge that @c@ has been in the drag phase from time $t_l + 1$ to +time @ldvTime@$ - 1$ (if $t_l + 1 > $@ldvTime@$ - 1$, nothing happens). +Therefore, we increase the @dragNew@ field of @gi[@$t_l + 1$@]@ through +@gi[ldvTime@$ - 1$@]@ +by the size of @c@.\footnote{As in the case of @voidNew@, we update +@gi[@$t_l + 1$@]@ and @gi[ldvTime]@ only.} + +Now we need to find out all the cases of closure destruction. +There are four cases in which a closure is destroyed: + +\begin{enumerate} +\item A closure is overwritten with a blackhole: + @UPD_BH_UPDATABLE()@ and @UPD_BH_SINGLE_ENTRY()@ in @includes/StgMacros.h@, + @threadLazyBlackHole()@ and @threadSqueezeStack()@ in @GC.c@, + the entry code for @BLACKHOLE@ closures in @StgMiscClosures.hc@ (a + @BLACKHOLE@ closure is changed into a @BLACKHOLE_BQ@ closure). + We call either @LDV_recordDead()@ or @LDV_recordDead_FILL_SLOP_DYNAMIC()@. + +\item A weak pointer is overwritten with a dead weak pointer: + @finalizzeWeakzh_fast()@ in @PrimOps.hc@, + @finalizeWeakPointersNow()@ and @scheduleFinalizers()@ in @Weak.c@. + Since a weak pointer is inherently used, we do not call @LDV_recordDead()@. + +\item A closure is overwritten with an indirection closure: + @updateWithIndirection()@ and @updateWithPermIndirection()@ in @Storage.h@, + @scavenge()@ in @GC.c@, in which an @IND_PERM@ closure is explicitly replaced + with an @IND_OLDGEN_PERM@ closure during scavenging. + We call either @LDV_recordDead()@ or @LDV_recordDead_FILL_SLOP_DYNAMIC()@. + +\item Closures are removed permanently from the graph during garbage +collections. We locate and dispose of all dead closures by linearly +scanning the from-space right before tidying up. This is feasible +because any closures which is about to be removed from the graph still +remains in the from-space until tidying up is completed. The next +subsection explains how to implement this idea. +\end{enumerate} + +\subsection{Linear scan of the from-space during garbage collections} + +In order to implement linear scan of the from-space during a garbage collection +(before tidying up), +we need to take into consideration the following facts: + +\begin{itemize} +\item The pointer @free@ of a block in the nursery may incorrectly point to +a byte past its actual boundary. +This happens because +the Haskell mutator first increases @hpLim@ without comparing it with the +actual boundary when allocating fresh memory for a new closure. +@hpLim@ is later assigned to the pointer @free@ of the corresponding memory +block, which means that during a heap census, the pointer @hpLim@ may not +be trusted. +Notice that @hpLim@ is not available during LDVU profiling; it is valid +only during the Haskell mutator time. + +\item The from-space may well contain a good number of @EVACUATED@ closures, +and they must be skipped over. + +\item The from-space includes the nursery. +Furthermore, a closure in the nursery may not necessarily be adjacent to the next +closure because slop words may lie between the two closures; +the Haskell mutator may allocate more space than actually needed in the +nursery when creating a closure, potentially leaving slop words. +\end{itemize} + +The first problem is easily solved by limiting the scan up to the +actual block boundary for each nursery block (see +@processNurseryForDead()@). In other words, for a nursery block +descriptor @bd@, whichever of @bd->start@$ + $@BLOCK_SIZE_W@ and +@bd->free@ is smaller is used as the actual boundary. + +We solve the second problem by exploiting LDV words of @EVACUATED@ +closures: we store the size of an evacuated closure, which now resides +in the to-space, in the LDV word of the new @EVACUATED@ closure +occupying its memory. This is easily implemented by inserting a call +to the macro @SET_EVACUAEE_FOR_LDV()@ in @copy()@ and @copyPart()@ (in +@GC.c@). Thus, when we encounter an @EVACUATED@ closure while +linearly scanning the nursery, we can skip a correct number of words +by referring to its LDV word. + +The third problem could be partially solved by always monitoring @Hp@ +during the Haskell mutator time: whenever @Hp@ is increased, we fill +with zeroes as many words as the change of @HP@. Then, we could skip +any trailing zero words when linearly scanning the nursery. +Alternatively we could initialize the entire nursery with zeroes after +each garbage collection and not worry about any change made to @Hp@ +during the Haskell mutator time. The number of zero words to be +written to the nursery could be reduced in the first approach, for we +do not have to fill the header for a new closure. Nevertheless we +choose to employ the second approach because it simplifies the +implementation code significantly (see @resetNurseries()@ in +@Storage.c@). Moreover, the second approach compensates for its +redundant initialization cost by providing faster execution (due to a +single memory write loop in contrast to frequent memory write loops in +the first approach). Also, we attribute the initialization cost to +the runtime system and thus the Haskell mutator behavior is little +affected. + +There is further complication though: occasionally a closure is +overwritten with a closure of a smaller size, leaving some slop +between itself and the next closure in the heap. There are two cases: + +\begin{enumerate} +\item A closure is overwritten with a blackhole. +\item A closure is overwritten with an indirection closure. +\end{enumerate} + +In either case, an existing closure is destroyed after being replaced +with a new closure. If the two closures are of the same size, no slop +words are introduced and we only need to invoke @LDV_recordDead()@ on +the existing closure, which cannot be an inherently used closure. If +not, that is, the new closure is smaller than the existing closure +(the opposite cannot happen), we need to fill one or more slop words +with zeroes as well as invoke @LDV_recordDead()@ on the existing +closure. The macro @LDV_recordDead_FILL_SLOP_DYNAMIC()@ accomplishes +these two tasks: it determines the size of the existing closure, +invokes @LDV_recordDead()@, and fills the slop words with zeroes. +After excluding all cases in which the two closures are of the same +size, we invoke @LDV_recordDead_FILL_SLOP_DYNAMIC()@ only from: + +\begin{enumerate} +\item @threadLazyBlackHole()@ and @threadSqueezeStack()@ in @GC.c@ +(for lazy blackholing), +\item @UPD_BH_UPDATABLE()@ and @UPD_BH_SINGLE_ENTRY()@ in +@includes/StgMacros.h@ (for eager blackholing, which isn't the +default), +\item @updateWithIndirection()@ and @updateWithPermIndirection()@ +in @Storage.h@.\footnote{Actually slop words created in +@updateWithIndirection()@ cannot survive major garbage collections. +Still we invoke @LDV\_recordDead\_FILL\_SLOP\_DYNAMIC()@ to support linear +scan of the heap during a garbage collection, which is discussed in the next +section.} +\end{enumerate} + +The linear scan of the from-space is initiated by the garbage +collector. From the function @LdvCensusForDead()@, every dead closure +in the from-space is visited through an invocation of +@processHeapClosureForDead()@. + +\subsection{Final scan of the heap} + +Since a closure surviving the final garbage collection is implicitly destroyed +when the runtime system shuts down, we must invoke @processHeapClosureForDead@ +on \emph{every} closure in the heap once more after the final garbage collection. +The function @LdvCensusKillAll()@, which is invoked from @shutdownHaskell()@ +in @RtsStartup.c@, traverses the entire heap and visits each closure. +It also stops LDVU profiling by resetting @ldvTime@ to $0$. + +It may be that after LDVU profiling stops, new closures may be created +and even garbage collections may be performed. +We choose to ignore these closures because they are all concerned about +finalizing weak pointers (in @finalizeWeakPointersNow()@). +It can be catastrophic to invoke @LdvCensusKillAll()@ after finishing +@finalizeWeakPointersNow()@: @finalizeWeakPointersNow()@ calls +@rts_evalIO()@, which is essentially initiating a new program execution, +and no assumptions made upon LDVU profiling hold any longer. + +\section{Time of Use} + +In order to yield correct LDVU profiling results, we must make sure +that @LDV_recordUse()@ be called on a closure whenever it is used; +otherwise, most of closures would be reported to be in the void phase. +@includes/StgLdvProf.h@ provides an entry macro @LDV_ENTER@ which +expands to @LDV_recordUse()@. The compiler arranges to invoke +@LDV_ENTER@ in the entry code for every dynamic closure it generates +code for (constructors, thunks and functions). We also have to add +@LDV_ENTER@ calls to the closures statically compiled into the RTS: +@PAP@s, @AP_UPD@s, standard thunk forms (in @StgStdThunks.hc@, and +several others in @StgMiscClosures.hc@. + +\section{Computing Final Statistics} + +After the final scan of the heap, we can accurately determine the total +size of closures in one of the four phases at the moment of each heap census. +The structure @LdvGenInfo@ is augmented with two additional fields +@voidTotal@ and @dragTotal@: + +\begin{code} +typedef struct { + ... + int voidTotal; + int dragTotal; + ... +} LdvGenInfo; +\end{code} + +@gi[@$i$@].voidTotal@ and @gi[@$i$@].dragTotal@ are computed +from @gi[@$i$@].voidNew@ and @gi[@$i$@].dragNew@, respectively.\footnote{Due +to a slight optimization described before, @gi[@$i$@].voidTotal@ is actually +computed as $\sum_{1 \leq j \leq i}$@gi[@$j$@].voidNew@. +@gi[@$i$@].dragTotal@ is computed in a similar way.} +Then, the total size of closures in the lag phase @gi[@$i$@].lagTotal@ is computed +as @gi[@$i$@].notUsed@$-$@gi[@$i$@].voidTotal@ (because any unused closure +is either in the void phase or in the lag phase). +Similarly, +the total size of closures in the use phase @gi[@$i$@].useTotal@ is computed +as @gi[@$i$@].used@$-$@gi[@$i$@].dragTotal@ (because any used closure +is either in the use phase or in the drag phase). +@endLdvProfiling()@, called from @endHeapProfiling@ in @ProfHeap.c@, computes these +final statistics. + +\section{Usage} + +The runtime system option @-hL@ tells the executable program to +perform LDVU profiling and produce a @.hp@ file: + +\begin{code} +$ Foo.out +RTS -hL +\end{code} + +The option @-i@ can be used to +specify a desired interval at which LDVU profiling is performed. +The default and minimum value is half a second: + +\begin{code} +$ Foo.out +RTS -hL -i2.5 -RTS +\end{code} + +The @.hp@ file can be supplied to the @hp2ps@ program to create a postscript +file showing the progress of LDVU profiling in a graph: + +\begin{code} +$ hp2ps Foo.hs +$ gv Foo.ps +\end{code} + +The horizontal axis of the graph is in the Haskell mutator time, which excludes +the runtime system time such as garbage collection time and LDVU profiling +time. +The Haskell mutator runs a bit slower than it would without performing +LDVU profiling, but the difference is minute. +Also, the timer employed to periodically perform retainer profiling +is not perfectly accurate. Therefore, the result may slightly vary for each +execution of retainer profiling. + +\textbf{To do:} Currently the LDVU profiling is not supported with @-G1@ option. + +\textbf{To do:} When we perform LDVU profiling, the Haskell mutator time seems to +be affected by @-S@ or @-s@ runtime option. For instance, the following +two options should result in nearly same profiling outputs, but +the second run (without @-Sstderr@ option) spends almost twice as +long in the Haskell mutator as the first run: +1) @+RTS -Sstderr -hL -RTS@; 2) @+RTS -hL -RTS@. +This is quite a subtle bug because this wierd phenomenon is not +observed in retainer profiling, yet the implementation of +@mut_user_time_during_LDV()@ is completely analogous to that of +@mut_user_time_during_RP()@. The overall shapes of the resultant graphs +are almost the same, though. + +\section{Files} + +This section gives a summary of changes made to the GHC in +implementing LDVU profiling. +Only three files (@includes/StgLdvProf.h@, @LdvProfile.c@, and +@LdvProfile.h@) are new, and all others exist in the GHC. + +@\includes@ directory: + +\begin{description} +\item[StgLdvProf.h] defines type @LdvGenInfo@, constants, and macros related +with LDVU profiling. +\item[ClosureMacros.h] changes macro @SET_PROF_HDR()@. +\item[Stg.h] includes th header file @StgLdvProf.h@. +\item[StgMacros.h] changes macros @UPD_BH_UPDATABLE()@ and @UPD_BH_SINGLE_ENTRY()@. +\end{description} + +@\rts@ directory: + +\begin{description} +\item[GC.c] invokes @LdvCensusForDead()@ before tidying up, sets @hasBeenAnyGC@ to + @rtsTrue@, and changes @copy()@ and @copyPart()@. + Invokes @LDV_recordDead()@ and @LDV_recordDead_FILL_SLOP_DYNAMIC()@. +\item[Itimer.c] changes @handle_tick()@. +\item[LdvProfile.c] implements the LDVU profiling engine. +\item[LdvProfile.h] is the header for @LdvProfile.c@. +\item[PrimOps.hc] changes @finalizzeWeakzh_fast()@. +\item[ProfHeap.c] changes @initHeapProfiling()@ and @endHeapProfiling()@. +\item[Profiling.c] changes @initProfilingLogFile@ and @report_ccs_profiling()@. +\item[Proftimer.c] declares @ticks_to_retainer_ldv_profiling@, + @performRetainerLdvProfiling@, and @doContextSwitch@. +\item[Proftimer.h] is the header for @Proftimer.c@. Defines @PROFILING_MIN_PERIOD@, + which specifies the minimum profiling period and the default profiling period. +%\item[RtsAPI.c] implements @setProfileHeader()@. +\item[RtsFlags.c] + sets @RtsFlags.ProfFlags.doHeapProfile@, + adds a string to @usage_text[]@ in @setupRtsFlags()@. +\item[RtsFlags.h] defines constants @HEAP_BY_LDV@ and @LDVchar@. +\item[RtsStartup.c] changes @shutDownHaskell()@. +\item[Schedule.c] changes @schedule()@. +\item[Stats.c] + declares @LDV_start_time@, @LDV_tot_time@, @LDVe_start_time@, + @LDVe_tot_time@. + Changes @mut_user_time_during_GC()@, @mut_user_time()@, + @stat_startExit()@, + @stat_endExit()@, and + @stat_exit()@. + Defines + @mut_user_time_during_LDV()@, + @stat_startLDV()@, and + @stat_endLDV()@. +\item[Stats.h] is hte header for @Stats.c@. +\item[StgMiscClosures.hc] inserts entry macros in + @stg_IND_entry()@, @stg_IND_PERM_entry()@, @stg_IND_OLDGEN_entry()@, + @stg_IND_OLDGEN_PERM_entry()@, @stg_BLACKHOLE_entry()@, @stg_BLACKHOLE_BQ_entry()@, + and @stg_CAF_BLACKHOLE_entry()@. + Invokes @LDV_recordDead()@ in @stg_BLACKHOLE_entry@. + Redefines @stg_DEAD_WEAK_info@. +\item[Storage.c] changes @initStorage()@, @resetNurseries()@, and @allocNursery()@. +\item[Storage.h] changes @updateWithIndirection()@ and @updateWithPermIndirection()@. +\item[Updates.hc] inserts entry macros in @stg_PAP_entry()@ and @stg_AP_UPD_entry()@. +\item[Weak.c] changes @scheduleFinalizers()@. +\end{description} + +\bibliographystyle{plain} +\bibliography{reference} + +\end{document} diff --git a/docs/storage-mgt/megablock.eepic b/docs/storage-mgt/megablock.eepic new file mode 100644 index 0000000000..922226945b --- /dev/null +++ b/docs/storage-mgt/megablock.eepic @@ -0,0 +1,35 @@ +\setlength{\unitlength}{0.00054167in} +% +\begingroup\makeatletter\ifx\SetFigFont\undefined% +\gdef\SetFigFont#1#2#3#4#5{% + \reset@font\fontsize{#1}{#2pt}% + \fontfamily{#3}\fontseries{#4}\fontshape{#5}% + \selectfont}% +\fi\endgroup% +{\renewcommand{\dashlinestretch}{30} +\begin{picture}(6849,1539)(0,-10) +\put(687,1062){\makebox(0,0)[lb]{\smash{{{\SetFigFont{8}{9.6}{\rmdefault}{\mddefault}{\updefault}block}}}}} +\put(687,837){\makebox(0,0)[lb]{\smash{{{\SetFigFont{8}{9.6}{\rmdefault}{\mddefault}{\updefault}descriptor}}}}} +\path(612,1512)(1737,1512)(1737,462) + (612,462)(612,1512) +\path(4062,1512)(5187,1512)(5187,462) + (4062,462)(4062,1512) +\path(12,1512)(6837,1512)(6837,462) + (12,462)(12,1512) +\path(2337,1512)(2337,462) +\path(132.000,192.000)(12.000,162.000)(132.000,132.000) +\path(12,162)(2337,162) +\path(2217.000,132.000)(2337.000,162.000)(2217.000,192.000) +\path(2457.000,192.000)(2337.000,162.000)(2457.000,132.000) +\path(2337,162)(6837,162) +\path(6717.000,132.000)(6837.000,162.000)(6717.000,192.000) +\path(2337,12)(2337,312) +\put(237,912){\makebox(0,0)[lb]{\smash{{{\SetFigFont{8}{9.6}{\rmdefault}{\mddefault}{\updefault}...}}}}} +\put(1962,912){\makebox(0,0)[lb]{\smash{{{\SetFigFont{8}{9.6}{\rmdefault}{\mddefault}{\updefault}...}}}}} +\put(2862,912){\makebox(0,0)[lb]{\smash{{{\SetFigFont{8}{9.6}{\rmdefault}{\mddefault}{\updefault}......}}}}} +\put(5637,912){\makebox(0,0)[lb]{\smash{{{\SetFigFont{8}{9.6}{\rmdefault}{\mddefault}{\updefault}......}}}}} +\put(4362,912){\makebox(0,0)[lb]{\smash{{{\SetFigFont{8}{9.6}{\rmdefault}{\mddefault}{\updefault}block}}}}} +\put(312,237){\makebox(0,0)[lb]{\smash{{{\SetFigFont{8}{9.6}{\rmdefault}{\mddefault}{\updefault}block descriptors}}}}} +\put(4212,237){\makebox(0,0)[lb]{\smash{{{\SetFigFont{8}{9.6}{\rmdefault}{\mddefault}{\updefault}blocks}}}}} +\end{picture} +} diff --git a/docs/storage-mgt/megablock.fig b/docs/storage-mgt/megablock.fig new file mode 100644 index 0000000000..8116c841b5 --- /dev/null +++ b/docs/storage-mgt/megablock.fig @@ -0,0 +1,40 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +65.00 +Single +-2 +1200 2 +6 3000 3675 4125 4725 +6 3075 3975 3900 4425 +4 0 0 50 0 0 12 0.0000 4 135 405 3075 4125 block\001 +4 0 0 50 0 0 12 0.0000 4 180 765 3075 4350 descriptor\001 +-6 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 3000 3675 4125 3675 4125 4725 3000 4725 3000 3675 +-6 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 6450 3675 7575 3675 7575 4725 6450 4725 6450 3675 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 2400 3675 9225 3675 9225 4725 2400 4725 2400 3675 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 + 4725 3675 4725 4725 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 1 2 + 0 0 1.00 60.00 120.00 + 0 0 1.00 60.00 120.00 + 2400 5025 4725 5025 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 1 2 + 0 0 1.00 60.00 120.00 + 0 0 1.00 60.00 120.00 + 4725 5025 9225 5025 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 + 4725 5175 4725 4875 +4 0 0 50 0 0 12 0.0000 4 15 135 2625 4275 ...\001 +4 0 0 50 0 0 12 0.0000 4 15 135 4350 4275 ...\001 +4 0 0 50 0 0 12 0.0000 4 15 270 5250 4275 ......\001 +4 0 0 50 0 0 12 0.0000 4 15 270 8025 4275 ......\001 +4 0 0 50 0 0 12 0.0000 4 135 405 6750 4275 block\001 +4 0 0 50 0 0 12 0.0000 4 180 1305 2700 4950 block descriptors\001 +4 0 0 50 0 0 12 0.0000 4 135 495 6600 4950 blocks\001 diff --git a/docs/storage-mgt/nursery.eepic b/docs/storage-mgt/nursery.eepic new file mode 100644 index 0000000000..9b06c6e0a3 --- /dev/null +++ b/docs/storage-mgt/nursery.eepic @@ -0,0 +1,89 @@ +\setlength{\unitlength}{0.00050000in} +% +\begingroup\makeatletter\ifx\SetFigFont\undefined% +\gdef\SetFigFont#1#2#3#4#5{% + \reset@font\fontsize{#1}{#2pt}% + \fontfamily{#3}\fontseries{#4}\fontshape{#5}% + \selectfont}% +\fi\endgroup% +{\renewcommand{\dashlinestretch}{30} +\begin{picture}(11262,7914)(0,-10) +\path(4575,7137)(6150,7137)(6150,5937) + (4575,5937)(4575,7137) +\path(5325,6987)(5325,7437)(7950,7437)(7950,7137) +\path(7920.000,7257.000)(7950.000,7137.000)(7980.000,7257.000) +\path(11025,7137)(11025,5937) +\path(5475,6687)(5475,7437) +\path(7950,7137)(11250,7137)(11250,5937) + (7950,5937)(7950,7137) +\path(5475,6687)(5475,7887)(11025,7887)(11025,7137) +\path(10995.000,7257.000)(11025.000,7137.000)(11055.000,7257.000) +\path(4725,6087)(4125,6087)(4125,5562) +\path(4095.000,5682.000)(4125.000,5562.000)(4155.000,5682.000) +\path(8070.000,6567.000)(7950.000,6537.000)(8070.000,6507.000) +\path(7950,6537)(11025,6537) +\path(10905.000,6507.000)(11025.000,6537.000)(10905.000,6567.000) +\path(4125,5112)(4125,4587)(4500,4587) +\path(4380.000,4557.000)(4500.000,4587.000)(4380.000,4617.000) +\path(4500,4662)(6075,4662)(6075,3462) + (4500,3462)(4500,4662) +\path(5250,4512)(5250,4962)(7875,4962)(7875,4662) +\path(7845.000,4782.000)(7875.000,4662.000)(7905.000,4782.000) +\path(5400,4212)(5400,4962) +\path(7875,4662)(11175,4662)(11175,3462) + (7875,3462)(7875,4662) +\path(4650,3612)(4050,3612)(4050,2112) +\path(4020.000,2232.000)(4050.000,2112.000)(4080.000,2232.000) +\path(5400,4212)(5400,5412)(7875,5412)(7875,4662) +\path(7845.000,4782.000)(7875.000,4662.000)(7905.000,4782.000) +\path(7995.000,4092.000)(7875.000,4062.000)(7995.000,4032.000) +\path(7875,4062)(9750,4062) +\path(9630.000,4032.000)(9750.000,4062.000)(9630.000,4092.000) +\path(9750,4662)(9750,3462) +\path(9150,2787)(9750,2787)(9750,3462) +\path(9780.000,3342.000)(9750.000,3462.000)(9720.000,3342.000) +\path(9525,2337)(11175,2337)(11175,3462) +\path(11205.000,3342.000)(11175.000,3462.000)(11145.000,3342.000) +\path(3300,4737)(3300,4362)(4500,4362) +\path(4380.000,4332.000)(4500.000,4362.000)(4380.000,4392.000) +\path(3375,7212)(3375,6837)(4575,6837) +\path(4455.000,6807.000)(4575.000,6837.000)(4455.000,6867.000) +\path(4050,1662)(4050,1137)(4425,1137) +\path(4305.000,1107.000)(4425.000,1137.000)(4305.000,1167.000) +\path(4425,1212)(6000,1212)(6000,12) + (4425,12)(4425,1212) +\path(5175,1062)(5175,1512)(7800,1512)(7800,1212) +\path(7770.000,1332.000)(7800.000,1212.000)(7830.000,1332.000) +\path(5325,762)(5325,1512) +\path(7800,1212)(11100,1212)(11100,12) + (7800,12)(7800,1212) +\path(5325,762)(5325,1962)(7800,1962)(7800,1212) +\path(7770.000,1332.000)(7800.000,1212.000)(7830.000,1332.000) +\put(4650,6912){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}start}}}}} +\put(4650,6612){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}free}}}}} +\put(4800,6012){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}link}}}}} +\put(4650,6312){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}blocks=1}}}}} +\put(8625,7287){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}single block}}}}} +\put(8625,6687){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}used memory}}}}} +\put(3900,5337){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}......}}}}} +\put(4575,4437){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}start}}}}} +\put(4575,4137){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}free}}}}} +\put(4725,3537){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}link}}}}} +\put(4575,3837){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}blocks=1}}}}} +\put(8550,4812){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}single block}}}}} +\put(8025,4212){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}used memory}}}}} +\put(9975,4212){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}free}}}}} +\put(9975,3927){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}memory}}}}} +\put(8625,2712){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}Hp}}}}} +\put(8625,2262){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}HpLim}}}}} +\put(0,4887){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}MainRegTable.rCurrentNursery}}}}} +\put(750,7362){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}MainRegTable.rNursery}}}}} +\put(3825,1887){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}......}}}}} +\put(4500,987){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}start}}}}} +\put(4500,687){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}free}}}}} +\put(4500,387){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}blocks=1}}}}} +\put(8475,1362){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}single block}}}}} +\put(8775,762){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}free memory}}}}} +\put(4500,87){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}link=NULL}}}}} +\end{picture} +} diff --git a/docs/storage-mgt/nursery.fig b/docs/storage-mgt/nursery.fig new file mode 100644 index 0000000000..6a4b60fb82 --- /dev/null +++ b/docs/storage-mgt/nursery.fig @@ -0,0 +1,107 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +60.00 +Single +-2 +1200 2 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 6300 1425 7875 1425 7875 2625 6300 2625 6300 1425 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 4 + 0 0 1.00 60.00 120.00 + 7050 1575 7050 1125 9675 1125 9675 1425 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 + 12750 1425 12750 2625 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 + 7200 1875 7200 1125 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 9675 1425 12975 1425 12975 2625 9675 2625 9675 1425 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 4 + 0 0 1.00 60.00 120.00 + 7200 1875 7200 675 12750 675 12750 1425 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 3 + 0 0 1.00 60.00 120.00 + 6450 2475 5850 2475 5850 3000 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 1 2 + 0 0 1.00 60.00 120.00 + 0 0 1.00 60.00 120.00 + 9675 2025 12750 2025 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 3 + 0 0 1.00 60.00 120.00 + 5850 3450 5850 3975 6225 3975 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 6225 3900 7800 3900 7800 5100 6225 5100 6225 3900 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 4 + 0 0 1.00 60.00 120.00 + 6975 4050 6975 3600 9600 3600 9600 3900 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 + 7125 4350 7125 3600 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 9600 3900 12900 3900 12900 5100 9600 5100 9600 3900 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 3 + 0 0 1.00 60.00 120.00 + 6375 4950 5775 4950 5775 6450 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 4 + 0 0 1.00 60.00 120.00 + 7125 4350 7125 3150 9600 3150 9600 3900 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 1 2 + 0 0 1.00 60.00 120.00 + 0 0 1.00 60.00 120.00 + 9600 4500 11475 4500 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 + 11475 3900 11475 5100 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 3 + 0 0 1.00 60.00 120.00 + 10875 5775 11475 5775 11475 5100 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 3 + 0 0 1.00 60.00 120.00 + 11250 6225 12900 6225 12900 5100 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 3 + 0 0 1.00 60.00 120.00 + 5025 3825 5025 4200 6225 4200 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 3 + 0 0 1.00 60.00 120.00 + 5100 1350 5100 1725 6300 1725 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 3 + 0 0 1.00 60.00 120.00 + 5775 6900 5775 7425 6150 7425 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 6150 7350 7725 7350 7725 8550 6150 8550 6150 7350 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 4 + 0 0 1.00 60.00 120.00 + 6900 7500 6900 7050 9525 7050 9525 7350 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 + 7050 7800 7050 7050 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 9525 7350 12825 7350 12825 8550 9525 8550 9525 7350 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 4 + 0 0 1.00 60.00 120.00 + 7050 7800 7050 6600 9525 6600 9525 7350 +4 0 0 50 0 0 17 0.0000 4 150 435 6375 1650 start\001 +4 0 0 50 0 0 17 0.0000 4 165 390 6375 1950 free\001 +4 0 0 50 0 0 17 0.0000 4 165 390 6525 2550 link\001 +4 0 0 50 0 0 17 0.0000 4 165 885 6375 2250 blocks=1\001 +4 0 0 50 0 0 17 0.0000 4 225 1185 10350 1275 single block\001 +4 0 0 50 0 0 17 0.0000 4 225 1320 10350 1875 used memory\001 +4 0 0 50 0 0 17 0.0000 4 30 360 5625 3225 ......\001 +4 0 0 50 0 0 17 0.0000 4 150 435 6300 4125 start\001 +4 0 0 50 0 0 17 0.0000 4 165 390 6300 4425 free\001 +4 0 0 50 0 0 17 0.0000 4 165 390 6450 5025 link\001 +4 0 0 50 0 0 17 0.0000 4 165 885 6300 4725 blocks=1\001 +4 0 0 50 0 0 17 0.0000 4 225 1185 10275 3750 single block\001 +4 0 0 50 0 0 17 0.0000 4 225 1320 9750 4350 used memory\001 +4 0 0 50 0 0 17 0.0000 4 165 390 11700 4350 free\001 +4 0 0 50 0 0 17 0.0000 4 180 825 11700 4635 memory\001 +4 0 0 50 0 0 17 0.0000 4 225 300 10350 5850 Hp\001 +4 0 0 50 0 0 17 0.0000 4 225 720 10350 6300 HpLim\001 +4 0 0 50 0 0 17 0.0000 4 225 3180 1725 3675 MainRegTable.rCurrentNursery\001 +4 0 0 50 0 0 17 0.0000 4 225 2415 2475 1200 MainRegTable.rNursery\001 +4 0 0 50 0 0 17 0.0000 4 30 360 5550 6675 ......\001 +4 0 0 50 0 0 17 0.0000 4 150 435 6225 7575 start\001 +4 0 0 50 0 0 17 0.0000 4 165 390 6225 7875 free\001 +4 0 0 50 0 0 17 0.0000 4 165 885 6225 8175 blocks=1\001 +4 0 0 50 0 0 17 0.0000 4 225 1185 10200 7200 single block\001 +4 0 0 50 0 0 17 0.0000 4 225 1275 10500 7800 free memory\001 +4 0 0 50 0 0 17 0.0000 4 165 1185 6225 8475 link=NULL\001 diff --git a/docs/storage-mgt/reference.bib b/docs/storage-mgt/reference.bib new file mode 100644 index 0000000000..48fa520b27 --- /dev/null +++ b/docs/storage-mgt/reference.bib @@ -0,0 +1,14 @@ +@inproceedings {CN, + author = {Colin Runciman and Niklas Rojemo}, + title = {New Dimensions in heap profiling}, + booktitle = "", + pages = "", + year = "1994" } + +@inproceedings {RR, + author = {Niklas Rojemo and Colin Runciman}, + title = {Lag, drag, void and use - heap profiling and space-efficient compilation revisited}, + booktitle = "", + pages = "", + year = "1996" } + diff --git a/docs/storage-mgt/rp.tex b/docs/storage-mgt/rp.tex new file mode 100644 index 0000000000..2055894282 --- /dev/null +++ b/docs/storage-mgt/rp.tex @@ -0,0 +1,1102 @@ +\documentclass{article} +\usepackage{code,a4wide} + +\usepackage{graphics,epsfig,epic,eepic,epsfig} + +\setlength{\parskip}{0.25cm} +\setlength{\parsep}{0.25cm} +\setlength{\topsep}{0cm} +\setlength{\parindent}{0cm} +\renewcommand{\textfraction}{0.2} +\renewcommand{\floatpagefraction}{0.7} + + +% Terminology +\newcommand{\block}{block} +\newcommand{\Block}{Block} +\newcommand{\segment}{segment} +\newcommand{\Segment}{Segment} +\newcommand{\step}{step} +\newcommand{\Step}{Step} + +\newcommand{\note}[1]{{\em $\spadesuit$ #1}} + +\begin{document} +\title{Implementation of Retainer Profiling} +\author{Sungwoo Park and Simon Peyton-Jones} + +\makeatactive +\maketitle + +\section{Retainer Profiling} + +Retainer profiling~\cite{CN} is a profiling technique which is based upon a +special view of production and consumption of heap objects at runtime: +while producers build heap objects to form new pieces of graph, +consumers hold pointers to these heap objects, or \emph{retain} them, so +that they are not freed during garbage collections. +On this basis, we refereed to such consumers as \emph{retainers}. +Notice that an object can have more than one retainer because it can +be pointed to by multiple objects. + +For each live object in the heap, retainer profiling computes +all its retainers, or its \emph{retainer set}. +A naive implementation of retainer profiling could consider every +immediate ancestor of an object as its retainer. +Although this approach appears to provide an accurate report on the +relationship between retainers and retainees, the result can hardly be useful. +For instance, it is pointless to scrutinize a list and treat each cons +cell as a retainer of the following cons cell. +This observation suggests that we need to have a way of designating only +certain types of objects as candidates for retainers. +In other words, we need to employ an oracle which tells whether a given +object can be a retainer or not. + +Since no retainer of a particular object needs to be using the +object actively, we can find all its retainers simply by traversing +the graph. In other words, we do not have to distinguish those retainers +actively exploiting it from other retainers just holding pointers +to it (either directly or indirectly). +Thus, retainer profiling can be accomplished simply by traversing the +graph. + +Figure~\ref{fig-retaineralgorithm} shows the algorithm for retainer +profiling. The traversal begins at every root, and proceeds +in a depth first manner (or a breadth first manner). +The function @R()@ returns the \emph{identity} of a given retainer such +as its information table address or +the name of the module which creates it. +Notice that the retainer identity function does not need to be a +one-to-one mapping: +multiple objects can share the same identity. +Such a retainer identity function reduces the cost of traversal. +For instance, when an object +is reached from several retainers which share the same identity, we need to +consider only the first visit to the object. +In other words, whichever retainer (among those sharing the same identity) +leads to the object for the first time affects the retainer set of the object +in consideration +and all the other retainers can be ignored. +Thus, the more coarse the function @R()@ is, the less +it costs to traverse the graph for retainer profiling. +The function @isRetainer()@ tells whether a given object is a retainer or not. +Hence, the behavior of the retainer profiling algorithm is parameterized +over: 1) the set of roots; 2) the function @R()@; 3) the function +@isRetainer()@. + +One important invariant on the function @R()@ is that its return value +must be consistent for a given retainer. In other words, @R()@ must return +the same value for a given retainer no matter it is invoked. +For this reason, the memory address of a retainer, for instance, cannot be used as +its retainer identity because its location may change during garbage collections. + +\begin{figure}[ht] +\begin{center} +\begin{code} +for every root r + retain(r, r) + +R(r) = + the identity of r + +isRetainer(c) = + if c is a retainer then + true + else + false + +retain(c, r) = + if R(r) is a member of c.retainerSet then + return + add R(r) to c.retainerSet + if isRetainer(c) then + r' := c + else + r' := r + for every successor c' of c + retain(c', r') +\end{code} +\caption{Retainer profiling algorithm} +\label{fig-retaineralgorithm} +\end{center} +\end{figure} + +Another way of formulating retainer profiling is in terms of fixed point +equations on retainer sets. +To be specific, given the two functions @isRetainer()@ and @R()@, +the retainer set of every object is computed as the least fixed point +solution of the following equations: +\begin{itemize} +\item For every root @r@, +\begin{center} + @R(r)@ $\in$ @r.retainerSet@. +\end{center} +\item For every reachable object @c@, +\begin{center} +$\bigcup_{\mathit{each\ ancestor\ @a@\ of\ @c@}}$ @from(a)@ $\subseteq$ +@c.retainerSet@ +\end{center} +where @from(a)@ returns retainer(s) obtainable from @a@: +\begin{center} +@from(a)@ = if @isRetainer(a)@ then $\{@a@\}$ else @a.retainerSet@. +\end{center} +\end{itemize} + +This document describes the implementation of retainer profiling on +the Glasgow Haskell Compiler runtime system. +It explains every detail of the development so that it can be (hopefully) +a complete maintenance guide. +A secondary goal is to help (hopefully) those who wish to extend the system +to implement another profiling scheme.\footnote{Unless otherwise mentioned, +all identifiers are defined in @RetainerProfile.c@ or @RetainerSet.c@.} + +\section{Installing the GHC} + +Installing the GHC is done as follows: + +\begin{enumerate} +\item Get the source code from the CVS repository. +\begin{code} +./ cvs checkout fpconfig +./fptools/ cvs update -d CONTRIB common-rts distrib docs ghc glafp-utils + hslibs literate mhms mk nofib testsuite +\end{code} + +\item Set up the basic configuration. +\begin{code} +./fptools/ autoconf +./fptools/ghc/ autoconf +./fptools/ configure +\end{code} + +\item Set up the configuration for development and debugging. +\begin{code} +./fptools/mk vi build.mk + GhcHcOpts = -O -fasm -Rghc-timing + SplitObjs = NO + GhcRtsHcOpts = + GhcRtsCcOpts = -g + STRIP =: +\end{code} +@GhcLibWays@ tells the compiler to build the code for profiling as well. +@GhcRtsHcOpts@ has additional flags for @gcc@ when compiling @.hc@ files. +@GhcRtsCcOpts@ has additional flags for @gcc@ when compiling @.c@ files. +Since we will implement retainer profiling in @.c@ files, we turn on the +debugging flag @-g@. +The empty setting for @STRIP@ tells the compiler not to remove source code +information (generated due to the @-g@ option) from executable files so that +they can be examined with @gdb@. + +\item Remove unnecessary files if needed and build everything. +\begin{code} +./fptools/ make +\end{code} +\end{enumerate} + +\section{Adding Retainer Set Fields} + +Since every Haskell closure now needs to store its retainer set at runtime, +it must be augmented with a new field, +namely, a \emph{retainer set field}. +This section explains how to add such a field to Haskell closures. +It should be clear how to generalize the idea for adding +any number of new fields.\footnote{The GHC provides two +ways of building executable programs from +source files: normal way and profiling way. +We are concerned only about profiling way, and all the pieces of code +implementing profiling way are wrapped by the @PROFILING@ +pre-processing directive (as in @\#ifdef PROFILING@). +Therefore, all the additions and changes that we make to the source code +are assumed to be wrapped by the @PROFILING@ pre-processing +directive as well unless otherwise mentioned.} + +\subsection{Adding a new field to Haskell closures} + +We want to add a retainer set field of type @retainerSet@ to every +closure, so we create a new file @includes/StgRetainerProf.h@ where +we define the type @retainerSet@. +The actual definition of @retainerSet@ will be given later. + +\begin{code} +/* includes/StgRetainerProf.h */ +typedef ... retainerSet; +\end{code} + +We make type @retainerSet@ to be publicly available by including +@includes/StgRetainerProf.h@ itself to @includes/Stg.h@ (not wrapped +by @PROFILING@). + +\begin{code} +/* includes/Stg.h */ +#include "StgRetainerProf.h" +\end{code} + +Then we add a retainer set field @rs@ to the @StgProfHeader@ structure. + +\begin{code} +/* include/Closures.h */ +typedef struct { + CostCentreStack *ccs; + retainerSet *rs; +} StgProfHeader; +\end{code} + +Now every closure @c@ (including static closures) has a retainer set field, +which can be accessed with @c->header.prof.rs@ (where @c@ denotes the +address of the closure). + +\subsection{Changing constants} + +We are ready to reflect the new size of Haskell closures to other part +of the source code. +This is accomplished by changing a few constants which specify the size +of certain types of closures and their layout. + +When building the runtime system, the @gcc@ compiler correctly figures out +the size of every structure on its own. +However, +GHC simply reads @includes/Constants.h@ to to determine the size of +closures assumed by the runtime system. +Thus, we must change the constants used by the GHC itself (as opposed to +the runtime system). They are all found in @includes/Constants.h@. +We increase each of them by 1 to reflect the retainer set field which is one +word long: +\begin{code} +/* includes/Constants.h */ +#define PROF_HDR_SIZE 2 +#define SCC_UF_SIZE 5 +#define SCC_SEQ_FRAME_SIZE 4 +\end{code} +@PROF_HDR_SIZE@ denotes the size of the structure @StgProfHeader@, which +is now two words long. +@SCC_UF_SIZE@ and @SCC_SEQ_FRAME_SIZE@ denote the size of the structures +@StgUpdateFrame@ and @StgSeqFrame@ (in @includes/Closures.h@) in +words. + +Now we must rebuild the GHC so that, when executed, the code generated by +the GHC must now allocate one more word for the retainer set field than before. + +\begin{code} +./fptools/ghc/ make boot +./fptools/ghc/ make +\end{code} + +The second command @make boot@ instructs the build system to analyze +the source code dependency so that the next execution of @make@ correctly +finds all required files. + +Next we change four bitmap constants which specify the layout of +certain types of closures. +As an example, let us consider @RET_BITMAP@, which specifies the layout +of thunk selectors (corresponding to closure type @THUNK_SELECTOR@). +Without a retainer set field, there is only one non-pointer (represented +by $1$) followed by one or more pointers (represented by $0$) in the closure +body and the bitmap representation is $0b1$, or $1$. +With a retainer set field, which is not a pointer to another closure and thus +represented by $1$, there are two non-pointers, and the bitmap representation +is $0b11$, or $3$. Notice that the bitmap is interpreted in reverse order: +the least significant bit corresponds to the first word in the closure body, +and the second least significant bit to the second word, and so forth. +The same rule applies to the other three bitmap constants: +@CATCH_FRAME_BITMAP@ (for closure type @CATCH_FRAME@ and structure +@StgCatchFrame@), +@STOP_THREAD_BITMAP@ (for closure type @STOP_FRAME@ and structure +@StgStopFrame@), and +@UPD_FRAME_BITMAP@ (for closure type @UPDATE_FRAME@ and structure +@StgUpdateFrame@). + +\begin{code} +/* rts/StgStdThunks.hc */ +#define RET_BITMAP 3 +/* rts/Exception.hc */ +#define CATCH_FRAME_BITMAP 15 +/* rts/StgStartup.hc */ +#define STOP_THREAD_BITMAP 3 +/* rts/updates.hc */ +#define UPD_FRAME_BITMAP 7 +\end{code} + +For most closure types, the new definition of @StgProfHeader@ is +automatically propagated to their corresponding structures. +However, there are six closures types which are not affected by +@StgProfHeader@. They are all stack closures: +@RET_DYN@, @RET_BCO@, @RET_SMALL@, @RET_VEC_SMALL@, @RET_BIG@, and +@RET_VEC_BIG@. +If you want a new field to be added to these closures, you may +have to modify their corresponding structures. + +\textbf{To do:} Presently the above changes introduce two bug in the +runtime system. +First, @nofib/real/symalg@ ends up with a division-by-zero +exception if we add a new field. +Second, the runtime system option @-auto-all@ clashes in some test files +in the @nofib@ testing suite (e.g., @spectral/expert@). + +\subsection{Initialization code} + +When a new closure is allocated, its retainer set field may have to be +initialized according to the way that retainer profiling is implemented. +For instance, we could use as an initial value a pointer to an empty retainer +set. +Alternatively we could assign a null pointer to indicate that its retainer +set has not been computed yet, which we adopt in our implementation. +In either case, we have to visit the new closure and execute some initialization +code on it so that its retainer set field is set to an appropriate value. + +There are three parts in the source code which need to be modified. +dynamic closure initialization, static closure initialization, +and update frame initialization. +The first is accomplished by modifying the macro @SET_PROF_HDR()@ (in +@include/ClosureMacros.h@). When a closure @c@ is created at runtime, +@SET_PROF_HDR()@ is invoked immediately with @c@ as its first argument. +Thus, the following code initializes the retainer set field of every +dynamic closure to a null pointer. + +\begin{code} +/* include/ClosureMacros.h */ +#define SET_PROF_HDR(c,ccs_) \ + ((c)->header.prof.ccs = ccs_, (c)->header.prof.rs = NULL) +\end{code} + +Similarly, the macro @SET_STATIC_PROF_HDR()@ (in the +same file) specifies how the retainer set field of every static closure +is initialized, which is rewritten as follows: + +\begin{code} +/* include/ClosureMacros.h */ +#define SET_STATIC_PROF_HDR(ccs_) \ + prof : { ccs : ccs_, rs : NULL }, +\end{code} + +\textbf{Obsolete:} Dynamic closures created through explicit C function invocations +(in @RtsAPI.c@) are now initialized by @SET_HDR()@. + +%There is another way of creating dynamic closures through explicit C +%function invocations at runtime. +%Such functions are all defined in @RtsAPI.c@: @rts_mkChar()@, @rts_mkInt()@, +%@rts_mkWord()@, and so forth. +%Each function allocates memory for a new closure, +%initializes it, and returns its address. +%Therefore, we can simply insert in each function another initialization code +%for retainer set fields. +%To this end, we define a macro @setRetainerField()@ and insert it +%in each function: +% +%\begin{code} +%#define setRetainerField(p) \ +% (p)->header.prof.rs = NULL +%\end{code} +% +%For instance, @rts_mkChar()@ is now defined as follows: +% +%\begin{code} +%/* RtsAPI.c */ +%HaskellObj +%rts_mkChar (HsChar c) +%{ +% StgClosure *p = (StgClosure *)allocate(CONSTR_sizeW(0,1)); +% ... +% setRetainerField(p); +% return p; +%} +%\end{code} + +Finally we may need to initialize the retainer set field of an update frame +(stack closure) when it is pushed onto the stack for the first time. +For instance, if we want to initialize the retainer set field of update +frames to a null pointer, we can rewrite the macro @PUSH_STD_CCCS()@ +(in @includes/Updates.h@) as follows: + +\begin{code} +/* includes/Updates.h */ +#define PUSH_STD_CCCS(frame) \ + (frame->header.prof.ccs = CCCS, frame->header.prof.rs = NULL) +\end{code} + +In our implementation of retainer profiling, however, the retainer set field is not +used for any stack closure. +Hence, the above modification is entirely unnecessary. +Also, update frames are the only exception to the standard way of creating +stack closures: all the other types of stack closures with a retainer set +field are eventually initialized by +the macro @SET\_HDR()@ (in @includes/ClosureMacros.h@), which in turn +invokes @SET\_PROF\_HDR()@. This is not the case for update frames. +Compare @PUSH\_UPD\_FRAME()@ (in @includes/Updates.h@) and +@PUSH\_SEQ\_FRAME()@ (in @includes/StgMacros.h@) for clarification. + +\section{Retainer Sets} + +At the end of retainer profiling, every live closure (except stack +closures, for which we do not compute retainer sets) is associated with +a retainer set; there can be no closure without an associated retainer set +because every live closure is visited during traversal. +Since many closures may well be associated with a common retainer set, +we want to avoid creating any particular retainer set more than once. +This section presents the details of manipulating retainer sets in our +implementation. + +\subsection{Identity of a retainer} + +The function @R()@ in Figure~\ref{fig-retaineralgorithm} returns +the identity of a retainer. In order to implement it, we need +a type for retainer identity. +The type @retainer@ (in @includes/StgRetainerProf.h@) is introduced for +this purpose. + +There are various ways of defining the type @retainer@. +For instance, we can designate the information table address of a retainer as +its identity as follows: + +\begin{code} +struct _StgInfoTable; +typedef struct _StgInfoTable *retainer; +\end{code} + +We can also use the cost centre stack associated with the retainer: + +\begin{code} +typedef CostCentreStack *retainer; +\end{code} + +The function @R()@ is embodied as the function @getRetainerFrom()@ in the +implementation, whose type is @(StgClosure *)@ $\rightarrow$ @retainer@. +It is straightforward to define @getRetainerFrom()@ according to the definition +of @retainer@, as illustrated below: + +\begin{code} +retainer getRetainerFrom(StgClosure *c) { return get_itbl(c); } +retainer getRetainerFrom(StgClosure *c) { return c->header.prof.ccs; } +\end{code} + +\subsection{Retainer sets and the cost function} + +A retainer set is stored in the structure @retainerSet@ +(in @includes/StgRetainerProf.h@): + +\begin{code} +typedef struct _retainerSet { + nat num; + nat cost; + ... + int id; + retainer element[0]; +} retainerSet; +\end{code} + +The field @num@ gives the number of retainers in the retainer set, which +are all stored in the array @element[]@. Thus, the size of @element[]@ +is assumed to be @num@. +The field @cost@ gives the sum of the \emph{costs} of those closures +associated with the retainer set: if a closure @c@ is +associated with the retainer set, that is, if @c@ is retained by each +retainer in the retainer set and none else, +the cost of @c@ is added to the field @cost@. +The field @id@ gives a unique identification number for the retainer set. + +The interface to @retainerSet@ is as follows +(see @RetainerSet.h@): + +\begin{description} +\item[@void initializeAllRetainerSet(void)@] initializes the store for retainer sets. +\item[@void refreshAllRetainerSet(void)@] refreshes each retainer set by setting +its @cost@ field to zero. This function does destroy any retainer set. +\item[@void closeAllRetainerSet(void)@] destroys all retainer sets and closes +the store for retainer sets. +\item[@retainerSet *singleton(retainer r)@] returns a singleton retainer set +consisting of @r@ alone. If such a retainer set already exists, no new retainer +set is created. Otherwise, a new retainer set is created. +\item[@retainerSet *addElement(retainer r, retainerSet *rs)@] returns a retainer set +@rs@ augmented with @r@. If such a retainer set already exists, no new retainer set +is created. Otherwise, a new retainer set is created. +\item[@rtsBool isMember(retainer r, retainerSet *rs)@] returns a boolean value +indicating whether @r@ is a member of @rs@. +\item[@void traverseAllRetainerSet(void (*f)(retainerSet *))@] invokes the function +@f@ on every retainer set created. +\item[@void printRetainerSetShort(FILE *, retainerSet *)@] prints a single retainer +set. +\item[@void outputRetainerSet(FILE *, nat *allCost, nat *numSet)@] prints all +retainer sets. Stores the sum of all their costs in @*allCost@ and the number +of them in @*numSet@. +\item[@void outputAllRetainerSet(FILE *)@] prints all retainer sets. +\end{description} + +We also define a \emph{cost function}, which returns the cost of a given closure, +in order to compute the field @cost@. +The cost function can be defined in several ways. +A typical definition is on the size of a closure, which results in +the field @cost@ accumulating the size of all the closures retained by a +retainer set. +If we just want to count the number of closures retained by the +retainer set, we can simply set the cost of every closure to one regardless +of its closure type. +Furthermore, we can define the cost function flexibly according to +the closure type. +For instance, we can set the size of any static closure to zero so that +it is not taken into account at all in computing the field @cost@. +Notice that static closures are also visited during traversal because they +may lead to other dynamic closures (e.g., static indirection closures of +closure type @IND_STATIC@). +This is especially desirable because we usually focus on the heap use. +We can also selectively choose certain dynamic closure types not to contribute +to the field @cost@. + +In our implementation, there are two functions related with the cost function: +@cost()@ and @costPure()@. +@cost()@ returns the size of the entire memory allocated for a given closure +(even including the two fields in the structure @StgProfHeader@). +It returns zero for static closures. +@costPure()@ returns the size of the memory which would be allocated for +a given closure with no profiling. +It is defined in terms of @cost()@, and it suffices to change only @cost()@ +when a new scheme for the cost function is desired. +@costPure()@ is put to actual use in computing the field @cost@ because it +effectively hides the memory overhead incurred by profiling. + +\subsection{Implementation} + +The algorithm for retainer profiling in Figure~\ref{fig-retaineralgorithm} +adds at most one retainer to an existing retainer set (or an empty retainer set) +at any moment; it does not require a retainer set union operation. +This observation simplifies the implementation, and +we employ the following two functions for creating new retainer sets: +@singleton()@, which creates a singleton retainer set, and +@addElement()@, which adds an element to an existing retainer set. + +It is a frequent operation during retainer profiling to search for a retainer +set, which may or may not exist, built from a given retainer set and a +particular retainer. +To efficiently implement this operation, +we choose to store all retainer sets in a hash table and +the structure @retainerSet@ is now extended with two new fields +@hashKey@ and @link@. +The field @hashKey@ stores the hash key which is obtained +from the retainers in a retainer set. +The field @link@ points to the next retainer set in the same bucket: + +\begin{code} +typedef struct _retainerSet { + ... + StgWord hashKey; + struct _retainerSet *link; + ... +} retainerSet; +\end{code} + +The hashing function must be defined in such a way that a retainer set +can have only one unique hash key regardless of the order its elements +are stored, i.e., the hashing function must be additive. + +It is often observed that two successive executions of retainer profiling share +a number of retainer sets in common, especially if the two executions are +close in time. +This also implies that the number of all retainer sets which can be created +at any moment does not grow indefinitely regardless of the interval at which +retainer profiling is performed; it does not grow commensurately with the +number of times retainer profiling is executed. +This observation eliminates the need to free the memory allocated for +retainer sets; we can simply set the @cost@ field of every retainer set +to zero after each retainer profiling and reuse it during the next time. + +\section{Graph Traversal} + +At the heart of retainer profiling lies \emph{graph traversal}; +the algorithm in Figure~\ref{fig-retaineralgorithm} is supposed to visit +every closure in the graph at least once and yield statistics on the heap use. +Since only live closures are reachable from the root, the algorithm +does not deal with dead closures. + +This section presents details on how to achieve an efficient implementation of +graph traversal without incurring extra memory overhead and compromising speed. + +\subsection{Goal} + +Traversing a graph itself can be done in a straightforward way; +we choose either depth first search or breadth first search, and traverse +the graph starting from a given set of roots. +After a complete traversal, each live closure @c@ (including static closures) +has an associated retainer set, whose address is stored in the field +@c->header.prof.rs@. + +A real complication arises when retainer profiling is performed once again: +all live closures which have survived all garbage collections since +the previous retainer profiling +still have an associated retainer set (indicated by +a non-null pointer in their retainer set field), which is no longer +valid. Any new closure created since then has +a null pointer in its retainer set field at the beginning of retainer +profiling and will become associated with a retainer set. +Thus, we can no longer distinguish valid retainer set fields +from invalid ones. + +A simple remedy is to linearly scan the heap at the beginning of each +retainer profiling and set all retainer set fields to a null pointer. +It resets the retainer set field of each dynamic closure, whether it is +live or not with respect to the given set of root. +This is feasible because any closure in the heap directly adjoins the +next closure, if any. +The problem is that we have no way of visiting all live static closures, +for which we compute retainer sets. + +A moment of thought, however, reveals that we can completely avoid computing +retainer sets for static closures. This is because retainer profiling is +concerned only about the heap, which consists of dynamic closures and no +static closures. In other words, we can treat every static closure as +a bridge connecting two dynamic closures. +For instance, if a dynamic closure @c@$_1$ has a pointer to a static +closure @s@ and @c@ has a pointer to another dynamic closure @c@$_2$, +we can think of the pointer in @c@$_1$ as a direct pointer to @c@$_2$. +The big problem is that if the graph has a cycle containing static closures, +an infinite loop occurs. In other words, we have no way of telling whether +a static closure has been visited or not and are forced to compute +retainer sets for static closures as well.\footnote{For instance, +a static closure is allowed to have a self-reference in its SRT, which +is also followed during retainer profiling.} + +Another remedy is to stores in every closure a time stamp for the +retainer set field. The time stamp indicates whether the retainer +set field is valid or no longer valid (i.e., it is for the previous +retainer profiling). +At the cost of one extra field in each closure, we can achieve an +elegant implementation with little complication. +However, it turns out that the memory overhead is too big.\footnote{A typical +dynamic closure is only two or three words long.} +Thus, our goal is to stick to the definition of the structure @StgProfHeader@ +given earlier and yet to achieve an elegant solution. + +\subsection{Basic plan} + +Since we visit every live object and update its retainer set field, +any retainer set field can either be valid (the corresponding retainer +set is valid) or point to a retainer set created during the previous +retainer profiling. +In order to distinguish valid retainer set fields +from invalid ones, we exploit the least significant bit of the retainer +set field: we maintain a one bit mark which flips over every time +retainer profiling is performed, and judge that a retainer set field is +valid only if its least significant bit matches the mark. +The variable @flip@ serves for this purpose. +The macros @isRetainerSetFieldValid()@ tests if the retainer set field +of a give closure @c@ is valid: + +\begin{code} +#define isRetainerSetFieldValid(c) \ + ((((StgWord)(c)->header.prof.rs & 1) ^ flip) == 0) +\end{code} + +As an example, a retainer set field can be set to a null value conforming +the current value of @flip@ by the macro @setRetainerSetToNull()@: + +\begin{code} +#define setRetainerSetToNull(c) \ + (c)->header.prof.rs = (retainerSet *)((StgWord)NULL | flip) +\end{code} + +Now, when a dynamic closure @c@ is created, its retainer set field is +initialized to a null value conforming to the current value of +@flip@:\footnote{Actually this is not mandatory: even when the null +value does not conform to the current value of @flip@, it will be replaced +by a correct null value when @c@ is visited later.} + +\begin{code} +extern StgWord flip; +#define SET_PROF_HDR(c,ccs_) \ + ((c)->header.prof.ccs = ccs_, (c)->header.prof.rs = (retainerSet *)((StgWord)NULL | flip)) +\end{code} + +We do not need to revise @SET_STATIC_PROF_HDR()@ if the initial value of +@flip@ is set to $0$.\footnote{For the same reason, an initial value $1$ +does not compromise the correctness of the implementation.} + +\subsection{Set of roots} + +The set of roots consists of all thread closures (running, sleeping, or +blocked) existing at the beginning of a retainer profiling. +It is handily obtained in an indirect way by invoking the function +@GetRoots()@ (in @Schedule.c@) with an appropriate argument, which must be +a function: +@GetRoots()@ invokes on each root known to the runtime system its argument. +Thus, we implement a function @retainClosure()@, which initiates traversal +from a given root and updates the retainer set of every closure reachable +from the root, +and invokes @GetRoots()@ with @retainClosure@ as an argument. + +In addition to the thread closures, weak pointers are also considered +as roots; they may not be reachable from any thread closure yet are still +being in used. +A weak pointer has three pointer fields: @key@, @value@, and +@finalizer@ (see the structure @StgWeak@ in @includes/Closures.h@). +It turns out that these pointers may not be valid all the time: +at a certain point during execution, for instance, the pointer @key@ may point +to a dead closure. +However, right after a major garbage collection, all the three pointers are +guaranteed to be valid, i.e., they all point to live closures. +This facilitates the handling of weak pointers if we choose to +perform retainer profiling immediately after a major garbage collection. +All weak pointers are found in the linked list @weak_ptr_list@ +(in @Weak.c@). + +See the function @computeRetainerSet()@ for details. + +\subsection{Static closures} + +When a live dynamic closure @c@ is visited for the first time during traversal, +its retainer set field is checked against the current value of @flip@. +If it was created at some point since the previous retainer profiling, +its retainer set field is already set to a correct null value. +Otherwise, it must have been visited +during the previous retainer profiling and thus its retainer set field is +invalid and will be set to a correct null value. +Therefore it is unnecessary to visit all dynamic closures and set their +retainer set field to a correct null value at the beginning of each retainer +profiling. + +However, this operation is required for static closures. +The reason is that a static closure, which is never garbage collected, +may appear alternately in the set of live closures. +In other words, a currently live static closure may become dead and +be resuscitated again. +Therefore, for a static closure, it does not help to check if its +retainer set field conforms to the current value of @flip@. +For instance, +if a static closure happens to belong to the set of live closures every other +retainer profiling, its retainer set field will never set to a null value, +which is disastrous. +Therefore, we choose to visit all live static closures at the beginning +of each retainer profiling and set their retainer set field to a +correct null value. + +In order to find all live static closures, we have each retainer +profiling preceded by a major garbage collection, which knows all live +static closures.\footnote{This is a heavy +restriction on retainer profiling, which makes retainer profiling partially +dependent on garbage collection. +However, it does not affect any retainer profiling result because +retainer profiling considers only live closures, which survive any +garbage collection.} +To be specific, the garbage collector builds a linked list +@scavenged_static_objects@ (in @GC.c@) during a major garbage collection, +which stores all live static closures of our interest. +\footnote{ +A static closure of closure type @IND\_STATIC@ may be put in the +list @mut\_once\_list@ of the oldest generation, instead of the list +@scavenged\_static\_objects@. +In our implementation, such a closure is just skipped over because it +contains only a pointer to a dynamic closure, and we do not compute +its retainer set. +Thus, there is no need to traverse the list @mut\_once\_list@ of the oldest +generation.} +Since it destroys the linked list after finishing the major garbage collection +(by invoking the function @zero_static_object_list()@ with +@scavenged_static_objects@ as its argument), +we traverse the linked list to set the retainer set field of each +live static closure to a correct null value before its destruction. +This is done by invoking the function +@resetStaticObjectForRetainerProfiling()@. + +\textbf{To do:} In the current implemenation, if a static closure has no child +(e.g., @CONSTR_NOCAF_STATIC@, @THUNK_STATIC@ with an empty SRT, and +@FUN_STATIC@ with an empty SRT), we do not compute its retainer set (because +there is no need to do). This slight optimization allows us to render +retainer profiling no longer dependent on garbage collection due to the +following propoerty: + +\begin{center} +A static closure can alternately appear and disappear in the set of live +closures across multiple executions of retainer profiling if and only if +it has an empty SRT and no child. +\end{center} + +Then we can completely eliminate the function +@resetStaticObjectForRetainerProfiling()@. + +\subsection{Traversal} + +The traversal proceeds in a depth first manner and is implemented +with two mutually recursive functions: @retainStack()@ and @retainerClosure()@. +@retainerStack()@ can be invoked on dynamic closures holding a stack chunk: +closure types @TSO@, @PAP@, and @AP_UPD@. +It in turn invokes @retainerClosure()@ on each closure reachable from +stack closures in the stack chunk. Notice that it does not invoke +@retainerClosure()@ on those stack closures because we do not compute +retainer sets for stack closures. +@retainerClosure()@ iteratively traverses all live closures reachable +from a given closure. +It maintains its own stack to record the next scan position in every closure +currently under consideration.\footnote{A recursive version of +@retainerClosure()@ could be implemented easily. +@retainerClosure()@ in our implementation is an iterative version.} +When it encounters a closure holding a stack chunk, it invokes @retainerStack()@ +on that closure. +Hence, +the traversal is triggered simply by invoking @retainerClosure()@ on every root. + +\textbf{To do:} +The correctness of retainer profiling is subject to the correctness +of the two macros @IS_ARG_TAG()@ and @LOOKS_LIKE_GHC_INFO()@ +(see @retainStack()@). Since +@LOOKS_LIKE_GHC_INFO()@ is a bit precarious macro, so I believe that +the current implementation may not be quite safe. Also, @scavenge_stack()@ +in @GC.c@ also exploits this macro in order to identify shallow pointers. +This can be a serious problem if a stack chunk contains some +word which looks like a pointer but is actually not a pointer. + +\subsection{Sanity check} + +Since we assume that a retainer profiling is preceded by a major garbage +collection, +we expect that the size of all the dynamic closures visited during +any retainer profiling adds up exactly to the total size of the heap. +In fact, this is not the case; there can be closures not reachable from +the set of roots yet residing in the heap even after a major garbage +collection. + +First, a dead weak pointer remains in the heap until its finalizer +finishes. Although its finalizer thread closure is part of the set of roots, +the dead weak pointer itself is not reachable from any root. +Since it cannot be visited during retainer profiling anyhow, we do not +need to located it and set its retainer set field +appropriately.\footnote{Dead weak pointers are identified with their +information table @stg\_DEAD\_WEAK\_info@ (in @StgMiscClosures.hc@). +Notice that their closure type is @CONSTR@, \emph{not} @WEAK@; +their information table is replaced by @stg\_DEAD\_WEAK\_info@ in the +function @scheduleFinalizers()@ (in @GC.c@).} + +Second, +mutable variables (of closure type @MUT_VAR@) may remain in the heap +even when they are not reachable from the set of roots while +dynamic closures pointed to by them must be live.\footnote{I do not +understand clearly why this happens :(} +Since such mutable variables may become live again (in the sense that +they become reachable from the set of roots), we must locate them +and set their retainer set field appropriately after each retainer +profiling. This is handily accomplished by traversing the list +@mut_once_list@ in every generation. + +\section{Retainer Profiling Schemes} + +A retainer profiling scheme specifies \emph{what} retainer profiling +yields (as opposed to \emph{how} retainer profiling computes the retainer +set for every live object). +It is determined primarily by the meaning of retainer identity, +that is, the type @retainer@ (in @includes/StgRetainerProf.h@). +The function @getRetainerFrom()@ must be defined according to the +definition of the type @retainer@. + +In order for a new retain profiling scheme to fully work, we need to follow +four steps: + +\begin{enumerate} +\item Define the type @retainer@ as desired. +\item Write @getRetainerFrom()@. +\item Write two hashing functions @hashkeySingletone()@ and + @hashKeyAddElement()@, which return the hash key from a single + retainer and a retainer set with another retainer, respectively. +\item Write two printing functions @printRetainer()@ and + @printRetainerSetShort()@. + These functions are employed when a retainer or a retainer set is + printed in the output file. +\end{enumerate} + +In our implementation, we use cost centre stacks for retainer identity: + +\begin{code} +typedef CostCentreStack *retainer; +\end{code} +\begin{code} +retainer getRetainerFrom(StgClosure *c) { return c->header.prof.ccs; } +\end{code} +\begin{code} +void printRetainer(FILE *f, retainer cc) +{ + fprintf(f,"%s[%s]", cc->label, cc->module); +} +\end{code} + +\textbf{To do:} All the closures created by @rts_mk...()@ in @RtsAPI.c@ are given +@CCS_SYSTEM@ as their cost centre stacks. This may not be accurate indeed, +and, for instance, @CCCS@ may be a better choice than @CCS_SYSTEM@. + +\section{Usage} + +Since cost centre stacks are used as retainer identity, a source program +must be given proper cost centre annotations by programmers. +Alternatively, +we can ask the compiler to automatically insert cost centre annotations. +For instance, the compiler option @-auto-all@ inserts a cost centre +annotation around every top-level function as shown below +(the @-p@ option is a must +because we must build the executable file in a profiling way): + +\begin{code} +$ ghc-inplace -o Foo.out -p -auto-all Foo.hs +\end{code} + +The runtime system option @-hR@ tells the executable program to +gather profiling statistics and report them in a @.prof@ file: + +\begin{code} +$ Foo.out +RTS -hR -RTS +\end{code} + +The option @-i@ can be used to +specify a desired interval at which retainer profiling is performed. +The default and minimum value is half a second: + +\begin{code} +$ Foo.out +RTS -hR -i2.5 -RTS +\end{code} + +Then, two text files are generated: a @.prof@ file and a @.hp@ file. +The @.prof@ file records the progress of retainer profiling: +for each retainer profiling performed during program execution, +it shows +the Haskell mutator time (as opposed to the user time) at which +the retainer profiling starts, +the average number of times a closure is visited, +the sum of costs assigned to all retainer sets (obtained from the field +@cost@ in each retainer set), +and the number of all retainer sets created \emph{since} the beginning +of program execution. +A typical entry in a @.prof@ file looks like: + +\begin{code} +Retainer Profiling: 3, at 3.530000 seconds + Average number of visits per object = 1.687765 + Current total costs = 801844 + Number of retainer sets = 118 +\end{code} + +The sum of costs assigned to all retainer sets may \emph{not} be equal to the +size of the heap. +The discrepancy is attributed to those live object which are not reachable +from the set of roots. +Still it is a good estimate of the size of the heap at the moment when +the retainer profiling was performed. + +The @.prof@ file also shows the contents of every retainer set which +has been assigned a positive cost (i.e., the field @cost@) at least once; +not every retainer set created is assigned a positive cost because quite +a few retainer sets are created as intermediate retainer sets before +creating a real retainer set. This results from the restriction on the way +retainer sets are created (only one retainer can be added to an existing +retainer set at a time). + +An example of the contents of a retainer set is: + +\begin{code} +SET 71 = {<doFile[Main],main[Main],MAIN[MAIN]>, <synth_2[Main],doFile[Main],main[Main],MAIN[MAIN]>} +\end{code} + +The retainer set has an identification number $71$. +It is associated with two retainers, whose retainer identities are shown +inside angle brackets @<...>@. +For instance, the first retainer is created when the cost centre stack +is @doFile[Main],main[Main],MAIN[MAIN]@, shown from the top to the bottom. +Each entry in angle brackets consists of a cost centre name (e.g., @doFile@) +and its module name (e.g., @Main@). + +The @.hp@ file can be supplied to the @hp2ps@ program to create a postscript +file showing the progress of retainer profiling in a graph: + +\begin{code} +$ hp2ps Foo.hs +$ gv Foo.ps +\end{code} + +An example of such a graph is shown in Figure~\ref{fig-cacheprof}. +It shows the cost assigned to each retainer set at the point +when a retainer profiling is performed (marked by a corresponding inverted +triangles on the horizontal axis). +The abbreviated contents of each retainer set is displayed in the right column. +Due to the space limitation, +it shows only topmost cost centres (without module names) +instead of printing the full contents. +For instance, @(71)doFile,synth_2@ corresponds to a retainer set shown above +(@71@ is its identification number). +The contents may be truncated if it is too long. + +Notice that the time is in the Haskell mutator time, which excludes +the runtime system time such as garbage collection time and retainer profiling +time. Thus, the actual execution takes longer than indicated in the +graph. Also, the timer employed to periodically perform retainer profiling +is not perfectly accurate. Therefore, the result may slightly vary for each +execution of retainer profiling. + +\begin{figure}[ht] +\centering +\epsfig{file=cacheprof_p.eps,width=5in} +\caption{A graph showing the progress of retainer profiling} +\label{fig-cacheprof} +\end{figure} + +\section{Comparision with nhc} + +\section{Files} + +This section gives a summary of changes made to the GHC in +implementing retainer profiling. +Only three files (@includes/StgRetainerProf.h@, @RetainerProfile.c@, and +@RetainerProfile.h@) are new, and all others exist in the GHC. + +@\includes@ directory: + +\begin{description} +\item[StgRetainerProf.h] defines types @retainer@ and @retainerSet@. +\item[Stg.h] includes the header file @StgRetainerProf.h@. +\item[Closures.h] changes structure @StgProfHeader@. +\item[Constants.h] changes constants @PROF_HDR_SIZE@, @SCC_UF_SIZE@, and + @SCC_SEQ_FRAME_SIZE@. +\item[ClosureMacros.h] changes macros @SET_PROF_HDR()@ and + @SET_STATIC_PROF_HDR()@. +\item[Updates.h] changes macro @PUSH_STD_CCCS()@. +\end{description} + +@\rts@ directory: + +\begin{description} +\item[Exception.hc] changes constant @CATCH_FRAME_BITMAP@, +\item[StgStartup.hc] changes constant @STOP_THREAD_BITMAP@. +\item[StgStdThunks.hc] changes constant @RET_BITMAP@. +\item[Updates.hc] changes constant @UPD_FRAME_BITMAP@. +\item[RetainerProfile.c] implements the retainer profiling engine. +\item[RetainerProfile.h] is the header for @RetainerProfile.c@. +\item[RetainerSet.c] implements the abstract datatype @retainerSet@. +\item[RetainerSet.h] defines the interface for @retainerSet@. +\item[GC.c] invokes @resetStaticObjectForRetainerProfiling()@ in + @GarbageCollect()@. +\item[Itimer.c] changes @handle_tick()@. +\item[ProfHeap.c] changes @initHeapProfiling()@ and @endHeapProfiling()@. +\item[Profiling.c] changes @initProfilingLogFile()@ and + @report_ccs_profiling()@. +\item[Proftimer.c] declares @ticks_to_retainer_profiling@, + @performRetainerProfiling@, and @doContextSwitch@. +\item[Proftimer.h] is the header for @Proftimer.c@. Defines @PROFILING_MIN_PERIOD@, + which specifies the minimum profiling period and the default profiling period. +%\item[RtsAPI.c] implements @setRetainerField()@. +\item[RtsFlags.c] + sets @RtsFlags.ProfFlags.doHeapProfile@ and + adds a string to @usage_text[]@ in @setupRtsFlags()@. +\item[RtsFlags.h] defines constants @HEAP_BY_RETAINER@ and @RETAINERchar@. +\item[RtsStartup.c] includes the header file @RetainerProfile.h@. + Changes @shutdownHaskell()@. +\item[Schedule.c] changes @schedule()@. +\item[Stats.c] + declares @RP_start_time@, @RP_tot_time@, @RPe_start_time@, + @RPe_tot_time@. + Changes @mut_user_time_during_GC()@, @mut_user_time()@, + @stat_startExit()@, + @stat_endExit()@, and + @stat_exit()@. + Defines + @mut_user_time_during_RP()@, + @stat_startRP()@, and + @stat_endRP()@. +\item[Stats.h] is the header for @Stats.c@. +\item[StgMiscClosures.hc] redefines @stg_DEAD_WEAK_info@. +\item[Storage.c] changes @initStorage()@, @memInventory()@. +\end{description} + +\bibliographystyle{plain} +\bibliography{reference} + +\end{document} diff --git a/docs/storage-mgt/sm.tex b/docs/storage-mgt/sm.tex new file mode 100644 index 0000000000..9dee565c7d --- /dev/null +++ b/docs/storage-mgt/sm.tex @@ -0,0 +1,995 @@ +\documentclass{article} +\usepackage{code,a4wide} + +\usepackage{graphics,epsfig,epic,eepic} + +\setlength{\parskip}{0.25cm} +\setlength{\parsep}{0.25cm} +\setlength{\topsep}{0cm} +\setlength{\parindent}{0cm} +\renewcommand{\textfraction}{0.2} +\renewcommand{\floatpagefraction}{0.7} + + +% Terminology +\newcommand{\block}{block} +\newcommand{\Block}{Block} +\newcommand{\segment}{segment} +\newcommand{\Segment}{Segment} +\newcommand{\step}{step} +\newcommand{\Step}{Step} + +\newcommand{\note}[1]{{\em $\spadesuit$ #1}} + +\begin{document} +\title{The GHC Storage Manager} +\author{Simon Peyton-Jones and Sungwoo Park} + +\makeatactive +\maketitle +\section{Introduction} + +This document describes the details of the GHC storage manager, including +the interface and implementation of each of its components. + +\section{Goals} + +Storage management goals are: +\begin{itemize} +\item Generational collection, supporting multiple generations. +\item The ability to pin the allocation +area into a few pages that we hope will fit entirely in the cache. +\item Allows objects to age within a generation before getting promoted. +\item Heap can grow as needed, rather than having to be pre-sized + by the programmer. +\item We support mark/sweep/compact collection for older generations. +This is a Good Thing when the live memory approaches the available +physical memory, because it reduces paging. +\item Little OS support needed. No @mmap()@ etc. All that we require is + the ability to call @malloc()@ to allocate a new chunk of memory. + There can be intervening ``sandbars'' allocated by other programs + (e.g. DLLs or other @malloc()@'d structures) between chunks of heap. +\end{itemize} + +Language-support goals are: +\begin{itemize} +\item The garbage collector ``shorts out'' indirection objects introduced +by the mutator (notably when overwriting a thunk with an indirection). +\item The garbage collector executes selector thunks. +For example, a thunk for +@(fst x)@ where @x@ is a pointer to a pair @(a,b)@ would be +evaluated by the garbage collector to just @a@. This is an important +strategy for plugging space leaks. +\item The garbage collector traversese the code tree, as well as +the heap data structures, to find which CAFs are live. This is a royal pain. +\item The garbage collector finalises some objects (typically a tiny minority). +At the moment ``finalisation'' means ``call a C routine when this thing +dies'' but it would be more general to schedule a call to a Haskell +procedure. +\end{itemize} + +Instrumentation goals are: +\begin{itemize} +\item The garbage collector can gather heap-census information for profiling. +To this end we can force GC to happen more often than it otherwise would, +and the collector can gather information about the type and cost-centre +associated with each heap object. +\end{itemize} + +\section{The architecture of the storage manager} + +The storage manager is a component of the GHC system which is responsible +for allocating fresh memory for new objects and reclaiming memory +that is no longer used. +It is built on a layered architecture and consists of four main parts: +\emph{megablock allocator}, \emph{block allocator}, \emph{heap allocator}, +and \emph{garbage collector} (Figure~\ref{fig-architecture}). +The megablock allocator communicates directly with the underlying +operating system and forms the lowest level of the storage manager. +The heap allocator and garbage collector lie in the topmost level of +the storage manager and process requests from +the mutator (the Haskell realm at the runtime) and the runtime system. +The block allocator lies between the two levels. + +\begin{figure}[ht] +\begin{center} +\input{architecture.eepic} +\caption{The overall architecture of the storage manager} +\label{fig-architecture} +\end{center} +\end{figure} + +\section{The megablock allocator} + +% need more elaboration - Sung +The megablock allocator implements a direct interface to the underlying +operating system. +It can request a chunk of physical memory of a fixed size, +which is called a \emph{megablock}, from the operating system and returns it +to the block allocator. A new megablock is not initialized by the +megablock allocator; it is later initialized by the block allocator. + +\subsection{Interface} + +\begin{description} +\item[@void *getMBlock()@] allocates a single megablock and returns its +starting address. +\item[@void *getMBlocks(nat n)@] allocates @n@ contiguous megablocks +and returns their starting address. +\end{description} + +\subsection{Implementation} + +Since the megablock allocator communicates directly with the underlying +operating system, its implementation relies on memory allocation functions +provided by the operating system; thus, the implementation varies between +platforms. +However, every megablock is always of a fixed size $2^M$ and aligned on a +$2^M$ boundary, regardless of the platform +(@MBLOCK_SIZE@ in @include/Constants.h@ defines the size of megablocks). +@mblocks_allocated@ in @MBlock.c@ stores the number of megablocks allocated. + +For implementation details, see @MBlock.c@, @MBlock.h@, @include/Block.h@. + +\section{The block allocator} + +The block allocator divides a megablock returned by the megablock allocator +into a contiguous group of \emph{block descriptors} followed by another +contiguous group of \emph{blocks}. + +A block is a contiguous chunk of $2^K$ bytes, starting on +a $2^K$-byte boundary (@BLOCK_SIZE@ in +@include/Constants.h@ defines the size of blocks). +Each block has its own associated block descriptor, which records the +current state of the block. + +Figure~\ref{fig-megablock} shows a megablock after initialization by the +megablock allocator. +Block descriptors occupy the lower address space and blocks the higher address +space in the megablock. +A block is the unit of allocation for the block allocator. +That is, the block allocator hands over store to the heap allocator in multiples of +one block, where multiple heap objects may be allocated. +A contiguous group of blocks, which is called a \emph{block group}, can be +directly handed over to the heap allocator to reduce inter-block +linkage costs. +The first block of a block group is called the \emph{group head}.\footnote{ +An alternative design has the block descriptor at the start of each block. +This makes it easy to locate the block descriptor corresponding to a particular +block, but is pessimistic for cache locality when fiddling with block descriptors. +It also means that only the first block in a contiguous chunk of blocks can +have a block descriptor. This in turn makes it difficult to achieve an +efficient mostly-copying conservative (MCC) garbage collector.} +Since block descriptors are ordered linearly, we can always locate a block +descriptor corresponding to a particular block from the starting address +of the block. + +\begin{figure}[ht] +\begin{center} +\input{megablock.eepic} +\caption{A megablock after initialization} +\label{fig-megablock} +\end{center} +\end{figure} + +\subsection{Interface} + +\begin{description} +\item[@typedef struct bdescr@] is the type of block descriptors. +\item[@void initBlockAllocator(void)@] initializes the block allocator. +\item[@bdescr *allocBlock(void)@] requests a single block and returns +the address of its block descriptor. +\item[@bdescr *allocGroup(nat n)@] allocates a block group of size @n@ +and returns the address of the block descriptor for the group head. +\item[@void freeGroup(bdescr *p)@] frees the block group where @p@ points +to the block descriptor of the group head, and places it in a pool of +free block groups. +\item[@bdescr *Bdescr(StgPtr p)@] takes a pointer @p@ to any byte within +a block and returns a pointer to its block descriptor. It is implemented as +an @inline@ procedure. +\end{description} + +\subsection{Block descriptors} + +A block descriptor has the following structure, defined in +@include/Blocks.h@: + +\begin{code} +typedef struct _bdescr { + StgPtr start; + StgPtr free; + StgWord32 blocks; + struct _bdescr *link; + /* additional fields */ +} bdescr; +\end{code} + +The fields of a block descriptor have the following purposes: + +\begin{description} +\item[@start@] points to the first byte of the corresponding block. +\item[@free@] For a group head, @free@ points to the first free byte in +the block group. For a non-group head, @free@ is set to zero to identify +the corresponding block as a non-group head. +\item[@blocks@] For a group head, @blocks@ stores the number of blocks +in the block group. It is not used for non-group heads. +\item[@link@] For a group head, @link@ is used to chain all individual +blocks or block groups together. For a non-group head, @link@ points +to the block descriptor of the group head. +\end{description} + +\subsection{Implementation} + +The block allocator maintains a linked list of free block groups, whose head +is stored in @free_list@ in @BlockAlloc.c@ (Figure~\ref{fig-freelist}). +When @allocBlock()@ or @allocGroup()@ is called, the block allocator +scans the linked list from @free_list@ and finds the first block group +which can handle the request. +If such a block group exists, it takes off the requested number of blocks +from the block group, creates a new block group from them, +initializes it if needed, and returns it to the caller. +The rest of the old block group, if any, is linked back to the list of free block +groups as another block group. +If such a block group does not exist, the block allocator requests a megablock +from the megablock allocator and processes the request using the new megablock. + +For implementation details, see @BlockAlloc.c@ and @include/Block.h@. + +\begin{figure}[ht] +\begin{center} +\input{freelist.eepic} +\caption{Linked list of free block groups} +\label{fig-freelist} +\end{center} +\end{figure} + +\section{Heap allocator} + +The role of the heap allocator in the storage manager is to allocate fresh +memory upon requests from the mutator and the runtime system. +Memory allocation takes place frequently during the execution of Haskell +programs, and hence its efficiency is crucial to the overall performance. +To handle requests from the mutator and the runtime system efficiently, +the heap allocator maintains three different memory stores, +each of which has its own purpose. + +The first store is the \emph{nursery}, where typical Haskell +objects are born. +The mutator itself can allocate fresh memory directly in the nursery +without invoking an interface function: +the configuration of the nursery is always revealed to the mutator and can even +be changed by the mutator when it allocates fresh memory from the nursery +on its own. +Thus, although the small overhead in manipulating the nursery results in fast +memory allocation, it is up to the mutator to keep the nursery in an +uncorrupted state. + +The second and the third are the \emph{small object pool} and the +\emph{large object pool}. +The heap allocator provides a common interface function to be shared by both stores: +the size of fresh memory requested, which is passed as an argument to the +interface function, determines which of the two stores to be used. +The interface function can be called by both the mutator and the runtime system. + +\subsection{Interface} + +\begin{description} +\item[@void initStorage(void)@] initializes the storage manager. @Storage.c@. +\item[@void allocNurseries(void)@] creates and initializes the nursery. +@Storage.c@. +\item[@void resetNurseries(void)@] re-initializes the nursery. @Storage.c@. +\item[@OpenNursery(hp, hplim)@] opens an allocation area in the nursery and sets +@hp@ and @hplim@ appropriately. +Then the caller can freely use the memory from @hp@ to @hpLim@. +A macro in @include/StgStorage.h@. +\item[@CloseNursery(hp)@] closes the current allocation area beginning at @hp@ +and returns it to the storage manager. +A macro in @include/StgStorage.h@. +\item[@ExtendNursery(hp, hplim)@] closes the current allocation area and +tries to find a new allocation area in the nursery. +If it succeeds, it sets @hp@ and @hplim@ appropriately and returns @rtsTrue@; +otherwise, it returns @rtsFalse@, +which means that the nursery has been exhausted. +The new allocation area is not necessarily contiguous with the old one. +A macro in @Storage.h@. +\item[@StgPtr allocate(nat n)@] allocates @n@ words from either the small +object pool or the large object pool, depending on the argument @n@, +and returns a pointer to the first byte. It \emph{always} succeeds. +@Storage.c@. +\end{description} + +\subsection{Implementation} + +The nursery is implemented with a fixed number of blocks (@nursery_blocks@ +in @Storage.c@ specifies the number of blocks). +Each of these blocks forms its own block group, and they are all linked together +by @allocNurseries()@. +The blocks in the nursery are carefully allocated in a contiguous address +range so that they fit next to each other in the cache. +They are never freed. + +A single block called the \emph{active block} provides the allocation area for +the mutator at any moment. +When the free space left in the active block is not enough for the request from +the mutator, the heap allocator sets the @free@ field in the corresponding +block descriptor to the first free byte in the block and moves the allocation +area to the next block. + +Figure~\ref{fig-nursery} shows the configuration of the nursery during +the mutator time. +The head of the linked list is stored in @MainRegTable.rNursery@, and +the address of the block descriptor of the active block is stored +in @MainRegTable.rCurrentNursery@. +@Hp@, defined as @MainRegTable.rHp@, points to the byte before the first byte of +the current allocation area in the active block. +@HpLim@, defines as @MainRegTable.rHpLim@, marks the boundary of the current +allocation area: +it points to the last byte in the current allocation area, and thus +all the bytes of memory addresses from @Hp@$ + 1$ to @HpLim@ are free. +The mutator can obtain fresh memory simply by adjusting @Hp@ as long as the new +value of @Hp@ does not exceed @HpLim@. For instance, if the mutator +increases @Hp@ by @n@, it can now store an object of size up to @n@ at the +address pointed to by the old value of @Hp@$ + 1$. + +When the runtime system runs, none of the above four pointers +(@MainRegTable.rNursery@, @MainRegTable.rCurrentNursery@, @Hp@ and @HpLim@) are +valid; they are simply aliases to registers. +Instead @g0s0->blocks@\footnote{@g0s0->blocks@ is valid all the time, even during +the mutator time. The meaning of @g0s0@ is explained in the next section.} +can be used to retrieve the head of the linked list, and +the @free@ field in each block descriptor points to the first free byte +in its corresponding block.\footnote{To be precise, this is \emph{not} the +case: a @free@ field may point to a byte past its actual boundary. +This happens because +the mutator first increases @hpLim@ without comparing it with the +actual boundary when allocating fresh memory, +and later assigns @hpLim@ to the @free@ of the corresponding block.} +@Hp@ and @HpLim@ are not saved because they can be inferred from @free@ fields +of the blocks descriptors in the nursery. + +\begin{figure}[ht] +\begin{center} +\input{nursery.eepic} +\caption{Nursery during the mutator time} +\label{fig-nursery} +\end{center} +\end{figure} + +The small object pool is implemented with a linked list of block groups, +each of which consists of a single block (Figure~\ref{fig-smallobjectpool}). +The head of the linked list is stored in @small_alloc_list@ in @Storage.c@. + +\begin{figure}[ht] +\begin{center} +\input{smallobjectpool.eepic} +\caption{Small object pool} +\label{fig-smallobjectpool} +\end{center} +\end{figure} + +The allocation in the small object pool is done in the same way as in the +nursery; @alloc_Hp@ and @alloc_HpLim@ (both defined in @Storage.c@) +point to the first free byte and the boundary of the small object pool, +respectively. +Thus, when @allocate()@ is called and the heap allocator decides to +allocate fresh memory in the small object pool, it simply increases @alloc_Hp@ +by the size of memory requested. +If the allocation cannot be done in the current small object pool, the +heap allocator calls @allocBlock()@ to obtain a new block from the block +allocator, puts it to the head of the linked list, and +sets @alloc_Hp@ and @alloc_HpLim@ appropriately. + +The large object pool is also implemented with a (doubly) linked list of block +groups (Figure~\ref{fig-largeobjectpool}). +The difference from the small object pool is that each block group stores only +a single object: each time the argument to @allocate()@ is +greater than a threshold value (computed from @LARGE_OBJECT_THRESHOLD@ +in @include/Constants.h@), a new block group accommodating the requested size +is created to store a single object. +The new block group is put to the head of the list. +The head of the linked list is available as @g0s0->large_objects@. + +\begin{figure}[ht] +\begin{center} +\input{largeobjectpool.eepic} +\caption{Large object pool} +\label{fig-largeobjectpool} +\end{center} +\end{figure} + +For implementation details, see @Storage.c@ and @include/StgStorage.h@. + +\section{Garbage collector} + +The garbage collector finds all the objects unreachable from a given set of +roots and frees the memory allocated to them. By invoking the +garbage collector regularly, the storage manager prevents the heap from +growing indefinitely and allows Haskell programs to be executed at a +reasonable memory cost. + +The garbage collector in the storage manager is based upon the generational +garbage collection algorithm. +The storage manager records the age for every object in the heap. +An object surviving one garbage collection grows old by one \emph{step}, +and an object surviving a certain number of garbage collections +is promoted to the next \emph{generation}. +That is, a step can be defined as a collection of objects which have survived +the same number of garbage collections (or a collection of objects which are +born at some point between two particular successive garbage collections), +and a generation as a group of steps belonging to a certain range of ages. +Notice that the unit of garbage collections is not step but generation: +a garbage collection applies to all the steps in a generation, and we cannot +perform a garbage collection just on part of a generation. +Furthermore, if a particular generation is garbage collected, so are +all the younger generations.\footnote{Some +authors define a generation as the set of +all the objects created between two particular garbage collection and +an object cannot change its generation (e.g., 1960's, 1970's, and so on). +In this document, +an object can change its generation as it survives garbage collections +(e.g., teenagers, 20's, and so on).} + +Figure~\ref{fig-generation} illustrates how an object grows old. +Every object is created in step $0$ of generation $0$. +As it survives garbage collections, it is moved to the next step of the +same generation until it is finally promoted to +step $0$ of the next generation: +during a garbage collection of generation $g < G$, live objects from +step $s < S_g$ are moved to step $s + 1$, and live objects from +the last step $S_g$ are promoted to step $0$ in generation $g + 1$. +Live objects in step $0$ of generation $G$ stay in the same step; +the oldest generation maintains only one step because there is no point +in aging objects in the oldest generation. +In this way, objects are given a decent chance of dying before being +promoted to the next generation. + +\begin{figure}[ht] +\begin{center} +\input{generation.eepic} +\caption{Evolution of objects through garbage collections} +\label{fig-generation} +\end{center} +\end{figure} + +The main reason that we separate steps from generations is to +reduce the cost of maintaining \emph{backward inter-generational pointers}, +that is, pointers from older generations to younger generations. +Suppose that a garbage collection applies to all generations $0$ +through $g$. If an object @O@ in one of these generations is pointed to +by another object in generation $g' > g$, we cannot free the object @O@ +even though generation $g'$ is out of consideration. Consequently +we have to track backward inter-generational pointers to perform garbage +collections correctly. +Since maintaining backward pointers is costly, we +choose to track backward inter-generational pointers only; +we do not track backward inter-step pointers. + +By grouping all the objects created between two garbage collections +and grouping multiple age groups into one generation, the garbage +collector makes an efficient use of heap memory. + +\subsection{Interface} + +\begin{description} +%\item[@StgClosure *MarkRoot(StgClosure *root)@] informs the garbage collector +%that @root@ is an object in the root set. It returns the new location of +%the object. @GC.c@. +\item[@void *mark\_root(StgClosure **root)@] informs the garbage collector +that @*root@ is an object in the root set. It replaces @*root@ by +the new location of the object. @GC.c@. +\item[@void GarbageCollect(void (*get\_roots)(evac\_fn), rtsBool force\_major\_gc)@] +performs a garbage collection. +@get_roots()@ is a function which is called by the garbage collector when +it wishes to find all the objects in the root set (other than those +it can find itself). +Therefore it is incumbent on the caller to find the root set. +@force_major_gc@ specifies whether a major garbage collection is required +or not. If a major garbage collection is not required, the garbage collector +decides an oldest generation $g$ to garbage collect on its own. +@GC.c@. +\item[@rtsBool doYouWantToGC(void)@] returns @rtsTrue@ if the garbage +collector is ready to perform a garbage collection. Specifically, it returns +@rtsTrue@ if the number of allocated blocks since the last garbage collection +(@alloc_blocks@ in @Storage.c@) exceeds an approximate limit +(@alloc_blocks_lim@ in @Storage.c@). +@Storage.h@. +\item[@void recordMutable(StgMutClosure *p)@] informs the garbage collector +that a previously immutable object @p@ has become mutable. +The garbage collector then puts the object @p@ in the list @mut_list@ of the +generation to which it belongs.\footnote{It is easy to +locate the generation to which a dynamic object belongs from its address: +we can identify the block in which the object resides from its address, +and the corresponding block descriptor stores pointers +to the step and the generation (@gen@ and @step@ fields in the @bdescr@ +structure) to which it belongs.} +It suffices to call @RecordMutable()@ only once for any object. + +For an object which is genuinely mutable (e.g., mutable arrays), +it is permanently recorded as mutable. +On the other hand, +an object which is temporarily mutable (e.g., frozen arrays), +can be dropped from the list @mut_list@ once its pointer has been dealt with +during garbage collections. @Storage.h@. +\item[@void recordOldToNewPtrs(StgMutClosure *p)@] puts the object @p@ in the +list @mut_once_list@ of the generation to which it belongs. +\item[@void newCAF(StgClosure *caf)@] puts the CAF @caf@ either +in the list @caf_list@ or +in the list @mut_once_list@ of the oldest generation, +depending on whether it is dynamically loaded or not. +\end{description} + +\subsection{Steps} + +A step has the following structure, defined in +@include/StgStorage.h@: + +\begin{code} +typedef struct _step { + unsigned int no; + bdescr *blocks; + unsigned int n_blocks; + bdescr *large_objects; + /* additional fields */ +} step; +\end{code} + +The fields of a step have the following purposes (Figure~\ref{fig-step}): + +\begin{description} +\item[@no@] indicates the age within its generation. +$0$ indicates the youngest step in a generation. +\item[@blocks@] is a linked list of all the blocks in this step +which contain small objects. +Each block forms its own block group. +\item[@n\_blocks@] is the number of blocks in the linked list @blocks@. +\item[@large\_objects@] is a (doubly) linked list of all the block groups +in this step which contain large objects. +Each block group stores only a single object. +\end{description} + +\begin{figure}[ht] +\begin{center} +\input{step.eepic} +\caption{Memory layout of a step} +\label{fig-step} +\end{center} +\end{figure} + +The linked list @blocks@ of step $s$ in generation $g$ is created +during a garbage collection +from live small objects of step $s - 1$ in the same generation +(or the last step in the previous generation if $s = 0$). +The @free@ field in every block descriptor never changes because +no objects are added after the garbage collection; new objects are created +only in step $0$ in generation $0$. +Likewise, the linked list @large_objects@ is created during a +garbage collection from live large objects of the previous step. + +There are three exceptions to the above rules. +First, both @blocks@ and @large_objects@ of +step $0$ in generation $0$ are not filled with new objects during a garbage +collection. +They are simply re-initialized by the garbage collector and +grow during during the execution of a program as new objects are +created. +Step $0$ in generation $0$ is accessible via a global variable @g0s0@, +and this is the reason why the large object pool (described in the previous +section) is indeed stored in @g0s0->large_objects@. +For the same reason, @MainRegTable.rNursery@ holds the same address as +@g0s0->blocks@ during the mutator time. +Second, @blocks@ of step $1$ in generation $0$ is created not only from +the nursery (@blocks@ of step $0$ in the same generation) but also from the +small object pool. In other words, all the live small objects created since +the previous garbage collection, either directly by the mutator or indirectly +through @allocate()@, are gathered together in the same linked list. +Finally, step $0$ of the oldest generation serves the source for itself during +any garbage collection, i.e., $S_G = 1$, because there exists no older step. + +\subsection{Generations} + +A generation has the following structure, defined in +@include/StgStorage.h@: + +\begin{code} +typedef struct _generation { + unsigned int no; + step *steps; + unsigned int n_steps; + unsigned int max_blocks; + StgMutClosure *mut_list; + StgMutClosure *mut_once_list; + /* additional fields */ +} generation; +\end{code} + +The fields of a generation have the following purposes (Figure~\ref{fig-gen}): + +\begin{description} +\item[@no@] is the generation number. +\item[@steps@] points to an array of @step@ structures. @steps[@$i$@]@ +corresponds to step $i$ in this generation, i.e., +@steps[@$i$@].no@ is equal to $i$. +\item[@n\_steps@] is the number of @step@ structures in the array pointed to +by @steps@. +\item[@max\_blocks@] is the maximum number of blocks allowed in step $0$ of +this generation. If the number of blocks allocated +in step @0@ exceeds @max_blocks@, +this generation is garbage collected during the next garbage collection. +\item[@mut\_list@] links all mutable objects in this generation, that is, +objects whose contents can be updated and hence may contain pointers to +younger generations. +Every object in this linked list is a dynamic object residing in the heap +and has a structure compatible with @StgMutClosure@. +The structure @StgMutClosure@ (@includes/Closures.h@) has a field +@mut_link@ (called a mutable link field) of type @StgMutClosure *@, which +points to the next object in this linked list. +The end mark of this linked list is a pointer to a statically allocated object +@END_MUT_LIST@ (@StoragePriv.h@). +\item[@mut\_once\_list@] links objects in this generation whose contents +cannot be updated any more but may already have pointers to younger generations. +As with @mut_list@, it links only those objects whose structure is compatible +with @StgMutClosure@ and ends with @END_MUT_LIST@. +\end{description} + +\begin{figure}[ht] +\begin{center} +\input{gen.eepic} +\caption{Memory layout of a generation} +\label{fig-gen} +\end{center} +\end{figure} + +The garbage collector maintains an array @generations@ of @generation@ structure +(defined in @Storage.c@), whose size is stored in a runtime system flag +(@RtsFlags.GcFlags.generations@). +The generation number of each generation coincides with its index into +the array @generations@, i.e., @generations[@$i$@].no@ is equal to $i$. + +As mentioned before, lists of objects which may have pointers to younger +generations are kept per generation, not per step. The youngest generation, +accessible via a global variable @g0@, does not keep such a list because it +does not have younger generations. + +The oldest generation, accessible via a global variable @oldest_gen@, may +contain static objects (as opposed to dynamic objects residing in the heap) +in its list @mut_once_list@. This happens when a static +thunk, also known as a \emph{constant applicative form} (CAF), is entered. +When a CAF (corresponding to closure type @THUNK_STATIC@, defined +in @includes/ClosureTypes.h@) is entered, +it is first put in the list @mut_once_list@ of the oldest generation +and then overwritten with an appropriate static indirection object +(corresponding to closure type @IND_STATIC@).\footnote{Actually a static +indirection object does not have a @mut\_link@ field. +We use its @static\_link@ field as a substitute for @mut\_link@. +See the structure @StgIndStatic@ in @include/Closures.h@.}\footnote{For +details of this operation, see the macro @UPD\_CAF()@ in @includes/Updates.h@} +If the CAF is dynamically loaded (e.g., in an interactive environment), it is +instead put in a separate linked list @caf_list@ +(declared in @Storage.c@). + +The evaluation result of the +CAF is stored in a separate dynamic object in the heap and the static +indirection object has a pointer to the dynamic object. +Thus, the new static indirection object is put in the list +@mut_once_list@ of the oldest generation (or the list @caf_list@) so that the +dynamic object is not removed during the next garbage collection. +Once it is created, the static indirection object remains unaltered, which +is the reason why it is put in the @mut_once_list@ list, not in the +@mut_list@ list. +Since the static indirection object survives any garbage collection (because +it comes from a static object) and would be eventually moved to the oldest +generation, +we put it in the @mut_once_list@ of the oldest generation as soon +as it is created. + +\subsection{Implementation} + +The overall structure of a garbage collection is as follows: + +\begin{enumerate} +\item[(1)] Initialize. +\item[(2)] Scavenge lists @mut_once_list@ and @mut_list@ if necessary. +\item[(3)] Scavenge CAFs. +\item[(4)] Evacuate roots. +\item[(5)] Scavenge objects. +\item[(6)] Tidy up. +\end{enumerate} + +\subsubsection{(1) Initialization} + +During initialization, the garbage collector first decides which generation +to garbage collect. +Specifically, +if the argument @force_major_gc@ to @GarbageCollect()@ is @rtsFalse@, +it decides the greatest generation number $N$ such +that the number of blocks allocated in step $0$ of generation $N$ exceeds +@generations[@$N$@].max_blocks@. +If the argument @force_major_gc@ to @GarbageCollect()@ is @rtsTrue@, +$N$ is set to the greatest generation number, namely, +$@RtsFlags.GcFlags.generations@ - 1$. +The garbage collector considers up to generation $N$ for garbage collection. +A major garbage collection takes place if $N$ is set to +$@RtsFlags.GcFlags.generations@ - 1$ during this process. + +Then, the garbage collector initialize the \emph{to-space} (as opposed to +\emph{from-space}) for each step of +each generation, which is complete with an \emph{allocation pointer} and +an \emph{sweep pointer}. +The to-space of a step is the memory to which any object belonging to the +step can be copied when it survives a garbage collection. +For instance, a live object in step $s$ of generation $g$ can first be copied +to the to-space associated with step $s$, which eventually becomes +associated with the next step $s + 1$ (or step $0$ of the next generation) +during tidying up. +This operation effectively moves an object to the next step if it survives +a garbage collection. +The allocation pointer points to the next free in the to-space while +the sweep pointer points to the next object considered for scavenging. + +During major garbage collections, +the static link field of every static object indicates whether it has +been visited by the garbage collector or not. +Therefore, the static link field of every static object must have +a null value before a major garbage collection starts. +The list @mut_once_list@ of the oldest generation may contain static +indirection objects, and thus +the garbage collector invokes @zero_mutable_list()@ on the list, +Although this breaks up the list, it does not cause any problem because +the list is not employed during major garbage collections. + +\subsubsection{\tt evacuate()} + +The function @evacuate()@ (defined in @GC.c@), which +is called eventually for every live object +(including even static objects reachable from roots), +moves an object to +a safe place so as not to be garbage collected. +Before invoking the function @evacuate()@ on an object @o@, the caller specifies +a \emph{desired generation} for @o@ in a variable @evac_gen@ +(declared in @GC.c@). +The desired generation is the youngest generation to which the caller wishes +@o@ to be evacuated; the garbage collector should evacuate @o@ to a +generation no younger than the desired generation. + +Depending on @evac_gen@ and the generation $M$ where @o@ currently resides, +@evacuate()@ behaves itself as follows: +\begin{itemize} +\item If @evac_gen@ $\leq M$ and $N < M$, it does nothing because @o@ is already + in a generation no younger than @evac_gen@. +\item If @evac_gen@ $\leq M \leq N$, it evacuates @o@ to the to-space of the +step to which @o@ currently belongs. @o@ will be moved to the next step later. +@recordMutable()@ may be invoked on @o@ depending on its type (e.g., @MVAR@). +\item If $M <$ @evac_gen@, @o@ is evacuated to the to-space of step $0$ + of generation @even_gen@, which accomplishes the request. + This happens even when $N \leq$ @evac_gen@. Therefore, those generations + which are not considered for garbage collection may still be augmented + with new objects during garbage collection. + @recordMutable()@ may be invoked on @o@ depending on its type. +\end{itemize} +If @o@ has already been evacuated, @evacuate()@ either does nothing (when +@even_gen@ $\leq M$) or reports +a failure to evacuate @o@ by setting the flag @failed_to_evac@ (declared +in @GC.c@). + +Evacuating a large object is handled by @evacuate_large()@. +Since it is costly to allocate new memory blocks and copy all the contents +of the object, the garbage collector simply removes the object form +the list @large_alloc_list@ of its step and links it to another list, +from which it will be scavenged later. + +\subsubsection{Set of roots for garbage collection} +Part of the set of roots for garbage collection is obtained indirectly by +invoking the function +@get_roots()@, an argument to @GarbageCollect()@: the garbage collector +invokes @get_roots()@ with @mark_root()@ as an argument, and @get_roots()@ +in turn invokes @mark_root()@ on each of known roots. +The rest of the set of roots is obtained from the lists @mut_list@ and +@mut_once_list@ of generation $N + 1$ through the oldest generation: +any objects in these lists may have pointers to objects in generations +$0$ to $N$, and thus must be considered as a root. +If a major garbage collection takes place, no @mut_list@ and @mut_once_list@ +lists are consider for scavenging and step (2) is skipped. +The entire set of roots is now specified by @get_roots()@ alone. + +\subsubsection{(2) Scavenging lists {\tt mut\_once\_list} and {\tt mut\_list}} + +Since the roots obtained from the lists @mut_list@ and @mut_once_list@ are +already in generations $N' > N$, we only have to scavenge them. +That is, it suffices to invoke @evacuate()@ once on each object +which is currently pointed to by an object in these lists. + +When scavenging an object @r@ in the list @mut_once_list@ of generation $M$, +the desired generation is set to $M$ for each object @o@ pointed +to by @r@ before invoking @evacuate()@. +The rationale is that the contents of @r@ cannot be updated any more, +and thus @r@ is always survived by @o@; @o@ is live as long as @r@ is. +Therefore, we wish @r@ to be evacuated to the same generation $M$ as @r@ +currently resides (not to its next step). +If the evacuation succeeds (indicated by a @rtsFalse@ value of a variable +@failed_to_evac@, declared in @GC.c@) for every object @o@, @r@ is removed +from the list @mut_once_list@ because it does not hold any backward +inter-generational pointers.\footnote{It turns out that @r@ can have only +one such object @o@. The type of @r@ is one of the following: +@IND\_OLDGEN@, @IND\_OLDGEN\_PERM@, @IND\_STATIC@, and @MUT\_VAR@.} + +Scavenging a list @mut_list@ is similar to the case of @mut_once_list@. +When scavenging an object @r@ in the list @mut_list@ of generation $M$, +the desired generation is set to $M$ for each object pointed to by @r@ +if @r@ is known to be immutable (e.g., @MUT_ARR_PTRS_FROZEN@, +@IND_OLDGEN@) +or to $0$ if @r@ is still mutable (e.g., @MUT_ARR_PTRS@, @MUT_VAR@). +The list @mut_once_list@ is also adjusted if it is safe to remove @r@ from +@mut_list@. + +\subsubsection{(3) Scavenging CAFs} + +When a dynamically loaded CAF is entered, it it first put to the list +@caf_list@ and then overwritten with a static indirection object. +The evaluation result of the CAF is stored in a dynamic object in the heap +and the static indirection object stores a pointer to the dynamic object. +Although the static indirection object (or the CAF) itself is never freed, +it may be removed later from the @caf_list@ when it is reverted to the +original CAF, and the dynamic object may not be live afterwards. +Hence, we treat the dynamic object just as normal dynamic objects and +set the desired generation to $0$. + +\subsubsection{(4) Evacuating roots} + +Evacuating roots (other than those in the lists @mut_once_list@ and +@mut_list@) is simply done by invoking @get_roots()@ with @mark_root()@ +as an argument. +Since these roots are normal dynamic objects, we set the desired generation +to $0$. + +\subsubsection{(5) Scavenging} + +The garbage collector scavenges all the objects in the to-space of +each step (by invoking @evacuate()@ on each object reachable from them) +until every sweep pointer has reached its corresponding +allocation pointer. +It repeatedly examines all the to-spaces because not only sweep pointers +but also allocation pointers change during scavenging: +when an object @r@ is scavenged, each object reachable from +@r@ is evacuated to a certain to-space, which increases the corresponding +allocation pointer, and +the sweep pointer of the to-space which currently contains @r@ +increases as well upon finishing scavenging the object @r@. +Thus, the garbage collector cannot anticipate in advance how many times +it needs to scan through all the to-spaces; it keeps scavenging until +no objects are left to be scavenged. + +\subsubsection{Scavenging static objects} + +Since it is possible for dynamic objects to point to static objects, +the garbage collector may invoke @evacuate()@ on static objects +while scavenging dynamic objects in to-spaces. +This complicates the garbage collector because +static objects cannot be evacuated in general yet +they may have pointers to dynamic objects, which must be evacuated. +Thus the garbage collector needs to at least scavenge live static objects +(as opposed to those static objects currently not reachable from roots). + +When a minor garbage collection is performed, any invocation of +@evacuate()@ on static objects is simply ignored. +Furthermore, no static object is considered for scavenging +(except those in the list @mut_once_list@ of the oldest generation during). +Still all dynamic objects which are marked as live due to static objects +are safely evacuated. +The reason is that we can reach all such dynamic objects from +indirection static objects stored in the list +@mut_once_list@ of the oldest generation, which is scavenged during step (2), +and the list @caf_list@. +In other words, in order to evacuate all such dynamic objects, it is +sufficient to evacuate all dynamic objects reachable from +static indirection objects in +the list @mut_once_list@ of the oldest generation and the list @caf_list@. +However, the garbage collector may unnecessarily scavenge certain static +indirection objects which are no longer used. +They are not scavenged during a major garbage collection, however. + +During a major garbage collection, +if an invocation of @evacuate()@ on a static object @r@ is made, +the garbage collector first checks whether @r@ needs to be scavenged or not. +If its SRT (Static Reference Table) is empty and it has no other pointers, +no dynamic objects are reachable from @r@ and it is ignored.\footnote{If +no dynamic objects are reachable from a static object @r@ (even indirectly +via multiple static objects), +@r@ is not stored in \emph{any} SRT table because it would be no use attempting +to follow any pointers in @r@.} +Otherwise, it is put in the list @static_objects@. +At the beginning of each scavenging loop in step (5), +the garbage collector invokes @scavenge_static()@ if the list @static_objects@ +is not empty. +@scavenge_static()@ scavenges the static objects in the list @static_objects@ +by invoking @evacuate()@ on every object reachable from them. +The desired generation is set to the oldest generation (because any +dynamic object directly pointed to by a static object lives +forever). +These static objects are then put in another list @scavenged_static_objects@ +and removed from the list @static_objects@. +For a static indirection object, if the evacuation +fails, it is put back to the list @mut_once_list@ of the oldest generation; +it can be thought of as a CAF just entered. + +After a major garbage collection, therefore, the list @scavenged_static_objects@ +links all live static objects except for static indirection objects put back +to the list @mut_once_list@ of the oldest generation. +Dynamically loaded CAFs are found in the list @caf_list@. + +\subsubsection{(6) Tidying up} + +The garbage collector tidies up the heap by +moving the to-space of each step to the next step. +It also re-initialize the small object pool (which now does not contain +any live objects), frees any large objects which have not been scavenged, +and invokes @resetNurseries()@. +If a major garbage collection has been performed, it +invokes @zero_static_object_list()@ on the list @scavenged_static_objects@ +so that all static objects +(other than those in the list @mut_once_list@ of the oldest generation) +have a null static link field again. + +At this point, both the small allocation pool and the large object pool are +empty. Upon the exit from @GarbageCollect()@, however, they may not +be empty any more because the garbage collector invokes @scheduleFinalizer()@ +before exiting, which tries to run pending finalizers on dead weak pointers and +may create new objects through @allocate()@. +The nursery still remains intact. + +The heap may contain extra objects which are not reachable from the roots +used during the garbage collection: 1) weak head pointers; 2) dead +weak head pointers. Weak head pointers can be tracked from +the list @weak_ptr_list@ (declared in @Weak.c@). However, there is no way +of reaching dead weak pointers; they will be garbage collected during the +next garbage collection. + +For implementation details, see @GC.c@. + +\section{State of the heap allocator and the garbage collector} + +The state of the heap allocator and the garbage collector is fully specified by the +following variables: + +\begin{description} +\item[@small\_alloc\_list@] is the header of the small object pool. +\item[@alloc\_Hp@] points to the first free byte in the small object pool. +\item[@alloc\_HpLim@] points to the boundary of the small object pool. +\item[@generations@] is the array of @generation@ structures. +\item[@RtsFlags.GcFlags.generations@] specifies the number of elements in +the array @generations@. +\item[@caf\_list@] links dynamically loaded CAFs. +\end{description} + +\textbf{To do:} check if this is a complete list. + +The following variables are derivable, but they are given special purposes: + +\begin{description} +\item[@g0s0@] points to step 0 of the youngest generation. +\item[@oldest\_gen@] points to the oldest generation. +\item[@g0s0->blocks@] is the header of the nursery. +\item[@g0s0->large\_blocks@] is the header of the large object pool. +\end{description} + +\section{Miscellaneous notes} + +\begin{itemize} +\item To see how to add new fields to Haskell closures, +see the document on the implementation of retainer profiling +(section `Adding Retainer Set Fields'). + +\item To see how to traverse the graph and visit every live closure, +see the document on the implementation of retainer profiling +(section `Graph Traversal'). + +\item To see how to linearly scan the heap at any random moment during +program execution, see the document on the implementation of LDVU profiling +(section `Heap Censuses'). + +\item To see how to linearly scan the from-space during garbage collections, +see the document on the implementation of LDVU profiling +(section `Destruction of Closures'). + +\end{itemize} + +\end{document} diff --git a/docs/storage-mgt/smallobjectpool.eepic b/docs/storage-mgt/smallobjectpool.eepic new file mode 100644 index 0000000000..0ccf61c3fb --- /dev/null +++ b/docs/storage-mgt/smallobjectpool.eepic @@ -0,0 +1,65 @@ +\setlength{\unitlength}{0.00050000in} +% +\begingroup\makeatletter\ifx\SetFigFont\undefined% +\gdef\SetFigFont#1#2#3#4#5{% + \reset@font\fontsize{#1}{#2pt}% + \fontfamily{#3}\fontseries{#4}\fontshape{#5}% + \selectfont}% +\fi\endgroup% +{\renewcommand{\dashlinestretch}{30} +\begin{picture}(10062,5607)(0,-10) +\path(3375,5262)(4950,5262)(4950,4062) + (3375,4062)(3375,5262) +\path(4125,5112)(4125,5562)(6750,5562)(6750,5262) +\path(6720.000,5382.000)(6750.000,5262.000)(6780.000,5382.000) +\path(6750,5262)(10050,5262)(10050,4062) + (6750,4062)(6750,5262) +\path(6870.000,4692.000)(6750.000,4662.000)(6870.000,4632.000) +\path(6750,4662)(8625,4662) +\path(8505.000,4632.000)(8625.000,4662.000)(8505.000,4692.000) +\path(8625,5262)(8625,4062) +\path(8025,3387)(8625,3387)(8625,4062) +\path(8655.000,3942.000)(8625.000,4062.000)(8595.000,3942.000) +\path(8400,2937)(10050,2937)(10050,4062) +\path(10080.000,3942.000)(10050.000,4062.000)(10020.000,3942.000) +\path(3525,4212)(2925,4212)(2925,2712) +\path(2895.000,2832.000)(2925.000,2712.000)(2955.000,2832.000) +\path(1950,4962)(3375,4962) +\path(3255.000,4932.000)(3375.000,4962.000)(3255.000,4992.000) +\path(2925,2262)(2925,1737)(3300,1737) +\path(3180.000,1707.000)(3300.000,1737.000)(3180.000,1767.000) +\path(3300,1812)(4875,1812)(4875,612) + (3300,612)(3300,1812) +\path(4050,1662)(4050,2112)(6675,2112)(6675,1812) +\path(6645.000,1932.000)(6675.000,1812.000)(6705.000,1932.000) +\path(9750,1812)(9750,612) +\path(6675,1812)(9975,1812)(9975,612) + (6675,612)(6675,1812) +\path(3450,762)(2850,762)(2850,237) +\path(2820.000,357.000)(2850.000,237.000)(2880.000,357.000) +\path(6795.000,1242.000)(6675.000,1212.000)(6795.000,1182.000) +\path(6675,1212)(9750,1212) +\path(9630.000,1182.000)(9750.000,1212.000)(9630.000,1242.000) +\path(3900,1362)(5850,1362)(5850,12) + (9750,12)(9750,612) +\path(9780.000,492.000)(9750.000,612.000)(9720.000,492.000) +\put(3450,5037){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}start}}}}} +\put(3600,4137){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}link}}}}} +\put(3450,4437){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}blocks=1}}}}} +\put(7425,5412){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}single block}}}}} +\put(6900,4812){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}used memory}}}}} +\put(8850,4812){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}free}}}}} +\put(8850,4527){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}memory}}}}} +\put(2700,2487){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}......}}}}} +\put(0,4887){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}small\_alloc\_list}}}}} +\put(6825,3312){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}alloc\_Hp}}}}} +\put(6600,2862){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}alloc\_HpLim}}}}} +\put(3375,1587){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}start}}}}} +\put(3525,687){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}link}}}}} +\put(3375,987){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}blocks=1}}}}} +\put(7350,1962){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}single block}}}}} +\put(7350,1362){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}used memory}}}}} +\put(2625,12){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}......}}}}} +\put(3375,1302){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}free}}}}} +\end{picture} +} diff --git a/docs/storage-mgt/smallobjectpool.fig b/docs/storage-mgt/smallobjectpool.fig new file mode 100644 index 0000000000..afcfe9862d --- /dev/null +++ b/docs/storage-mgt/smallobjectpool.fig @@ -0,0 +1,74 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +60.00 +Single +-2 +1200 2 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 6225 3900 7800 3900 7800 5100 6225 5100 6225 3900 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 4 + 0 0 1.00 60.00 120.00 + 6975 4050 6975 3600 9600 3600 9600 3900 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 9600 3900 12900 3900 12900 5100 9600 5100 9600 3900 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 1 2 + 0 0 1.00 60.00 120.00 + 0 0 1.00 60.00 120.00 + 9600 4500 11475 4500 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 + 11475 3900 11475 5100 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 3 + 0 0 1.00 60.00 120.00 + 10875 5775 11475 5775 11475 5100 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 3 + 0 0 1.00 60.00 120.00 + 11250 6225 12900 6225 12900 5100 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 3 + 0 0 1.00 60.00 120.00 + 6375 4950 5775 4950 5775 6450 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 4800 4200 6225 4200 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 3 + 0 0 1.00 60.00 120.00 + 5775 6900 5775 7425 6150 7425 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 6150 7350 7725 7350 7725 8550 6150 8550 6150 7350 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 4 + 0 0 1.00 60.00 120.00 + 6900 7500 6900 7050 9525 7050 9525 7350 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 + 12600 7350 12600 8550 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 9525 7350 12825 7350 12825 8550 9525 8550 9525 7350 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 3 + 0 0 1.00 60.00 120.00 + 6300 8400 5700 8400 5700 8925 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 1 2 + 0 0 1.00 60.00 120.00 + 0 0 1.00 60.00 120.00 + 9525 7950 12600 7950 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 5 + 0 0 1.00 60.00 120.00 + 6750 7800 8700 7800 8700 9150 12600 9150 12600 8550 +4 0 0 50 0 0 17 0.0000 4 150 435 6300 4125 start\001 +4 0 0 50 0 0 17 0.0000 4 165 390 6450 5025 link\001 +4 0 0 50 0 0 17 0.0000 4 165 885 6300 4725 blocks=1\001 +4 0 0 50 0 0 17 0.0000 4 225 1185 10275 3750 single block\001 +4 0 0 50 0 0 17 0.0000 4 225 1320 9750 4350 used memory\001 +4 0 0 50 0 0 17 0.0000 4 165 390 11700 4350 free\001 +4 0 0 50 0 0 17 0.0000 4 180 825 11700 4635 memory\001 +4 0 0 50 0 0 17 0.0000 4 30 360 5550 6675 ......\001 +4 0 0 50 0 0 17 0.0000 4 195 1575 2850 4275 small_alloc_list\001 +4 0 0 50 0 0 17 0.0000 4 225 900 9675 5850 alloc_Hp\001 +4 0 0 50 0 0 17 0.0000 4 225 1320 9450 6300 alloc_HpLim\001 +4 0 0 50 0 0 17 0.0000 4 150 435 6225 7575 start\001 +4 0 0 50 0 0 17 0.0000 4 165 390 6375 8475 link\001 +4 0 0 50 0 0 17 0.0000 4 165 885 6225 8175 blocks=1\001 +4 0 0 50 0 0 17 0.0000 4 225 1185 10200 7200 single block\001 +4 0 0 50 0 0 17 0.0000 4 225 1320 10200 7800 used memory\001 +4 0 0 50 0 0 17 0.0000 4 30 360 5475 9150 ......\001 +4 0 0 50 0 0 17 0.0000 4 165 390 6225 7860 free\001 diff --git a/docs/storage-mgt/step.eepic b/docs/storage-mgt/step.eepic new file mode 100644 index 0000000000..d5af2b7b04 --- /dev/null +++ b/docs/storage-mgt/step.eepic @@ -0,0 +1,121 @@ +\setlength{\unitlength}{0.00050000in} +% +\begingroup\makeatletter\ifx\SetFigFont\undefined% +\gdef\SetFigFont#1#2#3#4#5{% + \reset@font\fontsize{#1}{#2pt}% + \fontfamily{#3}\fontseries{#4}\fontshape{#5}% + \selectfont}% +\fi\endgroup% +{\renewcommand{\dashlinestretch}{30} +\begin{picture}(10749,10689)(0,-10) +\path(7437,4362)(10737,4362)(10737,3162) + (7437,3162)(7437,4362) +\path(7557.000,3792.000)(7437.000,3762.000)(7557.000,3732.000) +\path(7437,3762)(10587,3762) +\path(10467.000,3732.000)(10587.000,3762.000)(10467.000,3792.000) +\path(10587,4362)(10587,3162) +\put(8637,4437){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}blocks}}}}} +\put(8412,3912){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}single object}}}}} +\path(7437,2262)(10737,2262)(10737,1062) + (7437,1062)(7437,2262) +\path(7557.000,1692.000)(7437.000,1662.000)(7557.000,1632.000) +\path(7437,1662)(10587,1662) +\path(10467.000,1632.000)(10587.000,1662.000)(10467.000,1692.000) +\path(10587,2262)(10587,1062) +\put(8637,2337){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}blocks}}}}} +\put(8412,1812){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}single object}}}}} +\path(3912,2262)(5487,2262)(5487,1062) + (3912,1062)(3912,2262) +\path(4662,2112)(4662,2562)(7437,2562)(7437,2262) +\path(7407.000,2382.000)(7437.000,2262.000)(7467.000,2382.000) +\path(4812,1812)(4812,2562) +\path(5487,2262)(5937,2262)(5937,1062) + (5487,1062)(5487,2262) +\path(5937,2262)(6387,2262)(6387,1062) + (5937,1062)(5937,2262) +\path(6387,2262)(6837,2262)(6837,1062) + (6387,1062)(6387,2262) +\put(3987,2037){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}start}}}}} +\put(3987,1737){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}free}}}}} +\put(4137,1137){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}link}}}}} +\put(6087,1662){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}...}}}}} +\put(3987,1437){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}blocks=$n_2$}}}}} +\path(3912,9912)(5487,9912)(5487,8712) + (3912,8712)(3912,9912) +\path(4662,9762)(4662,10212)(7287,10212)(7287,9912) +\path(7257.000,10032.000)(7287.000,9912.000)(7317.000,10032.000) +\path(10362,9912)(10362,8712) +\path(4812,9462)(4812,10212) +\path(7287,9912)(10587,9912)(10587,8712) + (7287,8712)(7287,9912) +\path(4812,9462)(4812,10662)(10362,10662)(10362,9912) +\path(10332.000,10032.000)(10362.000,9912.000)(10392.000,10032.000) +\path(7407.000,9342.000)(7287.000,9312.000)(7407.000,9282.000) +\path(7287,9312)(10362,9312) +\path(10242.000,9282.000)(10362.000,9312.000)(10242.000,9342.000) +\put(3987,9687){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}start}}}}} +\put(3987,9387){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}free}}}}} +\put(4137,8787){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}link}}}}} +\put(3987,9087){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}blocks=1}}}}} +\put(7962,10062){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}single block}}}}} +\put(7962,9462){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}used memory}}}}} +\path(3462,7587)(3462,7062)(3837,7062) +\path(3717.000,7032.000)(3837.000,7062.000)(3717.000,7092.000) +\path(3912,7362)(5487,7362)(5487,6162) + (3912,6162)(3912,7362) +\path(4662,7212)(4662,7662)(7287,7662)(7287,7362) +\path(7257.000,7482.000)(7287.000,7362.000)(7317.000,7482.000) +\path(10362,7362)(10362,6162) +\path(4812,6912)(4812,7662) +\path(7287,7362)(10587,7362)(10587,6162) + (7287,6162)(7287,7362) +\path(4812,6912)(4812,8112)(10362,8112)(10362,7362) +\path(10332.000,7482.000)(10362.000,7362.000)(10392.000,7482.000) +\path(7407.000,6792.000)(7287.000,6762.000)(7407.000,6732.000) +\path(7287,6762)(10362,6762) +\path(10242.000,6732.000)(10362.000,6762.000)(10242.000,6792.000) +\put(3237,7812){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}......}}}}} +\put(3987,7137){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}start}}}}} +\put(3987,6837){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}free}}}}} +\put(3987,6537){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}blocks=1}}}}} +\put(7962,7512){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}single block}}}}} +\put(7962,6912){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}used memory}}}}} +\put(3987,6237){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}link=NULL}}}}} +\path(4062,8862)(3462,8862)(3462,8112) +\path(3432.000,8232.000)(3462.000,8112.000)(3492.000,8232.000) +\path(3942.000,1182.000)(4062.000,1212.000)(3942.000,1242.000) +\path(4062,1212)(3462,1212)(3462,12)(3912,12) +\path(3792.000,-18.000)(3912.000,12.000)(3792.000,42.000) +\path(3942.000,3282.000)(4062.000,3312.000)(3942.000,3342.000) +\path(4062,3312)(3462,3312)(3462,2112)(3912,2112) +\path(3792.000,2082.000)(3912.000,2112.000)(3792.000,2142.000) +\path(3912,4362)(5487,4362)(5487,3162) + (3912,3162)(3912,4362) +\path(4812,3912)(4812,4662) +\path(5487,4362)(5937,4362)(5937,3162) + (5487,3162)(5487,4362) +\path(5937,4362)(6387,4362)(6387,3162) + (5937,3162)(5937,4362) +\path(6387,4362)(6837,4362)(6837,3162) + (6387,3162)(6387,4362) +\path(4662,4212)(4662,4662)(7437,4662)(7437,4362) +\path(7407.000,4482.000)(7437.000,4362.000)(7467.000,4482.000) +\path(12,6087)(1737,6087)(1737,4887) + (12,4887)(12,6087) +\path(987,5637)(2637,5637)(2637,9612)(3912,9612) +\path(3792.000,9582.000)(3912.000,9612.000)(3792.000,9642.000) +\path(1587,5037)(2637,5037)(2637,4062)(3912,4062) +\path(3792.000,4032.000)(3912.000,4062.000)(3792.000,4092.000) +\put(4137,12){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}......}}}}} +\put(3987,4137){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}start}}}}} +\put(3987,3837){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}free}}}}} +\put(3987,3537){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}blocks=$n_1$}}}}} +\put(4137,3237){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}link}}}}} +\put(6087,3762){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}...}}}}} +\put(462,6237){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}step}}}}} +\put(87,5562){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}blocks}}}}} +\put(87,5862){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}no}}}}} +\put(87,5262){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}n\_blocks}}}}} +\put(87,4962){\makebox(0,0)[lb]{\smash{{{\SetFigFont{10}{12.0}{\rmdefault}{\mddefault}{\updefault}large\_object}}}}} +\end{picture} +} diff --git a/docs/storage-mgt/step.fig b/docs/storage-mgt/step.fig new file mode 100644 index 0000000000..af9661f2be --- /dev/null +++ b/docs/storage-mgt/step.fig @@ -0,0 +1,154 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +60.00 +Single +-2 +1200 2 +6 9825 1650 13125 3150 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 9825 1950 13125 1950 13125 3150 9825 3150 9825 1950 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 1 2 + 0 0 1.00 60.00 120.00 + 0 0 1.00 60.00 120.00 + 9825 2550 12975 2550 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 + 12975 1950 12975 3150 +4 0 0 50 0 0 17 0.0000 4 165 630 11025 1875 blocks\001 +4 0 0 50 0 0 17 0.0000 4 225 1230 10800 2400 single object\001 +-6 +6 6300 3750 13125 5250 +6 9825 3750 13125 5250 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 9825 4050 13125 4050 13125 5250 9825 5250 9825 4050 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 1 2 + 0 0 1.00 60.00 120.00 + 0 0 1.00 60.00 120.00 + 9825 4650 12975 4650 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 + 12975 4050 12975 5250 +4 0 0 50 0 0 17 0.0000 4 165 630 11025 3975 blocks\001 +4 0 0 50 0 0 17 0.0000 4 225 1230 10800 4500 single object\001 +-6 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 6300 4050 7875 4050 7875 5250 6300 5250 6300 4050 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 4 + 0 0 1.00 60.00 120.00 + 7050 4200 7050 3750 9825 3750 9825 4050 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 + 7200 4500 7200 3750 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 7875 4050 8325 4050 8325 5250 7875 5250 7875 4050 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 8325 4050 8775 4050 8775 5250 8325 5250 8325 4050 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 8775 4050 9225 4050 9225 5250 8775 5250 8775 4050 +4 0 0 50 0 0 17 0.0000 4 150 435 6375 4275 start\001 +4 0 0 50 0 0 17 0.0000 4 165 390 6375 4575 free\001 +4 0 0 50 0 0 17 0.0000 4 165 390 6525 5175 link\001 +4 0 0 50 0 0 17 0.0000 4 30 180 8475 4650 ...\001 +4 0 0 50 0 0 17 0.0000 4 195 1125 6375 4875 blocks=n_2\001 +-6 +6 5625 -4350 12975 150 +6 6300 -4350 12975 -2400 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 6300 -3600 7875 -3600 7875 -2400 6300 -2400 6300 -3600 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 4 + 0 0 1.00 60.00 120.00 + 7050 -3450 7050 -3900 9675 -3900 9675 -3600 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 + 12750 -3600 12750 -2400 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 + 7200 -3150 7200 -3900 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 9675 -3600 12975 -3600 12975 -2400 9675 -2400 9675 -3600 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 4 + 0 0 1.00 60.00 120.00 + 7200 -3150 7200 -4350 12750 -4350 12750 -3600 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 1 2 + 0 0 1.00 60.00 120.00 + 0 0 1.00 60.00 120.00 + 9675 -3000 12750 -3000 +4 0 0 50 0 0 17 0.0000 4 150 435 6375 -3375 start\001 +4 0 0 50 0 0 17 0.0000 4 165 390 6375 -3075 free\001 +4 0 0 50 0 0 17 0.0000 4 165 390 6525 -2475 link\001 +4 0 0 50 0 0 17 0.0000 4 165 885 6375 -2775 blocks=1\001 +4 0 0 50 0 0 17 0.0000 4 225 1185 10350 -3750 single block\001 +4 0 0 50 0 0 17 0.0000 4 225 1320 10350 -3150 used memory\001 +-6 +6 5625 -1800 12975 150 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 3 + 0 0 1.00 60.00 120.00 + 5850 -1275 5850 -750 6225 -750 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 6300 -1050 7875 -1050 7875 150 6300 150 6300 -1050 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 4 + 0 0 1.00 60.00 120.00 + 7050 -900 7050 -1350 9675 -1350 9675 -1050 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 + 12750 -1050 12750 150 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 + 7200 -600 7200 -1350 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 9675 -1050 12975 -1050 12975 150 9675 150 9675 -1050 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 4 + 0 0 1.00 60.00 120.00 + 7200 -600 7200 -1800 12750 -1800 12750 -1050 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 1 2 + 0 0 1.00 60.00 120.00 + 0 0 1.00 60.00 120.00 + 9675 -450 12750 -450 +4 0 0 50 0 0 17 0.0000 4 30 360 5625 -1500 ......\001 +4 0 0 50 0 0 17 0.0000 4 150 435 6375 -825 start\001 +4 0 0 50 0 0 17 0.0000 4 165 390 6375 -525 free\001 +4 0 0 50 0 0 17 0.0000 4 165 885 6375 -225 blocks=1\001 +4 0 0 50 0 0 17 0.0000 4 225 1185 10350 -1200 single block\001 +4 0 0 50 0 0 17 0.0000 4 225 1320 10350 -600 used memory\001 +4 0 0 50 0 0 17 0.0000 4 165 1185 6375 75 link=NULL\001 +-6 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 3 + 0 0 1.00 60.00 120.00 + 6450 -2550 5850 -2550 5850 -1800 +-6 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 1 4 + 0 0 1.00 60.00 120.00 + 0 0 1.00 60.00 120.00 + 6450 5100 5850 5100 5850 6300 6300 6300 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 1 4 + 0 0 1.00 60.00 120.00 + 0 0 1.00 60.00 120.00 + 6450 3000 5850 3000 5850 4200 6300 4200 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 6300 1950 7875 1950 7875 3150 6300 3150 6300 1950 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 + 7200 2400 7200 1650 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 7875 1950 8325 1950 8325 3150 7875 3150 7875 1950 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 8325 1950 8775 1950 8775 3150 8325 3150 8325 1950 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 8775 1950 9225 1950 9225 3150 8775 3150 8775 1950 +2 1 0 1 0 7 50 0 -1 0.000 0 0 7 1 0 4 + 0 0 1.00 60.00 120.00 + 7050 2100 7050 1650 9825 1650 9825 1950 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 2400 225 4125 225 4125 1425 2400 1425 2400 225 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 4 + 0 0 1.00 60.00 120.00 + 3375 675 5025 675 5025 -3300 6300 -3300 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 4 + 0 0 1.00 60.00 120.00 + 3975 1275 5025 1275 5025 2250 6300 2250 +4 0 0 50 0 0 17 0.0000 4 30 360 6525 6300 ......\001 +4 0 0 50 0 0 17 0.0000 4 150 435 6375 2175 start\001 +4 0 0 50 0 0 17 0.0000 4 165 390 6375 2475 free\001 +4 0 0 50 0 0 17 0.0000 4 195 1125 6375 2775 blocks=n_1\001 +4 0 0 50 0 0 17 0.0000 4 165 390 6525 3075 link\001 +4 0 0 50 0 0 17 0.0000 4 30 180 8475 2550 ...\001 +4 0 0 50 0 0 17 0.0000 4 210 390 2850 75 step\001 +4 0 0 50 0 0 17 0.0000 4 165 630 2475 750 blocks\001 +4 0 0 50 0 0 17 0.0000 4 120 240 2475 450 no\001 +4 0 0 50 0 0 17 0.0000 4 195 870 2475 1050 n_blocks\001 +4 0 0 50 0 0 17 0.0000 4 225 1200 2475 1350 large_object\001 |