Denne artikkelen er en speilartikkel om maskinoversettelse, vennligst klikk her for å hoppe til originalartikkelen.

Utsikt: 6317|Svare: 3

[Kilde] [Snu]. NET-ytelsesoptimaliseringer – gå raskt gjennom listesamlinger

[Kopier lenke]
Publisert 28.08.2022 kl. 20:51:16 | | | |
Kort introduksjon

System.Collections.Generic.List <T>er en generisk samlingsklasse i .NET, som kan lagre alle typer data på grunn av sin bekvemmelighet og rike API, som er mye brukt i vårt daglige liv, og kan sies å være den mest brukte samlingsklassen.

I kodeskriving må vi ofte iterere gjennom en <T>listesamling for å hente elementene i den for noe forretningsprosessering. Vanligvis er det ikke mange elementer i et sett, og det er veldig raskt å navigere. Men for noe big data-behandling, statistikk, sanntidsdatabehandling osv.<T>, hvordan kan man raskt navigere gjennom listesamlingen med titusenvis eller hundretusener av data? Det er det jeg trenger å dele med dere i dag.

Traverseringsmodus

La oss se på ytelsen til ulike traverseringsmetoder, og bygge følgende ytelsesbenchmark, ved å bruke ulik størrelsesordens samlingstraversering for å se ytelsen til ulike metoder. Kodesnippet ser slik ut:

Bruk foreach-setningen

Foreach er den vanligste måten vi går gjennom samlinger på, det er en syntaksbasert sukkerimplementering av iteratormønsteret, og det brukes også som en referanse for denne tiden.

Siden foreach-setningen er en syntaks-sugar, kaller kompilatoren til slutt GetEnumerator() og MoveNext() med en while-løkke for å implementere funksjonaliteten. Den kompilerte koden ser slik ut:



Implementasjonen av MoveNext()-metoden vil sikre at det ikke er andre tråder som endrer samlingen i iterasjonen, og hvis endringen skjer, vil den kaste et InvalidOperationException-unntak, og den vil ha en overløpssjekk for å sjekke om den nåværende indeksen er legitim, og den må også tildele det tilsvarende elementet til enumeratoren. Nåværende attributt,Så faktisk er ikke ytelsen den beste, kodeutdraget ser slik ut:



La oss se på hvordan den presterer på tvers av ulike settstørrelser, og resultatene ser slik ut:



Det kan sees at i tilfelle av ulike størrelser kreves det lineære vekstforholdet til den tidkrevende prosessen, selv om den beveger seg gjennom 100w data uten noen prosesseringslogikk, tar det minst 1 sekunder.

Bruk ForEach-metoden List

En annen vanlig måte er å bruke List<T>. ForEach()-metoden, som lar deg sende inn en <T>Handling-delegat, som kaller Handling-delegaten mens den itererer gjennom elementet<T>.

Det er en <T>intern implementeringsmetode for List, slik at den kan få direkte tilgang til private matriser og unngå overløpskontroller. I teorien burde det være raskt; Men i vårt scenario finnes det bare én tom metode, som kanskje ikke fungerer bra med et fullt inline-kall til foreach-metoden. Nedenfor er kildekoden til ForEach-metoden, som viser at den ikke har overløpskontroll, men den beholder fortsatt samtidig versjonsnummerkontroll.



I tillegg, siden det er nødvendig å sende en delegat til ForEach-metoden, vil den i kallkoden sjekke om delegatobjektet i lukkingsgenereringsklassen er tom hver gang, og hvis ikke, ny Action<T>(), som vist nedenfor:



La oss se på hvordan det sammenlignes med foreach-nøkkelordet når det gjelder ytelse. Følgende bilde viser resultatene av benchmarken:



Ut fra testresultatene er det 40 % tregere enn å bruke foreach-nøkkelordet direkte, det virker som om det ikke er nødvendig, er det et bedre valg å bruke foreach direkte, så finnes det noen raskere måte?

for loop-traversering

Tilbake til vår eldste måte, som er å bruke for-nøkkelordet for å navigere gjennom samlingen. Det bør være den best presterende traverseringsmetoden for øyeblikket, fordi den ikke krever noe redundant kode som de forrige (selv om indekseren også sjekkes for å forhindre overflow), og den sjekker åpenbart ikke versjonsnummeret, så i et multitrådet miljø endres samlingen, og det vil ikke bli noe unntak kastet når du bruker for. Testkoden ser slik ut:

La oss se hvordan det går.



Dette ser ut til å være slik vi forventer det.Å bruke for-løkken direkte er 60 % raskere enn foreach, et sett som tidligere tok 1 sekund å traversere, nå bare tar 400 millisekunder. Så finnes det en raskere måte?

Bruk CollectionsMarshal

Etter .NET5 implementerte dotnet-fellesskapet CollectionsMarshal-klassen for å forbedre ytelsen til samlingsoperasjoner. Denne klassen implementerer hvordan man får tilgang til native arrays av samlingstyper (hvis du har sett min [. .NET ytelsesoptimalisering - Du bør sette startstørrelsen for samlingstyper] artikkel, du vet at den underliggende implementeringen av mange datastrukturer er arrays). Så den kan hoppe over alle slags deteksjoner og få direkte tilgang til det opprinnelige arrayet, som bør være raskest. Koden ser slik ut:

Du kan se at koden generert av kompilatoren er veldig effektiv.



Direkte tilgang til det underliggende arrayet er veldig farlig, du må vite hva du gjør med hver kodelinje, og ha nok testing. Referanseresultatene er som følger:



JøssÅ bruke CollectionsMarshal er 79 % raskere enn å bruke foreach, men det bør være grunnen til JIT-optimalisering, det er ingen stor forskjell mellom å bruke foreach og for keyword loop Span.

sammendrag

I dag snakket jeg med deg om hvordan man raskt kan gå gjennom List-samlingen, og i de fleste tilfeller anbefales det å bruke foreach-nøkkelordet, som har både overflow-sjekk og flertrådet versjonsnummerkontroll, noe som kan gjøre det enklere for oss å skrive riktig kode.

Hvis du trenger høy ytelse og store datavolumer, anbefales det å bruke CollectionsMarshal.AsSpan direkte for å navigere gjennom samlingen.

Kildekodelenke til denne artikkelen:

Innloggingen med hyperkoblingen er synlig.

Original lenke:Innloggingen med hyperkoblingen er synlig.





Foregående:Detaljert forklaring av RabbitMQ AMQP-meldingsarkitekturen
Neste:Nettverkskabelkrystallhode T568A og T568B standard og forskjell
Publisert 2022-9-4 22:15:52 |
Lær å lære
Publisert 2022-9-8 10:33:05 |
Lær å lære
Publisert 27.06.2023 kl. 22:39:13 |
Hei 12306 Kan du sende meg en privat melding med data
Ansvarsfraskrivelse:
All programvare, programmeringsmateriell eller artikler publisert av Code Farmer Network er kun for lærings- og forskningsformål; Innholdet ovenfor skal ikke brukes til kommersielle eller ulovlige formål, ellers skal brukerne bære alle konsekvenser. Informasjonen på dette nettstedet kommer fra Internett, og opphavsrettstvister har ingenting med dette nettstedet å gjøre. Du må fullstendig slette innholdet ovenfor fra datamaskinen din innen 24 timer etter nedlasting. Hvis du liker programmet, vennligst støtt ekte programvare, kjøp registrering, og få bedre ekte tjenester. Hvis det foreligger noen krenkelse, vennligst kontakt oss på e-post.

Mail To:help@itsvse.com