diff options
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 |