Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix memory leak #442

Merged
merged 10 commits into from
Dec 27, 2023
Merged

Fix memory leak #442

merged 10 commits into from
Dec 27, 2023

Conversation

withinboredom
Copy link
Collaborator

@withinboredom withinboredom commented Dec 25, 2023

It appears we aren't deleting ALL the created handles. This PR introduces a "smartpointer.go" file which can manage handles (and pointers, though it isn't used in this PR -- can remove the pointer code) without having to keep track of them manually. I like it because it frees up the cognitive load when trying to ensure everything is actually freed, without having to trace through the entire program's execution to figure out whether or not it is freed.

To illustrate the difference, here are screen shots after 1:15 of running a load-test on a 2gb container (pay attention to memory usage).

fixes #366

image

^ before this change

image

^ after this change (~7k RPS!)

@withinboredom withinboredom mentioned this pull request Dec 25, 2023
@dunglas
Copy link
Owner

dunglas commented Dec 25, 2023

The test failure looks new. Can it be related to the change?

frankenphp.go Outdated Show resolved Hide resolved
@withinboredom withinboredom changed the title do not use caddy context WIP: do not use caddy context Dec 26, 2023

var contextKey key
var contextKey = contextKeyStruct{}
var handleKey = handleKeyStruct{}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed contextKey to follow Go best-practices and ensure uniqueness during runtime.

@@ -480,7 +490,6 @@ func maybeCloseContext(fc *FrankenPHPContext) {
//export go_execute_script
func go_execute_script(rh unsafe.Pointer) {
handle := cgo.Handle(rh)
defer handle.Delete()
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is now deleted by the handle list.

@withinboredom withinboredom changed the title WIP: do not use caddy context Fix memory leak Dec 27, 2023
@withinboredom
Copy link
Collaborator Author

This is now ready for review @dunglas

@dunglas
Copy link
Owner

dunglas commented Dec 27, 2023

You rock 😍

I'll review ASAP! Don't worry about the CI failure, I'll take care of it.

smartpointer.go Outdated Show resolved Hide resolved
smartpointer.go Outdated Show resolved Hide resolved
smartpointer.go Outdated Show resolved Hide resolved
@withinboredom
Copy link
Collaborator Author

Looks like there is still a leak in cgi-mode, trying to figure out the best way to fix it.

argc := C.int(len(args))
argv := make([]*C.char, argc)
for i, arg := range args {
argv[i] = C.CString(arg)
defer C.free(unsafe.Pointer(argv[i]))
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stumbled across this one by accident. If my IDE warning is correct and I understand correctly, defer in a for-loop will actually just call defer C.free(unsafe.Pointer(argv["last-i"])) i times.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😭 good one, the typical for loop bug.

@withinboredom
Copy link
Collaborator Author

It should be g2g if you're happy with it. The best way to see the memory leak (or lack thereof) is to run k6 with --no-connection-reuse --no-vu-connection-reuse, which will eat a couple of gigs of ram in a few mins without this PR.

Copy link
Owner

@dunglas dunglas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Amazing hunt and fix!

@withinboredom withinboredom merged commit 5bda50c into main Dec 27, 2023
38 of 40 checks passed
@withinboredom withinboredom deleted the fix/memory-leak branch December 27, 2023 23:16
@mathieudz
Copy link
Contributor

Just letting you know that my memory leak problems are gone too. Try to guess where I restarted my application to run the new version of frankenphp using the heap allocation stats in prometheus 😄
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Memory leak
3 participants