C - 需要展开循环宏

  • 本文关键字:循环 c m4
  • 更新时间 :
  • 英文 :


请考虑以下代码:

extern int conn_fds[MAX_CLIENTS];
extern int fl_conn_indexes[MAX_CLIENTS];
extern int fl_req_bufs[MAX_CLIENTS];
extern struct epoll_event estab_events[MAX_THREADS];
extern req_buf_t req_bufs[MAX_REQ_BUFS];
extern int fl_req_bufs_top;
extern int conn_statuses[MAX_CLIENTS];
extern int fl_conn_indexes_top;
extern  tcpl_nc_t nc_http_list;
extern struct sockaddr_in conn_addresses[MAX_CLIENTS];
void accept_connections(unsigned int num_conns) {
    int fds[MAX_THREADS];
    int conn_indexes[MAX_THREADS];
    int conn_idx=0;
    int new_bottom;
    socklen_t slenghts[MAX_THREADS];
    void *labels1[MAX_THREADS] = {&&a0,&&a1,&&a2,&&a3,&&a4,&&a5,&&a6,&&a7,&&a8,&&a9,&&a10,&&a11,&&a12,&&a13,&&a14,&&a15};
    void *labels2[MAX_THREADS] = {&&b0,&&b1,&&b2,&&b3,&&b4,&&b5,&&b6,&&b7,&&b8,&&b9,&&b10,&&b11,&&b12,&&b13,&&b14,&&b15};
    void *labels3[MAX_THREADS] = {&&c0,&&c1,&&c2,&&c3,&&c4,&&c5,&&c6,&&c7,&&c8,&&c9,&&c10,&&c11,&&c12,&&c13,&&c14,&&c15};
    new_bottom=fl_conn_indexes_top-num_conns;
    if (new_bottom<=0) return;
    goto *labels1[num_conns];
 a15:
    conn_indexes[MAX_THREADS- 1]=fl_conn_indexes[fl_conn_indexes_top- 1];
 a14:
    conn_indexes[MAX_THREADS- 2]=fl_conn_indexes[fl_conn_indexes_top- 2];
 a13:
    conn_indexes[MAX_THREADS- 3]=fl_conn_indexes[fl_conn_indexes_top- 3];
 a12:
    conn_indexes[MAX_THREADS- 4]=fl_conn_indexes[fl_conn_indexes_top- 4];
 a11:
    conn_indexes[MAX_THREADS- 5]=fl_conn_indexes[fl_conn_indexes_top- 5];
 a10:
    conn_indexes[MAX_THREADS- 6]=fl_conn_indexes[fl_conn_indexes_top- 6];
 a9:
    conn_indexes[MAX_THREADS- 7]=fl_conn_indexes[fl_conn_indexes_top- 7];
 a8:
    conn_indexes[MAX_THREADS- 8]=fl_conn_indexes[fl_conn_indexes_top- 8];
 a7:
    conn_indexes[MAX_THREADS- 9]=fl_conn_indexes[fl_conn_indexes_top- 9];
 a6:
    conn_indexes[MAX_THREADS-10]=fl_conn_indexes[fl_conn_indexes_top-10];
 a5:
    conn_indexes[MAX_THREADS-11]=fl_conn_indexes[fl_conn_indexes_top-11];
 a4:
    conn_indexes[MAX_THREADS-12]=fl_conn_indexes[fl_conn_indexes_top-12];
 a3:
    conn_indexes[MAX_THREADS-13]=fl_conn_indexes[fl_conn_indexes_top-13];
 a2:
    conn_indexes[MAX_THREADS-14]=fl_conn_indexes[fl_conn_indexes_top-14];
 a1:
    conn_indexes[MAX_THREADS-15]=fl_conn_indexes[fl_conn_indexes_top-15];
 a0:
    conn_indexes[MAX_THREADS-16]=fl_conn_indexes[fl_conn_indexes_top-16];
    fl_conn_indexes_top=fl_conn_indexes_top-num_conns;
    goto *labels2[num_conns];
 b15:
    conn_fds[conn_indexes[MAX_THREADS- 1]]=accept(nc_http_list.sock_fd,(struct sockaddr*) &conn_addresses[conn_indexes[MAX_THREADS- 1]],&slenghts[MAX_THREADS- 1]);
 b14:
    conn_fds[conn_indexes[MAX_THREADS- 2]]=accept(nc_http_list.sock_fd,(struct sockaddr*) &conn_addresses[conn_indexes[MAX_THREADS- 2]],&slenghts[MAX_THREADS- 2]);
 b13:
    conn_fds[conn_indexes[MAX_THREADS- 3]]=accept(nc_http_list.sock_fd,(struct sockaddr*) &conn_addresses[conn_indexes[MAX_THREADS- 3]],&slenghts[MAX_THREADS- 3]);
 b12:
    conn_fds[conn_indexes[MAX_THREADS- 4]]=accept(nc_http_list.sock_fd,(struct sockaddr*) &conn_addresses[conn_indexes[MAX_THREADS- 4]],&slenghts[MAX_THREADS- 4]);
 b11:
    conn_fds[conn_indexes[MAX_THREADS- 5]]=accept(nc_http_list.sock_fd,(struct sockaddr*) &conn_addresses[conn_indexes[MAX_THREADS- 5]],&slenghts[MAX_THREADS- 5]);
 b10:
    conn_fds[conn_indexes[MAX_THREADS- 6]]=accept(nc_http_list.sock_fd,(struct sockaddr*) &conn_addresses[conn_indexes[MAX_THREADS- 6]],&slenghts[MAX_THREADS- 6]);
 b9:
    conn_fds[conn_indexes[MAX_THREADS- 7]]=accept(nc_http_list.sock_fd,(struct sockaddr*) &conn_addresses[conn_indexes[MAX_THREADS- 7]],&slenghts[MAX_THREADS- 7]);
 b8:
    conn_fds[conn_indexes[MAX_THREADS- 8]]=accept(nc_http_list.sock_fd,(struct sockaddr*) &conn_addresses[conn_indexes[MAX_THREADS- 8]],&slenghts[MAX_THREADS- 8]);
 b7:
    conn_fds[conn_indexes[MAX_THREADS- 9]]=accept(nc_http_list.sock_fd,(struct sockaddr*) &conn_addresses[conn_indexes[MAX_THREADS- 9]],&slenghts[MAX_THREADS- 9]);
 b6:
    conn_fds[conn_indexes[MAX_THREADS-10]]=accept(nc_http_list.sock_fd,(struct sockaddr*) &conn_addresses[conn_indexes[MAX_THREADS-10]],&slenghts[MAX_THREADS-10]);
 b5:
    conn_fds[conn_indexes[MAX_THREADS-11]]=accept(nc_http_list.sock_fd,(struct sockaddr*) &conn_addresses[conn_indexes[MAX_THREADS-11]],&slenghts[MAX_THREADS-11]);
 b4:
    conn_fds[conn_indexes[MAX_THREADS-12]]=accept(nc_http_list.sock_fd,(struct sockaddr*) &conn_addresses[conn_indexes[MAX_THREADS-12]],&slenghts[MAX_THREADS-12]);
 b3:
    conn_fds[conn_indexes[MAX_THREADS-13]]=accept(nc_http_list.sock_fd,(struct sockaddr*) &conn_addresses[conn_indexes[MAX_THREADS-13]],&slenghts[MAX_THREADS-13]);
 b2:
    conn_fds[conn_indexes[MAX_THREADS-14]]=accept(nc_http_list.sock_fd,(struct sockaddr*) &conn_addresses[conn_indexes[MAX_THREADS-14]],&slenghts[MAX_THREADS-14]);
 b1:
    conn_fds[conn_indexes[MAX_THREADS-15]]=accept(nc_http_list.sock_fd,(struct sockaddr*) &conn_addresses[conn_indexes[MAX_THREADS-15]],&slenghts[MAX_THREADS-15]);
 b0:
    conn_fds[conn_indexes[MAX_THREADS-16]]=accept(nc_http_list.sock_fd,(struct sockaddr*) &conn_addresses[conn_indexes[MAX_THREADS-16]],&slenghts[MAX_THREADS-16]);
    goto *labels3[num_conns];
 c15:
    conn_statuses[conn_indexes[MAX_THREADS- 1]]=CONN_STATUS_READING;
 c14:
    conn_statuses[conn_indexes[MAX_THREADS- 2]]=CONN_STATUS_READING;
 c13:
    conn_statuses[conn_indexes[MAX_THREADS- 3]]=CONN_STATUS_READING;
 c12:
    conn_statuses[conn_indexes[MAX_THREADS- 4]]=CONN_STATUS_READING;
 c11:
    conn_statuses[conn_indexes[MAX_THREADS- 5]]=CONN_STATUS_READING;
 c10:
    conn_statuses[conn_indexes[MAX_THREADS- 6]]=CONN_STATUS_READING;
 c9:
    conn_statuses[conn_indexes[MAX_THREADS- 7]]=CONN_STATUS_READING;
 c8:
    conn_statuses[conn_indexes[MAX_THREADS- 8]]=CONN_STATUS_READING;
 c7:
    conn_statuses[conn_indexes[MAX_THREADS- 9]]=CONN_STATUS_READING;
 c6:
    conn_statuses[conn_indexes[MAX_THREADS-10]]=CONN_STATUS_READING;
 c5:
    conn_statuses[conn_indexes[MAX_THREADS-11]]=CONN_STATUS_READING;
 c4:
    conn_statuses[conn_indexes[MAX_THREADS-12]]=CONN_STATUS_READING;
 c3:
    conn_statuses[conn_indexes[MAX_THREADS-13]]=CONN_STATUS_READING;
 c2:
    conn_statuses[conn_indexes[MAX_THREADS-14]]=CONN_STATUS_READING;
 c1:
    conn_statuses[conn_indexes[MAX_THREADS-15]]=CONN_STATUS_READING;
 c0:
    conn_statuses[conn_indexes[MAX_THREADS-16]]=CONN_STATUS_READING;
}

我在这里所做的是并行处理MAX_THREADS数量的连接。循环是故意展开的,是为了速度。但是代码很长。我需要使用宏来减少它,有点像这样:

extern int conn_fds[MAX_CLIENTS];
extern int fl_conn_indexes[MAX_CLIENTS];
extern int fl_req_bufs[MAX_CLIENTS];
extern struct epoll_event estab_events[MAX_THREADS];
extern req_buf_t req_bufs[MAX_REQ_BUFS];
extern int fl_req_bufs_top;
extern int conn_statuses[MAX_CLIENTS];
extern int fl_conn_indexes_top;
extern  tcpl_nc_t nc_http_list;
extern struct sockaddr_in conn_addresses[MAX_CLIENTS];
void accept_connections(unsigned int num_conns) {
    int fds[MAX_THREADS];
    int conn_indexes[MAX_THREADS];
    int conn_idx=0;
    int new_bottom;
    socklen_t slenghts[MAX_THREADS];
    void *labels1[MAX_THREADS] = {&&a0,&&a1,&&a2,&&a3,&&a4,&&a5,&&a6,&&a7,&&a8,&&a9,&&a10,&&a11,&&a12,&&a13,&&a14,&&a15};
    void *labels2[MAX_THREADS] = {&&b0,&&b1,&&b2,&&b3,&&b4,&&b5,&&b6,&&b7,&&b8,&&b9,&&b10,&&b11,&&b12,&&b13,&&b14,&&b15};
    void *labels3[MAX_THREADS] = {&&c0,&&c1,&&c2,&&c3,&&c4,&&c5,&&c6,&&c7,&&c8,&&c9,&&c10,&&c11,&&c12,&&c13,&&c14,&&c15};
    new_bottom=fl_conn_indexes_top-num_conns;
    if (new_bottom<=0) return;
    goto *labels1[num_conns];
LOOP(1,MAX_THREADS) {
 a{ITERATOR}:
    conn_indexes[MAX_THREADS- {ITERATOR}]=fl_conn_indexes[fl_conn_indexes_top- {ITERATOR}];
}
    fl_conn_indexes_top=fl_conn_indexes_top-num_conns;
    goto *labels2[num_conns];
LOOP(1,MAX_THREADS) {      
 b{ITERATOR}:
    conn_fds[conn_indexes[MAX_THREADS- {ITERATOR}]]=accept(nc_http_list.sock_fd,(struct sockaddr*) &conn_addresses[conn_indexes[MAX_THREADS- 1{ITERATOR}]],&slenghts[MAX_THREADS- {ITERATOR}]);
}
    goto *labels3[num_conns];
LOOP(1,MAX_THREADS) {
 c{ITERATOR}:
    conn_statuses[conn_indexes[MAX_THREADS- {ITERATOR}]]=CONN_STATUS_READING;
}
}

{iterator} 在 LOOP() 内部从 1 变为 MAX_THREADS标签被取消是因为连接数可以低于MAX_THREADS并且我必须跳过空变量,否则我会得到段错误。

这可以通过GCC的预处理器轻松实现吗?如果没有,也许我可以使用 m4,但是如何将 m4 与 GCC 集成以实现舒适的开发。因为,我将经常在源代码中编辑这些宏以及许多其他文件,并且需要易于编码。

将非常感谢您的帮助

如果您确实需要m4答案:

dnl usage: unroll(var, initial, max, code)
dnl e.g. unroll(`i', 0, 10, ``total += arr[i]'')
dnl The above goes from 0 to 9, it does not include the final 10.
define(`unroll',
       `define(`$1', `$2')ifelse(eval($2 < $3),
                                 1,
                                 `$4`'unroll(`$1',incr($2),$3,`$4')',
                                 `undefine(`$1')')')dnl
void accept_connections(unsigned int num_conns) {
    int fds[MAX_THREADS];
    int conn_indexes[MAX_THREADS];
    int conn_idx=0;
    int new_bottom;
    socklen_t slenghts[MAX_THREADS];
    void *labels1[MAX_THREADS] = {unroll(`i', 0, 16, `&&a`'i,')};
    void *labels2[MAX_THREADS] = {unroll(`i', 0, 16, `&&b`'i,')};
    void *labels3[MAX_THREADS] = {unroll(`i', 0, 16, `&&c`'i,')};
    new_bottom=fl_conn_indexes_top-num_conns;
    if (new_bottom<=0) return;
    define(`MAX_NUM_CONNS', 16)
    goto *labels1[num_conns];
unroll(`count', 1, incr(MAX_NUM_CONNS()), `dnl
 a`'eval(MAX_NUM_CONNS() - count):
    conn_indexes[MAX_THREADS - count]=fl_conn_indexes[fl_conn_indexes_top - count];
')dnl
    fl_conn_indexes_top=fl_conn_indexes_top-num_conns;
    goto *labels2[num_conns];
unroll(`count', 1, incr(MAX_NUM_CONNS()), `dnl
define(`index', `MAX_THREADS - count')dnl
 b`'eval(MAX_NUM_CONNS() - count):
    conn_fds[conn_indexes[index]]=accept(nc_http_list.sock_fd,(struct sockaddr*) &conn_addresses[conn_indexes[index]],&slenghts[index]);
')dnl
undefine(`index')
    goto *labels3[num_conns];
unroll(`count', 1, incr(MAX_NUM_CONNS()), `dnl
 c`'eval(MAX_NUM_CONNS() - count):
    conn_statuses[conn_indexes[MAX_THREADS - count]]=CONN_STATUS_READING;
')dnl
}

特别注意代码中的宏:defineunrollevalMAX_NUM_CONNScountindexi。还要注意 m4 喜欢的古怪引用。

我可以对此提出改进建议(无论您是否使用 m4)。您在这里的 gotos 紧随其后的用例已经完全被一个更知名的控制结构所覆盖:switch(因为fallthrough是没有break的默认行为):

    define(`MAX_NUM_CONNS', 16)
    switch (num_conns) {
unroll(`count', 1, incr(MAX_NUM_CONNS()), `dnl
    case eval(MAX_NUM_CONNS() - count):
        conn_indexes[MAX_THREADS - count]=fl_conn_indexes[fl_conn_indexes_top - count];
')dnl
    }
    fl_conn_indexes_top=fl_conn_indexes_top-num_conns;
    switch (num_conns) {
unroll(`count', 1, incr(MAX_NUM_CONNS()), `dnl
define(`index', `MAX_THREADS - count')dnl
    case eval(MAX_NUM_CONNS() - count):
        conn_fds[conn_indexes[index]]=accept(nc_http_list.sock_fd,(struct sockaddr*) &conn_addresses[conn_indexes[index]],&slenghts[index]);
')dnl
    }
undefine(`index')
    switch (num_conns) {
unroll(`count', 1, incr(MAX_NUM_CONNS()), `dnl
    case eval(MAX_NUM_CONNS() - count):
        conn_statuses[conn_indexes[MAX_THREADS - count]]=CONN_STATUS_READING;
')dnl
    }

如果将此转换为交换机,则可以删除标签数组。

最后,也许它都可以是一个开关:

    define(`MAX_NUM_CONNS', 16)
    switch (num_conns) {
unroll(`count', 1, incr(MAX_NUM_CONNS()), `dnl
define(`index', `MAX_THREADS - count')dnl
    case eval(MAX_NUM_CONNS() - count):
        conn_indexes[index]=fl_conn_indexes[fl_conn_indexes_top - count];
        conn_fds[conn_indexes[index]]=accept(nc_http_list.sock_fd,(struct sockaddr*) &conn_addresses[conn_indexes[index]],&slenghts[index]);
        conn_statuses[conn_indexes[index]]=CONN_STATUS_READING;
')dnl
    }
undefine(`index')
    fl_conn_indexes_top=fl_conn_indexes_top-num_conns;

请注意,我已将fl_conn_indexes_top修改移至整个展开循环完成后 - 我不确定这是否有效,因为它取决于何时读取或写入该变量。你可以在那里做出判断。


正如我在评论中提到的,这也可以使用编译器标志来完成。GCC 支持 -funroll-loops 选项,该选项在编译器级别为您执行此操作。GCC也支持-fprofile-use,当从-fprofile-generate提供配置文件时)将展开循环,这被证明会导致性能问题。


最后:

我认为这都是过早的优化。我强烈怀疑循环的比较检查是每次迭代调用accept时的瓶颈!

你可以用 chaos-pp 预处理器库滥用 C 预处理器

#include <chaos/preprocessor/arithmetic/dec.h>
#include <chaos/preprocessor/config.h>
#include <chaos/preprocessor/lambda/ops.h>
#include <chaos/preprocessor/logical/bool.h>
#include <chaos/preprocessor/recursion/expr.h>
#include <chaos/preprocessor/repetition/for.h>
#define PRED(s, x) CHAOS_PP_BOOL(x)
#define OP(s, x)   CHAOS_PP_DEC(x)
#define CONN_IDX(s , idx) 
a##idx: 
  conn_indexes[MAX_THREADS - (16 - idx)]=fl_conn_indexes[fl_conn_indexes_top - (16 - idx)]; 
CHAOS_PP_EXPR(CHAOS_PP_FOR(PRED, OP, CONN_IDX, 15))

(格式化的)输出为:

a15: 
conn_indexes[MAX_THREADS - (16 - 15)]=fl_conn_indexes[fl_conn_indexes_top - (16 - 15)]; 
a14: 
conn_indexes[MAX_THREADS - (16 - 14)]=fl_conn_indexes[fl_conn_indexes_top - (16 - 14)];
...

相关内容

  • 没有找到相关文章

最新更新