简体   繁体   English

减少 memory 和 CPU 使用率

[英]Reduce memory and CPU usage

In a system where I'm limited with CPU power and memory, I was wondering if I can use this trick (which doesn't work) to gain some performance.在我受限于 CPU 功率和 memory 的系统中,我想知道我是否可以使用这个技巧(它不起作用)来获得一些性能。 The goal is to reduce memory and CPU usage.目标是减少 memory 和 CPU 使用率。

Let's say I allocated 6*sizeof(int) at some point during runtime and I don't need the first value of the pointer later anymore.假设我在运行时的某个时刻分配了6*sizeof(int) ,以后不再需要指针的第一个值。 At this point I will have a portion of that allocated memory, more specifically 1*sizeof(int) that the program doesn't need and cannot use.在这一点上,我将分配 memory 的一部分,更具体地说是程序不需要且无法使用的1*sizeof(int)

So my first idea is to allocate 5*sizeof(int) in another pointer, move the data through and free the first one, but by doing this I will have to use more memory for a short duration (2 pointers) and by moving data from addresses to other addresses I'll lose CPU performance.所以我的第一个想法是在另一个指针中分配5*sizeof(int) ,移动数据并释放第一个,但是这样做我将不得不在短时间内使用更多 memory (2个指针)并通过移动数据从地址到其他地址我会失去 CPU 性能。

My second idea was better in theory but it didn't work, instead of moving data, I can directly allocate the second pointer to the second address of the first pointer, and by doing that, I didn't have to use the CPU to move data and my new pointer is working fine until I free the old one... Basically this is the code I tried:我的第二个想法理论上更好但它没有工作,而不是移动数据,我可以直接将第二个指针分配给第一个指针的第二个地址,这样做,我不必使用CPU来移动数据并且我的新指针工作正常,直到我释放旧指针......基本上这是我尝试过的代码:

void Print(int* k, int size)
{
    for(int i=0;i<size;i++)
    {
        printf("%d, ",k[i]);
    }
}

void Scan(int* k, int size)
{
    for(int i=0;i<size;i++)
    {
        k[i] = i+1;
    }
}

int main() {
    int* a = malloc(6 * sizeof(int));
    Scan(a,6);
    Print(a, 6);
    int* p = malloc(5 * sizeof(int));
    p = a+1;
    free(a);
    Print(p, 5);
    
    return 0;
}

Is there a way to make it work please?请问有没有办法让它工作?

That won't work -- you have to call free() on the exact pointer that was previously returned by malloc() , and the call to free() will always free the entire amount of memory that was previously allocated by the malloc() call.那是行不通的——您必须在malloc()先前返回的确切指针上调用free() ) ,并且对free()的调用将始终释放之前由malloc() () 分配的全部 memory malloc()调用。 Partial-frees aren't supported by malloc() and free() . malloc()free()不支持部分释放。

If you want to change the size of an existing heap allocation, you can attempt to do so by calling realloc() on it.如果要更改现有堆分配的大小,可以尝试通过调用realloc()来实现。 Be aware that realloc() is tricky to use correctly, though (eg it returns a new pointer-value that you should use instead of the old one).请注意, realloc()很难正确使用(例如,它返回一个新的指针值,您应该使用它而不是旧的指针值)。 eg if you wanted to remove the first int from front of your 6-int heap-allocation, you'd need to copy each of the 5 following ints over the int that was before it, then do a = realloc(a, 5*sizeof(int)) .例如,如果您想从 6-int 堆分配前面删除第一个int ,则需要将以下 5 个ints中的每一个复制到它之前的int上,然后执行a = realloc(a, 5*sizeof(int)) Whether doing that would actually save you a measurable amount of RAM or CPU usage is an open question (personally I doubt it, unless it's actually several thousand or more ints you want to remove, not just one).这样做是否真的会为您节省大量的 RAM 或 CPU 使用率是一个悬而未决的问题(我个人对此表示怀疑,除非它实际上是您要删除的数千个或更多ints ,而不仅仅是一个)。

Probably your best bet is to give up on fancy separate heap-allocations and just use pointer-math to get the job done:可能你最好的选择是放弃花哨的单独堆分配,只使用指针数学来完成工作:

int main() {
    int* a = malloc(6 * sizeof(int));
    Scan(a,6);
    Print(a, 6);

    Print(a+1, 5);

    free(a);
    return 0;
}

... and for the example code given, you don't need the first heap-allocation either, so you can reduce your program's complexity and memory usage by going with a stack-array instead: ...对于给出的示例代码,您也不需要第一个堆分配,因此您可以通过使用堆栈数组来降低程序的复杂性和 memory 的使用:

int main() {
    int a[6];
    Scan(a,6);
    Print(a, 6);
    Print(a+1, 5);
    return 0;
}

TL;DR: No, there is no way to make it work (using the system's allocator). TL;DR:不,没有办法让它工作(使用系统的分配器)。


free() neither has nor wants any awareness of pointers to or into an allocated block, except only the copy it receives (by value) as its first parameter. free()既不知道也不想要知道指向或指向分配块的指针,除了它接收的副本(按值)作为其第一个参数。 And it works only in terms of whole blocks previously allocated by malloc() or calloc() .它仅适用于先前由malloc()calloc()分配的整个块。 Therefore, you cannot use free to reduce a memory allocation.因此,您不能使用 free 来减少 memory 分配。

You can use realloc() to shrink a memory allocation, but可以使用realloc()缩小 memory 分配,但是

  1. The memory is released from the high-address end of the allocation, contrary to what you want. memory 从分配的高地址端释放,与您想要的相反。 You would need to shift the data you want to keep to the beginning of the array.您需要将要保留的数据转移到数组的开头。

  2. The change is not necessarily performed in place, even when you reduce the size (as opposed to increasing it).即使您减小大小(而不是增加大小),也不一定会就地执行更改。 That means you might be even worse off with realloc than with the first strategy you described.这意味着使用realloc可能比使用您描述的第一个策略更糟糕。 You could end up with the same temporary use of extra memory and the same cost to copy, plus the cost to shift the array contents as described in (1).您最终可能会临时使用额外的 memory 和相同的复制成本,再加上 (1) 中描述的移动数组内容的成本。

  3. It's probably not useful to release an int -size portion of a six- int -sized region anyway, because allocators don't usually operate with fine enough granularity for that to make a difference.无论如何,释放 6 个int大小区域的int大小部分可能没有用,因为分配器通常不会以足够精细的粒度进行操作以产生影响。 You can reduce the formal allocation size, but that probably would not, in practice, make any additional space available for the program to allocate.您可以减少正式的分配大小,但实际上这可能不会为程序分配任何额外的空间。

breaking this code down分解这段代码

int main() {
    int* a = malloc(6 * sizeof(int)); // allocate 6 ints
    Scan(a,6);
    Print(a, 6);
    int* p = malloc(5 * sizeof(int)); // allocate 5 ints
    p = a+1; // overwrite the pointer to those 5 ints ==> leak
    free(a); // release the memory the p points at
    Print(p, 5); // undeifined behavior
    
    return 0;
}

this will work tho这会起作用的

int main() {
    int* a = malloc(6 * sizeof(int));
    Scan(a,6);
    Print(a, 6);
    int* p = a + 1; // new pointer to malloced memory that skips the first entry
    Print(p, 5);
    
    return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM