File Coverage

blib/lib/AtteanX/Model/SPARQLCache.pm
Criterion Covered Total %
statement 56 64 87.5
branch 24 34 70.5
condition n/a
subroutine 9 9 100.0
pod 0 3 0.0
total 89 110 80.9


line stmt bran cond sub pod time code
1             package AtteanX::Model::SPARQLCache;
2              
3              
4 11     11   28967 use v5.14;
  11         39  
5 11     11   40 use warnings;
  11         13  
  11         250  
6              
7 11     11   39 use Moo;
  11         13  
  11         50  
8 11     11   8695 use Types::Standard qw(InstanceOf);
  11         15  
  11         69  
9 11     11   3655 use namespace::clean;
  11         15  
  11         67  
10 11     11   1530 use List::Util qw(min);
  11         19  
  11         5209  
11              
12             extends 'AtteanX::Model::SPARQL';
13             with 'MooX::Log::Any';
14              
15             has 'cache' => (
16             is => 'ro',
17             isa => InstanceOf['CHI::Driver'],
18             required => 1
19             );
20              
21             # Override the store's planner, to take back control
22             sub plans_for_algebra {
23 12     12 0 189157 return;
24             }
25              
26             sub cost_for_plan {
27 21294     21294 0 2896919 my $self = shift;
28 21294         19821 my $plan = shift;
29 21294         17604 my $planner = shift;
30             # warn $plan->as_string;
31 21294 100       166371 if ($plan->isa('Attean::Plan::Iterator')) {
    50          
    100          
    50          
32 14         18 my $cost = 2;
33 14 50       293 $cost += int(log($plan->size_estimate+1)/log(10)) if ($plan->has_size_estimate);
34 14         165 return $cost;
35             } elsif ($plan->isa('Attean::Plan::Quad')) {
36 0         0 return 100000;
37             } elsif ($plan->isa('AtteanX::Plan::SPARQLBGP')) {
38             # BGPs should have a cost proportional to the number of triple patterns,
39             # but be much more costly if they contain a cartesian product.
40 1845         4651 $self->log->trace('Estimating cost for single BGP');
41 1845 50       66587 if ($plan->children_are_variable_connected) {
42 1845         84276 return 20 * scalar(@{ $plan->children });
  1845         7065  
43             } else {
44 0         0 return 200 * scalar(@{ $plan->children });
  0         0  
45             }
46             } elsif ($plan->does('Attean::API::Plan::Join')) {
47 19435         224007 my @bgps = $plan->subpatterns_of_type('AtteanX::Plan::SPARQLBGP');
48 19435         3203949 my $countbgps = scalar(@bgps);
49 19435 100       39842 return unless $countbgps;
50             # Now, we have SPARQLBGPs as subplans, which is usually not wanted
51 19428         17574 my @children = @{ $plan->children };
  19428         33153  
52 19428 50       56243 if ($self->log->is_trace) {
53 0         0 $self->log->trace("Found $countbgps SPARQL BGP subplans, immediate children are of type " . join(', ', map {ref} @children))
  0         0  
54             }
55 19428         619205 my $cost = 0;
56             # The below code is from Attean::API::SimpleCostPlanner
57 19428 100       74620 if ($plan->isa('Attean::Plan::NestedLoopJoin')) {
    50          
58 9862         178285 my $lcost = $planner->cost_for_plan($children[0], $self);
59 9862         891926 my $rcost = $planner->cost_for_plan($children[1], $self);
60 9862 50       688453 if ($lcost == 0) {
    50          
61 0         0 $cost = $rcost;
62             } elsif ($rcost == 0) {
63 0         0 $cost = $lcost;
64             } else {
65 9862         11782 $cost = $lcost * $rcost;
66             }
67 9862 100       18226 $cost++ if ($rcost > $lcost);
68 9862 100       27795 $cost *= 10 unless ($plan->children_are_variable_connected);
69             } elsif ($plan->isa('Attean::Plan::HashJoin')) {
70 9566         21623 my $joined = $plan->children_are_variable_connected;
71 9566         561788 my $lcost = $planner->cost_for_plan($children[0], $self);
72 9566         878114 my $rcost = $planner->cost_for_plan($children[1], $self);
73 9566         685852 $cost = ($lcost + $rcost);
74 9566 100       21584 $cost++ if ($rcost > $lcost);
75 9566 50       23468 $cost *= 100 unless ($plan->children_are_variable_connected);
76             }
77 19428 50       762749 if ($cost) {
78 19428         24326 $cost *= $countbgps * 1.2;
79 19428         29884 $cost = min($cost, 1_000_000_000);
80 19428         52767 return int($cost);
81             }
82             }
83 0         0 return;
84             };
85              
86             sub is_cached {
87 3     3 0 149574 my $self = shift;
88 3         5 my $keypattern = shift;
89 3         24 return $self->cache->is_valid($keypattern);
90             }
91              
92              
93             1;