Re: Sockets slow on Macintosh
Re: Sockets slow on Macintosh
- Subject: Re: Sockets slow on Macintosh
- From: Abhinav Kumar <email@hidden>
- Date: Thu, 7 Apr 2005 01:05:15 -0700 (PDT)
- Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys
True sockets must be used with TCP_NODELAY, also what Quinn pointed holds good. The shell script u r running starts a new instance of the client everytime. the loop must be inside the client code.
Vincent Lubet <email@hidden> wrote:
When sending small messages to emulate transactions, you have to use
the socket option TCP_NODELAY - see man page tcp(4).
Vincent
On Apr 5, 2005, at 3:39 PM, Tron Thomas wrote:
> I am working on a cross platform project that takes a long time to
> start up on the Macintosh. Some investigates indicate that a large
> portion of the slowness is related to the use of sockets for
> communicating information between different processes.
>
> To test this idea, I have written a much simpler client/server
> implementation that simulates what the original code tries to do.
> I ran this new implementation on an G4 iMac with 512 Megabytes of
> RAM, running at 800 Megahertz, and using Mac OS X 10.3.8. I sent
> 370 text messages from the client to the server. The process took
> over a minute and!
a half
to complete. I ran the same program on an
> Intel Pentium IV with 512 Megabytes of RAM, running at 1.7
> Gigahertz, and using Fedora Core 3 Linux. That system took just
> over 5 seconds to complete the same number of iterations.
>
> Given that the Intel system can perform the program so quickly,
> what can be changed in the code so the Macintosh can have
> comparable speed? Below are the source listing both the client and
> server, the Makefile for building the programs, and a Bash shell
> script used to aid in testing. I would appreciated any feedback,
> anyone has to offer.
>
> +-------------+
> | Server Code |
> +-------------+
> #include
> #include
> #include
> #include
> #include // needed for strerror
> #include
>
> #include
> #include
> #include
> #include
>
> using std::string;
>
> namespace
> {
> void ThrowError
> (
> const char* pszPrefix
> )
> {
> string strError = pszPrefix;
> strError += ::strerror(errno);
> strError += '\n';
> throw std::runtime_error(strError);
> }
> }
>
> int main()
> {
> const short nPORT = 8979;
> const int nMAXIMUM_CONNECTIONS = 5;
> const int nINVALID_SOCKET = -1;
> using std::cerr;
> using std::clog;
> using std::cout;
> int nServerSocket = ::socket(AF_INET, SOCK_STREAM, 0);
> if(0 == nServerSocket){
> cerr << "Failed to create the server socket.\n";
> return 0;
> }
>
> sockaddr_in address;
> ::memset(&address, 0, sizeof(address));
> address.sin_family = AF_INET;
> address.sin_addr.s_addr = ::inet_addr("127.0.0.1");>
address.sin_port = htons(nPORT);
> int connection = nINVALID_SOCKET;
> try{
> if(0 > ::bind(nServerSocket, reinterpret_cast
> (&address),
> sizeof(address))){
> ::ThrowError("The following error occurred binding
> to the server "
> "socket:\n");
> }
> if(0 > ::listen(nServerSocket, nMAXIMUM_CONNECTIONS)){
> ::ThrowError("The following error occurred creating the
> listening "
> "queue.\n");
> }
>
> cout << "The server is running and waiting for connections.\n";
>
> bool bRun = true;
> while(bRun){
> fd_set readSet;
> FD_ZERO (&readSet);
> FD_SET(nServerSocket, &readSet);
> timeval timeout = {5, 0};
> int nResult = ::select(FD_SETSIZE, &readSet, NULL, NULL,
> &timeout);
> if(0 > nResult){
> ::ThrowError("The following error occurred while waiting
> for a "
!
>
"connection:\n");
> }
> if(0 == nResult){
> clog << "Timed out waiting for a connection.\n";
> continue;
> }
> cout << "Accepting a client connection.\n";
> if(FD_ISSET(nServerSocket, &readSet)){
> sockaddr_in client_address = address;
> socklen_t client_address_len =
> static_cast(sizeof(client_address));
> connection = ::accept(nServerSocket,
> reinterpret_cast(&client_address),
> &client_address_len);
> if(0 > connection){
> ::ThrowError("The following error occrured accepting
> a client "
> "connection:\n");
> }
> }
>
> size_t bufferSize;
> nResult = ::recv(connection, &bufferSize, sizeof
> (bufferSize), 0);
> if(nResult != sizeof(bufferSize)){
> ::ThrowError("The follow error occurred trying to read
> the buffer "
> "size:\n");
> }
> std::vect!
or
buffer(bufferSize);
> nResult = ::recv(connection, &(buffer[0]), bufferSize, 0);
>
> string message;
> if(nResult == static_cast(bufferSize)){
> message.assign(buffer.begin(), buffer.end());
> }
> else
> {
> ::ThrowError("The following error ocurred reading the
> text:\n");
> }
> if(0 == message.compare("stop")){
> clog << "Stopping the server.\n";
> bRun = false;
> }
> else{
> clog << "Received the following client data:\n" <<
> message << '\n';
> }
>
> message = "?return_code=PASS";
> size_t length = message.size();
> nResult = ::send(connection, &length, sizeof(length), 0);
> if(sizeof(length) != nResult){
> ::ThrowError("The following error occurred sending the
> message "
> "reply size.\n");
> }
>
> nResult = ::send(connection, message.c_str(), length,
0);
> if(nResult != static_cast(length)){
> ::ThrowError("The following error occurred sending the
> reply "
> "message.\n"); }
> ::close(connection);
> connection = nINVALID_SOCKET;
> }
> }
> catch(const std::exception& error){
> cerr << error.what() << std::endl;
> if(nINVALID_SOCKET != connection){
> ::close(connection);
> connection = nINVALID_SOCKET;
> }
> }
> ::close(nServerSocket);
>
> return 0;
> }
>
> +-------------+
> | Client Code |
> +-------------+
> #include
> #include
> #include
> #include
> #include // needed for strerror
> #include
> #include
>
> #include
> #include
> #include
> #include
> #inclu!
de
> #include
>
> using std::string;
>
> namespace
> {
> void ThrowError
> (
> const char* pszPrefix
> )
> {
> string strError = pszPrefix;
> strError += ::strerror(errno);
> strError += '\n';
> throw std::runtime_error(strError);
> }
> char RandomChar()
> {
> return(' ' + (::rand() % 95));
> }
> void CreateRandomMessage
> (
> string* pstrMessage
> )
> {
> if(NULL == pstrMessage){
> return;
> }
> pstrMessage->erase();
> size_t size = ::rand() % 100;
> // Allow only an 8% chance of large size buffers
> if(size >= 8){
> size = 40 + ::rand() % 40;
> }
> else{
> size = 100 + ::rand() % 250;
> }
> std::insert_iterator insert(*pstrMessage,
> pstrMessage->begin());
> std::generate_n(insert, size, RandomChar)!
;
>
}
> }
>
> int main
> (
> int nArgumentCount,
> const char* pszArguments[]
> )
> {
> const short nPORT = 8979;
> using std::cerr;
> using std::clog;
> using std::cout;
>
> int nServerSocket = ::socket(AF_INET, SOCK_STREAM, 0);
> if(0 > nServerSocket){
> cerr << "Failed to create the server socket.\n";
> return 0;
> }
>
> try{
> sockaddr_in serverAddress;
> ::memset(&serverAddress, 0, sizeof(serverAddress));
> serverAddress.sin_family = AF_INET;
> serverAddress.sin_addr.s_addr = ::inet_addr("127.0.0.1");
> serverAddress.sin_port = htons(nPORT);
>
> cout << "Connecting to the server...\n";
> int nResult = ::connect(nServerSocket,
> reinterpret_cast(&serverAddress),
> sizeof(serverAddress));
> if(0 != nResult){
> ::ThrowError("The following error occurred
establishing a
> connection "
> "to the server:\n");
> }
> string strMessage;
> if(1 < nArgumentCount){
> strMessage = pszArguments[1];
> }
> else{
> ::srand(::getpid());
> ::CreateRandomMessage(&strMessage);
> }
> size_t length = strMessage.size();
> clog << "Sending " << length << " bytes of data to the
> server.\n";
> nResult = ::send(nServerSocket, &length, sizeof(length), 0);
> if(0 > nResult){
> ::ThrowError("The following error occurred sending data
> size:\n");
> }
>
> nResult = ::send(nServerSocket, strMessage.c_str(), length, 0);
> if(nResult == static_cast(length)){
> clog << "Sent message '" << strMessage << "' to the server.
> \n";
> } else{
> ::ThrowError("The following error occurred sending data:\n");
> }
>
> cout << "Waiti!
ng for
the server reply...\n";
> size_t bufferSize;
> nResult = ::recv(nServerSocket, &bufferSize, sizeof
> (bufferSize), 0);
> if(0 > nResult){
> ::ThrowError("The following error occurred reading the
> buffer "
> "size:\n");
> }
>
> std::vector buffer(bufferSize);
> nResult = ::recv(nServerSocket, &(buffer[0]), bufferSize, 0);
> if(nResult != static_cast(bufferSize)){
> ::ThrowError("The following error occurred getting the
> reply data.\n");
> }
> string strReply(buffer.begin(), buffer.end());
> clog << "The server replied with '" << strReply << "'.\n";
> }
> catch(const std::exception& error){
> cerr << error.what() << std::endl;
> }
> ::close(nServerSocket);
> return 0;
> }
>
> +----------+
> | Makefile |
> +----------+
> CXX = /usr/bin/g++
>!
; CFLAGS
= -g3 -Wall -ansi -pedantic
>
> .SUFFIXES: .cpp
>
> .cpp.o:
> $(CXX) $(CFLAGS) -c $< -o $@
>
> all: Server Client
>
> Server: Server.o
> $(CXX) -Wall $< -o $@
>
> Client: Client.o
> $(CXX) -Wall $< -o $@
>
> clean:
> rm -f Client
> rm -f Server
> rm -f *.o
>
> +--------------+
> | Shell Script |
> +--------------+
> #! /bin/sh
>
> if [ $# -gt 0 ]; then
> passes=$1
> else
> passes=10
> fi
>
> echo "Running $passes test passes..."
>
> while [ $passes -gt 0 ]
> do
> ./Client
> passes=$[$passes - 1]
> echo "$passes passes left."
> done
>
> ./Client stop
>
> _______________________________________________
> Do not post admin requests to the list. They will be ignored.
> Macnetworkprog mailing list
Yahoo! Messenger
Show us what our next emoticon should look like. Join the fun. _______________________________________________
Do not post admin requests to the list. They will be ignored.
Macnetworkprog mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden