Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

BlueCobold

Community-Fossil

  • »BlueCobold« ist der Autor dieses Themas

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

1

03.01.2011, 08:02

[C#] Yield Return Performance

Moin.

Mich hat mal interessiert, wie sich yield return Performance-mäßig so verhält im Vergleich zum Arbeiten mit einer Liste.
Dabei kamen sehr interessante Resultate zum Vorschein.

Es wurden mehrere Fälle betrachtet:
1.A) Mix aus List / foreach-yield returns ohne Verwendung der zurückgegebenen Ergebnisse.
2.A) reine yield-returns ohne Verwendung der zurückgegebenen Ergebnisse.
1.B) Mix aus List / foreach-yield returns mit Verwendung der zurückgegebenen Ergebnisse.
2.B) reine yield-returns mit Verwendung der zurückgegebenen Ergebnisse.

Die konkreten Zeiten:
1.A = ~3.240.000 yield, ~490.000 List
2.A = ~4.670.000 yield, ~1.470.000 List
1.B = ~4.920.000 yield, ~11.000.000 List
2.B = ~4.830.000 yield, ~12.800.000 List

Anmerkung:
Die Absolutwerte der Zahlen können durch das Verfahren nicht als repräsentativ erachtet werden, die Verhältnisse zwischen yield und List sind allerdings so massiv, dass sie durchaus brauchbar sind um eine quantitative Aussage darüber abzugeben, ob yield oder eine Liste verwendet werden sollte.

Fazit:
Werden die Ergebnisse einer Enumeration sofort benötigt um sie direkt weiter zu verwenden (was eigentlich niemals der Fall ist, da Werte ja immer benötigt werden oder der Call wäre unsinnig), ist yield absolut im Vorteil. Sollten die Werte aber nur ge-fetched werden, so bleibt die Liste unangefochten, da sie keine unnötige Iteration über die einzelnen Elemente erzwingt.

Würde mich freuen, wenn Ihr Eure Erfahrungen oder Wissen darüber teilen könntet, da ich mich vorher zwar mit yield, aber nie mit dessen Performance auseinander gesetzt habe.


Der Code für den Test sah wie folgt aus:

C#-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
            YieldTest yt = new YieldTest ( );
            long t = DateTime.Now.Ticks;
            int x = 0;
            for ( int i = 0; i < 1000000; i++ )
#if A
                yt.GetThem ( );
#else
                foreach ( var y in yt.GetThem ( ) )
                    x += y;
#endif
            long t2 = DateTime.Now.Ticks;
            x = 0;
            for ( int i = 0; i < 1000000; i++ )
#if A
                yt.GetThemList ( );
#else
                foreach ( var y in yt.GetThemList ( ) )
                    x += y;
#endif
            long t3 = DateTime.Now.Ticks;


C#-Quelltext

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
        private class YieldTest
        {
            private Random m_Rand = new Random ( );
            public IEnumerable<int> GetThem ( )
            {
                int choice = m_Rand.Next ( 4 );
                int rep = m_Rand.Next ( 15 );
                if ( choice == 0 )
                {
#if CASE1
                    for ( int i = 0; i < rep; i++ )
                    {
                        yield return (i * 15) % 7;
                    }
#else
                    foreach ( int x in GetMore ( ) )
                        yield return x;
#endif
                    yield return 24;
                }
                if ( choice == 1 )
                {
                    foreach ( int x in GetMore ( ) )
                    {
                        yield return x;
                    }
                    yield return 214;
                }
                if ( choice == 2 )
                {
                    foreach ( int x in GetMore ( ) )
                    {
                        yield return x;
                    }
                    yield return 34;
                }
                if ( choice == 3 )
                {
                    foreach ( int x in GetMore ( ) )
                    {
                        yield return x;
                    }
                    yield return 94;
                }
            }
            public IEnumerable<int> GetThemList ( )
            {
                int choice = m_Rand.Next ( 4 );
                int rep = m_Rand.Next ( 15 );
                List<int> l = new List<int> ( );
                if ( choice == 0 )
                {
#if CASE1
                    for ( int i = 0; i < rep; i++ )
                    {
                        l.Add ( (i * 15) % 7 );
                    }
#else
                    l = GetMore ( );
#endif
                    l.Add ( 24 );
                    return l;
                }
                if ( choice == 1 )
                {
                    l = GetMore ( );
                    l.Add ( 214 );
                    return l;
                }
                if ( choice == 2 )
                {
                    l = GetMore ( );
                    l.Add ( 34 );
                    return l;
                }
                if ( choice == 3 )
                {
                    l = GetMore ( );
                    l.Add ( 94 );
                    return l;
                }
                return null;
            }

            private List<int> GetMore ( )
            {
                List<int> ret = new List<int> ( );
                int rep = 5 + m_Rand.Next ( 3 );
                for ( int i = 0; i < rep; i++ )
                {
                    ret.Add ( 3 * i );
                }
                ret.Add ( 13 );
                return ret;
            }
        }
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]