-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Don't create prewarm container when used memory reaches the limit #5048
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
Don't create prewarm container when used memory reaches the limit #5048
Conversation
Codecov Report
@@ Coverage Diff @@
## master #5048 +/- ##
===========================================
- Coverage 82.52% 71.76% -10.76%
===========================================
Files 206 206
Lines 10006 10007 +1
Branches 445 451 +6
===========================================
- Hits 8257 7182 -1075
- Misses 1749 2825 +1076
Continue to review full report at Codecov.
|
f07708f to
c27800e
Compare
| val newContainer = childFactory(context) | ||
| prewarmStartingPool = prewarmStartingPool + (newContainer -> (exec.kind, memoryLimit)) | ||
| newContainer ! Start(exec, memoryLimit, ttl) | ||
| if (hasPoolSpaceFor(busyPool ++ freePool ++ prewarmedPool, memoryLimit)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When create prewarm container, judge whether exist enough memory.
c27800e to
c9cba12
Compare
| def hasPoolSpaceFor[A](pool: Map[A, ContainerData], | ||
| prewarmStartingPool: Map[A, (String, ByteSize)], | ||
| memory: ByteSize): Boolean = { | ||
| memoryConsumptionOf(pool) + +prewarmStartingPool.map(_._2._2.toMB).sum + memory.toMB <= poolConfig.userMemory.toMB |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When calculate whether has idle space, it is better to calculate prewarmStartingPool's memory as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this a typo?
+ +
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, yes, you are right.
Already fixed to memoryConsumptionOf(pool) + prewarmStartingPool.map(_._2._2.toMB).sum + memory.toMB <= poolConfig.userMemory.toMB
| val prewarmExpirationCheckIntervel = 2.seconds | ||
| val poolConfig = | ||
| ContainerPoolConfig(MemoryLimit.STD_MEMORY * 8, 0.5, false, prewarmExpirationCheckIntervel, None, 100) | ||
| ContainerPoolConfig(MemoryLimit.STD_MEMORY * 12, 0.5, false, prewarmExpirationCheckIntervel, None, 100) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Due to add logic of whether exist enough memory, so need to adjust the user memory here.
|
|
||
| val createdContainer = | ||
| // Is there enough space on the invoker for this action to be executed. | ||
| if (hasPoolSpaceFor(busyPool ++ prewarmedPool, memory)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Due to didn't create any container here, so it is better to remove below logic here.
// Is there enough space on the invoker for this action to be executed.
if (hasPoolSpaceFor(busyPool ++ prewarmedPool, memory))
c9cba12 to
743070e
Compare
|
Have any comment? |
| def hasPoolSpaceFor[A](pool: Map[A, ContainerData], | ||
| prewarmStartingPool: Map[A, (String, ByteSize)], | ||
| memory: ByteSize): Boolean = { | ||
| memoryConsumptionOf(pool) + +prewarmStartingPool.map(_._2._2.toMB).sum + memory.toMB <= poolConfig.userMemory.toMB |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this a typo?
+ +
| // There was no warm/warming/warmingCold container. Try to take a prewarm container or a cold container. | ||
|
|
||
| // Is there enough space to create a new container or do other containers have to be removed? | ||
| if (hasPoolSpaceFor(busyPool ++ freePool ++ prewarmedPool, prewarmStartingPool, memory)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we take a container from the prewarmPool as there is a matched container, do we still need to concern about the total memory?
Since one container is moved from prewarmPool to busyPool and there would be no difference in the sum of memory consumption.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hm..i think we need to concern about the total memory when take a prewarm conainer from prewarmPool,
e.g. let's assume invoker's user memory is 1024 MB, currently, busyPool is 512MB, prewarmPool is 512MB,
if user's activation's corresponding action can match the warmedPool, have no need to add condition: if (hasPoolSpaceFor(busyPool...) due to didn't create new container
but if doesn't match warmedPool and matches a prewarm container(256MB), then, busyPool will be 512MB+256MB, prewarmedPool is 512MB-256MB+256MB, so the total used memory will be 1024MB +256MB, so it is better to add judge condition before take a prewarmed container.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But if we take the current approach, even under the condition that there are 512MB of prewarm containers, they can't be used.
I'd rather let it take prewarm containers but prevent the subsequent creation of a new prewarm container.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated accordingly.
1f270a1 to
0c91e52
Compare
| .map(container => (container, "prewarmed")) | ||
| .orElse { | ||
| // Is there enough space to create a new container or do other containers have to be removed? | ||
| if (hasPoolSpaceFor(busyPool ++ freePool ++ prewarmedPool, prewarmStartingPool, memory)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add memory check condition for coldStart
| val container = Some(createContainer(memory), "cold") | ||
| .map(container => (container, "recreatedPrewarm")) | ||
| .getOrElse { | ||
| val container = (createContainer(memory), "recreated") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For here's coldStart, i think has no need to do memory check. because it will delete a container from freePool in advance.
style95
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
| def hasPoolSpaceFor[A](pool: Map[A, ContainerData], | ||
| prewarmStartingPool: Map[A, (String, ByteSize)], | ||
| memory: ByteSize): Boolean = { | ||
| memoryConsumptionOf(pool) + prewarmStartingPool.map(_._2._2.toMB).sum + memory.toMB <= poolConfig.userMemory.toMB |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BTW, when the prewarm pool are backfilled again?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't create new container