perf(io): avoid reopening v2 files during indexing
All checks were successful
Build / build-script (push) Successful in 14s
Build / cmake-build (push) Successful in 41s
Build / unit-tests (push) Successful in 25s

This commit is contained in:
2026-06-17 11:29:29 -05:00
parent 64256f93f2
commit 17e468d649
3 changed files with 96 additions and 8 deletions

View File

@@ -225,6 +225,29 @@ static bool read_file_prefix(const char *path, uint8_t *prefix, size_t prefix_ca
return true;
}
static bool open_file_with_prefix(const char *path, FILE **out_file, uint8_t *prefix, size_t prefix_capacity, size_t *out_size)
{
FILE *file = NULL;
size_t size = 0u;
if (!path || !out_file || !prefix || prefix_capacity == 0u || !out_size)
return false;
*out_file = NULL;
*out_size = 0u;
prefix[0] = 0u;
file = IKV_FOPEN(path, "rb");
if (!file)
return false;
size = IKV_FREAD(prefix, 1u, prefix_capacity - 1u, file);
prefix[size] = 0u;
*out_file = file;
*out_size = size;
return true;
}
static char *ikv_strdup(const char *s)
{
if (!s)
@@ -2279,16 +2302,38 @@ ikv_node_t *ikv_parse_string_version(const char *src, ikv_version_t version)
ikv_node_t *ikv_parse_file(const char *path)
{
FILE *file = NULL;
uint8_t prefix[16] = {0};
size_t prefix_size = 0u;
ikv_version_t version = IKV_VERSION_UNKNOWN;
if (!read_file_prefix(path, prefix, sizeof(prefix), &prefix_size))
if (!open_file_with_prefix(path, &file, prefix, sizeof(prefix), &prefix_size))
return NULL;
version = ikv_detect_binary_version(prefix, prefix_size);
if (version != IKV_VERSION_UNKNOWN)
{
ikv_node_t *root = NULL;
if (version == IKV_VERSION_2)
{
if (IKV_FSEEK(file, 0L, SEEK_SET) != 0)
{
IKV_FCLOSE(file);
return NULL;
}
root = ikv2_parse_binary_stream(file);
if (!root)
IKV_FCLOSE(file);
return root;
}
IKV_FCLOSE(file);
return ikvb_parse_file_version(path, version);
}
IKV_FCLOSE(file);
version = ikv_detect_text_version((const char *)prefix);
if (version == IKV_VERSION_UNKNOWN)
@@ -2355,10 +2400,38 @@ ikv_node_t *ikvb_parse_memory_version(const void *data, size_t size, ikv_version
ikv_node_t *ikvb_parse_file(const char *path)
{
FILE *file = NULL;
uint8_t prefix[16] = {0};
size_t prefix_size = 0u;
ikv_version_t version = ikv_detect_file_version(path, true);
if (version == IKV_VERSION_UNKNOWN)
if (!open_file_with_prefix(path, &file, prefix, sizeof(prefix), &prefix_size))
return NULL;
version = ikv_detect_binary_version(prefix, prefix_size);
if (version == IKV_VERSION_UNKNOWN)
{
IKV_FCLOSE(file);
return NULL;
}
if (version == IKV_VERSION_2)
{
ikv_node_t *root = NULL;
if (IKV_FSEEK(file, 0L, SEEK_SET) != 0)
{
IKV_FCLOSE(file);
return NULL;
}
root = ikv2_parse_binary_stream(file);
if (!root)
IKV_FCLOSE(file);
return root;
}
IKV_FCLOSE(file);
return ikvb_parse_file_version(path, version);
}

View File

@@ -774,9 +774,8 @@ static bool ikv2_write_binary_file(const char *path, const ikv_node_t *root)
return ok;
}
static ikv_node_t *ikv2_parse_binary_file(const char *path)
ikv_node_t *ikv2_parse_binary_stream(FILE *file)
{
FILE *file = NULL;
uint8_t magic[4];
uint8_t kind = 0u;
uint32_t version = 0u;
@@ -788,10 +787,6 @@ static ikv_node_t *ikv2_parse_binary_file(const char *path)
long file_size_long = 0;
size_t file_size = 0u;
if (!path)
return NULL;
file = IKV_FOPEN(path, "rb");
if (!file)
return NULL;
@@ -919,6 +914,24 @@ static ikv_node_t *ikv2_parse_binary_file(const char *path)
return root;
}
static ikv_node_t *ikv2_parse_binary_file(const char *path)
{
FILE *file = NULL;
ikv_node_t *root = NULL;
if (!path)
return NULL;
file = IKV_FOPEN(path, "rb");
if (!file)
return NULL;
root = ikv2_parse_binary_stream(file);
if (!root)
IKV_FCLOSE(file);
return root;
}
static ikv_node_t *ikv2_parse_binary_memory(const void *data, size_t size)
{
uint8_t *buffer = NULL;

View File

@@ -3,3 +3,5 @@
#include "../internal/ikv_internal.h"
extern const ikv_loader_t ikv_loader_v2;
ikv_node_t *ikv2_parse_binary_stream(FILE *file);