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