{"id":163,"date":"2022-02-20T22:50:01","date_gmt":"2022-02-20T22:50:01","guid":{"rendered":"https:\/\/baldsolutions.com\/?p=163"},"modified":"2022-03-12T11:48:56","modified_gmt":"2022-03-12T11:48:56","slug":"linq-vs-plinq-speedup-your-query","status":"publish","type":"post","link":"https:\/\/baldsolutions.com\/index.php\/2022\/02\/20\/linq-vs-plinq-speedup-your-query\/","title":{"rendered":"LINQ vs PLINQ &#8211; speed up your query"},"content":{"rendered":"\n<h1 class=\"wp-block-heading\" id=\"introduction\">Introduction<\/h1>\n\n\n\n<p>Have you ever used LINQ? If you are a dotnet developer, then I&#8217;m sure you have as it is probably the most well know way to work with your data source. Sometimes your LINQ operations might take more time than you actually expect. One of the possible solutions is to use something that is named PLINQ. The &#8220;P&#8221; letter stands for one of the most powerful word in the field of computer science (drumroll) &#8211; PARALLEL. In this article I will show you how you can speed up your LINQ query by using PLINQ.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"linq\">LINQ<\/h1>\n\n\n\n<p>If you have never used LINQ let me give you quick and simple explanation. Long story shorts, the <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/csharp\/programming-guide\/concepts\/linq\/\" target=\"_blank\" rel=\"noreferrer noopener\" title=\"LINQ\">LINQ<\/a> is a library that helps you to write queries against data source. You can use it for any collection of objects that supports&nbsp;<a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.collections.ienumerable\" target=\"_blank\" rel=\"noreferrer noopener\">IEnumerable<\/a>&nbsp;or the generic&nbsp;<a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.collections.generic.ienumerable-1\" target=\"_blank\" rel=\"noreferrer noopener\">IEnumerable&lt;T&gt;<\/a>&nbsp;interface. There are two syntaxes you can use: query-syntax and method-syntax. To be honest, the method-syntax is much more readable for me, but of course it&#8217;s up to you which one you&#8217;ll use (<a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/csharp\/programming-guide\/concepts\/linq\/query-syntax-and-method-syntax-in-linq#standard-query-operator-extension-methods\" target=\"_blank\" rel=\"noreferrer noopener\" title=\"here\">here<\/a> are some docs regarding the syntax). LINQ offers many <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/csharp\/programming-guide\/concepts\/linq\/basic-linq-query-operations\" target=\"_blank\" rel=\"noreferrer noopener\" title=\"operations\">operations<\/a> you can use such as filtering, ordering, grouping, joining and so on.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"plinq\">PLINQ<\/h1>\n\n\n\n<p>I don&#8217;t try to give my own explanation as the one from the <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/standard\/parallel-programming\/introduction-to-plinq\" target=\"_blank\" rel=\"noreferrer noopener\" title=\"docs\">docs<\/a> looks pretty neat and concise: &#8220;Parallel LINQ (PLINQ) is a parallel implementation of the&nbsp;<a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/csharp\/programming-guide\/concepts\/linq\/\" target=\"_blank\" rel=\"noreferrer noopener\">Language-Integrated Query (LINQ)<\/a>&nbsp;pattern. PLINQ implements the full set of LINQ standard query operators as extension methods for the&nbsp;<a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.linq\" target=\"_blank\" rel=\"noreferrer noopener\">System.Linq<\/a>&nbsp;namespace and has additional operators for parallel operations. PLINQ combines the simplicity and readability of LINQ syntax with the power of parallel programming.&#8221;<\/p>\n\n\n\n<p>Anything that is parallel sounds like the potential performance booster. Bare in mind the cost of parallelization. It is highly possible that PLINQ will execute slower than its LINQ counterpart (I encourage to read the <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/standard\/parallel-programming\/understanding-speedup-in-plinq\" target=\"_blank\" rel=\"noreferrer noopener\" title=\"Understanding Speedup in PLINQ\">Understanding Speedup in PLINQ<\/a>).<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"linq-vs-plinq-benchmark\">LINQ vs PLINQ &#8211; benchmark<\/h1>\n\n\n\n<p>Let&#8217;s consider the following code snippets:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public double SelectLINQ() =&gt;\n     _list\n        .Select(x =&gt; Math.Sqrt(x))\n        .Select(x =&gt; Math.Tan(x))\n        .Select(x =&gt; Math.Cos(x))\n        .Select(x =&gt; Math.Sin(x))\n        .Select(x =&gt; Math.Log10(x))\n        .Max();\n\npublic double SelectPLINQ(int degree) =&gt;\n    _list\n        .AsParallel()\n        .WithDegreeOfParallelism(degree)\n        .Select(x =&gt; Math.Sqrt(x))\n        .Select(x =&gt; Math.Tan(x))\n        .Select(x =&gt; Math.Cos(x))\n        .Select(x =&gt; Math.Sin(x))\n        .Select(x =&gt; Math.Log10(x))\n        .Max();<\/code><\/pre>\n\n\n\n<p>As you can see, executing PLINQ is as simple as adding the <code>.AsParallel()<\/code> invocation. <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.linq.parallelenumerable.withdegreeofparallelism\" target=\"_blank\" rel=\"noreferrer noopener\">WithDegreeOfParallelism<\/a> is PLINQ-specific part that specifies the maximum number of processors that PLINQ should use to parallelize the query. Both methods do exactly the same. Let&#8217;s look at the benchmark:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"563\" height=\"238\" src=\"https:\/\/baldsolutions.com\/wp-content\/uploads\/2022\/02\/image-5.png\" alt=\"\" class=\"wp-image-171\" srcset=\"https:\/\/baldsolutions.com\/wp-content\/uploads\/2022\/02\/image-5.png 563w, https:\/\/baldsolutions.com\/wp-content\/uploads\/2022\/02\/image-5-300x127.png 300w\" sizes=\"auto, (max-width: 563px) 100vw, 563px\" \/><\/figure><\/div>\n\n\n\n<p>The benchmark&#8217;s been executed for the 10_000_000 elements collection  and for different degrees of parallelism (degree of parallelism concerns only PLINQ). As you can see, by using PLINQ the execution times drops down almost three times for the particular degree of parallelism (1420.2 ms vs 496.9 ms).  My machine has 4 logical and 4 physical cores (no hyperthreading) so it makes sense that for degree = 4 the results are the best.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"summary\">Summary<\/h1>\n\n\n\n<p>To sum up, PLINQ is an interesting solution when it comes to decrease the LINQ execution time. The benchmark shows that the such a tiny code adjustment would decrease the execution time almost three times. Keep in mind that PLINQ is not always a solution and it might introduce additional overhead that entails the worse performance. PLINQ works well as long as used correctly. Probably the best approach is to try the PLINQ and test your code by using simple benchmark.<\/p>\n\n\n\n<p>As always I&#8217;ve prepared an example and you can find it on my <a href=\"https:\/\/github.com\/tglowka\/baldsolutions\/tree\/master\/.NET\" target=\"_blank\" rel=\"noreferrer noopener\" title=\"github\">github<\/a>, project: <a href=\"https:\/\/github.com\/tglowka\/baldsolutions\/tree\/master\/.NET\/LINQ-vs-PLINQ\" target=\"_blank\" rel=\"noreferrer noopener\">LINQ-vs-PLINQ<\/a>, test project: <a href=\"https:\/\/github.com\/tglowka\/baldsolutions\/tree\/master\/.NET\/LINQ-vs-PLINQ-tests\" target=\"_blank\" rel=\"noreferrer noopener\">LINQ-vs-PLINQ-tests<\/a>, benchmark project: <a href=\"https:\/\/github.com\/tglowka\/baldsolutions\/tree\/master\/.NET\/LINQ-vs-PLINQ-benchmark\" target=\"_blank\" rel=\"noreferrer noopener\">LINQ-vs-PLINQ-benchmark<\/a>. I encourage you to go through the code, debug it and try to test your own scenarios.<\/p>\n\n\n\n<p>Have a nice day, bye!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction Have you ever used LINQ? If you are a dotnet developer, then I&#8217;m sure you have as it is probably the most well know&#8230;<\/p>\n<div class=\"more-link-wrapper\"><a class=\"more-link\" href=\"https:\/\/baldsolutions.com\/index.php\/2022\/02\/20\/linq-vs-plinq-speedup-your-query\/\">Continue reading<span class=\"screen-reader-text\">LINQ vs PLINQ &#8211; speed up your query<\/span><\/a><\/div>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[2],"tags":[],"class_list":["post-163","post","type-post","status-publish","format-standard","hentry","category-net","entry"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/baldsolutions.com\/index.php\/wp-json\/wp\/v2\/posts\/163","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/baldsolutions.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/baldsolutions.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/baldsolutions.com\/index.php\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/baldsolutions.com\/index.php\/wp-json\/wp\/v2\/comments?post=163"}],"version-history":[{"count":32,"href":"https:\/\/baldsolutions.com\/index.php\/wp-json\/wp\/v2\/posts\/163\/revisions"}],"predecessor-version":[{"id":212,"href":"https:\/\/baldsolutions.com\/index.php\/wp-json\/wp\/v2\/posts\/163\/revisions\/212"}],"wp:attachment":[{"href":"https:\/\/baldsolutions.com\/index.php\/wp-json\/wp\/v2\/media?parent=163"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/baldsolutions.com\/index.php\/wp-json\/wp\/v2\/categories?post=163"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/baldsolutions.com\/index.php\/wp-json\/wp\/v2\/tags?post=163"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}