--- freem/src/global_bltin.c 2025/04/11 14:21:03 1.17
+++ freem/src/global_bltin.c 2025/04/11 16:23:18 1.18
@@ -1,5 +1,5 @@
/*
- * $Id: global_bltin.c,v 1.17 2025/04/11 14:21:03 snw Exp $
+ * $Id: global_bltin.c,v 1.18 2025/04/11 16:23:18 snw Exp $
* freem database engine
*
*
@@ -24,6 +24,9 @@
* along with FreeM. If not, see .
*
* $Log: global_bltin.c,v $
+ * Revision 1.18 2025/04/11 16:23:18 snw
+ * Avoid re-reading the same block consecutively when possible
+ *
* Revision 1.17 2025/04/11 14:21:03 snw
* Make all but one of the read/write calls in global_bltin use gbl_read_block or gbl_write_block
*
@@ -323,7 +326,7 @@ int gbl_write_header(global_handle *g, g
return FALSE;
}
- if (g->locked == FALSE) gbl_lock (g, 1);
+ gbl_lock (g, 1);
old_position = lseek (g->fd, 0, SEEK_CUR);
lseek (g->fd, 0, SEEK_SET);
@@ -333,7 +336,7 @@ int gbl_write_header(global_handle *g, g
}
lseek (g->fd, old_position, SEEK_SET);
- if (g->locked == TRUE) gbl_unlock (g);
+ gbl_unlock (g);
gbl_read_header (g, &g->header);
@@ -445,9 +448,13 @@ short gbl_open(global_handle *g, short a
}
else {
g->opened = TRUE;
- result = gbl_read_header (g, &g->header);
+ result = gbl_read_header (g, &g->header);
if (result == GBL_HDR_OK) {
+ /* initialize last_block_accessed cache */
+ g->last_block_accessed = (char *) calloc (g->header.block_size, sizeof (char));
+ NULLPTRCHK(g->last_block_accessed,"gbl_open");
+
g->opened = TRUE;
}
else {
@@ -479,6 +486,7 @@ short gbl_open(global_handle *g, short a
int gbl_read_block(global_handle *g, unsigned long blocknum, char *block)
{
+ struct stat gstat;
unsigned long hdr_offset;
hdr_offset = sizeof (global_header);
@@ -486,13 +494,38 @@ int gbl_read_block(global_handle *g, uns
return FALSE;
}
- gbl_lock (g, 1);
- lseek (g->fd, hdr_offset + ((long) blocknum * (long) (g->header.block_size)), SEEK_SET);
- read (g->fd, block, g->header.block_size);
- g->last_block = blocknum;
g->use_count++;
- g->read_ops++;
- gbl_unlock (g);
+
+ fstat (g->fd, &gstat);
+ if (!g->locked) gbl_lock (g, 1);
+
+
+ if ((g->last_block == blocknum) &&
+ (g->have_cached_block) &&
+ (g->cached_block_num == blocknum) &&
+ (gstat.st_mtime < g->last_read_time)) {
+ /* the global has not been modified since the last read; grab from memory */
+ g->memory_reads++;
+ g->last_read_time = time (0L);
+ memcpy (block, g->last_block_accessed, g->header.block_size);
+ }
+ else {
+ /* have to go out to disk */
+ lseek (g->fd, hdr_offset + ((long) blocknum * (long) (g->header.block_size)), SEEK_SET);
+ read (g->fd, block, g->header.block_size);
+
+ /* update cache */
+ memcpy (g->last_block_accessed, block, g->header.block_size);
+ g->have_cached_block = TRUE;
+ g->last_read_time = time (0L);
+ g->cached_block_num = blocknum;
+
+ g->last_block = blocknum;
+ g->use_count++;
+ g->read_ops++;
+ }
+
+ if (g->locked) gbl_unlock (g);
return TRUE;
} /* gbl_read_block() */
@@ -507,9 +540,7 @@ int gbl_write_block(global_handle *g, un
return FALSE;
}
- if (!g->locked) {
- gbl_lock (g, 1);
- }
+ gbl_lock (g, 1);
for (;;) {
@@ -528,11 +559,8 @@ int gbl_write_block(global_handle *g, un
}
- gbl_update_tid (g);
-
- if (g->locked) {
- gbl_unlock (g);
- }
+ gbl_update_tid (g);
+ gbl_unlock (g);
return TRUE;
}
@@ -578,6 +606,7 @@ global_handle *gbl_handle(char *key)
g->use_count = 1;
g->locked = FALSE;
g->age = time (0L);
+ g->last_read_time = 0;
g->last_block = 0;
g->opened = FALSE;
g->fd = 0;
@@ -586,6 +615,9 @@ global_handle *gbl_handle(char *key)
g->cache_hits = 0;
g->read_ops = 0;
g->write_ops = 0;
+ g->memory_reads = 0;
+ g->have_cached_block = FALSE;
+ g->last_block_accessed = NULL;
strcpy (g->global_name, global_name);
gbl_path (key, g->global_path);
@@ -3716,25 +3748,29 @@ void gbl_dump_stat(void)
int hit_pct;
unsigned long access_total;
unsigned long hit_total;
-
+ unsigned long mem_reads_total;
+
+ mem_reads_total = 0;
printf ("\r\nFreeM Global Statistics [PID %d]\r\n\r\n", pid);
- printf ("%-20s%-10s%-10s%-10s%-12s%-20s%-10s%s\r\n", "GLOBAL", "USECT", "READS", "WRITES", "SLOW PTHCT", "AGE", "LAST BLK", "FILE");
- printf ("%-20s%-10s%-10s%-10s%-12s%-20s%-10s%s\r\n", "======", "=====", "=====", "======", "==========", "===", "========", "====");
+ printf ("%-20s%-10s%-10s%-10s%-10s%-12s%-20s%-10s%s\r\n", "GLOBAL", "USECT", "READS", "WRITES", "MEMREADS", "SLOW PTHCT", "AGE", "LAST BLK", "FILE");
+ printf ("%-20s%-10s%-10s%-10s%-10s%-12s%-20s%-10s%s\r\n", "======", "=====", "=====", "======", "========", "==========", "===", "========", "====");
access_total = 0;
ct = 0;
for (g = global_handles_head; g != NULL; g = g->next) {
- printf ("%-20s%-10ld%-10ld%-10ld%-12ld%-20ld%-10ld%s\r\n",
+ printf ("%-20s%-10ld%-10ld%-10ld%-10ld%-12ld%-20ld%-10ld%s\r\n",
g->global_name,
g->use_count,
g->read_ops,
g->write_ops,
+ g->memory_reads,
g->cache_misses,
g->age,
g->last_block,
g->global_path);
ct++;
+ mem_reads_total += g->memory_reads;
access_total += g->use_count;
}
if (!ct) printf ("\r\n");
@@ -3745,5 +3781,7 @@ void gbl_dump_stat(void)
printf ("\r\nTotal accesses: %ld\r\n", access_total);
printf ("Fast path hits %ld\t(%d%%)\r\n", hit_total, hit_pct);
- printf ("Fast path misses: %ld\t(%d%%)\r\n", gbl_cache_misses, miss_pct);
+ printf ("Fast path misses: %ld\t(%d%%)\r\n", gbl_cache_misses, miss_pct);
+ printf ("Disk reads avoided: %ld\r\n", mem_reads_total);
+
}