使用readahead()读取函数期间的printf()会增加I / O.为什么呢?

时间:2016-11-06 13:42:59

标签: c linux samba smb buffering

我在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);
}

也许我需要使用不同的线程属性??

请帮助。

感谢。

0 个答案:

没有答案