{"id":55991,"date":"2012-11-16T17:19:25","date_gmt":"2012-11-16T17:19:25","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/pfxteam\/2012\/11\/16\/plinq-and-int32-maxvalue\/"},"modified":"2012-11-16T17:19:25","modified_gmt":"2012-11-16T17:19:25","slug":"plinq-and-int32-maxvalue","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/plinq-and-int32-maxvalue\/","title":{"rendered":"PLINQ and Int32.MaxValue"},"content":{"rendered":"<p>In both .NET 4 and .NET 4.5, PLINQ supports enumerables with up to Int32.MaxValue elements.&nbsp; Beyond that limit, PLINQ will throw an overflow exception.&nbsp; LINQ to Objects itself has this limitation with certain query operators (such as the indexed Select operator which counts the elements processed), but PLINQ has it with more.<\/p>\n<p>This limitation impacts so few scenarios that it&rsquo;s relatively benign and I rarely hear about it.&nbsp; That said, it does come up now and again, and I was in fact asked about it earlier this week.&nbsp; So, to help in case anyone else runs into this&hellip;<\/p>\n<p>There is a relatively straightforward workaround you can apply if you do run up against this limit: ensure the enumerable passed to PLINQ has no more than Int32.MaxValue.&nbsp; That answer might sound flippant and impractical, but in reality it&rsquo;s often easily accomplished by batching a longer enumerable into multiple shorter enumerables, where none of the shorter enumerables exceed the limit.<\/p>\n<p>Consider a basic query like the following:<\/p>\n<blockquote>\n<p><font face=\"Consolas\">IEnumerable&lt;Output&gt; outputs =        <br>&nbsp;&nbsp;&nbsp; from input in inputs.AsParallel()         <br>&nbsp;&nbsp;&nbsp; where Filter(input)        <br>&nbsp;&nbsp;&nbsp; select Map(input);<\/font><\/p>\n<\/blockquote>\n<p>If the <em>inputs<\/em> enumerable has more than Int32.MaxValue elements, this will result in an overflow.&nbsp; To workaround this, imagine if we had a <em>Batch<\/em> extension method for IEnumerable&lt;T&gt; that would partition the IEnumerable&lt;T&gt; into multiple sequential IEnumerable&lt;T&gt; instances, each of which had no more than Int32.MaxValue elements.&nbsp; With that, we could rewrite this as follows:<\/p>\n<blockquote>\n<p><font face=\"Consolas\">IEnumerable&lt;Output&gt; outputs = inputs.Batch(Int32.MaxValue).SelectMany(batch =&gt;       <br>&nbsp;&nbsp;&nbsp; from input in batch.AsParallel()         <br>&nbsp;&nbsp;&nbsp; where Filter(input)        <br>&nbsp;&nbsp;&nbsp; select Map(input)        <br>);<\/font><\/p>\n<\/blockquote>\n<p>The original query remains intact, except that instead of operating on the original <em>inputs<\/em> enumerable, it&rsquo;s operating on the new <em>batch<\/em> enumerable, which is a subset provided by the Batch method.&nbsp; We&rsquo;ll now be parallelizing our processing of each sequential batch, moving on to the next batch to be processed in parallel once we finish the previous one.<\/p>\n<p>Such a <em>Batch<\/em> method doesn&rsquo;t actually exist built-in to .NET 4.5, but writing one is relatively straightforward.&nbsp; Here&rsquo;s one implementation which you could customize as your needs demand:<\/p>\n<blockquote>\n<p><font face=\"Consolas\">static class MyLinqExtensions       <br>{        <br>&nbsp;&nbsp;&nbsp; public static IEnumerable&lt;IEnumerable&lt;T&gt;&gt; Batch&lt;T&gt;(        <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this IEnumerable&lt;T&gt; source, int batchSize)        <br>&nbsp;&nbsp;&nbsp; {        <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; using (var enumerator = source.GetEnumerator())        <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (enumerator.MoveNext())        <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; yield return YieldBatchElements(enumerator, batchSize &#8211; 1);        <br>&nbsp;&nbsp;&nbsp; }        <\/p>\n<p>&nbsp;&nbsp;&nbsp; private static IEnumerable&lt;T&gt; YieldBatchElements&lt;T&gt;(        <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IEnumerator&lt;T&gt; source, int batchSize)        <br>&nbsp;&nbsp;&nbsp; {        <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; yield return source.Current;        <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; batchSize &amp;&amp; source.MoveNext(); i++)        <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; yield return source.Current;        <br>&nbsp;&nbsp;&nbsp; }        <br>}<\/font><\/p>\n<\/blockquote>\n","protected":false},"excerpt":{"rendered":"<p>In both .NET 4 and .NET 4.5, PLINQ supports enumerables with up to Int32.MaxValue elements.&nbsp; Beyond that limit, PLINQ will throw an overflow exception.&nbsp; LINQ to Objects itself has this limitation with certain query operators (such as the indexed Select operator which counts the elements processed), but PLINQ has it with more. This limitation impacts [&hellip;]<\/p>\n","protected":false},"author":360,"featured_media":58792,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[7908],"tags":[7907,7925,7909,7910],"class_list":["post-55991","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-pfxteam","tag-net-4","tag-net-4-5","tag-parallel-extensions","tag-plinq"],"acf":[],"blog_post_summary":"<p>In both .NET 4 and .NET 4.5, PLINQ supports enumerables with up to Int32.MaxValue elements.&nbsp; Beyond that limit, PLINQ will throw an overflow exception.&nbsp; LINQ to Objects itself has this limitation with certain query operators (such as the indexed Select operator which counts the elements processed), but PLINQ has it with more. This limitation impacts [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/55991","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/360"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=55991"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/55991\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/58792"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=55991"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=55991"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=55991"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}