2023 දී ආරම්භ වන විට 1.20 Go පරිශීලකයින්ට පරීක්ෂා කිරීම සඳහා. ප්රමුඛ දැක්ම තුළ දැනගත් සීමාවන් විසඳා ගැනීමෙන් පසුව, සහ සමාජයේ ප්රතිපත්තිය සහ ප්රවේශයන් මගින් වැඩි දියුණු කිරීම් සමඟ, Go 1.21 හි PGO සහාය සාමාන්ය නිෂ්පාදන භාවිතය සඳහා සූදානම් වේ! සම්පූර්ණ ලේඛන සඳහා Profile-Guided Optimization (PGO) ලෙස හැඳින්වීම Profile-guided Optimization පරිශීලක උපදෙස් අපි යෙදුම ක්රියාකාරීත්වය වැඩි දියුණු කිරීම සඳහා PGO භාවිතා කිරීම සඳහා උදාහරණයක් හරහා ක්රියාත්මක වනු ඇත.We will run through an example of using PGO to improve the performance of an application.Before we get to that, what exactly is “profile-guided optimization”? පහළ උදාහරණයක් ලෙස, ස්ථාවර ප්රදර්ශනය පරිවර්තනය කාලය තුළ ස්ථාවර ප්රදර්ශන අගය කළ හැකි අතර, ක්රියාකාරීව ක්රියාකාරීව ක්රියාකාරීව ක්රියාකාරීව ක්රියාකාරීව ක්රියාකාරීව ක්රියාකාරීව ක්රියාකාරීව ක්රියාකාරීව ක්රියාකාරීව ක්රියාකාරීව ක්රියාකාරීව ක්රියාකාරීව ක්රියාකාරීව ක්රියාකාරීව ක්රියාකාරීව ක්රියාකාරීව ක්රියාකාරීව ක්රියාකාරීව ක්රියාකාරීව ක්රියාකාරීව ක්රියාකාරීව ක්රියාකාරීව ක්රියාකාරීව ක්රියාකාරීව ක්රියාකාරීව ක්රියාකාරීව Go ප්රදර්ශනයෙන් ප්රදර්ශනය දක්වා optimizations වැඩි දියුණු කරයි, නමුත් එසේ කිරීම පහසු කාර්යයක් නොවේ. සමහර optimizations සංසන්දනය කළ හැකි, නමුත් පරිවර්තකය සෑම පරිශීලකයටම "තව 11 දක්වා" "පරවර්තනය" කළ නොහැක, එබැවින් අතිශයින් ආක් රමණීය පරිශීලකයන් සැබවින්ම ප්රතිඵලදායිතාවයට හානි කළ හැකි හෝ වැඩිපුර ඉදිකිරීම් කාලය හේතු විය හැක. නැත්නම් පුලුවන්ද? නිෂ්පාදන පරිසරය තුළ කේතය භාවිතා කරන ආකාරය පිළිබඳ නිශ්චිත තොරතුරු නොමැතිව, පරිවර්තකය පැකේජයේ මූලාශ්ර කේතය මත පමණක් වැඩ කළ හැකිය. අපි පරිගණකයට ප්රවේශයක් සපයන විට, එය වඩාත් තොරතුරු දැනුවත් තීරණ ගත හැකිය: වඩාත් නිතර භාවිතා කරන කාර්යයන් වඩාත් ආක් රමණය කිරීම, හෝ වඩාත් නිශ්චිතව පොදු ප්රවණතා තෝරා ගැනීම. ප් රොෆයිල් compiler optimization සඳහා application behavior profiles භාවිතා කිරීම ලෙස හැඳින්වේ. Feedback-Directed Optimization (FDO) ලෙස හඳුන්වනු ලැබේ. Profile-Guided Optimization (PGO) ලෙස හැඳින්වීම උදාහරණයක් Markdown වෙත HTML බවට පරිවර්තනය කරන සේවා නිර්මාණය කරමු: පරිශීලකයින් Markdown මූලාශ්රය උඩුගත කරන්න , HTML පරිවර්තනය ලබා දෙයි.අපි භාවිතා කළ හැකිය මෙය පහසුවෙන් ක් රියාත්මක කරන්න. /render gitlab.com/golang-commonmark/markdown ස්ථාපනය $ go mod init example.com/markdown $ go get gitlab.com/golang-commonmark/markdown@bf3e522c626a එයට : main.go package main import ( "bytes" "io" "log" "net/http" _ "net/http/pprof" "gitlab.com/golang-commonmark/markdown" ) func render(w http.ResponseWriter, r *http.Request) { if r.Method != "POST" { http.Error(w, "Only POST allowed", http.StatusMethodNotAllowed) return } src, err := io.ReadAll(r.Body) if err != nil { log.Printf("error reading body: %v", err) http.Error(w, "Internal Server Error", http.StatusInternalServerError) return } md := markdown.New( markdown.XHTMLOutput(true), markdown.Typographer(true), markdown.Linkify(true), markdown.Tables(true), ) var buf bytes.Buffer if err := md.Render(&buf, src); err != nil { log.Printf("error converting markdown: %v", err) http.Error(w, "Malformed markdown", http.StatusBadRequest) return } if _, err := io.Copy(w, &buf); err != nil { log.Printf("error writing response: %v", err) http.Error(w, "Internal Server Error", http.StatusInternalServerError) return } } func main() { http.HandleFunc("/render", render) log.Printf("Serving on port 8080...") log.Fatal(http.ListenAndServe(":8080", nil)) } සේවාදායකය නිර්මාණය කිරීම සහ ක්රියාත්මක කිරීම: $ go build -o markdown.nopgo.exe $ ./markdown.nopgo.exe 2023/08/23 03:55:51 Serving on port 8080... අපි වෙනත් terminal වලින් Markdown යවන්න උත්සාහ කරමු. උදාහරණයක් ලෙස Go ව්යාපෘතියෙන්: README.md $ curl -o README.md -L "https://raw.githubusercontent.com/golang/go/c16c2c49e2fa98ae551fc6335215fadd62d33542/README.md" $ curl --data-binary @README.md http://localhost:8080/render <h1>The Go Programming Language</h1> <p>Go is an open source programming language that makes it easy to build simple, reliable, and efficient software.</p> ... ප් රොෆයිල් දැන් අපි ක්රියාකාරී සේවාවක් ඇති අතර, අපි වඩා හොඳ ප්රතිඵල ලබා ගැනීමට PGO සමඟ ප්රශ්නයක් එකතු කර නැවත ගොඩනඟා බලමු. එයට අපි ආනයනය කළා ස්වයංක් රීයව එකතු කරන A CPU Profile එකක් හොයා ගන්න Server එකෙන්. main.go අන්තර්ජාලය / HTTP / PPProf /debug/pprof/profile සාමාන්යයෙන් ඔබ ඔබේ නිෂ්පාදන පරිසරයෙන් ප්රවේශයක් රැස් කිරීමට අවශ්ය වේ, එබැවින් පරිවර්තනයක නිෂ්පාදන ක්රියාකාරකම් පිළිබඳ ප්රදර්ශනීය දර්ශනයක් ලබා දෙයි. අපි ප්රශ්නය රැස් කරන අතර ප්රවේශයක් නිර්මාණය කිරීම සඳහා. ෆේට් සහ ප්රවේශ ජෙනරාටර් ආරම්භ කරන්න (සර්වර් තවමත් ක්රියාත්මක වන බව තහවුරු කරන්න!): සරල වැඩසටහන $ go run github.com/prattmic/markdown-pgo/load@latest එය ක්රියා කරන අතර, සේවාදායකයෙන් ප්රශ්නයක් බාගත කරන්න: $ curl -o cpu.pprof "http://localhost:8080/debug/pprof/profile?seconds=30" මෙය සම්පූර්ණ වන විට, load generator සහ server එක මරන්න. Profile භාවිතා කිරීම Go toolchain ස්වයංක්රීයව PGO ක්රියාත්මක කරනු ඇත, එය නමැති ප් රොෆයිල් සොයා ගනු ඇත ප් රමුඛ පණිවුඩය - ප් රමුඛ පණිවුඩය පුවරුව PGO සඳහා භාවිතා කිරීමට ප් රොෆයිල් වෙත මාර්ගය ගත යුතුය. default.pgo -pgo go build අපි යෝජනා කරනවා commit ඔබගේ ප්රවර්ග කේතය සමඟ ප්රවර්ග ලැයිස්තුවක් ගබඩා කිරීමෙන්, පරිශීලකයින්ට ප්රවර්ගයට (විශේෂය පාලනය පද්ධතිය හරහා හෝ හරහා) සරලව ප්රවර්ගයට ප්රවේශයක් ඇති බව සහතික කරයි. ඒ ගොඩනැගිලි තවමත් ප් රතිපත්තියි. default.pgo go get අපි හදමු : $ mv cpu.pprof default.pgo $ go build -o markdown.withpgo.exe අපි පරීක්ෂා කළ හැක්කේ PGO ක්රියාකාරී වී ඇති බව ඉදිකිරීම් සමග : go version $ go version -m markdown.withpgo.exe ./markdown.withpgo.exe: go1.21.0 ... build -pgo=/tmp/pgo121/default.pgo විශ්ලේෂණය අපි benchmark එක පාවිච්චි කරනවා. PGO හි ප්රතිඵල මත බලපෑම අගය කිරීම. Load Generator එක පළමුව, අපි PGO නොමැතිව සේවාදායකය benchmark කරමු. $ ./markdown.nopgo.exe එය ක්රියා කරන අතර, කිහිපයක් benchmark iterations ක්රියාත්මක කරන්න: $ go get github.com/prattmic/markdown-pgo@latest $ go test github.com/prattmic/markdown-pgo/load -bench=. -count=40 -source $(pwd)/README.md > nopgo.txt එය සම්පූර්ණ වන විට, මුල් සේවාදායකය මරන්න සහ PGO සමඟ අනුවාදය ආරම්භ කරන්න: $ ./markdown.withpgo.exe එය ක්රියා කරන අතර, කිහිපයක් benchmark iterations ක්රියාත්මක කරන්න: $ go test github.com/prattmic/markdown-pgo/load -bench=. -count=40 -source $(pwd)/README.md > withpgo.txt එය සම්පූර්ණ වන විට, අපි ප්රතිඵල සංසන්දනය කරමු: $ go install golang.org/x/perf/cmd/benchstat@latest $ benchstat nopgo.txt withpgo.txt goos: linux goarch: amd64 pkg: github.com/prattmic/markdown-pgo/load cpu: Intel(R) Xeon(R) W-2135 CPU @ 3.70GHz │ nopgo.txt │ withpgo.txt │ │ sec/op │ sec/op vs base │ Load-12 374.5µ ± 1% 360.2µ ± 0% -3.83% (p=0.000 n=40) නව අනුවාදය වේගයෙන් 3.8% ක් පමණ වේගවත් වේ! Go 1.2 හි, වැඩපිළිවෙළ සාමාන් යයෙන් 2% සහ 7% අතර CPU භාවිතය වැඩි දියුණු වීමෙන් PGO ක්රියාත්මක කිරීමෙන් ලබා දෙයි. ප්රශ්න යෙදුම් හැසිරීම පිළිබඳ බොහෝ තොරතුරු ඇතුළත් වන අතර, Go 1.21 මෙම තොරතුරු සීමිත සීමාවක් සඳහා භාවිතා කිරීමෙන් පෘථිවිය බිඳ වැටීමට පටන් ගනී. ඊළඟ පියවර මෙම උදාහරණයේ දී, ප්රශ්නය එකතු කිරීමෙන් පසු, අපි මුල් සංස්කරණය තුළ භාවිතා කරන එකම මූලාශ්ර කේතය භාවිතා කිරීමෙන් අපගේ සේවාදායකය නැවත ගොඩනඟා ගනිමු. සැබෑ ලෝකයක් තුළ, සෑම විටම සංවර්ධනය සිදු වේ. එබැවින් අපි පසුගිය සතියේ කේතය ක්රියාකාරී වන නිෂ්පාදන ප්රශ්නය එකතු කළ හැකි අතර එය අද වන මූලාශ්ර කේතය සමඟ ගොඩනඟා ගැනීම සඳහා භාවිතා කළ හැකිය. එය සම්පූර්ණයෙන්ම හොඳයි! PGO in Go ප්රශ්නයක් නොමැතිව මූලාශ්ර කේතයට කුඩා වෙනසක් කළ හැකිය. PGO භාවිතා කිරීම, හොඳම ක්රියාකාරකම් සහ අනතුරු ඇඟවීම ගැන වැඩි විස්තර සඳහා, කරුණාකර බලන්න ඔබ කුතුහලය නම් කුමක් සිදුවේද පහලට, කියවීම දිගටම! Profile-guided Optimization පරිශීලක උපදෙස් Hood යටතේ මෙම යෙදුම වේගවත් කර ඇති දේ වඩාත් හොඳින් තේරුම් ගැනීම සඳහා, ක්රියාකාරකම් වෙනස් වී ඇති ආකාරය දකින්න පිටුපස බලමු.We will take a look at two different PGO driven optimizations. INLINING Inlining වැඩි දියුණු කිරීම් නිරීක්ෂණය කිරීම සඳහා, PGO සමඟ සහ නොමැතිව මෙම markdown යෙදුම විශ්ලේෂණය කරමු. මම මෙය සංසන්දනය කරන්නම් differential profiling යන තාක්ෂණය භාවිතා කරන අතර, එහිදී අපි ප්රශ්න දෙකක් (PGO සමග එක් සහ කිසිදු) එකතු කර එය සසඳන්න. , එකම ප්රමාණයක් නොවේ, එබැවින් මම ස්වයංක්රීයව ප්රශ්න රැස්වීම සඳහා සේවාදායකය සකස් කර ඇති අතර, තැබූ ඉල්ලීම් සංඛ්යාවක් යැවීමට හා ඉන්පසු සේවාදායකයෙන් පිටතට යැවීමට ප්රවේශ Generator. work මම සේවාදායකයට සිදු කරන ලද වෙනස්කම් සහ එකතු කරන ලද ප් රොෆයිල් සොයා ගත හැකිය: එන්ජිම ජෙනරාටර් එකත් එක්ක වැඩ කළා. . https://github.com/prattmic/markdown-pgo -count=300000 -quit වේගවත් අනුකූලතාව පරීක්ෂා කිරීම සඳහා, සියලුම 300k ඉල්ලීම් කළමනාකරණය කිරීම සඳහා අවශ්ය මුළු CPU කාලය දෙස බලමු: $ go tool pprof -top cpu.nopgo.pprof | grep "Total samples" Duration: 116.92s, Total samples = 118.73s (101.55%) $ go tool pprof -top cpu.withpgo.pprof | grep "Total samples" Duration: 113.91s, Total samples = 115.03s (100.99%) CPU කාලය ~118s සිට ~115s දක්වා පහත වැටී, හෝ 3% ක් පමණ වේ. දැන් අපි ඉතිරි සොයන්න වෙනස් ප්රශ්නය විවෘත කළ හැකිය: $ go tool pprof -diff_base cpu.nopgo.pprof cpu.withpgo.pprof File: markdown.profile.withpgo.exe Type: cpu Time: Aug 28, 2023 at 10:26pm (EDT) Duration: 230.82s, Total samples = 118.73s (51.44%) Entering interactive mode (type "help" for commands, "o" for options) (pprof) top -cum Showing nodes accounting for -0.10s, 0.084% of 118.73s total Dropped 268 nodes (cum <= 0.59s) Showing top 10 nodes out of 668 flat flat% sum% cum cum% -0.03s 0.025% 0.025% -2.56s 2.16% gitlab.com/golang-commonmark/markdown.ruleLinkify 0.04s 0.034% 0.0084% -2.19s 1.84% net/http.(*conn).serve 0.02s 0.017% 0.025% -1.82s 1.53% gitlab.com/golang-commonmark/markdown.(*Markdown).Render 0.02s 0.017% 0.042% -1.80s 1.52% gitlab.com/golang-commonmark/markdown.(*Markdown).Parse -0.03s 0.025% 0.017% -1.71s 1.44% runtime.mallocgc -0.07s 0.059% 0.042% -1.62s 1.36% net/http.(*ServeMux).ServeHTTP 0.04s 0.034% 0.0084% -1.58s 1.33% net/http.serverHandler.ServeHTTP -0.01s 0.0084% 0.017% -1.57s 1.32% main.render 0.01s 0.0084% 0.0084% -1.56s 1.31% net/http.HandlerFunc.ServeHTTP -0.09s 0.076% 0.084% -1.25s 1.05% runtime.newobject (pprof) top Showing nodes accounting for -1.41s, 1.19% of 118.73s total Dropped 268 nodes (cum <= 0.59s) Showing top 10 nodes out of 668 flat flat% sum% cum cum% -0.46s 0.39% 0.39% -0.91s 0.77% runtime.scanobject -0.40s 0.34% 0.72% -0.40s 0.34% runtime.nextFreeFast (inline) 0.36s 0.3% 0.42% 0.36s 0.3% gitlab.com/golang-commonmark/markdown.performReplacements -0.35s 0.29% 0.72% -0.37s 0.31% runtime.writeHeapBits.flush 0.32s 0.27% 0.45% 0.67s 0.56% gitlab.com/golang-commonmark/markdown.ruleReplacements -0.31s 0.26% 0.71% -0.29s 0.24% runtime.writeHeapBits.write -0.30s 0.25% 0.96% -0.37s 0.31% runtime.deductAssistCredit 0.29s 0.24% 0.72% 0.10s 0.084% gitlab.com/golang-commonmark/markdown.ruleText -0.29s 0.24% 0.96% -0.29s 0.24% runtime.(*mspan).base (inline) -0.27s 0.23% 1.19% -0.42s 0.35% bytes.(*Buffer).WriteRune නිශ්චිත කරන විට , pprof දී ප්රදර්ශනය කරන ලද ප්රමාණයන් ප් රවර්ග දෙක අතර, උදාහරණයක් ලෙස PGO සමග 0.46s අඩු CPU කාලය භාවිතා කර ඇත. එනම්, මෙම ප්රතිඵල ප්රතිඵල ප්රතිඵල ප්රතිඵල ප්රතිඵල ප්රතිඵල ප්රතිඵල ප්රතිඵල ප්රතිඵල ප්රතිඵල ප්රතිඵල ප්රතිඵල ප්රතිඵල ( සහ ප් රතිශත ගණන, ප් රතිශත ගණන තේරුමක් නැති නිසා. pprof -diff_base වෙනස runtime.scanobject gitlab.com/golang-commonmark/markdown.performReplacements flat cum ප්රධාන වෙනස්කම් සංඛ්යාත වෙනස්කම් මගින් පෙන්වයි.එනම්, ක්රියාකාරිත්වයේ CPU වෙනස සහ එම ක්රියාකාරිත්වයෙන් සියලු transitive පාරවල්.This will generally show the outermost frames in our program's call graph, such as: මෙතැනදී අපි දකිනවා බොහෝමයක් ආදායම් ආදායම් එන්නේ HTTP ඉල්ලීම් ප්රතිකාර කිරීම. top -cum main ruleLinkify ප්රධාන වෙනස පමණක් ක්රියාකාරීත්වය තුළ වෙනස්කම් සීමා කරන බව පෙන්වයි. මෙය සාමාන්යයෙන් අපගේ වැඩසටහනගේ ඇමතුම් ග්රැෆිවල අභ්යන්තර රාමුව පෙන්වයි, සැබෑ වැඩ බොහෝමයක් සිදු වන ස්ථානය. ක්රියාකාරකම් top runtime ඔවුන් කොහෙන්ද එන්නේ කියලා බලන්න Call Stack එක දිහා බලමු: (pprof) peek scanobject$ Showing nodes accounting for -3.72s, 3.13% of 118.73s total ----------------------------------------------------------+------------- flat flat% sum% cum cum% calls calls% + context ----------------------------------------------------------+------------- -0.86s 94.51% | runtime.gcDrain -0.09s 9.89% | runtime.gcDrainN 0.04s 4.40% | runtime.markrootSpans -0.46s 0.39% 0.39% -0.91s 0.77% | runtime.scanobject -0.19s 20.88% | runtime.greyobject -0.13s 14.29% | runtime.heapBits.nextFast (inline) -0.08s 8.79% | runtime.heapBits.next -0.08s 8.79% | runtime.spanOfUnchecked (inline) 0.04s 4.40% | runtime.heapBitsForAddr -0.01s 1.10% | runtime.findObject ----------------------------------------------------------+------------- (pprof) peek gcDrain$ Showing nodes accounting for -3.72s, 3.13% of 118.73s total ----------------------------------------------------------+------------- flat flat% sum% cum cum% calls calls% + context ----------------------------------------------------------+------------- -1s 100% | runtime.gcBgMarkWorker.func2 0.15s 0.13% 0.13% -1s 0.84% | runtime.gcDrain -0.86s 86.00% | runtime.scanobject -0.18s 18.00% | runtime.(*gcWork).balance -0.11s 11.00% | runtime.(*gcWork).tryGet 0.09s 9.00% | runtime.pollWork -0.03s 3.00% | runtime.(*gcWork).tryGetFast (inline) -0.03s 3.00% | runtime.markroot -0.02s 2.00% | runtime.wbBufFlush 0.01s 1.00% | runtime/internal/atomic.(*Bool).Load (inline) -0.01s 1.00% | runtime.gcFlushBgCredit -0.01s 1.00% | runtime/internal/atomic.(*Int64).Add (inline) ----------------------------------------------------------+------------- එහෙම අවසානයේ ඔහු පැමිණෙන්නේ The අපට කියනවා ඒ කුණු රැස්වීමේ කොටසක්, ඒ නිසා GC Savings කියන්නේ මොනවද? අනෙකුත් මෙහෙයුම් ? runtime.scanobject runtime.gcBgMarkWorker GC මාර්ගෝපදේශ runtime.gcBgMarkWorker runtime.scanobject nextFreeFast runtime (pprof) peek nextFreeFast$ Showing nodes accounting for -3.72s, 3.13% of 118.73s total ----------------------------------------------------------+------------- flat flat% sum% cum cum% calls calls% + context ----------------------------------------------------------+------------- -0.40s 100% | runtime.mallocgc (inline) -0.40s 0.34% 0.34% -0.40s 0.34% | runtime.nextFreeFast ----------------------------------------------------------+------------- (pprof) peek writeHeapBits Showing nodes accounting for -3.72s, 3.13% of 118.73s total ----------------------------------------------------------+------------- flat flat% sum% cum cum% calls calls% + context ----------------------------------------------------------+------------- -0.37s 100% | runtime.heapBitsSetType 0 0% | runtime.(*mspan).initHeapBits -0.35s 0.29% 0.29% -0.37s 0.31% | runtime.writeHeapBits.flush -0.02s 5.41% | runtime.arenaIndex (inline) ----------------------------------------------------------+------------- -0.29s 100% | runtime.heapBitsSetType -0.31s 0.26% 0.56% -0.29s 0.24% | runtime.writeHeapBits.write 0.02s 6.90% | runtime.arenaIndex (inline) ----------------------------------------------------------+------------- (pprof) peek heapBitsSetType$ Showing nodes accounting for -3.72s, 3.13% of 118.73s total ----------------------------------------------------------+------------- flat flat% sum% cum cum% calls calls% + context ----------------------------------------------------------+------------- -0.82s 100% | runtime.mallocgc -0.12s 0.1% 0.1% -0.82s 0.69% | runtime.heapBitsSetType -0.37s 45.12% | runtime.writeHeapBits.flush -0.29s 35.37% | runtime.writeHeapBits.write -0.03s 3.66% | runtime.readUintptr (inline) -0.01s 1.22% | runtime.writeHeapBitsForAddr (inline) ----------------------------------------------------------+------------- (pprof) peek deductAssistCredit$ Showing nodes accounting for -3.72s, 3.13% of 118.73s total ----------------------------------------------------------+------------- flat flat% sum% cum cum% calls calls% + context ----------------------------------------------------------+------------- -0.37s 100% | runtime.mallocgc -0.30s 0.25% 0.25% -0.37s 0.31% | runtime.deductAssistCredit -0.07s 18.92% | runtime.gcAssistAlloc ----------------------------------------------------------+------------- පේනවා වගේ අන්තිමේදී Top 10 එකේ ඉන්න අය තමයි එන්නේ. , GC මාර්ගෝපදේශය අපට පවසන්නේ මතකය බෙදාහැරීමකි. nextFreeFast runtime.mallocgc Reduced costs in the GC and allocator imply that we are allocating less overall. Let’s take a look at the heap profiles for insight: $ go tool pprof -sample_index=alloc_objects -diff_base heap.nopgo.pprof heap.withpgo.pprof File: markdown.profile.withpgo.exe Type: alloc_objects Time: Aug 28, 2023 at 10:28pm (EDT) Entering interactive mode (type "help" for commands, "o" for options) (pprof) top Showing nodes accounting for -12044903, 8.29% of 145309950 total Dropped 60 nodes (cum <= 726549) Showing top 10 nodes out of 58 flat flat% sum% cum cum% -4974135 3.42% 3.42% -4974135 3.42% gitlab.com/golang-commonmark/mdurl.Parse -4249044 2.92% 6.35% -4249044 2.92% gitlab.com/golang-commonmark/mdurl.(*URL).String -901135 0.62% 6.97% -977596 0.67% gitlab.com/golang-commonmark/puny.mapLabels -653998 0.45% 7.42% -482491 0.33% gitlab.com/golang-commonmark/markdown.(*StateInline).PushPending -557073 0.38% 7.80% -557073 0.38% gitlab.com/golang-commonmark/linkify.Links -557073 0.38% 8.18% -557073 0.38% strings.genSplit -436919 0.3% 8.48% -232152 0.16% gitlab.com/golang-commonmark/markdown.(*StateBlock).Lines -408617 0.28% 8.77% -408617 0.28% net/textproto.readMIMEHeader 401432 0.28% 8.49% 499610 0.34% bytes.(*Buffer).grow 291659 0.2% 8.29% 291659 0.2% bytes.(*Buffer).String (inline) ඒ මෙම විකල්පය අපට ප්රමාණයෙන් තොරව බෙදාහැරීමේ සංඛ්යාව පෙන්වයි. මෙය ප්රයෝජනවත් වන අතර අපි CPU භාවිතය අඩුවීමේ පර්යේෂණ කරමු, එය ප්රමාණයට වඩා බෙදාහැරීමේ සංඛ්යාව සමඟ වඩාත් ගැලපෙනු ඇත. . -sample_index=alloc_objects mdurl.Parse ප්රවේශය සඳහා, PGO නොමැතිව මෙම කාර්යය සඳහා මුළු බෙදාහැරීමේ ගණන බලන්න: $ go tool pprof -sample_index=alloc_objects -top heap.nopgo.pprof | grep mdurl.Parse 4974135 3.42% 68.60% 4974135 3.42% gitlab.com/golang-commonmark/mdurl.Parse මුළු සංඛ් යාව පෙර 4974135 විය, එබැවින් 100% ප් රතිලාභ ඉවත් කර ඇත! mdurl.Parse ආයෙමත් differential profile එකට, අපි ටිකක් තව context එකක් එකතු කරමු: (pprof) peek mdurl.Parse Showing nodes accounting for -12257184, 8.44% of 145309950 total ----------------------------------------------------------+------------- flat flat% sum% cum cum% calls calls% + context ----------------------------------------------------------+------------- -2956806 59.44% | gitlab.com/golang-commonmark/markdown.normalizeLink -2017329 40.56% | gitlab.com/golang-commonmark/markdown.normalizeLinkText -4974135 3.42% 3.42% -4974135 3.42% | gitlab.com/golang-commonmark/mdurl.Parse ----------------------------------------------------------+------------- ඇමතුම් වලට ඔවුන් පැමිණෙන්නේ සහ . mdurl.Parse markdown.normalizeLink markdown.normalizeLinkText (pprof) list mdurl.Parse Total: 145309950 ROUTINE ======================== gitlab.com/golang-commonmark/mdurl.Parse in /usr/local/google/home/mpratt/go/pkg/mod/gitlab.com/golang-commonmark/mdurl@v0.0.0-20191124015652-932350d1cb84/parse .go -4974135 -4974135 (flat, cum) 3.42% of Total . . 60:func Parse(rawurl string) (*URL, error) { . . 61: n, err := findScheme(rawurl) . . 62: if err != nil { . . 63: return nil, err . . 64: } . . 65: -4974135 -4974135 66: var url URL . . 67: rest := rawurl . . 68: hostless := false . . 69: if n > 0 { . . 70: url.RawScheme = rest[:n] . . 71: url.Scheme, rest = strings.ToLower(rest[:n]), rest[n+1:] මෙම කාර්යයන් හා ඇමතුම් සඳහා සම්පූර්ණ මූලාශ්රය සොයා ගත හැකිය: පැරිස් markdown.normalizeLink පිටුපස markdown.normalizeLinkඛේද මෙතැනදි මොනවද වෙන්නේ? අපගේ PGO ප්රවේශය මෙම ක්රියාකාරකම් සඳහා ඇමතුම් උණුසුම් බව සලකා බැලීම නිසා, පරිවර්තනකරුවා එය සලකා බැලුවා. mdurl.Parse $ go tool pprof -top cpu.nopgo.pprof | grep mdurl.Parse 0.36s 0.3% 63.76% 2.75s 2.32% gitlab.com/golang-commonmark/mdurl.Parse $ go tool pprof -top cpu.withpgo.pprof | grep mdurl.Parse 0.55s 0.48% 58.12% 2.03s 1.76% gitlab.com/golang-commonmark/mdurl.Parse (inline) නිර්මාණය A ප් රචණ්ඩත්වයේ ප් රතිඵලයක් ලෙස 66 ( එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් එහෙනම් සාමාන් යයෙන් මෙම ප්රමාණයට ගබඩාව මත බෙදාහැරීමට අවශ් ය වන අතර, එය ප්රතිඵල ප්රතිඵලයට වඩා ජීවත් වන බැවිනි. ඇතුළත් වෙලා තියෙන්නේ පරිගණකයා දකින්නේ වෙනස්කම් පැන නොලැබෙන බවය. එවිට පරිගණකයා එය ස්කෑම් මත බෙදාහැරීමට ඉඩ සලසයි. සමානයි . mdurl.Parse URL var url URL return &url, nil mdurl.Parse markdown.normalizeLink normalizeLink markdown.normalizeLinkText markdown.normalizeLink දෙවන විශාලතම අඩුපාඩු ප් රදර්ශනය, සිට එවැනි ප් රතිඵලයක් පසෙකින් පසෙකින් පසෙකින් පසෙකින් පසෙකින් පසෙකින් පවතී. mdurl.(*URL).String මෙම අවස්ථා වලදී, PGO සහ compiler optimizations සාමාන්යයෙන් ඇති බලපෑම කොටසක් වන්නේ ප්රමාණයේ ප්රමාණයේ ප්රමාණයේ බලපෑම කොපිලර්ගේ PGO යෙදවීමේ කොටසක් නොවන බවයි. පලායන විශ්ලේෂණය හා ගබඩාව බෙදාහැරීම සඳහා සියලුම බලපෑම් ඕනෑම ගොඩනැගිල්ලකට අදාළ වන සම්මත පරිශීලකයන් විය. වැඩි දියුණු පලායන හැසිරීම inlining හි විශිෂ්ට downstream බලපෑමක් වේ, නමුත් එය එකම බලපෑමක් නොවේ. බොහෝ පරිශීලකයන් inlining ප් රතිලාභ ලබා ගත හැකිය. උදාහරණයක් ලෙස, ස්ථාවර ප්රමාණය සමහර ආදායම් ස්ථාවර වන විට inlining පසු කාර්යයක කේතය සරල කර ගත හැකිය. Devirtualization කිරීම අප ඉහත උදාහරණයේ දැක ඇති inling වලට අමතරව, PGO ද අන්තර්ෆියුම් ඇමතුම් වල කොන්දේසිගත විෂයගත කිරීමක් සිදු කළ හැකිය. PGO-Driven Devirtualization වෙත ළඟා වීමට පෙර, නැවත පියවරක් ගෙන “Devirtualization” සාමාන්යයෙන් සකස් කරමු. f, _ := os.Open("foo.txt") var r io.Reader = f r.Read(b) මෙහිදී අපි ඇමතුමක් දෙනවා The Interface ක් රමය පරිගණක කිහිපයක් භාවිතා කළ හැකි නිසා, පරිගණකයක් නිර්මාණය කරයි. ක්රියාකාරිත්වය ඇමතුමක්, එනම් එය පරිශීලක අමුද්රව්ය වටිනාකම තුළ ඇති ආකාරයෙන් ක්රියාකාරිත්වය කාලයේදී ඇමතුමක් කිරීමට නිවැරදි ක්රමයක් සොයයි.දෘෂ්ටික ඇමතුම් සෘජු ඇමතුම් වලට වඩා කුඩා අතිරේක ක්රියාකාරිත්වය වියදමක් ඇත, නමුත් වඩාත් වැදගත් වන්නේ ඒවා සමහර පරිවර්තන පරිශීලක පහසුකම් සීමා කරයි.උදාහරණයක් ලෙස, පරිවර්තනකයා අමුද්රව්ය ඇමතුමක් මත පලායන විශ්ලේෂණය කළ නොහැක, මොකද එය සැබෑ ක්රමයේ යෙදුම නොදන්නා නිසා. io.Reader Read අතුරුදහන් නමුත් ඉහත උදාහරණයට අනුව අපි නිවැරදි ක් රමවේදය හඳුනාගත යුතුය.එය ඒ නිසා ඒ සඳහා අවසර ලබා ගත හැකි එකම වර්ගයකි. මෙම අවස්ථාවේදී, පරිගණකයා ක්රියා කරයි ඉන්පසු, එය සෘජු ඇමතුමක් සකස් කරන විට, සෘජු ඇමතුමක් සමග එසේම අනෙකුත් ආකෘති optimizations ලබා ගත හැක. දෝ os.(*File).Read *os.File r Devirtualization කිරීම io.Reader.Read os.(*File).Read (ඔබ සමහර විට සිතන්නේ "මේ කේතය අහිතකරයි, ඇයි කවුරුහරි එය එවැනි ආකාරයෙන් ලියන්නේ?" එය පාවිච්චි කරන Function එකක් බවට පත්වෙනවා. ප් රතිඵලයක් වශයෙන්, ක් රියාමාර්ගයක් සකස් කිරීමෙන් පසු, දැන් සැබැවින්ම සංකීර්ණ වේ.) f io.Reader io.Reader PGO-Driven Devirtualization මෙම සංකල්පය ස්ථීරව හඳුනාගත නොහැකි වන තත්වයන් වෙත පුළුල් කරයි, නමුත් ප් රොෆයිල් කිරීම පෙන්වන්න පුළුවන්, උදාහරණයක් ලෙස, ඉලක්ක ඇමතුම් මෙම අවස්ථාවේදී, PGO මාරු කළ හැකිය එවැනි දෙයක් සමග: io.Reader.Read os.(*File).Read r.Read(b) if f, ok := r.(*os.File); ok { f.Read(b) } else { r.Read(b) } එනම්, අපි වඩාත් ප්රමාණවත් වනු ඇති බටහිර වර්ගය සඳහා runtime check එකක් එකතු කර, එසේ නම් බටහිර ඇමතුමක් භාවිතා කරන්න, හෝ වෙනත් ආකාරයකින් සම්මත අතුරුදහන් ඇමතුමට ආපසු වැටෙනු ඇත. ) ඇතුළත් කළ හැකි සහ අමතර ආකෘති භාවිතා කළ හැකි, නමුත් අපි තවමත් පරාක් රමණික මාර්ගය පවත්වාගෙන ඇත, මොකද ප්රශ්නය එය සෑම විටම එසේ වනු ඇති බව සහතික නොවේ. *os.File අපගේ markdown සේවාදායකය විශ්ලේෂණය තුළ අපි PGO ආකර්ෂණීය devirtualization නොපෙනේ, නමුත් අපි පමණක් ඉහළ බලපෑම් ප්රදේශ දෙස බැලුවා. PGO (අද බොහෝ compiler optimizations) සාමාන්යයෙන් බොහෝ විවිධ ස්ථානවල ඉතා කුඩා වැඩි දියුණු කිරීම් සංඛ්යාව තුළ ඔවුන්ගේ ප්රතිලාභ ලබා දෙයි, එබැවින් අප බැලූ දේට වඩා වැඩි සිදුවීමක් ඇති විය හැකිය. Inlining සහ Devirtualization යනු Go 1.2 හි ලබා ගත හැකි PGO ආකෘතියෙන් සකස් කරන optimizations දෙකක්, නමුත් අපි දැක ඇති පරිදි, මෙම බොහෝ විට අතිරේක optimizations විවෘත කරනු ඇත. අනුමැතිය Profile-guided optimization එකතු කිරීම Go එකට කණ්ඩායම් උත්සාහයක් විය, මම අනිවාර්යයෙන්ම Uber හි Raj Barik සහ Jin Lin සහ Google හි Cherry Mui සහ Austin Clements විසින් උපකාර කිරීමට කැමතියි. මයිකල් පැට් This article is available on The Go Blog under a CC BY 4.0 DEED License. Go Blog එක Go Blog එක ඡායාරූපය: Ben Sweet on Unsplash සුපිරි Ben Unsplash කිරීම