Electing to bat, Sri Lanka posted a challenging 165 for seven in 20 overs, riding on a 40-ball 61 by Perera and then restricted South Africa to 160 for eight, thanks to some fine bowling towards the end.
South Africa seemed to be cruising towards the target of 166 as they required 19 runs from the last two overs, but Sri Lankan pacers Nuwan Kulasekara and Lasith Malinga choked the Protea batsmen with their superb bowling.
South Africa needed 15 runs from the last over bowled by Malinga and there was still hope for a win as David Miller (19) was still batting. But, they could not hold on to their nerves and two run-outs in the last over, including that of Miller, sealed the match in favour of Sri Lanka.
South Africa's run chase was built on a 60-run second-wicket stand between opener Hashim Amla (23) and top-scorer J P Duminy (39) to find themselves in a strong position at 75 for one at the halfway mark only to fritter away the advantage in the next 10 overs.
Opener Quinton de Kock (25), A B de Villiers (24), who stood in as captain in place of an injured Faf du Plessis, made useful contributions but for a lost cause.
For Sri Lanka, off-spinner Sachithra Senanayake grabbed two wickets for 22 runs while Kulasekara, Angelo Mathews, Malinga and Ajantha Mendis chipped in with a wicket apiece.
Earlier, Perera smashed a strokeful 61 as Sri Lanka posted 165 for seven after electing to bat.
Perera, who hit his fifth T20I fifty in his 12th match, treated the South African fast bowlers with disdain as he hit six fours and three sixes in his 40-ball innings.
ODI captain Angelo Mathews chipped in with a fine 32-ball 43, which was lashed with three fours and a six, down the order to do the bulk of scoring in the second half of Sri Lanka innings after Perera was out in the 14th over.
Captain Dinesh Chandimal (12) and Kumar Sangakkara (14) were the other Sri Lankan batsmen who reached double digit scores.
A aggressive Perera hit a six each off Dale Steyn (2/37), Lonwabo Tsotsobe (0/31) and Morne Morkel (2/31) to lay the foundation for the challenging total for Sri Lanka.
He took 17 runs from the first over bowled by Steyn with two fours and a six and that led to the South African fast bowler being taken off the attack after bowling his first over.
Steyn, who conceded runs at an average of 9.25 per over, came back into operation only in the 11th over. His pacemates Tsotsobe, Morne Morkel and Albie Morkel (0/24 from 2 overs) were also equally expensive by conceding runs at averages of 7.75, 7.75 and 12 respectively.
Sri Lanka looked like posting a big total after racing to 84 for three at the halfway mark but thanks to slow bowlers Imran Tahir (3/36) and J P Duminy (0/13 from 2 overs), South Africa could slow them down in the next 10 overs.