port_command performs in cycle
Jimmy
youj@REDACTED
Thu Oct 7 22:32:33 CEST 2010
Hi Gurus,
We have an Erlang program communicates to a C-port through the
port_command(). We have messured the time taken to perform 6000
send/response at a time and repeated for 100 times. That is 600000
send/responses in total. The data are shown below. The first column is the
return from timer:tc() for each 6000 send/responses. The second column is
the elapsed time from timer:now_diff(). The data shows sawtooth-shape
function. The response time decrease to a point and then jump up vertically
and then decrease again. The period is around 60 seconds.
We have attached the full test code (erl, C, makefile) for your review.
We've experimented "+A 10", "+A 100". It does not seem to help.
Thank you very much for your insight.
Jimmy
Erlang (BEAM) emulator version 5.6.5 [source] [64-bit] [smp:2]
[async-threads:0] [hipe] [kernel-poll:false]
Eshell V5.6.5 (abort with ^G)
1> drv:test(100).
{244061,[d]} elapseTime(us)= 245508
{222369,[d]} elapseTime(us)= 470812
{212453,[d]} elapseTime(us)= 683355
{203302,[d]} elapseTime(us)= 886736
{213917,[d]} elapseTime(us)= 1100729
{228699,[d]} elapseTime(us)= 1329508
{218659,[d]} elapseTime(us)= 1548250
{209391,[d]} elapseTime(us)= 1757724
{199847,[d]} elapseTime(us)= 1957645
{1947658,[d]} elapseTime(us)= 3905381
{2293637,[d]} elapseTime(us)= 6199105
{2195128,[d]} elapseTime(us)= 8394322
{2102996,[d]} elapseTime(us)= 10497397
{2011831,[d]} elapseTime(us)= 12509320
{1924136,[d]} elapseTime(us)= 14433533
{1841881,[d]} elapseTime(us)= 16275502
{1762773,[d]} elapseTime(us)= 18038356
{1687034,[d]} elapseTime(us)= 19725481
{1614767,[d]} elapseTime(us)= 21340324
{1545251,[d]} elapseTime(us)= 22885661
{1478884,[d]} elapseTime(us)= 24364620
{1415657,[d]} elapseTime(us)= 25780365
{1355062,[d]} elapseTime(us)= 27135500
{1229070,[d]} elapseTime(us)= 28364652
{1170889,[d]} elapseTime(us)= 29535615
{1120657,[d]} elapseTime(us)= 30656352
{1099148,[d]} elapseTime(us)= 31755575
{1097913,[d]} elapseTime(us)= 32853595
{1050709,[d]} elapseTime(us)= 33904385
{1005591,[d]} elapseTime(us)= 34910065
{962535,[d]} elapseTime(us)= 35872677
{920992,[d]} elapseTime(us)= 36793757
{881633,[d]} elapseTime(us)= 37675461
{844040,[d]} elapseTime(us)= 38519576
{807764,[d]} elapseTime(us)= 39327414
{773142,[d]} elapseTime(us)= 40100635
{739643,[d]} elapseTime(us)= 40840346
{708142,[d]} elapseTime(us)= 41548564
{677807,[d]} elapseTime(us)= 42226440
{648385,[d]} elapseTime(us)= 42874904
%%%%%%% drv.erl starts here %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-module(drv).
-export([start/1, init/2, call_port/1, read/2, test/1, perftest/2]).
%% import
-import(timer, [tc/3, now_diff/2]).
init(ExtPrg, DrvID) ->
register(DrvID, self()),
Port = open_port({spawn, ExtPrg}, [{packet, 2}, binary, exit_status]),
loop(Port).
start(DrvID) ->
spawn_link(?MODULE, init, ["./mydrv.out", DrvID]).
call_port(DrvID) ->
DrvID ! {call, self()},
receive
_ ->
ok
end.
loop(Port) ->
receive
{call, Caller} ->
erlang:port_command(Port, <<00>>),
receive
_ ->
Caller ! ok
end,
loop(Port);
stop ->
erlang:port_close(Port),
exit(normal)
end.
read(0,DrvID) ->
[DrvID];
read(N,DrvID) ->
call_port(DrvID),
read((N-1),DrvID).
perftest(0, {MS, S, US}) ->
io:format("~p~celapseTime(us)=~10.B~n", [tc(drv, read, [6000,d]), 9,
now_diff(now(), {MS, S, US})]);
perftest(N, {MS, S, US}) ->
io:format("~p~celapseTime(us)=~10.B~n", [tc(drv, read, [6000,d]), 9,
now_diff(now(), {MS, S, US})]),
perftest(N-1, {MS, S, US}).
test(N) ->
start(d),
perftest(N, now()).
%%%%%%% drv.erl ends here %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/* **** fef_drver_lib.c starts here ******* */
#include <unistd.h>
#include <sys/io.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ei.h>
int fef_read_cmd(char **buf, int *size);
int fef_write_cmd(ei_x_buff* x);
int fef_read_exact(char *buf, int len);
int fef_write_exact(char *buf, int len);
void fef_encode_ok(ei_x_buff* x)
{
const char* k_ok = "ok";
ei_x_encode_atom(x, k_ok);
}
void flush_free(ei_x_buff* x)
{
fef_write_cmd(x);
ei_x_free(x);
}
int fef_read_cmd(char **buf, int *size)
{
int len, gotLen;
gotLen = fef_read_exact(*buf, 2);
if (gotLen != 2) {
return(-1);
}
len = ((**((unsigned char**)buf)) << 8) | *(*((unsigned char**)buf)+1);
if (len > *size) {
char* tmp = (char *) realloc(*buf, len);
if (tmp == NULL) {
return -1;
} else {
*buf = tmp;
}
*size = len;
}
gotLen = fef_read_exact(*buf, len);
return gotLen;
}
int fef_write_cmd(ei_x_buff *buff)
{
char li;
li = (buff->index >> 8) & 0xff;
fef_write_exact(&li, 1);
li = buff->index & 0xff;
fef_write_exact(&li, 1);
return fef_write_exact(buff->buff, buff->index);
}
int fef_read_exact(char *buf, int len)
{
int i, got=0;
do {
if ((i = read(0, buf+got, len-got)) <= 0) {
return i;
}
got += i;
} while (got<len);
return len;
}
int fef_write_exact(char *buf, int len)
{
int i, wrote = 0;
do {
if ((i = write(1, buf+wrote, len-wrote)) <= 0)
return i;
wrote += i;
} while (wrote<len);
return len;
}
/*-----------------------------------------------------------------
* MAIN
*----------------------------------------------------------------*/
int main() {
char* buf;
int size = 8192; /* BUF_SIZE; */
ei_x_buff x;
if ((buf = (char *) malloc(size)) == NULL) {
return -1;
}
while (fef_read_cmd(&buf, &size) > 0) {
ei_x_new_with_version(&x);
fef_encode_ok(&x);
flush_free(&x);
}
return 0;
}
/* **** fef_drver_lib.c ends here ******* */
# #### Makefile starts here #############
THIS_PLATFORM:= $(shell uname -s)
THIS_ARCH:= $(shell uname -p)
TARGETS= mydrv.out drv.beam
YCFLAGS+= -pipe -W -Wall \
-DTHIS_PLATFORM=\"${THIS_PLATFORM}\"
-DTHIS_ARCH=\"${THIS_ARCH}\" \
-DTHIS_TARGET=${THIS_PLATFORM}_Target \
-I/usr/lib64/erlang/usr/include \
-I/usr/lib64/erlang/lib/erl_interface-3.5.9/include \
-L/usr/lib64/erlang/lib/erl_interface-3.5.9/lib \
-I .
all : ${TARGETS}
%.beam: %.erl
erlc $<
mydrv.out : fef_driver_lib.c
cc ${YCFLAGS} -g -o $@ $^ -lpthread
-L/usr/lib64/erlang/lib/erl_interface-3.5.9/lib -lerl_interface -lei
.PHONY : clean
clean :
@rm -f ${TARGETS} *~
# #### Makefile ends here #############
More information about the erlang-questions
mailing list