我在Linux(不是SAMBA)中有一个SMB服务器,在读取请求(函数)中我正在使用readahead()函数。 我正在循环读取一个24KB文件,客户端要求使用4KB的帧大小读取文件(循环中有6个请求)。
事情是,当我使用printf()进行每次读取时,我的I / O数量增加了20%!我不明白为什么。
以下是代码示例:
typedef struct _MYFile /* file descriptor */
{
FILE* file; /* underlying file handle */
chat* fileBuf[24*1024];
uint64 fileId; /* file Id */
uint64 fileOffset; /* the file offset */
uint64 readAHeadOffset; /* the read a head offset */
uint64 readAHeadLength; /* length of the read a head frame */
}MYFile
创建文件:(文件保存在我的数据库中)
void create()
{
MYFile file;
file.file = fopen(name, "w+");
file.readAHeadOffset = 0;
file.readAHeadLength = 0;
file.fileId = 1;
updateDB(file)
setvbuf(file.file, file.fileBuf, _IOFBF, sizeof(file.fileBuf));
}
现在我收到了阅读请求:
void read(uint32 size, uint64 offset, uint64fileId, char* readBuf)
{
MYFile * file;
file = getFileFromDB(fileId);
/* position to the offset */
if (file->offset != offset)
lseek(fileno(file->file), (off_t)offset, SEEK_SET);
if (0 == file->readAHeadLength)
{
readahead(file->file, 0, 0, size * 6);
file->readAHeadLength = params->length * 6;
}
//printf("print\n");
fread(fileno(file->file), readBuf, size);
}
所以readahead()只调用一次。 *使用printf(“print \ n”);我得到大约16000个I / O,而不仅仅是大约14000个。
**似乎即使我不使用readahead(),性能也会变得更好。 ***当我将printf()添加到write()函数时,我遇到了同样的问题 任何人都可以启发我?
谢谢你的头脑:)
编辑1:
我使用putty.exe(ssh:22)连接到Linux,每条“printf”消息都通过网络发送,打印显示在终端上。 所以我的猜测是“printf”正在进行系统调用并使我的消息被发送而不是等待(我认为)发送内核超时。
问题是“printf”的作用以及我如何模仿它以增加I / O的数量。
编辑2:(更多信息)
我的服务器在一个线程中接收请求并在另一个线程中响应。我正在使用pthread-s的线程池来接收和发送。然而,表现并不差......
当我在一个线程中执行相同的算法(未定义MULTITHREAD)以便recvs和发送都在同一个工作线程中时,我的应用程序运行大约好10%。
奇怪的是,当我使用单独的线程(工作和操作)但在任何操作中包含printf时,性能会提高(是的,加注 - 而不是下降)大约20%。我的printfs通过SSH。(*)
(数据包分析显示了大约100微秒的ACK响应延迟(不是单独的ACK)。这种延迟不会发生在printfs上,也不会发生在单线程模式下。似乎SSH触发了TCP堆栈中的某些内容。)
我尝试在每次recv()之后使用TCP_QUICKACK选项,但性能下降了!(**) 我正在使用Centos7。应用程序非常并发 - 它是SMB服务器。
算法如下: 一个线程使用epoll_wait()获取消息,然后执行第一个工作线程,该线程解析消息并启动操作线程(创建/读/写等)。
主要帖子:
static void mainThreadBodySocketTransport(CSTransport * transport)
{
struct epoll_event e;
int res;
while (true)
{
void * context = NULL; /* to pass to thread */
res = epoll_wait(transport->epoll, &e, 1, (int)*60 * 12 * 1000));
if (res == 1)
{
*context = e.data.ptr;
}
/* wrapper to execute the worker thread */
cmThreadPoolExecute(transport->threadPool, context);
}
}
工作线程
static void threadBodySocketTransport(void * context)
{
msgBuffer * message;
message = parseMSG(context);
switch (message->cmd)
{
case WRITE:
doWriteOp(message);
break;
case READ:
doReadOp(message);
break;
case CREATE:
doCreateOp(message);
break;
}
}
void doWriteOp(msgBuffer * message)
{
#ifdef MULTITHREAD
/* wrapper to execute the worker thread */
cmThreadPoolExecute(threadPoolWrite, (void *)message);
#else
/* write to file */
threadBodyWrite(message);
#endif
}
操作主题
static void threadBodyWrite(void * context)
{
msgBuffer * message = (msgBuffer *)context;
int fd;
.
.(get the fd)
.
/* printf("w\n");*/
write(fd, message->write.data , message->write.len);
sendResponse(message->cmd, true);
}
pthread create
void threadStart(SYThread *taskIdPtr, void (*startpoint)(void), NQ_BOOL background)
{
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(taskIdPtr, &attr, (void * (*)(void *))startpoint, NULL)
pthread_attr_destroy(&attr);
}
也许我需要使用不同的线程属性??
请帮助。
感谢。