-
Notifications
You must be signed in to change notification settings - Fork 106
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Re-Insert Memory Reserve for Queries and Upgrades (#4158)
With the incremental GC, programs can scale to the full 4GB memory space. As a consequence, update calls can allocate the full memory space, such that even a simple query, a simple composite query, or a simple upgrade logic can no longer succeed. This could also happen with classical non-copying GCs if deterministic time slicing is sufficiently extended. This PR prevents update calls (including canister initialization, heartbeats, and timers) from allocating the full memory by leaving a reserve for queries, composite queries, and canister upgrades. During queries, composite queries, and canister upgrades, garbage collection is suspended, such that the reserve is available to the mutator code. Callbacks of composite queries can also use the memory reserve. The current allocation limit for upgrade calls is 3.75 GB and applies to all GCs. This gives a reserve of 224 MB for the incremental GC as the last 32MB partition is unallocated in the current design. The scheduling heuristics of the incremental and generational GC needs to consider the reduced capacity for determining memory shortage. This PR can be viewed as a temporary measure until a memory reserve is implemented in the IC runtime system. The memory reserve may **not** be sufficient for a complex canister upgrade logic or large amount of stable heap data. Moreover, the upgrade logic may exceed the instruction limit. Thorough upgrade testing is required for canisters in any case.
- Loading branch information
1 parent
64bad1a
commit c4c98d7
Showing
17 changed files
with
233 additions
and
22 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,8 @@ | ||
ingress Completed: Reply: 0x4449444c016c01b3c4b1f204680100010a00000000000000000101 | ||
ingress Completed: Reply: 0x4449444c0000 | ||
debug.print: (+335_544_320, 4_764_731_706) | ||
debug.print: (+335_544_320, 4_764_731_816) | ||
ingress Completed: Reply: 0x4449444c0000 | ||
debug.print: (+335_544_320, 4_764_731_523) | ||
debug.print: (+335_544_320, 4_764_731_633) | ||
ingress Completed: Reply: 0x4449444c0000 | ||
debug.print: (+335_544_320, 4_764_731_535) | ||
debug.print: (+335_544_320, 4_764_731_645) | ||
ingress Completed: Reply: 0x4449444c0000 |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,8 @@ | ||
ingress Completed: Reply: 0x4449444c016c01b3c4b1f204680100010a00000000000000000101 | ||
ingress Completed: Reply: 0x4449444c0000 | ||
debug.print: (+335_544_320, 4_898_949_603) | ||
debug.print: (+335_544_320, 4_898_949_723) | ||
ingress Completed: Reply: 0x4449444c0000 | ||
debug.print: (+335_544_320, 4_898_949_410) | ||
debug.print: (+335_544_320, 4_898_949_530) | ||
ingress Completed: Reply: 0x4449444c0000 | ||
debug.print: (+335_544_320, 4_898_949_423) | ||
debug.print: (+335_544_320, 4_898_949_543) | ||
ingress Completed: Reply: 0x4449444c0000 |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
ingress Completed: Reply: 0x4449444c016c01b3c4b1f204680100010a00000000000000000101 | ||
ingress Completed: Reply: 0x4449444c0000 | ||
debug.print: (50_227, +37_021_304, 767_984_255) | ||
debug.print: (50_070, +40_056_236, 830_437_406) | ||
debug.print: (50_227, +37_021_304, 767_984_266) | ||
debug.print: (50_070, +40_056_236, 830_437_417) | ||
ingress Completed: Reply: 0x4449444c0000 |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
ingress Completed: Reply: 0x4449444c016c01b3c4b1f204680100010a00000000000000000101 | ||
ingress Completed: Reply: 0x4449444c0000 | ||
debug.print: (50_227, +37_021_304, 815_894_722) | ||
debug.print: (50_070, +40_056_236, 880_136_109) | ||
debug.print: (50_227, +37_021_304, 815_894_734) | ||
debug.print: (50_070, +40_056_236, 880_136_121) | ||
ingress Completed: Reply: 0x4449444c0000 |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# INCREMENTAL-GC-ONLY | ||
# SKIP ic-ref-run | ||
install $ID memory-reserve-composite/memory-reserve-composite.mo "" | ||
ingress $ID prepare1 "DIDL\x00\x00" | ||
ingress $ID prepare2 "DIDL\x00\x00" | ||
query $ID allocateInCompositeQuery "DIDL\x00\x00" |
39 changes: 39 additions & 0 deletions
39
test/run-drun-non-ci/memory-reserve-composite/memory-reserve-composite.mo
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import Prim "mo:⛔"; | ||
actor { | ||
stable var stableData = Prim.Array_tabulate<Nat>(1024 * 1024, func(index) { index }); | ||
var array0 : [var Nat] = [var]; | ||
var array1 : [var Nat] = [var]; | ||
var array2 : [var Nat] = [var]; | ||
var array3 : [var Nat] = [var]; | ||
Prim.debugPrint("Initialized " # debug_show (Prim.rts_memory_size())); | ||
|
||
public func prepare1() : async () { | ||
array0 := Prim.Array_init<Nat>(256 * 1024 * 1024, 0); // 1GB | ||
array1 := Prim.Array_init<Nat>(256 * 1024 * 1024, 1); // 2GB | ||
Prim.debugPrint("Prepared1 " # debug_show (Prim.rts_memory_size())); | ||
}; | ||
|
||
public func prepare2() : async () { | ||
array2 := Prim.Array_init<Nat>(256 * 1024 * 1024, 2); // 3GB | ||
array3 := Prim.Array_init<Nat>(150 * 1024 * 1024, 3); // around 3.75GB | ||
Prim.debugPrint("Prepared2 " # debug_show (Prim.rts_memory_size())); | ||
}; | ||
|
||
public composite query func allocateInCompositeQuery() : async () { | ||
ignore Prim.Array_init<Nat>(50 * 1024 * 1024, 4); | ||
Prim.debugPrint("Composite query call " # debug_show (Prim.rts_memory_size())); | ||
assert (Prim.rts_memory_size() > 3840 * 1024 * 1024); | ||
await nestedQuery(); | ||
ignore Prim.Array_init<Nat>(5 * 1024 * 1024, 4); | ||
Prim.debugPrint("Composite query callback " # debug_show (Prim.rts_memory_size())); | ||
assert (Prim.rts_memory_size() > 3840 * 1024 * 1024); | ||
}; | ||
|
||
public query func nestedQuery() : async () { | ||
Prim.debugPrint("Nested query " # debug_show (Prim.rts_memory_size())); | ||
}; | ||
}; | ||
|
||
//SKIP run | ||
//SKIP run-ir | ||
//SKIP run-low |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# INCREMENTAL-GC-ONLY | ||
# SKIP ic-ref-run | ||
install $ID memory-reserve-query/memory-reserve-query.mo "" | ||
ingress $ID prepare1 "DIDL\x00\x00" | ||
ingress $ID prepare2 "DIDL\x00\x00" | ||
query $ID allocateInQuery "DIDL\x00\x00" |
31 changes: 31 additions & 0 deletions
31
test/run-drun-non-ci/memory-reserve-query/memory-reserve-query.mo
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import Prim "mo:⛔"; | ||
actor { | ||
stable var stableData = Prim.Array_tabulate<Nat>(1024 * 1024, func(index) { index }); | ||
var array0 : [var Nat] = [var]; | ||
var array1 : [var Nat] = [var]; | ||
var array2 : [var Nat] = [var]; | ||
var array3 : [var Nat] = [var]; | ||
Prim.debugPrint("Initialized " # debug_show (Prim.rts_memory_size())); | ||
|
||
public func prepare1() : async () { | ||
array0 := Prim.Array_init<Nat>(256 * 1024 * 1024, 0); // 1GB | ||
array1 := Prim.Array_init<Nat>(256 * 1024 * 1024, 1); // 2GB | ||
Prim.debugPrint("Prepared1 " # debug_show (Prim.rts_memory_size())); | ||
}; | ||
|
||
public func prepare2() : async () { | ||
array2 := Prim.Array_init<Nat>(256 * 1024 * 1024, 2); // 3GB | ||
array3 := Prim.Array_init<Nat>(150 * 1024 * 1024, 3); // around 3.75GB | ||
Prim.debugPrint("Prepared2 " # debug_show (Prim.rts_memory_size())); | ||
}; | ||
|
||
public query func allocateInQuery() : async () { | ||
ignore Prim.Array_init<Nat>(50 * 1024 * 1024, 4); | ||
Prim.debugPrint("Query call " # debug_show (Prim.rts_memory_size())); | ||
assert (Prim.rts_memory_size() > 3840 * 1024 * 1024); | ||
}; | ||
}; | ||
|
||
//SKIP run | ||
//SKIP run-ir | ||
//SKIP run-low |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# INCREMENTAL-GC-ONLY | ||
# SKIP ic-ref-run | ||
install $ID memory-reserve-update/memory-reserve-update.mo "" | ||
ingress $ID prepare1 "DIDL\x00\x00" | ||
ingress $ID prepare2 "DIDL\x00\x00" | ||
ingress $ID allocateInUpdate "DIDL\x00\x00" |
30 changes: 30 additions & 0 deletions
30
test/run-drun-non-ci/memory-reserve-update/memory-reserve-update.mo
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import Prim "mo:⛔"; | ||
actor { | ||
stable var stableData = Prim.Array_tabulate<Nat>(1024 * 1024, func(index) { index }); | ||
var array0 : [var Nat] = [var]; | ||
var array1 : [var Nat] = [var]; | ||
var array2 : [var Nat] = [var]; | ||
var array3 : [var Nat] = [var]; | ||
Prim.debugPrint("Initialized " # debug_show (Prim.rts_memory_size())); | ||
|
||
public func prepare1() : async () { | ||
array0 := Prim.Array_init<Nat>(256 * 1024 * 1024, 0); // 1GB | ||
array1 := Prim.Array_init<Nat>(256 * 1024 * 1024, 1); // 2GB | ||
Prim.debugPrint("Prepared1 " # debug_show (Prim.rts_memory_size())); | ||
}; | ||
|
||
public func prepare2() : async () { | ||
array2 := Prim.Array_init<Nat>(256 * 1024 * 1024, 2); // 3GB | ||
array3 := Prim.Array_init<Nat>(150 * 1024 * 1024, 3); // around 3.75GB | ||
Prim.debugPrint("Prepared2 " # debug_show (Prim.rts_memory_size())); | ||
}; | ||
|
||
public func allocateInUpdate() : async () { | ||
Prim.debugPrint("Update call " # debug_show (Prim.rts_memory_size())); | ||
ignore Prim.Array_init<Nat>(50 * 1024 * 1024, 4); | ||
}; | ||
}; | ||
|
||
//SKIP run | ||
//SKIP run-ir | ||
//SKIP run-low |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# INCREMENTAL-GC-ONLY | ||
# SKIP ic-ref-run | ||
install $ID memory-reserve-upgrade/memory-reserve-upgrade.mo "" | ||
ingress $ID prepare1 "DIDL\x00\x00" | ||
ingress $ID prepare2 "DIDL\x00\x00" | ||
upgrade $ID memory-reserve-upgrade/memory-reserve-upgrade.mo "" |
25 changes: 25 additions & 0 deletions
25
test/run-drun-non-ci/memory-reserve-upgrade/memory-reserve-upgrade.mo
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import Prim "mo:⛔"; | ||
actor { | ||
stable var stableData = Prim.Array_tabulate<Nat>(1024 * 1024, func(index) { index }); | ||
var array0 : [var Nat] = [var]; | ||
var array1 : [var Nat] = [var]; | ||
var array2 : [var Nat] = [var]; | ||
var array3 : [var Nat] = [var]; | ||
Prim.debugPrint("Initialized " # debug_show (Prim.rts_memory_size())); | ||
|
||
public func prepare1() : async () { | ||
array0 := Prim.Array_init<Nat>(256 * 1024 * 1024, 0); // 1GB | ||
array1 := Prim.Array_init<Nat>(256 * 1024 * 1024, 1); // 2GB | ||
Prim.debugPrint("Prepared1 " # debug_show (Prim.rts_memory_size())); | ||
}; | ||
|
||
public func prepare2() : async () { | ||
array2 := Prim.Array_init<Nat>(256 * 1024 * 1024, 2); // 3GB | ||
array3 := Prim.Array_init<Nat>(150 * 1024 * 1024, 3); // around 3.75GB | ||
Prim.debugPrint("Prepared2 " # debug_show (Prim.rts_memory_size())); | ||
}; | ||
}; | ||
|
||
//SKIP run | ||
//SKIP run-ir | ||
//SKIP run-low |
This file contains 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