Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d691d6e9 authored by Jin Qian's avatar Jin Qian
Browse files

storaged: record IO perf history from proto updates

Record the bandwidth when writing storaged.proto to monitor system
storage performance.

The history is maintained in 3 catergories.
1. samples of last 24 hours.
2. daily average of last 7 days.
3. weekly average of last 52 weeks.

Sampling frequency of the first catergory is set to once every hour.
Storaged also flushes proto at same frequency.

The proto file is padded to reach a minimal size of 128KB. Storaged
writes 16KB at a time. Bandwidth calculation ignores time spent in
the first write and writes smaller than 16KB.

bandwidth = total size of 16KB writes / time spent in 16KB writes

Restructured the code so that storaged.cpp handles proto load/flush.
It calls individual module to sync proto with internal data
structures.

Added a cmdline argument to dump perf history.

adb shell storaged -p
I/O perf history (KB/s) :  most_recent  <---------  least_recent
last 24 hours : 5315 3775 3659 2042 3890 5652 3649 3696 6023
last 7 days   : 4648 3532 3828 3567 3841 3359 4676
last 52 weeks : 3817 4275 3836 3766 4280 0 0 0 0 0 ...

Test: adb shell storaged -p
      atp:asit/perf/jank_systemui_test
      atp:asit/perf/appstartup_hermetic_cyclic_dropcache_test
      atp:asit/perf/appstartup_non_hermetic_cyclic_dropcache_test

Bug: 63629306
Change-Id: Ie7051e7a8df883d4a6818ea9a54a10f4dccb4843
parent 65dea712
Loading
Loading
Loading
Loading
+28 −10
Original line number Diff line number Diff line
@@ -32,12 +32,6 @@
#define FRIEND_TEST(test_case_name, test_name) \
friend class test_case_name##_##test_name##_Test

#include "storaged_diskstats.h"
#include "storaged_info.h"
#include "storaged_uid_monitor.h"

using namespace android;

#define ARRAY_SIZE(x)   (sizeof(x) / sizeof((x)[0]))

#define SECTOR_SIZE ( 512 )
@@ -47,12 +41,23 @@ using namespace android;
#define SEC_TO_USEC ( 1000000 )
#define HOUR_TO_SEC ( 3600 )
#define DAY_TO_SEC ( 3600 * 24 )
#define WEEK_TO_DAYS ( 7 )
#define YEAR_TO_WEEKS ( 52 )

#include "storaged_diskstats.h"
#include "storaged_info.h"
#include "storaged_uid_monitor.h"
#include "storaged.pb.h"

using namespace std;
using namespace android;

// Periodic chores intervals in seconds
#define DEFAULT_PERIODIC_CHORES_INTERVAL_UNIT ( 60 )
#define DEFAULT_PERIODIC_CHORES_INTERVAL_DISK_STATS_PUBLISH ( 3600 )
#define DEFAULT_PERIODIC_CHORES_INTERVAL_UID_IO ( 3600 )
#define DEFAULT_PERIODIC_CHORES_INTERVAL_UID_IO_LIMIT (300)
#define DEFAULT_PERIODIC_CHORES_INTERVAL_FLUSH_PROTO (3600)

// UID IO threshold in bytes
#define DEFAULT_PERIODIC_CHORES_UID_IO_THRESHOLD ( 1024 * 1024 * 1024ULL )
@@ -61,6 +66,7 @@ struct storaged_config {
    int periodic_chores_interval_unit;
    int periodic_chores_interval_disk_stats_publish;
    int periodic_chores_interval_uid_io;
    int periodic_chores_interval_flush_proto;
    int event_time_check_usec;  // check how much cputime spent in event loop
};

@@ -73,7 +79,10 @@ private:
    uid_monitor mUidm;
    time_t mStarttime;
    sp<IBatteryPropertiesRegistrar> battery_properties;
    std::unique_ptr<storage_info_t> storage_info;
    unique_ptr<storage_info_t> storage_info;
    static const uint32_t crc_init;
    static const string proto_file;
    storaged_proto::StoragedProto proto;
public:
    storaged_t(void);
    ~storaged_t() {}
@@ -87,12 +96,18 @@ public:
        return mStarttime;
    }

    std::unordered_map<uint32_t, struct uid_info> get_uids(void) {
    unordered_map<uint32_t, struct uid_info> get_uids(void) {
        return mUidm.get_uid_io_stats();
    }
    std::map<uint64_t, struct uid_records> get_uid_records(

    vector<vector<uint32_t>> get_perf_history(void) {
        return storage_info->get_perf_history();
    }

    map<uint64_t, struct uid_records> get_uid_records(
            double hours, uint64_t threshold, bool force_report) {
        return mUidm.dump(hours, threshold, force_report);
        return mUidm.dump(hours, threshold, force_report,
                          proto.mutable_uid_io_usage());
    }
    void update_uid_io_interval(int interval) {
        if (interval >= DEFAULT_PERIODIC_CHORES_INTERVAL_UID_IO_LIMIT) {
@@ -105,6 +120,9 @@ public:
    void binderDied(const wp<IBinder>& who);

    void report_storage_info();

    void load_proto();
    void flush_proto();
};

// Eventlog tag
+30 −3
Original line number Diff line number Diff line
@@ -19,10 +19,17 @@

#include <string.h>

#include <chrono>

#include "storaged.h"
#include "storaged.pb.h"

#define FRIEND_TEST(test_case_name, test_name) \
friend class test_case_name##_##test_name##_Test

using namespace std;
using namespace chrono;
using namespace storaged_proto;

class storage_info_t {
protected:
@@ -36,16 +43,36 @@ protected:
    const string userdata_path = "/data";
    uint64_t userdata_total_kb;
    uint64_t userdata_free_kb;
    // io perf history
    time_point<system_clock> day_start_tp;
    vector<uint32_t> recent_perf;
    uint32_t nr_samples;
    vector<uint32_t> daily_perf;
    uint32_t nr_days;
    vector<uint32_t> weekly_perf;
    uint32_t nr_weeks;
    sem_t si_lock;

    storage_info_t() : eol(0), lifetime_a(0), lifetime_b(0),
        userdata_total_kb(0), userdata_free_kb(0) {}
        userdata_total_kb(0), userdata_free_kb(0), nr_samples(0),
        daily_perf(WEEK_TO_DAYS, 0), nr_days(0),
        weekly_perf(YEAR_TO_WEEKS, 0), nr_weeks(0) {
            sem_init(&si_lock, 0, 1);
            day_start_tp = system_clock::now();
            day_start_tp -= chrono::seconds(duration_cast<chrono::seconds>(
                day_start_tp.time_since_epoch()).count() % DAY_TO_SEC);
    }
    void publish();
    storage_info_t* s_info;
public:
    static storage_info_t* get_storage_info();
    virtual ~storage_info_t() {}
    virtual ~storage_info_t() { sem_destroy(&si_lock); }
    virtual void report() {};
    void refresh();
    void init(const IOPerfHistory& perf_history);
    void refresh(IOPerfHistory* perf_history);
    void update_perf_history(uint32_t bw,
                             const time_point<system_clock>& tp);
    vector<vector<uint32_t>> get_perf_history(void);
};

class emmc_info_t : public storage_info_t {
+9 −4
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@

#include "storaged.h"

using namespace std;
using namespace android;

// Interface
@@ -31,9 +32,11 @@ class IStoraged : public IInterface {
public:
    enum {
        DUMPUIDS = IBinder::FIRST_CALL_TRANSACTION,
        DUMPPERF,
    };
    // Request the service to run the test function
    virtual std::vector<struct uid_info> dump_uids(const char* option) = 0;
    virtual vector<struct uid_info> dump_uids(const char* option) = 0;
    virtual vector<vector<uint32_t>> dump_perf_history(const char* option) = 0;

    DECLARE_META_INTERFACE(Storaged);
};
@@ -42,7 +45,8 @@ public:
class BpStoraged : public BpInterface<IStoraged> {
public:
    BpStoraged(const sp<IBinder>& impl) : BpInterface<IStoraged>(impl){};
    virtual std::vector<struct uid_info> dump_uids(const char* option);
    virtual vector<struct uid_info> dump_uids(const char* option);
    virtual vector<vector<uint32_t>> dump_perf_history(const char* option);
};

// Server
@@ -51,7 +55,8 @@ class BnStoraged : public BnInterface<IStoraged> {
};

class Storaged : public BnStoraged {
    virtual std::vector<struct uid_info> dump_uids(const char* option);
    virtual vector<struct uid_info> dump_uids(const char* option);
    virtual vector<vector<uint32_t>> dump_perf_history(const char* option);
    virtual status_t dump(int fd, const Vector<String16>& args);
};

+12 −9
Original line number Diff line number Diff line
@@ -23,6 +23,10 @@
#include <unordered_map>
#include <vector>

#include "storaged.pb.h"

using namespace storaged_proto;

enum uid_stat_t {
    FOREGROUND = 0,
    BACKGROUND = 1,
@@ -113,8 +117,6 @@ private:
    uint64_t start_ts;
    // true if UID_IO_STATS_PATH is accessible
    const bool enable;
    // protobuf file for io_history
    static const std::string io_history_proto_file;

    // reads from /proc/uid_io/stats
    std::unordered_map<uint32_t, struct uid_info> get_uid_io_stats_locked();
@@ -122,26 +124,27 @@ private:
    void add_records_locked(uint64_t curr_ts);
    // updates curr_io_stats and set last_uid_io_stats
    void update_curr_io_stats_locked();
    // restores io_history from protobuf file
    void load_io_history_from_proto();
    // converts io_history to protobuf and writes to a file
    void flush_io_history_to_proto();
    // restores io_history from protobuf
    void load_uid_io_proto(const UidIOUsage& proto);
    // writes io_history to protobuf
    void update_uid_io_proto(UidIOUsage* proto);

public:
    uid_monitor();
    ~uid_monitor();
    // called by storaged main thread
    void init(charger_stat_t stat);
    void init(charger_stat_t stat, const UidIOUsage& proto);
    // called by storaged -u
    std::unordered_map<uint32_t, struct uid_info> get_uid_io_stats();
    // called by dumpsys
    std::map<uint64_t, struct uid_records> dump(
        double hours, uint64_t threshold, bool force_report);
        double hours, uint64_t threshold, bool force_report,
        UidIOUsage* uid_io_proto);
    // called by battery properties listener
    void set_charger_state(charger_stat_t stat);
    // called by storaged periodic_chore or dump with force_report
    bool enabled() { return enable; };
    void report();
    void report(UidIOUsage* proto);
};

#endif /* _STORAGED_UID_MONITOR_H_ */
+1 −0
Original line number Diff line number Diff line
@@ -35,5 +35,6 @@ void sort_running_uids_info(std::vector<struct uid_info> &uids);

// Logging
void log_console_running_uids_info(const std::vector<struct uid_info>& uids, bool flag_dump_task);
void log_console_perf_history(const vector<vector<uint32_t>>& perf_history);

#endif /* _STORAGED_UTILS_H_ */
Loading