@@ -5815,3 +5815,124 @@ fn scheduled_heap_delta_limit_scaling() {
5815
5815
assert_eq ! ( 10 , scheduled_limit( 50 , 50 , 9 , 10 , 5 ) ) ;
5816
5816
assert_eq ! ( 10 , scheduled_limit( 55 , 50 , 9 , 10 , 5 ) ) ;
5817
5817
}
5818
+
5819
+ #[ test]
5820
+ fn inner_round_first_execution_is_not_a_full_execution ( ) {
5821
+ let scheduler_cores = 2 ;
5822
+ let instructions = 20 ;
5823
+ let max_messages_per_round = 3 ;
5824
+ let mut test = SchedulerTestBuilder :: new ( )
5825
+ . with_scheduler_config ( SchedulerConfig {
5826
+ scheduler_cores,
5827
+ max_instructions_per_round : ( instructions * max_messages_per_round) . into ( ) ,
5828
+ max_instructions_per_message : instructions. into ( ) ,
5829
+ max_instructions_per_message_without_dts : instructions. into ( ) ,
5830
+ max_instructions_per_slice : instructions. into ( ) ,
5831
+ instruction_overhead_per_execution : NumInstructions :: from ( 0 ) ,
5832
+ instruction_overhead_per_canister : NumInstructions :: from ( 0 ) ,
5833
+ instruction_overhead_per_canister_for_finalization : NumInstructions :: from ( 0 ) ,
5834
+ ..SchedulerConfig :: application_subnet ( )
5835
+ } )
5836
+ . build ( ) ;
5837
+
5838
+ // Bump up the round number.
5839
+ test. execute_round ( ExecutionRoundType :: OrdinaryRound ) ;
5840
+
5841
+ // Create `scheduler_cores * 2` canisters, so target canister is not scheduled first.
5842
+ let mut canister_ids = vec ! [ ] ;
5843
+ for _ in 0 ..scheduler_cores * 2 {
5844
+ canister_ids. push ( test. create_canister ( ) ) ;
5845
+ }
5846
+ // Create target canister after.
5847
+ let target_id = test. create_canister ( ) ;
5848
+ // Send messages to the target canister.
5849
+ for canister_id in & canister_ids {
5850
+ let message = ingress ( instructions) . call (
5851
+ other_side ( target_id, instructions - 1 ) ,
5852
+ on_response ( instructions - 2 ) ,
5853
+ ) ;
5854
+ test. send_ingress ( * canister_id, message) ;
5855
+ }
5856
+
5857
+ test. execute_round ( ExecutionRoundType :: OrdinaryRound ) ;
5858
+
5859
+ let mut total_accumulated_priority = 0 ;
5860
+ let mut total_priority_credit = 0 ;
5861
+ for canister in test. state ( ) . canisters_iter ( ) {
5862
+ let system_state = & canister. system_state ;
5863
+ let scheduler_state = & canister. scheduler_state ;
5864
+ // All ingresses should be executed in the previous round.
5865
+ assert_eq ! ( system_state. queues( ) . ingress_queue_size( ) , 0 ) ;
5866
+ assert_eq ! ( system_state. canister_metrics. executed, 1 ) ;
5867
+ if canister. canister_id ( ) == target_id {
5868
+ // The target canister, despite being executed first in the second inner round,
5869
+ // should not be marked as fully executed.
5870
+ assert_ne ! ( test. last_round( ) , 0 . into( ) ) ;
5871
+ assert_eq ! ( scheduler_state. last_full_execution_round, 0 . into( ) ) ;
5872
+ } else {
5873
+ assert_eq ! ( scheduler_state. last_full_execution_round, test. last_round( ) ) ;
5874
+ }
5875
+ total_accumulated_priority += scheduler_state. accumulated_priority . get ( ) ;
5876
+ total_priority_credit += scheduler_state. priority_credit . get ( ) ;
5877
+ }
5878
+ // The accumulated priority invariant should be respected.
5879
+ assert_eq ! ( total_accumulated_priority - total_priority_credit, 0 ) ;
5880
+ }
5881
+
5882
+ #[ test]
5883
+ fn inner_round_long_execution_is_a_full_execution ( ) {
5884
+ let scheduler_cores = 2 ;
5885
+ let slice = 20 ;
5886
+ let mut test = SchedulerTestBuilder :: new ( )
5887
+ . with_scheduler_config ( SchedulerConfig {
5888
+ scheduler_cores,
5889
+ max_instructions_per_round : ( slice * 2 ) . into ( ) ,
5890
+ max_instructions_per_message : ( slice * 10 ) . into ( ) ,
5891
+ max_instructions_per_message_without_dts : slice. into ( ) ,
5892
+ max_instructions_per_slice : slice. into ( ) ,
5893
+ instruction_overhead_per_execution : NumInstructions :: from ( 0 ) ,
5894
+ instruction_overhead_per_canister : NumInstructions :: from ( 0 ) ,
5895
+ instruction_overhead_per_canister_for_finalization : NumInstructions :: from ( 0 ) ,
5896
+ ..SchedulerConfig :: application_subnet ( )
5897
+ } )
5898
+ . build ( ) ;
5899
+
5900
+ // Bump up the round number.
5901
+ test. execute_round ( ExecutionRoundType :: OrdinaryRound ) ;
5902
+
5903
+ // Create `scheduler_cores` canisters, so target canister is not scheduled first.
5904
+ let mut canister_ids = vec ! [ ] ;
5905
+ for _ in 0 ..scheduler_cores {
5906
+ let canister_id = test. create_canister ( ) ;
5907
+ test. send_ingress ( canister_id, ingress ( slice) ) ;
5908
+ canister_ids. push ( canister_id) ;
5909
+ }
5910
+ // Create a target canister with two long executions.
5911
+ let target_id = test. create_canister ( ) ;
5912
+ test. send_ingress ( target_id, ingress ( slice * 2 + 1 ) ) ;
5913
+ test. send_ingress ( target_id, ingress ( slice * 2 + 1 ) ) ;
5914
+
5915
+ test. execute_round ( ExecutionRoundType :: OrdinaryRound ) ;
5916
+
5917
+ let mut total_accumulated_priority = 0 ;
5918
+ let mut total_priority_credit = 0 ;
5919
+ for canister in test. state ( ) . canisters_iter ( ) {
5920
+ let system_state = & canister. system_state ;
5921
+ let scheduler_state = & canister. scheduler_state ;
5922
+ // All canisters should be executed.
5923
+ assert_eq ! ( system_state. canister_metrics. executed, 1 ) ;
5924
+ if canister. canister_id ( ) == target_id {
5925
+ // The target canister was not executed first, and still have messages.
5926
+ assert_eq ! ( system_state. queues( ) . ingress_queue_size( ) , 1 ) ;
5927
+ } else {
5928
+ assert_eq ! ( system_state. queues( ) . ingress_queue_size( ) , 0 ) ;
5929
+ }
5930
+ // All canisters should be marked as fully executed. The target canister,
5931
+ // despite still having messages, executed a full slice of instructions.
5932
+ assert_eq ! ( scheduler_state. last_full_execution_round, test. last_round( ) ) ;
5933
+ total_accumulated_priority += scheduler_state. accumulated_priority . get ( ) ;
5934
+ total_priority_credit += scheduler_state. priority_credit . get ( ) ;
5935
+ }
5936
+ // The accumulated priority invariant should be respected.
5937
+ assert_eq ! ( total_accumulated_priority - total_priority_credit, 0 ) ;
5938
+ }
0 commit comments