update 批量跑同步执行,避免内存溢出

dev_heyuan
liusiyang 4 weeks ago
parent 8274481bd6
commit c1b8cda63e

@ -0,0 +1,50 @@
#ifndef _MEM_MONITOR_H_
#define _MEM_MONITOR_H_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/resource.h>
// 获取当前进程 RSS (物理内存) 使用量,单位 MB
static inline long getRSS_KB()
{
long rss = 0;
FILE *fp = fopen("/proc/self/status", "r");
if (!fp) return -1;
char line[256];
while (fgets(line, sizeof(line), fp))
{
if (strncmp(line, "VmRSS:", 6) == 0)
{
// 格式: "VmRSS: 12345 kB"
const char *p = line + 6;
while (*p == ' ' || *p == '\t') p++;
rss = atol(p);
break;
}
}
fclose(fp);
return rss;
}
// 获取当前进程内存使用,打印格式化日志
static inline void printMemUsage(const char *tag, const char *extra)
{
long rss = getRSS_KB();
struct rusage usage;
getrusage(RUSAGE_SELF, &usage);
printf("[MEM] %-30s | VmRSS: %6ld MB | maxRSS: %6ld MB | %s\n",
tag, rss / 1024, usage.ru_maxrss / 1024, extra ? extra : "");
}
// 获取产品检测 pipeline 队列深度信息快照
#define MEM_LOG(tag, fmt, ...) \
do { \
long _rss = getRSS_KB(); \
printf("[MEM] %-30s | VmRSS: %6ld MB | " fmt "\n", tag, _rss / 1024, ##__VA_ARGS__); \
} while(0)
#endif // _MEM_MONITOR_H_

@ -3,6 +3,7 @@
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "MemMonitor.h"
#include <unistd.h>
#include <string>
#include "CheckUtil.hpp"
@ -856,6 +857,10 @@ void deal::ResultThread(int id)
writeLog(strlog, m_DetResult.strlist);
mutex_DetResult_.unlock();
}
// ✅ 递增已保存结果计数,并通知等待线程,立刻唤醒检查
m_nProductSavedResultCount.fetch_add(1);
m_productResultCV.notify_all();
}
usleep(5 * 1000);
@ -1341,11 +1346,105 @@ int deal::CheckFileImg()
products[i].print("产品" + std::to_string(i + 1));
}
// getchar();
printMemUsage("CheckFileImg-开始处理", "");
for (size_t i = 0; i < products.size(); i++)
{
char buf[128];
snprintf(buf, sizeof(buf), "产品[%zu/%zu] %s 处理前", i+1, products.size(), products[i].product_id.c_str());
printMemUsage(buf, "");
CheckProduct(products[i]); // 处理单个产品
// ✅ 等待当前产品的所有检测结果保存完成,再处理下一个产品
// 使用条件变量ResultThread 每保存完一个结果就 notify_all立刻唤醒检查
printf("\n[同步] 等待产品 %s 检测结果保存完成...\n", products[i].product_id.c_str());
{
std::unique_lock<std::mutex> lock(mutex_Result_list);
int waitCount = 0;
while (true)
{
bool done = m_productResultCV.wait_for(lock, std::chrono::milliseconds(5000), [this]() {
return m_nProductSavedResultCount.load() >= m_nProductSuccessCount.load()
&& m_Result_list.empty();
});
if (done) break;
waitCount++;
printf("[同步] 等待中... 已保存: %d/%d (成功:%d 失败:%d), 结果队列: %s\n",
m_nProductSavedResultCount.load(),
m_nProductSuccessCount.load() + m_nProductFailCount.load(),
m_nProductSuccessCount.load(), m_nProductFailCount.load(),
m_Result_list.empty() ? "" : "非空");
}
}
printf("[同步] 产品 %s 所有结果已保存完成 (saved=%d, success=%d)\n",
products[i].product_id.c_str(),
m_nProductSavedResultCount.load(),
m_nProductSuccessCount.load());
// ✅ 释放资源:清理图像数据,释放内存
{
// 清理图像信息列表(已在 CheckProduct 开头清理过,这里做双重保障)
for (auto &info : m_ImageInfoList)
{
if (!info.img.empty())
{
info.img.release();
}
}
m_ImageInfoList.clear();
std::vector<JC_IMAGE_INFO_>().swap(m_ImageInfoList); // 强制释放 vector 内存
}
snprintf(buf, sizeof(buf), "产品[%zu/%zu] %s 资源释放后", i+1, products.size(), products[i].product_id.c_str());
printMemUsage(buf, "");
}
// ✅ 修复:所有产品处理完成后,通知后台线程退出
printf("\n>>> 所有产品处理完成,正在停止后台线程...\n");
// 1. 通知产品读图线程退出
m_bProductReadExit = true;
m_productTaskCV.notify_all();
m_checkNotifyCV.notify_all();
// 2. 通知结果处理线程退出
m_bExit = true;
cv.notify_all();
// 3. 等待产品读图线程结束
for (auto &thread : m_productReadThreads)
{
if (thread && thread->joinable())
{
thread->join();
}
}
m_productReadThreads.clear();
// 4. 等待结果处理线程结束
for (auto &thread : ptr_ResultthreadList)
{
if (thread && thread->joinable())
{
thread->join();
}
}
ptr_ResultthreadList.clear();
// 5. 等待 GetResult 线程结束
if (ptr_GetResultthread && ptr_GetResultthread->joinable())
{
ptr_GetResultthread->join();
}
ptr_GetResultthread.reset();
// 6. 等待 DealImg 线程结束(如果存在)
if (ptr_DealImgthread && ptr_DealImgthread->joinable())
{
ptr_DealImgthread->join();
}
ptr_DealImgthread.reset();
printf(">>> 所有后台线程已停止,程序退出.\n");
printf("\n");
// TODO: 后续实现具体功能
@ -1383,9 +1482,15 @@ int deal::CheckProduct(const LoadProductImages &product)
m_nProductPendingTasks = 0;
m_nProductSuccessCount = 0;
m_nProductFailCount = 0;
m_nProductSavedResultCount = 0; // 重置已保存结果计数
m_ProductFailedList.clear();
m_nCheckNotifiedCount = 0;
// ✅ 修复内存泄漏清理上一个产品累积的原始图像数据cv::Mat
// 注意m_DetResult 是统计结果(轻量字符串/数字),不清除,跨产品累积
m_ImageInfoList.clear();
m_productIdList.clear();
// 3. 打印产品信息
printf("\n");
printf("╔══════════════════════════════════════════════════════════\n");

@ -799,6 +799,8 @@ public:
std::mutex m_checkNotifyMutex; // 通知队列锁
std::condition_variable m_checkNotifyCV; // 通知条件变量
std::atomic<int> m_nCheckNotifiedCount{0}; // 已通知数量
std::atomic<int> m_nProductSavedResultCount{0}; // 已保存结果数量(用于产品间同步等待)
std::condition_variable m_productResultCV; // 产品结果保存通知CV每次save后notify
std::set<std::string> m_productIdList; // 产品ID列表
};

@ -245,10 +245,10 @@ int main(int argc, char *argv[])
signal(SIGINT, handler);
test.start();
while (true)
{
usleep(10 * 1000);
}
// while (true)
// {
// usleep(10 * 1000);
// }
return 0;
}

Loading…
Cancel
Save