Skip to content

Commit

Permalink
Limit the number of reported warnings
Browse files Browse the repository at this point in the history
Artifically limiting the number of reported warnings to 100.
Also added benchmarks with random ints to investigate perf issues when
dealing with warnings (future task).

Closes #6283.
  • Loading branch information
hubertp committed May 5, 2023
1 parent 30f27be commit 4b2ce8c
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@
import org.openjdk.jmh.infra.BenchmarkParams;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Random;
import java.util.concurrent.TimeUnit;

@BenchmarkMode(Mode.AverageTime)
Expand All @@ -28,27 +32,50 @@
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Benchmark)
public class WarningBenchmarks extends TestBase {
private static final int INPUT_VEC_SIZE = 10000;
private static final int INPUT_VEC_SIZE = 10_000;
private static final int INPUT_DIFF_VEC_SIZE = 10_000;
private Context ctx;
private Value vecSumBench;

private Value createVec;
private Value mapVecWithWarnings;
private Value noWarningsVec;
private Value sameWarningVec;
private Value randomVec;
private Value randomElemsWithWarningsVec;
private Value constElem;
private Value constElemWithWarning;

private Value elem;
private String benchmarkName;

private Value elemWithWarning;
private int randomVectorSum = 0;

private String benchmarkName;
private record GeneratedVector(StringBuilder repr, int sum) {}

private GeneratedVector generateRandomVector(Random random, String vectorName, long vectorSize, int maxRange) {
List<Integer> primitiveValues = new ArrayList<>();
random.ints(vectorSize, 0, maxRange).forEach(primitiveValues::add);
Collections.shuffle(primitiveValues);
var sb = new StringBuilder();
sb.append(vectorName).append(" = [");
var sum = 0;
for (Integer intValue : primitiveValues) {
sb.append(intValue).append(",");
sum += Math.abs(intValue);
}
sb.setCharAt(sb.length() - 1, ']');
sb.append('\n');
return new GeneratedVector(sb, sum);
}

@Setup
public void initializeBench(BenchmarkParams params) throws IOException {
ctx = createDefaultContext();
var random = new Random(42);

benchmarkName = SrcUtil.findName(params);

var code = """
var code = new StringBuilder("""
from Standard.Base import all
vec_sum_bench : Vector Integer -> Integer
Expand All @@ -61,18 +88,34 @@ public void initializeBench(BenchmarkParams params) throws IOException {
elem =
42
elem_with_warning =
elem_const_with_warning =
x = 42
Warning.attach "Foo!" x
""";
var src = SrcUtil.source(benchmarkName, code);
elem_with_warning v =
Warning.attach "Foo!" v
map_vector_with_warnings vec =
vec.map (e-> elem_with_warning e)
""");

// generate random vector
var randomIntVectorName = "vector_with_random_values";
var vectorWithRandomValues = generateRandomVector(random, randomIntVectorName, INPUT_DIFF_VEC_SIZE, 3_000);
code.append(vectorWithRandomValues.repr());
randomVectorSum = vectorWithRandomValues.sum();

var src = SrcUtil.source(benchmarkName, code.toString());
Value module = ctx.eval(src);
vecSumBench = Objects.requireNonNull(module.invokeMember(MethodNames.Module.EVAL_EXPRESSION, "vec_sum_bench"));
createVec = Objects.requireNonNull(module.invokeMember(MethodNames.Module.EVAL_EXPRESSION, "create_vec"));
elem = Objects.requireNonNull(module.invokeMember(MethodNames.Module.EVAL_EXPRESSION, "elem"));
elemWithWarning = Objects.requireNonNull(module.invokeMember(MethodNames.Module.EVAL_EXPRESSION, "elem_with_warning"));
noWarningsVec = createVec.execute(INPUT_VEC_SIZE, elem);
sameWarningVec = createVec.execute(INPUT_VEC_SIZE, elemWithWarning);
mapVecWithWarnings = Objects.requireNonNull(module.invokeMember(MethodNames.Module.EVAL_EXPRESSION, "map_vector_with_warnings"));
constElem = Objects.requireNonNull(module.invokeMember(MethodNames.Module.EVAL_EXPRESSION, "elem"));
constElemWithWarning = Objects.requireNonNull(module.invokeMember(MethodNames.Module.EVAL_EXPRESSION, "elem_const_with_warning"));
noWarningsVec = createVec.execute(INPUT_VEC_SIZE, constElem);
sameWarningVec = createVec.execute(INPUT_VEC_SIZE, constElemWithWarning);
randomVec = Objects.requireNonNull(module.invokeMember(MethodNames.Module.EVAL_EXPRESSION, randomIntVectorName));
randomElemsWithWarningsVec = mapVecWithWarnings.execute(randomVec);
}

@TearDown
Expand All @@ -83,17 +126,30 @@ public void cleanup() {
@Benchmark
public void noWarningsVecSum() {
Value res = vecSumBench.execute(noWarningsVec);
checkResult(res);
checkResult(res, INPUT_VEC_SIZE*42);
}

@Benchmark
public void sameWarningVecSum() {
Value res = vecSumBench.execute(sameWarningVec);
checkResult(res);
checkResult(res, INPUT_VEC_SIZE*42);
}

@Benchmark
public void randomElementsVecSum() {
Value res = vecSumBench.execute(randomVec);
checkResult(res, randomVectorSum);
}

private static void checkResult(Value res) {
if (res.asInt() != INPUT_VEC_SIZE*42) {
@Benchmark
public void diiffWarningRandomElementsVecSum() {
Value res = vecSumBench.execute(randomElemsWithWarningsVec);
checkResult(res, randomVectorSum);
}


private static void checkResult(Value res, int expected) {
if (res.asInt() != expected) {
throw new AssertionError("Expected result: " + INPUT_VEC_SIZE*42 + ", got: " + res.asInt());
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
@ExportLibrary(WarningsLibrary.class)
@ExportLibrary(ReflectionLibrary.class)
public final class WithWarnings implements TruffleObject {

private static final int MAX_WARNINGS_LIMIT = 100;

private final EconomicSet<Warning> warnings;
private final Object value;

Expand Down Expand Up @@ -160,15 +163,31 @@ public int hashCode(Object o) {
@CompilerDirectives.TruffleBoundary
private EconomicSet<Warning> createSetFromArray(Warning[] entries) {
EconomicSet<Warning> set = EconomicSet.create(new WarningEquivalence());
set.addAll(Arrays.stream(entries).iterator());
for (int i=0; i<entries.length; i++) {
if (set.size() >= MAX_WARNINGS_LIMIT) {
return set;
}
set.add(entries[i]);
}

return set;
}

@CompilerDirectives.TruffleBoundary
private EconomicSet<Warning> cloneSetAndAppend(EconomicSet<Warning> initial, Warning[] entries) {
EconomicSet<Warning> set = EconomicSet.create(new WarningEquivalence());
set.addAll(initial.iterator());
set.addAll(Arrays.stream(entries).iterator());
for (Warning warning: initial) {
if (set.size() >= MAX_WARNINGS_LIMIT) {
return set;
}
set.add(warning);
}
for (int i=0; i<entries.length; i++) {
if (set.size() >= MAX_WARNINGS_LIMIT) {
return set;
}
set.add(entries[i]);
}
return set;
}

Expand Down
9 changes: 9 additions & 0 deletions test/Tests/src/Semantic/Warnings_Spec.enso
Original file line number Diff line number Diff line change
Expand Up @@ -408,4 +408,13 @@ spec = Test.group "Dataflow Warnings" <|
result_4 = f a 1 + f a 2 + f a 3
Warning.get_all result_4 . map (x-> x.value.to_text) . should_equal ["Baz!", "Baz!", "Baz!"]

Test.specify "should only report the first 100 unique warnings" <|
vec = (0.up_to 500).map(e -> Warning.attach "Foo!" e)
vec_plus_1 = vec.map(e -> e+1)
Warning.get_all vec_plus_1 . length . should_equal 100

warn = Warning.attach "Boo!" 42
vec_2 = (0.up_to 500).map(e -> if (e < 30) then Warning.attach "Foo!" e else (warn + e))
Warning.get_all vec_2 . length . should_equal 31

main = Test_Suite.run_main spec

0 comments on commit 4b2ce8c

Please sign in to comment.