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.
/*
* 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.trino.execution;
import com.google.common.base.Ticker;
import io.airlift.units.Duration;
import org.joda.time.DateTime;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadMXBean;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;
import static io.airlift.units.Duration.succinctNanos;
import static java.lang.Math.max;
import static java.util.Objects.requireNonNull;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
class QueryStateTimer
{
private static final ThreadMXBean THREAD_MX_BEAN = ManagementFactory.getThreadMXBean();
private final Ticker ticker;
private final DateTime createTime = DateTime.now();
private final long createNanos;
private final AtomicReference beginResourceWaitingNanos = new AtomicReference<>();
private final AtomicReference beginDispatchingNanos = new AtomicReference<>();
private final AtomicReference beginPlanningNanos = new AtomicReference<>();
private final AtomicReference beginPlanningCpuNanos = new AtomicReference<>();
private final AtomicReference beginFinishingNanos = new AtomicReference<>();
private final AtomicReference endNanos = new AtomicReference<>();
private final AtomicReference queuedTime = new AtomicReference<>();
private final AtomicReference resourceWaitingTime = new AtomicReference<>();
private final AtomicReference dispatchingTime = new AtomicReference<>();
private final AtomicReference executionTime = new AtomicReference<>();
private final AtomicReference planningTime = new AtomicReference<>();
private final AtomicReference planningCpuTime = new AtomicReference<>();
private final AtomicReference finishingTime = new AtomicReference<>();
private final AtomicReference beginAnalysisNanos = new AtomicReference<>();
private final AtomicReference analysisTime = new AtomicReference<>();
private final AtomicReference lastHeartbeatNanos;
public QueryStateTimer(Ticker ticker)
{
this.ticker = requireNonNull(ticker, "ticker is null");
this.createNanos = tickerNanos();
this.lastHeartbeatNanos = new AtomicReference<>(createNanos);
}
//
// State transitions
//
public void beginWaitingForResources()
{
beginWaitingForResources(tickerNanos());
}
private void beginWaitingForResources(long now)
{
queuedTime.compareAndSet(null, nanosSince(createNanos, now));
beginResourceWaitingNanos.compareAndSet(null, now);
}
public void beginDispatching()
{
beginDispatching(tickerNanos());
}
private void beginDispatching(long now)
{
beginWaitingForResources(now);
resourceWaitingTime.compareAndSet(null, nanosSince(beginResourceWaitingNanos, now));
beginDispatchingNanos.compareAndSet(null, now);
}
public void beginPlanning()
{
beginPlanning(tickerNanos(), currentThreadCpuTime());
}
private void beginPlanning(long now, long cpuNow)
{
beginDispatching(now);
dispatchingTime.compareAndSet(null, nanosSince(beginDispatchingNanos, now));
beginPlanningNanos.compareAndSet(null, now);
beginPlanningCpuNanos.compareAndSet(null, cpuNow);
}
public void beginStarting()
{
beginStarting(tickerNanos(), currentThreadCpuTime());
}
private void beginStarting(long now, long cpuNow)
{
beginPlanning(now, cpuNow);
planningTime.compareAndSet(null, nanosSince(beginPlanningNanos, now));
planningCpuTime.compareAndSet(null, nanosSince(beginPlanningCpuNanos, cpuNow));
}
public void beginRunning()
{
beginRunning(tickerNanos());
}
private void beginRunning(long now)
{
beginStarting(now, currentThreadCpuTime());
}
public void beginFinishing()
{
beginFinishing(tickerNanos());
}
private void beginFinishing(long now)
{
beginRunning(now);
beginFinishingNanos.compareAndSet(null, now);
}
public void endQuery()
{
endQuery(tickerNanos());
}
private void endQuery(long now)
{
beginFinishing(now);
finishingTime.compareAndSet(null, nanosSince(beginFinishingNanos, now));
executionTime.compareAndSet(null, nanosSince(beginPlanningNanos, now));
endNanos.compareAndSet(null, now);
// Analysis is run in separate thread and there is no query state for analysis.
// In case when analysis thread was canceled the analysis should be marked as finished.
if (beginAnalysisNanos.get() == null) {
analysisTime.compareAndSet(null, succinctNanos(0));
}
else {
endAnalysis(now);
}
}
//
// Additional timings
//
public void beginAnalysis()
{
beginAnalysisNanos.compareAndSet(null, tickerNanos());
}
public void endAnalysis()
{
endAnalysis(tickerNanos());
}
private void endAnalysis(long now)
{
analysisTime.compareAndSet(null, nanosSince(beginAnalysisNanos, now));
}
public void recordHeartbeat()
{
lastHeartbeatNanos.set(tickerNanos());
}
//
// Stats
//
public DateTime getCreateTime()
{
return createTime;
}
public Optional getExecutionStartTime()
{
return toDateTime(beginPlanningNanos);
}
public Optional getPlanningStartTime()
{
return toDateTime(beginPlanningNanos);
}
public Duration getElapsedTime()
{
if (endNanos.get() != null) {
return succinctNanos(endNanos.get() - createNanos);
}
return nanosSince(createNanos, tickerNanos());
}
public Duration getQueuedTime()
{
Duration queuedTime = this.queuedTime.get();
if (queuedTime != null) {
return queuedTime;
}
// if queue time is not set, the query is still queued
return getElapsedTime();
}
public Duration getResourceWaitingTime()
{
return getDuration(resourceWaitingTime, beginResourceWaitingNanos);
}
public Duration getDispatchingTime()
{
return getDuration(dispatchingTime, beginDispatchingNanos);
}
public Duration getPlanningTime()
{
return getDuration(planningTime, beginPlanningNanos);
}
public Duration getPlanningCpuTime()
{
return getDuration(planningCpuTime, beginPlanningCpuNanos);
}
public Duration getFinishingTime()
{
return getDuration(finishingTime, beginFinishingNanos);
}
public Duration getExecutionTime()
{
return getDuration(executionTime, beginPlanningNanos);
}
public Optional getEndTime()
{
return toDateTime(endNanos);
}
public Duration getAnalysisTime()
{
return getDuration(analysisTime, beginAnalysisNanos);
}
public DateTime getLastHeartbeat()
{
return toDateTime(lastHeartbeatNanos.get());
}
//
// Helper methods
//
private long tickerNanos()
{
return ticker.read();
}
private static Duration nanosSince(AtomicReference start, long end)
{
Long startNanos = start.get();
if (startNanos == null) {
throw new IllegalStateException("Start time not set");
}
return nanosSince(startNanos, end);
}
private static Duration nanosSince(long start, long now)
{
return succinctNanos(max(0, now - start));
}
private Duration getDuration(AtomicReference finalDuration, AtomicReference start)
{
Duration duration = finalDuration.get();
if (duration != null) {
return duration;
}
Long startNanos = start.get();
if (startNanos != null) {
return nanosSince(startNanos, tickerNanos());
}
return new Duration(0, MILLISECONDS);
}
private Optional toDateTime(AtomicReference instantNanos)
{
Long nanos = instantNanos.get();
if (nanos == null) {
return Optional.empty();
}
return Optional.of(toDateTime(nanos));
}
private DateTime toDateTime(long instantNanos)
{
long millisSinceCreate = NANOSECONDS.toMillis(instantNanos - createNanos);
return new DateTime(createTime.getMillis() + millisSinceCreate);
}
private static long currentThreadCpuTime()
{
return THREAD_MX_BEAN.getCurrentThreadCpuTime();
}
}