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

Commit bbb1fab7 authored by Mark Salyzyn's avatar Mark Salyzyn Committed by Gerrit Code Review
Browse files

Merge "logd: optimize statistics"

parents ca2b67e1 97c1c2be
Loading
Loading
Loading
Loading
+87 −82
Original line number Diff line number Diff line
@@ -27,8 +27,6 @@

#include "LogBuffer.h"
#include "LogReader.h"
#include "LogStatistics.h"
#include "LogWhiteBlackList.h"

// Default
#define LOG_BUFFER_SIZE (256 * 1024) // Tuned on a per-platform basis here?
@@ -193,7 +191,7 @@ void LogBuffer::log(log_id_t log_id, log_time realtime,
        LogTimeEntry::unlock();
    }

    stats.add(len, log_id, uid, pid);
    stats.add(elem);
    maybePrune(log_id);
    pthread_mutex_unlock(&mLogElementsLock);
}
@@ -216,6 +214,16 @@ void LogBuffer::maybePrune(log_id_t id) {
    }
}

LogBufferElementCollection::iterator LogBuffer::erase(LogBufferElementCollection::iterator it) {
    LogBufferElement *e = *it;

    it = mLogElements.erase(it);
    stats.subtract(e);
    delete e;

    return it;
}

// prune "pruneRows" of type "id" from the buffer.
//
// mLogElementsLock must be held when this function is called.
@@ -250,12 +258,8 @@ void LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) {
                continue;
            }

            uid_t uid = e->getUid();

            if (uid == caller_uid) {
                it = mLogElements.erase(it);
                stats.subtract(e->getMsgLen(), id, uid, e->getPid());
                delete e;
            if (e->getUid() == caller_uid) {
                it = erase(it);
                pruneRows--;
                if (pruneRows == 0) {
                    break;
@@ -269,6 +273,7 @@ void LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) {
    }

    // prune by worst offender by uid
    bool hasBlacklist = mPrune.naughty();
    while (pruneRows > 0) {
        // recalculate the worst offender on every batched pass
        uid_t worst = (uid_t) -1;
@@ -276,17 +281,21 @@ void LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) {
        size_t second_worst_sizes = 0;

        if ((id != LOG_ID_CRASH) && mPrune.worstUidEnabled()) {
            LidStatistics &l = stats.id(id);
            l.sort();
            UidStatisticsCollection::iterator iu = l.begin();
            if (iu != l.end()) {
                UidStatistics *u = *iu;
                worst = u->getUid();
                worst_sizes = u->sizes();
                if (++iu != l.end()) {
                    second_worst_sizes = (*iu)->sizes();
            const UidEntry **sorted = stats.sort(2, id);

            if (sorted) {
                if (sorted[0] && sorted[1]) {
                    worst = sorted[0]->getKey();
                    worst_sizes = sorted[0]->getSizes();
                    second_worst_sizes = sorted[1]->getSizes();
                }
                delete [] sorted;
            }
        }

        // skip if we have neither worst nor naughty filters
        if ((worst == (uid_t) -1) && !hasBlacklist) {
            break;
        }

        bool kick = false;
@@ -304,24 +313,28 @@ void LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) {

            uid_t uid = e->getUid();

            if ((uid == worst) || mPrune.naughty(e)) { // Worst or BlackListed
                it = mLogElements.erase(it);
            // !Worst and !BlackListed?
            if ((uid != worst) && (!hasBlacklist || !mPrune.naughty(e))) {
                ++it;
                continue;
            }

            unsigned short len = e->getMsgLen();
                stats.subtract(len, id, uid, e->getPid());
                delete e;
            it = erase(it);
            pruneRows--;
                if (uid == worst) {
                    kick = true;
                    if ((pruneRows == 0) || (worst_sizes < second_worst_sizes)) {
            if (pruneRows == 0) {
                break;
            }
                    worst_sizes -= len;
                } else if (pruneRows == 0) {
                    break;

            if (uid != worst) {
                continue;
            }
            } else {
                ++it;

            kick = true;
            if (worst_sizes < second_worst_sizes) {
                break;
            }
            worst_sizes -= len;
        }

        if (!kick || !mPrune.worstUidEnabled()) {
@@ -330,42 +343,51 @@ void LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) {
    }

    bool whitelist = false;
    bool hasWhitelist = mPrune.nice();
    it = mLogElements.begin();
    while((pruneRows > 0) && (it != mLogElements.end())) {
        LogBufferElement *e = *it;
        if (e->getLogId() == id) {

        if (e->getLogId() != id) {
            it++;
            continue;
        }

        if (oldest && (oldest->mStart <= e->getSequence())) {
                if (!whitelist) {
            if (whitelist) {
                break;
            }

            if (stats.sizes(id) > (2 * log_buffer_size(id))) {
                // kick a misbehaving log reader client off the island
                oldest->release_Locked();
            } else {
                oldest->triggerSkip_Locked(id, pruneRows);
            }
                }
            break;
        }

            if (mPrune.nice(e)) { // WhiteListed
        if (hasWhitelist && mPrune.nice(e)) { // WhiteListed
            whitelist = true;
            it++;
            continue;
        }

            it = mLogElements.erase(it);
            stats.subtract(e->getMsgLen(), id, e->getUid(), e->getPid());
            delete e;
        it = erase(it);
        pruneRows--;
        } else {
            it++;
        }
    }

    // Do not save the whitelist if we are reader range limited
    if (whitelist && (pruneRows > 0)) {
        it = mLogElements.begin();
        while((it != mLogElements.end()) && (pruneRows > 0)) {
            LogBufferElement *e = *it;
            if (e->getLogId() == id) {

            if (e->getLogId() != id) {
                ++it;
                continue;
            }

            if (oldest && (oldest->mStart <= e->getSequence())) {
                if (stats.sizes(id) > (2 * log_buffer_size(id))) {
                    // kick a misbehaving log reader client off the island
@@ -375,13 +397,9 @@ void LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) {
                }
                break;
            }
                it = mLogElements.erase(it);
                stats.subtract(e->getMsgLen(), id, e->getUid(), e->getPid());
                delete e;

            it = erase(it);
            pruneRows--;
            } else {
                it++;
            }
        }
    }

@@ -487,22 +505,9 @@ uint64_t LogBuffer::flushTo(
}

void LogBuffer::formatStatistics(char **strp, uid_t uid, unsigned int logMask) {
    uint64_t oldest = UINT64_MAX;

    pthread_mutex_lock(&mLogElementsLock);

    // Find oldest element in the log(s)
    LogBufferElementCollection::iterator it;
    for (it = mLogElements.begin(); it != mLogElements.end(); ++it) {
        LogBufferElement *element = *it;

        if ((logMask & (1 << element->getLogId()))) {
            oldest = element->getSequence();
            break;
        }
    }

    stats.format(strp, uid, logMask, oldest);
    stats.format(strp, uid, logMask);

    pthread_mutex_unlock(&mLogElementsLock);
}
+1 −1
Original line number Diff line number Diff line
@@ -78,7 +78,7 @@ public:
private:
    void maybePrune(log_id_t id);
    void prune(log_id_t id, unsigned long pruneRows, uid_t uid = AID_ROOT);

    LogBufferElementCollection::iterator erase(LogBufferElementCollection::iterator it);
};

#endif // _LOGD_LOG_BUFFER_H__
+2 −1
Original line number Diff line number Diff line
@@ -17,8 +17,9 @@
#ifndef _LOGD_LOG_BUFFER_ELEMENT_H__
#define _LOGD_LOG_BUFFER_ELEMENT_H__

#include <sys/types.h>
#include <stdatomic.h>
#include <sys/types.h>

#include <sysutils/SocketClient.h>
#include <log/log.h>
#include <log/log_read.h>
+164 −700

File changed.

Preview size limit exceeded, changes collapsed.

+25 −140
Original line number Diff line number Diff line
@@ -20,175 +20,60 @@
#include <sys/types.h>

#include <log/log.h>
#include <log/log_read.h>
#include <utils/List.h>
#include <utils/BasicHashtable.h>

#include "LogBufferElement.h"

#define log_id_for_each(i) \
    for (log_id_t i = LOG_ID_MIN; i < LOG_ID_MAX; i = (log_id_t) (i + 1))

class PidStatistics {
    const pid_t pid;

    // Total
    size_t mSizesTotal;
    size_t mElementsTotal;
    // Current
    size_t mSizes;
    size_t mElements;

    char *name;
    bool mGone;

public:
    static const pid_t gone = (pid_t) -1;

    PidStatistics(pid_t pid, char *name = NULL);
    PidStatistics(const PidStatistics &copy);
    ~PidStatistics();

    pid_t getPid() const { return pid; }
    bool pidGone();
    char *getName() const { return name; }
    void setName(char *name);

    void add(unsigned short size);
    bool subtract(unsigned short size); // returns true if stats and PID gone
    void addTotal(size_t size, size_t element);

    size_t sizes() const { return mSizes; }
    size_t elements() const { return mElements; }

    size_t sizesTotal() const { return mSizesTotal; }
    size_t elementsTotal() const { return mElementsTotal; }

    // helper
    static char *pidToName(pid_t pid);
};

typedef android::List<PidStatistics *> PidStatisticsCollection;

class UidStatistics {
struct UidEntry {
    const uid_t uid;
    size_t size;

    PidStatisticsCollection Pids;

    void insert(PidStatisticsCollection::iterator i, PidStatistics *p)
        { Pids.insert(i, p); }
    void push_back(PidStatistics *p) { Pids.push_back(p); }

    size_t mSizes;
    size_t mElements;

public:
    UidStatistics(uid_t uid);
    ~UidStatistics();

    PidStatisticsCollection::iterator begin() { return Pids.begin(); }
    PidStatisticsCollection::iterator end() { return Pids.end(); }
    PidStatisticsCollection::iterator erase(PidStatisticsCollection::iterator i)
        { return Pids.erase(i); }

    uid_t getUid() { return uid; }

    void add(unsigned short size, pid_t pid);
    void subtract(unsigned short size, pid_t pid);
    void sort();
    UidEntry(uid_t uid):uid(uid),size(0) { }

    static const pid_t pid_all = (pid_t) -1;

    // fast track current value
    size_t sizes() const { return mSizes; };
    size_t elements() const { return mElements; };

    // statistical track
    size_t sizes(pid_t pid);
    size_t elements(pid_t pid);

    size_t sizesTotal(pid_t pid = pid_all);
    size_t elementsTotal(pid_t pid = pid_all);

    // helper
    static char *pidToName(pid_t pid) { return PidStatistics::pidToName(pid); }
};

typedef android::List<UidStatistics *> UidStatisticsCollection;

class LidStatistics {
    UidStatisticsCollection Uids;

public:
    LidStatistics();
    ~LidStatistics();

    UidStatisticsCollection::iterator begin() { return Uids.begin(); }
    UidStatisticsCollection::iterator end() { return Uids.end(); }

    void add(unsigned short size, uid_t uid, pid_t pid);
    void subtract(unsigned short size, uid_t uid, pid_t pid);
    void sort();

    static const pid_t pid_all = (pid_t) -1;
    static const uid_t uid_all = (uid_t) -1;

    size_t sizes(uid_t uid = uid_all, pid_t pid = pid_all);
    size_t elements(uid_t uid = uid_all, pid_t pid = pid_all);

    size_t sizesTotal(uid_t uid = uid_all, pid_t pid = pid_all);
    size_t elementsTotal(uid_t uid = uid_all, pid_t pid = pid_all);
    inline const uid_t&getKey() const { return uid; }
    size_t getSizes() const { return size; }
    inline void add(size_t s) { size += s; }
    inline bool subtract(size_t s) { size -= s; return !size; }
};

// Log Statistics
class LogStatistics {
    LidStatistics LogIds[LOG_ID_MAX];

    size_t mSizes[LOG_ID_MAX];
    size_t mElements[LOG_ID_MAX];
    size_t mSizesTotal[LOG_ID_MAX];
    size_t mElementsTotal[LOG_ID_MAX];

    bool mStatistics;

    static const unsigned short mBuckets[14];
    log_time mMinimum[sizeof(mBuckets) / sizeof(mBuckets[0])];
    // uid to size list
    typedef android::BasicHashtable<uid_t, UidEntry> uidTable_t;
    uidTable_t uidTable[LOG_ID_MAX];

public:
    const log_time start;

    LogStatistics();

    LidStatistics &id(log_id_t log_id) { return LogIds[log_id]; }
    void enableStatistics() { }

    void enableStatistics() { mStatistics = true; }
    void add(LogBufferElement *entry);
    void subtract(LogBufferElement *entry);

    void add(unsigned short size, log_id_t log_id, uid_t uid, pid_t pid);
    void subtract(unsigned short size, log_id_t log_id, uid_t uid, pid_t pid);
    void sort();
    // Caller must delete array
    const UidEntry **sort(size_t n, log_id i);

    // fast track current value by id only
    size_t sizes(log_id_t id) const { return mSizes[id]; }
    size_t elements(log_id_t id) const { return mElements[id]; }

    // statistical track
    static const log_id_t log_id_all = (log_id_t) -1;
    static const uid_t uid_all = (uid_t) -1;
    static const pid_t pid_all = (pid_t) -1;

    size_t sizes(log_id_t id, uid_t uid, pid_t pid = pid_all);
    size_t elements(log_id_t id, uid_t uid, pid_t pid = pid_all);
    size_t sizes() { return sizes(log_id_all, uid_all); }
    size_t elements() { return elements(log_id_all, uid_all); }

    size_t sizesTotal(log_id_t id = log_id_all,
                      uid_t uid = uid_all,
                      pid_t pid = pid_all);
    size_t elementsTotal(log_id_t id = log_id_all,
                         uid_t uid = uid_all,
                         pid_t pid = pid_all);
    size_t sizesTotal(log_id_t id) const { return mSizesTotal[id]; }
    size_t elementsTotal(log_id_t id) const { return mElementsTotal[id]; }

    // *strp = malloc, balance with free
    void format(char **strp, uid_t uid, unsigned int logMask, log_time oldest);
    void format(char **strp, uid_t uid, unsigned int logMask);

    // helper
    static char *pidToName(pid_t pid) { return PidStatistics::pidToName(pid); }
    char *pidToName(pid_t pid);
    uid_t pidToUid(pid_t pid);
    char *uidToName(uid_t uid);
};

#endif // _LOGD_LOG_STATISTICS_H__
Loading