Agora existe uma 4ª opção - parâmetros com valor de tabela , onde você pode realmente passar uma tabela de valores para um sproc como um parâmetro e depois usá-lo como faria normalmente com uma variável de tabela. Eu preferiria essa abordagem sobre a abordagem de análise XML (ou CSV)
Não posso citar números de desempenho entre todas as abordagens diferentes, mas essa é uma que eu estaria tentando - eu recomendaria fazer alguns testes de desempenho reais nelas.
Editar:
Um pouco mais sobre TVPs. Para passar os valores para o seu sproc, basta definir um SqlParameter (SqlDbType.Structured) - o valor deste pode ser definido para qualquer fonte IEnumerable, DataTable ou DbDataReader. Então, presumivelmente, você já tem a lista de valores em uma lista/array de algum tipo - você não precisa fazer nada para transformá-la em XML ou CSV.
Acho que isso também torna o sproc mais claro, simples e de fácil manutenção, proporcionando uma maneira mais natural de alcançar o resultado final. Um dos pontos principais é que o SQL tem melhor desempenho em atividades baseadas em conjunto/sem loop/manipulação de strings.
Isso não quer dizer que terá um ótimo desempenho com um grande conjunto de valores passados. Mas com conjuntos menores (até ~1000) deve ficar bem.