Skip to content

Commit 61dba4d

Browse files
committed
Reduce the memory allocation for AE
1 parent 0a8e546 commit 61dba4d

File tree

3 files changed

+49
-42
lines changed

3 files changed

+49
-42
lines changed

src/ae.c

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,13 @@
4545

4646
aeEventLoop *aeCreateEventLoop(int setsize) {
4747
aeEventLoop *eventLoop;
48-
int i;
4948

5049
monotonicInit(); /* just in case the calling app didn't initialize */
5150

5251
if ((eventLoop = zmalloc(sizeof(*eventLoop))) == NULL) goto err;
53-
eventLoop->events = zmalloc(sizeof(aeFileEvent)*setsize);
54-
eventLoop->fired = zmalloc(sizeof(aeFiredEvent)*setsize);
55-
if (eventLoop->events == NULL || eventLoop->fired == NULL) goto err;
52+
eventLoop->events = zcalloc(sizeof(aeFileEvent*)*setsize);
53+
eventLoop->fired = NULL;
54+
if (eventLoop->events == NULL) goto err;
5655
eventLoop->setsize = setsize;
5756
eventLoop->timeEventHead = NULL;
5857
eventLoop->timeEventNextId = 0;
@@ -62,10 +61,6 @@ aeEventLoop *aeCreateEventLoop(int setsize) {
6261
eventLoop->aftersleep = NULL;
6362
eventLoop->flags = 0;
6463
if (aeApiCreate(eventLoop) == -1) goto err;
65-
/* Events with mask == AE_NONE are not set. So let's initialize the
66-
* vector with it. */
67-
for (i = 0; i < setsize; i++)
68-
eventLoop->events[i].mask = AE_NONE;
6964
return eventLoop;
7065

7166
err:
@@ -108,14 +103,14 @@ int aeResizeSetSize(aeEventLoop *eventLoop, int setsize) {
108103
if (eventLoop->maxfd >= setsize) return AE_ERR;
109104
if (aeApiResize(eventLoop,setsize) == -1) return AE_ERR;
110105

111-
eventLoop->events = zrealloc(eventLoop->events,sizeof(aeFileEvent)*setsize);
112-
eventLoop->fired = zrealloc(eventLoop->fired,sizeof(aeFiredEvent)*setsize);
106+
eventLoop->events = zrealloc(eventLoop->events,sizeof(aeFileEvent*)*setsize);
113107
eventLoop->setsize = setsize;
114108

115109
/* Make sure that if we created new slots, they are initialized with
116110
* an AE_NONE mask. */
117-
for (i = eventLoop->maxfd+1; i < setsize; i++)
118-
eventLoop->events[i].mask = AE_NONE;
111+
for (i = eventLoop->maxfd+1; i < setsize; i++) {
112+
eventLoop->events[i] = NULL;
113+
}
119114
return AE_OK;
120115
}
121116

@@ -147,7 +142,13 @@ int aeCreateFileEvent(aeEventLoop *eventLoop, int fd, int mask,
147142
errno = ERANGE;
148143
return AE_ERR;
149144
}
150-
aeFileEvent *fe = &eventLoop->events[fd];
145+
aeFileEvent *fe = eventLoop->events[fd];
146+
if (!fe) {
147+
fe = zcalloc(sizeof(struct aeFileEvent));
148+
fe->fd = fd;
149+
fe->mask = AE_NONE;
150+
eventLoop->events[fd] = fe;
151+
}
151152

152153
if (aeApiAddEvent(eventLoop, fd, mask) == -1)
153154
return AE_ERR;
@@ -163,8 +164,8 @@ int aeCreateFileEvent(aeEventLoop *eventLoop, int fd, int mask,
163164
void aeDeleteFileEvent(aeEventLoop *eventLoop, int fd, int mask)
164165
{
165166
if (fd >= eventLoop->setsize) return;
166-
aeFileEvent *fe = &eventLoop->events[fd];
167-
if (fe->mask == AE_NONE) return;
167+
aeFileEvent *fe = eventLoop->events[fd];
168+
if (!fe || fe->mask == AE_NONE) return;
168169

169170
/* We want to always remove AE_BARRIER if set when AE_WRITABLE
170171
* is removed. */
@@ -176,23 +177,25 @@ void aeDeleteFileEvent(aeEventLoop *eventLoop, int fd, int mask)
176177
/* Update the max fd */
177178
int j;
178179

179-
for (j = eventLoop->maxfd-1; j >= 0; j--)
180-
if (eventLoop->events[j].mask != AE_NONE) break;
180+
for (j = eventLoop->maxfd-1; j >= 0; j--) {
181+
if (eventLoop->events[j] && eventLoop->events[j]->mask != AE_NONE)
182+
break;
183+
}
181184
eventLoop->maxfd = j;
182185
}
183186
}
184187

185188
void *aeGetFileClientData(aeEventLoop *eventLoop, int fd) {
186189
if (fd >= eventLoop->setsize) return NULL;
187-
aeFileEvent *fe = &eventLoop->events[fd];
190+
aeFileEvent *fe = eventLoop->events[fd];
188191
if (fe->mask == AE_NONE) return NULL;
189192

190193
return fe->clientData;
191194
}
192195

193196
int aeGetFileEvents(aeEventLoop *eventLoop, int fd) {
194197
if (fd >= eventLoop->setsize) return 0;
195-
aeFileEvent *fe = &eventLoop->events[fd];
198+
aeFileEvent *fe = eventLoop->events[fd];
196199

197200
return fe->mask;
198201
}
@@ -341,7 +344,7 @@ static int processTimeEvents(aeEventLoop *eventLoop) {
341344
* The function returns the number of events processed. */
342345
int aeProcessEvents(aeEventLoop *eventLoop, int flags)
343346
{
344-
int processed = 0, numevents;
347+
int processed = 0;
345348

346349
/* Nothing to do? return ASAP */
347350
if (!(flags & AE_TIME_EVENTS) && !(flags & AE_FILE_EVENTS)) return 0;
@@ -352,7 +355,6 @@ int aeProcessEvents(aeEventLoop *eventLoop, int flags)
352355
* to fire. */
353356
if (eventLoop->maxfd != -1 ||
354357
((flags & AE_TIME_EVENTS) && !(flags & AE_DONT_WAIT))) {
355-
int j;
356358
struct timeval tv, *tvp = NULL; /* NULL means infinite wait. */
357359
int64_t usUntilTimer;
358360

@@ -377,21 +379,21 @@ int aeProcessEvents(aeEventLoop *eventLoop, int flags)
377379
}
378380
/* Call the multiplexing API, will return only on timeout or when
379381
* some event fires. */
380-
numevents = aeApiPoll(eventLoop, tvp);
382+
aeApiPoll(eventLoop, tvp);
381383

382384
/* Don't process file events if not requested. */
383385
if (!(flags & AE_FILE_EVENTS)) {
384-
numevents = 0;
386+
eventLoop->fired = NULL;
385387
}
386388

387389
/* After sleep callback. */
388390
if (eventLoop->aftersleep != NULL && flags & AE_CALL_AFTER_SLEEP)
389391
eventLoop->aftersleep(eventLoop);
390392

391-
for (j = 0; j < numevents; j++) {
392-
int fd = eventLoop->fired[j].fd;
393-
aeFileEvent *fe = &eventLoop->events[fd];
394-
int mask = eventLoop->fired[j].mask;
393+
aeFileEvent *fe = eventLoop->fired;
394+
while (fe) {
395+
int fd = fe->fd;
396+
int mask = fe->fired_mask;
395397
int fired = 0; /* Number of events fired for current fd. */
396398

397399
/* Normally we execute the readable event first, and the writable
@@ -416,7 +418,7 @@ int aeProcessEvents(aeEventLoop *eventLoop, int flags)
416418
if (!invert && fe->mask & mask & AE_READABLE) {
417419
fe->rfileProc(eventLoop,fd,fe->clientData,mask);
418420
fired++;
419-
fe = &eventLoop->events[fd]; /* Refresh in case of resize. */
421+
fe = eventLoop->events[fd]; /* Refresh in case of resize. */
420422
}
421423

422424
/* Fire the writable event. */
@@ -430,7 +432,7 @@ int aeProcessEvents(aeEventLoop *eventLoop, int flags)
430432
/* If we have to invert the call, fire the readable event now
431433
* after the writable one. */
432434
if (invert) {
433-
fe = &eventLoop->events[fd]; /* Refresh in case of resize. */
435+
fe = eventLoop->events[fd]; /* Refresh in case of resize. */
434436
if ((fe->mask & mask & AE_READABLE) &&
435437
(!fired || fe->wfileProc != fe->rfileProc))
436438
{
@@ -440,7 +442,9 @@ int aeProcessEvents(aeEventLoop *eventLoop, int flags)
440442
}
441443

442444
processed++;
445+
fe = fe->next;
443446
}
447+
eventLoop->fired = NULL;
444448
}
445449
/* Check time events */
446450
if (flags & AE_TIME_EVENTS)

src/ae.h

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,12 @@ typedef void aeBeforeSleepProc(struct aeEventLoop *eventLoop);
5050
/* File event structure */
5151
typedef struct aeFileEvent {
5252
int mask; /* one of AE_(READABLE|WRITABLE|BARRIER) */
53+
int fd;
54+
int fired_mask;
5355
aeFileProc *rfileProc;
5456
aeFileProc *wfileProc;
5557
void *clientData;
58+
struct aeFileEvent *next;
5659
} aeFileEvent;
5760

5861
/* Time event structure */
@@ -68,19 +71,13 @@ typedef struct aeTimeEvent {
6871
* freed in recursive time event calls. */
6972
} aeTimeEvent;
7073

71-
/* A fired event */
72-
typedef struct aeFiredEvent {
73-
int fd;
74-
int mask;
75-
} aeFiredEvent;
76-
7774
/* State of an event based program */
7875
typedef struct aeEventLoop {
7976
int maxfd; /* highest file descriptor currently registered */
8077
int setsize; /* max number of file descriptors tracked */
8178
long long timeEventNextId;
82-
aeFileEvent *events; /* Registered events */
83-
aeFiredEvent *fired; /* Fired events */
79+
aeFileEvent **events; /* Registered events */
80+
aeFileEvent *fired; /* Fired events */
8481
aeTimeEvent *timeEventHead;
8582
int stop;
8683
void *apidata; /* This is used for polling API specific data */

src/ae_epoll.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,12 @@ static int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask) {
5555
struct epoll_event ee = {0}; /* avoid valgrind warning */
5656
/* If the fd was already monitored for some event, we need a MOD
5757
* operation. Otherwise we need an ADD operation. */
58-
int op = eventLoop->events[fd].mask == AE_NONE ?
58+
59+
int op = eventLoop->events[fd]->mask == AE_NONE ?
5960
EPOLL_CTL_ADD : EPOLL_CTL_MOD;
6061

6162
ee.events = 0;
62-
mask |= eventLoop->events[fd].mask; /* Merge old events */
63+
mask |= eventLoop->events[fd]->mask; /* Merge old events */
6364
if (mask & AE_READABLE) ee.events |= EPOLLIN;
6465
if (mask & AE_WRITABLE) ee.events |= EPOLLOUT;
6566
ee.data.fd = fd;
@@ -70,7 +71,7 @@ static int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask) {
7071
static void aeApiDelEvent(aeEventLoop *eventLoop, int fd, int delmask) {
7172
aeApiState *state = eventLoop->apidata;
7273
struct epoll_event ee = {0}; /* avoid valgrind warning */
73-
int mask = eventLoop->events[fd].mask & (~delmask);
74+
int mask = eventLoop->events[fd]->mask & (~delmask);
7475

7576
ee.events = 0;
7677
if (mask & AE_READABLE) ee.events |= EPOLLIN;
@@ -98,13 +99,18 @@ static int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp) {
9899
for (j = 0; j < numevents; j++) {
99100
int mask = 0;
100101
struct epoll_event *e = state->events+j;
102+
struct aeFileEvent *fe = eventLoop->events[e->data.fd];
101103

102104
if (e->events & EPOLLIN) mask |= AE_READABLE;
103105
if (e->events & EPOLLOUT) mask |= AE_WRITABLE;
104106
if (e->events & EPOLLERR) mask |= AE_WRITABLE|AE_READABLE;
105107
if (e->events & EPOLLHUP) mask |= AE_WRITABLE|AE_READABLE;
106-
eventLoop->fired[j].fd = e->data.fd;
107-
eventLoop->fired[j].mask = mask;
108+
fe->fired_mask = mask;
109+
fe->next = NULL;
110+
if (!eventLoop->fired)
111+
eventLoop->fired = fe;
112+
else
113+
eventLoop->fired->next = fe;
108114
}
109115
} else if (retval == -1 && errno != EINTR) {
110116
panic("aeApiPoll: epoll_wait, %s", strerror(errno));

0 commit comments

Comments
 (0)