www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Is Phobos's Garbage Collector utterly broken? (Phobos vs Tango)

reply "Vladimir Panteleev" <thecybershadow gmail.com> writes:
------------WRzekDfFGhbkjmHaRBKD2z
Content-Type: text/plain; charset=koi8-r
Content-Transfer-Encoding: 7bit

Attached is a simple program which creates 326*100000 objects, and periodically
prints out progress. I initially wrote it to try to find a memory leak in
Tango's GC (which was actually fixed at some point).

The results of this program are quite interesting.
The Tango version runs in 65-75 seconds on my machine, and never seems to take
more than 3MB of RAM.
The Phobos version, however, runs much more poorly - it starts to consume
hundreds of MB of RAM immediately, and the fastest run from my tests was 265
seconds. It also behaves quite randomly (memory usage patterns differ each run).
Here's a description of one of the not-so-great runs: it starts off with almost
instantly allocating 80 MB of memory, and after a while allocates about 30
more. It runs fine for a while, doing a 1000 in 2-3 seconds - until around
60000 it spontaneously starts eating a lot of memory. It goes on like this
until it eats ~340 MB of RAM in all, where it plateaus. At that point, the
program slows down to a crawl, doing a 1000 in a few minutes. I've attached a
screenshot of the RAM history of this run - I had to stop the program to keep
the run's history within view (don't think much would have changed had I left
it running, and it could have taken half an hour or more).

What could be the problem of this seemingly random behavior? Is the GC not
releasing the memory to the OS on purpose, by estimating that the OS doesn't
need it? Or is it a GC bug - if it is, are the warnings Valgrind outputs about
Phobos's GC referencing and using undefined memory somehow related to this?

-- 
Best regards,
  Vladimir                          mailto:thecybershadow gmail.com
------------WRzekDfFGhbkjmHaRBKD2z
Content-Disposition: attachment; filename=gcTest.d
Content-Type: text/x-dsrc; name=gcTest.d
Content-Transfer-Encoding: Quoted-Printable

version(Tango)
	import tango.io.Stdout;
else
	import std.stdio;

int n;

class C
{
	C[] children;
	char[1024] data;

	this(int level)
	{
		n++;
		for(int i=3D0;i<level;i++)
			children ~=3D new C(level-1);
		data[1023] =3D 5;  // "use up"
	}

	~this()
	{
		n--;
		//Stdout("C[")(children.length)("].dtor").newline;
	}
}

const progressInterval =3D 1000;

void main()
{
	version(Tango)
		Stdout("This is the Tango version").newline;
	else
		writefln("This is the Phobos version");

	for(int i=3D0;i<100000;i++)
	{
		if (i % progressInterval =3D=3D 0)
		{
			version(Tango)
				Stdout(i, n)("\r").flush;
			else
			{
				writef(i, ", ", n, "\r");
				fflush(stdout);
			}
		}
		new C(5);
	}
}
------------WRzekDfFGhbkjmHaRBKD2z
Content-Disposition: attachment; filename=phobos-ram-usage.png
Content-Type: image/png; name=phobos-ram-usage.png
Content-Transfer-Encoding: Base64

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
cwv186ykfh752t/+/tcKYctf4k2ckaYmj+4Bdg9wZu7iHuDgpbkHOApemnuAw6uu
e+4BXkg2i5IMtPzru2RpSd77gY9/6o9+962LqfKhKxPgjC+ztJQ6ZQj0H/zWG0u3
40N/cVP1boSlDmdDoA2BzlqaIdBRs+UzBDolzBDo8LSzC4dAH/+y7e/afPjSr9Pj
/+O6R3LHv+w17zqpOHPm/j+8+9Hkiyu3kEA+ez6ljI575QcHX1j86fuf+8xX742e
N/Tas3/1uYXfH//GxL6jtxYSzmNe8R/eeszNN/3jvUtLP+4VV79qffGn2Ztv+mp0
5gU7NkbT/3Dbx3580vt//YQjf/rwtbdPfee4l1/9ysWYz/7jfce9/KpXrp/+yt/8
l0dmb50sftH+7OdPRNFRzz/qzOcmG/CDrz966CG/kMx54UuPP/LWr/8k+oWB1xz9
8yd+dtgRhx+Se/azn5UspnTOoYce8qxDknm/9Pyj1v3skEKhDnnWuuU/2VBMgHPP
elaylp///PFkLUcc+ax1A8vbc9NX710uQnHLH4miXyxsfPTTnx/53MOKNTbxh3+3
v/DDi1/xwVeVVNHyrz97/KeHH1mon1f+2W+96HPj0esHXzg9/tfXPRLlSmv1L/+h
UKsXbFuo1X1f/NOv/aSJVNEQ6LRTR0Ogq5bCEOjwtNMQ6KiRMhkCXWNuu4dA/8Fv
vaE02UymxXyz+HVYnsYW3vnBT37mD9/2puSHpez3gzd8pizhLb/y/Wd/ecv8aUja
FfHyk5Lfv+jCsjlJPnzNZ/5Hlff9wVuXy/Afb/prCbAEWAIsAZYAS4CrJ8D5F52W
ZL9PTN9z5dd/Onj6b+zYULiY+qyXnJZkv088lMz8WbRwcXddMVl81kKf6rGnfuDl
L3joH++4/nsb3vG6X3n92cd9/6e//KvP/fm9X7jn1vnO1G/80/rX/cqJ3/+n940f
iBa7YaMXvezK017w0P1/+/HvbfjdC0/ecdZx7/v7r//KhScPvPSlO352/JHRD//q
C9/e/8uvvPq0X3ro/js/vv+Fv/ubJ+/41WO/MnNIMSdd7HPO5Y598YYjov913/f/
v9ln/a8oesGv/PKhX4med0Qh0f3FdYeu+83TT4i++fdfPvzVrzs8V9zaw8vnfP+f
/tM3Tx/edOZVSY7+/a+/f+p/l3wpF/P8Q4pf30c8L8lRH/r5/15XTJifeGh87z//
NDoh2bwXzP987EvPuORV23b8r3v/R1SomyNyP/joLQ/lt5x56YlbLz7hB9dHW8uq
6B8enV/OfR9IsvRowzuGTjnxwIN/lNTPsae+PinWs5NqP/Wql79g+h9v/y/f3fB7
Q6e8/tdefOCnJyS1es/Y3fO1mtGdLgGWAEuAJcASYAlwIwlwpaUvmopvnIV3/tmN
t/z+Ra9bym0rv5jWPXXwYFjqmDJ3Pv9e6gReTMer5Ykf+tRnq518S4AlwBJgCbAE
WAK80vGHPyeKfvbP33r8qYPRPY98f8eGF0ZPHxw8+gVJaviF+594anm9Tz1T+O57
+pmDB5OZLz4seVd04svP+8DLixGH/csXFsYeH3bGa87b9I0v//sHkwTv6UL4M08X
vgcXG+aLn1PoID3xtF+/8rSFdx1z8Bv/+R9+6epXHX/G4dH0V75yz8HFJZ927lLM
0d/6yuXfKtniX9x00UueE8187ebHDkaPPXDPC88889Rzrii+8sSPf3T0wNbT8w9f
+7UnNp5e+LZOtvbok08um/PULwwsLCF62Y6NJ/+bDd/9L48sLf2pwma/8OQrf/Pk
5P/pr/xNoYP3uGeSnx+bK1RRsQg/3/edws/f+s73Hz/xhE0v/BdPfa9QN4/v3/+t
gwfz3znw+IkvOeKwf3FMdFhZFR3z9NJy8gsryj9VqJ8nC/PzTx489hcLZR94+flX
zb/l8H+54UdJ1OFnnvMbJ2V2/0qAJcASYAmwBFgC3HgCvNTlO594vvtNC12wFWns
wjvne4Dn/f6bX/fBGz5TkQA/eTD0vKxWDvfUwScz0ojlH5+ej4ncA+weYPcAN5Fp
uQe42nrdA9zY9bfuvQd4Pq/NP/Xk009Gv1wcwZt/+sl8ISN7Jn/w4NPLDaCYsEXP
PPPkk0kCvOHwwwuPwrrtbz87t7SOB+9+eMufXLDpyJPO/uDhX/2/vlSMf+app558
cmldLzz8sMK7Pn/n554ouQf46YXv1CMP+5dPH/zxhkLMz/4uiZlLPSwdc/G5Jxzx
04eu+dJ3itv22Of++tbPJVHPf+kf/8aJj889uXXLYdHhJ1z2+hOKwS/Ycd6p01HZ
nJe84CcnHJGs4sHv3D331JadL9900okv+uY/L97nW9ya+XuAVybFSbUkVfTMM/PF
erKQxD5V3IRnnnxq6YeksE89U/z5qQ3Pmy/s337u8aWLDafPJ7pPPZkUfPECwZNP
5p6eX/7BhVr9n3d8dm5p3Umtnvwn/8emIzdv+9Bzv/LuLzziHuCQpbkHODztdA9w
eNW5Bzg87XQPcHjVteMe4MvfvrNyKVf9t/+ees3kqYNPloYt3gmcvtLdiyOfl+4B
/sPfftMHPv4XKxPg9B7gsFO/ld/6Zbl06nNdM/Lt8pTKU6DrXK+nQGd+GlXX6ynQ
2ev1FOiwNhR5CnT7nwL90GM/TrLKlx73nKdmo9OOeW4xGT74hW89+oZjjn7N1ud8
Yfm5xAej+Yyt2AM8H/DSYw976gdzhxz5sjc9/2s3fjOKfvBA/N/mLv03gyc977Bj
D/64EF744eC3TzzrP/7qxm/83Y0f+c7MG47Z+NIXHXbj7Fyu8K4HP/PN4y49/YXR
T2a+EW086aWbzvjK333x2zOvP3rj5hc956kf/Cg64pQ3Pf+fPhOdWXz7TR95+LhL
d71800++8aFbCs9tLi3NWSefeGQ0c9f0Y3dPf3b+WvRZ29/wxmNmbvqrpadAL82Z
2P/yF/7q0YViJll/YSN/PPfQ8pf10wsds6Xfp8We2yRBfepg9NATP4mipAjPSYrw
yy/acGSSrz78w6ejDYUE/rnPeergD3/5mOLMb/7wS88vFvaYw278/nxhv/aZZ4rL
eaawnIUVPe/w4w4efHhx+Qu1etx82be++fkTf5nU6uz9//bjT7zrd08/6bnF4KCz
I0+B9hTo0KV5CrSnQDd+3ctToDuw3tY9BXrhe63iKdBl+WNZWKr5p0An0/mnQJcl
vP4OsCHQzWbo6WlMWFitTMIQ6MbKZwh0w5cRDIGuY/NTl9amh2C95l/tevNxhR8e
//FPjvyF6Euf/atPP5Z7yeDrLt/6vMLcR/7u4s9/K4qe/5ad//rs6OtX//f7v1l8
VxLw3vmAKPrGFz75P4+48L0vm//1J1/+3K2ffiwJmJ+z/8YvRhdtO+YbX/yLP5uO
XvLq3/zDly2+64t/84NT/9XZv5D88BfXRNs+uu2Y6Mf//MHPPBC9+l//4SmLMV/6
1DXRr330145Jfrjt+cvzC1v74N/8ycMv/ndDLy08TSpZy/Vf/lJJoX7tvLdcdOyK
mSVzfvHNbyyst6C4xpKs8vh3/94ZJ3333uHblx/9nBsobkBx+4u/Fjd1oQiFmbmj
Tv13O7YcubRhX/ufe8bnilW0VCeFKvoP0Wuue80xhR+m8iUVuP/GL0QXFebf8OGp
aLnak7fc9Ym/PmJo8defFD6XH2aeIBsCHQUvzRDoKLgUhkBHwUszBDpqpEyGQLfm
mlzDQ6D/5F2/V/b6v/uPH8tYb+gdxbkXvPX3o0CB1/0Dx8eFhQVnrLnQMjTUU5qZ
2QcvLdfoSqPgbpTUlC6w/7jWeuvu7A3MwFZhva1ISOsJD0yr6+ueDa3C8KEUdfa7
hvf7VttX6+/sDezkbjRFa2i9gYlm4EqrLbu+/t7A5LqZTaj/EkGjoxRKZpz7r39v
5/MfvPKGv38o9EaFXNiMBq/JBl7gDDuq1HHukg8LW/ZLr7jyolOiB2553z2Ph50z
BJ6q1NHvmm90pVHwaMhqJ9+1wmqtt+7O3nwDK60/mW34l2aSyvast5HChtd4RmbT
SE9p9ouhS8s3utKoyt+HaU0y2IJcto7ogFK0c70tuGBQ30dSR2dqHd2zAS2mZXdW
pLbffFhYRlSDK83YLQP/+F/WEOiG7gHOPoWp+8TCPcB1rtc9wO4Brnn5yD3AjR3e
3ANcHtb5e4DzG8740G+detT8L3MTV1x/71Q9K61rh65sUnX+HeBGjl6pX96Bwzqr
no8th+WeXLgzuOxOqsosIHBYZ7XczT3AzVw5cA9wtYZc30oj9wBH7gHOXJp7gMOr
rnv+DnB41VVvjrnnXfi7jZ9I5lpwV19qSuUe4DrX6x7g2pdhIvcA17Ve9wCHtaHI
PcDtvwe4nvUGdu+GFjb82lojR6DqJ9/VvrubOOMOvK+xoaFl4Wez7gF2D3AUvDT3
ALsHuPHrXu4B7sB6W3cPcNl+G34zQb2XstY9/eSTUSBDoOvPTpfCDIEOz8QMgQ6v
OkOgwzMxQ6DDq66bh0BnzTUEOvzKuiHQ4WmnIdDhVWcItCHQdUcbAt1EqmsIdDND
oHPR7msjAAAAWOtyYxOTagEAAIA17xBVAAAAgAQYAAAAJMAAAAAgAQYAAICusk4V
rIpNGzaqhAZMHZhRCQAAQGP0AMt+e8n4vmmVAAAANCa0B7jzOVtpX9/ayxj1ZDaT
A+/avq07P8puaKjdueOsyd25GwrlSAIAUJegHuBVObdb6utbq/2lD9779+ds3WIa
Pu3ahLyrGmp37jhrcnfuhkIZEwEAUJfc2MRkSPbb+X6G+RO7+b6+tdTLsVSfSUZX
s/IpvV5wyhmvnm8Vg5sHui0L6p6G2p07zprcnbuhUF24RwAAdDP3AK+aD3/0v674
/Yl7Prp79+WL/26p1a/z0M1BYZ0zffPSxl9+7T1P1Pv2pPhV3/WeS35HmwEAACTA
PSklozv2wvfv3XtV8u99F87cUT2HnJ4cH3zn3r2v65KOnyT7vT565/zGJ//Om72i
gRy4rusFAAAAnUiAa3XWtVev95SGZHRH/NLG784+Xq0Sfjhz7Poju6Uoj993x8yO
9+04cWnGwI6rLjvziHZfLyj5fFf8u/balrXPJpp6yobdPF1c5LXlrbdGk378vmtv
fmhpS+ps/1n7TrfsESuL0527apPlusVdugAAvZ0Ar7re7SkNyOhW5LfLp9HX3vfE
fD528y3X7r78ylu//d1br9h980MrYhZ/nY8ppIILP3z0nun7Fn54vCw3K5ydF5Or
+24uO1+fviUzTytuzPLWfuOB6NRNR6Rmj/MbcPMtKWtc3Mj5zS6aujkzZ8i6XnDi
jvlu53ecGQ0udEG/5dRu+HxTNmzHQJL9XvHAqQutd+87ousXS1qlSU9/6YFTf+3E
Btv/igXdcuUDp75v8Y3XL1d7U1cHmr8ctlSc4r+gXbXD1+DqXl1FVVcuYXUvIwIA
SIB7Uo/1lNbK6Ao5bTEDTM6e33LmEdHj93166TT61Ac+XTxd/u7M+rcUzqqPL6QN
O04sxNy68R2FmPdfOPOxYh/jcsziD9Gtd0TzPzzwjSeWc7OSDOq7t86eXDrn8fuu
vT56x1KelmS8aRuTcuZ/84rbgOc3YO+O16Wscf6l0s0u24bg6wU94/GpB6Idb1nq
Gx94XWW+V96kH7/vjujXzzyywfZfvi8sXqc44sxL9u44sdm978xLWt3P3wOrblVV
d3kRAAAkwBUnecudeDU6GKOVAx3LR3Ku7E6s+0Szd3pKa2Z0y11hl51+RLFn9bvf
vfnK+ZQ4KcgDU48lMSv7Wgu9rxeeXUyijth86vEzPyyscCmm8odo5RYmi11c9dkD
6Yst5mmXnR5VbExq0QZ2zGewx0cr15uyxoWXCps9/vWHKreh5vWCqlZ0Jpf0RT9U
8elUa66LW7s0bnm+YTTaXDO6yqtcsqns/m34+s4RJ50a3fqXZduf0lZXtufSjsrl
Lt+SHefTxV1sfr+4eWGXSKq08Yqq3MsKG7m4efM/T5dtSenHurR3VywkYzdPO3qU
vrdwjWm+jE80WNUlS1hRewv95+WHlIqjZWuaHwAAzfYAh3YwLvdSLqZGYd2Jmevt
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
qWlXVk6aTAc3D1SJWbfKBY2b7sKNu7ITOA4odSRGjBgxYsSIESNGjBgxYqJouEMJ
qCHQAAAA9AVPgQYAAEAC3OXZb6uWAAAAgAS4EwlwbAg0AAAAaz4BjgyBBgAAoB8S
4OYzWDkwAAAAvZEAx4ZAAwAAsOYT4MgQaAAAADph3SqvP9/Ee3NNvx0AAIC+cYgq
AAAAoB/kxiYms17btGFjMp06MBOyoPF907u2bysNTuYk0z07h3qxXvbPzpWVPbWA
ZXOWSz01pG0BAAAE5V/Dc1m5Z2ralZWTJtPBzQNVYgyBbo+41qtxwBLEiBEjRowY
MWI6EJOvel6kfsTUG1Paorp/myvbv890VWKGO5SAGgJN78t32XL6uQ7J2546t2FE
o+nIZzfSopjVKm++nuXku/uYNtJnR+N8G9pqJ/eLfjie59u89pGqe2W+jz/T7t/m
fEs/qa45vq12D3BuVd+Oc0QZoOy3Hz5fh0p7ZWBLWButJdezh7X8aq/dsYKWt6hk
Oro4yqB6zGrtQfk+3uv79ThzyOrXQsP/mn87a/VsoLGrjNXPmZrpxcp3sGYaW1f4
+WLz14nzbaurfMc/hZEua/nNJwPhdTjSogWOZp8VtfwTb6YXtJPfGlnnB/k6jwD5
+ltCy1PHfD1Fzmd8FuEtpIFTq3wT7Sdf/3JS23y+6kfQ/Wcs+To/2XrrJ2stTY4u
qbKu1h6l292/Wu825Fu0efX2DVZpCbnsXuJ6z3aa+U5Ze/lwvblPPnv/rTw+py65
898yPZkAQ/Onic3vSzXPmZrPrPLdXYcd+75va/ab69QIq8bOxlbxw80Ft9LqdVj6
RRh+4tjAHrpaI/3yPfiptXAPGu1sbdf13lx7zrHy9ezdoxXbULpH5Bo9Jiy9N/Vo
nO/I+WIzX6b5jrSQ7jy65jtexjb1cDZ5dSxftUXlws5ARpu+elVlXV2blc1v82ir
RxqXFS3XojO9XMXVurIl5wMK2x1WOwHONfGv+bfTK1luS76Wwi9Ppl7TylXtcBit
dUk1l321LHWZ1SMbSPYaO/qXbXMu4GOqeSKV9dJIKy5n5DJ6aXJVP8GQz6JyTq51
X6IjVT/fluRsNfOH0rxrpNZychnLbGyUTS4trwg818mH1eFSAlPzAxqtpyuvk1dJ
QtKtKONqfcPJbWNlHAnYp0YCWsJoPadiIduZT2tpNWuy8qpEvmJOLuM4H35My1U9
jqXua+2+bzDf0C6cegTI1cqRQrYhl30BIgq4YNHC2qhsDyNVvymyjuf5gO+verO7
mt+8bRrikWvoLCtwv87XubRcPXt6+y64NHY5Kde6ayuNJZy54NETDR+Nu6AT2FOg
6YL8NtfZN1ZfTi6tiTZzVXJp+aMrn3RXfftzDe0j9Sb/IXWYy85/qi+/MrJ9F/+q
nxnkwj6pKu/NZ9TJaPuvaHamx7KsFKNVP7uWt9sorP104GQlF/DIytbWfAsPa4G7
c82wspjG9qB81a/pkAtkS59F6gEn11AN1DUUIvzkoWzfiQPaWK7kcJ3LWE7Zt0/l
W9rRCHN19jlnHSjyTVdyvuKHduxrcdhOkc/4yJY2LF7ZXOu9i6H0PKGxg0C+1mX6
yuodbe7YsrTGkSb2l2bOanItahipbbgz6VnzB/y6ltDwvda5eh4h0SM3mRoCTXfk
wFX2pVza5b2RTl3CyDV68pRr7pbjus4UK+ePBASPZHwptvCCVF1nUaMB7wrp8RhN
67dpYCNHKk49o84O4Mllt6WsvoXw+3Jz2bVUuvaa3blZNRNyYlTlpCr8WJHLHoXR
fLPMOhaNVO3VqbnNpZ9XS55JMVJ/ntlAqbPO3bMqufo2VN9PA8+Vc3W2+awW23DP
W1svb+VqnYaOtjkHztXZCTySdgBJbQmBlzByYW2ggSeE5zNeiqp+FzRw/aiBDc7V
OZqmbLBxZW98vTlYvV15bWqBrVpIC3tBU89FqzehfNUrIA20k3zV1jLS3MGn7EJM
vdl11pZ35X2CngJNF8itHEVT5YPOelpg5aXZ+Z/jWt9MIYn0aPYSUr/dm2yWNY84
Iw1dQG1sS0KuFI4EHMRH0+qq5rtyzRWwSl43Wqtm2nE/ZGApava1Vilv9d6D1H2n
enyHDwI1s+V8xq5XpYpyLX368VJvT/glvOqDNnMB1xfijIpaeu9odkxrv6lL21g+
u/JH62+9Vdpe9e7f0eyekLrqYbShHpV6v+Nyde5fuVXaK3PtfGPgJ5XLPrfONXRg
CTnWpWaDo01/alVOHvK1PuV8rWNC4J7ScNpZczmjbTvytPyY1tgxIauW8mnHjbIf
Uo//uVpLDskVcwGtpR3HhOq9MtW/B3NV983O3iFsCDSr3QBKL/Hm29nAci1qe7nW
5Qy5pkctZr00WuskIyvBy9X/WKzRsJwzV+sgHriuyiF2ufo/o3xaZ0XZqUncwb1g
tLnb+Ro7GLb7+yZXcXtYrkV7X8OHmjjsclWunjwt32hlliaKIcMmq7TnuLnmlwtu
81l3gDfWllp121j7To5bu4/04llH6UWWmqnRaK3PK9fcY4qqJACp3wtN7hctWU47
Tl9rZqe5OudX2baRVWq3VW62au3HEX4tPp8xECDkfCPOfntU9bpPvbcYjIZd8ck3
3UpbtV+U7svza/xBnyTA9FWW28JjYhz2ZRxX3dtb/sWWa6Ls+fZ0HXd+yG7WQTmr
rkKeJtVAuWpesY5b/UHk6x/u29q1VLm3cLXOyEebq4qa/UKBVVRljG6+FVWRa3Md
xtnX8hq4Epd6UtXYvtySnLMlb2nVlce2Xg/qWJ5Qr5B7OPMNfV3mwo4JUf0jLfPZ
l6KijEEW9V7SauvxMNfmj3g0bLEjGWPO801fHGz52ePS6JsmP6BcizoASs9Fa141
y9c/+iPrck/UiuJ37Kg1UvWPGlSOqErmzPZJArxWh0DHTQesjZiRxQNx6eEmrvqW
eOXMODt1idMO91kLH01bZtxouUpLVH1TR1bOT43JZ2xY6jaMpCVvqW8cLfnr86lb
nrWikJjSjYlqlbFm+8lnfHyji2uJ02osbmlbrfmZptZnav2PVny/xsGHhZGMVZR2
EcdVU/q4VhWN1HpOT711WKVmoooHv1XfT/PBzTvKbroNHDdS23DIkSrr2FIaVrlD
VTa2mnVY8yML2R3i7F14JK3UIZ9p4HEjbugDjarubiFlH80YJR6+nNGw49vqfufG
q7c98SqVfbTqOUDZ/l75XVz9u6DD5YoD9ovUmOoH8zis3uL6v4/i7B9GA47zgfVT
16fWzHdT9YNVaolGM46ZqZ/XaPAJwGjAWVD492CVtjG68hu53i/c0YAjT1z1u7KB
fWetJcBrdQh0zT0zZE9YAzEjFRftynaAyvyw9GhV/djX2DaPrByL0sxySi+dxtnJ
RlwrJl65O+QyYvIlT2VIrcPKdVXZpJGqDbV6TLxyU+OAI2Zc9aV81Q2uLHv1/oqG
P9N45WXa1PZc+U2ZK9m8OPtzH8ne7JGVJxxVPpSao9Hikq+lfHYZW76/j2R/dmVt
o/LSePVtHqn4XKpvT6vaxkitI1XN9lP6c2UpRirafEgdNlCu1H258qARN/SZZjXR
OKP28gHHzOrriuuvn9R2Fbe6nlcxZqTWaWjN5YyEnYCO1HqqfzfXYdytn2kcsF+M
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
ck/HjBST2JK/3FwWM/9S4cuy5MssV/oluvLVlm/zwrb1w2dRWeou3uaUNtNQTGfa
RtaWzJ+ZLbXnsm0uveadq9iezNJ15LOoLHurtqf55VQuoaxWc1HbP/fOHzeqlzFr
e/JlDayd25x1nK/x6bS0/TR2TCg/HkY1vneWvpu6pI0tR0bLX6zVP/d8ahlbtZ9m
5Tkly2y+DsM/r7qOLeX1ll0/6ZEd/86tt81XP36u1jnAik8w4DjfW+ctjX1fhO+D
zR9XmzyO1dyXa9RM6rqGO5SoGQJNuyx80do2pW7pFra7FOHLz8+fzGUsIZexzKVX
c4sz813zGVWuvVXb0/xyqm9b1mfRW22vehsL/3TyKxvYquyzlW2+fZ9OY8sve1f1
M7mgVKGzbWy+bSxnEa343Bv+pJbqp/Lt+ZWb17KGF7dsaeH1Vm8Nt++IUe+S048e
8WqeD6S2h/Z9B63uMbBdZyCrUTPhO3L1c6RV/0xzYxOTWa9t2rAxmU4dmAlZ0Pi+
6V3bt5UGJ3OS6Z6dQ72YKuyfnSsre2oBy+YslfqPe7PULW5bJW095NXUvoL8amxb
f34ivbKF3dM2lq7s5jOWkNqeq/QYr/pnlGvb9jS/nNpHjLTPorfaXvU2Fv7p5DJa
Vyf3l9Yez+v9NmlHa++2NlZzpEa+UzUZeDxsyX7ajv0xfH+pd89q3xGj3iWnt/bW
fRbt+8bp3fOWVh2Xuu2MrqznNt/cMaHSoxX5V/W0KysnTaaDmwdWLQFO5vR0wtBY
AtzrpQYAAFjd/KtNCXAbh0D3Zx4o+wUAAOhObXwIVmDX8RrTn6UGAADofh6CBQAA
gAQYAAAAJMAAAAAgAQYAAIDu0sqHYH3iri/2W/X1YZEBAAD6PQHuwz//4y8eAQAA
9GMC3Id//sdfPAIAAOgh7gEGAABAAgwAAABrxbpOrGT2tvj83Xcv/vb2Gybfdkpn
1nXents/vH39atTrGihystirosuuvuCo1F8BAAB6Tad6gM/de+PE5Fjy7/a9D99w
22OlWdZ7S36tno8FRkaXXrOwrnO/fFXFW+pYjiKHbVLHqhQAAKAJ6zq9wvVHn3Dn
vbNRtNCRuP6C+OpOrWu1rKUit3XjAQAAeiIBHt83XTlzcPNA+azZRx8+97jXFsbT
PnJC9JE/v7PYU3p5dO35d549P3a3MKC38PP6v9ry7usW3vT2G+46+obdd98Z3f3e
6MarLzhqedBv1RG/xXUdfd2Wd0efGrt4azJj8rqFZWYt57HPv+ei99+R/H7WFXfF
r11fVrRd27eVPvl5DRc50+JA6Gj5XZ86eyx1Oy+9ZuKSLaWlvnh5k246bmFdqXUI
AACwpCwR64oEOEr7u7jLW3nn7ou27o4W866jotuiOx86+vbJscsLCVW0/oI3Xrz7
pvtnt792/WP333n3xbviJDm6eHLs4qWk66uvvXzvWdH8Paizd12VpIuT8XzqeNVt
p5TfmPqRd2/9yNK6tkfRl8+/d/LirVuiifuvu/Sa24+76aqs5Rz9+fefeM3Ehwtp
2/mfm3ztJVtKyvWJu77YP0WuKELRuXsvW/hpouRd966/vXQ7d59ww2R8SjGvvm5i
bChaLnXJJr1xYn1WBQIAACxJTcS6IgGOqvxp3HP33lias80mc849ZX3xh6ItQ3tv
uuqrj732FQ+ORXsu37qQBC4922k59Urmf/XLd95x951b/nTh9/POnr1gZY9ose+x
mKd9cutHJycueePFW+5/MJlz759ffMbbokdvylzO+44+t5BJFvpCJy6oXai1W+SU
IhT7fhdtWPGu2duWlx/tvaz4uK+jTjv3rLFHCzcGz5c6umDlJgXVLQAAQPcmwI1b
/4qzoysffDD6cnTuZeuLidz5pX2VZdFL+V51SZ720OxstP2MS99978Rp0UN7hi6J
okerLefqye3FMbrnbA1cRX8Wef320nfdflzIe7as2CQAAIBO656/A7z+lHOiP/3t
3dE5r1jsNT1x/Xwn5+wjd5fljed+5P4H51+6Ld760cmsRRY6PIsLOeWMt1/31nd/
c74rMns5hel77pqNtlx8155iGqnIGWvJeFchpd/9+eLyC+O6X3L0inHaqZsEAADQ
Keu6Z1MKg2aj6OzT5tOjra+94hMXbV3sjzx3b/H5xm+9aOsj10xcsv3qT31y65Zz
Ci8Ubnmt6LRcuiG28Ad4i69uPe3i6OHjinlmleWsj9ZfcedF5xdGCBcG965X5KzM
/YLLSt91yoFHl5Z/+d74/OLyC8Ont0azpZ3PJZsEAADQcbmxiczexE0bNkbBd2mO
75tu4bO5Wm3ik1vvPa25Ic2VBVzzRe6DTQIAALpaeNo1/ydmUv4uT4lD1n6FPfjR
c7a+9eErXt9HeVcXFrkPPwUAAKDLrFv7RTzlkrGJPnvqUhcWuQ8/BQAAoMscogoA
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
ZpOODfUPxNvy0mKagabn5ifGRmvD8Z54OzlezOJ5WViu1M294QTr9mzNulzM+Rtr
5WAoHPLnCwAASNG/SpWk7tmwdiV10ng7Mjy4TabPuW6LaKejUYoRMp05mJDPw9xl
ZGRkZGRkZGRkZE4qU+pQUbMEGgAAgFxwBbgtVlZ2ShxMMUqvZgAAAHZDe78HON6T
6bNzat8DnPVZAwAA7G7/2r52JXXSsNP3ALdxCXQ+e6D2CwAA0J3auAQ65aXjHpPP
WQMAAHQ/N8ECAABAAQYAAAAFGAAAADKkld8DfMcDD+bt9OVwygAAAHkvwDm8+7Eb
PgMAAOSxAOfw7sdu+AwAAJAhvgcYAAAABRgAAAAU4JOw/KXoD7/01PG7HvjD22fj
/37j9osP7F/99XsPLDd64PrRhEDX6rYp1z2fBk8PAABAAW6Hb/z5ly/+tf1xFfxQ
+NTM7FT8695Lvvzehn3v2q3ATSd0tgwVuS6ccsOhdGMAAEABbp3lBz4XrnhfeOBz
j0/ee83+tX173x997pw/+ouZxAftPfPt9z+xnNXz3JVTjp/Aze8/3R8CAAAgH1p2
F+jpufkTd44MDzaIrl4LjZa/9oX7z7ni5to+dvZFn35k9uoD+xtXyKPfuuTsMz+9
/yPhT6euPhDvmI0//nT1yEN/GP4sLnLLX4ree/1D1R3vmbz3lrG94am/+r0Pfvy+
+POLbngget/ebZ5nShNjo7V3fs7KlJNb+Zeim8J1N78/bD3qT989df1D9584/rWf
mrlmfzX/xNvDbX9yfwhXbz2lL5y9/ns1c24BAADSFLGuKMCh0c/FbfQsV6+F3rw3
LIdwydnHVbS9Z749PHFC/raPHLgtbHa8EL783rXGOPP1T1/7qXvP/sJqhTs9Hvam
+99972y0d63Xfem8m8/8q4+f86mZW6q17b1/Pvu+9euup/zDe+944MGMTnnd/dd/
8MD1W59ecuN16x/N1Dzqkb333nhR2Bz/+rd/bjY6b7VXf3pmqhgP8viZ985OfbSa
3HxKV8zsDc2dWwAAgPRFrCsKcEjzo3HXroWuV7Lq+t6tJbjLR78VwgX1D1i99rja
0z5/4PbZmWuuuHr/178R73nkT66+8DfC0S+sP/ZrX77/vofu3/9H6496z7uXP3bm
JdUmWb0WOvP+k3iGPTflzcb7Z5sLnlev/W7oP+5Ry1/aGj/ceN151Q9Pv+CSi6aO
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
nBRa938QnTgnOz6s0M7Bm341C619Ci15WQptG7mVL+WpDF5oU/Zlrxw8UDgpe/YU
2mVPoX1jt3HwzD7tjU2mBt9T99+MDL6n4YfdPXKnnnaWBt+z446uHLxXnnY2Bt9z
Uru7ZvDeetrdPvieUz64q4PvafJ4zz3tPS2JdHzwPS1MdXDwnn7aXTf4njZl2zz4
yaRf+69+K+7BbzpnMISVzf/FH6+sbhvu2f7o5p6NfVuHG+45md80cZDNPWl/07j6
v+IV8fbFn/xk7dJpYe0C6sYHa//d/KCwemjzg/Xw2kc1HxTWLh1vfLC2N9SMWvNp
/WN3HmTtk7XLghsfPPXtf/jpj36U6Sk88+QTP/nBDzI9hcrCkR9///uZnsKzi0d/
9L3vpZ1CzZNpPLXtntV2TzLh2dZP+bi518zie99Z+sGzz2b6hXjuu999/pmnMz2F
7z/91PePHcv0FJ6vPPPc8vLGuprC5uqamm3dJ5v/qzuwXazuK17NF6u13fWfN47V
5zb+E8Lr+/t361p02iVVHb8W3bJrlO2/7lpo5+DNjFzo4EXdFr2au3zdtdDOwVuw
NKlTF3Wbfk3ackX3ZAcvtGnkpq+7tvrVLLTzz267LuqeVLrwuks/rABffcHb6t7a
Jy4V+czfLHZtAf65//jvCy972Ykv7ovPPXfiG+PpL37xh4s/VIBbXoAz/SqsFeC0
U1h9aHUKR3/QhQU40y/EWgHO9BTWCnCmp1AtwN/5zvG997gqW/vh8b23vuRuEzvx
C119lT3uf8mxxn04vH5gYP0cL79t8FfOfemnKy+9tPLST0N1+2L8cVh5sfrBiy+u
rLwUqp++VP0i+3O/8Lqvff0v1h74lnd+5cxX9F/w5gvOeNUZhcLKnrCn+qCXXvjB
T3/w3I+ff/aHlWM/Onbs+acXf7J89K8XX/WmKztcgP9P9Lvx9rbbbvvlX/7lX/ql
X/rqV7/6la985dprr03a+auHPtWSYvTDr9z/7N/Pr338hn86+DO/cknS45fuuv2k
ZtQ/fu3qo247qUcNXHltS5rkW1++8o6BvW9/896ffd1rXnjhp0e/e+zvF7/zxLP/
eDS8MqkAv+7Hz71QeeqVx46d8fz3z3jhhXjPsZe//NirX/PjM854+Wmnf++Vr93x
ye//7vzsmwbTP+1/978+/6o3vfHV/QOvfuPpL3vNa65/6Q07zuy/XfarR44cnZuL
Z7Pw0soLbzztdUOD5wye847f/eJDdY88+vmtd8g1Z//sRT/oGz92bPODu844I97e
PrT3Z595aXz13/jO/I3f3cz/59//rR0nO3nLHycdWr5r+Pgd39s7vnhi7Et/8Fj1
9/pnb3642N982XvNs99d+elPzj3jDUePHTt6+ttOTA2+4Ymff8eRf/LKF+L/S/nh
j175f786tLzyxrYW4Nd9/+lXPP/s3tf8zJvf8Po3vOa1P/rxT449+8zyc8//Y3j5
yqte972feX3SeE/+8SdP3HnWb//+iTuP3vF32zyvF1/8y7N++w9aWID/+qNXpUz+
i5s/u/bBJ/7yjtr9f/788/H211796qQHfuxf/+baGR38yXcu3/N3rwwvbn4F2fxK
tPa35h+v7NlTCP/pZf9MAY79f+aX1qkHz/puAAAAAElFTkSuQmCC
------------WRzekDfFGhbkjmHaRBKD2z--
Jul 31 2007
parent reply "Vladimir Panteleev" <thecybershadow gmail.com> writes:
------------5BZH27g6rgT6vUdyTexBow
Content-Type: text/plain; charset=koi8-r
Content-Transfer-Encoding: 7bit

On Wed, 01 Aug 2007 09:08:16 +0300, Vladimir Panteleev
<thecybershadow gmail.com> wrote:

 I initially wrote it to try to find a memory leak in Tango's GC (which was
actually fixed at some point).

Turns out it's still there, and it's the old "binary data" issue with pointer-searching GCs, which was fixed in D/Phobos 1.001 by making the GC type-aware. Check out the attached sample programs for a simple example - the Tango version can't know there are no pointers in its GrowBuffer's data, and thus leaks like crazy, while the Phobos version stays at 13MB. -- Best regards, Vladimir mailto:thecybershadow gmail.com ------------5BZH27g6rgT6vUdyTexBow Content-Disposition: attachment; filename=TangoLeakTest.d Content-Type: text/x-dsrc; name=TangoLeakTest.d Content-Transfer-Encoding: Quoted-Printable import tango.io.Stdout; import tango.io.GrowBuffer; import tango.io.FileConduit; import tango.math.Random; void main() { auto f =3D new FileConduit("test.bin", FileConduit.ReadWriteCreate); for(int i=3D0;i<256*1024;i++) { uint n =3D Random.shared.next(); f.output.write((&n)[0..1]); } f.close(); int n; while(true) { if(++n%10=3D=3D0) Stdout(n)("\r").flush; auto buffer =3D new GrowBuffer; f =3D new FileConduit("test.bin"); buffer.setConduit(f); buffer.fill(); = f.close(); } } ------------5BZH27g6rgT6vUdyTexBow Content-Disposition: attachment; filename=PhobosLeakTest.d Content-Type: text/x-dsrc; name=PhobosLeakTest.d Content-Transfer-Encoding: Quoted-Printable import std.stdio; import std.stream; import std.random; void main() { auto f =3D new File("test.bin", FileMode.Out); for(int i=3D0;i<256*1024;i++) f.write(rand()); f.close(); int n; while(true) { if(++n%10=3D=3D0) { writef(n, "\r"); fflush(stdout); } auto buffer =3D new MemoryStream; f =3D new File("test.bin"); buffer.copyFrom(f); f.close(); } } ------------5BZH27g6rgT6vUdyTexBow--
Aug 01 2007
next sibling parent reply Sean Kelly <sean f4.ca> writes:
Vladimir Panteleev wrote:
 On Wed, 01 Aug 2007 09:08:16 +0300, Vladimir Panteleev
<thecybershadow gmail.com> wrote:
 
 I initially wrote it to try to find a memory leak in Tango's GC (which was
actually fixed at some point).

Turns out it's still there, and it's the old "binary data" issue with pointer-searching GCs, which was fixed in D/Phobos 1.001 by making the GC type-aware. Check out the attached sample programs for a simple example - the Tango version can't know there are no pointers in its GrowBuffer's data, and thus leaks like crazy, while the Phobos version stays at 13MB.

It turns out this is because GrowBuffer uses a void[] internally to store data. The type should probably be changed to byte[]. I'll file a ticket for it. Sean
Aug 01 2007
next sibling parent reply Deewiant <deewiant.doesnotlike.spam gmail.com> writes:
Sean Kelly wrote:
 Vladimir Panteleev wrote:
 Turns out it's still there, and it's the old "binary data" issue with
 pointer-searching GCs, which was fixed in D/Phobos 1.001 by making the
 GC type-aware. Check out the attached sample programs for a simple
 example - the Tango version can't know there are no pointers in its
 GrowBuffer's data, and thus leaks like crazy, while the Phobos version
 stays at 13MB.

It turns out this is because GrowBuffer uses a void[] internally to store data. The type should probably be changed to byte[]. I'll file a ticket for it.

Isn't this also a problem with all the IO stuff that use void[] for everything? It starts right up there at IBuffer and IConduit. The way I see it: void[] is for "pure memory" that you might want to access in multiple different ways (akin to unions), ubyte[] is for the traditional model of "arbitrary data", and byte[] is just weird, I've yet to figure out a use for it. -- Remove ".doesnotlike.spam" from the mail address.
Aug 01 2007
parent Sean Kelly <sean f4.ca> writes:
Deewiant wrote:
 Sean Kelly wrote:
 Vladimir Panteleev wrote:
 Turns out it's still there, and it's the old "binary data" issue with
 pointer-searching GCs, which was fixed in D/Phobos 1.001 by making the
 GC type-aware. Check out the attached sample programs for a simple
 example - the Tango version can't know there are no pointers in its
 GrowBuffer's data, and thus leaks like crazy, while the Phobos version
 stays at 13MB.

store data. The type should probably be changed to byte[]. I'll file a ticket for it.

Isn't this also a problem with all the IO stuff that use void[] for everything? It starts right up there at IBuffer and IConduit.

Well, passing data around as void[] is fine, it just can't be stored as void[]. Buffer is one of the few objects that actually stores data in this way.
 The way I see it: void[] is for "pure memory" that you might want to access in
 multiple different ways (akin to unions), ubyte[] is for the traditional model
 of "arbitrary data", and byte[] is just weird, I've yet to figure out a use
for it.

That sounds like a good distinction. Feel free to add to the ticket if you think other uses of void[] should be changed to byte[] or ubyte[]. Sean
Aug 01 2007
prev sibling parent reply "Vladimir Panteleev" <thecybershadow gmail.com> writes:
On Wed, 01 Aug 2007 17:48:26 +0300, Sean Kelly <sean f4.ca> wrote:

 It turns out this is because GrowBuffer uses a void[] internally to
 store data.  The type should probably be changed to byte[].  I'll file a
 ticket for it.

Cheers, that indeed fixed it. And now it runs much faster than the Phobos version, too! What's the reasoning of scanning void[] - why would anyone keep pointers in a void[] since it's supposed to mean "binary non-descript data"? -- Best regards, Vladimir mailto:thecybershadow gmail.com
Aug 01 2007
next sibling parent Sean Kelly <sean f4.ca> writes:
Vladimir Panteleev wrote:
 On Wed, 01 Aug 2007 17:48:26 +0300, Sean Kelly <sean f4.ca> wrote:
 
 It turns out this is because GrowBuffer uses a void[] internally to
 store data.  The type should probably be changed to byte[].  I'll file a
 ticket for it.

Cheers, that indeed fixed it. And now it runs much faster than the Phobos version, too! What's the reasoning of scanning void[] - why would anyone keep pointers in a void[] since it's supposed to mean "binary non-descript data"?

I think the idea was that a void array may contain /anything/ including structs, in-place constructed classes, array references, etc, and it was easier specifying that void arrays be scanned than expecting the user to call gc.hasPointers() or whatever on the memory block every time a reallocation occurs. Sean
Aug 01 2007
prev sibling next sibling parent reply kenny <funisher gmail.com> writes:
ok you convinced me... I'll switch to tango now -- or at least start heading
that direction..

I use dmd 2.003 at the moment (it is fast enough for me, I guess... postgre is
the slow one actually), and I noticed that it definitely doesn't work with
2.003 at all.

Another thing that's really awesome about phobos / d is that the documentation
is 100% available offline. Personally, I have the worlds worst internet
connection on this planet. I would definitely be needing the documentation to
be available offline to be able to use tango effectively. I see some doc stuff,
but it looks like css and js files (I assume that the html is generated
somehow) -- but what about all of the good information on the wiki?

Other than that, I was checking out the docs and tango looks really really
good. I really like the threading stuff you've got. There are so many really
good features -- I'm actually pretty excited.

So here's the questions:
1. when is dmd 2.0 support? (I guess I can downgrade to dmd 1.0 for some time)
2. will all the documentation be available offline?
3. what other features are way faster than the phobos equiv?

Last thing... I really wish I had buffers and GrowBuffers right now... I could
really use them for some cool stuff... They look awesome! Dang... I've been
missing out. When I get converted over to tango, I'll provide before and after
benchmarks.

Good work guys.

Kenny

Vladimir Panteleev wrote:
 On Wed, 01 Aug 2007 17:48:26 +0300, Sean Kelly <sean f4.ca> wrote:
 
 It turns out this is because GrowBuffer uses a void[] internally to
 store data.  The type should probably be changed to byte[].  I'll file a
 ticket for it.

Cheers, that indeed fixed it. And now it runs much faster than the Phobos version, too! What's the reasoning of scanning void[] - why would anyone keep pointers in a void[] since it's supposed to mean "binary non-descript data"?

Aug 01 2007
parent reply Sean Kelly <sean f4.ca> writes:
kenny wrote:
 ok you convinced me... I'll switch to tango now -- or at least start heading
that direction..
 
 I use dmd 2.003 at the moment (it is fast enough for me, I guess... postgre is
the slow one actually), and I noticed that it definitely doesn't work with
2.003 at all.

Tango hasn't transitioned to D 2.0 yet. Maintaining parallel versions of the library isn't a terribly appealing notion, though I suppose it may become necessary at some point. Also, I had been worried that some of the existing features might change (though it seems like this probably won't actually happen), and because the work involved in a port to 2.0 will likely be fairly significant, I don't want to have to do it more than once.
 Another thing that's really awesome about phobos / d is that the documentation
is 100% available offline. Personally, I have the worlds worst internet
connection on this planet. I would definitely be needing the documentation to
be available offline to be able to use tango effectively. I see some doc stuff,
but it looks like css and js files (I assume that the html is generated
somehow) -- but what about all of the good information on the wiki?

I believe there is some work underway to generate offline information from the wiki, but I'm not sure how far along it is. I agree that offline documentation is very useful, as I do most of my D programming on the train.
 Other than that, I was checking out the docs and tango looks really really
good. I really like the threading stuff you've got. There are so many really
good features -- I'm actually pretty excited.
 
 So here's the questions:
 1. when is dmd 2.0 support? (I guess I can downgrade to dmd 1.0 for some time)

Not sure. After the conference I may start looking into it.
 2. will all the documentation be available offline?

Yes, but no timetable yet.
 3. what other features are way faster than the phobos equiv?

IO is the stand-out in terms of performance. I think regex would be faster with a rewrite if we (or someone else) can find the time for it (we use the Phobos version right now). And I'm not sure if it matters, but I've been told our threading implementation is more robust, and certain calls there are definitely faster than Phobos given the way each are implemented. Sean
Aug 02 2007
parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
Sean Kelly wrote:
 kenny wrote:
 2. will all the documentation be available offline?

Yes, but no timetable yet.

You can do this yourself with a copy of wget. It's not a *perfect* copy, but it does work. I did this a while back, so forgive the sketchy instructions :) Also, this is *just* the API reference, and doesn't include the formatted source code. That said, I found it useful when my dialup was down. NB: Thunderbird <3s wrapping lines, so be careful with the shell commands (prefixed with a '$'). First, make a directory for the docs. Then open up a shell (or command line or whatever) and get into that directory. Then run these commands (note: these are for bash. If you don't have bash, just expand the curly braces: "a{b,c}d" ==> "abd acd", and join the lines together at the end-of-line backslashes.) $ wget -np -nH -m -p -k -E -x --cut-dirs=4 \ http://www.dsource.org/projects/tango/docs/current/ $ wget -np -nH -m -p -k -E -x --cut-dirs=6 \ http://svn.dsource.org/projects/tango/trunk/doc/html/candydoc/img/ $ wget -nH -x --cut-dirs=4 \ http://www.dsource.org/projects/tango/docs/current/js/\ {explorer,tree,util}.js \ http://www.dsource.org/projects/tango/chrome/common/js/\ {dsource,trac}.js $ wget -nH -x --cut-dirs=3 \ http://www.dsource.org/projects/tango/themeengine/theme.js That should do it. Hope that helps. -- Daniel
Aug 02 2007
parent Brad Anderson <brad dsource.org> writes:
Daniel Keep wrote:
 
 Sean Kelly wrote:
 kenny wrote:
 2. will all the documentation be available offline?


You can do this yourself with a copy of wget. It's not a *perfect* copy, but it does work. I did this a while back, so forgive the sketchy instructions :) Also, this is *just* the API reference, and doesn't include the formatted source code. That said, I found it useful when my dialup was down. NB: Thunderbird <3s wrapping lines, so be careful with the shell commands (prefixed with a '$'). First, make a directory for the docs. Then open up a shell (or command line or whatever) and get into that directory. Then run these commands (note: these are for bash. If you don't have bash, just expand the curly braces: "a{b,c}d" ==> "abd acd", and join the lines together at the end-of-line backslashes.) $ wget -np -nH -m -p -k -E -x --cut-dirs=4 \ http://www.dsource.org/projects/tango/docs/current/ $ wget -np -nH -m -p -k -E -x --cut-dirs=6 \ http://svn.dsource.org/projects/tango/trunk/doc/html/candydoc/img/ $ wget -nH -x --cut-dirs=4 \ http://www.dsource.org/projects/tango/docs/current/js/\ {explorer,tree,util}.js \ http://www.dsource.org/projects/tango/chrome/common/js/\ {dsource,trac}.js $ wget -nH -x --cut-dirs=3 \ http://www.dsource.org/projects/tango/themeengine/theme.js That should do it. Hope that helps. -- Daniel

Ah, that was you sucking my server dry, eh? I do have it on my list of things to do for offline docs... and potentially Gregor's DSSS could help here. BA
Aug 02 2007
prev sibling parent reply Dave <Dave_member pathlink.com> writes:
Vladimir Panteleev wrote:
 On Wed, 01 Aug 2007 17:48:26 +0300, Sean Kelly <sean f4.ca> wrote:
 
 It turns out this is because GrowBuffer uses a void[] internally to
 store data.  The type should probably be changed to byte[].  I'll file a
 ticket for it.

Cheers, that indeed fixed it. And now it runs much faster than the Phobos version, too!

I thought the Phobos and Tango GC's were basically the same -- has that changed over the last 1/2 year or so? Thanks, - Dave
 What's the reasoning of scanning void[] - why would anyone keep pointers in a
void[] since it's supposed to mean "binary non-descript data"?
 

Aug 02 2007
parent Sean Kelly <sean f4.ca> writes:
Dave wrote:
 Vladimir Panteleev wrote:
 On Wed, 01 Aug 2007 17:48:26 +0300, Sean Kelly <sean f4.ca> wrote:

 It turns out this is because GrowBuffer uses a void[] internally to
 store data.  The type should probably be changed to byte[].  I'll file a
 ticket for it.

Cheers, that indeed fixed it. And now it runs much faster than the Phobos version, too!

changed over the last 1/2 year or so?

No. They're still basically the same. But some of the differences that exist both there and in the runtime could have a noticeable impact on performance in some situations, as this test shows. Also, recent discussion about this issue has inspired me to make some additional changes that will further affect certain aspects of how memory is managed, etc, and these could have an impact on the performance of some corner cases (or at least that's my hope). Eventually, I'd like to spend some time developing a new GC which is more oriented towards multithreaded programming. But that promises to be a fairly large project, and I don't have time for it quite yet. Sean
Aug 02 2007
prev sibling next sibling parent reply Jascha Wetzel <"[firstname]" mainia.de> writes:
Vladimir Panteleev wrote:
 On Wed, 01 Aug 2007 09:08:16 +0300, Vladimir Panteleev
<thecybershadow gmail.com> wrote:
 
 I initially wrote it to try to find a memory leak in Tango's GC (which was
actually fixed at some point).

Turns out it's still there, and it's the old "binary data" issue with pointer-searching GCs, which was fixed in D/Phobos 1.001 by making the GC type-aware. Check out the attached sample programs for a simple example - the Tango version can't know there are no pointers in its GrowBuffer's data, and thus leaks like crazy, while the Phobos version stays at 13MB.

i ran into another issue with the phobos gc. i have constant array literals that are used in a constructor to initialize a member. the data isn't always used. each instance uses it at most once. the second time an instance uses that data, it has been overwritten. the problem disappears if i disable the gc. it looks like the gc frees the memory that holds the constant initializer. unfortunately it's really hard to reproduce this problem in a small program.
Aug 06 2007
parent reply Sean Kelly <sean f4.ca> writes:
Jascha Wetzel wrote:
 Vladimir Panteleev wrote:
 On Wed, 01 Aug 2007 09:08:16 +0300, Vladimir Panteleev 
 <thecybershadow gmail.com> wrote:

 I initially wrote it to try to find a memory leak in Tango's GC 
 (which was actually fixed at some point).

Turns out it's still there, and it's the old "binary data" issue with pointer-searching GCs, which was fixed in D/Phobos 1.001 by making the GC type-aware. Check out the attached sample programs for a simple example - the Tango version can't know there are no pointers in its GrowBuffer's data, and thus leaks like crazy, while the Phobos version stays at 13MB.

i ran into another issue with the phobos gc. i have constant array literals that are used in a constructor to initialize a member. the data isn't always used. each instance uses it at most once. the second time an instance uses that data, it has been overwritten. the problem disappears if i disable the gc. it looks like the gc frees the memory that holds the constant initializer. unfortunately it's really hard to reproduce this problem in a small program.

Have you tested this with Tango? I would expect the same broken behavior but you never know, and any differences may help track down the issue. Sean
Aug 06 2007
next sibling parent Jascha Wetzel <"[firstname]" mainia.de> writes:
Sean Kelly wrote:
 Have you tested this with Tango?  I would expect the same broken 
 behavior but you never know, and any differences may help track down the 
 issue.

i postponed that because it'll take a bit longer to my the D2.0 code compile with 1.018 again. but i will definitely test it.
Aug 06 2007
prev sibling parent Jascha Wetzel <firstname mainia.de> writes:
Sean Kelly wrote:
 Jascha Wetzel wrote:
 Vladimir Panteleev wrote:
 On Wed, 01 Aug 2007 09:08:16 +0300, Vladimir Panteleev 
 <thecybershadow gmail.com> wrote:

 I initially wrote it to try to find a memory leak in Tango's GC 
 (which was actually fixed at some point).

Turns out it's still there, and it's the old "binary data" issue with pointer-searching GCs, which was fixed in D/Phobos 1.001 by making the GC type-aware. Check out the attached sample programs for a simple example - the Tango version can't know there are no pointers in its GrowBuffer's data, and thus leaks like crazy, while the Phobos version stays at 13MB.

i ran into another issue with the phobos gc. i have constant array literals that are used in a constructor to initialize a member. the data isn't always used. each instance uses it at most once. the second time an instance uses that data, it has been overwritten. the problem disappears if i disable the gc. it looks like the gc frees the memory that holds the constant initializer. unfortunately it's really hard to reproduce this problem in a small program.

Have you tested this with Tango? I would expect the same broken behavior but you never know, and any differences may help track down the issue.

Tango has the same problem. I couldn't find a small test program that provokes this problem, but i can reproduce it with a larger one. The problem doesn't arise the second time it is used, as i guessed earlier, it's after the GC ran once. It seems to miss the root in B.data (see below), free that memory and re-assign it to some other block. When the program crashes, the memory pointed to by B.data has been overwritten with values (used as indeces) that cause the crash. It's basically this: align(1) struct C { uint a, b, c; uint[] s; } abstract class A { C[] data; // gets initialized in subclass' c'tor - see below void foo() { bar(&data[calcIndex()]); } void bar(C* a) { foreach ( s; a.s ) doSomething(s); // crashes because s is used as an index } } class B : A { this() { data = [ C(1,2,3,[4,5,6]), C(7,8,9,[1,3,6]), C(35,5,88,[1234,78,6]) ]; } }
Sep 17 2007
prev sibling parent reply Sean Kelly <sean f4.ca> writes:
Vladimir Panteleev wrote:
 On Wed, 01 Aug 2007 09:08:16 +0300, Vladimir Panteleev
<thecybershadow gmail.com> wrote:
 
 I initially wrote it to try to find a memory leak in Tango's GC (which was
actually fixed at some point).

Turns out it's still there, and it's the old "binary data" issue with pointer-searching GCs, which was fixed in D/Phobos 1.001 by making the GC type-aware. Check out the attached sample programs for a simple example - the Tango version can't know there are no pointers in its GrowBuffer's data, and thus leaks like crazy, while the Phobos version stays at 13MB.

The cause of this is somewhat an artifact of the OO design in Tango. The underlying buffer being allocated is a byte[], but the reference to it is a void[]. The problem occurs when GrowBuffer grows the buffer by increasing its length, which causes the buffer to be reallocated as a void[]. The reason this is a problem is that neither runtime, Tango or Phobos, preserves memory block attributes during a reallocation--they both simply key off the type being used to perform the reallocation. Obviously, this is a problem, and I've decided to change the behavior in Tango accordingly. It will take some doing and I'm a bit over-busy at the moment, but before long the Tango runtime will preserve all block attributes on a reallocation. In essence, this will occur by having the runtime call gc_realloc, but before this will work gc_realloc must be fixed to handle slices. Sean
Aug 06 2007
parent reply "Vladimir Panteleev" <thecybershadow gmail.com> writes:
On Mon, 06 Aug 2007 18:20:22 +0300, Sean Kelly <sean f4.ca> wrote:

 Vladimir Panteleev wrote:
 On Wed, 01 Aug 2007 09:08:16 +0300, Vladimir Panteleev
<thecybershadow gmail.com> wrote:

 I initially wrote it to try to find a memory leak in Tango's GC (which was
actually fixed at some point).

Turns out it's still there, and it's the old "binary data" issue with pointer-searching GCs, which was fixed in D/Phobos 1.001 by making the GC type-aware. Check out the attached sample programs for a simple example - the Tango version can't know there are no pointers in its GrowBuffer's data, and thus leaks like crazy, while the Phobos version stays at 13MB.

The cause of this is somewhat an artifact of the OO design in Tango. The underlying buffer being allocated is a byte[], but the reference to it is a void[]. The problem occurs when GrowBuffer grows the buffer by increasing its length, which causes the buffer to be reallocated as a void[]. The reason this is a problem is that neither runtime, Tango or Phobos, preserves memory block attributes during a reallocation--they both simply key off the type being used to perform the reallocation. Obviously, this is a problem, and I've decided to change the behavior in Tango accordingly. It will take some doing and I'm a bit over-busy at the moment, but before long the Tango runtime will preserve all block attributes on a reallocation. In essence, this will occur by having the runtime call gc_realloc, but before this will work gc_realloc must be fixed to handle slices.

I'd still rather vote towards making the GC not scan void[] - it makes the most sense. -- Best regards, Vladimir mailto:thecybershadow gmail.com
Aug 07 2007
parent Sean Kelly <sean f4.ca> writes:
Vladimir Panteleev wrote:
 On Mon, 06 Aug 2007 18:20:22 +0300, Sean Kelly <sean f4.ca> wrote:
 
 Vladimir Panteleev wrote:
 On Wed, 01 Aug 2007 09:08:16 +0300, Vladimir Panteleev
<thecybershadow gmail.com> wrote:

 I initially wrote it to try to find a memory leak in Tango's GC (which was
actually fixed at some point).


The underlying buffer being allocated is a byte[], but the reference to it is a void[]. The problem occurs when GrowBuffer grows the buffer by increasing its length, which causes the buffer to be reallocated as a void[]. The reason this is a problem is that neither runtime, Tango or Phobos, preserves memory block attributes during a reallocation--they both simply key off the type being used to perform the reallocation. Obviously, this is a problem, and I've decided to change the behavior in Tango accordingly. It will take some doing and I'm a bit over-busy at the moment, but before long the Tango runtime will preserve all block attributes on a reallocation. In essence, this will occur by having the runtime call gc_realloc, but before this will work gc_realloc must be fixed to handle slices.

I'd still rather vote towards making the GC not scan void[] - it makes the most sense.

Others have expressed the same opinion. I'll withhold my own thoughts but to say that I think the idea behind the current approach is twofold: 1. void[] is the 'any' buffer type for in-program data. The type of the underlying data could be an array of bytes or it could be an array of structs containing pointers. The 'any' buffer type for out-of-program data is byte[], because until such data is translated to D types, it's merely a stream of bytes. 2. It is nice to have an in-language option for specifying that an 'any' buffer type may contain pointers. The most obvious counter-argument is that by assigning special behavior to void[], those who don't like that behavior must use something else and lose the implicit conversion that void[] provides. This is extremely convenient in some cases. Another being that because void[] does not specify a type, it is appropriate for out-of-program data as well, and scanning a stream of bytes read from a file for pointers is bad. I personally don't think there is a solution to this that will make everyone happy, and am hoping that by preserving block attributes I will make void[] more usable as a reference type since then only the first allocation must be "new byte[x]". It is also more consistent, since some reallocations obtain a new array (and lose block information), while others do not (and preserve block information). Sean
Aug 07 2007