|
59 | 59 | #include "tpu_sync/kv_cache/kv_cache_store_backend.h" |
60 | 60 | #include "tpu_sync/kv_cache/kv_cache_store_backend_factory.h" |
61 | 61 | #include "tpu_sync/proto/worker_service.pb.h" |
| 62 | +#include "tpu_sync/telemetry/metrics_api.h" |
| 63 | +#include "tpu_sync/telemetry/metrics_backend.h" |
| 64 | +#include "tpu_sync/telemetry/mock_metrics_backend.h" |
62 | 65 |
|
63 | 66 | namespace tpu_raiden { |
64 | 67 | namespace kv_cache { |
@@ -2709,6 +2712,185 @@ TEST_F(MetadataCacheTest, UnmappableHashTruncatesPrefix) { |
2709 | 2712 | 1); |
2710 | 2713 | } |
2711 | 2714 |
|
| 2715 | +auto MetadataCheckLabels(absl::string_view dp_rank, absl::string_view result) { |
| 2716 | + return testing::ElementsAre( |
| 2717 | + testing::FieldsAre(telemetry::metric_labels::kDpRank, |
| 2718 | + std::string(dp_rank)), |
| 2719 | + testing::FieldsAre(telemetry::metric_labels::kResult, |
| 2720 | + std::string(result))); |
| 2721 | +} |
| 2722 | + |
| 2723 | +TEST_F(MetadataCacheTest, EmitsStatHitAndStatMissWhenCacheDisabled) { |
| 2724 | + Env env = CreateEnv(MetadataCacheOptions{}, /*batch_size=*/8, /*tp_size=*/2); |
| 2725 | + env.CreateAllShards("a"); |
| 2726 | + env.CreateBlock("b", /*tp_rank=*/0); // Rank 1 shard is missing. |
| 2727 | + |
| 2728 | + auto mock_backend = std::make_unique<telemetry::MockMetricsBackend>(); |
| 2729 | + auto* raw_backend = mock_backend.get(); |
| 2730 | + EXPECT_CALL( |
| 2731 | + *raw_backend, |
| 2732 | + IncrementCounter( |
| 2733 | + telemetry::metric_names::kStorageMetadataCheckTotal, |
| 2734 | + MetadataCheckLabels("0", telemetry::metric_labels::kResultStatHit), |
| 2735 | + 3)); |
| 2736 | + EXPECT_CALL( |
| 2737 | + *raw_backend, |
| 2738 | + IncrementCounter( |
| 2739 | + telemetry::metric_names::kStorageMetadataCheckTotal, |
| 2740 | + MetadataCheckLabels("0", telemetry::metric_labels::kResultStatMiss), |
| 2741 | + 3)); |
| 2742 | + |
| 2743 | + telemetry::ScopedMetricsBackendReset scoped_reset(std::move(mock_backend)); |
| 2744 | + // 6 shards in one chunk: a_r0, a_r1, b_r0 exist (3 stat_hits); b_r1, c_r0, |
| 2745 | + // c_r1 are absent (3 stat_misses). |
| 2746 | + EXPECT_EQ(env.LookupCount({"a", "b", "c"}), 1); |
| 2747 | +} |
| 2748 | + |
| 2749 | +TEST_F(MetadataCacheTest, |
| 2750 | + EmitsCacheHitStatHitAndStatMissWithTtlExpiryAndDelete) { |
| 2751 | + Env env = |
| 2752 | + CreateEnv(Enabled(/*max_entries=*/1000, kShortTtl), /*batch_size=*/4); |
| 2753 | + env.CreateBlock("a"); |
| 2754 | + env.CreateBlock("b"); |
| 2755 | + |
| 2756 | + // 1. Cold lookup of {"a", "b"}: 2 stat_hit, 0 cache_hit, 0 stat_miss. |
| 2757 | + { |
| 2758 | + auto mock_backend = std::make_unique<telemetry::MockMetricsBackend>(); |
| 2759 | + EXPECT_CALL( |
| 2760 | + *mock_backend, |
| 2761 | + IncrementCounter( |
| 2762 | + telemetry::metric_names::kStorageMetadataCheckTotal, |
| 2763 | + MetadataCheckLabels("0", telemetry::metric_labels::kResultStatHit), |
| 2764 | + 2)); |
| 2765 | + telemetry::ScopedMetricsBackendReset scoped_reset(std::move(mock_backend)); |
| 2766 | + EXPECT_EQ(env.LookupCount({"a", "b"}), 2); |
| 2767 | + } |
| 2768 | + |
| 2769 | + // 2. Warm lookup of {"a", "b", "c"} where "c" is missing: 2 cache_hit, |
| 2770 | + // 1 stat_miss. |
| 2771 | + { |
| 2772 | + auto mock_backend = std::make_unique<telemetry::MockMetricsBackend>(); |
| 2773 | + EXPECT_CALL( |
| 2774 | + *mock_backend, |
| 2775 | + IncrementCounter( |
| 2776 | + telemetry::metric_names::kStorageMetadataCheckTotal, |
| 2777 | + MetadataCheckLabels("0", telemetry::metric_labels::kResultCacheHit), |
| 2778 | + 2)); |
| 2779 | + EXPECT_CALL( |
| 2780 | + *mock_backend, |
| 2781 | + IncrementCounter( |
| 2782 | + telemetry::metric_names::kStorageMetadataCheckTotal, |
| 2783 | + MetadataCheckLabels("0", telemetry::metric_labels::kResultStatMiss), |
| 2784 | + 1)); |
| 2785 | + telemetry::ScopedMetricsBackendReset scoped_reset(std::move(mock_backend)); |
| 2786 | + EXPECT_EQ(env.LookupCount({"a", "b", "c"}), 2); |
| 2787 | + } |
| 2788 | + |
| 2789 | + // 3. Create "c" on disk and lookup {"a", "b", "c"}: 2 cache_hit, 1 stat_hit. |
| 2790 | + env.CreateBlock("c"); |
| 2791 | + { |
| 2792 | + auto mock_backend = std::make_unique<telemetry::MockMetricsBackend>(); |
| 2793 | + EXPECT_CALL( |
| 2794 | + *mock_backend, |
| 2795 | + IncrementCounter( |
| 2796 | + telemetry::metric_names::kStorageMetadataCheckTotal, |
| 2797 | + MetadataCheckLabels("0", telemetry::metric_labels::kResultCacheHit), |
| 2798 | + 2)); |
| 2799 | + EXPECT_CALL( |
| 2800 | + *mock_backend, |
| 2801 | + IncrementCounter( |
| 2802 | + telemetry::metric_names::kStorageMetadataCheckTotal, |
| 2803 | + MetadataCheckLabels("0", telemetry::metric_labels::kResultStatHit), |
| 2804 | + 1)); |
| 2805 | + telemetry::ScopedMetricsBackendReset scoped_reset(std::move(mock_backend)); |
| 2806 | + EXPECT_EQ(env.LookupCount({"a", "b", "c"}), 3); |
| 2807 | + } |
| 2808 | + |
| 2809 | + // 4. Delete "b" from cache and disk, then lookup {"a", "b", "c"}: "a" and "c" |
| 2810 | + // hit in cache (2 cache_hit), "b" is re-probed on disk (1 stat_miss). |
| 2811 | + EXPECT_EQ(env.store->Delete({"b"}), 1); |
| 2812 | + env.RemoveBlock("b"); |
| 2813 | + { |
| 2814 | + auto mock_backend = std::make_unique<telemetry::MockMetricsBackend>(); |
| 2815 | + EXPECT_CALL( |
| 2816 | + *mock_backend, |
| 2817 | + IncrementCounter( |
| 2818 | + telemetry::metric_names::kStorageMetadataCheckTotal, |
| 2819 | + MetadataCheckLabels("0", telemetry::metric_labels::kResultCacheHit), |
| 2820 | + 2)); |
| 2821 | + EXPECT_CALL( |
| 2822 | + *mock_backend, |
| 2823 | + IncrementCounter( |
| 2824 | + telemetry::metric_names::kStorageMetadataCheckTotal, |
| 2825 | + MetadataCheckLabels("0", telemetry::metric_labels::kResultStatMiss), |
| 2826 | + 1)); |
| 2827 | + telemetry::ScopedMetricsBackendReset scoped_reset(std::move(mock_backend)); |
| 2828 | + EXPECT_EQ(env.LookupCount({"a", "b", "c"}), 1); |
| 2829 | + } |
| 2830 | + |
| 2831 | + // 5. After TTL expiry, "a" is re-probed on disk (1 stat_hit, 0 cache_hit). |
| 2832 | + absl::SleepFor(kShortTtl + absl::Milliseconds(50)); |
| 2833 | + { |
| 2834 | + auto mock_backend = std::make_unique<telemetry::MockMetricsBackend>(); |
| 2835 | + EXPECT_CALL( |
| 2836 | + *mock_backend, |
| 2837 | + IncrementCounter( |
| 2838 | + telemetry::metric_names::kStorageMetadataCheckTotal, |
| 2839 | + MetadataCheckLabels("0", telemetry::metric_labels::kResultStatHit), |
| 2840 | + 1)); |
| 2841 | + telemetry::ScopedMetricsBackendReset scoped_reset(std::move(mock_backend)); |
| 2842 | + EXPECT_EQ(env.LookupCount({"a"}), 1); |
| 2843 | + } |
| 2844 | +} |
| 2845 | + |
| 2846 | +TEST_F(MetadataCacheTest, PropagatesCustomDpRankViaConstructorAndFactory) { |
| 2847 | + auto backend = std::make_shared<CountingPosixKVBackend>( |
| 2848 | + "posix", absl::flat_hash_map<std::string, std::string>{}); |
| 2849 | + auto mapper = std::make_shared<PosixPathMapper>( |
| 2850 | + scratch_dir_, "model_test", |
| 2851 | + ParallelismConfig{.tp_size = 1, .tp_rank = 0}); |
| 2852 | + backend->set_mapper(mapper); |
| 2853 | + |
| 2854 | + // Empty dp_rank falls back to "0". |
| 2855 | + PosixKVCacheStoreBackend default_store(backend, "posix", /*capacity=*/0, |
| 2856 | + /*lookup_batch_size=*/4, |
| 2857 | + MetadataCacheOptions{}, |
| 2858 | + /*dp_rank=*/""); |
| 2859 | + EXPECT_EQ(default_store.dp_rank(), "0"); |
| 2860 | + |
| 2861 | + // Factory propagates config.raiden_id.data_replica_idx to dp_rank. |
| 2862 | + BackendConfig config; |
| 2863 | + config.type = "posix"; |
| 2864 | + config.SetProperty("root_dir", scratch_dir_); |
| 2865 | + config.SetProperty("model_name", "model_test"); |
| 2866 | + config.parallelism = {.tp_size = 1, .tp_rank = 0}; |
| 2867 | + config.raiden_id = {"test_job", "0", "kv_cache", /*data_replica_idx=*/3}; |
| 2868 | + |
| 2869 | + TF_ASSERT_OK_AND_ASSIGN(std::shared_ptr<KVCacheStoreBackend> created, |
| 2870 | + KVCacheStoreBackendFactory::Instance().CreateBackend( |
| 2871 | + config, /*controller=*/nullptr)); |
| 2872 | + auto factory_store = |
| 2873 | + std::dynamic_pointer_cast<PosixKVCacheStoreBackend>(created); |
| 2874 | + ASSERT_NE(factory_store, nullptr); |
| 2875 | + EXPECT_EQ(factory_store->dp_rank(), "3"); |
| 2876 | + |
| 2877 | + auto mock_backend = std::make_unique<telemetry::MockMetricsBackend>(); |
| 2878 | + auto* raw_backend = mock_backend.get(); |
| 2879 | + EXPECT_CALL( |
| 2880 | + *raw_backend, |
| 2881 | + IncrementCounter( |
| 2882 | + telemetry::metric_names::kStorageMetadataCheckTotal, |
| 2883 | + MetadataCheckLabels("3", telemetry::metric_labels::kResultStatMiss), |
| 2884 | + 1)); |
| 2885 | + EXPECT_CALL(*raw_backend, |
| 2886 | + SetGauge(telemetry::metric_names::kStorageFilesystemBytes, |
| 2887 | + testing::_, testing::_)) |
| 2888 | + .Times(testing::AnyNumber()); |
| 2889 | + telemetry::ScopedMetricsBackendReset scoped_reset(std::move(mock_backend)); |
| 2890 | + TF_ASSERT_OK_AND_ASSIGN(BlockSliceList result, |
| 2891 | + factory_store->Lookup({"missing_block"})); |
| 2892 | + EXPECT_TRUE(result.empty()); |
| 2893 | +} |
2712 | 2894 | } // namespace |
2713 | 2895 | } // namespace storage |
2714 | 2896 | } // namespace backends |
|
0 commit comments