Hi:
I am involved in the optimization of the performance of a memcached
client library now(written by c).
And I found that if I want to set a big value(say: 9000 bytes long),
prepare all the data and call write once or split the data to two writes
will cause dramatic performance difference: the latter is about 100 times
slow than the former.
I do the experiment on my own machine, a single core T43 notebook. Run
one memcached server instance with the command "/usr/bin/memcached -m 64 -p
11211 -u root", and write code to connect to the 11211 port to write the set
operation data. Iterate 100 times to set a 9000 bytes value each time. The
client.c code prepares all the data and write the data once. The
client_multi_write.c code splite the data to two writes. Run the two
programs to get the above result.
I think it's partly related to the implement of the memcached? Anybody to
confirm the above experiment or give me an explanation?
Thanks.
--
Chen Yin
School of EE & CS, Peking University
/* client.c */
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
#include<fcntl.h>
char buffer[9024];
int c_set(char *buffer, char* key, size_t key_len, size_t value_len, uint32_t flags, unsigned long long expiration)
{
int write_len;
write_len = snprintf(buffer, 1024, "%s %.*s %u %llu %zu\r\n", "set",
(int)key_len, key, flags,
(unsigned long long)expiration, value_len);
return write_len;
}
main(int argc,char *argv[])
{
int create_socket;
struct sockaddr_in address;
char *host = "127.0.0.1";
if ((create_socket = socket(AF_INET,SOCK_STREAM,0)) > 0)
printf("The Socket was created\n");
address.sin_family = AF_INET;
address.sin_port = htons(11211);
inet_pton(AF_INET,host,&address.sin_addr);
if (connect(create_socket, (struct sockaddr *)&address, sizeof(address)) == 0)
printf("The connection was accepted with the server %s...\n",inet_ntoa(address.sin_addr));
int i;
int write_len;
int ret;
char response[100];
for(i = 1; i <= 100; ++i) {
// set the key "fortest" to a value whose length is 9000
write_len = c_set(buffer, "fortest", 8, 9000, 0, 0);
printf("write_len is %d\n", write_len);
buffer[9022] = '\r';
buffer[9023] = '\n';
ret = write(create_socket, buffer, 9024);
printf("begin reading\n");
ret = read(create_socket, response, 100);
if(ret > 0) {
printf("read data(%.*s)\n", ret, response);
} else {
perror("read error:");
}
}
out:
close(create_socket);
}
/* client.c */
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
#include<fcntl.h>
#define BUFFER_SIZE 8196
char buffer[BUFFER_SIZE];
int c_set(char *buffer, char* key, size_t key_len, size_t value_len, uint32_t flags, unsigned long long expiration)
{
int write_len;
write_len = snprintf(buffer, 1024, "%s %.*s %u %llu %zu\r\n", "set",
(int)key_len, key, flags,
(unsigned long long)expiration, value_len);
return write_len;
}
main(int argc,char *argv[])
{
int create_socket;
struct sockaddr_in address;
char *host = "127.0.0.1";
if ((create_socket = socket(AF_INET,SOCK_STREAM,0)) > 0)
printf("The Socket was created\n");
address.sin_family = AF_INET;
address.sin_port = htons(11211);
inet_pton(AF_INET,host,&address.sin_addr);
if (connect(create_socket, (struct sockaddr *)&address, sizeof(address)) == 0)
printf("The connection was accepted with the server %s...\n",inet_ntoa(address.sin_addr));
int i;
int write_len;
int ret;
char response[100];
for(i = 1; i <= 100; ++i) {
// set the key "fortest" to a value whose length is 9000
write_len = c_set(buffer, "fortest", 8, 9000, 0, 0);
printf("write_len is %d\n", write_len);
ret = write(create_socket, buffer, BUFFER_SIZE);
int left_len = 9000 - BUFFER_SIZE + write_len;
buffer[left_len] = '\r';
buffer[left_len + 1] = '\n';
ret = write(create_socket, buffer, left_len + 2);
printf("begin reading\n");
ret = read(create_socket, response, 100);
if(ret > 0) {
printf("read data(%.*s)\n", ret, response);
} else {
perror("read error:");
}
}
out:
close(create_socket);
}