Files
doris/be/src/runtime/task_group/task_group.h

181 lines
5.0 KiB
C++

// 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.
#pragma once
#include <stddef.h>
#include <stdint.h>
#include <atomic>
#include <memory>
#include <queue>
#include <shared_mutex>
#include <string>
#include <unordered_set>
#include "common/status.h"
namespace doris {
class TPipelineWorkloadGroup;
class MemTrackerLimiter;
namespace pipeline {
class PipelineTask;
} // namespace pipeline
namespace taskgroup {
class TaskGroup;
struct TaskGroupInfo;
class ScanTaskQueue;
template <typename QueueType>
class TaskGroupEntity {
public:
explicit TaskGroupEntity(taskgroup::TaskGroup* tg, std::string type);
~TaskGroupEntity();
TaskGroupEntity() = default; // used for empty group entity
uint64_t vruntime_ns() const { return _vruntime_ns; }
QueueType* task_queue();
void incr_runtime_ns(uint64_t runtime_ns);
void adjust_vruntime_ns(uint64_t vruntime_ns);
size_t task_size() const;
uint64_t cpu_share() const;
std::string debug_string() const;
uint64_t task_group_id() const;
void check_and_update_cpu_share(const TaskGroupInfo& tg_info);
void set_empty_group_entity(bool is_empty_group_entity);
bool is_empty_group_entity();
void update_empty_cpu_share(uint64_t empty_cpu_share);
private:
QueueType* _task_queue;
uint64_t _vruntime_ns = 0;
taskgroup::TaskGroup* _tg;
std::string _type;
// Because updating cpu share of entity requires locking the task queue(pipeline task queue or
// scan task queue) contains that entity, we kept version and cpu share in entity for
// independent updates.
int64_t _version;
uint64_t _cpu_share;
bool _is_empty_group_entity = false;
};
// TODO llj tg use PriorityTaskQueue to replace std::queue
using TaskGroupPipelineTaskEntity = TaskGroupEntity<std::queue<pipeline::PipelineTask*>>;
using TGPTEntityPtr = TaskGroupPipelineTaskEntity*;
using TaskGroupScanTaskEntity = TaskGroupEntity<ScanTaskQueue>;
using TGSTEntityPtr = TaskGroupScanTaskEntity*;
struct TgTrackerLimiterGroup {
std::unordered_set<std::shared_ptr<MemTrackerLimiter>> trackers;
std::mutex group_lock;
};
class TaskGroup : public std::enable_shared_from_this<TaskGroup> {
public:
explicit TaskGroup(const TaskGroupInfo& tg_info);
TaskGroupPipelineTaskEntity* task_entity() { return &_task_entity; }
TGSTEntityPtr local_scan_task_entity() { return &_local_scan_entity; }
int64_t version() const { return _version; }
uint64_t cpu_share() const { return _cpu_share.load(); }
uint64_t id() const { return _id; }
std::string name() const { return _name; };
bool enable_memory_overcommit() const {
std::shared_lock<std::shared_mutex> r_lock(_mutex);
return _enable_memory_overcommit;
};
int64_t memory_limit() const {
std::shared_lock<std::shared_mutex> r_lock(_mutex);
return _memory_limit;
};
int64_t memory_used();
std::string debug_string() const;
void check_and_update(const TaskGroupInfo& tg_info);
void add_mem_tracker_limiter(std::shared_ptr<MemTrackerLimiter> mem_tracker_ptr);
void remove_mem_tracker_limiter(std::shared_ptr<MemTrackerLimiter> mem_tracker_ptr);
void task_group_info(TaskGroupInfo* tg_info) const;
std::vector<TgTrackerLimiterGroup>& mem_tracker_limiter_pool() {
return _mem_tracker_limiter_pool;
}
private:
mutable std::shared_mutex _mutex; // lock _name, _version, _cpu_share, _memory_limit
const uint64_t _id;
std::string _name;
int64_t _version;
int64_t _memory_limit; // bytes
bool _enable_memory_overcommit;
std::atomic<uint64_t> _cpu_share;
TaskGroupPipelineTaskEntity _task_entity;
TaskGroupScanTaskEntity _local_scan_entity;
std::vector<TgTrackerLimiterGroup> _mem_tracker_limiter_pool;
};
using TaskGroupPtr = std::shared_ptr<TaskGroup>;
struct TaskGroupInfo {
uint64_t id;
std::string name;
uint64_t cpu_share;
int64_t memory_limit;
bool enable_memory_overcommit;
int64_t version;
static Status parse_group_info(const TPipelineWorkloadGroup& resource_group,
TaskGroupInfo* task_group_info, int* query_cpu_hard_limit);
private:
static bool check_group_info(const TPipelineWorkloadGroup& resource_group);
};
} // namespace taskgroup
} // namespace doris