//------------------------------------------------------------------------------ // File: MutexLatencyWatcher.cc //------------------------------------------------------------------------------ /************************************************************************ * EOS - the CERN Disk Storage System * * Copyright (C) 2020 CERN/Switzerland * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation, either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see .* ************************************************************************/ #include "common/MutexLatencyWatcher.hh" #include "common/Logging.hh" EOSCOMMONNAMESPACE_BEGIN //------------------------------------------------------------------------------ // Empty constructor //------------------------------------------------------------------------------ MutexLatencyWatcher::MutexLatencyWatcher() { aStart = 0; } //------------------------------------------------------------------------------ // Constructor //------------------------------------------------------------------------------ MutexLatencyWatcher::MutexLatencyWatcher(RWMutex& mutex, const std::string &friendlyName) { activate(mutex, friendlyName); } //------------------------------------------------------------------------------ // Custom "constructor" //------------------------------------------------------------------------------ void MutexLatencyWatcher::activate(RWMutex& mutex, const std::string &friendlyName) { mMutex = &mutex; mFriendlyName = friendlyName; mThread.reset(&MutexLatencyWatcher::main, this); } //------------------------------------------------------------------------------ // Main thread loop //------------------------------------------------------------------------------ void MutexLatencyWatcher::main(ThreadAssistant &assistant) { while(!assistant.terminationRequested()) { Datapoint point; aStart = time(NULL); point.start = std::chrono::system_clock::now(); mMutex->LockWrite(); aStart = 0; mMutex->UnLockWrite(); point.end = std::chrono::system_clock::now(); if(point.getMilli() > std::chrono::milliseconds(200)) { eos_static_warning("acquisition of mutex %s took %d milliseconds", mFriendlyName.c_str(), point.getMilli().count()); } appendDatapoint(point); assistant.wait_for(std::chrono::seconds(2)); } } //------------------------------------------------------------------------------ // Append datapoint //------------------------------------------------------------------------------ void MutexLatencyWatcher::appendDatapoint(const Datapoint &point) { std::lock_guard lock(mDataMutex); mData.push_back(point); if(mData.size() > 200) { mData.pop_front(); } } //------------------------------------------------------------------------------ // Get latency spikes //------------------------------------------------------------------------------ MutexLatencyWatcher::LatencySpikes MutexLatencyWatcher::getLatencySpikes() const { LatencySpikes spikes; std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); std::lock_guard lock(mDataMutex); for(auto it = mData.begin(); it != mData.end(); it++) { if(now - it->end <= std::chrono::minutes(1)) { spikes.lastMinute = std::max(spikes.lastMinute, it->getMilli()); } if(now - it->end <= std::chrono::minutes(2)) { spikes.last2Minutes = std::max(spikes.last2Minutes, it->getMilli()); } if(now - it->end <= std::chrono::minutes(5)) { spikes.last5Minutes = std::max(spikes.last5Minutes, it->getMilli()); } } if(!mData.empty()) { spikes.last = mData.back().getMilli(); } return spikes; } //------------------------------------------------------------------------------ // Append datapoint //------------------------------------------------------------------------------ EOSCOMMONNAMESPACE_END