3232#include < vespa/vespalib/data/fileheader.h>
3333#include < vespa/vespalib/gtest/gtest.h>
3434#include < vespa/vespalib/net/http/state_explorer.h>
35+ #include < vespa/vespalib/util/fake_deadline.h>
3536#include < vespa/vespalib/util/mmap_file_allocator_factory.h>
3637#include < vespa/vespalib/util/threadstackexecutor.h>
3738
@@ -300,6 +301,10 @@ class MockNearestNeighborIndex : public NearestNeighborIndex {
300301 std::vector<Neighbor> find_top_k (Stats& stats, uint32_t k, const search::tensor::BoundDistanceFunction& df,
301302 uint32_t explore_k, double exploration_slack, bool prefetch_tensors,
302303 const vespalib::Deadline& doom, double distance_threshold) const override {
304+ std::this_thread::sleep_for (1ms); // Make sure that test does not fail because it ran too fast
305+ if (doom.is_missed ()) {
306+ return {};
307+ }
303308 stats.count_computed_distance ();
304309 stats.count_visited_node ();
305310 stats.count_visited_node ();
@@ -308,7 +313,6 @@ class MockNearestNeighborIndex : public NearestNeighborIndex {
308313 (void )explore_k;
309314 (void )exploration_slack;
310315 (void )prefetch_tensors;
311- (void )doom;
312316 (void )distance_threshold;
313317 return {};
314318 }
@@ -318,6 +322,10 @@ class MockNearestNeighborIndex : public NearestNeighborIndex {
318322 uint32_t explore_k, double exploration_slack, bool prefetch_tensors,
319323 const vespalib::Deadline& doom,
320324 double distance_threshold) const override {
325+ std::this_thread::sleep_for (1ms); // Make sure that test does not fail because it ran too fast
326+ if (doom.is_missed ()) {
327+ return {};
328+ }
321329 stats.count_computed_distance ();
322330 stats.count_visited_node ();
323331 stats.count_visited_node ();
@@ -330,7 +338,6 @@ class MockNearestNeighborIndex : public NearestNeighborIndex {
330338 (void )filter;
331339 (void )low_hit_ratio;
332340 (void )exploration;
333- (void )doom;
334341 (void )distance_threshold;
335342 return {};
336343 }
@@ -1538,6 +1545,9 @@ TEST(TensorAttributeTest, NN_blueprint_collects_stats) {
15381545 }
15391546 EXPECT_EQ (1 , f.stats ().approximate_nns_distances_computed ());
15401547 EXPECT_EQ (2 , f.stats ().approximate_nns_nodes_visited ());
1548+ EXPECT_GT (f.stats ().approximate_nns_time_used (), vespalib::duration::zero ());
1549+ EXPECT_EQ (0 , f.stats ().approximate_nns_timeouts_hit ());
1550+ vespalib::duration last_approximate_nns_time_used = f.stats ().approximate_nns_time_used ();
15411551
15421552 // With filter active
15431553 {
@@ -1558,6 +1568,46 @@ TEST(TensorAttributeTest, NN_blueprint_collects_stats) {
15581568 }
15591569 EXPECT_EQ (2 , f.stats ().approximate_nns_distances_computed ());
15601570 EXPECT_EQ (4 , f.stats ().approximate_nns_nodes_visited ());
1571+ EXPECT_GT (f.stats ().approximate_nns_time_used (), last_approximate_nns_time_used);
1572+ EXPECT_EQ (0 , f.stats ().approximate_nns_timeouts_hit ());
1573+ last_approximate_nns_time_used = f.stats ().approximate_nns_time_used ();
1574+
1575+ // Using up time budget (but not hitting timeout)
1576+ {
1577+ auto bp = f.make_blueprint (true );
1578+ auto inactive_filter = GlobalFilter::create ();
1579+ EXPECT_FALSE (bp->pending_index_search ());
1580+ bp->set_global_filter (*inactive_filter, 0.6 );
1581+ EXPECT_TRUE (bp->pending_index_search ());
1582+ vespalib::FakeDeadline fake_deadline (-1s, vespalib::Deadline::Type::BUDGET);
1583+ bp->perform_index_search (fake_deadline.get_deadline (), f.stats ());
1584+ EXPECT_FALSE (bp->pending_index_search ());
1585+ }
1586+ EXPECT_EQ (2 , f.stats ().approximate_nns_distances_computed ());
1587+ EXPECT_EQ (4 , f.stats ().approximate_nns_nodes_visited ());
1588+ EXPECT_GT (f.stats ().approximate_nns_time_used (), last_approximate_nns_time_used);
1589+ EXPECT_EQ (0 , f.stats ().approximate_nns_timeouts_hit ());
1590+ last_approximate_nns_time_used = f.stats ().approximate_nns_time_used ();
1591+
1592+ // Hitting timeout
1593+ {
1594+ auto bp = f.make_blueprint (true );
1595+ auto inactive_filter = GlobalFilter::create ();
1596+ EXPECT_FALSE (bp->pending_index_search ());
1597+ bp->set_global_filter (*inactive_filter, 0.6 );
1598+ EXPECT_TRUE (bp->pending_index_search ());
1599+ vespalib::FakeDeadline fake_deadline (-1s, vespalib::Deadline::Type::TIMEOUT);
1600+ bp->perform_index_search (fake_deadline.get_deadline (), f.stats ());
1601+ EXPECT_FALSE (bp->pending_index_search ());
1602+ }
1603+ EXPECT_EQ (2 , f.stats ().approximate_nns_distances_computed ());
1604+ EXPECT_EQ (4 , f.stats ().approximate_nns_nodes_visited ());
1605+ EXPECT_GT (f.stats ().approximate_nns_time_used (), last_approximate_nns_time_used);
1606+ EXPECT_EQ (1 , f.stats ().approximate_nns_timeouts_hit ());
1607+ size_t last_approximate_nns_distances_computed = f.stats ().approximate_nns_distances_computed ();
1608+ size_t last_approximate_nns_nodes_visited = f.stats ().approximate_nns_nodes_visited ();
1609+ last_approximate_nns_time_used = f.stats ().approximate_nns_time_used ();
1610+ size_t last_approximate_nns_timeouts_hit = f.stats ().approximate_nns_timeouts_hit ();
15611611
15621612 // Hitting fallback
15631613 {
@@ -1570,8 +1620,10 @@ TEST(TensorAttributeTest, NN_blueprint_collects_stats) {
15701620 bp->set_global_filter (*strong_filter, 0.6 );
15711621 EXPECT_FALSE (bp->pending_index_search ());
15721622 }
1573- EXPECT_EQ (2 , f.stats ().approximate_nns_distances_computed ());
1574- EXPECT_EQ (4 , f.stats ().approximate_nns_nodes_visited ());
1623+ EXPECT_EQ (last_approximate_nns_distances_computed, f.stats ().approximate_nns_distances_computed ());
1624+ EXPECT_EQ (last_approximate_nns_nodes_visited, f.stats ().approximate_nns_nodes_visited ());
1625+ EXPECT_EQ (last_approximate_nns_time_used, f.stats ().approximate_nns_time_used ());
1626+ EXPECT_EQ (last_approximate_nns_timeouts_hit, f.stats ().approximate_nns_timeouts_hit ());
15751627
15761628 // Using exact search in the first place
15771629 {
@@ -1581,8 +1633,10 @@ TEST(TensorAttributeTest, NN_blueprint_collects_stats) {
15811633 bp->set_global_filter (*inactive_filter, 0.6 );
15821634 EXPECT_FALSE (bp->pending_index_search ());
15831635 }
1584- EXPECT_EQ (2 , f.stats ().approximate_nns_distances_computed ());
1585- EXPECT_EQ (4 , f.stats ().approximate_nns_nodes_visited ());
1636+ EXPECT_EQ (last_approximate_nns_distances_computed, f.stats ().approximate_nns_distances_computed ());
1637+ EXPECT_EQ (last_approximate_nns_nodes_visited, f.stats ().approximate_nns_nodes_visited ());
1638+ EXPECT_EQ (last_approximate_nns_time_used, f.stats ().approximate_nns_time_used ());
1639+ EXPECT_EQ (last_approximate_nns_timeouts_hit, f.stats ().approximate_nns_timeouts_hit ());
15861640}
15871641
15881642auto test_values = ::testing::Values(1u , 2u );
0 commit comments