Tehtävä- tai tehtäväluokkien käytössä on suorituskyvyn pullonkaula, jota emme maininneet aiemmissa artikkeleissa. Lyhyesti sanottuna nämä kurssit johtavat, kun tulokset ovat heti saatavillaTurha allokaatio。 Tämä tarkoittaa, että uusi tehtävä tai tehtäväobjekti luodaan aina, vaikka tulos olisi jo saatavilla. Mainitsimme, että aiemmissa artikkeleissa käytetty asynkronisoitu/odotuskonsepti on ollut olemassa .NET 4.5 -julkaisusta lähtien. Tätä ominaisuutta on parannettu C# 7:stä lähtien .NET 4.7 -versiolla, jossa on ValueTask-rakenne, jota voidaan käyttää asynkronisten funktioiden palautuksena.
ValueTask -rakenne
ValueTask-rakenne ilmestyi ensimmäisen kerran corefxlab-tietovarastossa vuonna 2015. Tätä arkistoa käytetään kokeilemaan ja tutkimaan uusia ideoita, jotka saattavat päätyä pääasialliseen corefx-tietovarastoon tai eivät. Corefx-repositorio on se arkisto, jossa kaikki .NET Core -peruskirjastot sijaitsevat. Sen kehitti ja ehdotti Stephen Taub System.Threading.Tasks.Channels -kirjastoon. Tuolloin Stephen antoi lyhyen selityksen:
COREFXLAB-kirjaston osoite:Hyperlinkin kirjautuminen on näkyvissä.
ValueTask on erillinen yhdistelmä T:stä ja Taskista, jonka avulla ReadAsync voi vapaasti allokatoida ja palauttaa käytettävissä olevat T-arvonsa synkronisesti (toisin kuin Task.FromResult, joka vaatii Task-instanssin allokointia). ValueTask on odotettavissa oleva, joten useimpien instanssien kulutus on erottamaton tehtävien kulutuksesta. Monet näkevät tämän rakenteen hyödyt, sillä se sisältyy C# 7:ään osana System.Threading.Tasks.Extensions NuGet -pakettia. Ennen kuin sukellamme ValueTask-rakenteeseen, tarkastellaan ongelmaa, jota se ratkaisee. Koska Task(Task) on viitetyyppi, aloitetaanAsynkroninen metodi, joka palauttaa Tehtävä-objektin, tarkoittaa, että se on varattu kekolle joka kerta。 Tämä on monissa tapauksissa välttämätöntä.
Joissakin tapauksissa asynkroniset menetelmät palauttavat tulokset välittömästi tai kokonaan synkronisesti. Näissä tapauksissa tämä allokaatio on tarpeetonta ja voi käydä kalliiksi koodin suorituskykykriittisissä osissa. Ennen .NET 4.7 -julkaisua tätä ei voinut välttää, sillä asynkronisten metodien piti palauttaa Task, Task <T>tai void (viimeinen yleensä ei-toivottu). Tässä .NET-versiossa tämä on laajennettu, mikä tarkoittaa, että asynkroninen metodi voi palauttaa minkä tahansa tyypin, kunhan sillä on saatavilla oleva GetAwaiter-metodi. ValueTask on konkreettinen esimerkki tästä tyypistä, ja se lisättiin myös tähän julkaisuun.
Voit selata corefx-tietovarastoa ja nähdä ValueTaskin koko toteutuksen, tässä on API-osio, joka kiinnostaa:
Rakenteena ValueTask mahdollistaa asynkronisten metodien kirjoittamisen, jotka eivät varaa muistia synkronisen suorituksen aikana. API:n johdonmukaisuus asynkronisen/odotuskonseptin osalta ei ole vaarantunut. Lisäksi tämä rakenne odottaa itsenäisesti, mikä tekee siitä helppokäyttöisen. Esimerkiksi, jos suoritamme tämän yksinkertaisen koodin:
MultiplyAsync-menetelmässä simuloimme tilannetta, jossa haluamme välttää Tehtävän käyttöä ja palauttaa vain yksinkertaisen kokonaisluvun. Tämä tehdään metodin if-lauseessa, jossa käytännössä tarkistetaan, onko ohitettu parametri nolla. Ongelma onVaikka ehtomme if-lauseessa olisi tosi, yllä oleva koodi luo Task-objektin。 Ratkaisemme tämän ongelman näin:
ValueTask ja Task
Kuten aiemmin mainittiin, ValueTaskin käytössä on kaksi pääasiallista hyötyä:
- Suorituskyvyn parannukset
- Lisää käyttöönoton joustavuutta
Joten, mitkä ovat suorituskyvyn parannusten taustalla olevat luvut? Seuraa tätä koodia:
Jos ajamme tämän koodin, JIT:n suorittamiseen menee 120 ns. Nyt, jos korvaamme Taskin ValueTaskilla näin:
JIT:llä saamme 65 ns:n suoritusajan. On totta, että Task.Delayn vuoksi emme suorita sitä synkronisesti, mutta näemme parannuksen suoritusajassa.
Toinen mainitsemamme etu on toteutuksen lisääntynyt joustavuus. Mitä tämä tarkalleen ottaen tarkoittaa? Asynkronisten rajapintojen toteutukset, jotka pitäisi synkronoida, pakotetaan käyttämään Task.Run- tai Task.FromResultia. Tämä johtaa tietenkin aiemmin käsittelemiimme suorituskykyongelmiin. Kun käytämme ValueTaskia, valitsemme todennäköisemmin synkronisen tai asynkronisen toteutuksen välillä. Muista, että tämä voi olla merkki siitä, että koodisi ei välttämättä ole hyvin suunniteltu, jos näin käy sinulle.
Esimerkiksi tarkastellaan tätä rajapintaa:
Oletetaan, että haluat kutsua sitä tällaisesta koodista:
Koska käytämme ValueTaskia rajapinnassa, rajapinnan toteutus voi olla synkronista tai asynkronista. Voimme saada tämän hyödyn käytännössä jättämällä väliin joitakin synkronointitoimintoja lisääviä funktioita IThingiin. Tämän käyttöliittymän käyttö on paljon helpompaa. Tässä on yllä olevan rajapinnan synkroninen toteutus:
Tässä on saman käyttöliittymän asynkroninen toteutus:
Meidän on kuitenkin otettava huomioon joitakin kompromisseja ennen ValueTaskin käyttöä. On helppo ajatella, että ValueTaskia pitäisi käyttää oletuksena Taskin sijaan, mikä ei todellakaan pidä paikkaansa. Esimerkiksi, vaikka ValueTask auttaa välttämään tarpeettomia tehtäviä, kun tulosten synkronointi on saatavilla, se sisältää myös kaksi kenttää.
On tärkeää muistaa, että tämä on rakenne, jota tässä käytämme, eli käytämme arvotyyppejä ja kaikkia niiden taakkoja. Tehtävä puolestaan on viitetyyppi, jossa on vain yksi kenttä.Kun käytät ValueTaskia, meillä on enemmän dataa käsiteltävänä ja käsiteltävänä. Jos tällaista menetelmää odotetaan asynkronisessa menetelmässä, niin asynkroninen menetelmä onValtiokone tulee myös olemaan suurempi, koska koko rakenteen tallentaminen vaatii yleensä enemmän tilaa kuin yhden viitteen tallentaminen.
Siksi Microsoftin väki suosittelee käyttämään Tehtävää tai Tehtävää oletuspalautustyyppinä asynkronisille metodeille. Vasta suorituskykyanalyysin jälkeen kannattaa harkita siirtymistä ValueTaskiin.
yhteenveto
ValueTask on rakenne, joka esiteltiin .NET 4.7:ssä ja tarjoaa meille paljon mahdollisuuksia käyttää asynkronisia menetelmiä .NET:ssä. Kuitenkin se ei ole ilman hintaa. Tämä on hyödyllistä suorituskykykriittisissä menetelmissä, jotka suoritetaan synkronisesti. Niiden avulla voimme välttää tarpeettomien objektien määrittämisen. Silti, arvotyyppinä siihen liittyy kaikki ne ongelmat, joita arvotyypeillä yleensä on. Siksi voimme hyötyä tästä rakenteesta, mutta meidän on oltava varovaisia.
Alkuperäinen osoite:Hyperlinkin kirjautuminen on näkyvissä.
|