- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在为我的一个类(class)编写一个文件系统。这个函数大大降低了我的性能,我不明白为什么。我盯着这段代码看的时间太长了,我可能遗漏了一些非常明显的东西。有人明白为什么这个功能运行得这么慢吗?
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
还是我没有正确理解输出?
感谢您的帮助。
最佳答案
您一直盯着这段代码并对 gprof
输出感到困惑这一事实让您成为了好伙伴,因为 gprof
和它教授的概念仅适用于没有 I/O 的小型学术规模程序。 Here's the method I use.
一些有用的帖子的摘录已被删除,给出了一些关于分析的神话:
程序计数器采样很有用。
它只有在你有一个不必要的热点瓶颈时才有用,比如大量标量值的冒泡排序。例如,一旦将其更改为使用字符串比较的排序,它仍然是一个瓶颈,但程序计数器采样不会看到它,因为现在热点在字符串比较中。另一方面,如果要对 extended 程序计数器(调用堆栈)进行采样,则会清楚地显示调用字符串比较的点(排序循环)。 事实上,gprof 试图弥补仅 pc 采样的局限性。
阻塞时不需要采集样本
这个神话的原因有两个:1)当程序等待时 PC 采样是没有意义的,以及 2)对计时准确性的关注。然而,对于 (1),程序很可能正在等待它请求的某些东西,例如文件 I/O,您需要知道,以及哪些堆栈示例显示。 (很明显,您希望在等待用户输入时排除样本。)对于 (2),如果程序只是因为与其他进程竞争而等待,那么它可能在运行时以相当随机的方式发生。因此,虽然程序可能需要更长的时间,但这不会对重要的统计数据产生很大影响,即语句在堆栈上的时间百分比。
语句或函数调用的计数很有用。
假设您知道某个函数已被调用 1000 次。你能从中看出它花费了多少时间吗?您还需要知道平均运行需要多长时间,将其乘以计数,然后除以总时间。平均调用时间可能从纳秒到秒不等,因此仅靠计数并不能说明什么。如果有堆栈样本,则例程或任何语句的成本只是它所在的样本的一小部分。如果可以使例程或语句不花时间,那么这部分时间原则上可以节省整个时间,因此这是与性能最直接的关系。
还有更多的来源。
关于c - 功能运行太慢......我不明白为什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20308078/
我是一名优秀的程序员,十分优秀!