@@ -129,44 +129,40 @@ class ContainerPool(childFactory: ActorRefFactory => ActorRef,
129
129
val memory = r.action.limits.memory.megabytes.MB
130
130
131
131
val createdContainer =
132
- // Is there enough space on the invoker for this action to be executed.
133
- if (hasPoolSpaceFor(busyPool ++ prewarmedPool, memory)) {
134
- // Schedule a job to a warm container
135
- ContainerPool
136
- .schedule(r.action, r.msg.user.namespace.name, freePool)
137
- .map(container => (container, container._2.initingState)) // warmed, warming, and warmingCold always know their state
138
- .orElse(
139
- // There was no warm/warming/warmingCold container. Try to take a prewarm container or a cold container.
140
-
141
- // Is there enough space to create a new container or do other containers have to be removed?
142
- if (hasPoolSpaceFor(busyPool ++ freePool ++ prewarmedPool, memory)) {
132
+ // Schedule a job to a warm container
133
+ ContainerPool
134
+ .schedule(r.action, r.msg.user.namespace.name, freePool)
135
+ .map(container => (container, container._2.initingState)) // warmed, warming, and warmingCold always know their state
136
+ .orElse(
137
+ // There was no warm/warming/warmingCold container. Try to take a prewarm container or a cold container.
138
+ // When take prewarm container, has no need to judge whether user memory is enough
139
+ takePrewarmContainer(r.action)
140
+ .map(container => (container, " prewarmed" ))
141
+ .orElse {
142
+ // Is there enough space to create a new container or do other containers have to be removed?
143
+ if (hasPoolSpaceFor(busyPool ++ freePool ++ prewarmedPool, prewarmStartingPool, memory)) {
144
+ val container = Some (createContainer(memory), " cold" )
145
+ incrementColdStartCount(kind, memory)
146
+ container
147
+ } else None
148
+ })
149
+ .orElse(
150
+ // Remove a container and create a new one for the given job
151
+ ContainerPool
152
+ // Only free up the amount, that is really needed to free up
153
+ .remove(freePool, Math .min(r.action.limits.memory.megabytes, memoryConsumptionOf(freePool)).MB )
154
+ .map(removeContainer)
155
+ // If the list had at least one entry, enough containers were removed to start the new container. After
156
+ // removing the containers, we are not interested anymore in the containers that have been removed.
157
+ .headOption
158
+ .map(_ =>
143
159
takePrewarmContainer(r.action)
144
- .map(container => (container, " prewarmed " ))
145
- .orElse {
146
- val container = Some (createContainer(memory), " cold " )
160
+ .map(container => (container, " recreatedPrewarm " ))
161
+ .getOrElse {
162
+ val container = (createContainer(memory), " recreated " )
147
163
incrementColdStartCount(kind, memory)
148
164
container
149
- }
150
- } else None )
151
- .orElse(
152
- // Remove a container and create a new one for the given job
153
- ContainerPool
154
- // Only free up the amount, that is really needed to free up
155
- .remove(freePool, Math .min(r.action.limits.memory.megabytes, memoryConsumptionOf(freePool)).MB )
156
- .map(removeContainer)
157
- // If the list had at least one entry, enough containers were removed to start the new container. After
158
- // removing the containers, we are not interested anymore in the containers that have been removed.
159
- .headOption
160
- .map(_ =>
161
- takePrewarmContainer(r.action)
162
- .map(container => (container, " recreatedPrewarm" ))
163
- .getOrElse {
164
- val container = (createContainer(memory), " recreated" )
165
- incrementColdStartCount(kind, memory)
166
- container
167
- }))
168
-
169
- } else None
165
+ }))
170
166
171
167
createdContainer match {
172
168
case Some (((actor, data), containerState)) =>
@@ -371,9 +367,15 @@ class ContainerPool(childFactory: ActorRefFactory => ActorRef,
371
367
372
368
/** Creates a new prewarmed container */
373
369
def prewarmContainer (exec : CodeExec [_], memoryLimit : ByteSize , ttl : Option [FiniteDuration ]): Unit = {
374
- val newContainer = childFactory(context)
375
- prewarmStartingPool = prewarmStartingPool + (newContainer -> (exec.kind, memoryLimit))
376
- newContainer ! Start (exec, memoryLimit, ttl)
370
+ if (hasPoolSpaceFor(busyPool ++ freePool ++ prewarmedPool, prewarmStartingPool, memoryLimit)) {
371
+ val newContainer = childFactory(context)
372
+ prewarmStartingPool = prewarmStartingPool + (newContainer -> (exec.kind, memoryLimit))
373
+ newContainer ! Start (exec, memoryLimit, ttl)
374
+ } else {
375
+ logging.warn(
376
+ this ,
377
+ s " Cannot create prewarm container due to reach the invoker memory limit: ${poolConfig.userMemory.toMB}" )
378
+ }
377
379
}
378
380
379
381
/** this is only for cold start statistics of prewarm configs, e.g. not blackbox or other configs. */
@@ -439,8 +441,10 @@ class ContainerPool(childFactory: ActorRefFactory => ActorRef,
439
441
* @param memory The amount of memory to check.
440
442
* @return true, if there is enough space for the given amount of memory.
441
443
*/
442
- def hasPoolSpaceFor [A ](pool : Map [A , ContainerData ], memory : ByteSize ): Boolean = {
443
- memoryConsumptionOf(pool) + memory.toMB <= poolConfig.userMemory.toMB
444
+ def hasPoolSpaceFor [A ](pool : Map [A , ContainerData ],
445
+ prewarmStartingPool : Map [A , (String , ByteSize )],
446
+ memory : ByteSize ): Boolean = {
447
+ memoryConsumptionOf(pool) + prewarmStartingPool.map(_._2._2.toMB).sum + memory.toMB <= poolConfig.userMemory.toMB
444
448
}
445
449
446
450
/**
0 commit comments