The Good, The Bad, and the DAMN that code is ugly!!!

by Mwwhited 18. June 2009 01:06

 

In the sprit of playing with a string chop question on stackoverflow… I somehow got myself into the middle of some fun code profiling.  So this is a report of the code and results.

(this is related to a previous most I made as well http://hackersbasement.com/?p=134)

Charted Short String Results

Person Version Run 1 Run 2 Run 3
Str SB J Str SB J Str SB J
Alan M 1 8484     707     1477    
2 43526     616     700    
3 7224     707     2296    
Aric TenEyck 1   15477 560   385 175   301 273
2   31773 357   133 322   168 294
Fredou 1 14567     322     154    
Joel Coehoorn 1   51282 735   350 308   1071 329
2 22876     161     140    
Martin 1 14357     140     98    
2 12138     112     84    
3   39109 1127   119 147   119 287
Matthew Whited 1   29211 11179   518 665   378 448
2   45794 1484   546 182   301 679
3 11697     210     217    
4 14322     175     147    
Tim J 1   38997 784   91 168   168 280

Charted Long String Results

Person Version Run 1 Run 2 Run 3
Str SB J Str SB J Str SB J
Alan M 1 46550     38535     40677    
2 45899     39312     39858    
3 28910     303254     26845    
Aric TenEyck 1   28987 3647   2240 1904   2198 3563
2   35364 3661   4767 4284   5096 5285
Fredou 1 13699     4256     9520    
Joel Coehoorn 1   49686 1344   581 700   812 840
2 31304     329     329    
Martin 1 15050     308     336    
2 12537     350     469    
3   34027 1099   406 434   532 777
Matthew Whited 1   69566 11886   882 819   651 875
2   39620 2254   581 497   658 707
3 17227     441     588    
4 27349     441     616    
Tim J 1   36260 142233   672 1008   497 1610

 

Results for Short string "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"

============================================
StringBuilder: MatthewWhited1 Ticks: 29211
StringBuilder: MatthewWhited2 Ticks: 45794
Join: MatthewWhited1 Ticks: 11179
Join: MatthewWhited2 Ticks: 1484
String: MatthewWhited3 Ticks: 11697
String: MatthewWhited4 Ticks: 14322
String: AlanM_1 Ticks: 8484
String: AlanM_2 Ticks: 43526
String: AlanM_3 Ticks: 7224
StringBuilder: AricTenEyck1 Ticks: 15477
StringBuilder: AricTenEyck2 Ticks: 31773
Join: AricTenEyck1 Ticks: 560
Join: AricTenEyck2 Ticks: 357
String: Martin1 Ticks: 14357
String: Martin2 Ticks: 12138
StringBuilder: Martin3 Ticks: 39109
Join: Martin3 Ticks: 1127
String: JoelCoehoorn2 Ticks: 22876
StringBuilder: JoelCoehoorn1 Ticks: 51282
Join: JoelCoehoorn1 Ticks: 735
StringBuilder: TimJ Ticks: 38997
Join: TimJ Ticks: 784
String: Fredou1 Ticks: 14567
============================================
StringBuilder: MatthewWhited1 Ticks: 518
StringBuilder: MatthewWhited2 Ticks: 546
Join: MatthewWhited1 Ticks: 665
Join: MatthewWhited2 Ticks: 182
String: MatthewWhited3 Ticks: 210
String: MatthewWhited4 Ticks: 175
String: AlanM_1 Ticks: 707
String: AlanM_2 Ticks: 616
String: AlanM_3 Ticks: 707
StringBuilder: AricTenEyck1 Ticks: 385
StringBuilder: AricTenEyck2 Ticks: 133
Join: AricTenEyck1 Ticks: 175
Join: AricTenEyck2 Ticks: 322
String: Martin1 Ticks: 140
String: Martin2 Ticks: 112
StringBuilder: Martin3 Ticks: 119
Join: Martin3 Ticks: 147
String: JoelCoehoorn2 Ticks: 161
StringBuilder: JoelCoehoorn1 Ticks: 350
Join: JoelCoehoorn1 Ticks: 308
StringBuilder: TimJ Ticks: 91
Join: TimJ Ticks: 168
String: Fredou1 Ticks: 322
============================================
StringBuilder: MatthewWhited1 Ticks: 378
StringBuilder: MatthewWhited2 Ticks: 301
Join: MatthewWhited1 Ticks: 448
Join: MatthewWhited2 Ticks: 679
String: MatthewWhited3 Ticks: 217
String: MatthewWhited4 Ticks: 147
String: AlanM_1 Ticks: 1477
String: AlanM_2 Ticks: 700
String: AlanM_3 Ticks: 2296
StringBuilder: AricTenEyck1 Ticks: 301
StringBuilder: AricTenEyck2 Ticks: 168
Join: AricTenEyck1 Ticks: 273
Join: AricTenEyck2 Ticks: 294
String: Martin1 Ticks: 98
String: Martin2 Ticks: 84
StringBuilder: Martin3 Ticks: 119
Join: Martin3 Ticks: 287
String: JoelCoehoorn2 Ticks: 140
StringBuilder: JoelCoehoorn1 Ticks: 1071
Join: JoelCoehoorn1 Ticks: 329
StringBuilder: TimJ Ticks: 168
Join: TimJ Ticks: 280
String: Fredou1 Ticks: 154

Results for Long string "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" * 68

============================================
StringBuilder: MatthewWhited1 Ticks: 69566
StringBuilder: MatthewWhited2 Ticks: 39620
Join: MatthewWhited1 Ticks: 11886
Join: MatthewWhited2 Ticks: 2254
String: MatthewWhited3 Ticks: 17227
String: MatthewWhited4 Ticks: 27349
String: AlanM_1 Ticks: 46550
String: AlanM_2 Ticks: 45899
String: AlanM_3 Ticks: 28910
StringBuilder: AricTenEyck1 Ticks: 28987
StringBuilder: AricTenEyck2 Ticks: 35364
Join: AricTenEyck1 Ticks: 3647
Join: AricTenEyck2 Ticks: 3661
String: Martin1 Ticks: 15050
String: Martin2 Ticks: 12537
StringBuilder: Martin3 Ticks: 34027
Join: Martin3 Ticks: 1099
String: JoelCoehoorn2 Ticks: 31304
StringBuilder: JoelCoehoorn1 Ticks: 49686
Join: JoelCoehoorn1 Ticks: 1344
StringBuilder: TimJ Ticks: 36260
Join: TimJ Ticks: 142233
String: Fredou1 Ticks: 13699
============================================
StringBuilder: MatthewWhited1 Ticks: 882
StringBuilder: MatthewWhited2 Ticks: 581
Join: MatthewWhited1 Ticks: 819
Join: MatthewWhited2 Ticks: 497
String: MatthewWhited3 Ticks: 441
String: MatthewWhited4 Ticks: 441
String: AlanM_1 Ticks: 38535
String: AlanM_2 Ticks: 39312
String: AlanM_3 Ticks: 303254
StringBuilder: AricTenEyck1 Ticks: 2240
StringBuilder: AricTenEyck2 Ticks: 4767
Join: AricTenEyck1 Ticks: 1904
Join: AricTenEyck2 Ticks: 4284
String: Martin1 Ticks: 308
String: Martin2 Ticks: 350
StringBuilder: Martin3 Ticks: 406
Join: Martin3 Ticks: 434
String: JoelCoehoorn2 Ticks: 329
StringBuilder: JoelCoehoorn1 Ticks: 581
Join: JoelCoehoorn1 Ticks: 700
StringBuilder: TimJ Ticks: 672
Join: TimJ Ticks: 1008
String: Fredou1 Ticks: 4256
============================================
StringBuilder: MatthewWhited1 Ticks: 651
StringBuilder: MatthewWhited2 Ticks: 658
Join: MatthewWhited1 Ticks: 875
Join: MatthewWhited2 Ticks: 707
String: MatthewWhited3 Ticks: 588
String: MatthewWhited4 Ticks: 616
String: AlanM_1 Ticks: 40677
String: AlanM_2 Ticks: 39858
String: AlanM_3 Ticks: 26845
StringBuilder: AricTenEyck1 Ticks: 2198
StringBuilder: AricTenEyck2 Ticks: 5096
Join: AricTenEyck1 Ticks: 3563
Join: AricTenEyck2 Ticks: 5285
String: Martin1 Ticks: 336
String: Martin2 Ticks: 469
StringBuilder: Martin3 Ticks: 532
Join: Martin3 Ticks: 777
String: JoelCoehoorn2 Ticks: 329
StringBuilder: JoelCoehoorn1 Ticks: 812
Join: JoelCoehoorn1 Ticks: 840
StringBuilder: TimJ Ticks: 497
Join: TimJ Ticks: 1610
String: Fredou1 Ticks: 9520

Test code

#define OUTPUT_RESULTS_

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Text.RegularExpressions;
using System.IO;
using System.Threading;

namespace StringChop20
{
    //http://stackoverflow.com/questions/1009839/net-split-by-length/
    class Program
    {
        static readonly string s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        static readonly int len = 12;
        static readonly byte[] bytes = Encoding.UTF8.GetBytes("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
        static string logFile = null;

        static void Main(string[] args)
        {
            logFile = "results_" + DateTime.Now.ToString("yyyyMMdd_hhmmss") + ".txt";
            Thread.CurrentThread.Priority = ThreadPriority.Highest;

            for (int i = 0; i < 3; i++)
            {
                WriteLine("============================================");
                RunTestSB(MatthewWhited1);
                RunTestSB(MatthewWhited2);
                RunTestJoin(MatthewWhited1);
                RunTestJoin(MatthewWhited2);
                RunTest(MatthewWhited3);
                RunTest(MatthewWhited4);

                RunTest(AlanM_1);
                RunTest(AlanM_2);
                RunTest(AlanM_3);

                RunTestSB(AricTenEyck1);
                RunTestSB(AricTenEyck2);
                RunTestJoin(AricTenEyck1);
                RunTestJoin(AricTenEyck2);

                RunTest(Martin1);
                RunTest(Martin2);
                RunTestSB(Martin3);
                RunTestJoin(Martin3);

                RunTest(JoelCoehoorn2);
                RunTestSB(JoelCoehoorn1);
                RunTestJoin(JoelCoehoorn1);

                RunTestSB(TimJ);
                RunTestJoin(TimJ);

                RunTest(Fredou1);

                GC.Collect();
                GC.WaitForPendingFinalizers();

            }

            //Console.ReadLine();
        }

        static object _syncLock = new object();
        static void WriteLine(string message)
        {
            lock (_syncLock)
            {
                File.AppendAllText(logFile, message + "\r\n");
                Console.WriteLine(message);
            }
        }

        delegate string MethodRunner();
        delegate IEnumerable OtherRunner();

        static void RunTest(MethodRunner testMethod)
        {
            Stopwatch sw = Stopwatch.StartNew();
            string result = testMethod();
            sw.Stop();
            WriteLine("String: " + testMethod.Method.Name + " Ticks: " + sw.ElapsedTicks.ToString());
#if OUTPUT_RESULTS
            WriteLine(result);
            WriteLine("-----------");
#endif
        }

        static void RunTestJoin(OtherRunner testMethod)
        {
            Stopwatch sw = Stopwatch.StartNew();
            string result = testMethod().WithJoin();
            sw.Stop();
            WriteLine("Join: " + testMethod.Method.Name + " Ticks: " + sw.ElapsedTicks.ToString());
#if OUTPUT_RESULTS
            WriteLine(result);
            WriteLine("-----------");
#endif
        }

        static void RunTestSB(OtherRunner testMethod)
        {
            Stopwatch sw = Stopwatch.StartNew();
            string result = testMethod().WithStringBuilder();
            sw.Stop();
            WriteLine("StringBuilder: " + testMethod.Method.Name + " Ticks: " + sw.ElapsedTicks.ToString());
#if OUTPUT_RESULTS
            WriteLine(result);
            WriteLine("-----------");
#endif
        }

        static IEnumerable MatthewWhited1()
        {
            char[] chopMeArray = s.ToCharArray();
            int totalLength = s.Length;
            int partCount = (totalLength / len) + ((totalLength % len == 0) ? 0 : 1);
            int posIndex = 0;
            char[] part = new char[len];
            string[] parts = new string[partCount];
            int get = len;
            for (int i = 0; i < partCount; i++)
            {
                get = Math.Min(len, totalLength - posIndex);
                Array.Copy(chopMeArray, posIndex, part, 0, get);
                parts[i] = new string(part, 0, get);
                posIndex += len;
            }
            return parts;
        }

        static IEnumerable MatthewWhited2()
        {
            char[] chopMeArray = s.ToCharArray();
            int totalLength = s.Length;
            int partCount = (totalLength / len) + ((totalLength % len == 0) ? 0 : 1);
            int posIndex = 0;
            char[] part = new char[len];
            string[] parts = new string[partCount];
            int get = len;
            for (int i = 0; i < partCount; i++)
            {
                get = Math.Min(len, totalLength - posIndex);
                Array.Copy(chopMeArray, posIndex, part, 0, get);
                yield return new string(part, 0, get);
                posIndex += len;
            }
        }

        static string MatthewWhited3()
        {
            char[] chopMeArray = s.ToCharArray();
            int totalLength = s.Length;
            int partCount = (totalLength / len) + ((totalLength % len == 0) ? 0 : 1);
            int posIndex = 0;
            char[] part = new char[len];
            string[] parts = new string[partCount];
            int get = len;
            for (int i = 0; i < partCount; i++)
            {
                get = Math.Min(len, totalLength - posIndex);
                Array.Copy(chopMeArray, posIndex, part, 0, get);
                parts[i] = new string(part, 0, get);
                posIndex += len;
            }
            return string.Join("\r\n", parts) + "\r\n";
        }

        static string MatthewWhited4()
        {
            char[] chopMeArray = s.ToCharArray();
            int totalLength = s.Length;
            int partCount = (totalLength / len) + ((totalLength % len == 0) ? 0 : 1);
            int posIndex = 0;
            char[] part = new char[len];
            StringBuilder sb = new StringBuilder();
            int get = len;
            for (int i = 0; i < partCount; i++)
            {
                get = Math.Min(len, totalLength - posIndex);
                Array.Copy(chopMeArray, posIndex, part, 0, get);
                sb.AppendLine(new string(part, 0, get));
                posIndex += len;
            }
            return sb.ToString();
        }

        static string AlanM_1()
        {
            return Regex.Replace(s, @"(?<=\G.{12})", "\r\n");
        }

        static Regex rx0 = new Regex(@"(?<=\G.{12})");
        static string AlanM_2()
        {
            return rx0.Replace(s, "\r\n");
        }

        static Regex rx1 = new Regex(".{12}");
        static string AlanM_3()
        {
            return Regex.Replace(s, @"(?<=\G.{12})", "\r\n");
        }

        static IEnumerable AricTenEyck1()
        {
            List output = new List();
            string s2 = s;
            while (s2.Length > len)
            {
                output.Add(s2.Substring(0, len) + "\n");

                //Aric I had to change this next line 
                // to add the asignement (or else this was an infinate loop
                s2 = s2.Remove(0, len);
            }
            //this would add an extra blank line
            output.Add(s2 + "\n");

            return output;
        }

        //I added a Iterator version for you as well
        static IEnumerable AricTenEyck2()
        {
            string s2 = s;
            while (s2.Length > len)
            {
                yield return s2.Substring(0, len) + "\n";
                s2 = s2.Remove(0, len);
            }
            yield return s2+ "\n";
        }

        static string Martin1()
        {
            StringBuilder sb = new StringBuilder(s.Length + (int)(s.Length / len) + 1);
            int start = 0;
            for (start = 0; start < s.Length - len; start += len)
            {
                sb.Append(s.Substring(start, len));
                sb.Append("\n");
            }
            sb.Append(s.Substring(start));
            return sb.ToString();
        }

        //Martin I added this version to match with the others
        static string Martin2()
        {
            StringBuilder sb = new StringBuilder(s.Length + (int)(s.Length / len) + 1);
            int start = 0;
            for (start = 0; start < s.Length - len; start += len)
                sb.AppendLine(s.Substring(start, len));
            sb.AppendLine(s.Substring(start));
            return sb.ToString();
        }

        //Martin I added this version to match with the others
        static IEnumerable Martin3()
        {
            StringBuilder sb = new StringBuilder(s.Length + (int)(s.Length / len) + 1);
            int start = 0;
            for (start = 0; start < s.Length - len; start += len)
                yield return s.Substring(start, len);
            yield return s.Substring(start);
        }

        static string SLaks()
        {
            return Convert.ToBase64String(bytes, Base64FormattingOptions.InsertLineBreaks);
        }

        static IEnumerable JoelCoehoorn1()
        {
            var buf = new char[len];
            using (var rdr = new StringReader(s))
            {
                int l;
                l = rdr.ReadBlock(buf, 0, len);
                while (l > 0)
                {
                    yield return (new string(buf, 0, l)) + Environment.NewLine;
                    l = rdr.ReadBlock(buf, 0, len);
                }
            }
        }

        static string JoelCoehoorn2()
        {
            char[] buf = new char[s.Length + (int)Math.Ceiling(s.Length / (double)len)];
            using (var rdr = new StringReader(s))
            {
                for (int i = 0; i < buf.Length - len; i++)
                {
                    rdr.ReadBlock(buf, i, len);
                    i += len; buf[i] = '\n';
                    if (i < s.Length)
                        rdr.ReadBlock(buf, i, s.Length - i); buf[buf.Length - 1] = '\n';
                }
            }
            return new string(buf);
        }

        static IEnumerable TimJ()
        {
            int i = 0; while (i < s.Length)
            {
                yield return i + len <= s.Length ? s.Substring(i, len) : s.Substring(i);
                i += len;
            }
        }

        static string Fredou1()
        {
            var s2 = s;
            StringBuilder n = new StringBuilder(); int chopSize = 0;
            while (!string.IsNullOrEmpty(s2))
            {
                chopSize = s2.Length > len ? len : s2.Length;
                n.Append(s2.Substring(0, chopSize) + "\r\n");
                s2 = s2.Remove(0, chopSize);
            }
            return n.ToString();
        }

    }

    // for Robert and others that are interested in the 
    // string.Join v. StringBuilder I will test both of these
    public static class Extensions
    {
        public static string WithJoin(this IEnumerable input)
        {
            return string.Join("\r\n", input.ToArray()) + "\r\n";
        }

        public static string WithStringBuilder(this IEnumerable input)
        {
            var sb = new StringBuilder();
            foreach (var item in input)
                sb.AppendLine(item);
            return sb.ToString();
        }
    }
}

Tags: , ,

Programming

Comments are closed

Powered by BlogEngine.NET 1.5.0.7
Theme by Mads Kristensen

RecentPosts

Badges