Skip to content

Instantly share code, notes, and snippets.

@jeffque
Last active January 28, 2025 17:16
Show Gist options
  • Save jeffque/1ae97c285cf35b13edeb4612a2911b87 to your computer and use it in GitHub Desktop.
Save jeffque/1ae97c285cf35b13edeb4612a2911b87 to your computer and use it in GitHub Desktop.
A controller that yields a stream of results while computing Ackerman Peter function to check timeout problems in Spring Boot
@RestController
class SlowlorrisController {
@GetMapping(path = "/slowlorris2", produces = "text/plain")
StreamingResponseBody teste2() {
return out -> {
out.write(("COMEÇANDO!!!\n").getBytes(Charset.defaultCharset()));
out.flush();
for (int i = 0; i < 1000; i++) {
out.write(("rodada %d\n".formatted(i)).getBytes(Charset.defaultCharset()));
System.out.println("passei aqui antes do ack peter");
final var result = ackPeter(3, 3, out);
System.out.println("passei aqui depois do ack peter");
out.write(("\tresult %d\n".formatted(result)).getBytes(Charset.defaultCharset()));
out.flush();
}
out.write(("FINISHED\n").getBytes(Charset.defaultCharset()));
};
}
@GetMapping(path = "/slowlorris", produces = "text/plain")
ResponseEntity<StreamingResponseBody> teste() {
return ResponseEntity
.ok()
.body(out -> {
out.write(("COMEÇANDO!!!\n").getBytes(Charset.defaultCharset()));
out.flush();
for (int i = 0; i < 1000; i++) {
out.write(("rodada %d\n".formatted(i)).getBytes(Charset.defaultCharset()));
System.out.println("passei aqui antes do ack peter");
final var result = ackPeter(3, 3, out);
System.out.println("passei aqui depois do ack peter");
out.write(("\tresult %d\n".formatted(result)).getBytes(Charset.defaultCharset()));
out.flush();
}
out.write(("FINISHED\n").getBytes(Charset.defaultCharset()));
});
}
interface Continuation {
boolean finished();
long value();
Continuation step();
// computation has over
static Continuation found(long v) {
return new Continuation() {
@Override
public boolean finished() {
return true;
}
@Override
public long value() {
return v;
}
@Override
public Continuation step() {
return this;
}
};
}
// go on computing
static Continuation goon(Supplier<Continuation> nextStep) {
return new Continuation() {
@Override
public boolean finished() {
return false;
}
@Override
public long value() {
return 0;
}
@Override
public Continuation step() {
return nextStep.get();
}
};
}
}
private static Continuation ackermannPeter(long m, Continuation c, OutputStream out) {
if (!c.finished()) {
safewrite(out, "descendo com m %d e n continuation\n".formatted(m));
return Continuation.goon(() -> {
final var next = c.step();
return Continuation.goon(() -> ackermannPeter(m, next, out));
});
}
final var n = c.value();
safewrite(out, "descendo com m %d e n %d\n".formatted(m, n));
if (m <= 0) {
return Continuation.found(n + 1);
}
if (n <= 0) {
return Continuation.goon(() -> ackermannPeter(m - 1, Continuation.found(1), out));
}
return Continuation.goon(() ->
ackermannPeter(m - 1,
Continuation.goon(() -> ackermannPeter(m, Continuation.found(n - 1), out
)), out)
);
}
private static void safewrite(OutputStream out, String s) {
try {
out.write(s.getBytes(Charset.defaultCharset()));
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
public static long ackPeter(long m, long n, OutputStream out) {
return compute(Continuation.goon(() -> ackermannPeter(m, Continuation.found(n), new FilterOutputStream(out) {
long startWindow = System.currentTimeMillis();
int cnt = 0;
@Override
public void write(byte[] b) throws IOException {
super.write(b);
cnt++;
if (cnt % 8000 == 0) {
long now = System.currentTimeMillis();
super.write(("SINCELASTCALL: %d\n".formatted(now - startWindow)).getBytes(Charset.defaultCharset()));
startWindow = now;
super.flush();
cnt = 0;
}
}
})));
}
static long compute(Continuation c) {
while (!c.finished()) {
c = c.step();
}
return c.value();
}
}
@jeffque
Copy link
Author

jeffque commented Jan 28, 2025

Check https://computaria.gitlab.io/blog/2024/01/23/trampoline-ackermann-peter for details about the implementation of Ackermann Peter function

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment