Home | History | Annotate | Download | only in sys_stats
      1 /*
      2  * Copyright (C) 2018 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <unistd.h>
     18 
     19 #include "gmock/gmock.h"
     20 #include "gtest/gtest.h"
     21 #include "perfetto/base/temp_file.h"
     22 #include "src/base/test/test_task_runner.h"
     23 #include "src/traced/probes/sys_stats/sys_stats_data_source.h"
     24 #include "src/tracing/core/trace_writer_for_testing.h"
     25 
     26 #include "perfetto/config/sys_stats/sys_stats_config.pb.h"
     27 #include "perfetto/trace/trace_packet.pb.h"
     28 #include "perfetto/trace/trace_packet.pbzero.h"
     29 
     30 using ::testing::_;
     31 using ::testing::Invoke;
     32 using ::testing::Return;
     33 using ::testing::UnorderedElementsAre;
     34 
     35 namespace perfetto {
     36 namespace {
     37 
     38 const char kMockMeminfo[] = R"(
     39 MemTotal:        3744240 kB
     40 MemFree:           73328 kB
     41 MemAvailable:     629896 kB
     42 Buffers:           19296 kB
     43 Cached:           731032 kB
     44 SwapCached:         4936 kB
     45 Active:          1616348 kB
     46 Inactive:         745492 kB
     47 Active(anon):    1322636 kB
     48 Inactive(anon):   449172 kB
     49 Active(file):     293712 kB
     50 Inactive(file):   296320 kB
     51 Unevictable:      142152 kB
     52 Mlocked:          142152 kB
     53 SwapTotal:        524284 kB
     54 SwapFree:            128 kB
     55 Dirty:                 0 kB
     56 Writeback:             0 kB
     57 AnonPages:       1751140 kB
     58 Mapped:           508372 kB
     59 Shmem:             18604 kB
     60 Slab:             240352 kB
     61 SReclaimable:      64684 kB
     62 SUnreclaim:       175668 kB
     63 KernelStack:       62672 kB
     64 PageTables:        70108 kB
     65 NFS_Unstable:          0 kB
     66 Bounce:                0 kB
     67 WritebackTmp:          0 kB
     68 CommitLimit:     2396404 kB
     69 Committed_AS:   81911488 kB
     70 VmallocTotal:   258867136 kB
     71 VmallocUsed:           0 kB
     72 VmallocChunk:          0 kB
     73 CmaTotal:         196608 kB
     74 CmaFree:              60 kB)";
     75 
     76 const char kMockVmstat[] = R"(
     77 nr_free_pages 16449
     78 nr_alloc_batch 79
     79 nr_inactive_anon 112545
     80 nr_active_anon 322027
     81 nr_inactive_file 75904
     82 nr_active_file 87939
     83 nr_unevictable 35538
     84 nr_mlock 35538
     85 nr_anon_pages 429005
     86 nr_mapped 125844
     87 nr_file_pages 205523
     88 nr_dirty 23
     89 nr_writeback 0
     90 nr_slab_reclaimable 15840
     91 nr_slab_unreclaimable 43912
     92 nr_page_table_pages 17158
     93 nr_kernel_stack 3822
     94 nr_overhead 0
     95 nr_unstable 0
     96 nr_bounce 0
     97 nr_vmscan_write 558690
     98 nr_vmscan_immediate_reclaim 14853
     99 nr_writeback_temp 0
    100 nr_isolated_anon 0
    101 nr_isolated_file 0
    102 nr_shmem 5027
    103 nr_dirtied 6732417
    104 nr_written 6945513
    105 nr_pages_scanned 0
    106 workingset_refault 32784684
    107 workingset_activate 8200928
    108 workingset_nodereclaim 0
    109 nr_anon_transparent_hugepages 0
    110 nr_free_cma 0
    111 nr_swapcache 1254
    112 nr_dirty_threshold 33922
    113 nr_dirty_background_threshold 8449
    114 pgpgin 161257156
    115 pgpgout 35973852
    116 pgpgoutclean 37181384
    117 pswpin 185308
    118 pswpout 557662
    119 pgalloc_dma 79259070
    120 pgalloc_normal 88265512
    121 pgalloc_movable 0
    122 pgfree 175051592
    123 pgactivate 11897892
    124 pgdeactivate 20412230
    125 pgfault 181696234
    126 pgmajfault 1060871
    127 pgrefill_dma 12970047
    128 pgrefill_normal 14391564
    129 pgrefill_movable 0
    130 pgsteal_kswapd_dma 19471476
    131 pgsteal_kswapd_normal 21138380
    132 pgsteal_kswapd_movable 0
    133 pgsteal_direct_dma 40625
    134 pgsteal_direct_normal 50912
    135 pgsteal_direct_movable 0
    136 pgscan_kswapd_dma 23544417
    137 pgscan_kswapd_normal 25623715
    138 pgscan_kswapd_movable 0
    139 pgscan_direct_dma 50369
    140 pgscan_direct_normal 66284
    141 pgscan_direct_movable 0
    142 pgscan_direct_throttle 0
    143 pginodesteal 0
    144 slabs_scanned 39582828
    145 kswapd_inodesteal 110199
    146 kswapd_low_wmark_hit_quickly 21321
    147 kswapd_high_wmark_hit_quickly 4112
    148 pageoutrun 37666
    149 allocstall 1587
    150 pgrotated 12086
    151 drop_pagecache 0
    152 drop_slab 0
    153 pgmigrate_success 5923482
    154 pgmigrate_fail 3439
    155 compact_migrate_scanned 92906456
    156 compact_free_scanned 467077168
    157 compact_isolated 13456528
    158 compact_stall 197
    159 compact_fail 42
    160 compact_success 155
    161 compact_daemon_wake 2131
    162 unevictable_pgs_culled 50170
    163 unevictable_pgs_scanned 0
    164 unevictable_pgs_rescued 14640
    165 unevictable_pgs_mlocked 52520
    166 unevictable_pgs_munlocked 14640
    167 unevictable_pgs_cleared 2342
    168 unevictable_pgs_stranded 2342)";
    169 
    170 const char kMockStat[] = R"(
    171 cpu  2655987 822682 2352153 8801203 41917 322733 175055 0 0 0
    172 cpu0 762178 198125 902284 8678856 41716 152974 68262 0 0 0
    173 cpu1 613833 243394 504323 15194 96 60625 28785 0 0 0
    174 cpu2 207349 95060 248856 17351 42 32148 26108 0 0 0
    175 cpu3 138474 92158 174852 17537 48 25076 25035 0 0 0
    176 cpu4 278720 34689 141048 18117 1 20782 5873 0 0 0
    177 cpu5 235376 33907 85098 18278 2 10049 3774 0 0 0
    178 cpu6 239568 67149 155814 17890 5 11518 3807 0 0 0
    179 cpu7 180484 58196 139874 17975 3 9556 13407 0 0 0
    180 intr 238128517 0 0 0 63500984 0 6253792 6 4 5 0 0 0 0 0 0 0 160331 0 0 14 0 0 0 0 0 0 0 0 0 0 0 20430 2279 11 11 83272 0 0 0 0 0 0 0 5754 220829 0 154753 908545 1824602 7314228 0 0 0 6898259 0 0 10 0 0 2 0 0 0 0 0 0 0 42 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 575816 1447531 134022 0 0 0 0 0 435008 319921 2755476 0 0 0 0 91 310212 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 4 0 0 545 901 554 9 3377 4184 12 10 588851 0 2 1109045 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 8 0 0 0 0 0 0 0 0 0 0 0 0 497 0 0 0 0 0 26172 0 0 0 0 0 0 0 1362 0 0 0 0 0 0 0 424 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 23427 0 0 0 0 1 1298 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 108 0 0 0 0 86 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1784935 407979 2140 10562241 52374 74699 6976 84926 222 169088 0 0 0 0 174 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2789 51543 0 83 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 0 13 11 17 1393 0 0 0 0 0 0 0 0 0 0 26 0 0 2 106 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 11150 0 13 0 1 390 6 0 6 4 0 0 0 0 352 284743 2 0 0 24 3 0 3 0 0 0 12 0 668788 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 680 0 0
    181 ctxt 373122860
    182 btime 1536912218
    183 processes 243320
    184 procs_running 1
    185 procs_blocked 0
    186 softirq 84611084 10220177 28299167 155083 3035679 6390543 66234 4396819 15604187 0 16443195)";
    187 
    188 base::ScopedFile MockOpenReadOnly(const char* path) {
    189   base::TempFile tmp_ = base::TempFile::CreateUnlinked();
    190   if (!strcmp(path, "/proc/meminfo")) {
    191     EXPECT_GT(pwrite(tmp_.fd(), kMockMeminfo, strlen(kMockMeminfo), 0), 0);
    192   } else if (!strcmp(path, "/proc/vmstat")) {
    193     EXPECT_GT(pwrite(tmp_.fd(), kMockVmstat, strlen(kMockVmstat), 0), 0);
    194   } else if (!strcmp(path, "/proc/stat")) {
    195     EXPECT_GT(pwrite(tmp_.fd(), kMockStat, strlen(kMockStat), 0), 0);
    196   } else {
    197     PERFETTO_FATAL("Unexpected file opened %s", path);
    198   }
    199   return tmp_.ReleaseFD();
    200 }
    201 
    202 class SysStatsDataSourceTest : public ::testing::Test {
    203  protected:
    204   std::unique_ptr<SysStatsDataSource> GetSysStatsDataSource(
    205       const DataSourceConfig& cfg) {
    206     auto writer =
    207         std::unique_ptr<TraceWriterForTesting>(new TraceWriterForTesting());
    208     writer_raw_ = writer.get();
    209     auto instance = std::unique_ptr<SysStatsDataSource>(new SysStatsDataSource(
    210         &task_runner_, 0, std::move(writer), cfg, MockOpenReadOnly));
    211     instance->set_ns_per_user_hz_for_testing(1000000000ull / 100);  // 100 Hz.
    212     instance->Start();
    213     return instance;
    214   }
    215 
    216   void Poller(SysStatsDataSource* ds, std::function<void()> checkpoint) {
    217     if (ds->tick_for_testing())
    218       checkpoint();
    219     else
    220       task_runner_.PostDelayedTask(
    221           [ds, checkpoint, this] { Poller(ds, checkpoint); }, 1);
    222   }
    223 
    224   void WaitTick(SysStatsDataSource* data_source) {
    225     auto checkpoint = task_runner_.CreateCheckpoint("on_tick");
    226     Poller(data_source, checkpoint);
    227     task_runner_.RunUntilCheckpoint("on_tick");
    228   }
    229 
    230   TraceWriterForTesting* writer_raw_ = nullptr;
    231   base::TestTaskRunner task_runner_;
    232 };
    233 
    234 TEST_F(SysStatsDataSourceTest, Meminfo) {
    235   using C = protos::MeminfoCounters;
    236   protos::DataSourceConfig config;
    237   config.mutable_sys_stats_config()->set_meminfo_period_ms(1);
    238   config.mutable_sys_stats_config()->add_meminfo_counters(C::MEMINFO_MEM_TOTAL);
    239   config.mutable_sys_stats_config()->add_meminfo_counters(C::MEMINFO_MEM_FREE);
    240   config.mutable_sys_stats_config()->add_meminfo_counters(
    241       C::MEMINFO_ACTIVE_ANON);
    242   config.mutable_sys_stats_config()->add_meminfo_counters(
    243       C::MEMINFO_INACTIVE_FILE);
    244   config.mutable_sys_stats_config()->add_meminfo_counters(C::MEMINFO_CMA_FREE);
    245   DataSourceConfig config_obj;
    246   config_obj.FromProto(config);
    247   auto data_source = GetSysStatsDataSource(config_obj);
    248 
    249   WaitTick(data_source.get());
    250 
    251   std::unique_ptr<protos::TracePacket> packet = writer_raw_->ParseProto();
    252   ASSERT_TRUE(packet->has_sys_stats());
    253   const auto& sys_stats = packet->sys_stats();
    254   EXPECT_EQ(sys_stats.vmstat_size(), 0);
    255   EXPECT_EQ(sys_stats.cpu_stat_size(), 0);
    256 
    257   using KV = std::pair<int, uint64_t>;
    258   std::vector<KV> kvs;
    259   for (const auto& kv : sys_stats.meminfo())
    260     kvs.push_back({kv.key(), kv.value()});
    261 
    262   EXPECT_THAT(kvs,
    263               UnorderedElementsAre(KV{C::MEMINFO_MEM_TOTAL, 3744240},     //
    264                                    KV{C::MEMINFO_MEM_FREE, 73328},        //
    265                                    KV{C::MEMINFO_ACTIVE_ANON, 1322636},   //
    266                                    KV{C::MEMINFO_INACTIVE_FILE, 296320},  //
    267                                    KV{C::MEMINFO_CMA_FREE, 60}));
    268 }
    269 
    270 TEST_F(SysStatsDataSourceTest, Vmstat) {
    271   using C = protos::VmstatCounters;
    272   protos::DataSourceConfig config;
    273   config.mutable_sys_stats_config()->set_vmstat_period_ms(1);
    274   config.mutable_sys_stats_config()->add_vmstat_counters(
    275       C::VMSTAT_NR_FREE_PAGES);
    276   config.mutable_sys_stats_config()->add_vmstat_counters(C::VMSTAT_PGACTIVATE);
    277   config.mutable_sys_stats_config()->add_vmstat_counters(
    278       C::VMSTAT_PGMIGRATE_FAIL);
    279   DataSourceConfig config_obj;
    280   config_obj.FromProto(config);
    281   auto data_source = GetSysStatsDataSource(config_obj);
    282 
    283   WaitTick(data_source.get());
    284 
    285   std::unique_ptr<protos::TracePacket> packet = writer_raw_->ParseProto();
    286   ASSERT_TRUE(packet->has_sys_stats());
    287   const auto& sys_stats = packet->sys_stats();
    288   EXPECT_EQ(sys_stats.meminfo_size(), 0);
    289   EXPECT_EQ(sys_stats.cpu_stat_size(), 0);
    290 
    291   using KV = std::pair<int, uint64_t>;
    292   std::vector<KV> kvs;
    293   for (const auto& kv : sys_stats.vmstat())
    294     kvs.push_back({kv.key(), kv.value()});
    295 
    296   EXPECT_THAT(kvs, UnorderedElementsAre(KV{C::VMSTAT_NR_FREE_PAGES, 16449},  //
    297                                         KV{C::VMSTAT_PGACTIVATE, 11897892},  //
    298                                         KV{C::VMSTAT_PGMIGRATE_FAIL, 3439}));
    299 }
    300 
    301 TEST_F(SysStatsDataSourceTest, StatAll) {
    302   using C = protos::SysStatsConfig;
    303   protos::DataSourceConfig config;
    304   config.mutable_sys_stats_config()->set_stat_period_ms(1);
    305   config.mutable_sys_stats_config()->add_stat_counters(C::STAT_CPU_TIMES);
    306   config.mutable_sys_stats_config()->add_stat_counters(C::STAT_IRQ_COUNTS);
    307   config.mutable_sys_stats_config()->add_stat_counters(C::STAT_SOFTIRQ_COUNTS);
    308   config.mutable_sys_stats_config()->add_stat_counters(C::STAT_FORK_COUNT);
    309   DataSourceConfig config_obj;
    310   config_obj.FromProto(config);
    311   auto data_source = GetSysStatsDataSource(config_obj);
    312 
    313   WaitTick(data_source.get());
    314 
    315   std::unique_ptr<protos::TracePacket> packet = writer_raw_->ParseProto();
    316   ASSERT_TRUE(packet);
    317   ASSERT_TRUE(packet->has_sys_stats());
    318   const auto& sys_stats = packet->sys_stats();
    319   EXPECT_EQ(sys_stats.meminfo_size(), 0);
    320   EXPECT_EQ(sys_stats.vmstat_size(), 0);
    321 
    322   ASSERT_EQ(sys_stats.cpu_stat_size(), 8);
    323   EXPECT_EQ(sys_stats.cpu_stat(0).user_ns(), 762178 * 10000000ull);
    324   EXPECT_EQ(sys_stats.cpu_stat(0).system_mode_ns(), 902284 * 10000000ull);
    325   EXPECT_EQ(sys_stats.cpu_stat(0).softirq_ns(), 68262 * 10000000ull);
    326   EXPECT_EQ(sys_stats.cpu_stat(7).user_ns(), 180484 * 10000000ull);
    327   EXPECT_EQ(sys_stats.cpu_stat(7).system_mode_ns(), 139874 * 10000000ull);
    328   EXPECT_EQ(sys_stats.cpu_stat(7).softirq_ns(), 13407 * 10000000ull);
    329 
    330   EXPECT_EQ(sys_stats.num_forks(), 243320);
    331 
    332   EXPECT_EQ(sys_stats.num_irq_total(), 238128517);
    333   ASSERT_EQ(sys_stats.num_irq_size(), 793);
    334   EXPECT_EQ(sys_stats.num_irq(0).count(), 0);
    335   EXPECT_EQ(sys_stats.num_irq(3).count(), 63500984);
    336   EXPECT_EQ(sys_stats.num_irq(790).count(), 680);
    337 
    338   EXPECT_EQ(sys_stats.num_softirq_total(), 84611084);
    339   ASSERT_EQ(sys_stats.num_softirq_size(), 10);
    340   EXPECT_EQ(sys_stats.num_softirq(0).count(), 10220177);
    341   EXPECT_EQ(sys_stats.num_softirq(9).count(), 16443195);
    342 
    343   EXPECT_EQ(sys_stats.num_softirq_total(), 84611084);
    344 }
    345 
    346 TEST_F(SysStatsDataSourceTest, StatForksOnly) {
    347   using C = protos::SysStatsConfig;
    348   protos::DataSourceConfig config;
    349   config.mutable_sys_stats_config()->set_stat_period_ms(1);
    350   config.mutable_sys_stats_config()->add_stat_counters(C::STAT_FORK_COUNT);
    351   DataSourceConfig config_obj;
    352   config_obj.FromProto(config);
    353   auto data_source = GetSysStatsDataSource(config_obj);
    354 
    355   WaitTick(data_source.get());
    356 
    357   std::unique_ptr<protos::TracePacket> packet = writer_raw_->ParseProto();
    358   ASSERT_TRUE(packet->has_sys_stats());
    359   const auto& sys_stats = packet->sys_stats();
    360   EXPECT_EQ(sys_stats.meminfo_size(), 0);
    361   EXPECT_EQ(sys_stats.vmstat_size(), 0);
    362   ASSERT_EQ(sys_stats.cpu_stat_size(), 0);
    363   EXPECT_EQ(sys_stats.num_forks(), 243320);
    364   EXPECT_EQ(sys_stats.num_irq_total(), 0);
    365   ASSERT_EQ(sys_stats.num_irq_size(), 0);
    366   EXPECT_EQ(sys_stats.num_softirq_total(), 0);
    367   ASSERT_EQ(sys_stats.num_softirq_size(), 0);
    368 }
    369 
    370 }  // namespace
    371 }  // namespace perfetto
    372