diff options
author | yuryalekseev <yuryalekseev@yandex-team.com> | 2024-04-28 09:30:35 +0300 |
---|---|---|
committer | yuryalekseev <yuryalekseev@yandex-team.com> | 2024-04-28 09:56:14 +0300 |
commit | f5c2f57f16eea2ec7ec33130b725dbe9a392fa26 (patch) | |
tree | eaa7440fd23c4e74fc0bb407a3e02d1966353da6 | |
parent | cb84e961773c15774ce94d1df9ef2fc260c82775 (diff) | |
download | ydb-f5c2f57f16eea2ec7ec33130b725dbe9a392fa26.tar.gz |
YT-21657: Read block device stat through /sys/block/$device/stat.
49101c41a066a40c31c7808a34508059403b299d
-rw-r--r-- | yt/yt/core/misc/proc.cpp | 37 | ||||
-rw-r--r-- | yt/yt/core/misc/proc.h | 29 | ||||
-rw-r--r-- | yt/yt/core/misc/unittests/proc_ut.cpp | 30 |
3 files changed, 96 insertions, 0 deletions
diff --git a/yt/yt/core/misc/proc.cpp b/yt/yt/core/misc/proc.cpp index e757d73ffd..2518ad1699 100644 --- a/yt/yt/core/misc/proc.cpp +++ b/yt/yt/core/misc/proc.cpp @@ -1529,6 +1529,43 @@ THashMap<TString, TDiskStat> GetDiskStats() #endif } +TBlockDeviceStat ParseBlockDeviceStat(const TString& statLine) +{ + auto buffer = SplitString(statLine, " "); + TBlockDeviceStat result; + TryParseField(buffer, 0, result.ReadsCompleted); + TryParseField(buffer, 1, result.ReadsMerged); + TryParseField(buffer, 2, result.SectorsRead); + TryParseField(buffer, 3, result.TimeSpentReading); + TryParseField(buffer, 4, result.WritesCompleted); + TryParseField(buffer, 5, result.WritesMerged); + TryParseField(buffer, 6, result.SectorsWritten); + TryParseField(buffer, 7, result.TimeSpentWriting); + TryParseField(buffer, 8, result.IOCurrentlyInProgress); + TryParseField(buffer, 9, result.TimeSpentDoingIO); + TryParseField(buffer, 10, result.WeightedTimeSpentDoingIO); + TryParseField(buffer, 11, result.DiscardsCompleted); + TryParseField(buffer, 12, result.DiscardsMerged); + TryParseField(buffer, 13, result.SectorsDiscarded); + TryParseField(buffer, 14, result.TimeSpentDiscarding); + TryParseField(buffer, 15, result.FlushesCompleted); + TryParseField(buffer, 16, result.TimeSpentFlushing); + return result; +} + +std::optional<TBlockDeviceStat> GetBlockDeviceStat(const TString& deviceName) +{ +#ifdef _linux_ + const TString path = Format("/sys/block/%v/stat", deviceName); + TFileInput diskStatsFile(path); + auto data = diskStatsFile.ReadAll(); + return ParseBlockDeviceStat(Strip(data)); +#else + Y_UNUSED(deviceName); + return std::nullopt; +#endif +} + std::vector<TString> ListDisks() { #ifdef _linux_ diff --git a/yt/yt/core/misc/proc.h b/yt/yt/core/misc/proc.h index 1248d66a5c..7eafd72113 100644 --- a/yt/yt/core/misc/proc.h +++ b/yt/yt/core/misc/proc.h @@ -343,8 +343,37 @@ struct TDiskStat TDiskStat ParseDiskStat(const TString& statLine); +// See https://docs.kernel.org/block/stat.html for more info. +struct TBlockDeviceStat +{ + i64 ReadsCompleted = 0; + i64 ReadsMerged = 0; + i64 SectorsRead = 0; + TDuration TimeSpentReading; + + i64 WritesCompleted = 0; + i64 WritesMerged = 0; + i64 SectorsWritten = 0; + TDuration TimeSpentWriting; + + i64 IOCurrentlyInProgress = 0; + TDuration TimeSpentDoingIO; + TDuration WeightedTimeSpentDoingIO; + + i64 DiscardsCompleted = 0; + i64 DiscardsMerged = 0; + i64 SectorsDiscarded = 0; + TDuration TimeSpentDiscarding; + + i64 FlushesCompleted = 0; + TDuration TimeSpentFlushing; +}; + +TBlockDeviceStat ParseBlockDeviceStat(const TString& statLine); + //! DeviceName to stat info THashMap<TString, TDiskStat> GetDiskStats(); +std::optional<TBlockDeviceStat> GetBlockDeviceStat(const TString& deviceName); std::vector<TString> ListDisks(); //////////////////////////////////////////////////////////////////////////////// diff --git a/yt/yt/core/misc/unittests/proc_ut.cpp b/yt/yt/core/misc/unittests/proc_ut.cpp index f18e462aef..ed8bca5cb5 100644 --- a/yt/yt/core/misc/unittests/proc_ut.cpp +++ b/yt/yt/core/misc/unittests/proc_ut.cpp @@ -165,6 +165,36 @@ TEST(TProcTest, DiskStat) } } +TEST(TProcTest, BlockDeviceStat) +{ + { + auto stat = ParseBlockDeviceStat("509883438 87421933 206345875260 1643399993 1892382802 4495364138 837307482336 2391271400 0 2964131914 3304110410 0 0 0 0 81921472 3564406312"); + EXPECT_EQ(stat.ReadsCompleted, 509883438ll); + EXPECT_EQ(stat.ReadsMerged, 87421933ll); + EXPECT_EQ(stat.SectorsRead, 206345875260ll); + EXPECT_EQ(stat.TimeSpentReading, TDuration::MilliSeconds(1643399993ul)); + EXPECT_EQ(stat.WritesCompleted, 1892382802ll); + EXPECT_EQ(stat.WritesMerged, 4495364138ll); + EXPECT_EQ(stat.SectorsWritten, 837307482336ll); + EXPECT_EQ(stat.TimeSpentWriting, TDuration::MilliSeconds(2391271400ul)); + EXPECT_EQ(stat.IOCurrentlyInProgress, 0ll); + EXPECT_EQ(stat.TimeSpentDoingIO, TDuration::MilliSeconds(2964131914ul)); + EXPECT_EQ(stat.WeightedTimeSpentDoingIO, TDuration::MilliSeconds(3304110410ul)); + EXPECT_EQ(stat.DiscardsCompleted, 0ll); + EXPECT_EQ(stat.DiscardsMerged, 0ll); + EXPECT_EQ(stat.SectorsDiscarded, 0ll); + EXPECT_EQ(stat.TimeSpentDiscarding, TDuration::MilliSeconds(0ul)); + EXPECT_EQ(stat.FlushesCompleted, 81921472ll); + EXPECT_EQ(stat.TimeSpentFlushing, TDuration::MilliSeconds(3564406312ul)); + } + { + for (const TString& disk : ListDisks()) { + auto stat = GetBlockDeviceStat(disk); + EXPECT_TRUE(stat); + } + } +} + TEST(TProcTest, FileDescriptorCount) { auto initialCount = GetFileDescriptorCount(); |