After bundling out Sri Lanka for 292, the Proteas moved to 63-2 at lunch in their second innings for an overall lead of 226 runs with eight wickets in hand. (Agencies)
The visitors had made 455-9 declared in their first innings.
New Test skipper Hashim Amla was batting on seven with Faf du Plessis on eight at the break.
South Africa started off cautiously against a bowling attack that relied heavily on spin in the absence of frontline seamer Shaminda Eranga, who is injured.
Opener Dean Elgar, who made 103 in the first innings, was the first batsman to fall as he tried to go for an ambitious drive off Herath (1-24) but nicked it behind to wicketkeeper Dinesh Chandimal.
He faced 29 balls and hit two fours in his 12-run knock.
Alviro Petersen (32) took on the spinners fearlessly, twice reverse-sweeping Perera in the same over for boundaries to step up the scoring.
In the end, it was Perera who brought Petersen's promising innings to an end with a good length ball that he nicked to Chandimal.
Earlier, South Africa wrapped up the Sri Lankan innings in the fifth over of the day with paceman Morne Morkel (3-49) sending back overnight batsman Herath for 19.
Herath edged the bowler to second slip where AB de Villiers dived to his left to pluck a stunning catch and bring the curtain down on Sri Lanka's first innings.
Sri Lanka added just nine runs to their overnight score of 283-9.
Pace spearhead Dale Steyn was the star of the South African bowling, finishing with 5-54, his 23rd five-wicket haul in Tests.
The visitors were dealt a blow when paceman Vernon Philander was fined 75 percent of his match fee on Friday after being accused of ball-tampering.
Philander, who bowled 15 wicketless overs for 31 runs, did not bowl on Saturday.
The second and final Test will be played in Colombo from July 24-28.
After bundling out Sri Lanka for 292, the Proteas moved to 63-2 at lunch in their second innings for an overall lead of 226 runs with eight wickets in hand.