Īss ievads
Veiktspējas optimizācija ir veids, kā nodrošināt, ka tāds pats pieprasījumu skaits tiek apstrādāts ar mazāk resursu, kas parasti ir CPU vai atmiņa, un, protams, operētājsistēmas IO rokturi, tīkla trafiks, diska lietojums utt. Bet lielākoties mēs samazinām CPU un atmiņas lietojumu. Iepriekš kopīgotajam saturam ir daži ierobežojumi, to ir grūti tieši pārveidot, šodien es vēlos dalīties ar jums vienkāršu metodi, tikai jāaizstāj daži kolekcijas veidi, lai panāktu veiktspējas uzlabošanu un atmiņas nospieduma samazināšanu. Šodien es vēlos dalīties ar jums klases bibliotēkā, kas ir šīKlases bibliotēkas nosaukums ir Collections.Pooled, Kā redzams no nosaukuma, tas ir caur apvienoto atmiņu, lai sasniegtu mērķi samazināt atmiņas nospiedumu un GC, un mēs tieši redzēsim, kā tā veiktspēja ir, un mēs arī aizvedīsim jūs redzēt avota kodu, kāpēc tas rada šos veiktspējas uzlabojumus.
Kolekcijas.Apvienots
Projekta saite:Hipersaites pieteikšanās ir redzama.
Bibliotēka ir balstīta uz System.Collections.Generic klasēm, kas ir modificētas, lai izmantotu jaunās System.Span <T>un System.Buffers.ArrayPool <T>klases bibliotēkas, lai samazinātu atmiņas piešķiršanu, uzlabotu veiktspēju un nodrošinātu lielāku sadarbspēju ar mūsdienu API. Collections.Pooled atbalsta .NET Standnd 2.0 (.NET Framework 4.6.1+), kā arī atbalstu . NET Core 2.1+. Plašs vienību testu un etalonu kopums ir pārnests no CoreFX.
Kopējais testu skaits: 27501. Caur: 27501. Neveiksme: 0. Izlaist: 0. Testa izpilde bija veiksmīga. Testa izpildes laiks: 9.9019 sekundes
Kā lietot
Šo bibliotēku var viegli instalēt, izmantojot Nuget, NuGet versiju.
Collections.Pooled bibliotēkā tā ievieš apkopotas versijas kolekciju tipiem, kurus mēs parasti izmantojam, kā parādīts salīdzinājumā ar .NET vietējiem tipiem.
| . .NET vietējā | Kolekcijas.Apvienots | Piezīme | | Saraksts<T> | Apvienotais saraksts<T> | Vispārīgās kolekcijas klases | | Vārdnīca<TKey, TValue> | PooledDictionary<TKey, TValue> | Vispārējās vārdnīcas klase | | Jaucējkods<T> | Apvienotais komplekts<T> | Vispārējās jaucējkodu kolekcijas klases | | Kaudze<T> | Kaudze<T> | Vispārējās kaudzes | | Rindu<T> | PooledQueue<T> | Vispārējā kohorta |
Lietojot, mums ir jāpievieno tikai atbilstošais . .NET vietējā versija ar Collections.Pooled versiju, kā parādīts zemāk esošajā kodā:
Tomēr mums jāatzīmē, ka Pooled tips ievieš IDispose interfeisu, kas atgriež izmantoto atmiņu baseinā, izmantojot Dispose() metodi, tāpēc mums ir jāizsauc tā Dispose() metode pēc Pooled kolekcijas objekta izmantošanas. Vai arī varat izmantot atslēgvārdu var tieši.
Piezīme: Kolekcijas objekta izmantošana Collections.PooledVislabāk ir to atbrīvot manuāli, bet nav svarīgi, ja jūs to neatbrīvojat, GC galu galā to pārstrādās, bet to nevar atgriezt baseinā, un tas nesasniegs atmiņas taupīšanas efektu. Tā kā tas atkārtoti izmanto atmiņas vietu, atgriežot atmiņas vietu baseinā, tam ir jāapstrādā kolekcijas elementi, un tas nodrošina uzskaitījumu ar nosaukumu ClearMode lietošanai, kas definēts šādi:
Pēc noklusējuma varat izmantot noklusējuma vērtību Automātiski, un, ja ir īpašas veiktspējas prasības, varat izmantot Nekad, zinot riskus. Atsauces tipiem un vērtību tipiem, kas satur atsauces tipus, mums ir jāiztukšo masīva atsauce, atgriežot atmiņas vietu baseinā, ja tas nav notīrīts, GC nevarēs atbrīvot šo atmiņas vietas daļu (jo elementa atsauce vienmēr ir bijusi baseinā), ja tas ir tīrs vērtības tips, tad to nevar iztukšot, šajā rakstā es aprakstu krātuves atšķirību starp atsauces tipiem un struct (vērtības tipa) masīviem, tīriem vērtību tipiem nav objekta galvenes pārstrādes un tiem nav nepieciešama GC iejaukšanās.
. .NET veiktspējas optimizācija — izmantojiet strukturēšanas alternatīvas klases:Hipersaites pieteikšanās ir redzama.
Veiktspējas salīdzinājums
Es nedarīju tikai Benchmark, un atvērtā koda projektu darbības rezultātu rezultāti, kurus es tieši izmantoju, bija 0 daudzu projektu atmiņas izmantošanai, kas bija tāpēc, ka apvienotajai atmiņai nebija papildu piešķīruma.
Apvienotais saraksts<T>
Cilpa caur 2048 elementiem, kas pievienoti kopai etalonā, . .NET vietējais saraksts <T>prasa 110us (saskaņā ar faktiskajiem etalona rezultātiem milisekundēm attēlā vajadzētu būt pārrakstīšanās kļūdai) un 263 KB atmiņu, bet PooledList <T>vajag tikai 36us un 0 KB atmiņu.
PooledDictionary<TKey, TValue>
Pievienojiet vārdnīcai 10_0000 elementus cilpā etalonā, . .NET vietējā vārdnīca<TKey, TValue> prasa 11 ms un 13 MB atmiņas, savukārt PooledDictionary<TKey, TValue> prasa tikai 7 ms un 0 MB atmiņas.
Apvienotais komplekts<T>
Cilpa caur jaucējkodu kolekciju etalonā pievienojiet 10_0000 elementus, . .NET vietējam HashSet <T>ir nepieciešami 5348 ms un 2 MB, savukārt PooledSet <T>prasa tikai 4723 ms un 0 MB atmiņu.
PooledStack<T>
Veiciet ciklu caur etalona steku, lai pievienotu 10_0000 elementus, . .NET vietējais PooledStack <T>prasa 1079 ms un 2 MB, savukārt PooledStack <T>prasa tikai 633 ms un 0 MB atmiņu.
PooledQueue<T>
Cilpa cilpām etalonā, lai rindai pievienotu 10_0000 elementus, . .NET vietējai <T>PooledQueue ir nepieciešami 681 ms un 1 MB, savukārt PooledQueue <T>ir nepieciešami tikai 408 ms un 0 MB atmiņas.
Aina netiek manuāli atbrīvota
Turklāt mēs iepriekš minējām, ka apvienotās kolekcijas veids ir jāatbrīvo, bet nav svarīgi, vai tas netiek izlaists, jo GC tiks pārstrādāts.
Etalona rezultāti ir šādi:
Secinājumu var izdarīt no iepriekš minētajiem etalona rezultātiem.
Atbrīvojot apvienoto tipu kolekciju laikā, GC tikko tiek aktivizēts GC un tiek piešķirta atmiņa, no iepriekš redzamā grafika tas piešķir tikai 56 baitus atmiņas. Pat ja apvienoto tipu kolekcija netiek izlaista, jo tā piešķir atmiņu no pūla, tā joprojām atkārtoti izmantos atmiņu ReSize paplašināšanas operācijas laikā un izlaidīs GC piešķiršanas atmiņas inicializācijas soli, kas ir salīdzinoši ātrs. Lēnākais ir izmantot parasto kolekcijas veidu, katrai ReSize paplašināšanas operācijai ir jāpiemēro jauna atmiņas vieta, un GC ir jāatgūst arī iepriekšējā atmiņas vieta.
Principu analīze
Ja esat izlasījis manu iepriekšējo emuāra ziņu, jums vajadzētu iestatīt sākotnējo kolekcijas veidu lielumu un analizēt C# vārdnīcas ieviešanas principu, jūs varat zināt, ka .NET BCL izstrādātāji izmanto šo pamata kolekcijas veidu pamatā esošās datu struktūras, lai būtu masīvi augstas veiktspējas nejaušai piekļuvei, ņemsim sarakstu <T>kā piemēru.
Izveidojiet jaunu masīvu, lai saglabātu pievienotos elementus. Ja masīvā nav pietiekami daudz vietas, tiek aktivizēta paplašināšanas operācija, lai pieprasītu divreiz lielāku vietu. Konstruktora kods ir šāds, un jūs varat redzēt, ka tas ir vispārējs masīvs, kas izveidots tieši:
Tātad, ja vēlaties apvienot atmiņu, jums ir jāmaina tikai vieta, kur klases bibliotēkā tiek izmantota jaunā atslēgvārda lietojumprogramma, lai izmantotu apvienoto lietojumprogrammu. Šeit es dalos ar jums. NET BCL ir veids, ko sauc par ArrayPool, kas nodrošina atkārtoti izmantojamu vispārēju instancju masīvu resursu kopumu, ko var izmantot, lai samazinātu spiedienu uz GC un uzlabotu veiktspēju biežas masīva izveides un iznīcināšanas gadījumā.
Mūsu Pooled tipa pamatā ir izmantot ArrayPool, lai koplietotu resursu baseinus, un no tā konstruktora mēs varam redzēt, ka tas izmanto ArrayPool pēc noklusējuma<T>. Koplietots, lai piešķirtu masīva objektus, un, protams, jūs varat arī izveidot savu ArrayPool, lai to izmantotu.
Turklāt, veicot jaudas regulēšanas operāciju (paplašināšanu), vecais masīvs tiek atgriezts pavedienu baseinā, un jaunais masīvs tiek iegūts arī no baseina.
Turklāt autors izmanto Span, lai optimizētu API, piemēram, Add un Insert, lai nodrošinātu labāku brīvpiekļuves veiktspēju. Turklāt ir pievienota TryXXX sērijas API, lai to varētu izmantot ērtāk. Piemēram, List <T>klasei <T>ir līdz 170 modifikācijām, salīdzinot ar PooledList.
Kopsavilkuma
Mūsu faktiskajā tiešsaistes lietošanā mēs varam aizstāt vietējo kolekcijas veidu ar kolekcijas veidu, ko nodrošina Pooled, kas ir ļoti noderīgi, lai samazinātu atmiņas lietojumu un P95 latentumu. Turklāt, pat ja aizmirstat to atbrīvot, veiktspēja nebūs daudz sliktāka nekā vietējā kolekcijas veida izmantošana. Protams, labākais ieradums ir to savlaicīgi atbrīvot.
Sākotnējā:Hipersaites pieteikšanās ir redzama.
|