By performing a profiler trace you can see if you have any bottlenecks on SQL Server. Your default profiler trace (include TextData for RPC:Completed) should be good enough to start with.
The profiler trace can be analysed to see what takes the longest time. You can easily load the trace into a table and analyse it there. Note that when loaded into a table, the duration column is in microseconds. See the function fn_trace_gettable for a quicker way of loading a trace file into a table.
A common cause for poor performance, especially after a major change, is bad indexing.
Since SQL Server 2005 the optimiser stores within in-memory structures the indices it would like to have seen. These can be accessed with the dynamic management views sys.dm_db_missing_index_details, sys.dm_db_missing_index_groups and sys.dm_db_missing_index_groups_stats.
Here is a simple sample SQL to create your own missing index report, including the basic code to generate the missing index.
select
d.statement
, d.equality_columns
, d.inequality_columns
, d.included_columns
, s.user_seeks Seeks
, s.last_user_seek
, cast (s.avg_total_user_cost as decimal (9,2)) Cost
, s.avg_user_impact [%]
, 'CREATE INDEX MissingIndex_ ON ' + d.statement + '('
+ case when equality_columns IS NOT NULL then equality_columns else '' end
+ case when equality_columns IS NOT NULL AND inequality_columns IS NOT NULL then ', ' else '' end
+ case when inequality_columns IS NOT NULL then inequality_columns else '' end
+ ')'
+ case when included_columns IS NOT NULL then ' INCLUDE (' + included_columns + ')' else '' end
AS SQL
from sys.dm_db_missing_index_details d
INNER JOIN sys.dm_db_missing_index_groups g ON d.index_handle = g.index_handle
INNER JOIN sys.dm_db_missing_index_group_stats s ON g.index_group_handle = s.group_handle