@@ -473,14 +473,18 @@ const Object = struct {
473
473
/// objects remaining in the cache will be freed when the cache itself is freed.
474
474
const ObjectCache = struct {
475
475
objects : std .AutoHashMapUnmanaged (u64 , CacheEntry ) = .empty ,
476
- lru_nodes : LruList = .{},
476
+ lru_nodes : std.DoublyLinkedList = .{},
477
+ lru_nodes_len : usize = 0 ,
477
478
byte_size : usize = 0 ,
478
479
479
480
const max_byte_size = 128 * 1024 * 1024 ; // 128MiB
480
481
/// A list of offsets stored in the cache, with the most recently used
481
482
/// entries at the end.
482
- const LruList = std .DoublyLinkedList (u64 );
483
- const CacheEntry = struct { object : Object , lru_node : * LruList .Node };
483
+ const LruListNode = struct {
484
+ data : u64 ,
485
+ node : std.DoublyLinkedList.Node ,
486
+ };
487
+ const CacheEntry = struct { object : Object , lru_node : * LruListNode };
484
488
485
489
fn deinit (cache : * ObjectCache , allocator : Allocator ) void {
486
490
var object_iterator = cache .objects .iterator ();
@@ -496,8 +500,8 @@ const ObjectCache = struct {
496
500
/// position if it is present.
497
501
fn get (cache : * ObjectCache , offset : u64 ) ? Object {
498
502
if (cache .objects .get (offset )) | entry | {
499
- cache .lru_nodes .remove (entry .lru_node );
500
- cache .lru_nodes .append (entry .lru_node );
503
+ cache .lru_nodes .remove (& entry .lru_node . node );
504
+ cache .lru_nodes .append (& entry .lru_node . node );
501
505
return entry .object ;
502
506
} else {
503
507
return null ;
@@ -510,26 +514,29 @@ const ObjectCache = struct {
510
514
/// will not be evicted before the next call to `put` or `deinit` even if
511
515
/// it exceeds the maximum cache size.
512
516
fn put (cache : * ObjectCache , allocator : Allocator , offset : u64 , object : Object ) ! void {
513
- const lru_node = try allocator .create (LruList . Node );
517
+ const lru_node = try allocator .create (LruListNode );
514
518
errdefer allocator .destroy (lru_node );
515
519
lru_node .data = offset ;
516
520
517
521
const gop = try cache .objects .getOrPut (allocator , offset );
518
522
if (gop .found_existing ) {
519
523
cache .byte_size -= gop .value_ptr .object .data .len ;
520
- cache .lru_nodes .remove (gop .value_ptr .lru_node );
524
+ cache .lru_nodes .remove (& gop .value_ptr .lru_node .node );
525
+ cache .lru_nodes_len -= 1 ;
521
526
allocator .destroy (gop .value_ptr .lru_node );
522
527
allocator .free (gop .value_ptr .object .data );
523
528
}
524
529
gop .value_ptr .* = .{ .object = object , .lru_node = lru_node };
525
530
cache .byte_size += object .data .len ;
526
- cache .lru_nodes .append (lru_node );
531
+ cache .lru_nodes .append (& lru_node .node );
532
+ cache .lru_nodes_len += 1 ;
527
533
528
- while (cache .byte_size > max_byte_size and cache .lru_nodes . len > 1 ) {
534
+ while (cache .byte_size > max_byte_size and cache .lru_nodes_len > 1 ) {
529
535
// The > 1 check is to make sure that we don't evict the most
530
536
// recently added node, even if it by itself happens to exceed the
531
537
// maximum size of the cache.
532
- const evict_node = cache .lru_nodes .popFirst ().? ;
538
+ const evict_node : * LruListNode = @fieldParentPtr ("node" , cache .lru_nodes .popFirst ().? );
539
+ cache .lru_nodes_len -= 1 ;
533
540
const evict_offset = evict_node .data ;
534
541
allocator .destroy (evict_node );
535
542
const evict_object = cache .objects .get (evict_offset ).? .object ;
0 commit comments