Here you have a full example with 4 ways but...
Be aware, parallelism is not always the better option especially with sets with lots of data and simple operations, like your example.
You can play with this example and change the length of data in Enumerable.Range(1, xxx)
and see times results:
- Example with 1000000*5 authors:
WAY 1, for 853
WAY 2, linq 448
WAY 3, parallel for each 1407
WAY 4, parallel with Partitioner 407
- Example with 1000000*1 authors:
WAY 1, for 190
WAY 2, linq 90
WAY 3, parallel for each 209
WAY 4, parallel with Partitioner 304
- Example with 1000000*10 authors:
WAY 1, for 962
WAY 2, linq 1747
WAY 3, parallel for each 1137
WAY 4, parallel with Partitioner 2690
In your case, i recommend you for
or linq
options.
CODE
// Set exchange rate
double usdt = 1.5667;
double btc = 21340.6532;
// Get authors with other funcion
var authors = Enumerable.Range(1, 1000000*10).Select(x=> new Author
{
Name = "Author " + x.ToString(),
usdtCoins = x*1000,
btcCoins = x
}).ToList();
// WAY 1, for
var authorsCalculated = new List<Author>();
var timer = Stopwatch.StartNew();
foreach (var author in authors)
{
authorsCalculated.Add(new Author
{
Name = author.Name,
usdtCoins = author.usdtCoins,
btcCoins = author.btcCoins,
usdtMoney = author.usdtCoins * usdt,
btcMoney = author.btcCoins * btc
});
}
timer.Stop();
Console.WriteLine("WAY 1, for "+timer.ElapsedMilliseconds);
// WAY 2, linq
authorsCalculated = new List<Author>();
timer.Restart();
authorsCalculated = authors.Select(x=> new Author {
Name = x.Name,
usdtCoins = x.usdtCoins,
btcCoins = x.btcCoins,
usdtMoney = x.usdtCoins * usdt,
btcMoney = x.btcCoins * btc
}).ToList();
timer.Stop();
Console.WriteLine("WAY 2, linq " + timer.ElapsedMilliseconds);
// WAY 3, parallel for each
authorsCalculated = new List<Author>();
var authorsCalculated_ConcurrentBag = new ConcurrentBag<Author>();
timer.Restart();
Parallel.ForEach(authors, author =>
{
// Each parallel add one item on concurrent bag = safe list
authorsCalculated_ConcurrentBag.Add(new Author
{
Name = author.Name,
usdtCoins = author.usdtCoins,
btcCoins = author.btcCoins,
usdtMoney = author.usdtCoins * usdt,
btcMoney = author.btcCoins * btc
});
});
authorsCalculated = authorsCalculated_ConcurrentBag.ToList();
timer.Stop();
Console.WriteLine("WAY 3, parallel for each " + timer.ElapsedMilliseconds);
// WAY 4, parallel with Partitioner
// https://stackoverflow.com/questions/4031820/when-to-use-partitioner-class
authorsCalculated = new List<Author>();
var authorsCalculated_ConcurrentBag2 = new ConcurrentBag<List<Author>>();
timer.Restart();
Parallel.ForEach(Partitioner.Create(0, authors.Count()), range => {
var innerList = new List<Author>();
for (var index = range.Item1; index < range.Item2; index++)
{
innerList.Add(new Author
{
Name = authors[index].Name,
usdtCoins = authors[index].usdtCoins,
btcCoins = authors[index].btcCoins,
usdtMoney = authors[index].usdtCoins * usdt,
btcMoney = authors[index].btcCoins * btc
});
}
authorsCalculated_ConcurrentBag2.Add(innerList);
});
foreach (var l in authorsCalculated_ConcurrentBag2)
{
authorsCalculated.AddRange(l);
}
timer.Stop();
Console.WriteLine("WAY 4, parallel with Partitioner " + timer.ElapsedMilliseconds);