@@ -22,7 +22,8 @@ all() ->
22
22
23
23
groups () ->
24
24
[
25
- {all_tests , [], all_tests ()}
25
+ {all_tests , [], all_tests ()},
26
+ {benchmarks , [], benchmarks ()}
26
27
].
27
28
28
29
all_tests () ->
@@ -37,6 +38,11 @@ all_tests() ->
37
38
build_multiple_key_from_deletion_events
38
39
].
39
40
41
+ benchmarks () ->
42
+ [
43
+ match_benchmark
44
+ ].
45
+
40
46
init_per_suite (Config ) ->
41
47
rabbit_ct_helpers :log_environment (),
42
48
rabbit_ct_helpers :run_setup_steps (Config ).
@@ -271,6 +277,83 @@ build_multiple_key_from_deletion_events1(Config) ->
271
277
lists :sort ([RK || {_ , RK } <- rabbit_db_topic_exchange :trie_records_to_key (Records )])),
272
278
passed .
273
279
280
+ % % ---------------------------------------------------------------------------
281
+ % % Benchmarks
282
+ % % ---------------------------------------------------------------------------
283
+
284
+ match_benchmark (Config ) ->
285
+ % % run the benchmark with Mnesia first
286
+ MnesiaResults = rabbit_ct_broker_helpers :rpc (Config , 0 , ? MODULE , match_benchmark1 , [Config ]),
287
+
288
+ % % migrate to Khepri
289
+ Servers = rabbit_ct_broker_helpers :get_node_configs (Config , nodename ),
290
+ {T , ok } = timer :tc (fun () ->
291
+ rabbit_ct_broker_helpers :enable_feature_flag (Config , Servers , raft_based_metadata_store_phase1 )
292
+ end ),
293
+ ct :pal (" ~p : time to migrate to Khepri: ~.2f s" , [? FUNCTION_NAME , T / 1000000 ]),
294
+
295
+ % % run the same same benchmark with Khepri enabled
296
+ KhepriResults = rabbit_ct_broker_helpers :rpc (Config , 0 , ? MODULE , match_benchmark1 , [Config ]),
297
+
298
+ % % print all the results first
299
+ maps :foreach (fun (Test , KhepriResult ) ->
300
+ MnesiaResult = maps :get (Test , MnesiaResults ),
301
+ ct :pal (" ~p : Test: ~p , Mnesia: ~.2f us, Khepri: ~.2f us" , [? FUNCTION_NAME , Test , MnesiaResult , KhepriResult ])
302
+ end , KhepriResults ),
303
+
304
+ % % fail the test if needed
305
+ maps :foreach (fun (Test , KhepriResult ) ->
306
+ MnesiaResult = maps :get (Test , MnesiaResults ),
307
+ ? assert (KhepriResult < MnesiaResult * 1.5 , " Khepri can't be significantly slower than Mnesia" )
308
+ end , KhepriResults ).
309
+
310
+ match_benchmark1 (_Config ) ->
311
+ Src = rabbit_misc :r (? VHOST , exchange , <<" test-exchange" >>),
312
+ Dst1 = rabbit_misc :r (? VHOST , queue , <<" test-queue1" >>),
313
+ Dst2 = rabbit_misc :r (? VHOST , queue , <<" test-queue2" >>),
314
+ Dst3 = rabbit_misc :r (? VHOST , queue , <<" test-queue3" >>),
315
+ Dst4 = rabbit_misc :r (? VHOST , queue , <<" test-queue4" >>),
316
+ Dst5 = rabbit_misc :r (? VHOST , queue , <<" test-queue5" >>),
317
+ Dst6 = rabbit_misc :r (? VHOST , queue , <<" test-queue6" >>),
318
+
319
+ SimpleTopics = [list_to_binary (" a.b." ++ integer_to_list (N )) || N <- lists :seq (1 ,1000 )],
320
+ Bindings = [# binding {source = Src , key = RoutingKey , destination = Dst1 , args = #{}} || RoutingKey <- SimpleTopics ],
321
+ BindingRes = [rabbit_db_topic_exchange :set (Binding ) || Binding <- Bindings ],
322
+ ? assertMatch ([ok ], lists :uniq (BindingRes )),
323
+ ok = rabbit_db_topic_exchange :set (# binding {source = Src , key = <<" a.b.*" >>, destination = Dst2 , args = #{}}),
324
+ ok = rabbit_db_topic_exchange :set (# binding {source = Src , key = <<" a.b.*" >>, destination = Dst3 , args = #{}}),
325
+ ok = rabbit_db_topic_exchange :set (# binding {source = Src , key = <<" a.#" >>, destination = Dst4 , args = #{}}),
326
+ ok = rabbit_db_topic_exchange :set (# binding {source = Src , key = <<" *.b.42" >>, destination = Dst5 , args = #{}}),
327
+ ok = rabbit_db_topic_exchange :set (# binding {source = Src , key = <<" #" >>, destination = Dst6 , args = #{}}),
328
+
329
+ {Tany , _ } = timer :tc (fun () ->
330
+ [rabbit_db_topic_exchange :match (Src , <<" foo" >>) || _ <- lists :seq (1 , 100 )]
331
+ end ),
332
+ ? assertMatch ([Dst6 ], rabbit_db_topic_exchange :match (Src , <<" foo" >>)),
333
+
334
+ {Tbar , _ } = timer :tc (fun () ->
335
+ [rabbit_db_topic_exchange :match (Src , <<" a.b.bar" >>) || _ <- lists :seq (1 , 100 )]
336
+ end ),
337
+ ? assertEqual (lists :sort ([Dst2 ,Dst3 ,Dst4 ,Dst6 ]), lists :sort (rabbit_db_topic_exchange :match (Src , <<" a.b.bar" >>))),
338
+
339
+ {Tbaz , _ } = timer :tc (fun () ->
340
+ [rabbit_db_topic_exchange :match (Src , <<" baz.b.42" >>) || _ <- lists :seq (1 , 100 )]
341
+ end ),
342
+ ? assertEqual (lists :sort ([Dst5 ,Dst6 ]), lists :sort (rabbit_db_topic_exchange :match (Src , <<" baz.b.42" >>))),
343
+
344
+ {Tsimple , Rsimple } = timer :tc (fun () ->
345
+ [rabbit_db_topic_exchange :match (Src , RoutingKey )
346
+ || RoutingKey <- SimpleTopics , RoutingKey =/= <<" a.b.123" >>]
347
+ end ),
348
+ ? assertEqual ([Dst1 ,Dst2 ,Dst3 ,Dst4 ,Dst6 ], lists :sort (lists :uniq (hd (Rsimple )))),
349
+
350
+ #{
351
+ " average time to match `foo`" => Tany / 100 ,
352
+ " average time to match `a.b.bar`" => Tbar / 100 ,
353
+ " average time to match `baz.b.42`" => Tbaz / 100 ,
354
+ " average time to match a simple topic" => Tsimple / length (SimpleTopics )
355
+ }.
356
+
274
357
subscribe_to_mnesia_changes ([Table | Rest ]) ->
275
358
case mnesia :subscribe ({table , Table , detailed }) of
276
359
{ok , _ } -> subscribe_to_mnesia_changes (Rest );
0 commit comments