Repository navigation
SW-Serverless 10.2.2: memory and CPU limits for adapters run locally - #168
Merged
Merged
Conversation
A call cut short because the host stopped the adapter (its hard or soft memory limit, its CPU limit, or missed heartbeats) failed with a bare "Adapter stream closed." It now fails with AdapterStoppedException, an IOException as before, whose message names the limit and what the adapter was using; ResidentAdapterInstance.StopReason keeps the reason. Calls made after the stop say it too. Python has no heap ceiling of its own. The host now hands the hard memory limit to a Python adapter as SW_SERVERLESS_MEMORY_LIMIT_BYTES, and never passes one on when there is no limit. The SDK sets it as RLIMIT_DATA on Linux, so an allocation past it raises MemoryError, which the call reports as running out of memory under the limit. RLIMIT_AS would count reserved address space (malloc arenas, thread stacks): an adapter using 26 MB with a few worker threads has over 600 MB of it. Off Linux the watchdog applies.
LocalAdapterHost.StartAsync takes LocalAdapterLimits (limits:), and ConformanceOptions.Limits passes them through: a memory limit, a CPU limit as a share of the machine, the samples in a row before the CPU limit trips, and how often the process is sampled. A tool that builds and tries drafts on a shared server can hold them to a budget. With limits, the host samples every second rather than every fifteen, so a short try is caught; the missed heartbeats allowed grow to keep 45 seconds of tolerance, and an adapter asked to stop at its CPU limit is killed after two samples. A call cut short says which limit, also when the adapter died at its runtime's own ceiling. Without limits nothing changes, and the existing StartAsync signature still binds for code built against 10.2.0. The conformance kit no longer counts a stopped adapter as refusing an unknown command.
The packages, and the Python and Node SDKs with them: the Python SDK now applies the memory limit the host hands it, so its version moves with the host's. The CLI install examples keep naming the released 10.2.0 binary.
|
Note Currently processing new changes in this PR. This may take a few minutes, please wait... ⚙️ Run configuration
📒 Files selected for processing (21)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…hout these changes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What's in 10.2.2
Limits for local runs.
LocalAdapterHost.StartAsync(..., limits:)andConformanceOptions.Limitstake a newLocalAdapterLimits:MemoryLimitBytesCpuPercentLimitCpuLimitSamplesSampleInterval(1 s by default)With limits set, the watchdog samples every interval and stops an adapter that goes over. Bitween's adapter editor uses this to cap the drafts it checks and tries on the server.
Python hard memory cap on Linux. When a hard limit is set, the host passes
SW_SERVERLESS_MEMORY_LIMIT_BYTESand the Python SDK applies it asRLIMIT_DATA. It isn'tRLIMIT_ASbecause that counts malloc arenas and thread stacks, and would break ordinary adapters. Elsewhere the watchdog applies.Clear stop reasons. An adapter stopped for memory, CPU or missed heartbeats raises
AdapterStoppedException(anIOException) with the reason, for example: stopped: it was using 167 MB, over its memory limit of 150 MB, and was killed. Previously each of these wasAdapter stream closed.Version. The SDKs are at 10.2.2:
sw-serverlessand@simplyworks/sw-serverless.Compatibility
Backward compatible:
LocalAdapterHost.StartAsyncsignature is kept as its own overload.AdapterStoppedExceptionderives fromIOException, so existingcatch (IOException)still catches it.Tests
LocalLimitsTests: Python over memory and over CPU, Node over memory, no limits unchanged, conformance with limitsRLIMIT_DATApathBitween's suites also pass against the locally packed 10.2.2.
After merge
Publish the 10.2.2 NuGet packages. Bitween's
releases/r10.0-stagingwaits on them. For the Python and Node SDKs, tagsdk-v10.2.2.Why 10.2.2
The merge of #167 already published 10.2.1 to nuget.org, without these changes, because the workflow numbers each publish from main. So this release is 10.2.2.