我刚刚回顾了一些非常糟糕的代码 - 通过创建一个新线程来在串行端口上发送消息的代码,以便在发送的每条消息的新线程中打包和组装消息.是的,对于创建pthread的每条消息,正确设置了位,然后线程终止.我不知道为什么有人会做这样的事情,但它提出了一个问题 - 实际创建一个线程有多少开销?
我有一块内存块,其中包含固定大小的元素,比如说100个字节,一个接一个地放入,所有内容都有相同的固定长度,所以内存看起来像这样
<element1(100 bytes)><element2(100 bytes)><element3(100 bytes)>...
Run Code Online (Sandbox Code Playgroud)
在某些情况下,我需要确定某个元素的所有字节是否都设置为0字节,因为它具有特殊含义(我没有说这是一个好主意,但这就是我所处的情况).
问题是,我该如何有效地做到这一点.进一步:有一个简单的功能来做到这一点.为了将字节设置为零,我可以使用memset或bzero,但我不知道检查零的任何函数.
目前我正在使用循环进行检查
char *elementStart = memoryBlock + elementNr*fixedElementSize;
bool special = true;
for ( size_t curByteNr=0; curByteNr<fixedElementSize; ++curByteNr )
{
special &= (*(elementStart+curByteNr)) == 0;
}
Run Code Online (Sandbox Code Playgroud)
当然,我可以使用更大的偏移量循环,并使用mword或其他更适合的更大类型一次检查几个字节.我想这样会很有效率,但我想知道是否有一种功能可以减轻我的负担.
建议功能:
我正在寻找一种更快的方法来完成这个:
int is_empty(char * buf, int size)
{
int i;
for(i = 0; i < size; i++) {
if(buf[i] != 0) return 0;
}
return 1;
}
Run Code Online (Sandbox Code Playgroud)
我意识到我正在寻找一种微观优化,除非在极端情况下,但我知道存在更快的方法,我很好奇它是什么.
如果我有一个unsigned char *data指针,我想检查size_t length该指针的数据是否为NULL,那么最快的方法是什么?换句话说,确保内存区域为空白的最快方法是什么?
我在iOS中实现,所以你可以假设iOS框架可用,如果有帮助的话.另一方面,简单的C方法(memcmp等)也可以.
注意,我不是要清除内存,而是试图确认它已经很清楚了(我试图找出某些位图数据中是否有任何内容,如果有帮助的话).例如,我认为以下内容可行,但我尚未尝试过:
- BOOL data:(unsigned char *)data isNullToLength:(size_t)length {
unsigned char tester[length] = {};
memset(tester, 0, length);
if (memcmp(tester, data, length) != 0) {
return NO;
}
return YES;
}
Run Code Online (Sandbox Code Playgroud)
我宁愿不创建一个测试器阵列,因为源数据可能非常大,我宁愿避免为测试分配内存,即使是暂时的.但我可能在那里过于保守.
感谢大家对下面的好评.我决定创建一个测试应用程序,看看它们是如何表现的,答案让我感到惊讶,所以我想我会分享它们.首先,我将向您展示我使用的算法版本(在某些情况下,它们与提议的算法略有不同),然后我将分享该领域的一些结果.
首先,我创建了一些示例数据:
size_t length = 1024 * 768;
unsigned char *data = (unsigned char *)calloc(sizeof(unsigned char), (unsigned long)length);
int i;
int count;
long check;
int loop = 5000;
Run Code Online (Sandbox Code Playgroud)
每个测试由循环运行loop时间组成.在循环期间,一些随机数据被添加到data字节流中以及从字节流中移除.请注意,实际上没有数据添加的一半时间,因此测试不应该找到任何非零数据的一半时间.请注意,该 …
考虑以下小功能:
void foo(int* iptr) {
iptr[10] = 1;
__asm__ volatile ("nop"::"r"(iptr):);
iptr[10] = 2;
}
Run Code Online (Sandbox Code Playgroud)
使用gcc,它将编译为:
foo:
nop
mov DWORD PTR [rdi+40], 2
ret
Run Code Online (Sandbox Code Playgroud)
请特别注意,即在第一次写iptr,iptr[10] = 1根本不会发生:内联汇编nop是在函数的第一件事,只有最后写2(会出现ASM呼叫后)。显然,编译器决定只需要提供其iptr 自身值的最新版本,而不需要提供其指向的内存。
我可以告诉编译器,内存必须是最新的memory,就像这样:
void foo(int* iptr) {
iptr[10] = 1;
__asm__ volatile ("nop"::"r"(iptr):"memory");
iptr[10] = 2;
}
Run Code Online (Sandbox Code Playgroud)
结果为预期的代码:
foo:
mov DWORD PTR [rdi+40], 1
nop
mov DWORD PTR [rdi+40], 2
ret
Run Code Online (Sandbox Code Playgroud)
但是,这太强了,因为它告诉编译器必须写入所有内存。例如,在以下功能中:
void foo2(int* iptr, long* …Run Code Online (Sandbox Code Playgroud) c ×3
c++ ×2
assembly ×1
buffer ×1
clang ×1
cocoa ×1
gcc ×1
ios ×1
nsdata ×1
objective-c ×1
optimization ×1
performance ×1
posix ×1
pthreads ×1