-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Useless linearization on large data during validation, of either type bytes or string-derived, potentially cause stalls due to reclaiming #7318
Comments
This following patch will restore the old behavior where linearization on bytes (blob) type is avoided:
|
Good catch! |
@raphaelsc is out this week @bhalevy can you please have someone send this fix (we have issues in the field because of that - especially when users have large blobs) |
@denesb can you please look into this? thanks |
@raphaelsc did you close the issue on purpose? |
No, by mistake. Sorry |
I think overriding
and have individual validating methods in the validator visitor decide whether they need linearising or not. |
LGTM. Thanks for working on this, @denesb! |
@avikivity @slivne Please, consider backporting this to all supported releases. |
Btw you're also interested in #7393, which was extracted out of this issue
into a new one
…On Wed, Oct 28, 2020, 8:36 PM vladzcloudius ***@***.***> wrote:
@avikivity <https://github.com/avikivity> @slivne
<https://github.com/slivne> Please, consider backporting this to all
supported releases.
@eliransin <https://github.com/eliransin> @eyalgutkind
<https://github.com/eyalgutkind> @amihayday <https://github.com/amihayday>
FYI
—
You are receiving this because you modified the open/close state.
Reply to this email directly, view it on GitHub
<#7318 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAKYA4YRLP4SRUC6BOGRUWTSNCTHLANCNFSM4SA7JUWA>
.
|
This isn't really a regression, the original code also used bytes_view. So not backporting. |
@avikivity Don't you think that it's worth backporting even if it's not a regression considering the comment #7318 (comment) ? |
Actually it's a regression. The original code also used bytes_view in the validator, but before devirtualizing the types, we had bytes_type_impl overriding virtual |
Given the latency impact on users produced by linearization on validation, I think the fix for this issue in addition to the one for #7393 are worth of backport. |
Ah, I looked at strings (which always need validation). You're right that it is a regression. But won't we have to linearize in anyway, given that we'll convert it to bytes soon? |
If I understand correctly, the blob will be kept fragmented (within managed_bytes) in memtable, but it will indeed be linearized as soon as it reaches the SSTable layer. So we need #7457 fixed too (we need to extend its scope to writer too, not only parser) |
FWIW, confirmed this with large mem allocation detector, a large blob is only linearized when memtable is flushed into a sstable. Backporting these available fixes will reduce the # of times we linearize a given large blob from 2 to 1, which alleviates the pain to some extent, but we need to fix #7457 for the problem to be completely fixed. |
Instead of eagerly linearizing all values as they are passed to validate(), defer linearization to those validators that actually need linearized values. Linearizing large values puts pressure on the memory allocator with large contiguous allocation requests. This is something we are trying to actively avoid, especially if it is not really neaded. Turns out the types, whose validators really want linearized values are a minority, as most validators just look at the size of the value, and some like bytes don't need validation at all, while usually having large values. This is achieved by templating the validator struct on the view and using the FragmentedRange concept to treat all passed in views (`bytes_view` and `fragmented_temporary_buffer_view`) uniformly. This patch makes no attempt at converting existing validators to work with fragmented buffers, only trivial cases are converted. The major offenders still left are ascii/utf8 and collections. Fixes: #7318 Tests: unit(dev) Signed-off-by: Botond Dénes <bdenes@scylladb.com> Message-Id: <20201007054524.909420-1-bdenes@scylladb.com> (cherry picked from commit db56ae6)
Instead of eagerly linearizing all values as they are passed to validate(), defer linearization to those validators that actually need linearized values. Linearizing large values puts pressure on the memory allocator with large contiguous allocation requests. This is something we are trying to actively avoid, especially if it is not really neaded. Turns out the types, whose validators really want linearized values are a minority, as most validators just look at the size of the value, and some like bytes don't need validation at all, while usually having large values. This is achieved by templating the validator struct on the view and using the FragmentedRange concept to treat all passed in views (`bytes_view` and `fragmented_temporary_buffer_view`) uniformly. This patch makes no attempt at converting existing validators to work with fragmented buffers, only trivial cases are converted. The major offenders still left are ascii/utf8 and collections. Fixes: #7318 Tests: unit(dev) Signed-off-by: Botond Dénes <bdenes@scylladb.com> Message-Id: <20201007054524.909420-1-bdenes@scylladb.com> (cherry picked from commit db56ae6)
Backported to 4.1, 4.2 (4.3 has it already) |
Instead of eagerly linearizing all values as they are passed to validate(), defer linearization to those validators that actually need linearized values. Linearizing large values puts pressure on the memory allocator with large contiguous allocation requests. This is something we are trying to actively avoid, especially if it is not really neaded. Turns out the types, whose validators really want linearized values are a minority, as most validators just look at the size of the value, and some like bytes don't need validation at all, while usually having large values. This is achieved by templating the validator struct on the view and using the FragmentedRange concept to treat all passed in views (`bytes_view` and `fragmented_temporary_buffer_view`) uniformly. This patch makes no attempt at converting existing validators to work with fragmented buffers, only trivial cases are converted. The major offenders still left are ascii/utf8 and collections. Fixes: #7318 Tests: unit(dev) Signed-off-by: Botond Dénes <bdenes@scylladb.com> Message-Id: <20201007054524.909420-1-bdenes@scylladb.com> (cherry picked from commit db56ae6) [avi: squashed ed6775c ("types: adjust validation_visitor construction for clang") as gcc 9 in scylla 4.1 suffers from the same problem as clang 11]
Instead of eagerly linearizing all values as they are passed to validate(), defer linearization to those validators that actually need linearized values. Linearizing large values puts pressure on the memory allocator with large contiguous allocation requests. This is something we are trying to actively avoid, especially if it is not really neaded. Turns out the types, whose validators really want linearized values are a minority, as most validators just look at the size of the value, and some like bytes don't need validation at all, while usually having large values. This is achieved by templating the validator struct on the view and using the FragmentedRange concept to treat all passed in views (`bytes_view` and `fragmented_temporary_buffer_view`) uniformly. This patch makes no attempt at converting existing validators to work with fragmented buffers, only trivial cases are converted. The major offenders still left are ascii/utf8 and collections. Fixes: scylladb#7318 Tests: unit(dev) Signed-off-by: Botond Dénes <bdenes@scylladb.com> Message-Id: <20201007054524.909420-1-bdenes@scylladb.com> (cherry picked from commit db56ae6) [avi: squashed ed6775c ("types: adjust validation_visitor construction for clang") as gcc 9 in scylla 4.1 suffers from the same problem as clang 11]
The type bytes_type_impl doesn't need any validation, and so no linearization. But due to a regression introduced in commit b175657, bytes_typoe_impl no longer overrides validate(const fragmented_temporary_buffer::view&, ...), Meaning linearization is performed on bytes type even though it needs no validation. Found out this while auditing code (comparing old versions with the current one)
Large data here means data > 128k, as that's the default fragment size used by fragmented_temporary_buffer. Data smaller than that will not need any linearization.
Also, string-derived types are performing linearization needlessly, given that validation checks individual bytes and that could be done on the fragmented buffer instead.
Linearization can try to allocate a large contiguous buffer to place large data, potentially triggering memory reclaiming and causing reactor stalls.
Follow a stall backtrace coming from that linearization on a string-derived type:
The text was updated successfully, but these errors were encountered: