-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
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
@@ -829,7 +842,7 @@ class ContainerPoolTests | |||
stream.reset() | |||
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.
@@ -129,44 +129,40 @@ class ContainerPool(childFactory: ActorRefFactory => ActorRef, | |||
val memory = r.action.limits.memory.megabytes.MB | |||
|
|||
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.
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