功能运行太慢...我不明白为啥

Posted

技术标签:

【中文标题】功能运行太慢...我不明白为啥【英文标题】:Function going too slowly...i can't see why功能运行太慢...我不明白为什么 【发布时间】:2013-12-01 02:31:07 【问题描述】:

我正在为我的一个课程编写一个文件系统。这个功能大大降低了我的表现,我不知道为什么。我一直盯着这段代码太久了,我可能遗漏了一些非常明显的东西。有人知道为什么这个功能会这么慢吗?

int getFreeDataBlock(struct disk *d, unsigned int dataBlockNumber)

    if (d == NULL)
    
        fprintf(stderr, "Invalid disk pointer to getFreeDataBlock()\n");
        errorCheck();
        return -1;
    

    // Allocate a buffer
    char *buffer = (char *) malloc(d->blockSize * sizeof(char));
    if (buffer == NULL)
    
        fprintf(stderr, "Out of memory.\n");
        errorCheck();
        return -1;
    

    do 
        // Read a block from the disk
        diskread(d, buffer, dataBlockNumber);

        // Cast to appropriate struct
        struct listDataBlock *block = (struct listDataBlock *) buffer;

        unsigned int i;
        for (i = 0; i < DATABLOCK_FREE_SLOT_LENGTH; ++i)
        
            // We are in the last datalisting block...and out of slots...break
            if (block->listOfFreeBlocks[i] == -2)
            
                break;
            

            if (block->listOfFreeBlocks[i] != -1)
            
                int returnValue = block->listOfFreeBlocks[i];

                // MARK THIS AS USED NOW
                block->listOfFreeBlocks[i] = -1;
                diskwriteNoSync(d, buffer, dataBlockNumber);

                // No memory leaks
                free(buffer);
                return returnValue;
            
        

        // Ok, nothing in this data block, move to next
        dataBlockNumber = block->nextDataBlock;
     while (dataBlockNumber != -1);

    // Nope, didn't find any...disk must be full
    free(buffer);
    fprintf(stderr, "DISK IS FULL\n");
    errorCheck();
    return -1;

正如您从 gprof 中看到的那样,diskread()diskwriteNoSync() 都需要大量时间?

  %   cumulative   self              self     total          
 time   seconds   seconds    calls  ms/call  ms/call  name    
 99.45     12.25    12.25     2051     5.97     5.99  getFreeDataBlock
  0.24     12.28     0.03  2220903     0.00     0.00  diskread
  0.24     12.31     0.03                             threadFunc
  0.08     12.32     0.01     2048     0.00     6.00  writeHelper
  0.00     12.32     0.00     6154     0.00     0.00  diskwriteNoSync
  0.00     12.32     0.00     2053     0.00     0.00  validatePath

还是我没有正确理解输出?

感谢您的帮助。

【问题讨论】:

好吧,你有一个do 循环(运行次数未知),其中包含一个for 循环,该循环最多运行DATABLOCK_FREE_SLOT_LENGTH 次(DATABLOCK_FREE_SLOT_LENGTH 的值是多少? ) 内部循环 I/O 内部正在发生(diskreaddiskwriteNoSync)。相对于 CPU 时间,I/O 需要大量时间。这就是我要看的地方。 是的,在喝了一杯 espresso 之后,我意识到它实际上只是在 FOR 循环中为大量磁盘块执行 1023 次所需的时间……所以 I/O 本身就没有了t 的问题,但我在做什么。重新编写了我的磁盘块实现,它现在正在运行。 【参考方案1】:

您一直盯着这段代码,对gprof 的输出感到困惑,这让您有了很好的陪伴,因为gprof 和用它教授的概念只适用于很少的学术规模的程序,没有输入/输出。 Here's the method I use.

一些有用帖子的摘录已被删除,给出了一些关于分析的神话:

程序计数器采样很有用。 仅当您有不必要的热点瓶颈时才有用,例如大量标量值的冒泡排序。例如,一旦您将其更改为使用字符串比较的排序,它仍然是一个瓶颈,但程序计数器采样不会看到它,因为现在热点在字符串比较中。另一方面,如果要对 extended 程序计数器(调用堆栈)进行采样,则会清楚地显示调用 string-compare 的点,即排序循环。 事实上,gprof 是为了弥补仅 pc 采样的局限性。

阻塞时无需采集样本 这个神话的原因有两个:1)当程序等待时,PC 采样是没有意义的,2)对时间准确性的关注。但是,对于 (1),程序很可能正在等待它要求的某些东西,例如文件 I/O,您需要知道,以及哪些堆栈样本显示。 (显然,您希望在等待用户输入时排除样本。)对于(2),如果程序只是因为与其他进程的竞争而等待,那么这可能会在它运行时以相当随机的方式发生。 因此,虽然程序可能需要更长的时间,但这不会对重要的统计数据产生很大影响,即语句在堆栈上的时间百分比。

对语句或函数调用进行计数很有用。 假设您知道一个函数已被调用 1000 次。你能从中看出它花费了多少时间吗?您还需要知道运行平均需要多长时间,将其乘以计数,然后除以总时间。平均调用时间可能从纳秒到秒不等,因此仅计数并不能说明太多。如果有堆栈样本,则例程或任何语句的成本只是它所在样本的一小部分。如果可以使例程或语句不花时间,原则上可以节省这部分时间,因此这与性能有最直接的关系。

还有更多来自哪里。

【讨论】:

以上是关于功能运行太慢...我不明白为啥的主要内容,如果未能解决你的问题,请参考以下文章

为啥隐藏和显示密码功能无法正常工作?

为啥列表容器的排序功能不起作用[关闭]

为啥我们不能在 C 语言中拥有两个主要功能?

为啥弱/强之舞解决了这个强参考循环?我不明白

错误:list.remove(x):x 不在列表中,我不明白为啥

DCOMCNFG:为啥 dll 不显示?