怎么提高写日志的效率

kingstarer 2011-10-29 08:26:47
为了维护需要,给程序加了不少日志,方便跟踪审计。


但是写日志时有一个比较郁闷的地方

如果写完日志不进行fflash 则程序在崩溃时会丢失在缓冲区的日志(往往是最关键的)

如果进行了fflash 则程序效率相对较低

有没有效率和日志完整性兼顾的方法
...全文
484 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
kingstarer 2012-04-12
  • 打赏
  • 举报
回复
跟我自己写的日志组件有10倍左右的速度差啊 log4cpp的功能太强大了,许多功能我不需要,可能是因这些功能拖慢速度的

这个事情一直没解决,现在只能砍掉详细日志,程序排错比较麻烦
pathuang68 2011-11-20
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 kingstarer 的回复:]

引用 18 楼 rendao0563 的回复:
使用别人造好的优质轮子. 不要自己造轮子.


有现成的高效日志库?

我在网上下过一个log4cpp

发现其写日志的速度比自己直接写文件慢很多
[/Quote]
log4cpp效率已经不错了。楼主要对写入的内容进行结构化编码,将编码写入另外一个文件的作为字典,写入普通日志的时候只写入编码皆可。俺曾经用log4j一秒钟可以写30w+条日志,log4cpp应该效果不会差到哪里去吧。
kingstarer 2011-11-20
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 rendao0563 的回复:]
使用别人造好的优质轮子. 不要自己造轮子.
[/Quote]

有现成的高效日志库?

我在网上下过一个log4cpp

发现其写日志的速度比自己直接写文件慢很多
heke_ken 2011-11-07
  • 打赏
  • 举报
回复
磁盘读写比网络传输快,当然,如果是千兆网卡,另当别论
rendao0563 2011-11-07
  • 打赏
  • 举报
回复
使用别人造好的优质轮子. 不要自己造轮子.
kingstarer 2011-11-07
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 qq120848369 的回复:]
引用 7 楼 kingstarer 的回复:
谢谢

日志做成网络程序的话好像方便一些 不过不知道网络传输效率快还是直接写文件速度快
=========================
共享内存可以考虑 谢谢


我一直都是在考虑效率问题以及可靠性的问题撒,日志总是要存起来,如果你让你的工作程序直接去写磁盘,而且还要保证同步写(O_SYNC)来保证数据的实时写入(数据库都是用O_S……
[/Quote]

网络传输数据也是要花时间的,这个得测一下,究竟是硬盘读写快还是网络传输快

另外,如果使用udp,数据容易丢失 并且顺序可能乱了。 我觉得还是要使用tcp好一些
BT六眼飞鱼 2011-11-07
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 qq120848369 的回复:]

引用 7 楼 kingstarer 的回复:
谢谢

日志做成网络程序的话好像方便一些 不过不知道网络传输效率快还是直接写文件速度快
=========================
共享内存可以考虑 谢谢


我一直都是在考虑效率问题以及可靠性的问题撒,日志总是要存起来,如果你让你的工作程序直接去写磁盘,而且还要保证同步写(O_SYNC)来保证数据的实时写入(数据库都是用O_……
[/Quote]
网络程序也可以本地调用~不错
kingstarer 2011-11-07
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 heke_ken 的回复:]
每写一条日志,都打开关闭文件一次,太多IO操作了,而且是加锁写file的缓冲区,在日志量大的情况下,可以优化
[/Quote]

现在我用的日志组件已经是这样了,不加锁,一天只打开关闭一次文件
qq120848369 2011-11-07
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 qq120848369 的回复:]
引用 7 楼 kingstarer 的回复:
谢谢

日志做成网络程序的话好像方便一些 不过不知道网络传输效率快还是直接写文件速度快
=========================
共享内存可以考虑 谢谢


我一直都是在考虑效率问题以及可靠性的问题撒,日志总是要存起来,如果你让你的工作程序直接去写磁盘,而且还要保证同步写(O_SYNC)来保证数据的实时写入(数据库都是用O_S……
[/Quote]

就算你的程序挂了,怎么办? 绝对不会写脏,因为你是发UDP包给另外一个进程啊,没发出去啊.

你如果写文件的时候程序挂了怎么办,写了一半脏数据啊.

qq120848369 2011-11-07
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 kingstarer 的回复:]
谢谢

日志做成网络程序的话好像方便一些 不过不知道网络传输效率快还是直接写文件速度快
=========================
共享内存可以考虑 谢谢
[/Quote]

我一直都是在考虑效率问题以及可靠性的问题撒,日志总是要存起来,如果你让你的工作程序直接去写磁盘,而且还要保证同步写(O_SYNC)来保证数据的实时写入(数据库都是用O_SYNC),那么必然会write阻塞等物理写入完成. 但如果我们把日志当做一个包送出去,我们可以不必管了,同步写交给了一个单独的进程,变成并发的两个进程了,日志进程爱怎么阻塞就怎么阻塞,无所谓了.

做成网络程序的目的是为了将堆积的日记都转移到一个单独的进程.

SOCKET有缓冲区,打日志的进程只管送一个UDP包过去,你就不用管了.

日志进程的SOCKET缓冲区里堆积着一条又一条日志,那么它就可以慢慢读走去写硬盘.

这个模型算是很简单的方法,甚至可以跨机器存储,很方便,因为这是网络程序.
heke_ken 2011-11-07
  • 打赏
  • 举报
回复
每写一条日志,都打开关闭文件一次,太多IO操作了,而且是加锁写file的缓冲区,在日志量大的情况下,可以优化
追求执着 2011-11-07
  • 打赏
  • 举报
回复
看到用户名和楼主相似,恢复一个!!
赵4老师 2011-11-07
  • 打赏
  • 举报
回复
写日志,重要的不是效率而是可靠性。(不会线程冲突、不会磁盘空间满、不会产生内存碎片、不会崩溃……)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef WIN32
#include <windows.h>
#include <io.h>
#else
#include <unistd.h>
#include <sys/time.h>
#include <pthread.h>
#define CRITICAL_SECTION pthread_mutex_t
#define _vsnprintf vsnprintf
#endif
//Log{
#define MAXLOGSIZE 100000000
#define ARRSIZE(x) (sizeof(x)/sizeof(x[0]))
#include <time.h>
#include <stdarg.h>
char logfilename1[]="MyLog1.log";
char logfilename2[]="MyLog2.log";
char logstr[16000];
char datestr[16];
char timestr[16];
char ms10[3];
CRITICAL_SECTION cs_log;
FILE *flog;
int centisec() {
#ifdef WIN32
return ((GetTickCount()%1000L)/10)%100;
#else
struct timeval tv;

if (!gettimeofday(&tv,NULL)) {
return ((tv.tv_usec%1000000L)/10000)%100;
} else {
return 0;
}
#endif
}
#ifdef WIN32
void Lock(CRITICAL_SECTION *l) {
EnterCriticalSection(l);
}
void Unlock(CRITICAL_SECTION *l) {
LeaveCriticalSection(l);
}
#else
void Lock(CRITICAL_SECTION *l) {
pthread_mutex_lock(l);
}
void Unlock(CRITICAL_SECTION *l) {
pthread_mutex_unlock(l);
}
#endif
void LogV(const char *pszFmt,va_list argp) {
struct tm *now;
time_t aclock;


if (NULL==pszFmt||0==pszFmt[0]) return;
if (-1==_vsnprintf(logstr,ARRSIZE(logstr),pszFmt,argp)) logstr[ARRSIZE(logstr)-1]=0;
time(&aclock);
now=localtime(&aclock);
sprintf(datestr,"%04d-%02d-%02d",now->tm_year+1900,now->tm_mon+1,now->tm_mday);
sprintf(timestr,"%02d:%02d:%02d",now->tm_hour ,now->tm_min ,now->tm_sec );
sprintf(ms10,"%02d",centisec());
printf("%s %s.%s %s",datestr,timestr,ms10,logstr);
flog=fopen(logfilename1,"a");
if (NULL!=flog) {
fprintf(flog,"%s %s.%s %s",datestr,timestr,ms10,logstr);
if (ftell(flog)>MAXLOGSIZE) {
fclose(flog);
if (rename(logfilename1,logfilename2)) {
remove(logfilename2);
rename(logfilename1,logfilename2);
}
flog=fopen(logfilename1,"a");
if (NULL==flog) return;
}
fclose(flog);
}
}
void Log(const char *pszFmt,...) {
va_list argp;

Lock(&cs_log);
va_start(argp,pszFmt);
LogV(pszFmt,argp);
va_end(argp);
Unlock(&cs_log);
}
//Log}
int main(int argc,char * argv[]) {
int i;
#ifdef WIN32
InitializeCriticalSection(&cs_log);
#else
pthread_mutex_init(&cs_log,NULL);
#endif
for (i=0;i<10000;i++) {
Log("This is a Log %04d from FILE:%s LINE:%d\n",i, __FILE__, __LINE__);
}
#ifdef WIN32
DeleteCriticalSection(&cs_log);
#else
pthread_mutex_destroy(&cs_log);
#endif
return 0;
}
kingstarer 2011-11-07
  • 打赏
  • 举报
回复
谢谢

日志做成网络程序的话好像方便一些 不过不知道网络传输效率快还是直接写文件速度快
=========================
共享内存可以考虑 谢谢
kingstarer 2011-10-29
  • 打赏
  • 举报
回复
机器已经是目前比较高端的小型机了,在硬件上优化空间比较小

不知道平时各位有没有碰上这种矛盾。
a707000646 2011-10-29
  • 打赏
  • 举报
回复
效率 可以用硬件环境来消除,
到是完整性确极其重要,如果系统崩溃丢失的那一份数据恰好是非常重要的数据
kingstarer 2011-10-29
  • 打赏
  • 举报
回复
做c++程序也要输出日志啊
QQ515311445 2011-10-29
  • 打赏
  • 举报
回复
楼主做网页的?跟C++有什么关系呢,提错地方了吧
qq120848369 2011-10-29
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 qq120848369 的回复:]

单独写一个日志进程,其他所有进程把日志发送给日志进程,让日志进程慢慢去写,日志进程甚至可以直接设置write的O_SYNC,等待磁盘I/O真正完成才返回。

fflush只是刷应用层buffer给write,丢数据是一方面是应用层buffer丢失,另一方面也是write自身缓冲丢失,所以fflush+sync才是王道。

日志进程可以用环回地址做成网络程序,支持并发接入。
也可以做成一……
[/Quote]

忘记说,做在共享内存里的好处就是当机日志不丢失,都在共享内存里,共享内存做文件映射,那么日志进程重新拉起,会继续处理队列里剩余的日志,遇到非法状况重置队列即可。在一定程度上减少了日志的丢失。
qq120848369 2011-10-29
  • 打赏
  • 举报
回复
单独写一个日志进程,其他所有进程把日志发送给日志进程,让日志进程慢慢去写,日志进程甚至可以直接设置write的O_SYNC,等待磁盘I/O真正完成才返回。

fflush只是刷应用层buffer给write,丢数据是一方面是应用层buffer丢失,另一方面也是write自身缓冲丢失,所以fflush+sync才是王道。

日志进程可以用环回地址做成网络程序,支持并发接入。
也可以做成一个阻塞等的模型,利用共享内存做一个环形日志队列,利用条件变量+互斥量完成。

64,683

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧