Megosztás a következőn keresztül:


Oktatóanyag: Memóriafoglalások ref csökkentése biztonsággal

A .NET-alkalmazások teljesítményhangolása gyakran két technikát is magában foglal. Először csökkentse a halomfoglalások számát és méretét. Másodszor csökkentse az adatok másolásának gyakoriságát. A Visual Studio nagyszerű eszközöket biztosít, amelyekkel elemezheti, hogyan használja az alkalmazás a memóriát. Miután megállapította, hogy az alkalmazás hol végez szükségtelen foglalásokat, módosításokat hajt végre a foglalások minimalizálása érdekében. class típusokat struct típusokká alakíthat át. Biztonsági ref megőrizheti a szemantikát, és minimalizálhatja a felesleges másolást.

Használja a Visual Studio 17.5-öt az oktatóanyag legjobb élményéhez. A memóriahasználat elemzéséhez használt .NET-objektumfoglalási eszköz a Visual Studio része. A Visual Studio Code és a parancssor használatával futtathatja az alkalmazást, és elvégezheti az összes módosítást. A módosítások elemzési eredményeit azonban nem fogja látni.

A használni kívánt alkalmazás egy IoT-alkalmazás szimulációja, amely több érzékelőt figyel annak megállapítására, hogy egy betolakodó belépett-e egy titkos gyűjteménybe értékekkel. Az IoT-érzékelők folyamatosan küldenek adatokat, amelyek az oxigén (O2) és a szén-dioxid (CO2) levegőben való kombinációját mérik. A hőmérsékletet és a relatív páratartalmat is jelentik. Ezek az értékek mindig kissé ingadoznak. Azonban, amikor egy személy belép a szobába, a változás valamelyest nagyobb, és mindig ugyanabban az irányban történik: az oxigén csökken, a szén-dioxid növekszik, nő a hőmérséklet és a relatív páratartalom is. Amikor az érzékelők a növekedés megjelenítéséhez egyesülnek, a betolakodó riasztása aktiválódik.

Ebben az oktatóanyagban futtatja az alkalmazást, méri a memóriafoglalásokat, majd a foglalások számának csökkentésével javítja a teljesítményt. A forráskód a mintaböngészőben érhető el.

A kezdőalkalmazás megismerése

Töltse le az alkalmazást, és futtassa a kezdőmintát. Az indítási alkalmazás megfelelően működik, de mivel sok kis objektumot foglal le minden mérési ciklussal, a teljesítménye lassan csökken az idő múlásával.

Press <return> to start simulation

Debounced measurements:
    Temp:      67.332
    Humidity:  41.077%
    Oxygen:    21.097%
    CO2 (ppm): 404.906
Average measurements:
    Temp:      67.332
    Humidity:  41.077%
    Oxygen:    21.097%
    CO2 (ppm): 404.906

Debounced measurements:
    Temp:      67.349
    Humidity:  46.605%
    Oxygen:    20.998%
    CO2 (ppm): 408.707
Average measurements:
    Temp:      67.349
    Humidity:  46.605%
    Oxygen:    20.998%
    CO2 (ppm): 408.707

Sok sor el lett távolítva.

Debounced measurements:
    Temp:      67.597
    Humidity:  46.543%
    Oxygen:    19.021%
    CO2 (ppm): 429.149
Average measurements:
    Temp:      67.568
    Humidity:  45.684%
    Oxygen:    19.631%
    CO2 (ppm): 423.498
Current intruders: 3
Calculated intruder risk: High

Debounced measurements:
    Temp:      67.602
    Humidity:  46.835%
    Oxygen:    19.003%
    CO2 (ppm): 429.393
Average measurements:
    Temp:      67.568
    Humidity:  45.684%
    Oxygen:    19.631%
    CO2 (ppm): 423.498
Current intruders: 3
Calculated intruder risk: High

Megismerheti a kódot, és megtudhatja, hogyan működik az alkalmazás. A fő program futtatja a szimulációt. A <Enter> megnyomása után létrehoz egy szobát, és összegyűjt néhány kezdeti alapadatot.

Console.WriteLine("Press <return> to start simulation");
Console.ReadLine();
var room = new Room("gallery");
var r = new Random();

int counter = 0;

room.TakeMeasurements(
    m =>
    {
        Console.WriteLine(room.Debounce);
        Console.WriteLine(room.Average);
        Console.WriteLine();
        counter++;
        return counter < 20000;
    });

Az alapadatok megállapítása után futtatja a szimulációt a helyiségben, ahol egy véletlenszerű számgenerátor megállapítja, hogy egy betolakodó lépett-e be a szobába:

counter = 0;
room.TakeMeasurements(
    m =>
    {
        Console.WriteLine(room.Debounce);
        Console.WriteLine(room.Average);
        room.Intruders += (room.Intruders, r.Next(5)) switch
        {
            ( > 0, 0) => -1,
            ( < 3, 1) => 1,
            _ => 0
        };

        Console.WriteLine($"Current intruders: {room.Intruders}");
        Console.WriteLine($"Calculated intruder risk: {room.RiskStatus}");
        Console.WriteLine();
        counter++;
        return counter < 200000;
    });

Más típusok tartalmazzák a méréseket, az utolsó 50 mérés átlagát és az összes elvégzett mérés átlagát.

Ezután futtassa az alkalmazást a .NET-objektumfoglalási eszközzel. Győződjön meg arról, hogy a Release verziót használja, és nem a Debug verziót. A Hibakeresés menüben nyissa meg a Teljesítményprofilozót. Ellenőrizze a .NET objektumfoglalás követése opciót, de semmi mást. Futtassa az alkalmazást a teljes befejezésig. A profilkészítő méri az objektumfoglalásokat és jelentést készít a foglalásokról és a szemétgyűjtési ciklusokról. Az alábbi ábrához hasonló gráfnak kell megjelennie:

Foglalási grafikon a behatoló riasztási alkalmazás optimalizálása előtt történő futtatásához.

Az előző grafikonon látható, hogy a foglalások minimalizálása teljesítménybeli előnyökkel jár. Az élő objektumok grafikonján egy fűrészfog mintázat látható. Ez azt jelzi, hogy számos objektum jön létre, amelyek gyorsan szemétté válnak. Ezeket később gyűjtjük össze, ahogy az objektum deltagráfjában is látható. A lefelé mutató piros sávok szemétgyűjtési ciklust jeleznek.

Ezután tekintse meg a gráfok alatti Foglalások lapot. Ez a táblázat azt mutatja be, hogy milyen típusok vannak a leginkább lefoglalva:

Diagram, amely a leggyakrabban lefoglalt típusokat mutatja.

A System.String típus számol el a legtöbb foglalást. A legfontosabb feladat a karakterláncok kiosztásának gyakoriságának minimalizálása. Ez az alkalmazás számos formázott kimenetet nyomtat folyamatosan a konzolra. Ebben a szimulációban meg szeretnénk tartani az üzeneteket, ezért a következő két sorra koncentrálunk: a SensorMeasurement típusra és a IntruderRisk típusra.

Kattintson duplán a SensorMeasurement vonalra. Láthatja, hogy az összes foglalás a static metódusban SensorMeasurement.TakeMeasurementtörténik. A metódust a következő kódrészletben tekintheti meg:

public static SensorMeasurement TakeMeasurement(string room, int intruders)
{
    return new SensorMeasurement
    {
        CO2 = (CO2Concentration + intruders * 10) + (20 * generator.NextDouble() - 10.0),
        O2 = (O2Concentration - intruders * 0.01) + (0.005 * generator.NextDouble() - 0.0025),
        Temperature = (TemperatureSetting + intruders * 0.05) + (0.5 * generator.NextDouble() - 0.25),
        Humidity = (HumiditySetting + intruders * 0.005) + (0.20 * generator.NextDouble() - 0.10),
        Room = room,
        TimeRecorded = DateTime.Now
    };
}

Minden mérés egy új SensorMeasurement objektumot foglal le, amely egy class típus. Minden SensorMeasurement létrehozása halom memóriaterületet foglal.

Osztályok átalakítása szerkezetekre

Az alábbi kód a következő kezdeti deklarációt SensorMeasurementmutatja:

public class SensorMeasurement
{
    private static readonly Random generator = new Random();

    public static SensorMeasurement TakeMeasurement(string room, int intruders)
    {
        return new SensorMeasurement
        {
            CO2 = (CO2Concentration + intruders * 10) + (20 * generator.NextDouble() - 10.0),
            O2 = (O2Concentration - intruders * 0.01) + (0.005 * generator.NextDouble() - 0.0025),
            Temperature = (TemperatureSetting + intruders * 0.05) + (0.5 * generator.NextDouble() - 0.25),
            Humidity = (HumiditySetting + intruders * 0.005) + (0.20 * generator.NextDouble() - 0.10),
            Room = room,
            TimeRecorded = DateTime.Now
        };
    }

    private const double CO2Concentration = 409.8; // increases with people.
    private const double O2Concentration = 0.2100; // decreases
    private const double TemperatureSetting = 67.5; // increases
    private const double HumiditySetting = 0.4500; // increases

    public required double CO2 { get; init; }
    public required double O2 { get; init; }
    public required double Temperature { get; init; }
    public required double Humidity { get; init; }
    public required string Room { get; init; }
    public required DateTime TimeRecorded { get; init; }

    public override string ToString() => $"""
            Room: {Room} at {TimeRecorded}:
                Temp:      {Temperature:F3}
                Humidity:  {Humidity:P3}
                Oxygen:    {O2:P3}
                CO2 (ppm): {CO2:F3}
            """;
}

A típus eredetileg azért lett létrehozva class , mert számos double mérést tartalmaz. Nagyobb, mint amennyit a gyakori elérési utakon szeretne másolni. Ez a döntés azonban sok kiosztást jelentett. Módosítsa a típust a class típusról a struct.

class-ról struct-re történő váltás néhány fordítóhibát eredményez, mivel az eredeti kód néhány helyen null hivatkozás-ellenőrzést használt. Az első az DebounceMeasurement osztályban van, a AddMeasurement metódusban:

public void AddMeasurement(SensorMeasurement datum)
{
    int index = totalMeasurements % debounceSize;
    recentMeasurements[index] = datum;
    totalMeasurements++;
    double sumCO2 = 0;
    double sumO2 = 0;
    double sumTemp = 0;
    double sumHumidity = 0;
    for (int i = 0; i < debounceSize; i++)
    {
        if (recentMeasurements[i] is not null)
        {
            sumCO2 += recentMeasurements[i].CO2;
            sumO2+= recentMeasurements[i].O2;
            sumTemp+= recentMeasurements[i].Temperature;
            sumHumidity += recentMeasurements[i].Humidity;
        }
    }
    O2 = sumO2 / ((totalMeasurements > debounceSize) ? debounceSize : totalMeasurements);
    CO2 = sumCO2 / ((totalMeasurements > debounceSize) ? debounceSize : totalMeasurements);
    Temperature = sumTemp / ((totalMeasurements > debounceSize) ? debounceSize : totalMeasurements);
    Humidity = sumHumidity / ((totalMeasurements > debounceSize) ? debounceSize : totalMeasurements);
}

A DebounceMeasurement típus 50 mérésből álló tömböt tartalmaz. Az érzékelő mérései az utolsó 50 mérés átlagaként jelennek meg. Ez csökkenti a zajt az olvasatokban. A teljes 50 érték leolvasása előtt ezek az értékek a következők null: . A kód ellenőrzi a null hivatkozásokat a helyes átlag jelentéséhez a rendszer indításakor. Miután módosította a SensorMeasurement típust egy szerkezetre, egy másik tesztet kell használnia. A SensorMeasurement típus tartalmaz egy string helyiségazonosítót, így ezt a tesztet használhatja:

if (recentMeasurements[i].Room is not null)

A másik három fordítóhiba mind abban a módszerben szerepel, amely ismétlődően végez méréseket egy helyiségben:

public void TakeMeasurements(Func<SensorMeasurement, bool> MeasurementHandler)
{
    SensorMeasurement? measure = default;
    do {
        measure = SensorMeasurement.TakeMeasurement(Name, Intruders);
        Average.AddMeasurement(measure);
        Debounce.AddMeasurement(measure);
    } while (MeasurementHandler(measure));
}

A kezdő metódusban a helyi változó SensorMeasurement egy nullázható hivatkozás:

SensorMeasurement? measure = default;

Most, hogy az SensorMeasurement egy struct a class helyett, a null értékű egy null értékű értéktípus. A deklarációt értéktípusra módosíthatja a fennmaradó fordítóhibák kijavításához:

SensorMeasurement measure = default;

Most, hogy a fordító hibáinak elhárítása megtörtént, meg kell vizsgálnia a kódot, hogy a szemantika ne változzon. Mivel struct a típusok érték szerint vannak átadva, a metódusparaméterek módosításai nem láthatók a metódus visszatérése után.

Fontos

Ha egy típust a típusról class a másikra struct módosít, az megváltoztathatja a program szemantikáját. Amikor egy típust class átadnak egy metódusnak, a metódusban végrehajtott összes mutáció az argumentumra kerül. Amikor egy struct típus kerül átadásra egy metódusnak, a metódusban végrehajtott módosítások az argumentum egy példányára vonatkoznak. Ez azt jelenti, hogy minden olyan metódust, amely terv szerint módosítja az argumentumait, frissíteni kell úgy, hogy a ref módosítót használd bármely argumentumtípuson, amelyet class-ről struct-re változtattál.

A SensorMeasurement típus nem tartalmaz olyan metódusokat, amelyek módosítják az állapotot, ezért ez ebben a mintában nem okoz problémát. Ezt bizonyítja, ha hozzáadja a readonly módosítót a SensorMeasurement szerkezethez:

public readonly struct SensorMeasurement

A fordító kikényszeríti a readonly szerkezet természetét SensorMeasurement . Ha a kód ellenőrzése során kihagyna egy olyan metódust, amely módosítja az állapotot, a fordító jelezné. Az alkalmazás továbbra is hibák nélkül épül fel, így ez a típus readonly. A módosító hozzáadása a readonly típusról class a típusra struct való váltáskor segíthet megtalálni azokat a tagokat, amelyek módosítják az structállapotot.

Kerülje a másolatkészítést

Számos szükségtelen hozzárendelést eltávolítottatok az alkalmazásotokból. A SensorMeasurement típus sehol nem jelenik meg a táblázatban.

Most még több munkát végez a SensorMeasurement struktúra másolásán minden alkalommal, amikor paraméterként vagy visszatérési értékként használják. A SensorMeasurement szerkezet négy dupla, egy DateTime és egy string. Ez a struktúra mérhetően nagyobb, mint egy hivatkozás. Tegyük hozzá a ref vagy in módosítókat azokhoz a helyekhez, ahol a SensorMeasurement típust használjuk.

A következő lépés a mérést visszaadó metódusok megkeresése, vagy a mérés argumentumként való használata, valamint a hivatkozások használata, ahol lehetséges. Kezdje a SensorMeasurement szerkezetben. A statikus TakeMeasurement metódus létrehoz és visszaad egy újat SensorMeasurement:

public static SensorMeasurement TakeMeasurement(string room, int intruders)
{
    return new SensorMeasurement
    {
        CO2 = (CO2Concentration + intruders * 10) + (20 * generator.NextDouble() - 10.0),
        O2 = (O2Concentration - intruders * 0.01) + (0.005 * generator.NextDouble() - 0.0025),
        Temperature = (TemperatureSetting + intruders * 0.05) + (0.5 * generator.NextDouble() - 0.25),
        Humidity = (HumiditySetting + intruders * 0.005) + (0.20 * generator.NextDouble() - 0.10),
        Room = room,
        TimeRecorded = DateTime.Now
    };
}

Ezt úgy fogjuk hagyni, ahogy van, érték szerint visszaadva. Ha megpróbálna a ref visszatérítést végrehajtani, a fordítóprogram hibát jelezne. Nem térhet vissza ref a helyileg létrehozott új struktúrába a metódusban. A nem módosítható szerkezet kialakítása azt jelenti, hogy csak az építéskor állíthatja be a mérés értékeit. Ennek a módszernek létre kell hoznia egy új mérési szerkezetet.

Tekintsünk újra DebounceMeasurement.AddMeasurement. Adja hozzá a in módosítót a measurement paraméterhez:

public void AddMeasurement(in SensorMeasurement datum)
{
    int index = totalMeasurements % debounceSize;
    recentMeasurements[index] = datum;
    totalMeasurements++;
    double sumCO2 = 0;
    double sumO2 = 0;
    double sumTemp = 0;
    double sumHumidity = 0;
    for (int i = 0; i < debounceSize; i++)
    {
        if (recentMeasurements[i].Room is not null)
        {
            sumCO2 += recentMeasurements[i].CO2;
            sumO2+= recentMeasurements[i].O2;
            sumTemp+= recentMeasurements[i].Temperature;
            sumHumidity += recentMeasurements[i].Humidity;
        }
    }
    O2 = sumO2 / ((totalMeasurements > debounceSize) ? debounceSize : totalMeasurements);
    CO2 = sumCO2 / ((totalMeasurements > debounceSize) ? debounceSize : totalMeasurements);
    Temperature = sumTemp / ((totalMeasurements > debounceSize) ? debounceSize : totalMeasurements);
    Humidity = sumHumidity / ((totalMeasurements > debounceSize) ? debounceSize : totalMeasurements);
}

Ez megtakarít egy másolási műveletet. A in paraméter a hívó által már létrehozott másolatra mutató hivatkozás. A példányt a típus TakeMeasurement metódusával Room is elmentheti. Ez a módszer bemutatja, hogy a fordító hogyan biztosítja a biztonságot, ha argumentumokat refad át. Az TakeMeasurement típus kezdeti Room metódusa egy Func<SensorMeasurement, bool> típusú argumentumot vár. Ha megpróbálja hozzáadni a in vagy ref módosítót ehhez a deklarációhoz, a fordító hibát jelez. Nem adhat át argumentumot ref lambdakifejezésnek. A fordító nem tudja garantálni, hogy a hívott kifejezés nem másolja a hivatkozást. Ha a lambda kifejezés rögzíti a hivatkozást, a hivatkozás élettartama hosszabb lehet, mint a hivatkozott érték. Ha a ref biztonságos környezetén kívülre fér hozzá, memóriasérülést okozna. A ref biztonsági szabályok nem teszik lehetővé. A ref biztonsági funkcióinak áttekintésében többet is megtudhat.

Szemantikák megőrzése

A végleges módosításkészletek nem befolyásolják nagy mértékben az alkalmazás teljesítményét, mert a típusok nem gyakori elérésű útvonalakon jönnek létre. Ezek a módosítások a teljesítményhangolásban használt egyéb technikák némelyikét szemléltetik. Tekintsük meg a kezdeti Room osztályt:

public class Room
{
    public AverageMeasurement Average { get; } = new ();
    public DebounceMeasurement Debounce { get; } = new ();
    public string Name { get; }

    public IntruderRisk RiskStatus
    {
        get
        {
            var CO2Variance = (Debounce.CO2 - Average.CO2) > 10.0 / 4;
            var O2Variance = (Average.O2 - Debounce.O2) > 0.005 / 4.0;
            var TempVariance = (Debounce.Temperature - Average.Temperature) > 0.05 / 4.0;
            var HumidityVariance = (Debounce.Humidity - Average.Humidity) > 0.20 / 4;
            IntruderRisk risk = IntruderRisk.None;
            if (CO2Variance) { risk++; }
            if (O2Variance) { risk++; }
            if (TempVariance) { risk++; }
            if (HumidityVariance) { risk++; }
            return risk;
        }
    }

    public int Intruders { get; set; }

    
    public Room(string name)
    {
        Name = name;
    }

    public void TakeMeasurements(Func<SensorMeasurement, bool> MeasurementHandler)
    {
        SensorMeasurement? measure = default;
        do {
            measure = SensorMeasurement.TakeMeasurement(Name, Intruders);
            Average.AddMeasurement(measure);
            Debounce.AddMeasurement(measure);
        } while (MeasurementHandler(measure));
    }
}

Ez a típus több tulajdonságot is tartalmaz. Vannak class típusok. Egy Room objektum létrehozása több foglalást is magában foglal. Egyet magáért Room, és egyet a class típus minden egyes benne lévő tagjára. Két ilyen tulajdonságot konvertálhat class típusokról struct típusokra: a DebounceMeasurement típusokat és a AverageMeasurement típusokat. Vizsgáljuk meg ezt az átalakítást mindkét típussal.

Módosítsa a DebounceMeasurement típust a class típusról struct típusra. Ez egy fordítóhibát CS8983: A 'struct' with field initializers must include an explicitly declared constructoreredményez. Ezt egy üres paraméter nélküli konstruktor hozzáadásával javíthatja:

public DebounceMeasurement() { }

Erről a követelményről a szerkezetekről szóló nyelvi referenciacikkben tudhat meg többet.

A Object.ToString() felülbírálás nem módosítja a szerkezet egyik értékét sem. A módosító hozzáadható a readonly metódusdeklarációhoz. A DebounceMeasurement típus változtatható, ezért gondoskodnia kell arról, hogy a módosítások ne befolyásolják az eldobott másolatokat. A AddMeasurement metódus módosítja az objektum állapotát. Az Room metódus az TakeMeasurements osztályból van meghívva. A metódus meghívása után is meg szeretné őrizni ezeket a módosításokat. A Room.Debounce tulajdonságot módosíthatja úgy, hogy hivatkozást adjon vissza a DebounceMeasurement típus egy példányára.

private DebounceMeasurement debounce = new();
public ref readonly DebounceMeasurement Debounce { get { return ref debounce; } }

Az előző példában van néhány változás. Először is a tulajdonság egy csak olvasható tulajdonság, amely a helyiség tulajdonában lévő példányra mutató, csak olvasható hivatkozást ad vissza. Most már egy deklarált mező is alátámasztja, amely inicializálva van az Room objektum példányosításakor. A módosítások elvégzése után frissíteni fogja a metódus implementálását AddMeasurement . A privát háttérmezőt használja, debounce, nem a csak olvasható tulajdonságot Debounce. Így a módosítások az inicializálás során létrehozott egyetlen példányon történnek.

Ugyanez a technika működik a Average tulajdonsággal. Először módosítsa a típust egyről AverageMeasurement egyre classstruct, majd adja hozzá a readonly módosítót a ToString metódushoz:

namespace IntruderAlert;

public struct AverageMeasurement
{
    private double sumCO2 = 0;
    private double sumO2 = 0;
    private double sumTemperature = 0;
    private double sumHumidity = 0;
    private int totalMeasurements = 0;

    public AverageMeasurement() { }

    public readonly double CO2 => sumCO2 / totalMeasurements;
    public readonly double O2 => sumO2 / totalMeasurements;
    public readonly double Temperature => sumTemperature / totalMeasurements;
    public readonly double Humidity => sumHumidity / totalMeasurements;

    public void AddMeasurement(in SensorMeasurement datum)
    {
        totalMeasurements++;
        sumCO2 += datum.CO2;
        sumO2 += datum.O2;
        sumTemperature += datum.Temperature;
        sumHumidity+= datum.Humidity;
    }

    public readonly override string ToString() => $"""
        Average measurements:
            Temp:      {Temperature:F3}
            Humidity:  {Humidity:P3}
            Oxygen:    {O2:P3}
            CO2 (ppm): {CO2:F3}
        """;
}

Ezután a Room osztályt a Debounce tulajdonsághoz használt technikát követve módosítja. A Average tulajdonság egy értéket ad vissza readonly ref a magánmezőbe az átlagos méréshez. A AddMeasurement metódus módosítja a belső mezőket.

private AverageMeasurement average = new();
public  ref readonly AverageMeasurement Average { get { return ref average; } }

Kerülje a boxolást

A teljesítmény javítása érdekében van még egy utolsó változás. A fő program a szoba statisztikáinak nyomtatása, beleértve a kockázatértékelést:

Console.WriteLine($"Current intruders: {room.Intruders}");
Console.WriteLine($"Calculated intruder risk: {room.RiskStatus}");

Az ToString hívása a generált enum értéket boxolja. Ezt elkerülheti, ha felülbírálást ír az Room osztályba, amely a becsült kockázat értéke alapján formázza a sztringet:

public override string ToString() =>
    $"Calculated intruder risk: {RiskStatus switch
    {
        IntruderRisk.None => "None",
        IntruderRisk.Low => "Low",
        IntruderRisk.Medium => "Medium",
        IntruderRisk.High => "High",
        IntruderRisk.Extreme => "Extreme",
        _ => "Error!"
    }}, Current intruders: {Intruders.ToString()}";

Ezután módosítsa a kódot a fő programban az új ToString metódus meghívásához:

Console.WriteLine(room.ToString());

Futtassa az alkalmazást a profilozóval, és nézze meg a foglalások frissített táblázatát.

Foglalási grafikon a betolakodó riasztási alkalmazás módosításának utáni futtatásához.

Számos foglalást eltávolított, és teljesítménynövelő funkciót biztosított az alkalmazásnak.

Az referencia-biztonság használata az alkalmazásban

Ezek a technikák alacsony szintű teljesítményhangolást jelentenek. Javulást érhetnek el az alkalmazás teljesítményében, ha azokat a kritikus útvonalakra alkalmazzák, és ha a módosítások előtti és utáni hatást is mérik. A legtöbb esetben a következő ciklust fogja követni:

  • Mértékfoglalások: Határozza meg, hogy mely típusok vannak a leginkább lefoglalva, és mikor lehet csökkenteni a halomfoglalásokat.
  • Osztály átalakítása strukturálttá: A típusok sokszor átalakíthatók egy class osztályból egybe struct. Az alkalmazás veremterületet használ a halomfoglalások helyett.
  • Szemantikák megőrzése: A classstruct való átalakítása hatással lehet a paraméterek és a visszatérési értékek szemantikájára. Minden olyan metódusnak, amely módosítja a paramétereit, most már meg kell jelölnie ezeket a paramétereket a ref módosítóval. Ez biztosítja, hogy a módosítások a megfelelő objektumon legyenek elvégezve. Hasonlóképpen, ha a hívónak módosítania kell egy tulajdonság vagy metódus visszatérési értékét, a visszatérést a ref módosítóval kell megjelölni.
  • Kerülje a másolást: Ha egy nagy szerkezetet ad át paraméterként, a in módosítóval megjelölheti a paramétert. Kevesebb bájtban adhat át egy hivatkozást, és győződjön meg arról, hogy a metódus nem módosítja az eredeti értéket. Az értékeket readonly ref úgy is visszaadhatja, hogy olyan hivatkozást ad vissza, amely nem módosítható.

Ezekkel a technikákkal javíthatja a teljesítményt a kód gyakori elérési útjaiban.