Skip to content

Commit

Permalink
Integrate Regions in Random GC Tests (#4144)
Browse files Browse the repository at this point in the history
Extending the random GC tests to also allocate regions. 
The same tests can also be used for long-running and larger-scaling tests. 
Therefore, the maximum number of randomly created regions is limited - until region garbage collection will be supported.
  • Loading branch information
luc-blaeser authored Feb 15, 2024
1 parent 82ff3eb commit a27efd6
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 7 deletions.
2 changes: 2 additions & 0 deletions test/run-drun/gc-random-test-force-gc.mo
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//MOC-FLAG --stable-regions

import GCRandomTest "gc-random-test/gc-random-test";

actor {
Expand Down
3 changes: 3 additions & 0 deletions test/run-drun/gc-random-test-no-force-gc.mo
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
//MOC-NO-FORCE-GC
//MOC-FLAG --stable-regions
//MOC-FLAG --max-stable-pages=1000000

import GCRandomTest "gc-random-test/gc-random-test";

actor {
Expand Down
21 changes: 15 additions & 6 deletions test/run-drun/gc-random-test/gc-random-test.mo
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,33 @@ module {
public class GCRandomTest() {
let seed = 4711;
let random = Random.Random(seed);
let types = Types.allocationTypes();
var root : Values.RandomValue = #none;
var allocationCount = 0;
let allocationPerType = Prim.Array_init<Nat>(types.size(), 0);
func maxAlive() : Nat {
assert(allocationCount > 0);
assert (allocationCount > 0);
let averageObjectSize = Prim.rts_total_allocation() / allocationCount;
(Prim.rts_heap_size() + averageObjectSize - 1) / averageObjectSize;
};
func randomAllocate() {
Prim.debugPrint("Random allocation");
let types = Types.allocationTypes();
let factory = types[random.next() % types.size()];
let randomValue = factory.instantiate(random);
allocationCount += 1;
append(randomValue);
let index = random.next() % types.size();
let factory = types[index];
let canAllocate = switch (factory.allocationLimit) {
case null true;
case (?limit) { allocationPerType[index] < limit };
};
if (canAllocate) {
let randomValue = factory.instantiate(random);
allocationCount += 1;
allocationPerType[index] += 1;
append(randomValue);
};
};
func append(value : Values.RandomValue) {
Expand Down
82 changes: 81 additions & 1 deletion test/run-drun/gc-random-test/types.mo
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ import Prim "mo:prim";
import Array "array";
import Random "random";
import Values "values";
import Region "../stable-region/Region";
module {
public type RandomType = {
name : Text;
allocationLimit : ?Nat;
instantiate(random : Random.Random) : Values.RandomValue;
readReferences(source : Values.RandomValue) : [Values.RandomValue];
append(target : Values.RandomValue, value : Values.RandomValue) : Bool;
Expand All @@ -18,7 +20,7 @@ module {
};
public func allocationTypes() : [RandomType] {
[RandomObjectType, RandomArrayType, RandomBlobType, RandomBoxType, RandomTextType, RandomOptionType];
[RandomObjectType, RandomArrayType, RandomBlobType, RandomBoxType, RandomTextType, RandomOptionType, RandomRegionType];
};
public func getType(value : Values.RandomValue) : RandomType {
Expand All @@ -30,6 +32,7 @@ module {
case (#box _) RandomBoxType;
case (#text _) RandomTextType;
case (#option _) RandomOptionType;
case (#region _) RandomRegionType;
};
};
Expand Down Expand Up @@ -57,6 +60,7 @@ module {
public object NoneType {
public let name = "none";
public let allocationLimit : ?Nat = null;
public func instantiate(_random : Random.Random) : Values.RandomValue {
Prim.trap("unsupported");
Expand Down Expand Up @@ -98,6 +102,7 @@ module {
public object RandomObjectType {
public let name = "object";
public let allocationLimit : ?Nat = null;
public func instantiate(random : Random.Random) : Values.RandomValue {
let number = random.next();
Expand Down Expand Up @@ -182,6 +187,7 @@ module {
public object RandomArrayType {
public let name = "array";
public let allocationLimit : ?Nat = null;
public func instantiate(random : Random.Random) : Values.RandomValue {
let maxLength = 100_000;
Expand Down Expand Up @@ -287,6 +293,7 @@ module {
public object RandomBlobType {
public let name = "blob";
public let allocationLimit : ?Nat = null;
public func instantiate(random : Random.Random) : Values.RandomValue {
let maxLength = 128 * 1024 * 1024;
Expand Down Expand Up @@ -341,6 +348,7 @@ module {
public object RandomBoxType {
public let name = "box";
public let allocationLimit : ?Nat = null;
public func instantiate(random : Random.Random) : Values.RandomValue {
let randomBigInt : Int = (random.next() * 2 ** 64 + random.next() * 2 ** 32 + random.next()) * -1 * random.next() % 2;
Expand Down Expand Up @@ -404,6 +412,7 @@ module {
public object RandomTextType {
public let name = "text";
public let allocationLimit : ?Nat = null;
public func instantiate(random : Random.Random) : Values.RandomValue {
var text = "";
Expand Down Expand Up @@ -477,6 +486,7 @@ module {
public object RandomOptionType {
public let name = "option";
public let allocationLimit : ?Nat = null;
public func instantiate(random : Random.Random) : Values.RandomValue {
let types = allocationTypes();
Expand Down Expand Up @@ -550,4 +560,74 @@ module {
};
};
};
public object RandomRegionType {
public let name = "region";
public let allocationLimit = ?32752; // 32 * 1024 minus 16 reserved ids
public func instantiate(random : Random.Random) : Values.RandomValue {
let PageSize = Prim.natToNat64(64 * 1024);
let maxPages = 128;
let pageCount = Prim.natToNat64(1 + random.next() % maxPages);
let region = Region.new();
let checkValue = Prim.natToNat8(random.next() % 2 ** 8);
let result = Region.grow(region, pageCount);
assert (result != 0xFFFF_FFFF_FFFF_FFFF);
Region.storeNat8(region, 0, checkValue);
Region.storeNat8(region, pageCount * PageSize - 2, checkValue);
#region {
region;
checkSize = pageCount;
checkValue;
};
};
public func readReferences(_source : Values.RandomValue) : [Values.RandomValue] {
[];
};
public func append(_target : Values.RandomValue, _value : Values.RandomValue) : Bool {
false;
};
public func randomWrite(_random : Random.Random, _target : Values.RandomValue, _value : Values.RandomValue) {};
public func randomCheck(_random : Random.Random, value : Values.RandomValue) {
let PageSize = Prim.natToNat64(64 * 1024);
let regionValue = cast(value);
let region = regionValue.region;
assert (Region.size(region) == regionValue.checkSize);
assert (Region.loadNat8(region, 0) == regionValue.checkValue);
assert (Region.loadNat8(region, regionValue.checkSize * PageSize - 2) == regionValue.checkValue);
};
public func identical(left : Values.RandomValue, right : Values.RandomValue) : Bool {
let leftRegion = cast(left).region;
let rightRegion = cast(right).region;
Region.id(leftRegion) == Region.id(rightRegion);
};
public func hash(value : Values.RandomValue) : Nat {
let regionValue = cast(value);
let region = regionValue.region;
Prim.nat64ToNat(Region.size(region)) * 2 ** 8 + Prim.nat8ToNat(regionValue.checkValue);
};
public func text(value : Values.RandomValue) : Text {
shortText(value);
};
public func shortText(value : Values.RandomValue) : Text {
let regionValue = cast(value);
let region = regionValue.region;
"region(size = " # debug_show (Region.size(region)) # ")";
};
func cast(value : Values.RandomValue) : Values.RandomRegion {
switch value {
case (#region randomRegion) randomRegion;
case _ Prim.trap("invalid cast");
};
};
};
};
8 changes: 8 additions & 0 deletions test/run-drun/gc-random-test/values.mo
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Array "array";
import Region "../stable-region/Region";

module {
public type RandomValue = {
Expand All @@ -9,6 +10,7 @@ module {
#box : RandomBox;
#text : RandomText;
#option : RandomOption;
#region : RandomRegion;
};

public type RandomObject = {
Expand Down Expand Up @@ -38,6 +40,12 @@ module {

public type RandomOption = ?RandomValue;

public type RandomRegion = {
region : Region;
checkSize : Nat64;
checkValue : Nat8;
};

public func isNone(value : RandomValue) : Bool {
switch value {
case (#none) true;
Expand Down

0 comments on commit a27efd6

Please sign in to comment.