| /* |
| * 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; |
| } |
| } |
| } |