Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2019 Google LLC
*
* Licensed 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 io.perfmark.tracewriter;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonIOException;
import com.google.gson.annotations.SerializedName;
import io.perfmark.impl.Mark;
import io.perfmark.impl.MarkList;
import io.perfmark.impl.Storage;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.lang.management.ManagementFactory;
import java.lang.reflect.Method;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Deque;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.GZIPOutputStream;
/**
* Writes the PerfMark results to a "Trace Event" JSON file usable by the Chromium Profiler
* "Catapult". The format is defined at
* https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview
*
*
This code is NOT API stable, and may be removed in the future, or changed
* without notice.
*
* @since 0.16.0
*/
public final class TraceEventWriter {
private static final Logger logger = Logger.getLogger(TraceEventWriter.class.getName());
/**
* Writes trace events the home directory. By default, it prefers the location in {@code
* $XDG_DATA_HOME/perfmark} environment variable. If unset, it attempts to use {@code
* $HOME/.local/share/perfmark}.
*
*
Authors note: if you are on Windows, or the above defaults aren't right, I'm not really sure
* where else is a good place to put this data. Please file an issue at https://www.perfmark.io/
* if you have a preference.
*
*
Updated in 0.17.0 to return the created path.
*
* @throws IOException if there is an error writing to the file.
* @return the path used to create the trace file.
*/
@CanIgnoreReturnValue
public static Path writeTraceEvents() throws IOException {
Path p = pickNextDest(guessDirectory());
try (OutputStream os = Files.newOutputStream(p);
OutputStream gzos = new GZIPOutputStream(os);
Writer osw = new OutputStreamWriter(gzos, UTF_8)) {
writeTraceEvents(osw);
}
logger.info("Wrote trace to " + p);
return p;
}
/**
* Writes all trace events in in JSON format to the given destination.
*
* @param destination the destination for the JSON data.
* @throws IOException if there are errors build the JSON, or can't write to the destination.
*/
public static void writeTraceEvents(Writer destination) throws IOException {
writeTraceEvents(
destination, Storage.read(), Storage.getInitNanoTime(), System.nanoTime(), getPid());
}
/**
* Writes the trace events gathered from {@link Storage#read()}. This method is not API stable. It
* will be eventually.
*
* @param destination the destination for the JSON data.
* @param markLists the data to use to build the trace event JSON
* @param initNanoTime the time PerfMark classes were first loaded as specified by {@link
* System#nanoTime()}
* @param nowNanoTime the current time as specified by {@link System#nanoTime()}.
* @param pid the PID of the current process.
* @throws IOException if there are errors build the JSON, or can't write to the destination.
*/
public static void writeTraceEvents(
Writer destination,
List extends MarkList> markLists,
long initNanoTime,
long nowNanoTime,
long pid)
throws IOException {
List traceEvents = new ArrayList<>();
new TraceEventWalker(traceEvents, pid, initNanoTime).walk(markLists, nowNanoTime);
Gson gson = new GsonBuilder().setPrettyPrinting().create();
try {
gson.toJson(new TraceEventObject(traceEvents), destination);
} catch (JsonIOException e) {
throw new IOException(e);
}
}
private static Path pickNextDest(Path dir) throws IOException {
String fmt = "perfmark-trace-%03d.json.gz";
int lo;
int hi = 0;
while (true) {
Path candidate = dir.resolve(String.format(fmt, hi));
if (!Files.exists(candidate)) {
lo = hi >>> 1;
break;
}
if (hi == 0) {
hi++;
} else if (hi >>> 1 >= Integer.MAX_VALUE) {
throw new IOException("too many files in dir");
} else {
hi <<= 1;
}
}
// After this point, hi must always point to a non-existent file.
while (hi > lo) {
int mid = (hi + lo) >>> 1; // take THAT, overflow!
Path candidate = dir.resolve(String.format(fmt, mid));
if (Files.exists(candidate)) {
lo = mid + 1;
} else {
hi = mid;
}
}
return dir.resolve(String.format(fmt, hi));
}
private static Path guessDirectory() throws IOException {
final String PERFMARK_TRACE_DIR = "perfmark";
final String sep = File.separator;
List dataHomeChoices = new ArrayList<>();
String dataHome = System.getenv("XDG_DATA_HOME");
if (dataHome != null) {
dataHomeChoices.add(new File(dataHome + sep + PERFMARK_TRACE_DIR).toPath());
}
String home = System.getProperty("user.home");
if (home != null) {
dataHomeChoices.add(
new File(home + sep + ".local" + sep + "share" + sep + PERFMARK_TRACE_DIR).toPath());
}
for (Path path : dataHomeChoices) {
if (!Files.exists(path)) {
Files.createDirectories(path);
} else {
if (!Files.isDirectory(path)) {
continue;
}
}
return path;
}
return new File(".").toPath();
}
static final class TraceEventObject {
@SerializedName("traceEvents")
@SuppressWarnings("unused")
final List traceEvents;
@SerializedName("displayTimeUnit")
@SuppressWarnings("unused")
final String displayTimeUnit = "ns";
@SerializedName("systemTraceEvents")
@SuppressWarnings("unused")
final String systemTraceData = "";
@SerializedName("samples")
@SuppressWarnings("unused")
final List