Skip to content

Commit bab58d6

Browse files
committed
fix: 🐛 修复合并输出时log_write的长度错误,优化性能
1. 修复使用fc_log_merge时,fc_log_write的长度统计错误问题 2. 优化函数的栈消耗 3. 优化函数性能,函数部分展开以少量空间换时间
1 parent 3214070 commit bab58d6

File tree

2 files changed

+191
-99
lines changed

2 files changed

+191
-99
lines changed

core/fc_log.c

Lines changed: 172 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,12 @@ static int __fc_log_alloc_write(FC_FILE *f, const void *buf, int len)
9999
user->block_write += mem->size;
100100
if (false == log->alloc(FC_LOG_ALLOC_NEW, mem, FC_LOG_LINE_SIZE))
101101
{
102+
#if !FC_LOG_POOL_FAIL_RECORD
102103
f->io.write = __fc_log_fail_record_write; // 改变下一次进来的函数,后续只做丢失记录
103104
return len;
105+
#else
106+
return FC_IO_EOF; // 强制结束后面的序列化
107+
#endif
104108
}
105109

106110
// 切换到新的内存块
@@ -127,64 +131,100 @@ fc_weak void fc_log_fprintf(fc_log_t *log, fc_log_level_t level, const char *fmt
127131

128132
if (log->level >= level)
129133
{
130-
FC_FILE temp_f = {0};
131-
fc_log_file_user_t temp_user = {0};
134+
if (!log->merge) // 单次日志输出,不使用log自身的FC_FILE/fc_log_file_user_t对象,使用栈对象
135+
{
136+
FC_FILE temp_f = {0};
137+
fc_log_file_user_t temp_user = {0};
132138

133-
FC_FILE *f = &temp_f;
134-
fc_log_file_user_t *user = &temp_user;
139+
FC_FILE *f = &temp_f;
140+
fc_log_file_user_t *user = &temp_user;
135141

136-
if (log->merge) // 推迟输出,使用对象自身的f和user
137-
{
138-
f = &log->f;
139-
user = &log->file_user;
140-
}
142+
// if (NULL == user->mem.buff && NULL == f->io.write) // 还没有分配过内存并设置write指针(第一次进入)
143+
// 优化性能,这里一定会进
144+
{
145+
// 分配内存池
146+
if (false == log->alloc(FC_LOG_ALLOC_NEW, &(user->mem), FC_LOG_LINE_SIZE))
147+
{
148+
#if !FC_LOG_POOL_FAIL_RECORD
149+
va_list vargs;
150+
va_start(vargs, fmt);
151+
user->total_write = fc_vsnprintf(NULL, 0, fmt, vargs);
152+
va_end(vargs);
153+
154+
// 调用钩子记录丢失的日志长度
155+
FC_LOG_LOSE_HOOK(0 == user->total_write, log, user->total_write);
156+
#endif
157+
// 优化性能,这里不需要赋值
158+
// f->io.write = __fc_log_fail_record_write; // 改变下一次进来的函数,后续只做丢失记录,一次失败后续连续失败,避免一个段内的日志存在中间丢失两边存在的情况
159+
160+
return;
161+
}
162+
163+
user->log = (log->file_user.log) ? log->file_user.log : log; // 始终指向其根对象,如果根对象没有赋值的话就指向当前log对象(代价是日志丢失没有记录)
164+
user->mem_chain = user->mem.buff;
165+
// user->block_write = 0;
166+
167+
f->p_now = user->mem.buff;
168+
f->p_start = user->mem.buff;
169+
f->p_end = user->mem.buff + user->mem.size;
170+
f->user = (void *)user;
171+
f->io.write = __fc_log_alloc_write;
172+
}
141173

142-
if (!user->mem.buff && NULL == f->io.write) // 还没有分配过内存并设置write指针(第一次进入)
143-
{
144-
// 分配内存池
145-
if (false == log->alloc(FC_LOG_ALLOC_NEW, &(user->mem), FC_LOG_LINE_SIZE))
146174
{
147175
va_list vargs;
148176
va_start(vargs, fmt);
149-
user->total_write = fc_vsnprintf(NULL, 0, fmt, vargs);
177+
user->total_write = fc_vfprintf(f, fmt, vargs);
150178
va_end(vargs);
151-
152-
// 调用钩子记录丢失的日志长度
153-
FC_LOG_LOSE_HOOK(0 == user->total_write, log, user->total_write);
154-
155-
f->io.write = __fc_log_fail_record_write; // 改变下一次进来的函数,后续只做丢失记录,一次失败后续连续失败,避免一个段内的日志存在中间丢失两边存在的情况
156-
157-
return;
158179
}
159180

160-
user->log = (log->file_user.log) ? log->file_user.log : log; // 始终指向其根对象,如果根对象没有赋值的话就指向当前log对象(代价是日志丢失没有记录)
161-
user->mem_chain = user->mem.buff;
162-
// user->block_write = 0;
181+
// 写入数据,数据早已写入,这里是将内存块链入fifo
182+
log->write(user);
163183

164-
f->p_now = user->mem.buff;
165-
f->p_start = user->mem.buff;
166-
f->p_end = user->mem.buff + user->mem.size;
167-
f->user = (void *)user;
168-
f->io.write = __fc_log_alloc_write;
184+
// 释放内存池
185+
log->alloc(FC_LOG_ALLOC_FREE, &(user->mem), 0);
169186
}
170-
187+
else
171188
{
172-
va_list vargs;
173-
va_start(vargs, fmt);
174-
user->total_write = fc_vfprintf(f, fmt, vargs);
175-
va_end(vargs);
176-
}
189+
FC_FILE *f = &log->f;
190+
fc_log_file_user_t *user = &log->file_user;
177191

178-
if (!log->merge)
179-
{
180-
// 这里必须展开调用,使用的是栈对象
181-
// fc_log_fflush(log);
192+
if (NULL == user->mem.buff && NULL == f->io.write) // 还没有分配过内存并设置write指针(第一次进入)
193+
{
194+
// 分配内存池
195+
if (false == log->alloc(FC_LOG_ALLOC_NEW, &(user->mem), FC_LOG_LINE_SIZE))
196+
{
197+
#if !FC_LOG_POOL_FAIL_RECORD
198+
va_list vargs;
199+
va_start(vargs, fmt);
200+
user->total_write = fc_vsnprintf(NULL, 0, fmt, vargs);
201+
va_end(vargs);
202+
203+
// 调用钩子记录丢失的日志长度
204+
FC_LOG_LOSE_HOOK(0 == user->total_write, log, user->total_write);
205+
#endif
206+
f->io.write = __fc_log_fail_record_write; // 改变下一次进来的函数,后续只做丢失记录,一次失败后续连续失败,避免一个段内的日志存在中间丢失两边存在的情况
182207

183-
// 写入数据,数据早已写入,这里是将内存块链入fifo
184-
log->write(user);
208+
return;
209+
}
185210

186-
// 释放内存池
187-
log->alloc(FC_LOG_ALLOC_FREE, &(user->mem), 0);
211+
user->log = (log->file_user.log) ? log->file_user.log : log; // 始终指向其根对象,如果根对象没有赋值的话就指向当前log对象(代价是日志丢失没有记录)
212+
user->mem_chain = user->mem.buff;
213+
// user->block_write = 0;
214+
215+
f->p_now = user->mem.buff;
216+
f->p_start = user->mem.buff;
217+
f->p_end = user->mem.buff + user->mem.size;
218+
f->user = (void *)user;
219+
f->io.write = __fc_log_alloc_write;
220+
}
221+
222+
{
223+
va_list vargs;
224+
va_start(vargs, fmt);
225+
user->total_write = fc_vfprintf(f, fmt, vargs);
226+
va_end(vargs);
227+
}
188228
}
189229
}
190230
}
@@ -251,74 +291,117 @@ int fc_log_fwrite(fc_log_t *log, fc_log_level_t level, const void *buff, int len
251291

252292
if (log->level >= level)
253293
{
254-
FC_FILE temp_f = {0};
255-
fc_log_file_user_t temp_user = {0};
256-
257-
FC_FILE *f = &temp_f;
258-
fc_log_file_user_t *user = &temp_user;
294+
int enter_len = len;
259295

260-
if (log->merge) // 推迟输出,使用对象自身的f和user
296+
if (!log->merge) // 单次日志输出,使用栈对象
261297
{
262-
f = &log->f;
263-
user = &log->file_user;
264-
}
298+
FC_FILE temp_f = {0};
299+
fc_log_file_user_t temp_user = {0};
265300

266-
user->total_write = len;
301+
FC_FILE *f = &temp_f;
302+
fc_log_file_user_t *user = &temp_user;
267303

268-
if (!user->mem.buff && NULL == f->io.write) // 还没有分配过内存并设置write指针(第一次进入)
269-
{
270-
// 分配内存池
271-
if (false == log->alloc(FC_LOG_ALLOC_NEW, &(user->mem), FC_LOG_LINE_SIZE))
304+
// if (NULL == user->mem.buff && NULL == f->io.write) // 还没有分配过内存并设置write指针(第一次进入)
305+
// 优化性能,这里一定会进
272306
{
273-
// 调用钩子记录丢失的日志长度
274-
FC_LOG_LOSE_HOOK(false, log, len);
307+
// 分配内存池
308+
if (false == log->alloc(FC_LOG_ALLOC_NEW, &(user->mem), FC_LOG_LINE_SIZE))
309+
{
310+
// 调用钩子记录丢失的日志长度
311+
FC_LOG_LOSE_HOOK(false, log, len);
275312

276-
f->io.write = __fc_log_fail_record_write; // 改变下一次进来的函数,后续只做丢失记录,一次失败后续连续失败,避免一个段内的日志存在中间丢失两边存在的情况
313+
// 优化性能,这里不需要赋值
314+
// f->io.write = __fc_log_fail_record_write; // 改变下一次进来的函数,后续只做丢失记录,一次失败后续连续失败,避免一个段内的日志存在中间丢失两边存在的情况
277315

278-
return 0;
279-
}
316+
return 0;
317+
}
280318

281-
user->log = log;
282-
user->mem_chain = user->mem.buff;
283-
// user->block_write = 0;
319+
user->log = (log->file_user.log) ? log->file_user.log : log; // 始终指向其根对象,如果根对象没有赋值的话就指向当前log对象(代价是日志丢失没有记录)
320+
user->mem_chain = user->mem.buff;
321+
// user->block_write = 0;
284322

285-
// 保持跟fprintf一样
286-
f->p_now = user->mem.buff;
287-
f->p_start = user->mem.buff;
288-
f->p_end = user->mem.buff + user->mem.size;
289-
f->user = (void *)user;
290-
f->io.write = __fc_log_alloc_write;
291-
}
323+
// 保持跟fprintf一样
324+
f->p_now = user->mem.buff;
325+
f->p_start = user->mem.buff;
326+
f->p_end = user->mem.buff + user->mem.size;
327+
f->user = (void *)user;
328+
f->io.write = __fc_log_alloc_write;
329+
}
292330

293-
{
294-
char *this_buff = (char *)buff;
295-
do
296331
{
297-
if (!_write_ch(f, *this_buff))
298-
break;
299-
this_buff++;
300-
len--;
301-
} while (len > 0);
332+
char *this_buff = (char *)buff;
333+
do
334+
{
335+
if (!_write_ch(f, *this_buff))
336+
break;
337+
this_buff++;
338+
len--;
339+
} while (len > 0);
302340

303-
if (f->io.write)
304-
{
305-
f->io.write(f, f->p_now, (int)FC_IO_EOF); // 结束
341+
if (f->io.write)
342+
{
343+
f->io.write(f, f->p_now, (int)FC_IO_EOF); // 结束
344+
}
306345
}
307-
}
308346

309-
if (!log->merge)
310-
{
311-
// 这里必须展开调用,使用的是栈对象
312-
// fc_log_fflush(log);
347+
user->total_write += (enter_len - len);
313348

314349
// 写入数据,数据早已写入,这里是将内存块链入fifo
315350
log->write(user);
316351

317352
// 释放内存池
318353
log->alloc(FC_LOG_ALLOC_FREE, &(user->mem), 0);
319354
}
355+
else
356+
{
357+
FC_FILE *f = &log->f;
358+
fc_log_file_user_t *user = &log->file_user;
359+
360+
if (NULL == user->mem.buff && NULL == f->io.write) // 还没有分配过内存并设置write指针(第一次进入)
361+
{
362+
// 分配内存池
363+
if (false == log->alloc(FC_LOG_ALLOC_NEW, &(user->mem), FC_LOG_LINE_SIZE))
364+
{
365+
// 调用钩子记录丢失的日志长度
366+
FC_LOG_LOSE_HOOK(false, log, len);
367+
368+
f->io.write = __fc_log_fail_record_write; // 改变下一次进来的函数,后续只做丢失记录,一次失败后续连续失败,避免一个段内的日志存在中间丢失两边存在的情况
369+
370+
return 0;
371+
}
372+
373+
user->log = (log->file_user.log) ? log->file_user.log : log; // 始终指向其根对象,如果根对象没有赋值的话就指向当前log对象(代价是日志丢失没有记录)
374+
user->mem_chain = user->mem.buff;
375+
// user->block_write = 0;
376+
377+
// 保持跟fprintf一样
378+
f->p_now = user->mem.buff;
379+
f->p_start = user->mem.buff;
380+
f->p_end = user->mem.buff + user->mem.size;
381+
f->user = (void *)user;
382+
f->io.write = __fc_log_alloc_write;
383+
}
384+
385+
{
386+
char *this_buff = (char *)buff;
387+
do
388+
{
389+
if (!_write_ch(f, *this_buff))
390+
break;
391+
this_buff++;
392+
len--;
393+
} while (len > 0);
394+
395+
if (f->io.write)
396+
{
397+
f->io.write(f, f->p_now, (int)FC_IO_EOF); // 结束
398+
}
399+
}
400+
401+
user->total_write += (enter_len - len);
402+
}
320403

321-
return (int)(user->total_write - len);
404+
return (enter_len - len);
322405
}
323406

324407
return 0;

core/fc_log.h

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,15 @@
6363
#define FC_LOG_USING_COLOR 1 /**< 是否使用颜色 */
6464
#endif
6565

66+
#ifndef FC_LOG_POOL_FAIL_RECORD
67+
#define FC_LOG_POOL_FAIL_RECORD 0 /**< 序列化日志分配失败是否记录丢失日志长度,需要消耗性能用于空序列化一次,个人觉得没必要 */
68+
#endif
69+
70+
#ifndef FC_LOG_FMT_START
71+
#define FC_LOG_FMT_START "" /**< 每句log格式开始部分,结尾跟\r\n可能打印丢失,开头打印可以保证日志清晰 */
72+
// #define FC_LOG_FMT_START "\r\n"
73+
#endif
74+
6675
#ifndef FC_LOG_FMT_END
6776
#define FC_LOG_FMT_END "" /**< 每句log格式结尾部分 */
6877
#endif
@@ -140,17 +149,17 @@
140149
* log级别字符(包含颜色)
141150
*/
142151
#if FC_LOG_USING_COLOR == 1
143-
#define FC_ERROR_TEXT CSI(31) FC_LOG_ERROR_HEAD FC_LOG_PREFIX_FMT CSI(39) FC_LOG_FMT_END /**< 错误标签 */
144-
#define FC_WARNING_TEXT CSI(33) FC_LOG_WARNING_HEAD FC_LOG_PREFIX_FMT CSI(39) FC_LOG_FMT_END /**< 警告标签 */
145-
#define FC_INFO_TEXT CSI(32) FC_LOG_INFO_HEAD FC_LOG_PREFIX_FMT CSI(39) FC_LOG_FMT_END /**< 信息标签 */
146-
#define FC_DEBUG_TEXT CSI(34) FC_LOG_DEBUG_HEAD FC_LOG_PREFIX_FMT CSI(39) FC_LOG_FMT_END /**< 调试标签 */
147-
#define FC_VERBOSE_TEXT CSI(36) FC_LOG_VERBOSE_HEAD FC_LOG_PREFIX_FMT CSI(39) FC_LOG_FMT_END /**< 冗余信息标签 */
152+
#define FC_ERROR_TEXT FC_LOG_FMT_START CSI(31) FC_LOG_ERROR_HEAD FC_LOG_PREFIX_FMT CSI(39) FC_LOG_FMT_END /**< 错误标签 */
153+
#define FC_WARNING_TEXT FC_LOG_FMT_START CSI(33) FC_LOG_WARNING_HEAD FC_LOG_PREFIX_FMT CSI(39) FC_LOG_FMT_END /**< 警告标签 */
154+
#define FC_INFO_TEXT FC_LOG_FMT_START CSI(32) FC_LOG_INFO_HEAD FC_LOG_PREFIX_FMT CSI(39) FC_LOG_FMT_END /**< 信息标签 */
155+
#define FC_DEBUG_TEXT FC_LOG_FMT_START CSI(34) FC_LOG_DEBUG_HEAD FC_LOG_PREFIX_FMT CSI(39) FC_LOG_FMT_END /**< 调试标签 */
156+
#define FC_VERBOSE_TEXT FC_LOG_FMT_START CSI(36) FC_LOG_VERBOSE_HEAD FC_LOG_PREFIX_FMT CSI(39) FC_LOG_FMT_END /**< 冗余信息标签 */
148157
#else
149-
#define FC_ERROR_TEXT FC_LOG_ERROR_HEAD FC_LOG_PREFIX_FMT FC_LOG_FMT_END
150-
#define FC_WARNING_TEXT FC_LOG_WARNING_HEAD FC_LOG_PREFIX_FMT FC_LOG_FMT_END
151-
#define FC_INFO_TEXT FC_LOG_INFO_HEAD FC_LOG_PREFIX_FMT FC_LOG_FMT_END
152-
#define FC_DEBUG_TEXT FC_LOG_DEBUG_HEAD FC_LOG_PREFIX_FMT FC_LOG_FMT_END
153-
#define FC_VERBOSE_TEXT FC_LOG_VERBOSE_HEAD FC_LOG_PREFIX_FMT FC_LOG_FMT_END
158+
#define FC_ERROR_TEXT FC_LOG_FMT_START FC_LOG_ERROR_HEAD FC_LOG_PREFIX_FMT FC_LOG_FMT_END
159+
#define FC_WARNING_TEXT FC_LOG_FMT_START FC_LOG_WARNING_HEAD FC_LOG_PREFIX_FMT FC_LOG_FMT_END
160+
#define FC_INFO_TEXT FC_LOG_FMT_START FC_LOG_INFO_HEAD FC_LOG_PREFIX_FMT FC_LOG_FMT_END
161+
#define FC_DEBUG_TEXT FC_LOG_FMT_START FC_LOG_DEBUG_HEAD FC_LOG_PREFIX_FMT FC_LOG_FMT_END
162+
#define FC_VERBOSE_TEXT FC_LOG_FMT_START FC_LOG_VERBOSE_HEAD FC_LOG_PREFIX_FMT FC_LOG_FMT_END
154163
#endif
155164

156165
// clang-format on

0 commit comments

Comments
 (0)