{"id":15036156,"url":"https://github.com/jackmott/linqfaster","last_synced_at":"2025-05-15T17:02:06.619Z","repository":{"id":41278189,"uuid":"86279947","full_name":"jackmott/LinqFaster","owner":"jackmott","description":"Linq-like extension functions for Arrays, Span\u003cT\u003e, and List\u003cT\u003e that are faster and allocate less.","archived":false,"fork":false,"pushed_at":"2020-05-05T09:53:10.000Z","size":487,"stargazers_count":749,"open_issues_count":16,"forks_count":35,"subscribers_count":35,"default_branch":"master","last_synced_at":"2024-05-28T14:30:45.544Z","etag":null,"topics":["allocation","csharp-library","gamedev-library","linq","perfromance","simd"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jackmott.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-03-27T01:56:54.000Z","updated_at":"2024-05-26T03:41:08.000Z","dependencies_parsed_at":"2022-07-14T11:30:43.182Z","dependency_job_id":null,"html_url":"https://github.com/jackmott/LinqFaster","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jackmott%2FLinqFaster","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jackmott%2FLinqFaster/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jackmott%2FLinqFaster/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jackmott%2FLinqFaster/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jackmott","download_url":"https://codeload.github.com/jackmott/LinqFaster/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247737788,"owners_count":20987721,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["allocation","csharp-library","gamedev-library","linq","perfromance","simd"],"created_at":"2024-09-24T20:30:21.989Z","updated_at":"2025-04-07T22:07:06.144Z","avatar_url":"https://github.com/jackmott.png","language":"C#","readme":"![Build Status](https://ci.appveyor.com/api/projects/status/github/jackmott/LinqFaster \"Build Status\")\n\n# LinqFaster  \n\n![Logo](https://jackmott.github.io/images/LinqFaster.png \"Logo\")\n\nA set of Linq-Like extension methods for `arrays[]`, `Span\u003cT\u003e`, and `List\u003cT\u003e` that are faster and allocate less.  LinqFaster is designed\nto work well alongside Linq, rather than replace it completely. Extension method names mirror Linq names with an extra character, e.g. Select**F**.  If you have code that is often doing small Linq operations and immediatelly calling `ToArray()` or `ToList()`, or you are often using `Min`,`Max`,`Sum`,`Average`,or `Aggregate`, LinqFaster may provide massive cpu and memory usage reductions. See the documentation section below for more details.\n\nLinqFaster now includes all relevant Linq extension methods, and many **SIMD** and **Parallel** enhanced extension methods are available as well in separate projects and nuget packages.  The projects have no dependencies on each other so you can pick and choose at will.\n\nThe base LinqFaster project is now compatible with Unity3D\n\n## [Now available on Nuget](https://www.nuget.org/packages?q=linqfaster)\n\n# Sample Benchmarks\n\n64bit Win 10, 2 Core I7 Mobile\n\n |             Method | TEST_SIZE |           Mean | Allocated |\n |------------------- |---------- |--------------- |---------- |\n |        OrderByLinq |    100000 | 24,436.0135 us |    1.2 MB |\n |        OrderByFast |    100000 |  5,612.7712 us |  802.1 kB |\n |            MinLinq |    100000 |    548.9181 us |      48 B |\n |            MinFast |    100000 |     69.2122 us |       0 B |\n |        MinFastSIMD |    100000 |     14.5291 us |       0 B |\n |            SumLinq |    100000 |    541.3823 us |      48 B |\n |            SumFast |    100000 |     53.8166 us |       0 B |\n |        SumFastSIMD |    100000 |      9.7636 us |       0 B |\n |SumFastSIMDParallel |    100000 |      3.7074 us |   1.11 kB |\n\n\nMore detailed info and benchmarks available in the **[benchmarks](Benchmarks.md)**  file which\nwill be continually updated.\n\n\n# Features\n\n* **SIMD** enhanced array operations\n* :arrow_down: Execution time\n* :arrow_down: GC churn\n* :arrow_up: Battery life\n* :arrow_down: Sever farm costs\n* :arrow_down: Co2 output\n* :arrow_down: Electricity bill\n* :arrow_up: L1 cache hits\n* :arrow_up: FPS!\n\n# Documentation\n\n* [LinqFaster](#linqfaster-1)\n* [LinqFaster.SIMD](#linqfastersimd)\n* [LinqFaster.Parallel](#linqfasterparallel)\n* [LinqFaster.SIMD.Parallel](#linqfastersimdparallel)\n* [Limitations](#limitations)\n\nAs well, all functions are properly documented so as to be explorable via intellisense.\n\n### LinqFaster\n```c#\n\tusing JM.LinqFaster;\n\t\n\t\n\t//Create an array of ints with values -500 to 500\n\tvar myArray = LinqFaster.RangeArrayF(-500, 1000);\n\t//Create a List\u003cT\u003e with 1000 elements all set to 5.0\n\tvar myList = LinqFaster.RepeatListF(5.0, 1000);\n\n\t//Compute sum, average, max,min\n\tvar sum = myArray.SumF();\n\tvar average = myArray.AverageF();\n\tvar min = myArray.MinF();\n\tvar max = myArray.MaxF();\n\t\n\t// Compute the sum of a slice of your array using Span\u003cT\u003e\n\t// LinqFaster includes a handy extension method to make slices easier\n\tvar sliceSum = myArray.Slice(10,20).SumF();\n\n\t//As above but on a transformation\n\tvar sum2 = myArray.SumF(x =\u003e x*x);\n\tvar average2 = myArray.AverageF(x =\u003e x*x);\n\tvar min2 = myArray.MinF(x =\u003e x*x);\n\tvar max2 = myArray.MaxF(x =\u003e x*x);\n\n\t//Do a where and a select or select and where in a single pass\n\tvar newArray = myArray.WhereSelectF(x =\u003e x % 2 == 0,x=\u003ex*x);\n\tvar newArray2 = myArray.SelectWhereF(x =\u003e x * x,x =\u003e x % 2 == 0);\n\n\t//Compute the sum of only the even values in a single pass\n\tvar filteredSum = myArray.WhereAggregateF(x =\u003e x % 2 == 0, (acc, x) =\u003e acc + x);\n\n\t//New in-place methods are provided where appropriate\n\tmyArray.SelectInPlaceF(x =\u003e x * x);\n\tmyArray.ReverseInPlaceF();\n```\n\n### LinqFaster.SIMD\n\nSee MSDN [documentation](https://msdn.microsoft.com/en-us/library/dn858385(v=vs.111).aspx) on System.Numerics.Vectors\nfor more detail on SIMD in C#.\n\n```c#\nusing JM.LinqFaster.SIMD;\n\n// SIMD extension methods are only available for arrays\n// SIMD functions all have an S at the end, for clarity\n// and to avoid naming collisions.\n\nvar myArray = LinqFaster.RangeS(-500, 500);\n\n// Some operations work identically to their scalar\n// counterparts,but faster, as long as the machine has \n// SIMD hardware.\n\nvar sum = myArray.SumS();\nbool b = myArray.ContainsS(5);\nvar max = myArray.MaxS();\n\n// Floating point math is not commutative, so the results\n// of operations such as Sum and Average may differ slightly.\n// Accuracy is usually better.\n\nConsole.WriteLine(myFloats.SumS() == myFloats.SumF()); // --\u003e False!\n\n// When using selectors, you must provide one that operates on\n// Vector\u003cT\u003e. Optionally, you may provide a second selector\n// that operates on T to handle elements that are left over, \n// when your array is not evenly divisible by the Vector width.\n\n// When there will be no leftovers\nvar sum = myArray.SumS( x =\u003e x*x );   // Vector\u003cT\u003e has overrides for *, + etc\n\n// When there will be leftovers\nvar sum = myArray.SumS(x=\u003ex*x, x=\u003ex*x); \n\n// As with the regular LinqFaster project, SIMD includes\n// in place versions when appropriate:\n\nmyArray.SelectInPlaceS( v =\u003e v + new Vector(1));\n\n\n\n```\n\n### LinqFaster.Parallel\n\n```c#\n\nusing JM.LinqFaster.Parallel;\n\n// Parallel extension methods are all named with a P \n// at the end.\n\nvar sum = myList.SumP();\n\n// Floating point math is not commutative, so the results\n// of operations such as Sum and Average may differ slightly.\n// Accuracy is usually better.\n\nConsole.WriteLine(myFloats.SumP() == myFloats.SumF()); // --\u003e False!\n\n// In some cases, unordered versions of a function are provided for\n// better performance\n\nmyList.SelectUnorderedP(x =\u003e x*x);  \n\n// All parallel functions have an optional batch size, which\n// defines how many elements are operated on per task/thread.\n// This can be tuned for performance.\n\nmyArray.Select(x=\u003ex*x,myArray.Length/10);  //split the array into 10 ranges\nmyArray.Select(x=\u003ex*x,10000); // split the array into ranges of 10,000 elements each\n\n// Parallel functions cause some allocations, and requires care in their use, as they \n// may not be faster than scalar or SIMD versions depending on the workload and\n// hardware available.\n```\n\n### LinqFaster.SIMD.Parallel\n\nSee MSDN [documentation](https://msdn.microsoft.com/en-us/library/dn858385(v=vs.111).aspx) on System.Numerics.Vectors\nfor more detail on SIMD in C#.\n\n```c#\n\nusing LingFaster.SIMD.Parallel\n\n// These functions combine SIMD acceleration and multithreading.\n// They are all named with an SP at the end, and are available\n// only for arrays.\n\nvar sum = myArray.SumSP();\n\n// Floating point math is not commutative, so the results\n// of operations such as Sum and Average may differ slightly.\n// Accuracy is usually better.\n\nConsole.WriteLine(myFloats.SumSP() == myFloats.SumF()); // --\u003e False!\n\n// All SIMD parallel functions have an optional batch size, which\n// defines how many elements are operated on per task/thread.\n// This can be tuned for performance.\n\nmyArray.AverageSP(myArray.Length/10);  //split the array into 10 ranges\nmyArray.SelectSP(x=\u003ex*x,10000); // split the array into ranges of 10,000 elements each\n\n\n// SIMD operations are already very fast, so combining them with \n// multiple threads will only be worthwhile for large arrays and/or\n// for very expensive operations.\n```\n\n# Limitations\n\nThese are purely imperative implementations of the same higher order functions that\nLinq provides, but unlike Linq they are not lazily evaluated.  This means that when chaining\nfunctions together such as:\n\n```c#\n\nvar a = data.Where(predicate).Select(transform).Aggregate(foo);\n//or\nvar b = data.Select(selector).Sum();\n\n```\nLinq would not do any work until the calls to `Sum()` or `Aggregate()`, and thus iterate over the collection only once and\nallocate very little. LinqFaster used this way would iterate over the collection each time and allocate\nmuch more.  Sometimes the net result will still be faster overall but the better approach is to\nuse the combined LinqFaster operations such as `SelectWhere`, `WhereSelect`, and `WhereAggregate`.\nFor example the expressions above would become:\n\n```c#\n\nvar a = data.WhereAggregate(predicate,transform,foo);\n// and\nvar b = data.Sum(selector);\n\n```\n\nThis gets you the best of both worlds.  The speed of memory locality and no allocations at all.\nIn short, think about how you are transforming your data. In some cases normal Linq may be the better choice.\n\nWhile most of the functions strive to provide indentical results to Linq, the OrderBy methods are not a stable sort, while in Linq they are.\n\n\n\n\n\n\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjackmott%2Flinqfaster","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjackmott%2Flinqfaster","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjackmott%2Flinqfaster/lists"}