On Sat, 16 Mar 2002, Malcolm Kavalsky wrote:

> I attach a program benchmark.c that compares speed of memcpy versus data
> transfer
> over unix sockets.

on my PC (AMD k-6 II 366MHz w/256MB RAM, kernel 2.2.20):

[choo@simey ~]$ gcc -O2 benchmark.c
[choo@simey ~]$ ./a.out
Memcpy'ed 2000 blocks of size 1048576 in 38 seconds => 52 Mbytes/second
Sent 2000 blocks of size 1048576 in 94 seconds over unix socket => 21
Mbytes/second
[choo@simey ~]$

could it be that you were running this while your system was busy doing
other things during the memcpy run, and hence altered the results?
which kernel are you using, btw?

as for zero-copy - no need to argue without reading the kernel's source.
i checked, and it does not do any zero-copy. in kernel 2.2.20, the unix
domain socket functions that handle socket reads/writes
(/usr/src/linux-2-2.20/net/unix/af_unix.c, functions unix_stream_sendmsg
and unix_stream_recvmsg, data is sent using the memcpy_toiovec and
memcpy_fromiovec, respectively. those functions eventually call
copy_from_user and copy_to_user, which has to actualy copy the data.

btw, your 'time testing' is not proper for the unix sockets test - you
measure the time in the client only, while you should measure the _end_
time in the server, not in the client. thought i don't think this has too
much effect on the test...

in any event, for many applications, this is not relevant because:

1. you're comparing socket transfer to memcpy - but you should compare it
   to no copy at all (as is the case with shared mem).

2. sometimes, you cannot afford to copy the data, because of memory
   constrains.

3. if you have complex data structures with pointers, you cannot simply
   copy the data between processes - you need to serialize and
   de-serialize it, which takes more time.

4. there is no synchronization in this manner between the processes - one
   might work on data that's already been modified in another process.

--
guy

"For world domination - press 1,
 or dial 0, and please hold, for the creator." -- nob o. dy


-- Attached file included as plaintext by Listar --
-- File: benchmark.c

#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <time.h>
#include <sys/socket.h>
#include <sys/un.h>

#define BUFSIZE 0x100000  /* 1 Megabyte */
#define NBLOCKS   2000
#define PORT_NAME    "/tmp/foo"

socket_benchmark()
{
  if ( fork() == 0 ) {
    server();
  } else {
    sleep(1); /* Dirty, but ensures client runs after server is ready */
    client();
  }
}

server()
{
  struct sockaddr_un sin,from;
  int s,g,len;
  char *buf;
  
  buf = malloc( BUFSIZE );
  /* Create an unbound socket */
  if( (s=socket( PF_UNIX, SOCK_STREAM, 0 )) < 0 ){
    printf( "Bad socket\n");
    return 0;
  }
  strcpy( sin.sun_path, PORT_NAME );
  sin.sun_family = PF_UNIX;
  if( bind( s, (struct sockaddr *)&sin, 
            strlen(sin.sun_path) + sizeof(sin.sun_family)) < 0){
    printf( "Bad bind\n");
    return 0;
  }
  listen( s, 5 );
  len = sizeof(from);
  g = accept( s, (struct sockaddr *)&from, &len );
  while( read( g, buf, BUFSIZE ) > 0 ); /* sink all data received */
  close(g);
  close(s);
  unlink( PORT_NAME );
}

client()
{
  struct sockaddr_un sin;
  int s;
  char *buf;
  time_t start_time, elapsed_time;
  int i;
  
  buf = malloc( BUFSIZE );
  
  if( (s=socket( PF_UNIX, SOCK_STREAM, 0 )) < 0 ){
    printf( "Bad socket\n");
    return -1;
  }
  strcpy( sin.sun_path, PORT_NAME );
  sin.sun_family = PF_UNIX;
  if( connect( s, (struct sockaddr *)&sin, sizeof(sin)) < 0 ){
    printf("Bad connect\n");
    close(s);
    return -1;
  }

  start_time = time(0);
  for( i=0; i< NBLOCKS && write(s, buf, BUFSIZE) == BUFSIZE ; i++ );
  elapsed_time = time(0) - start_time;
  close(s);
  printf( "Sent %d blocks of size %d in %d seconds over unix socket =>",
          i, BUFSIZE, elapsed_time );
  printf( " %d Mbytes/second \n", (NBLOCKS * BUFSIZE) / (0x100000 * elapsed_time) );

}

memcpy_benchmark()
{
  char *src, *dst;
  time_t start_time, elapsed_time;
  int i;

  src = malloc ( BUFSIZE );
  dst = malloc ( BUFSIZE );
  start_time = time(0);
  for( i=0; i< NBLOCKS; i++ )
    memcpy( dst, src, BUFSIZE );
  elapsed_time = time(0) - start_time;

  printf( "Memcpy'ed %d blocks of size %d in %d seconds =>",
          NBLOCKS, BUFSIZE, elapsed_time );
  printf( " %d Mbytes/second\n", (NBLOCKS * BUFSIZE) / (0x100000 * elapsed_time) );
}

main()
{
  memcpy_benchmark();
  socket_benchmark();
}


=================================================================
To unsubscribe, send mail to [EMAIL PROTECTED] with
the word "unsubscribe" in the message body, e.g., run the command
echo unsubscribe | mail [EMAIL PROTECTED]

Reply via email to