[OPTIM] move some rarely used fields out of fdtab

Some rarely information are stored in fdtab, making it larger for no
reason (source port ranges, remote address, ...). Such information
lie there because the checks can't find them anywhere else. The goal
will be to move these information to the stream interface once the
checks make use of it.

For now, we move them to an fdinfo array. This simple change might
have improved the cache hit ratio a little bit because a 0.5% of
performance increase has measured.
This commit is contained in:
Willy Tarreau 2009-10-18 07:25:52 +02:00
parent ff9d5ba721
commit 8d5d77efc3
8 changed files with 67 additions and 59 deletions

View File

@ -1,23 +1,23 @@
/*
include/types/fd.h
File descriptors states.
Copyright (C) 2000-2008 Willy Tarreau - w@1wt.eu
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation, version 2.1
exclusively.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
* include/types/fd.h
* File descriptors states.
*
* Copyright (C) 2000-2009 Willy Tarreau - w@1wt.eu
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, version 2.1
* exclusively.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _TYPES_FD_H
#define _TYPES_FD_H
@ -75,10 +75,14 @@ struct fdtab {
unsigned short flags; /* various flags precising the exact status of this fd */
unsigned char state; /* the state of this fd */
unsigned char ev; /* event seen in return of poll() : FD_POLL_* */
struct sockaddr *peeraddr; /* pointer to peer's network address, or NULL if unset */
socklen_t peerlen; /* peer's address length, or 0 if unset */
int local_port; /* optional local port */
};
/* less often used information */
struct fdinfo {
struct port_range *port_range; /* optional port range to bind to */
int local_port; /* optional local port */
struct sockaddr *peeraddr; /* pointer to peer's network address, or NULL if unset */
socklen_t peerlen; /* peer's address length, or 0 if unset */
};
/*
@ -123,6 +127,7 @@ extern int nbpollers;
extern struct poller pollers[MAX_POLLERS]; /* all registered pollers */
extern struct fdtab *fdtab; /* array of all the file descriptors */
extern struct fdinfo *fdinfo; /* less-often used infos for file descriptors */
extern int maxfd; /* # of the highest fd + 1 */
extern int totalconn; /* total # of terminated sessions */
extern int actconn; /* # of active sessions */

View File

@ -838,19 +838,19 @@ struct task *process_chk(struct task *t)
/* note: in case of retry, we may have to release a previously
* allocated port, hence this loop's construct.
*/
port_range_release_port(fdtab[fd].port_range, fdtab[fd].local_port);
fdtab[fd].port_range = NULL;
port_range_release_port(fdinfo[fd].port_range, fdinfo[fd].local_port);
fdinfo[fd].port_range = NULL;
if (!bind_attempts)
break;
bind_attempts--;
fdtab[fd].local_port = port_range_alloc_port(s->sport_range);
if (!fdtab[fd].local_port)
fdinfo[fd].local_port = port_range_alloc_port(s->sport_range);
if (!fdinfo[fd].local_port)
break;
fdtab[fd].port_range = s->sport_range;
src.sin_port = htons(fdtab[fd].local_port);
fdinfo[fd].port_range = s->sport_range;
src.sin_port = htons(fdinfo[fd].local_port);
ret = tcpv4_bind_socket(fd, flags, &src, remote);
} while (ret != 0); /* binding NOK */
@ -926,8 +926,8 @@ struct task *process_chk(struct task *t)
fdtab[fd].cb[DIR_RD].b = NULL;
fdtab[fd].cb[DIR_WR].f = &event_srv_chk_w;
fdtab[fd].cb[DIR_WR].b = NULL;
fdtab[fd].peeraddr = (struct sockaddr *)&sa;
fdtab[fd].peerlen = sizeof(sa);
fdinfo[fd].peeraddr = (struct sockaddr *)&sa;
fdinfo[fd].peerlen = sizeof(sa);
fdtab[fd].state = FD_STCONN; /* connection in progress */
fdtab[fd].flags = FD_FL_TCP | FD_FL_TCP_NODELAY;
EV_FD_SET(fd, DIR_WR); /* for connect status */
@ -963,8 +963,8 @@ struct task *process_chk(struct task *t)
}
}
}
port_range_release_port(fdtab[fd].port_range, fdtab[fd].local_port);
fdtab[fd].port_range = NULL;
port_range_release_port(fdinfo[fd].port_range, fdinfo[fd].local_port);
fdinfo[fd].port_range = NULL;
close(fd); /* socket creation error */
}

View File

@ -449,8 +449,8 @@ int event_accept(int fd) {
fdtab[cfd].cb[DIR_RD].b = s->req;
fdtab[cfd].cb[DIR_WR].f = l->proto->write;
fdtab[cfd].cb[DIR_WR].b = s->rep;
fdtab[cfd].peeraddr = (struct sockaddr *)&s->cli_addr;
fdtab[cfd].peerlen = sizeof(s->cli_addr);
fdinfo[cfd].peeraddr = (struct sockaddr *)&s->cli_addr;
fdinfo[cfd].peerlen = sizeof(s->cli_addr);
if ((p->mode == PR_MODE_HTTP && (s->flags & SN_MONITOR)) ||
(p->mode == PR_MODE_HEALTH && (p->options & PR_O_HTTP_CHK))) {

View File

@ -22,6 +22,7 @@
#include <proto/port_range.h>
struct fdtab *fdtab = NULL; /* array of all the file descriptors */
struct fdinfo *fdinfo = NULL; /* less-often used infos for file descriptors */
int maxfd; /* # of the highest fd + 1 */
int totalconn; /* total # of terminated sessions */
int actconn; /* # of active sessions */
@ -37,8 +38,8 @@ int nbpollers = 0;
void fd_delete(int fd)
{
EV_FD_CLO(fd);
port_range_release_port(fdtab[fd].port_range, fdtab[fd].local_port);
fdtab[fd].port_range = NULL;
port_range_release_port(fdinfo[fd].port_range, fdinfo[fd].local_port);
fdinfo[fd].port_range = NULL;
close(fd);
fdtab[fd].state = FD_STCLOSE;

View File

@ -641,6 +641,8 @@ void init(int argc, char **argv)
if (global.nbproc < 1)
global.nbproc = 1;
fdinfo = (struct fdinfo *)calloc(1,
sizeof(struct fdinfo) * (global.maxsock));
fdtab = (struct fdtab *)calloc(1,
sizeof(struct fdtab) * (global.maxsock));
for (i = 0; i < global.maxsock; i++) {

View File

@ -279,19 +279,19 @@ int tcpv4_connect_server(struct stream_interface *si,
/* note: in case of retry, we may have to release a previously
* allocated port, hence this loop's construct.
*/
port_range_release_port(fdtab[fd].port_range, fdtab[fd].local_port);
fdtab[fd].port_range = NULL;
port_range_release_port(fdinfo[fd].port_range, fdinfo[fd].local_port);
fdinfo[fd].port_range = NULL;
if (!attempts)
break;
attempts--;
fdtab[fd].local_port = port_range_alloc_port(srv->sport_range);
if (!fdtab[fd].local_port)
fdinfo[fd].local_port = port_range_alloc_port(srv->sport_range);
if (!fdinfo[fd].local_port)
break;
fdtab[fd].port_range = srv->sport_range;
src.sin_port = htons(fdtab[fd].local_port);
fdinfo[fd].port_range = srv->sport_range;
src.sin_port = htons(fdinfo[fd].local_port);
ret = tcpv4_bind_socket(fd, flags, &src, remote);
} while (ret != 0); /* binding NOK */
@ -301,8 +301,8 @@ int tcpv4_connect_server(struct stream_interface *si,
}
if (ret) {
port_range_release_port(fdtab[fd].port_range, fdtab[fd].local_port);
fdtab[fd].port_range = NULL;
port_range_release_port(fdinfo[fd].port_range, fdinfo[fd].local_port);
fdinfo[fd].port_range = NULL;
close(fd);
if (ret == 1) {
@ -388,8 +388,8 @@ int tcpv4_connect_server(struct stream_interface *si,
msg = "local address already in use";
qfprintf(stderr,"Cannot connect: %s.\n",msg);
port_range_release_port(fdtab[fd].port_range, fdtab[fd].local_port);
fdtab[fd].port_range = NULL;
port_range_release_port(fdinfo[fd].port_range, fdinfo[fd].local_port);
fdinfo[fd].port_range = NULL;
close(fd);
send_log(be, LOG_EMERG,
"Connect() failed for server %s/%s: %s.\n",
@ -397,15 +397,15 @@ int tcpv4_connect_server(struct stream_interface *si,
return SN_ERR_RESOURCE;
} else if (errno == ETIMEDOUT) {
//qfprintf(stderr,"Connect(): ETIMEDOUT");
port_range_release_port(fdtab[fd].port_range, fdtab[fd].local_port);
fdtab[fd].port_range = NULL;
port_range_release_port(fdinfo[fd].port_range, fdinfo[fd].local_port);
fdinfo[fd].port_range = NULL;
close(fd);
return SN_ERR_SRVTO;
} else {
// (errno == ECONNREFUSED || errno == ENETUNREACH || errno == EACCES || errno == EPERM)
//qfprintf(stderr,"Connect(): %d", errno);
port_range_release_port(fdtab[fd].port_range, fdtab[fd].local_port);
fdtab[fd].port_range = NULL;
port_range_release_port(fdinfo[fd].port_range, fdinfo[fd].local_port);
fdinfo[fd].port_range = NULL;
close(fd);
return SN_ERR_SRVCL;
}
@ -419,8 +419,8 @@ int tcpv4_connect_server(struct stream_interface *si,
fdtab[fd].cb[DIR_WR].f = &stream_sock_write;
fdtab[fd].cb[DIR_WR].b = si->ob;
fdtab[fd].peeraddr = (struct sockaddr *)srv_addr;
fdtab[fd].peerlen = sizeof(struct sockaddr_in);
fdinfo[fd].peeraddr = (struct sockaddr *)srv_addr;
fdinfo[fd].peerlen = sizeof(struct sockaddr_in);
fd_insert(fd);
EV_FD_SET(fd, DIR_WR); /* for connect status */
@ -562,8 +562,8 @@ int tcp_bind_listener(struct listener *listener, char *errmsg, int errlen)
if (listener->options & LI_O_NOLINGER)
fdtab[fd].flags |= FD_FL_TCP_NOLING;
fdtab[fd].peeraddr = NULL;
fdtab[fd].peerlen = 0;
fdinfo[fd].peeraddr = NULL;
fdinfo[fd].peerlen = 0;
tcp_return:
if (msg && errlen)
strlcpy2(errmsg, msg, errlen);

View File

@ -267,8 +267,8 @@ static int uxst_bind_listener(struct listener *listener)
fdtab[fd].cb[DIR_RD].b = fdtab[fd].cb[DIR_WR].b = NULL;
fdtab[fd].owner = listener; /* reference the listener instead of a task */
fdtab[fd].state = FD_STLISTEN;
fdtab[fd].peeraddr = NULL;
fdtab[fd].peerlen = 0;
fdinfo[fd].peeraddr = NULL;
fdinfo[fd].peerlen = 0;
return ERR_NONE;
}
@ -537,8 +537,8 @@ int uxst_event_accept(int fd) {
fdtab[cfd].cb[DIR_RD].b = s->req;
fdtab[cfd].cb[DIR_WR].f = l->proto->write;
fdtab[cfd].cb[DIR_WR].b = s->rep;
fdtab[cfd].peeraddr = (struct sockaddr *)&s->cli_addr;
fdtab[cfd].peerlen = sizeof(s->cli_addr);
fdinfo[cfd].peeraddr = (struct sockaddr *)&s->cli_addr;
fdinfo[cfd].peerlen = sizeof(s->cli_addr);
EV_FD_SET(cfd, DIR_RD);

View File

@ -712,7 +712,7 @@ int stream_sock_write(int fd)
* - connecting (EALREADY, EINPROGRESS)
* - connected (EISCONN, 0)
*/
if ((connect(fd, fdtab[fd].peeraddr, fdtab[fd].peerlen) == 0))
if ((connect(fd, fdinfo[fd].peeraddr, fdinfo[fd].peerlen) == 0))
errno = 0;
if (errno == EALREADY || errno == EINPROGRESS) {