-
Notifications
You must be signed in to change notification settings - Fork 4
Latency #16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Latency #16
Changes from all commits
44c8e1e
f17188f
82921bc
6cb6ebb
ef15b4d
30b2041
98571a4
9b34816
a6add49
b99cfaa
15f07ea
a59d047
30f21be
e1183b7
041c238
a5c0d3d
98ccbf1
8460432
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,118 @@ | ||
| /** | ||
| * Copyright 2024 Comcast Cable Communications Management, LLC | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| * | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| #include "rdk_perf_sequence.h" | ||
| #include "rdk_perf_location.h" | ||
| #include "rdk_perf_latency.h" | ||
| #include "rdk_perf_scopedlock.h" | ||
|
|
||
| #define REPORT_FREQUENCY 500 | ||
|
|
||
| #ifdef USE_RDK_PERF | ||
| #include "rdk_perf.h" | ||
| #define PERF_FUNC(a) RDKPerf perf(a); | ||
| #else | ||
| #define PERF_FUNC(a) | ||
| #endif // USE_RDK_PERF | ||
|
|
||
| // Prototypes | ||
| bool RDKCheckSequenceCount(PerfSequence* pSeq); | ||
|
|
||
| void RDKLatency(const char* sequence, const char* location) | ||
| { | ||
| PERF_FUNC(__FUNCTION__); | ||
|
|
||
| SCOPED_LOCK(); | ||
|
|
||
| PerfSequence* pSeq = PerfSequence::GetInstance(); | ||
| if(pSeq->GetSequence(sequence)) { | ||
| pSeq->RecordLocation(location); | ||
|
|
||
| if(RDKCheckSequenceCount(pSeq)) { | ||
| RDKLatencyReport(sequence); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| bool RDKCheckSequenceCount(PerfSequence* pSeq) | ||
| { | ||
| PERF_FUNC(__FUNCTION__); | ||
|
|
||
| static uint32_t lastCount = 0; | ||
| bool retVal = false; | ||
|
|
||
| uint32_t count = pSeq->GetRecordCount(); | ||
| // Report every n-th location | ||
| if(count != lastCount && count % REPORT_FREQUENCY == 0) { | ||
| // Count will be the same for all the locations | ||
| // in the sequence, so only print the report when the | ||
| // last location in the sequence is recorded | ||
| retVal = true; | ||
| } | ||
| lastCount = count; | ||
|
|
||
| return retVal; | ||
| } | ||
| bool RDKLatencyReportAll() | ||
| { | ||
| // For all sequences in the PerfSequence instance | ||
| PERF_FUNC(__FUNCTION__); | ||
| SCOPED_LOCK(); | ||
| PerfSequence* pSeq = PerfSequence::GetInstance(); | ||
| // Iterate through all sequences | ||
| // Note: This requires adding an iterator method to PerfSequence class | ||
| // For simplicity, assuming we have a method GetAllSequenceNames that returns a vector of names | ||
| std::vector<std::string> sequenceNames = pSeq->GetAllSequenceNames(); | ||
| for(const auto& seqName : sequenceNames) { | ||
| RDKLatencyReport(seqName.c_str()); | ||
| } | ||
| return true; | ||
| } | ||
| bool RDKLatencyReport(const char* sequence) | ||
| { | ||
| PERF_FUNC(__FUNCTION__); | ||
|
|
||
| SCOPED_LOCK(); | ||
| FILE* fp = stderr; | ||
| //fp = fopen("/tmp/rdkperf_latency.log", "a"); | ||
|
|
||
| PerfSequence* pSeq = PerfSequence::GetInstance(); | ||
| if(pSeq->GetSequence(sequence)) { | ||
| DataRecord* pData = pSeq->GetDataRecord(); | ||
| if(pData != nullptr) { | ||
| fprintf(fp, "Sequence %s Depth %d\n", pSeq->GetName(), pSeq->GetLocationsDepth()); | ||
|
Comment on lines
+94
to
+98
|
||
| uint8_t depth = 1; | ||
|
Comment on lines
+95
to
+99
|
||
| while(pData != nullptr) { | ||
|
Comment on lines
+96
to
+100
|
||
| for(uint8_t i = 0; i <= depth; i++) { | ||
| fprintf(fp, "--"); | ||
| } | ||
| fprintf(fp, "| %s >> Elapsed %0.3lf Avg %0.3lf Min %0.3lf Max %0.3lf Count %u \n", | ||
| pData->name, | ||
| (double)pData->average_elapsed / 1000.0, | ||
| (double)pData->average / 1000.0, | ||
| (double)pData->min / 1000.0, | ||
| (double)pData->max / 1000.0, | ||
| pData->count); | ||
| pData = pData->child; | ||
| depth++; | ||
| } | ||
| return true; | ||
|
Comment on lines
+94
to
+114
|
||
| } | ||
| } | ||
| return false; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,179 @@ | ||
| /** | ||
| * Copyright 2021 Comcast Cable Communications Management, LLC | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| * | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| #include <stdint.h> | ||
| #include <stdio.h> | ||
| #include <string.h> | ||
| #include <dlfcn.h> | ||
| #include <stdlib.h> | ||
| #include <stdarg.h> | ||
|
|
||
| #include <string> | ||
| #include <map> | ||
|
|
||
| #include "rdk_mem_tracker.h" | ||
|
|
||
| RDKMemTracker::RDKMemTracker(LogFunction pLog) | ||
| : _sequence(0) | ||
| , _lastFreed(0) | ||
| , _totalAllocatedSize(0) | ||
| , _totalAllocatedElements(0) | ||
| , _logFunc(NULL) | ||
| { | ||
| if(pLog != NULL) { | ||
| _logFunc = pLog; | ||
| } | ||
| return; | ||
| } | ||
|
|
||
| RDKMemTracker::~RDKMemTracker() | ||
| { | ||
| Report(); | ||
|
|
||
| auto it = _map.begin(); | ||
| while(it != _map.end()) { | ||
| delete it->second; | ||
| it++; | ||
| } | ||
| _map.clear(); | ||
|
|
||
| return; | ||
| } | ||
|
|
||
| void RDKMemTracker::Allocation(void* memory, uint32_t size, const char* szFunction, const uint32_t nLine) | ||
| { | ||
| _sequence++; | ||
| AllocationData* pAlloc = (AllocationData*)calloc(1, sizeof(AllocationData)); | ||
| pAlloc->size = size; | ||
| pAlloc->szFunction = szFunction; | ||
| pAlloc->nLine = nLine; | ||
| pAlloc->sequence = _sequence; | ||
|
|
||
| _map[memory] = pAlloc; | ||
| _totalAllocatedSize += size; | ||
| _totalAllocatedElements += 1; | ||
|
|
||
| return; | ||
| } | ||
|
|
||
| void RDKMemTracker::Free(void* memory) | ||
| { | ||
| auto it = _map.find(memory); | ||
| if(it != _map.end()) { | ||
| AllocationData* pAlloc = it->second; | ||
| if(_lastFreed != pAlloc->sequence - 1) { | ||
| // Free out of sequence | ||
| Log("Freeing memory %p of size %u out of sequence %u, last freed sequence %u\n", | ||
| memory, pAlloc->size, pAlloc->sequence, _lastFreed); | ||
| } | ||
| _lastFreed = pAlloc->sequence; | ||
| _totalAllocatedSize -= pAlloc->size; | ||
| _totalAllocatedElements -= 1; | ||
| ::free(pAlloc); | ||
| _map.erase(it); | ||
| } | ||
| else { | ||
| // Error, allocation not in list | ||
| Log("ERROR: Could not find memory item %p in the allocation list\n", memory); | ||
| } | ||
|
|
||
| return; | ||
| } | ||
|
|
||
| void RDKMemTracker::Log(std::string& buffer) | ||
| { | ||
| if(_logFunc != NULL) { | ||
| _logFunc(buffer.c_str()); | ||
| } | ||
| else { | ||
| fprintf(stdout, "%s", buffer.c_str()); | ||
| } | ||
| } | ||
|
|
||
| void RDKMemTracker::Log(const char * format, ...) | ||
| { | ||
| char logMessage[LOG_MESSAGE_SIZE]; | ||
|
|
||
| // Generate the log string | ||
| va_list ap; | ||
| va_start(ap, format); | ||
| vsnprintf(logMessage, LOG_MESSAGE_SIZE, format, ap); | ||
| va_end(ap); | ||
|
|
||
| std::string buffer(logMessage); | ||
| Log(buffer); | ||
| } | ||
|
|
||
| void RDKMemTracker::Report(bool bForce) | ||
| { | ||
| if(bForce == true || _map.size() > 0) { | ||
| // How many allocations in the map | ||
| Log("Total active allocations %u (%u)\n", _totalAllocatedElements, _map.size()); | ||
|
|
||
| auto it = _map.begin(); | ||
| while(it != _map.end()) { | ||
| AllocationData* pAlloc = it->second; | ||
| Log("Element sequence %u size %u, allocated here %s, %u\n", | ||
| pAlloc->sequence, pAlloc->size, pAlloc->szFunction, pAlloc->nLine); | ||
| it++; | ||
| } | ||
| } | ||
| } | ||
|
|
||
|
|
||
| // C interface | ||
| extern "C" { | ||
|
|
||
| RDKMemTrackerHandle CreateMemTrackerWithLogCallback(LogFunction pLog) | ||
| { | ||
| return static_cast<RDKMemTrackerHandle>(new RDKMemTracker(pLog)); | ||
| } | ||
|
|
||
| RDKMemTrackerHandle CreateMemTracker() | ||
| { | ||
| return static_cast<RDKMemTrackerHandle>(new RDKMemTracker()); | ||
| } | ||
|
|
||
| void TerminateMemTracker(RDKMemTrackerHandle hTracker) | ||
| { | ||
| delete static_cast<RDKMemTracker*>(hTracker); | ||
| return; | ||
| } | ||
|
|
||
| // Memory tracking | ||
| void TrackAllocation(RDKMemTrackerHandle hTracker, void* memory, uint32_t size, const char* szFunction, const uint32_t nLine) | ||
| { | ||
| static_cast<RDKMemTracker*>(hTracker)->Allocation(memory, size, szFunction, nLine); | ||
| return; | ||
| } | ||
|
|
||
| void TrackFree(RDKMemTrackerHandle hTracker, void* memory) | ||
| { | ||
| static_cast<RDKMemTracker*>(hTracker)->Free(memory); | ||
| return; | ||
| } | ||
|
|
||
| // Reporting | ||
| void MemTrackerReport(RDKMemTrackerHandle hTracker) | ||
| { | ||
| static_cast<RDKMemTracker*>(hTracker)->Report(); | ||
| return; | ||
| } | ||
|
|
||
|
|
||
| } // extern "C" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RDKCheckSequenceCount()uses a singlestatic uint32_t lastCountfor all sequences. If the process records multiple sequences, updates from one sequence will affect reporting decisions for others. This should be tracked per-sequence (e.g., keyed by sequence name) or stored on theSequenceitself.