Middle+
Որտե՞ղ է փոփոխականը, երբ այն առանձնացվում է գորուտինում։
sobes.tech AI
Պատասխան AI-ից
Փոփոխականը կարող է հատկացվել ինչպես goroutine-ի stack-ում, այնպես էլ heap-ում: Դա որոշվում է Go կոմպիլյատորի escape analysis (փախուստի վերլուծություն) մեխանիզմով:
Escape analysis-ի հիմնական սկզբունքները՝
- Եթե կոմպիլյատորը կարող է ապացուցել, որ փոփոխականը ապրում է միայն մեկ ֆունկցիայի կանչի շրջանակում կամ միայն մեկ goroutine-ի stack-ում (այսինքն՝ այն չի հղվում դուրսից), այն հատկացվում է այդ goroutine-ի stack-ին: Սա ավելի արագ է, քանի որ stack-ը ավտոմատ կերպով կառավարվում է և չի պահանջում գարշահոտ հավաքում:
- Եթե կոմպիլյատորը չի կարող ապացուցել, որ փոփոխականը սահմանափակված է stack-ի մեջ, կամ եթե դրա վրա կան հղումներ դուրսից (օրինակ՝ փոխանցվում է ցույցատիչով մյուս ֆունկցիային, գրանցվում է գլոբալ փոփոխականում, վերադառնում է ցույցատիչով ֆունկցիայից), այն հատկացվում է heap-ում: Heap-ը պահանջում է գարշահոտ հավաքում, ինչը կարող է դանդաղեցնել գործարկումը:
Օրինակ՝ stack-ում հատկացման:
// Փոփոխական 'x'-ը հատկացվում է stack-ում, քանի որ այն օգտագործվում է միայն ֆունկցիայի ներսում:
func exampleStack() int {
x := 10
return x
}
Օրինակ՝ heap-ում հատկացման:
// Փոփոխական 'p' (ցույցատիչ դեպի int) և այն ցուցադրվող int-ը կարող են հատկացվել heap-ում:
// Դա տեղի է ունենում, քանի որ ցույցատիչը վերադառնում է ֆունկցիայից և կարող է օգտագործվել դուրս:
func exampleHeap() *int {
x := 20 // արժեքը 20 կարող է հատկացվել heap-ում
return &x // վերադարձնում է x փոփոխականի հասցեն
}
Escape analysis-ը տեղի է ունենում կոմպիլյացիայի ժամանակ: Այն կարելի է ստուգել -gcflags "-m" նշանի միջոցով:
// Կոմպիլյացիա՝ escape analysis-ով
go build -gcflags "-m" your_package_name
Կոմպիլյատորի ելքը ցույց կտա, թե որ փոփոխականներն են "escape to heap":
Այսպիսով, փոփոխականի տեղադրումը (stack vs heap) որոշվում է ոչ թե այն բանի վրա, որ փոփոխականը հատկացվում է goroutine-ում, այլ այն բանի, թե ինչպես է Go-ի կոմպիլյատորը վերլուծում նրա կյանքի ցիկլը և տարածքը: