转换三个 uint32_t 以在 C 中生成唯一键的更快方法

Faster way to convert three uint32_t to generate a unique key in C

我有三个 uint32_t,当它们组合在一起时,它们会生成一个唯一的密钥。我必须执行大约 100M 或更多的操作,并且可能一天执行几次,并将其存储在键值数据库中。我想将密钥保持在尽可能少的字节数上。我正在按照以下方式进行操作,但我很好奇是否有更快的方法。

char *key = xmalloc(snprintf(NULL, 0, "%" PRIu32 "-%" PRIu32 "-%" PRIu32,num1,num2,num3) + 1);   
sprintf(key, "%" PRIu32 "-%" PRIu32 "-%" PRIu32, num1,num2,num3);
  • 转换为十进制表示的成本相当高。如果您使用十六进制,您可以获得更快的转换:

      sprintf(key, "%" PRIx32 "-%" PRIx32 "-%" PRIx32, num1, num2, num3);
    
  • 如@AKX 所述,使用固定大小的缓冲区。由于字符串(可能)被复制到数据库中,因此您不必担心它在数据库中占用的 space 比必要的多:

      char key[32];
      snprintf(key, sizeof(key), "%" PRIx32 "-%" PRIx32 "-%" PRIx32, num1, num2, num3);
    

    数据库引擎不知道您过度分配了缓冲区。它将根据字符串的实际长度而不是缓冲区的大小分配自己的内存。

  • 实现您自己的十六进制格式。 snprintf 需要解析其格式字符串并在运行时根据参数列表对其进行解释。对于像您这样的任务,这具有不可忽略的开销。相反,您可以自己进行专用于您的任务的 int32 到十六进制的转换。我会使用 "abcdefghijklmnop" 作为数字而不是传统的 "0123456789abcdef".

  • 您的键值数据库是否需要文本编码键?如果没有,您可以尝试对密钥进行二进制编码(例如,查看 SQLite4 varint encoding 以获得灵感)。

如果您更喜欢文本编码的密钥,我会进一步采用 Yakov 的建议(好吧,两步)并使用 base64 编码而不是十六进制。这样你就可以将 6 位打包成一个字符,而不是只有 4 个。

该实现将有多个移位加查找 table。我打赌它会比 printf.