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

Commit 2cf55995 authored by Christopher Ferris's avatar Christopher Ferris
Browse files

Decrease size of LogBufferElements to 32 bytes.

- Remove virtual from the destructor.
- Remove mTag and derive it when calling getTag().
- Add a boolean mDropped to tell when a message is dropped.
- When dropping a message, and it contains valid tag data, reallocate
  the message to only contain the tag data.
- Add the packed tag to the class.

This saves about ~150K of PSS on a typical log stream since it moves the
size of the LogBufferElement from 48 bytes to 32 bytes which puts it in
a smaller bin.

Bug: 63792187

Test: Builds, unit tests pass.
Change-Id: Ia5afce343ea3d344fcecd78c648338e94f5c9312
(cherry picked from commit 74e74f96)
parent f7ad6222
Loading
Loading
Loading
Loading
+36 −12
Original line number Diff line number Diff line
@@ -41,22 +41,20 @@ LogBufferElement::LogBufferElement(log_id_t log_id, log_time realtime,
      mTid(tid),
      mRealTime(realtime),
      mMsgLen(len),
      mLogId(log_id) {
      mLogId(log_id),
      mDropped(false) {
    mMsg = new char[len];
    memcpy(mMsg, msg, len);
    mTag = (isBinary() && (mMsgLen >= sizeof(uint32_t)))
               ? le32toh(reinterpret_cast<android_event_header_t*>(mMsg)->tag)
               : 0;
}

LogBufferElement::LogBufferElement(const LogBufferElement& elem)
    : mTag(elem.mTag),
      mUid(elem.mUid),
    : mUid(elem.mUid),
      mPid(elem.mPid),
      mTid(elem.mTid),
      mRealTime(elem.mRealTime),
      mMsgLen(elem.mMsgLen),
      mLogId(elem.mLogId) {
      mLogId(elem.mLogId),
      mDropped(elem.mDropped) {
    mMsg = new char[mMsgLen];
    memcpy(mMsg, elem.mMsg, mMsgLen);
}
@@ -65,6 +63,32 @@ LogBufferElement::~LogBufferElement() {
    delete[] mMsg;
}

uint32_t LogBufferElement::getTag() const {
    return (isBinary() &&
            ((mDropped && mMsg != nullptr) ||
             (!mDropped && mMsgLen >= sizeof(android_event_header_t))))
               ? reinterpret_cast<const android_event_header_t*>(mMsg)->tag
               : 0;
}

unsigned short LogBufferElement::setDropped(unsigned short value) {
    // The tag information is saved in mMsg data, if the tag is non-zero
    // save only the information needed to get the tag.
    if (getTag() != 0) {
        if (mMsgLen > sizeof(android_event_header_t)) {
            char* truncated_msg = new char[sizeof(android_event_header_t)];
            memcpy(truncated_msg, mMsg, sizeof(android_event_header_t));
            delete[] mMsg;
            mMsg = truncated_msg;
        }  // mMsgLen == sizeof(android_event_header_t), already at minimum.
    } else {
        delete[] mMsg;
        mMsg = nullptr;
    }
    mDropped = true;
    return mDroppedCount = value;
}

// caller must own and free character string
char* android::tidToName(pid_t tid) {
    char* retval = NULL;
@@ -164,8 +188,8 @@ size_t LogBufferElement::populateDroppedMessage(char*& buffer, LogBuffer* parent
    // identical to below to calculate the buffer size required
    const char* type = lastSame ? "identical" : "expire";
    size_t len = snprintf(NULL, 0, format_uid, mUid, name ? name : "",
                          commName ? commName : "", type, mDropped,
                          (mDropped > 1) ? "s" : "");
                          commName ? commName : "", type, getDropped(),
                          (getDropped() > 1) ? "s" : "");

    size_t hdrLen;
    if (isBinary()) {
@@ -196,8 +220,8 @@ size_t LogBufferElement::populateDroppedMessage(char*& buffer, LogBuffer* parent
    }

    snprintf(buffer + hdrLen, len + 1, format_uid, mUid, name ? name : "",
             commName ? commName : "", type, mDropped,
             (mDropped > 1) ? "s" : "");
             commName ? commName : "", type, getDropped(),
             (getDropped() > 1) ? "s" : "");
    free(const_cast<char*>(name));
    free(const_cast<char*>(commName));

@@ -225,7 +249,7 @@ log_time LogBufferElement::flushTo(SocketClient* reader, LogBuffer* parent,

    char* buffer = NULL;

    if (!mMsg) {
    if (mDropped) {
        entry.len = populateDroppedMessage(buffer, parent, lastSame);
        if (!entry.len) return mRealTime;
        iovec[1].iov_base = buffer;
+11 −19
Original line number Diff line number Diff line
@@ -32,25 +32,25 @@ class LogBuffer;
                                  // chatty for the temporal expire messages
#define EXPIRE_RATELIMIT 10  // maximum rate in seconds to report expiration

class LogBufferElement {
class __attribute__((packed)) LogBufferElement {
    friend LogBuffer;

    // sized to match reality of incoming log packets
    uint32_t mTag;  // only valid for isBinary()
    const uint32_t mUid;
    const uint32_t mPid;
    const uint32_t mTid;
    log_time mRealTime;
    char* mMsg;
    union {
        const uint16_t mMsgLen;  // mMSg != NULL
        uint16_t mDropped;       // mMsg == NULL
        const uint16_t mMsgLen;  // mDropped == false
        uint16_t mDroppedCount;  // mDropped == true
    };
    const uint8_t mLogId;
    bool mDropped;

    static atomic_int_fast64_t sequence;

    // assumption: mMsg == NULL
    // assumption: mDropped == true
    size_t populateDroppedMessage(char*& buffer, LogBuffer* parent,
                                  bool lastSame);

@@ -58,7 +58,7 @@ class LogBufferElement {
    LogBufferElement(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid,
                     pid_t tid, const char* msg, unsigned short len);
    LogBufferElement(const LogBufferElement& elem);
    virtual ~LogBufferElement();
    ~LogBufferElement();

    bool isBinary(void) const {
        return (mLogId == LOG_ID_EVENTS) || (mLogId == LOG_ID_SECURITY);
@@ -76,24 +76,16 @@ class LogBufferElement {
    pid_t getTid(void) const {
        return mTid;
    }
    uint32_t getTag() const {
        return mTag;
    }
    uint32_t getTag() const;
    unsigned short getDropped(void) const {
        return mMsg ? 0 : mDropped;
    }
    unsigned short setDropped(unsigned short value) {
        if (mMsg) {
            delete[] mMsg;
            mMsg = NULL;
        }
        return mDropped = value;
        return mDropped ? mDroppedCount : 0;
    }
    unsigned short setDropped(unsigned short value);
    unsigned short getMsgLen() const {
        return mMsg ? mMsgLen : 0;
        return mDropped ? 0 : mMsgLen;
    }
    const char* getMsg() const {
        return mMsg;
        return mDropped ? nullptr : mMsg;
    }
    log_time getRealTime(void) const {
        return mRealTime;