Skip to main content
fixing code
Source Link
codekaizen
  • 27.4k
  • 7
  • 87
  • 141
class Program { private const int ElementCount = 10000000; static void Main(string[] args) { var str = generateString(); var stopwatch = new Stopwatch(); var list1 = new List<int>(ElementCount); var list2 = new List<int>(ElementCount); var split = str.Split(';'); stopwatch.Start(); list1.AddRange(split .Select(ToInt32OrNull) .Where(i => i != null) .Cast<int>()); stopwatch.Stop(); TimeSpan nonParallel = stopwatch.Elapsed; stopwatch.Restart(); list1list2.AddRange(split .AsParallel() .Select(ToInt32OrNull) .Where(i => i != null) .Cast<int>()); stopwatch.Stop(); TimeSpan parallel = stopwatch.Elapsed; Debug.WriteLine("Non-parallel: {0}", nonParallel); Debug.WriteLine("Parallel: {0}", parallel); } private static String generateString() { var builder = new StringBuilder(1048576); var rnd = new Random(); for (int i = 0; i < ElementCount; i++) { builder.Append(rnd.Next(99999)); builder.Append(';'); } builder.Length--; return builder.ToString(); } static int? ToInt32OrNull(string s) { int value; return (Int32.TryParse(s, out value)) ? value : default(int?); } } 
class Program { private const int ElementCount = 10000000; static void Main(string[] args) { var str = generateString(); var stopwatch = new Stopwatch(); var list1 = new List<int>(ElementCount); var list2 = new List<int>(ElementCount); var split = str.Split(';'); stopwatch.Start(); list1.AddRange(split .Select(ToInt32OrNull) .Where(i => i != null) .Cast<int>()); stopwatch.Stop(); TimeSpan nonParallel = stopwatch.Elapsed; stopwatch.Restart(); list1.AddRange(split .AsParallel() .Select(ToInt32OrNull) .Where(i => i != null) .Cast<int>()); stopwatch.Stop(); TimeSpan parallel = stopwatch.Elapsed; Debug.WriteLine("Non-parallel: {0}", nonParallel); Debug.WriteLine("Parallel: {0}", parallel); } private static String generateString() { var builder = new StringBuilder(1048576); var rnd = new Random(); for (int i = 0; i < ElementCount; i++) { builder.Append(rnd.Next(99999)); builder.Append(';'); } builder.Length--; return builder.ToString(); } static int? ToInt32OrNull(string s) { int value; return (Int32.TryParse(s, out value)) ? value : default(int?); } } 
class Program { private const int ElementCount = 10000000; static void Main(string[] args) { var str = generateString(); var stopwatch = new Stopwatch(); var list1 = new List<int>(ElementCount); var list2 = new List<int>(ElementCount); var split = str.Split(';'); stopwatch.Start(); list1.AddRange(split .Select(ToInt32OrNull) .Where(i => i != null) .Cast<int>()); stopwatch.Stop(); TimeSpan nonParallel = stopwatch.Elapsed; stopwatch.Restart(); list2.AddRange(split .AsParallel() .Select(ToInt32OrNull) .Where(i => i != null) .Cast<int>()); stopwatch.Stop(); TimeSpan parallel = stopwatch.Elapsed; Debug.WriteLine("Non-parallel: {0}", nonParallel); Debug.WriteLine("Parallel: {0}", parallel); } private static String generateString() { var builder = new StringBuilder(1048576); var rnd = new Random(); for (int i = 0; i < ElementCount; i++) { builder.Append(rnd.Next(99999)); builder.Append(';'); } builder.Length--; return builder.ToString(); } static int? ToInt32OrNull(string s) { int value; return (Int32.TryParse(s, out value)) ? value : default(int?); } } 
adding perf update
Source Link
codekaizen
  • 27.4k
  • 7
  • 87
  • 141

Performance Update:

Performance of LINQ has been quesioned below. While in the comments the idea of LINQ being slower is defended since we gain the benefits of readability, maintainability and composibility, there is another aspect which gives LINQ an easy performance advantage: parallelism. Here is an example where adding just one extension method call, AsParallel() doubles the performance. This is a great example of where scale-out beats micro-optimization without even needing to measure very carefully. Note I'm not claiming that micro-optimizations are not ever needed, but with the tools we have available at this level of absraction, the need becomes vanishingly small.

class Program { private const int ElementCount = 10000000; static void Main(string[] args) { var str = generateString(); var stopwatch = new Stopwatch(); var list1 = new List<int>(ElementCount); var list2 = new List<int>(ElementCount); var split = str.Split(';'); stopwatch.Start(); list1.AddRange(split .Select(ToInt32OrNull) .Where(i => i != null) .Cast<int>()); stopwatch.Stop(); TimeSpan nonParallel = stopwatch.Elapsed; stopwatch.Restart(); list1.AddRange(split .AsParallel() .Select(ToInt32OrNull) .Where(i => i != null) .Cast<int>()); stopwatch.Stop(); TimeSpan parallel = stopwatch.Elapsed; Debug.WriteLine("Non-parallel: {0}", nonParallel); Debug.WriteLine("Parallel: {0}", parallel); } private static String generateString() { var builder = new StringBuilder(1048576); var rnd = new Random(); for (int i = 0; i < ElementCount; i++) { builder.Append(rnd.Next(99999)); builder.Append(';'); } builder.Length--; return builder.ToString(); } static int? ToInt32OrNull(string s) { int value; return (Int32.TryParse(s, out value)) ? value : default(int?); } } 

Non-parallel: 00:00:07.0719911

Parallel: 00:00:04.5933906

Performance Update:

Performance of LINQ has been quesioned below. While in the comments the idea of LINQ being slower is defended since we gain the benefits of readability, maintainability and composibility, there is another aspect which gives LINQ an easy performance advantage: parallelism. Here is an example where adding just one extension method call, AsParallel() doubles the performance. This is a great example of where scale-out beats micro-optimization without even needing to measure very carefully. Note I'm not claiming that micro-optimizations are not ever needed, but with the tools we have available at this level of absraction, the need becomes vanishingly small.

class Program { private const int ElementCount = 10000000; static void Main(string[] args) { var str = generateString(); var stopwatch = new Stopwatch(); var list1 = new List<int>(ElementCount); var list2 = new List<int>(ElementCount); var split = str.Split(';'); stopwatch.Start(); list1.AddRange(split .Select(ToInt32OrNull) .Where(i => i != null) .Cast<int>()); stopwatch.Stop(); TimeSpan nonParallel = stopwatch.Elapsed; stopwatch.Restart(); list1.AddRange(split .AsParallel() .Select(ToInt32OrNull) .Where(i => i != null) .Cast<int>()); stopwatch.Stop(); TimeSpan parallel = stopwatch.Elapsed; Debug.WriteLine("Non-parallel: {0}", nonParallel); Debug.WriteLine("Parallel: {0}", parallel); } private static String generateString() { var builder = new StringBuilder(1048576); var rnd = new Random(); for (int i = 0; i < ElementCount; i++) { builder.Append(rnd.Next(99999)); builder.Append(';'); } builder.Length--; return builder.ToString(); } static int? ToInt32OrNull(string s) { int value; return (Int32.TryParse(s, out value)) ? value : default(int?); } } 

Non-parallel: 00:00:07.0719911

Parallel: 00:00:04.5933906

adding cast
Source Link
codekaizen
  • 27.4k
  • 7
  • 87
  • 141
static int? ToInt32OrNull(string s) { int value; return (Int32.TryParse(s, out value)) ? value : default(int?); } // ... var str = "123;3344;4334;12"; var list = new List<int>(); list.AddRange(str.Split(';') .Select(ToInt32OrNull) .Where(i => i != null) .Cast<int>()); 

Questioner notes:

I don't know of a good way here other than to split in a loop and do a conversion then add to a List

In general, this is a major reason why LINQ was brought into C# - to remove the need to work with sequences of values by implementing loops, and instead just declare your intention to transform the sequence. If you ever find yourself thinking "I don't know how to do this except with a loop" - it's time to look into a LINQ construct which will do the work for you.

static int? ToInt32OrNull(string s) { int value; return (Int32.TryParse(s, out value)) ? value : default(int?); } // ... var str = "123;3344;4334;12"; var list = new List<int>(); list.AddRange(str.Split(';').Select(ToInt32OrNull).Where(i => i != null)); 

Questioner notes:

I don't know of a good way here other than to split in a loop and do a conversion then add to a List

In general, this is a major reason why LINQ was brought into C# - to remove the need to work with sequences of values by implementing loops, and instead just declare your intention to transform the sequence. If you ever find yourself thinking "I don't know how to do this except with a loop" - it's time to look into a LINQ construct which will do the work for you.

static int? ToInt32OrNull(string s) { int value; return (Int32.TryParse(s, out value)) ? value : default(int?); } // ... var str = "123;3344;4334;12"; var list = new List<int>(); list.AddRange(str.Split(';') .Select(ToInt32OrNull) .Where(i => i != null) .Cast<int>()); 

Questioner notes:

I don't know of a good way here other than to split in a loop and do a conversion then add to a List

In general, this is a major reason why LINQ was brought into C# - to remove the need to work with sequences of values by implementing loops, and instead just declare your intention to transform the sequence. If you ever find yourself thinking "I don't know how to do this except with a loop" - it's time to look into a LINQ construct which will do the work for you.

fixing code
Source Link
codekaizen
  • 27.4k
  • 7
  • 87
  • 141
Loading
wtf
Source Link
codekaizen
  • 27.4k
  • 7
  • 87
  • 141
Loading
adding exposition about linq
Source Link
codekaizen
  • 27.4k
  • 7
  • 87
  • 141
Loading
Source Link
codekaizen
  • 27.4k
  • 7
  • 87
  • 141
Loading