Some of these suggestions apply only after a bottleneck has been identified:
Tune the application before tuning the underlying system. This is especially pertinent to network communications.
Limit application bandwidth requirements to the network segment with the smallest bandwidth.
Consider network latencies when specifying feasible application response times.
Aim to minimize the number of network round trips necessary to satisfy an application request.
Constantly monitor the entire system with any monitoring tools available. Monitoring utilities include perfmeter (Unix CPU), vmstat (Unix CPU, RAM, and disks), iostat (Unix disks), performance monitor (Windows CPU, RAM, and disks), netstat (network I/O), ping (network latency), and nslookup (DNS lookup and routing).
Keep monitoring records to get a background usage pattern.
Use normal monitoring records to get an early warning of changes in the system usage patterns.
Watch for levels of paging that decrease system performance.
Watch for low CPU activity coupled with high disk activity and delayed responses. This may indicate an I/O problem.
Monitor for retransmissions of data packets.
Ensure the CPU runnable queue does not get too large.
Aim for average CPU utilization of not more than 75%.
Consider spreading extra computation loads to low activity times.
Run offline work in off-peak hours only.
Time all processes and terminate any that exceed timeout thresholds.
Consider upgrading or reconfiguring parts of the system.
Doubling the CPU speed is usually better than doubling the number of CPUs.
Consider striping the disks (e.g., RAID disks).
Add more swap space when there is no other way to increase the memory available to the application (or to reduce the application's memory usage requirements).
Test to see if running on raw partitions will be faster.
Look at mapping filesystems into memory for speedier startups and accesses. But be aware that this reduces system memory available to applications. For multiuser applications, this is an efficient way of sharing in-memory data.
Move components from network-mounted disks to local disks.
Ensure that system swap files are on different disks from any intensively used files.
Cluster files together at the disk level, if possible, or within one big container file.
Defragment disks regularly if applicable to your system.
Move executables or index files to disk sweet spots.
Consider altering priority levels of processes to tune the amount of CPU time they get.
Consider locking processes into memory so they do not get paged out.
Partition the system to allocate determinate resources to your application.
Consider tuning the maximum packet size specified by the TCP/IP stack.
Ensure that your TCP/IP stacks have no performance problems associated with them.
Consider running a local caching DNS server to improve the speed of hostname lookups.