powered by simpleCommunicator - 2.0.56     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / Преобразование вложенных циклов в Java 8 stream
3 сообщений из 28, страница 2 из 2
Преобразование вложенных циклов в Java 8 stream
    #39709598
cossack5
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton,

В данной случае - это LINQ To Objects. Согласно сорцам Join'а и и основного файла с linq-логикой создается что-то вроде мапы для каждой итерации верхнего уровня (т.е. sectors). Наверное, не самый эффективный вариант (а чего вы хотели - чудес не бывает). Я в джаве использовал cqengine , где для полей объектов можно создавать индексы (хеш-индексы, префиксное дерево и т.д.) и это работает быстрее (думаю в . NET тоже такое есть).

бенчмарк linq vs non-linq
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
void Main()
{
 	var summary = BenchmarkRunner.Run<Bench>(new AllowNonOptimized());
}

public class AllowNonOptimized : ManualConfig
{
	public AllowNonOptimized()
	{
		Add(JitOptimizationsValidator.DontFailOnError); // ALLOW NON-OPTIMIZED DLLS

		Add(DefaultConfig.Instance.GetLoggers().ToArray()); // manual config has no loggers by default
		Add(DefaultConfig.Instance.GetExporters().ToArray()); // manual config has no exporters by default
		Add(DefaultConfig.Instance.GetColumnProviders().ToArray()); // manual config has no columns by default
	}
}

[RPlotExporter, RankColumn, HtmlExporter]
[SimpleJob(launchCount: 1, warmupCount: 1, targetCount: 5, invocationCount: 10, id: "QuickJob")]
public class Bench
{
	
	static Random rand = new Random();
	
	[GlobalSetup]
	public void Setup()
	{
		allocationSector = new AllocationSector();
		var sectorNames = new HashSet<String>();
		sectors = new HashSet<Sector>();
		
		for (int i=0;i<NumSectors;i++)
		{
			sectorNames.Add(RandomString(2));
		}
		
		foreach (var sectorName in sectorNames)
		{
			sectors.Add(new Sector { sector = sectorName });
		}

		stocks = new HashSet<Stock>();
		var sectorNamesList = sectorNames.ToList();
		for (int i = 0; i < NumStocks; i++)
		{
			stocks.Add(new Stock
			{
				sector = sectorNamesList[rand.Next(0, sectorNames.Count)],
				assetValue = rand.Next(10, 100),
				symbol = i.ToString()
			});
		}
	}

	public static string RandomString(int length)
	{
		const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
		return new string(Enumerable.Repeat(chars, length)
		  .Select(s => s[rand.Next(s.Length)]).ToArray());
	}

	[Params(100_000, 1_000_000)]
	public int NumStocks;

	[Params(10, 100, 1_000, 10_000)]
	public int NumSectors;

	private AllocationSector allocationSector;
	private HashSet<Stock> stocks;
	private HashSet<Sector> sectors;


	[Benchmark]
	public void performUsingLINQ()
	{
		(from stock in stocks
		 join sector in sectors on stock.sector equals sector.sector
		 group stock by stock.sector into res
		 select new Sector { sector = res.Key, assetValue = res.Sum(_ => (int)_.assetValue) })
	  .ToList().ForEach(s => allocationSector.allocations.Add(s));

	}

	[Benchmark]
	public void performUsingOneCycle()
	{
		var sectorMap = sectors.ToDictionary(t => t.sector, t => t);
		foreach (var stock in stocks)
		{
			var sector = sectorMap[stock.sector];
			if (sector.sector == stock.sector)
			{
				sector.assetValue += (int)stock.assetValue;
			}
			allocationSector.allocations.Add(sector);
		}

	}
}



public class Sector
{
	public String sector {get; set;}
	public int assetValue {get; set;}
	public float proportion {get; set;}
}

public class Stock
{
	public String symbol {get;set;}
	public int volume  {get;set;}
	public double assetValue  {get;set;}
	public String sector  {get;set;}
}

public class AllocationSector
{
	public List<Sector> allocations = new List<Sector>();
}


Summary
BenchmarkDotNet=v0.11.1, OS=Windows 10.0.17134.285 (1803/April2018Update/Redstone4)
Intel Core i7-7700HQ CPU 2.80GHz (Max: 2.81GHz) (Kaby Lake), 1 CPU, 8 logical and 4 physical cores
[Host] : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.7.3163.0
QuickJob : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.7.3163.0

Job=QuickJob InvocationCount=10 IterationCount=5
LaunchCount=1 UnrollFactor=1 WarmupCount=1

Method | NumStocks | NumSectors | Mean | Error | StdDev | Rank |
------------------- |---------- |----------- |-----------:|-----------:|-----------:|-----:|
performUsingLINQ | 100000 | 10 | 20.334 ms | 2.905 ms | 0.7544 ms | 3 |
performUsingOneCycle| 100000 | 10 | 5.963 ms | 4.608 ms | 1.1969 ms | 1 |
performUsingLINQ | 100000 | 100 | 20.963 ms | 2.486 ms | 0.6457 ms | 3 |
performUsingOneCycle| 100000 | 100 | 5.789 ms | 4.384 ms | 1.1387 ms | 1 |
performUsingLINQ | 100000 | 1000 | 27.998 ms | 2.094 ms | 0.5439 ms | 4 |
performUsingOneCycle | 100000 | 1000 | 6.645 ms | 4.694 ms | 1.2193 ms | 1 |
performUsingLINQ | 100000 | 10000 | 78.585 ms | 5.072 ms | 1.3175 ms | 5 |
performUsingOneCycle| 100000 | 10000 | 11.994 ms | 8.442 ms | 2.1927 ms | 2 |
performUsingLINQ | 1000000 | 10 | 206.446 ms | 13.331 ms | 3.4626 ms | 7 |
performUsingOneCycle| 1000000 | 10 | 65.255 ms | 50.348 ms | 13.0776 ms | 5 |
performUsingLINQ | 1000000 | 100 | 244.823 ms | 57.552 ms | 14.9488 ms | 8 |
performUsingOneCycle| 1000000 | 100 | 55.222 ms | 36.442 ms | 9.4656 ms | 5 |
performUsingLINQ | 1000000 | 1000 | 318.040 ms | 20.250 ms | 5.2598 ms | 9 |
performUsingOneCycle| 1000000 | 1000 | 68.306 ms | 44.328 ms | 11.5140 ms | 5 |
performUsingLINQ | 1000000 | 10000 | 632.400 ms | 109.849 ms | 28.5328 ms | 10 |
performUsingOneCycle| 1000000 | 10000 | 100.853 ms | 41.869 ms | 10.8753 ms | 6 |


Как видно из таблицы, правильный алгоритм (как в примере Панфилова - когда хешмапа создается один раз в самом начале) будет где-то в 6 раз быстрее чем LINQ с джойнами. Код TC с вложенными итерациями, приведенный в начале темы будет в сотни раз медленнее.
...
Рейтинг: 0 / 0
Преобразование вложенных циклов в Java 8 stream
    #39710989
Nebo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
KopranychАндрей Панфилов,
Спасибо за решение!
А еще говорят, что функциональное программирование более проще читается, по мне так мой вариант в обычном стиле более проще в понимании

Во всём нужны мера. Где-то одно хорошо, где-то другое.
...
Рейтинг: 0 / 0
Преобразование вложенных циклов в Java 8 stream
    #39710991
Nebo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
3 сообщений из 28, страница 2 из 2
Форумы / Java [игнор отключен] [закрыт для гостей] / Преобразование вложенных циклов в Java 8 stream
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]