Performance-Aware Loops
Early Exit Scan
Stop When Found
An early exit can reduce unnecessary loop work when a condition has already been satisfied.
Program
Play the program to choose the target and compare how many checks the scan performs.
early_exit_scan.f90
Replay: real traced execution (multi-file project)
program early_exit_scan_demo
implicit none
integer :: values(5)
integer :: target
integer :: i
integer :: checks
integer :: found_at
values = [3, 6, 9, 12, 15]
target = 12
checks = 0
found_at = 0
do i = 1, size(values)
checks = checks + 1
if (values(i) == target) then
found_at = i
exit
end if
end do
print '(I0, 1X, I0)', found_at, checks
end program early_exit_scan_demo
program early_exit_scan_demo
implicit none
integer :: values(5)
integer :: target
integer :: i
integer :: checks
integer :: found_at
values = [3, 6, 9, 12, 15]
target = 6
checks = 0
found_at = 0
do i = 1, size(values)
checks = checks + 1
if (values(i) == target) then
found_at = i
exit
end if
end do
print '(I0, 1X, I0)', found_at, checks
end program early_exit_scan_demo
program early_exit_scan_demo
implicit none
integer :: values(5)
integer :: target
integer :: i
integer :: checks
integer :: found_at
values = [3, 6, 9, 12, 15]
target = 14
checks = 0
found_at = 0
do i = 1, size(values)
checks = checks + 1
if (values(i) == target) then
found_at = i
exit
end if
end do
print '(I0, 1X, I0)', found_at, checks
end program early_exit_scan_demo
values ← [3, 6, 9, 12, 15]
9values = [3, 6, 9, 12, 15]10target = 12values this step[3, 6, 9, 12, 15]valuestarget ← 12
9values = [3, 6, 9, 12, 15]10target = 1211checks = 0values this step12targetchecks ← 0
10target = 1211checks = 012found_at = 0values this step0checksfound_at ← 0
11checks = 012found_at = 013do i = 1, size(values)values this step0found_atchecks ← 1
13do i = 1, size(values)14 checks = checks + 115 if (values(i) == target) thenvalues this step0 → 1checks1imatched ← .false.
14checks = checks + 115if (values(i) == target) then16 found_at = ivalues this step.false.matched3values(i)12targetchecks ← 2
13do i = 1, size(values)14 checks = checks + 115 if (values(i) == target) thenvalues this step1 → 2checks2imatched ← .false.
14checks = checks + 115if (values(i) == target) then16 found_at = ivalues this step.false.matched6values(i)12targetchecks ← 3
13do i = 1, size(values)14 checks = checks + 115 if (values(i) == target) thenvalues this step2 → 3checks3imatched ← .false.
14checks = checks + 115if (values(i) == target) then16 found_at = ivalues this step.false.matched9values(i)12targetchecks ← 4
13do i = 1, size(values)14 checks = checks + 115 if (values(i) == target) thenvalues this step3 → 4checks4imatched ← .true.
14checks = checks + 115if (values(i) == target) then16 found_at = ivalues this step.true.matched12values(i)12targetfound_at ← 4
15if (values(i) == target) then16 found_at = i17 exitvalues this step4found_atexit ← scan stops
16 found_at = i17 exit18end ifvalues this stepscan stopsexitprint '(I0, 1X, I0)', found_at, checks
19 end do20 print '(I0, 1X, I0)', found_at, checks21end program early_exit_scan_demooutput4 4values this step4found_at4checks
values ← [3, 6, 9, 12, 15]
9values = [3, 6, 9, 12, 15]10target = 6values this step[3, 6, 9, 12, 15]valuestarget ← 6
9values = [3, 6, 9, 12, 15]10target = 611checks = 0values this step6targetchecks ← 0
10target = 611checks = 012found_at = 0values this step0checksfound_at ← 0
11checks = 012found_at = 013do i = 1, size(values)values this step0found_atchecks ← 1
13do i = 1, size(values)14 checks = checks + 115 if (values(i) == target) thenvalues this step0 → 1checks1imatched ← .false.
14checks = checks + 115if (values(i) == target) then16 found_at = ivalues this step.false.matched3values(i)6targetchecks ← 2
13do i = 1, size(values)14 checks = checks + 115 if (values(i) == target) thenvalues this step1 → 2checks2imatched ← .true.
14checks = checks + 115if (values(i) == target) then16 found_at = ivalues this step.true.matched6values(i)6targetfound_at ← 2
15if (values(i) == target) then16 found_at = i17 exitvalues this step2found_atexit ← scan stops
16 found_at = i17 exit18end ifvalues this stepscan stopsexitprint '(I0, 1X, I0)', found_at, checks
19 end do20 print '(I0, 1X, I0)', found_at, checks21end program early_exit_scan_demooutput2 2values this step2found_at2checks
values ← [3, 6, 9, 12, 15]
9values = [3, 6, 9, 12, 15]10target = 14values this step[3, 6, 9, 12, 15]valuestarget ← 14
9values = [3, 6, 9, 12, 15]10target = 1411checks = 0values this step14targetchecks ← 0
10target = 1411checks = 012found_at = 0values this step0checksfound_at ← 0
11checks = 012found_at = 013do i = 1, size(values)values this step0found_atchecks ← 1
13do i = 1, size(values)14 checks = checks + 115 if (values(i) == target) thenvalues this step0 → 1checks1imatched ← .false.
14checks = checks + 115if (values(i) == target) then16 found_at = ivalues this step.false.matched3values(i)14targetchecks ← 2
13do i = 1, size(values)14 checks = checks + 115 if (values(i) == target) thenvalues this step1 → 2checks2imatched ← .false.
14checks = checks + 115if (values(i) == target) then16 found_at = ivalues this step.false.matched6values(i)14targetchecks ← 3
13do i = 1, size(values)14 checks = checks + 115 if (values(i) == target) thenvalues this step2 → 3checks3imatched ← .false.
14checks = checks + 115if (values(i) == target) then16 found_at = ivalues this step.false.matched9values(i)14targetchecks ← 4
13do i = 1, size(values)14 checks = checks + 115 if (values(i) == target) thenvalues this step3 → 4checks4imatched ← .false.
14checks = checks + 115if (values(i) == target) then16 found_at = ivalues this step.false.matched12values(i)14targetchecks ← 5
13do i = 1, size(values)14 checks = checks + 115 if (values(i) == target) thenvalues this step4 → 5checks5imatched ← .false.
14checks = checks + 115if (values(i) == target) then16 found_at = ivalues this step.false.matched15values(i)14targetprint '(I0, 1X, I0)', found_at, checks
19 end do20 print '(I0, 1X, I0)', found_at, checks21end program early_exit_scan_demooutput0 5values this step0found_at5checks
early exit
`exit` leaves the loop as soon as the target is found.
checks
`checks` shows the amount of scanning work performed.
sentinel
`found_at = 0` records the not-found case without raising an error.