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

Don't create prewarm container when used memory reaches the limit #5048

Conversation

ningyougang
Copy link
Contributor

  • Don't create prewarm container when used memory reaches the limit
  • have no need to judge whether memory when take container from busy/free pool due to don't create new container

@codecov-io
Copy link

codecov-io commented Jan 20, 2021

Codecov Report

Merging #5048 (0c91e52) into master (6686820) will decrease coverage by 10.75%.
The diff coverage is 95.65%.

Impacted file tree graph

@@             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     
Impacted Files Coverage Δ
...e/openwhisk/core/containerpool/ContainerPool.scala 88.44% <95.65%> (-8.76%) ⬇️
...che/openwhisk/core/invoker/LogStoreCollector.scala 0.00% <0.00%> (-100.00%) ⬇️
...core/database/cosmosdb/RxObservableImplicits.scala 0.00% <0.00%> (-100.00%) ⬇️
...ore/database/cosmosdb/cache/CacheInvalidator.scala 0.00% <0.00%> (-100.00%) ⬇️
...e/database/cosmosdb/cache/ChangeFeedConsumer.scala 0.00% <0.00%> (-100.00%) ⬇️
...core/database/cosmosdb/CosmosDBArtifactStore.scala 0.00% <0.00%> (-95.85%) ⬇️
...sk/core/database/cosmosdb/CosmosDBViewMapper.scala 0.00% <0.00%> (-93.90%) ⬇️
...tabase/cosmosdb/cache/CacheInvalidatorConfig.scala 0.00% <0.00%> (-92.31%) ⬇️
...a/org/apache/openwhisk/http/BasicHttpService.scala 3.33% <0.00%> (-86.67%) ⬇️
...la/org/apache/openwhisk/http/BasicRasService.scala 16.66% <0.00%> (-83.34%) ⬇️
... and 44 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 6686820...0c91e52. Read the comment docs.

@ningyougang ningyougang force-pushed the not-create-prewarm-when-memory-reach-limit branch from f07708f to c27800e Compare January 21, 2021 00:18
val newContainer = childFactory(context)
prewarmStartingPool = prewarmStartingPool + (newContainer -> (exec.kind, memoryLimit))
newContainer ! Start(exec, memoryLimit, ttl)
if (hasPoolSpaceFor(busyPool ++ freePool ++ prewarmedPool, memoryLimit)) {
Copy link
Contributor Author

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.

@ningyougang ningyougang force-pushed the not-create-prewarm-when-memory-reach-limit branch from c27800e to c9cba12 Compare January 21, 2021 03:31
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
Copy link
Contributor Author

@ningyougang ningyougang Jan 21, 2021

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.

Copy link
Member

Choose a reason for hiding this comment

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

Is this a typo?
+ +

Copy link
Contributor Author

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)
Copy link
Contributor Author

@ningyougang ningyougang Jan 21, 2021

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)) {
Copy link
Contributor Author

@ningyougang ningyougang Jan 21, 2021

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))

@ningyougang ningyougang reopened this Jan 25, 2021
@ningyougang ningyougang force-pushed the not-create-prewarm-when-memory-reach-limit branch from c9cba12 to 743070e Compare January 28, 2021 04:47
@ningyougang
Copy link
Contributor Author

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
Copy link
Member

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)) {
Copy link
Member

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.

Copy link
Contributor Author

@ningyougang ningyougang Jan 28, 2021

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.

Copy link
Member

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated accordingly.

@ningyougang ningyougang force-pushed the not-create-prewarm-when-memory-reach-limit branch from 1f270a1 to 0c91e52 Compare January 29, 2021 00:49
.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)) {
Copy link
Contributor Author

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")
Copy link
Contributor Author

@ningyougang ningyougang Jan 29, 2021

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.

Copy link
Member

@style95 style95 left a 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
Copy link
Member

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@ningyougang ningyougang merged commit c6e32b1 into apache:master Feb 1, 2021
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.

3 participants