Deklaracja zmiennych poza pętlą, a deklaracja w pętli

0

Czy kompilator potraktuje to tak samo?

        void ShuffleIntList(List<int> l)
        {
            int tmp;
            int randIdx;

            for (int i = 0; i < l.Count; i++)
            {
                randIdx = Random.Range(0, l.Count);
                tmp = l[i];

                l[i] = l[randIdx];
                l[randIdx] = tmp;
            }
        }

vs

        void ShuffleIntList(List<int> l)
        {
            for (int i = 0; i < l.Count; i++)
            {
                int randIdx = Random.Range(0, l.Count);
                int tmp = l[i];

                l[i] = l[randIdx];
                l[randIdx] = tmp;
            }
        }
1

int'y nie są GC-owane

1

Przetestowałem wydajność, obie metody są wykonywane równie szybko. Jedyna różnica jest taka, że w pierwszym przypadku int nie jest niszczony (muszę doczytać jak kompilator usuwa typy proste ;p), a w drugim jest niszczony. A przez to, że tem w pierwszym przypadku jest zapamiętywane (trzymane w zmiennej zadeklarowanej przed pętlą), to jest zachowany porządek. A w drugiej metodzie przez to że tem jest usuwany, to przy tworzeniu nowego przypisuje się mu ostatnią znaną wartość l[randIdx].

3

Też mi się tak wydaje. Int powinien zostać odłożony na stack i zdjęty po opuszczeniu zakresu. Gdyby to był typ referencyjny to leci na stertę i jak się pamięć zapcha to wchodzi GC. @Spine wrzuć to w ILspy i porównaj ;) - chalwa wczoraj, 23:30

Wiedza z czasów, gdy się opłacało disasemblowac C.

Ramka (frame) funkcji bywała obliczona na największą deklarację w funkcji, w dowolnym z bloków (można powiedzieć "pesymistycznie"), Zwykle przy wejściu do bloków nie było kicania wskaźnikiem stosu. Jednym-dwoma rozkazami stos był przesuwany o wielkość ramki przy wyjściu z funkcji. Generalnie pozbywanie się jednej ramki, a nie wielu (po blokach) w dowolnej platformie wydaje się wydajniejsze (chociaż niekoniecznie eleganckie)

To taki tip dla @bakunet odnośnie szukania opisu niszczenia zmiennych prostych, moze tak być, nie musi

3
Spine napisał(a):

Czy kompilator potraktuje to tak samo?

Tak, wszystkie zmienne lokalne i tak są inicjalizowane na początku metody.
Po prostu druga wersja ładniej wygląda.

1
AnyKtokolwiek napisał(a):

(...)
To taki tip dla @bakunet odnośnie szukania opisu niszczenia zmiennych prostych, moze tak być, nie musi

Pierwszy wynik z Googli prowadzi do tej książki:

Value types typically are allocated on the stack and are automatically destroyed when the variable goes out of scope. Value types include the simple types like int and decimal, structures and enumeration types.

3

Skompilowałem to w Core 3.1 (zmieniłem tylko random bo się nie kompilował <co to za wersja??>) .
Wrzuciłem w resharpera IL View i diff w notepadzie.
Wniosek jest jeden:
Dla kompilatora jest to identyczna ilość instrukcji, więc różni się to wyłącznie czytelnością.
Moźna by się jeszcze pokusić o sprawdzenie wydajności przy kompilacji debug i release, ale nigdy się nie zgłębiałem w to jak działa JIT.

screenshot-20200626085544.png

0
chalwa napisał(a):

Wrzuciłem w resharpera IL View i diff w notepadzie.

Nie prościej użyć standardowego ildasm?

Dla kompilatora jest to identyczna ilość instrukcji, więc różni się to wyłącznie czytelnością.

No tak, to jest to, co napisałem wcześniej - zmienne metody są inicjalizowane przez kompilator na jej początku.

Moźna by się jeszcze pokusić o sprawdzenie wydajności przy kompilacji debug i release, ale nigdy się nie zgłębiałem w to jak działa JIT.

Ale jak ma działać? Jeśli kod obu wersji jest dokładnie taki sam, to będzie działać tak samo.
Zakładam, ze i tak dekompilowałeś tylko release.

2

Żeby pisać wydajne programy trzeba znać najlepiej wszystko . w jaki sposób program c# jest zaimplementowany w IL ,
następnie jak to wszystko jest zaimplementowane przez JIT w asemblerze , jak działa GC i środowisko uruchomieniowe, stos , sterta , jak Windows zarządza pamięcią a na samym końcu jak działa sam komputer - procesor i pamięć.
Aktualnie jestem w trakcie czytania książki - Zaawansowane zarządzanie pamięcią w NET. To jest kolejna książka napisana przez autora dla samego siebie.
Jest w niej zawartych trochę konkretów ale żeby ją zrozumieć do końca to trzeba przeczytać kolejnych 10 książek

1 użytkowników online, w tym zalogowanych: 0, gości: 1