Re: [Mono-dev] [SPAM] Re: ToString() performace in Mono revisited
The array initialization should also be done lazily and not in the static constructor (should be removed completely because it drags in other static fields that need to be preinitialized, code compiled and so on). Especially the Hex support is IMHO completely off bounds. I (personally) rarely see hex output and making EVERYBODY pay for a hex speedup doesn't seem right. A simple if (array == null) Init (); will be enough. You will pay per-call, but it is relatively cheap. Otherwise a single Console.WriteLine (1.ToString()); will get an EXTREMELY slow operation when you need to init a whole array just for a (potentially) single conversion. Greetings Andreas -Ursprüngliche Nachricht- Von: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] Im Auftrag von Eyal Alaluf Gesendet: Montag, 31. Dezember 2007 13:24 An: Juraj Skripsky; Atsushi Eno Cc: Miguel de Icaza; mono-devel-list@lists.ximian.com Betreff: [SPAM] Re: [Mono-dev] ToString() performace in Mono revisited Hi, all. Thanks for the feedback. The amount of used memory is indeed not appropriate for small devices and is not economic enough. The 'DblExpTab' is essential in order for the double ToString to be efficient. As for the other two arrays they cache a simple arithmetic caclcualtion. I'll therefore eliminate the '_decHexLen' array and use static readonly int[] _decHexDigits = new int [100]; I'll make DblRep into a struct and remove one member out of it (and slightly improve the double.ToString() perf along the way). This will change the allocation size to 100 * 4 + 2048 * (3 * 4) = ~25K. The performance impact is betweek 3-10% overall for simple ToString() depending on the hardware. Eyal. -Original Message- From: Juraj Skripsky [mailto:[EMAIL PROTECTED] Sent: 30 December 2007 19:34 To: Atsushi Eno Cc: Eyal Alaluf; Miguel de Icaza; mono-devel-list@lists.ximian.com Subject: Re: [Mono-dev] ToString() performace in Mono revisited Hello, I think the following two arrays account for most of those 300KB: static readonly int[] _decHexDigits = new int [1]; static readonly int[] _decHexLen = new int [0x1]; The first one consumes almost 40KB, the second one 256KB... The DblExpTab array uses 2048 * 4 = 8KB and its referenced DblRep objects 2048 * (8 + 4 * 4) = 48KB. This means a total of 56KB. Turning DblExbTab into a struct would reduce this to 2048 * (4 * 4) = 32KB. - Juraj On Mon, 2007-12-31 at 00:19 +0900, Atsushi Eno wrote: Hello, Kazuki pointed out that the static initialization part of NumberFormatter allocates 300KB. It is probably here: public static readonly DblRep[] DblExpTab = new DblRep [ExponentMax + 1]; It does not look good. Atsushi Eno Eyal Alaluf wrote: With the attchments zipped to reduce size. * From: * [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] *On Behalf Of *Eyal Alaluf *Sent:* 27 December 2007 17:28 *To:* mono-devel-list@lists.ximian.com *Cc:* Miguel de Icaza *Subject:* [Mono-dev] ToString() performace in Mono revisited I got complaints that the font color within the table is white so this is a resent J Hi, all. Attached is a redesigned implementation of the NumberFormatter class. The patch includes a new algorithm for float and double ToString implementation that improves performance by a factor of 25(!) and upto 440(!!!). The patch includes further improvements to integer /ToString/ as well as Andreas suggestion of avoiding calling /NumberFormatInfo.CurrentInfo/ in the case of integer types default /ToString()/ implementation. This patch should improve Mono's performance in important use cases such as web-services where primitive /ToString/ performance is an important factor. The following is a table showing the improvements for the different primitive types using the patch. All the results are in milliseconds and for a run of 10,000,000 iterations with warm-up of 10,000,000 iterations as well. Mono 1.2.6 Patch Improvement 12345.ToString(G) 10079 7328 1.37 12345L.ToString(G) 13203 7297 1.81 0.12345.ToString(G) 323750 13047 24.8(!) 1.2345E-200.ToString(G) 6376500 14328 445(!!!) 0.12345m.ToString(G) 51078 9875 5.2 12345.ToString() 12406/7781 5687 2.2/1.37 12345L.ToString() 281090 4006 3897 72.1(!!) 1.03 1.2345E-200.ToString(G) 5686000 12345.ToString(G)/!) and the second is after applying Andreas suggestion on top of Mono 1.2.6. The following are the results of the new algorithm compared
Re: [Mono-dev] [SPAM] Re: ToString() performace in Mono revisited
If the null test is not desired, a nested class can be used instead and the cctor trampoline will be patched later by the runtime. On Jan 2, 2008 2:24 PM, Andreas Nahr [EMAIL PROTECTED] wrote: The array initialization should also be done lazily and not in the static constructor (should be removed completely because it drags in other static fields that need to be preinitialized, code compiled and so on). Especially the Hex support is IMHO completely off bounds. I (personally) rarely see hex output and making EVERYBODY pay for a hex speedup doesn't seem right. A simple if (array == null) Init (); will be enough. You will pay per-call, but it is relatively cheap. Otherwise a single Console.WriteLine (1.ToString()); will get an EXTREMELY slow operation when you need to init a whole array just for a (potentially) single conversion. Greetings Andreas -Ursprüngliche Nachricht- Von: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] Im Auftrag von Eyal Alaluf Gesendet: Montag, 31. Dezember 2007 13:24 An: Juraj Skripsky; Atsushi Eno Cc: Miguel de Icaza; mono-devel-list@lists.ximian.com Betreff: [SPAM] Re: [Mono-dev] ToString() performace in Mono revisited Hi, all. Thanks for the feedback. The amount of used memory is indeed not appropriate for small devices and is not economic enough. The 'DblExpTab' is essential in order for the double ToString to be efficient. As for the other two arrays they cache a simple arithmetic caclcualtion. I'll therefore eliminate the '_decHexLen' array and use static readonly int[] _decHexDigits = new int [100]; I'll make DblRep into a struct and remove one member out of it (and slightly improve the double.ToString() perf along the way). This will change the allocation size to 100 * 4 + 2048 * (3 * 4) = ~25K. The performance impact is betweek 3-10% overall for simple ToString() depending on the hardware. Eyal. -Original Message- From: Juraj Skripsky [mailto:[EMAIL PROTECTED] Sent: 30 December 2007 19:34 To: Atsushi Eno Cc: Eyal Alaluf; Miguel de Icaza; mono-devel-list@lists.ximian.com Subject: Re: [Mono-dev] ToString() performace in Mono revisited Hello, I think the following two arrays account for most of those 300KB: static readonly int[] _decHexDigits = new int [1]; static readonly int[] _decHexLen = new int [0x1]; The first one consumes almost 40KB, the second one 256KB... The DblExpTab array uses 2048 * 4 = 8KB and its referenced DblRep objects 2048 * (8 + 4 * 4) = 48KB. This means a total of 56KB. Turning DblExbTab into a struct would reduce this to 2048 * (4 * 4) = 32KB. - Juraj On Mon, 2007-12-31 at 00:19 +0900, Atsushi Eno wrote: Hello, Kazuki pointed out that the static initialization part of NumberFormatter allocates 300KB. It is probably here: public static readonly DblRep[] DblExpTab = new DblRep [ExponentMax + 1]; It does not look good. Atsushi Eno Eyal Alaluf wrote: With the attchments zipped to reduce size. * From: * [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] *On Behalf Of *Eyal Alaluf *Sent:* 27 December 2007 17:28 *To:* mono-devel-list@lists.ximian.com *Cc:* Miguel de Icaza *Subject:* [Mono-dev] ToString() performace in Mono revisited I got complaints that the font color within the table is white so this is a resent J Hi, all. Attached is a redesigned implementation of the NumberFormatter class. The patch includes a new algorithm for float and double ToString implementation that improves performance by a factor of 25(!) and upto 440(!!!). The patch includes further improvements to integer /ToString/ as well as Andreas suggestion of avoiding calling /NumberFormatInfo.CurrentInfo/ in the case of integer types default /ToString()/ implementation. This patch should improve Mono's performance in important use cases such as web-services where primitive /ToString/ performance is an important factor. The following is a table showing the improvements for the different primitive types using the patch. All the results are in milliseconds and for a run of 10,000,000 iterations with warm-up of 10,000,000 iterations as well. Mono 1.2.6 Patch Improvement 12345.ToString(G) 10079 7328 1.37 12345L.ToString(G) 13203 7297 1.81 0.12345.ToString(G) 323750 13047 24.8(!) 1.2345E-200.ToString(G) 6376500 14328 445(!!!) 0.12345m.ToString(G) 51078 9875 5.2 12345.ToString() 12406/7781 5687 2.2/1.37 12345L.ToString() 281090 4006 3897 72.1(!!) 1.03 1.2345E-200.ToString(G
Re: [Mono-dev] [SPAM] Re: ToString() performace in Mono revisited
Hey, The array initialization should also be done lazily and not in the static constructor (should be removed completely because it drags in other static fields that need to be preinitialized, code compiled and so on). Especially the Hex support is IMHO completely off bounds. I (personally) rarely see hex output and making EVERYBODY pay for a hex speedup doesn't seem right. A simple if (array == null) Init (); will be enough. You will pay per-call, but it is relatively cheap. The only thing that is worth keeping in mind is that if this is a static field, initialization probably needs to be protected by a lock (I say probably, because we *could* ignore the race by carefully making sure that we assign the public array only after it has been initialized, so we would end up with N copies of an array initialized in the worst case, but N-1 will be discarded by the GC). Otherwise a single Console.WriteLine (1.ToString()); will get an EXTREMELY slow operation when you need to init a whole array just for a (potentially) single conversion. Greetings Andreas -Ursprüngliche Nachricht- Von: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] Im Auftrag von Eyal Alaluf Gesendet: Montag, 31. Dezember 2007 13:24 An: Juraj Skripsky; Atsushi Eno Cc: Miguel de Icaza; mono-devel-list@lists.ximian.com Betreff: [SPAM] Re: [Mono-dev] ToString() performace in Mono revisited Hi, all. Thanks for the feedback. The amount of used memory is indeed not appropriate for small devices and is not economic enough. The 'DblExpTab' is essential in order for the double ToString to be efficient. As for the other two arrays they cache a simple arithmetic caclcualtion. I'll therefore eliminate the '_decHexLen' array and use static readonly int[] _decHexDigits = new int [100]; I'll make DblRep into a struct and remove one member out of it (and slightly improve the double.ToString() perf along the way). This will change the allocation size to 100 * 4 + 2048 * (3 * 4) = ~25K. The performance impact is betweek 3-10% overall for simple ToString() depending on the hardware. Eyal. -Original Message- From: Juraj Skripsky [mailto:[EMAIL PROTECTED] Sent: 30 December 2007 19:34 To: Atsushi Eno Cc: Eyal Alaluf; Miguel de Icaza; mono-devel-list@lists.ximian.com Subject: Re: [Mono-dev] ToString() performace in Mono revisited Hello, I think the following two arrays account for most of those 300KB: static readonly int[] _decHexDigits = new int [1]; static readonly int[] _decHexLen = new int [0x1]; The first one consumes almost 40KB, the second one 256KB... The DblExpTab array uses 2048 * 4 = 8KB and its referenced DblRep objects 2048 * (8 + 4 * 4) = 48KB. This means a total of 56KB. Turning DblExbTab into a struct would reduce this to 2048 * (4 * 4) = 32KB. - Juraj On Mon, 2007-12-31 at 00:19 +0900, Atsushi Eno wrote: Hello, Kazuki pointed out that the static initialization part of NumberFormatter allocates 300KB. It is probably here: public static readonly DblRep[] DblExpTab = new DblRep [ExponentMax + 1]; It does not look good. Atsushi Eno Eyal Alaluf wrote: With the attchments zipped to reduce size. * From: * [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] *On Behalf Of *Eyal Alaluf *Sent:* 27 December 2007 17:28 *To:* mono-devel-list@lists.ximian.com *Cc:* Miguel de Icaza *Subject:* [Mono-dev] ToString() performace in Mono revisited I got complaints that the font color within the table is white so this is a resent J Hi, all. Attached is a redesigned implementation of the NumberFormatter class. The patch includes a new algorithm for float and double ToString implementation that improves performance by a factor of 25(!) and upto 440(!!!). The patch includes further improvements to integer /ToString/ as well as Andreas suggestion of avoiding calling /NumberFormatInfo.CurrentInfo/ in the case of integer types default /ToString()/ implementation. This patch should improve Mono's performance in important use cases such as web-services where primitive /ToString/ performance is an important factor. The following is a table showing the improvements for the different primitive types using the patch. All the results are in milliseconds and for a run of 10,000,000 iterations with warm-up of 10,000,000 iterations as well. Mono 1.2.6 Patch Improvement 12345.ToString(G) 10079 7328 1.37 12345L.ToString(G) 13203 7297 1.81 0.12345.ToString(G) 323750 13047 24.8(!) 1.2345E-200.ToString(G) 6376500
Re: [Mono-dev] [SPAM] Re: ToString() performace in Mono revisited
The array initialization should also be done lazily and not in the static constructor (should be removed completely because it drags in other static fields that need to be preinitialized, code compiled and so on). Especially the Hex support is IMHO completely off bounds. I (personally) rarely see hex output and making EVERYBODY pay for a hex speedup doesn't seem right. A simple if (array == null) Init (); will be enough. You will pay per-call, but it is relatively cheap. The only thing that is worth keeping in mind is that if this is a static field, initialization probably needs to be protected by a lock (I say probably, because we *could* ignore the race by carefully making sure that we assign the public array only after it has been initialized, so we would end up with N copies of an array initialized in the worst case, but N-1 will be discarded by the GC). You can also use the Bill Pugh's trick by using a nested class, so the jit should lazily initialize it (it works with .net, no idea whether it does with mono.) I don't know whether it would work with mono either but you may get additional problems having a nested class in a structure ;) Also there is no need to lock for multithreading. As Miguel wrote we can simply ignore the race in this situation. Worst case two (or n) Lookuparrays get created and all except one immediately garbage-collected after their use. All you need to have is void Init () { int[] temp = new int[x]; doinits() staticField = temp; // Must not happen before doinits() } Greetings Andreas ___ Mono-devel-list mailing list Mono-devel-list@lists.ximian.com http://lists.ximian.com/mailman/listinfo/mono-devel-list