Non, preg_match() c'est pas méga performant. C'est plus performant que ereg mais il ne faut pas oublier que dans le preg_match() il y a toute la partie traduction de la pcre alors que dans un is_numeric() et dans les autres fonctions, le masque est codé en dur, c'est normal que preg_match() prenne autant de temps…
Attention, ctype_digit() ne fera probablement pas partie de PHP6... si j'étais toi j'utiliserais plutôt filter_input()/filter_var() (plus un if pour vérifier que le nombre est positif) ou encore preg_match().