blob: 1b63f605b617ee89174cadbf226ef7eb70ee1bff [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.tomee.itest.startup;
import com.github.tomaslanger.chalk.Ansi;
import org.apache.cxf.jaxrs.client.WebClient;
import org.apache.openejb.loader.Files;
import org.apache.openejb.loader.IO;
import org.apache.openejb.math.stat.descriptive.SynchronizedDescriptiveStatistics;
import org.apache.openejb.util.Join;
import org.apache.tomee.server.composer.TomEE;
import org.junit.Test;
import javax.ws.rs.core.Response;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
public class StartupTest {
private static final File downloads = new File("/Users/dblevins/work/apache/downloads");
public StartupTest() {
if (!downloads.exists()) assertTrue(downloads.mkdir());
}
public static class Binary implements Sortable<Binary> {
final AtomicInteger nameWidth;
final AtomicInteger count = new AtomicInteger(0);
final SynchronizedDescriptiveStatistics extraction = new SynchronizedDescriptiveStatistics(2000);
final SynchronizedDescriptiveStatistics startup = new SynchronizedDescriptiveStatistics(2000);
final SynchronizedDescriptiveStatistics other = new SynchronizedDescriptiveStatistics(2000);
final File file;
final String name;
String last;
public Binary(final AtomicInteger nameWidth, final File file) {
this.file = file;
this.name = this.file.getName().replace(".tar.gz", "");
this.nameWidth = nameWidth;
this.nameWidth.set(Math.max(this.nameWidth.get(), name.length()));
}
@Override
public String last() {
return last;
}
public String get() {
final String namePadded = String.format("%-" + nameWidth.get() + "s", name);
final String nameColored = namePadded.replaceAll("(apache-tomee-)(.+)-(.+)", "$1\033[38;5;231m$2\033[0m-\033[38;5;186m$3\033[0m");
TomEE tomee = null;
try {
final long start = System.nanoTime();
tomee = TomEE.from(file)
.out(INGORED())
.err(INGORED())
.add("webapps/speed.war", new File(StartupTest.downloads, "speed.war"))
.build();
final String address = tomee.toURI().resolve("/speed").toURL().toExternalForm();
final WebClient webClient = WebClient.create(address);
{// valid token
final Response response = webClient.reset()
.path("/color/")
.header("Content-Type", "application/json")
.get();
assertEquals(200, response.getStatus());
}
extraction.addValue(toMillis(tomee.getStats().getExtracted()));
startup.addValue(toMillis(tomee.getStats().getStartup()));
other.addValue(toMillis(System.nanoTime() - start));
final int i = count.incrementAndGet();
final long extractedTime = (long) extraction.getPercentile(90.0);
final long startupTime = (long) startup.getPercentile(90.0);
final long executionTime = (long) other.getPercentile(90.0);
final int unit = 100;
final int n = (int) (executionTime / unit);
final char[] bar = new char[n];
int j = 0;
for (int k = 0; k * unit < extractedTime && j < bar.length; k++, j++) bar[j] = 'x';
for (int k = 0; k * unit < startupTime && j < bar.length; k++, j++) bar[j] = 's';
for (; j < bar.length; j++) bar[j] = 'o';
final String executionBar = new String(bar)
.replaceFirst("(x+)(s+)?(o+)?", "\033[38;5;060m$1\033[38;5;088m$2\033[38;5;071m$3\033[0m");
return last = String.format("%s %4s %6s %6s %6s %s",
nameColored,
i,
extractedTime,
startupTime,
executionTime,
executionBar
);
} catch (Throwable e1) {
return String.format("%-" + nameWidth.get() + "s %s: %s", nameColored, e1.getClass().getSimpleName(), e1.getMessage());
} finally {
if (tomee != null) tomee.shutdown();
}
}
@Override
public int compareTo(final Binary that) {
final Double a = this.other.getPercentile(90.0);
final Double b = that.other.getPercentile(90.0);
return a.compareTo(b);
}
}
@Test
public void test() throws Exception {
final AtomicInteger nameWidth = new AtomicInteger(10);
final List<Sortable> list = Stream.of(downloads.listFiles())
.filter(file -> file.getName().endsWith(".tar.gz"))
// .peek(System.out::println)
.filter(file -> file.getName().matches(".*(plus|webprofile).*"))
.filter(file -> !file.getName().contains("beta"))
.map(this::toJaxrs)
.filter(File::exists)
// .filter(file -> file.getName().contains("-M"))
.peek(System.out::println)
.map(file -> new Binary(nameWidth, file))
.map(binary -> (Sortable) binary)
.collect(Collectors.toList());
runAndSort(() -> true, list);
// run(() -> true,
// new Binary(nameWidth, new File(downloads, "apache-tomee-1.0.0-plus.tar.gz"))::run,
// new Binary(nameWidth, new File(downloads, "apache-tomee-1.7.0-plus.tar.gz"))::run,
// new Binary(nameWidth, new File(downloads, "apache-tomee-7.0.0-plus.tar.gz"))::run,
// new Binary(nameWidth, new File(downloads, "apache-tomee-8.0.0-M1-plus.tar.gz"))::run
// );
}
private File toJaxrs(final File file) {
if (!file.getName().contains("-1.")) return file;
if (!file.getName().contains("webprofile")) return file;
return new File(file.getAbsolutePath().replace("webprofile", "jaxrs"));
}
private static long toMillis(final long time) {
return TimeUnit.NANOSECONDS.toMillis(time);
}
private static PrintStream INGORED() {
return new PrintStream(new OutputStream() {
@Override
public void write(final int b) throws IOException {
}
});
}
// @Test
public void progress2() throws Exception {
run(() -> true,
new Line("seven", 7),
new Line("one", 1),
new Line("eleven", 11),
new Line("five", 5),
new Line("three", 3)
);
}
public interface Sortable<T> extends Comparable<T> {
String get();
String last();
}
public static class SortableAdapter implements Comparable<SortableAdapter> {
private String last;
private final SynchronizedDescriptiveStatistics time = new SynchronizedDescriptiveStatistics(10);
private Supplier<String> supplier;
public SortableAdapter(final Supplier<String> supplier) {
this.supplier = supplier;
}
public String get() {
final long start = System.currentTimeMillis();
try {
return last = supplier.get();
} finally {
final long elapsed = System.currentTimeMillis() - start;
time.addValue(elapsed);
}
}
public String last() {
return last;
}
@Override
public int compareTo(final SortableAdapter that) {
final Double a = this.time.getPercentile(90);
final Double b = that.time.getPercentile(90);
return a.compareTo(b);
}
}
private static void run(final Supplier<Boolean> proceed, Supplier<String>... items) {
run(proceed, Arrays.asList(items));
}
private static void run(final Supplier<Boolean> proceed, final List<Supplier<String>> items) {
final List<Sortable> sortables = items.stream()
.map(SortableAdapter::new)
.map(Sortable.class::cast)
.collect(Collectors.toList());
runAndSort(proceed, sortables);
}
private static void runAndSort(final Supplier<Boolean> proceed, final List<Sortable> list) {
final List<Sortable> items = new ArrayList<>(list);
for (final Sortable item : items) System.out.println();
long lastSort = System.currentTimeMillis();
while (proceed.get()) {
final long start = System.currentTimeMillis();
System.out.print(Ansi.cursorUp(items.size() + 1));
for (final Sortable item : items) {
System.out.print("\r");
System.out.print(Ansi.cursorDown());
final String s = item.get();
System.out.print(Ansi.eraseLine());
System.out.print(s);
}
System.out.print(Ansi.cursorDown());
System.out.printf("\r");
final long elapsed = System.currentTimeMillis() - start;
if (elapsed < 500) {
try {
Thread.sleep(500 - elapsed);
} catch (InterruptedException e) {
e.printStackTrace();
Thread.interrupted();
}
}
final long due = System.currentTimeMillis() - lastSort;
if (due > TimeUnit.SECONDS.toMillis(10)) {
lastSort = System.currentTimeMillis();
Collections.sort(items);
System.out.print(Ansi.cursorUp(items.size() + 1));
for (final Sortable item : items) {
System.out.print("\r");
System.out.print(Ansi.cursorDown());
final String s = item.last();
System.out.print(Ansi.eraseLine());
System.out.print(s);
}
System.out.print(Ansi.cursorDown());
System.out.printf("\r");
}
}
}
// @Test
public void get() throws Exception {
getCachedTomeeTarGzs()
.stream()
.map(this::getDownloaded)
.map(File::getAbsolutePath)
.forEach(System.out::println);
}
private List<URI> getCachedTomeeTarGzs() {
final File index = new File(downloads, "index.txt");
if (index.exists()) {
return Stream.of(slurp(index).split("\n"))
.map(URI::create)
.collect(Collectors.toList());
}
final List<URI> uris = getAllTomeeTarGzs();
try {
IO.copy(IO.read(Join.join("\n", uris)), index);
} catch (IOException e) {
throw new IllegalStateException(e);
}
return uris;
}
private File getDownloaded(final URI uri) {
final File file = getFile(uri);
if (file.exists()) return file;
return download(uri);
}
private File download(final URI uri) {
final WebClient client = WebClient.create(uri.toASCIIString());
final Response response = client.get();
assertEquals(200, response.getStatus());
final InputStream entity = (InputStream) response.getEntity();
final BufferedInputStream buffer = new BufferedInputStream(entity);
Files.mkdir(downloads);
final File file = getFile(uri);
System.out.printf("Downloading: %s%n", file.getAbsolutePath());
try {
IO.copy(buffer, file);
} catch (IOException e) {
throw new RuntimeException(e);
}
return file;
}
private File getFile(final URI uri) {
return new File(downloads, new File(uri.getPath()).getName());
}
private List<URI> getAllTomeeTarGzs() {
final URI uri = URI.create("http://archive.apache.org/dist/");
return (List<URI>) Stream.of("openejb/", "tomee/")
.map(uri::resolve)
.map(this::getVersions)
.flatMap(Collection::stream)
.map(this::getTarGzs)
.flatMap(Collection::stream)
.collect(Collectors.toList());
}
private String slurp(final File index) {
try {
return IO.slurp(index);
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
private List<URI> getVersions(final URI uri) {
final WebClient client = WebClient.create(uri.toASCIIString());
final String html = client.get(String.class);
return (List<URI>) Stream.of(html.split("\n"))
.filter(s -> s.contains("alt=\"[DIR]\""))
.map(s -> s.replaceAll(".*a href=\"([^\"]+)\".*", "$1"))
.map(uri::resolve)
.collect(Collectors.toList());
}
private List<URI> getTarGzs(final URI uri) {
final WebClient client = WebClient.create(uri.toASCIIString());
final String html = client.get(String.class);
return (List<URI>) Stream.of(html.split("[<>]"))
.filter(s -> s.contains("tar.gz\""))
.filter(s -> s.contains("apache-tomee"))
.map(s -> s.replace("a href=\"", ""))
.map(s -> s.replace("\"", ""))
.map(uri::resolve)
.collect(Collectors.toList());
}
private static class Line implements Supplier<String> {
private final String prefix;
private final int mod;
private int i;
public Line(final String prefix, final int mod) {
this.prefix = prefix;
this.mod = mod;
}
@Override
public String get() {
try {
Thread.sleep(10 * mod);
} catch (InterruptedException e) {
Thread.interrupted();
}
i += mod;
return prefix + " " + i;
}
}
}