Search in sources :

Example 1 with QueryExecution

use of com.facebook.presto.execution.QueryExecution in project presto by prestodb.

the class ClusterMemoryManager method process.

public synchronized void process(Iterable<QueryExecution> queries) {
    if (!enabled) {
        return;
    }
    boolean outOfMemory = isClusterOutOfMemory();
    if (!outOfMemory) {
        lastTimeNotOutOfMemory = System.nanoTime();
    }
    boolean queryKilled = false;
    long totalBytes = 0;
    for (QueryExecution query : queries) {
        long bytes = query.getTotalMemoryReservation();
        DataSize sessionMaxQueryMemory = getQueryMaxMemory(query.getSession());
        long queryMemoryLimit = Math.min(maxQueryMemory.toBytes(), sessionMaxQueryMemory.toBytes());
        totalBytes += bytes;
        if (resourceOvercommit(query.getSession()) && outOfMemory) {
            // If a query has requested resource overcommit, only kill it if the cluster has run out of memory
            DataSize memory = succinctBytes(bytes);
            query.fail(new PrestoException(CLUSTER_OUT_OF_MEMORY, format("The cluster is out of memory and %s=true, so this query was killed. It was using %s of memory", RESOURCE_OVERCOMMIT, memory)));
            queryKilled = true;
        }
        if (!resourceOvercommit(query.getSession()) && bytes > queryMemoryLimit) {
            DataSize maxMemory = succinctBytes(queryMemoryLimit);
            query.fail(exceededGlobalLimit(maxMemory));
            queryKilled = true;
        }
    }
    clusterMemoryUsageBytes.set(totalBytes);
    if (killOnOutOfMemory) {
        boolean shouldKillQuery = nanosSince(lastTimeNotOutOfMemory).compareTo(killOnOutOfMemoryDelay) > 0 && outOfMemory;
        boolean lastKilledQueryIsGone = (lastKilledQuery == null);
        if (!lastKilledQueryIsGone) {
            ClusterMemoryPool generalPool = pools.get(GENERAL_POOL);
            if (generalPool != null) {
                lastKilledQueryIsGone = generalPool.getQueryMemoryReservations().containsKey(lastKilledQuery);
            }
        }
        if (shouldKillQuery && lastKilledQueryIsGone && !queryKilled) {
            // Kill the biggest query in the general pool
            QueryExecution biggestQuery = null;
            long maxMemory = -1;
            for (QueryExecution query : queries) {
                long bytesUsed = query.getTotalMemoryReservation();
                if (bytesUsed > maxMemory && query.getMemoryPool().getId().equals(GENERAL_POOL)) {
                    biggestQuery = query;
                    maxMemory = bytesUsed;
                }
            }
            if (biggestQuery != null) {
                biggestQuery.fail(new PrestoException(CLUSTER_OUT_OF_MEMORY, "The cluster is out of memory, and your query was killed. Please try again in a few minutes."));
                queriesKilledDueToOutOfMemory.incrementAndGet();
                lastKilledQuery = biggestQuery.getQueryId();
            }
        }
    }
    Map<MemoryPoolId, Integer> countByPool = new HashMap<>();
    for (QueryExecution query : queries) {
        MemoryPoolId id = query.getMemoryPool().getId();
        countByPool.put(id, countByPool.getOrDefault(id, 0) + 1);
    }
    updatePools(countByPool);
    updateNodes(updateAssignments(queries));
    // check if CPU usage is over limit
    for (QueryExecution query : queries) {
        Duration cpuTime = query.getTotalCpuTime();
        Duration sessionLimit = getQueryMaxCpuTime(query.getSession());
        Duration limit = maxQueryCpuTime.compareTo(sessionLimit) < 0 ? maxQueryCpuTime : sessionLimit;
        if (cpuTime.compareTo(limit) > 0) {
            query.fail(new ExceededCpuLimitException(limit));
        }
    }
}
Also used : HashMap(java.util.HashMap) DataSize(io.airlift.units.DataSize) PrestoException(com.facebook.presto.spi.PrestoException) Duration(io.airlift.units.Duration) ExceededCpuLimitException(com.facebook.presto.ExceededCpuLimitException) QueryExecution(com.facebook.presto.execution.QueryExecution) MemoryPoolId(com.facebook.presto.spi.memory.MemoryPoolId)

Example 2 with QueryExecution

use of com.facebook.presto.execution.QueryExecution in project presto by prestodb.

the class ClusterMemoryManager method process.

public synchronized void process(Iterable<QueryExecution> runningQueries, Supplier<List<BasicQueryInfo>> allQueryInfoSupplier) {
    if (!enabled) {
        return;
    }
    // TODO revocable memory reservations can also leak and may need to be detected in the future
    // We are only concerned about the leaks in general pool.
    memoryLeakDetector.checkForMemoryLeaks(allQueryInfoSupplier, pools.get(GENERAL_POOL).getQueryMemoryReservations());
    boolean outOfMemory = isClusterOutOfMemory();
    if (!outOfMemory) {
        lastTimeNotOutOfMemory = System.nanoTime();
    }
    boolean queryKilled = false;
    long totalUserMemoryBytes = 0L;
    long totalMemoryBytes = 0L;
    for (QueryExecution query : runningQueries) {
        boolean resourceOvercommit = resourceOvercommit(query.getSession());
        long userMemoryReservation = query.getUserMemoryReservation().toBytes();
        long totalMemoryReservation = query.getTotalMemoryReservation().toBytes();
        if (resourceOvercommit && outOfMemory) {
            // If a query has requested resource overcommit, only kill it if the cluster has run out of memory
            DataSize memory = succinctBytes(getQueryMemoryReservation(query));
            query.fail(new PrestoException(CLUSTER_OUT_OF_MEMORY, format("The cluster is out of memory and %s=true, so this query was killed. It was using %s of memory", RESOURCE_OVERCOMMIT, memory)));
            queryKilled = true;
        }
        if (!resourceOvercommit) {
            long userMemoryLimit = min(maxQueryMemory.toBytes(), getQueryMaxMemory(query.getSession()).toBytes());
            if (userMemoryReservation > userMemoryLimit) {
                query.fail(exceededGlobalUserLimit(succinctBytes(userMemoryLimit)));
                queryKilled = true;
            }
            QueryLimit<DataSize> queryTotalMemoryLimit = getMinimum(createDataSizeLimit(maxQueryTotalMemory, SYSTEM), query.getResourceGroupQueryLimits().flatMap(ResourceGroupQueryLimits::getTotalMemoryLimit).map(rgLimit -> createDataSizeLimit(rgLimit, RESOURCE_GROUP)).orElse(null), createDataSizeLimit(getQueryMaxTotalMemory(query.getSession()), QUERY));
            if (totalMemoryReservation > queryTotalMemoryLimit.getLimit().toBytes()) {
                query.fail(exceededGlobalTotalLimit(queryTotalMemoryLimit.getLimit(), queryTotalMemoryLimit.getLimitSource().name()));
                queryKilled = true;
            }
        }
        totalUserMemoryBytes += userMemoryReservation;
        totalMemoryBytes += totalMemoryReservation;
    }
    clusterUserMemoryReservation.set(totalUserMemoryBytes);
    clusterTotalMemoryReservation.set(totalMemoryBytes);
    boolean killOnOomDelayPassed = nanosSince(lastTimeNotOutOfMemory).compareTo(killOnOutOfMemoryDelay) > 0;
    boolean lastKilledQueryGone = isLastKilledQueryGone();
    boolean shouldCallOomKiller = !(lowMemoryKiller instanceof NoneLowMemoryKiller) && outOfMemory && !queryKilled && killOnOomDelayPassed && lastKilledQueryGone;
    if (shouldCallOomKiller) {
        callOomKiller(runningQueries);
    } else {
        // if the cluster is out of memory and we didn't trigger the oom killer we log the state to make debugging easier
        if (outOfMemory) {
            log.debug("The cluster is out of memory and the OOM killer is not called (query killed: %s, kill on OOM delay passed: %s, last killed query gone: %s).", queryKilled, killOnOomDelayPassed, lastKilledQueryGone);
        }
    }
    Map<MemoryPoolId, Integer> countByPool = new HashMap<>();
    for (QueryExecution query : runningQueries) {
        MemoryPoolId id = query.getMemoryPool().getId();
        countByPool.put(id, countByPool.getOrDefault(id, 0) + 1);
    }
    updatePools(countByPool);
    MemoryPoolAssignmentsRequest assignmentsRequest;
    if (pools.containsKey(RESERVED_POOL)) {
        assignmentsRequest = updateAssignments(runningQueries);
    } else {
        // If reserved pool is not enabled, we don't create a MemoryPoolAssignmentsRequest that puts all the queries
        // in the general pool (as they already are). In this case we create an effectively NOOP MemoryPoolAssignmentsRequest.
        // Once the reserved pool is removed we should get rid of the logic of putting queries into reserved pool including
        // this piece of code.
        assignmentsRequest = new MemoryPoolAssignmentsRequest(coordinatorId, Long.MIN_VALUE, ImmutableList.of());
    }
    updateNodes(assignmentsRequest);
}
Also used : HashMap(java.util.HashMap) DataSize(io.airlift.units.DataSize) PrestoException(com.facebook.presto.spi.PrestoException) QueryExecution(com.facebook.presto.execution.QueryExecution) MemoryPoolId(com.facebook.presto.spi.memory.MemoryPoolId)

Example 3 with QueryExecution

use of com.facebook.presto.execution.QueryExecution in project presto by prestodb.

the class ClusterMemoryManager method findLargestMemoryQuery.

private QueryExecution findLargestMemoryQuery(ClusterMemoryPoolInfo generalPool, Iterable<QueryExecution> queries) {
    QueryExecution biggestQuery = null;
    long maxMemory = -1;
    Optional<QueryId> largestMemoryQuery = generalPool.getLargestMemoryQuery();
    // If present, this means the resource manager is determining the largest query, so do not make this determination locally
    if (memoryManagerService.isPresent()) {
        return largestMemoryQuery.flatMap(largestMemoryQueryId -> Streams.stream(queries).filter(query -> query.getQueryId().equals(largestMemoryQueryId)).findFirst()).orElse(null);
    }
    for (QueryExecution queryExecution : queries) {
        if (resourceOvercommit(queryExecution.getSession())) {
            // since their memory usage is unbounded.
            continue;
        }
        long bytesUsed = getQueryMemoryReservation(queryExecution);
        if (bytesUsed > maxMemory) {
            biggestQuery = queryExecution;
            maxMemory = bytesUsed;
        }
    }
    return biggestQuery;
}
Also used : JsonCodec(com.facebook.airlift.json.JsonCodec) SYSTEM(com.facebook.presto.execution.QueryLimit.Source.SYSTEM) QUERY(com.facebook.presto.execution.QueryLimit.Source.QUERY) Duration(io.airlift.units.Duration) ACTIVE(com.facebook.presto.spi.NodeState.ACTIVE) RESERVED_POOL(com.facebook.presto.memory.LocalMemoryManager.RESERVED_POOL) PreDestroy(javax.annotation.PreDestroy) Sets.difference(com.google.common.collect.Sets.difference) InternalNodeManager(com.facebook.presto.metadata.InternalNodeManager) QueryMemoryInfo(com.facebook.presto.memory.LowMemoryKiller.QueryMemoryInfo) QueryLimit.getMinimum(com.facebook.presto.execution.QueryLimit.getMinimum) Duration.nanosSince(io.airlift.units.Duration.nanosSince) Map(java.util.Map) GENERAL_POOL(com.facebook.presto.memory.LocalMemoryManager.GENERAL_POOL) BasicQueryInfo(com.facebook.presto.server.BasicQueryInfo) ServerConfig(com.facebook.presto.server.ServerConfig) QueryLimit(com.facebook.presto.execution.QueryLimit) ImmutableSet(com.google.common.collect.ImmutableSet) ImmutableMap(com.google.common.collect.ImmutableMap) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) Set(java.util.Set) ExceededMemoryLimitException.exceededGlobalUserLimit(com.facebook.presto.ExceededMemoryLimitException.exceededGlobalUserLimit) Math.min(java.lang.Math.min) Streams(com.google.common.collect.Streams) GuardedBy(javax.annotation.concurrent.GuardedBy) Codec(com.facebook.airlift.json.Codec) Executors(java.util.concurrent.Executors) String.format(java.lang.String.format) QueryIdGenerator(com.facebook.presto.execution.QueryIdGenerator) QueryExecution(com.facebook.presto.execution.QueryExecution) DataSize(io.airlift.units.DataSize) List(java.util.List) Stream(java.util.stream.Stream) Comparator.comparingLong(java.util.Comparator.comparingLong) Entry(java.util.Map.Entry) Optional(java.util.Optional) JmxException(org.weakref.jmx.JmxException) RESOURCE_GROUP(com.facebook.presto.execution.QueryLimit.Source.RESOURCE_GROUP) SystemSessionProperties.resourceOvercommit(com.facebook.presto.SystemSessionProperties.resourceOvercommit) Joiner(com.google.common.base.Joiner) QueryLimit.createDataSizeLimit(com.facebook.presto.execution.QueryLimit.createDataSizeLimit) NodeSchedulerConfig(com.facebook.presto.execution.scheduler.NodeSchedulerConfig) RESOURCE_OVERCOMMIT(com.facebook.presto.SystemSessionProperties.RESOURCE_OVERCOMMIT) Logger(com.facebook.airlift.log.Logger) DataSize.succinctBytes(io.airlift.units.DataSize.succinctBytes) HashMap(java.util.HashMap) PrestoException(com.facebook.presto.spi.PrestoException) CLUSTER_OUT_OF_MEMORY(com.facebook.presto.spi.StandardErrorCode.CLUSTER_OUT_OF_MEMORY) Supplier(java.util.function.Supplier) ArrayList(java.util.ArrayList) Inject(javax.inject.Inject) HashSet(java.util.HashSet) ResourceGroupQueryLimits(com.facebook.presto.spi.resourceGroups.ResourceGroupQueryLimits) SystemSessionProperties.getQueryMaxTotalMemory(com.facebook.presto.SystemSessionProperties.getQueryMaxTotalMemory) ImmutableList(com.google.common.collect.ImmutableList) Managed(org.weakref.jmx.Managed) Closer(com.google.common.io.Closer) Verify.verify(com.google.common.base.Verify.verify) SmileCodec(com.facebook.airlift.json.smile.SmileCodec) Objects.requireNonNull(java.util.Objects.requireNonNull) MemoryPoolInfo(com.facebook.presto.spi.memory.MemoryPoolInfo) SystemSessionProperties.getQueryMaxMemory(com.facebook.presto.SystemSessionProperties.getQueryMaxMemory) ImmutableSet.toImmutableSet(com.google.common.collect.ImmutableSet.toImmutableSet) SimpleEntry(java.util.AbstractMap.SimpleEntry) ExecutorService(java.util.concurrent.ExecutorService) MoreCollectors.toOptional(com.google.common.collect.MoreCollectors.toOptional) ClusterMemoryPoolManager(com.facebook.presto.spi.memory.ClusterMemoryPoolManager) ObjectNames.generatedNameOf(org.weakref.jmx.ObjectNames.generatedNameOf) SHUTTING_DOWN(com.facebook.presto.spi.NodeState.SHUTTING_DOWN) InternalCommunicationConfig(com.facebook.presto.server.InternalCommunicationConfig) IOException(java.io.IOException) LocationFactory(com.facebook.presto.execution.LocationFactory) HttpClient(com.facebook.airlift.http.client.HttpClient) ExceededMemoryLimitException.exceededGlobalTotalLimit(com.facebook.presto.ExceededMemoryLimitException.exceededGlobalTotalLimit) InternalNode(com.facebook.presto.metadata.InternalNode) Consumer(java.util.function.Consumer) MemoryPoolId(com.facebook.presto.spi.memory.MemoryPoolId) AtomicLong(java.util.concurrent.atomic.AtomicLong) ClusterMemoryPoolInfo(com.facebook.presto.spi.memory.ClusterMemoryPoolInfo) QueryId(com.facebook.presto.spi.QueryId) VisibleForTesting(com.google.common.annotations.VisibleForTesting) MBeanExporter(org.weakref.jmx.MBeanExporter) Comparator(java.util.Comparator) ClusterMemoryManagerService(com.facebook.presto.resourcemanager.ClusterMemoryManagerService) QueryId(com.facebook.presto.spi.QueryId) QueryExecution(com.facebook.presto.execution.QueryExecution)

Example 4 with QueryExecution

use of com.facebook.presto.execution.QueryExecution in project presto by prestodb.

the class ClusterMemoryManager method updateAssignments.

// TODO once the reserved pool is removed we can remove this method. We can also update
// RemoteNodeMemory as we don't need to POST anything.
private synchronized MemoryPoolAssignmentsRequest updateAssignments(Iterable<QueryExecution> queries) {
    ClusterMemoryPoolInfo reservedPool = getClusterInfo(RESERVED_POOL);
    ClusterMemoryPoolInfo generalPool = getClusterInfo(GENERAL_POOL);
    verify(generalPool != null, "generalPool is null");
    verify(reservedPool != null, "reservedPool is null");
    long version = memoryPoolAssignmentsVersion.incrementAndGet();
    // and is more of a safety check than a guarantee
    if (allAssignmentsHavePropagated(queries)) {
        if (reservedPool.getAssignedQueries() == 0 && generalPool.getBlockedNodes() > 0) {
            QueryExecution biggestQuery = findLargestMemoryQuery(generalPool, queries);
            if (biggestQuery != null) {
                log.info("Moving query %s to the reserved pool", biggestQuery.getQueryId());
                biggestQuery.setMemoryPool(new VersionedMemoryPoolId(RESERVED_POOL, version));
            }
        }
    }
    ImmutableList.Builder<MemoryPoolAssignment> assignments = ImmutableList.builder();
    for (QueryExecution queryExecution : queries) {
        assignments.add(new MemoryPoolAssignment(queryExecution.getQueryId(), queryExecution.getMemoryPool().getId()));
    }
    return new MemoryPoolAssignmentsRequest(coordinatorId, version, assignments.build());
}
Also used : ClusterMemoryPoolInfo(com.facebook.presto.spi.memory.ClusterMemoryPoolInfo) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) ImmutableList(com.google.common.collect.ImmutableList) QueryExecution(com.facebook.presto.execution.QueryExecution)

Example 5 with QueryExecution

use of com.facebook.presto.execution.QueryExecution in project presto by prestodb.

the class LocalDispatchQueryFactory method createDispatchQuery.

@Override
public DispatchQuery createDispatchQuery(Session session, String query, PreparedQuery preparedQuery, String slug, int retryCount, ResourceGroupId resourceGroup, Optional<QueryType> queryType, WarningCollector warningCollector, Consumer<DispatchQuery> queryQueuer) {
    QueryStateMachine stateMachine = QueryStateMachine.begin(query, preparedQuery.getPrepareSql(), session, locationFactory.createQueryLocation(session.getQueryId()), resourceGroup, queryType, isTransactionControlStatement(preparedQuery.getStatement()), transactionManager, accessControl, executor, metadata, warningCollector);
    stateMachine.addStateChangeListener(new QueryStateTracingListener(stateMachine.getSession().getTracer().orElse(NoopTracerProvider.NOOP_TRACER)));
    queryMonitor.queryCreatedEvent(stateMachine.getBasicQueryInfo(Optional.empty()));
    ListenableFuture<QueryExecution> queryExecutionFuture = executor.submit(() -> {
        QueryExecutionFactory<?> queryExecutionFactory = executionFactories.get(preparedQuery.getStatement().getClass());
        if (queryExecutionFactory == null) {
            throw new PrestoException(NOT_SUPPORTED, "Unsupported statement type: " + preparedQuery.getStatement().getClass().getSimpleName());
        }
        return queryExecutionFactory.createQueryExecution(preparedQuery, stateMachine, slug, retryCount, warningCollector, queryType);
    });
    return new LocalDispatchQuery(stateMachine, queryMonitor, queryExecutionFuture, clusterSizeMonitor, executor, queryQueuer, queryManager::createQuery, retryCount > 0, queryPrerequisitesManager);
}
Also used : QueryStateMachine(com.facebook.presto.execution.QueryStateMachine) QueryStateTracingListener(com.facebook.presto.tracing.QueryStateTracingListener) PrestoException(com.facebook.presto.spi.PrestoException) QueryExecution(com.facebook.presto.execution.QueryExecution)

Aggregations

QueryExecution (com.facebook.presto.execution.QueryExecution)7 PrestoException (com.facebook.presto.spi.PrestoException)5 MemoryPoolId (com.facebook.presto.spi.memory.MemoryPoolId)4 ClusterMemoryPoolInfo (com.facebook.presto.spi.memory.ClusterMemoryPoolInfo)3 DataSize (io.airlift.units.DataSize)3 HashMap (java.util.HashMap)3 HttpClient (com.facebook.airlift.http.client.HttpClient)2 Codec (com.facebook.airlift.json.Codec)2 JsonCodec (com.facebook.airlift.json.JsonCodec)2 SmileCodec (com.facebook.airlift.json.smile.SmileCodec)2 Logger (com.facebook.airlift.log.Logger)2 ExceededMemoryLimitException.exceededGlobalTotalLimit (com.facebook.presto.ExceededMemoryLimitException.exceededGlobalTotalLimit)2 ExceededMemoryLimitException.exceededGlobalUserLimit (com.facebook.presto.ExceededMemoryLimitException.exceededGlobalUserLimit)2 RESOURCE_OVERCOMMIT (com.facebook.presto.SystemSessionProperties.RESOURCE_OVERCOMMIT)2 SystemSessionProperties.getQueryMaxMemory (com.facebook.presto.SystemSessionProperties.getQueryMaxMemory)2 SystemSessionProperties.getQueryMaxTotalMemory (com.facebook.presto.SystemSessionProperties.getQueryMaxTotalMemory)2 SystemSessionProperties.resourceOvercommit (com.facebook.presto.SystemSessionProperties.resourceOvercommit)2 LocationFactory (com.facebook.presto.execution.LocationFactory)2 QueryIdGenerator (com.facebook.presto.execution.QueryIdGenerator)2 QueryLimit (com.facebook.presto.execution.QueryLimit)2