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

Decrease memory footprint of SessionData values #354

Closed
wants to merge 2 commits into from
Closed

Decrease memory footprint of SessionData values #354

wants to merge 2 commits into from

Conversation

ocheron
Copy link
Contributor

@ocheron ocheron commented Jan 29, 2019

The report in yesodweb/wai#728 shows a space leak in the session manager but also that retained memory is high overall.

Here are simple mitigations, mainly to decrease what is retained by SessionData values. This kind of modification can probably be carried out further to decrease footprint of live Context values.

With this PR I measure process memory on the server memleak test going down to 24 KB per session instead of 54 KB.

As for design, copying ByteStrings ideally should be moved out of extension decoding but this is a very convenient location (before additional transformations take place, like unpacking to String).

Cookie is needed only during HRR and can be cleared afterwards.
Retained memory was unnecessarily large because of two reasons:

* one reason was insufficiently evaluated fields sessionCipher and
  sessionCompression in SessionData values given to the session
  manager

* another one was due to how ByteString-oriented extensions are
  decoded.  ByteString pieces often share the same storage as a large
  input they are extracted from.  Decoded extension values that are
  held in the context and given to the session manager are now copied
  to fresh storage in order to break the dependency to the network
  packet content.
@kazu-yamamoto kazu-yamamoto self-requested a review January 30, 2019 01:08
@@ -262,8 +262,9 @@ decodeServerName = runGetMaybe $ do
where
getServerName = do
ty <- getWord8
sname <- getOpaque16
let name = case ty of
snameParsed <- getOpaque16
Copy link
Collaborator

Choose a reason for hiding this comment

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

What about inserting B.copy to getOpaque16 (all functions using getBytes) intead of here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That would certainly work, but we have also many transient elements, only retained on the stack, or in the context shortly, for which we don't need copying. This is why I clear the cookie value for example.

@kazu-yamamoto
Copy link
Collaborator

4f8f014 looks good to me.

@kazu-yamamoto kazu-yamamoto self-requested a review February 4, 2019 02:17
Copy link
Collaborator

@kazu-yamamoto kazu-yamamoto left a comment

Choose a reason for hiding this comment

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

OK for this time.

@kazu-yamamoto
Copy link
Collaborator

In my opinion, internal data structures should be ShortByteString to avoid fragmentations of ByteStreing. And also we should directly manuplate ByteString instead of Get and Put for performance. Let's discuss this kind of refactoring as another issue.

kazu-yamamoto added a commit to kazu-yamamoto/hs-tls that referenced this pull request Feb 4, 2019
@kazu-yamamoto
Copy link
Collaborator

Merged.

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.

None yet

2 participants