[Mono-dev] Few notes about finalization

2012-12-05 Thread Konrad M. Kruczynski
Hi all,
it is rather known fact that adding a finalizer to the class can hurt
performance quite badly with generational garbage collectors. This is
due to the premortem finalization used by CLR. If an object is not
reachable during GC, but has a finalizer, it will survive and probably
be promoted to the next generation. Not so bad in its essence, but such
object will transitively make all referenced objects alive and these
will be promoted as well.

Consider simple benchmark contained in the attached file Test705.cs. The
intstances of classes are being born and dying, also they have reference
to the table of objects. The class A has an finalizer. On my computer
(SGEN, Mono 2.10.8) the result is:

Took 00:00:32.4182579

If you comment out the finalizer, the result is:

Took 00:00:04.2515352

So the difference is significant.

Most of the time (at least from my experience) developers do not need
premortem finalization. That is, they do not need to have the reference
to the instance that is being finalized. What they need is some kind of
simple callback called after this instance is GCd (the callback could
also have some kind of parameter related to such instance). As you can
see, this is also the case in the mentioned example -- the reference to
the original instance is not needed.

When I encountered internal sgen API for reference queues, I thought
that this could be used to do postmortem finalization. Unfortunately,
the API was not stable yet and therefore not public.

But there is another, very simple idea. Instead of having a finalizer in
A, one could do dummy class B (with its own finalizer) to instance of
which A would have a reference. Therefore B's finalizer would serve as a
callback function of A.

The attached example Test706.cs is based on this idea. And the result
is:

Took 00:00:04.6424758

So it is in the same order of magnitude.

Yup, this is very simple idea, nonetheless works well and did not come
to me as a solution immediately, so maybe this will be useful to
someone. Or I am wrong somewhere ;)

--
Best regards,
 Konrad
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;

namespace Test706
{
	class MainClass
	{
		public static void Main(string[] args)
		{
			var sw = Stopwatch.StartNew();
			Parallel.For(0, 100, i =>
			 {
new A();
			});
			Console.WriteLine("Took {0}", sw.Elapsed);
		}
	}
	
	public class A
	{
		public A()
		{
			array = new object[GetRandom().Next(1000)];
			for(var i = 0; i < array.Length; i++)
			{
array[i] = new object();
			}
			b = new B();
		}
		
		public static int Counter;
		
		private object[] array;
		private B b;
		
		private static Random GetRandom()
		{
			if(Rand == null)
			{
Rand = new Random();
			}
			return Rand;
		}
		
		[ThreadStatic]
		private static Random Rand;
	}

	public class B
	{
		~B()
		{
			Interlocked.Increment(ref Counter);
		}

		public static int Counter;
	}
}
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;

namespace Test705
{
	class MainClass
	{
		public static void Main(string[] args)
		{
			var sw = Stopwatch.StartNew();
			Parallel.For(0, 100, i =>
			 {
new A();
			});
			Console.WriteLine("Took {0}", sw.Elapsed);
		}
	}

	public class A
	{
		public A()
		{
			array = new object[GetRandom().Next(1000)];
			for(var i = 0; i < array.Length; i++)
			{
array[i] = new object();
			}
		}

		~A()
		{
			Interlocked.Increment(ref Counter);
		}

		public static int Counter;

		private object[] array;

		private static Random GetRandom()
		{
			if(Rand == null)
			{
Rand = new Random();
			}
			return Rand;
		}

		[ThreadStatic]
		private static Random Rand;
	}
}
___
Mono-devel-list mailing list
Mono-devel-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-devel-list


Re: [Mono-dev] Few notes about finalization

2012-12-05 Thread Konrad M. Kruczynski
On śro, 2012-12-05 at 13:56 +0100, Konrad M. Kruczynski wrote:
> Hi all,
> it is rather known fact that adding a finalizer to the class can hurt
> performance quite badly with generational garbage collectors. This is
> due to the premortem finalization used by CLR. If an object is not
> reachable during GC, but has a finalizer, it will survive and probably
> be promoted to the next generation. Not so bad in its essence, but such
> object will transitively make all referenced objects alive and these
> will be promoted as well.
> 
> Consider simple benchmark contained in the attached file Test705.cs. The
> intstances of classes are being born and dying, also they have reference
> to the table of objects. The class A has an finalizer. On my computer
> (SGEN, Mono 2.10.8) the result is:
> 
> Took 00:00:32.4182579
> 
> If you comment out the finalizer, the result is:
> 
> Took 00:00:04.2515352
> 
> So the difference is significant.
> 
> Most of the time (at least from my experience) developers do not need
> premortem finalization. That is, they do not need to have the reference
> to the instance that is being finalized. What they need is some kind of
> simple callback called after this instance is GCd (the callback could
> also have some kind of parameter related to such instance). As you can
> see, this is also the case in the mentioned example -- the reference to
> the original instance is not needed.
> 
> When I encountered internal sgen API for reference queues, I thought
> that this could be used to do postmortem finalization. Unfortunately,
> the API was not stable yet and therefore not public.
> 
> But there is another, very simple idea. Instead of having a finalizer in
> A, one could do dummy class B (with its own finalizer) to instance of
> which A would have a reference. Therefore B's finalizer would serve as a
> callback function of A.
> 
> The attached example Test706.cs is based on this idea. And the result
> is:
> 
> Took 00:00:04.6424758
> 
> So it is in the same order of magnitude.
> 
> Yup, this is very simple idea, nonetheless works well and did not come
> to me as a solution immediately, so maybe this will be useful to
> someone. Or I am wrong somewhere ;)
> 
> --

It may be worth adding, that with the fresh Mono from GIT the results
are similar (although new sgen is faster in general which is a good
news), respectively:

Took 00:00:28.1762050
Took 00:00:03.5601241
Took 00:00:03.9642138

--
Konrad

___
Mono-devel-list mailing list
Mono-devel-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-devel-list


[Mono-dev] HttpListener

2012-12-05 Thread Greg Young
I was in looking at some code today in httplistener and didn't understand
some of the stuff going on (was hitting a performance penalty due to it).

In particular I was a bit confused when looking at Begin and EndGetContext
(included below).. It would seem harmful to call ares.Complete below while
holding a lock to wait_queue. I just wanted to see what someone may have
been thinking before spending time on a patch

public IAsyncResult BeginGetContext (AsyncCallback callback, 
Object state)
{
CheckDisposed ();
if (!listening)
throw new InvalidOperationException ("Please, 
call Start before
using this method.");

ListenerAsyncResult ares = new ListenerAsyncResult 
(callback, state);

// lock wait_queue early to avoid race conditions
lock (wait_queue) {
lock (ctx_queue) {
HttpListenerContext ctx = 
GetContextFromQueue ();
if (ctx != null) {
ares.Complete (ctx, true);
return ares;
}
}

wait_queue.Add (ares);
}

return ares;
}

public HttpListenerContext EndGetContext (IAsyncResult 
asyncResult)
{
CheckDisposed ();
if (asyncResult == null)
throw new ArgumentNullException ("asyncResult");

ListenerAsyncResult ares = asyncResult as 
ListenerAsyncResult;
if (ares == null)
throw new ArgumentException ("Wrong 
IAsyncResult.", "asyncResult");

if (!ares.IsCompleted)
ares.AsyncWaitHandle.WaitOne ();

lock (wait_queue) {
int idx = wait_queue.IndexOf (ares);
if (idx >= 0)
wait_queue.RemoveAt (idx);
}

HttpListenerContext context = ares.GetContext ();
context.ParseAuthentication (SelectAuthenticationScheme 
(context));
return context; // This will throw on error.
}


-- 
Le doute n'est pas une condition agréable, mais la certitude est absurde.
___
Mono-devel-list mailing list
Mono-devel-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-devel-list


Re: [Mono-dev] HttpListener

2012-12-05 Thread Rodrigo Kumpera
Did you look at the git history for those changes to see why those changes
have been made?

04c641a21c2ba92c3262948ed1b68eb22c643b11 seens relevant.


On Wed, Dec 5, 2012 at 8:52 AM, Greg Young  wrote:

> CheckDisposed ();
> if (!listening)
>  throw new InvalidOperationException ("Please, call Start before using
> this method.");
>
> ListenerAsyn
>
___
Mono-devel-list mailing list
Mono-devel-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-devel-list


Re: [Mono-dev] HttpListener

2012-12-05 Thread Greg Young
I did see it (and comment). Thought there might be something more to it.


On Wed, Dec 5, 2012 at 4:05 PM, Rodrigo Kumpera  wrote:

> Did you look at the git history for those changes to see why those changes
> have been made?
>
> 04c641a21c2ba92c3262948ed1b68eb22c643b11 seens relevant.
>
>
> On Wed, Dec 5, 2012 at 8:52 AM, Greg Young wrote:
>
>> CheckDisposed ();
>> if (!listening)
>>  throw new InvalidOperationException ("Please, call Start before using
>> this method.");
>>
>> ListenerAsyn
>>
>
>


-- 
Le doute n'est pas une condition agréable, mais la certitude est absurde.
___
Mono-devel-list mailing list
Mono-devel-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-devel-list


Re: [Mono-dev] Question about Mono.Data.Tds

2012-12-05 Thread Daniel Morgan
The assembly Mono.Data.Tds can be thought of as internal to the assembly 
System.Data for the SqlClient implementation.    So, you can change the API of 
Mono.Data.Tds as long as you change the assembly System.Data too.

The reason the assembly Mono.Data.Tds exists is historic: Mono.Data.Tds was 
created to provide the networking/protocol implementation of TDS for Sybase ASE 
(Mono.Data.SybaseClient), Microsoft SQL Server 7.0 or higher 
(System.Data.SqlClient), and old Sybase SQL Server and Microsoft SQL Server 
pre-7.0 (Mono.Data.TdsClient) databases.    However, I do not think the 
assemblies Mono.Data.SybaseClient nor Mono.Data.TdsClient is included in Mono 
anymore.  If you need Sybase ASE or support for older Sybase ASE or Microsoft 
SQL Server databases, you should use ODBC/FreeTDS.

Mono.Data.Tds is based on the projects FreeTDS and jTDS.





 From: Andres G. Aragoneses 
To: mono-devel-list@lists.ximian.com 
Sent: Tuesday, December 4, 2012 4:19 PM
Subject: [Mono-dev] Question about Mono.Data.Tds
 
Question about Mono.Data.Tds:

Is it API stable? Does it need to be?

I ask this because I'm interested in fixing a bug. And for me, it would be much 
easier to write a regression test for it if I could change it's API slightly.

And when I say "slightly" I don't mean breaking changes, but API additions: for 
instance, make some class inherit from some new interface.

Feedback appreciated. Thanks!

Andres

[1]https://github.com/mono/mono/tree/master/mcs/class/Mono.Data.Tds

___
Mono-devel-list mailing list
Mono-devel-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-devel-list___
Mono-devel-list mailing list
Mono-devel-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-devel-list


Re: [Mono-dev] Question about Mono.Data.Tds

2012-12-05 Thread Andres G. Aragoneses


Thanks for the info Daniel!

Then, a review on this pull request is appreciated, to bring ADO.NET's 
Connection Lifetime support to Mono:


https://github.com/mono/mono/pull/517


On 05/12/12 18:09, Daniel Morgan wrote:

The assembly Mono.Data.Tds can be thought of as internal to the assembly
System.Data for the SqlClient implementation.So, you can change the
API of Mono.Data.Tds as long as you change the assembly System.Data too.

The reason the assembly Mono.Data.Tds exists is historic: Mono.Data.Tds
was created to provide the networking/protocol implementation of TDS for
Sybase ASE (Mono.Data.SybaseClient), Microsoft SQL Server 7.0 or higher
(System.Data.SqlClient), and old Sybase SQL Server and Microsoft SQL
Server pre-7.0 (Mono.Data.TdsClient) databases.However, I do not
think the assemblies Mono.Data.SybaseClient nor Mono.Data.TdsClient is
included in Mono anymore.  If you need Sybase ASE or support for older
Sybase ASE or Microsoft SQL Server databases, you should use ODBC/FreeTDS.

Mono.Data.Tds is based on the projects FreeTDS and jTDS.



*From:* Andres G. Aragoneses 
*To:* mono-devel-list@lists.ximian.com
*Sent:* Tuesday, December 4, 2012 4:19 PM
*Subject:* [Mono-dev] Question about Mono.Data.Tds

Question about Mono.Data.Tds:

Is it API stable? Does it need to be?

I ask this because I'm interested in fixing a bug. And for me, it would
be much easier to write a regression test for it if I could change it's
API slightly.

And when I say "slightly" I don't mean breaking changes, but API
additions: for instance, make some class inherit from some new interface.

Feedback appreciated. Thanks!

Andres

[1]https://github.com/mono/mono/tree/master/mcs/class/Mono.Data.Tds

___
Mono-devel-list mailing list
Mono-devel-list@lists.ximian.com 
http://lists.ximian.com/mailman/listinfo/mono-devel-list




___
Mono-devel-list mailing list
Mono-devel-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-devel-list




___
Mono-devel-list mailing list
Mono-devel-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-devel-list


Re: [Mono-dev] HttpListener

2012-12-05 Thread Andres G. Aragoneses
Hey Rodrigo, by looking at 
https://github.com/mono/mono/commit/04c641a21c2ba92c3262948ed1b68eb22c643b11 
as you point out, it would make sense to find the call to 
GetContextFromQueue() inside the lock, but maybe ares.Complete() can be 
outside for better performance? (And then inside again when adding it to 
the wait_queue again.) Which is maybe what Greg meant.


On 05/12/12 14:05, Rodrigo Kumpera wrote:

Did you look at the git history for those changes to see why those
changes have been made?

04c641a21c2ba92c3262948ed1b68eb22c643b11 seens relevant.


On Wed, Dec 5, 2012 at 8:52 AM, Greg Young mailto:gregoryyou...@gmail.com>> wrote:

CheckDisposed ();
if (!listening)
throw new InvalidOperationException ("Please, call Start before
using this method.");

ListenerAsyn




___
Mono-devel-list mailing list
Mono-devel-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-devel-list




___
Mono-devel-list mailing list
Mono-devel-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-devel-list