Your Perforce server should normally be a light consumer of system resources. As your installation grows, however, you might want to revisit your system configuration to ensure that it is configured for optimal performance.
This chapter briefly outlines some of the factors that can affect the performance of a Perforce server, provides a few tips on diagnosing network-related difficulties, and offers some suggestions on decreasing server load for larger installations.
Server performance is highly dependent upon having sufficient memory. Two bottlenecks are relevant. The first bottleneck can be avoided by ensuring that the server doesn't page when it runs large queries, and the second by ensuring that the
db.rev table (or at least as much of it as practical) can be cached in main memory:
•
|
To cache db.rev, the size of the db.rev file in an existing installation can be observed and used as an estimate. New installations of Perforce can expect db.rev to require about 150-200 bytes per revision, and roughly three revisions per file, or about 0.5 kilobytes of RAM per file.
|
Thus, if there is 1.5 kilobytes of RAM available per file, or 150 MB for 100,000 files, the server does not page, even when performing operations involving all files. It is still possible that multiple large operations can be performed simultaneously and thus require more memory to avoid paging. On the other hand, the vast majority of operations involve only a small subset of files.
Perforce is judicious with regards to its use of disk I/O; its metadata is well-keyed, and accesses are mostly sequential scans of limited subsets of the data. The most disk-intensive activity is file check-in, where the Perforce server must write and rename files in the archive. Server performance depends heavily on the operating system's filesystem implementation, and in particular, on whether directory updates are synchronous. Server performance is also highly dependent upon the capabilities of the underlying hardware's I/O subsystem.
Although Perforce does not recommend any specific hardware configuration or filesystem, Linux servers are generally fastest (owing to Linux's asynchronous directory updating), but they may have poor recovery if power is cut at the wrong time. The BSD filesystem (also used in Solaris) is relatively slow but much more reliable. NTFS performance falls somewhere in between these two ranges.
Performance in systems where database and versioned files are stored on NFS-mounted volumes is typically dependent on the implementation of NFS in question or the underlying storage hardware. Perforce has been tested and is supported under the Solaris implementation of NFS.
Under Linux and FreeBSD, database updates over NFS can be an issue because file locking is relatively slow; if the journal is NFS-mounted on these platforms, all operations will be slower. In general (but in particular on Linux and FreeBSD), we recommend that the Perforce database, depot, and journal files be stored on disks local to the machine running the Perforce server process.
These issues affect only the Perforce server process (p4d). Perforce client programs, (such as
p4, the Perforce Command-Line Client) have always been able to work with client workspaces on NFS-mounted drives (for instance, workspaces in users' home directories).
The server's database size can be calculated with a fair level of accuracy; as a rough estimate, it requires 0.5 kilobytes per user per file. (For instance, a system with 10,000 files and 50 users requires 250 MB of disk space for the database). The database can be expected to grow over time as histories of the individual files grow.
The size of the server's archive of versioned files depends on the sizes of the original files stored and grows as revisions are added. For most sites, allocate space equivalent to at least three times the aggregate size of the original files.
The db.have file holds the list of files opened in client workspaces. This file tends to grow more rapidly than other files in the database. If you are experiencing issues related to the size of your
db.have file and are unable to quickly switch to a server with adequate support for large files, deleting unused client workspace specifications and reducing the scope of client workspace views can help alleviate the problem.
To find out how much disk space is currently occupied by files in a depot (or part of a depot), use the
p4 sizes command with a block size corresponding to that used by your storage solution. For example, the command
shows the sum (-s) of all revisions (
-a) in
//depot/... with a block size of 512 bytes.
Perforce uses a TCP/IP connection for each client interaction with the server. The server's port address is defined by
P4PORT, but the TCP/IP implementation picks a client port number. After the command completes and the connection is closed, the port is left in a state called
TIME_WAIT for two minutes. Although the port number ranges from
1025 to
32767, generally only a few hundred or thousand can be in use simultaneously. It is therefore possible to occupy all available ports by invoking a Perforce client command many times in rapid succession, such as with a script.
Perforce is based on a client/server architecture. Both the client and server are lightweight in terms of CPU resource consumption; in general, CPU power is not a major consideration when determining the platform on which to install a Perforce server.
Perforce is normally a light user of network resources. Although it is possible that an extremely large user operation could cause the Perforce server to respond slowly, consistently slow responses to
p4 commands are usually caused by network problems. Any of the following can cause slow response times:
A good initial test is to run p4 info. If this does not respond immediately, then there is a network problem. Although solving network problems is beyond the scope of this manual, here are some suggestions for troubleshooting them.
On a client machine, try setting P4PORT to the server's IP address instead of its hostname. For example, instead of using
If p4 info responds immediately when you use the IP address, but not when you use the hostname, the problem is likely related to DNS.
In some cases, p4 commands on Windows can result in a delayed response if they use unquoted filepatterns with a combination of depot syntax and wildcards, such as:
The cause of the problem is the p4 command's use of a Windows function to expand wildcards. When quotes are not used, the function interprets
//depot as a networked computer path and spends time in a futile search for a machine named
depot.
On Windows, the %SystemRoot%\system32\drivers\etc\hosts file can be used to hardcode IP address-hostname pairs. You might be able to work around DNS problems by adding entries to this file. The corresponding UNIX file is
/etc/hosts.
If none of the above diagnostic steps explains the sluggish response time, it's possible that the
p4 executable itself is on a networked file system that is performing very poorly. To check this, try running:
This merely prints out the version information, without attempting any network access. If you get a slow response, network access to the
p4 executable itself might be the problem. Copying or downloading a copy of
p4 onto a local filesystem should improve response times.
Generally, Perforce's performance depends on the number of files a user tries to manipulate in a single command invocation, not on the size of the depot. That is, syncing a client view of 30 files from a 3,000,000-file depot should not be much slower than syncing a client view of 30 files from a 30-file depot.
•
|
p4 command-line arguments (or selected folders in the case of GUI operations)
|
When the server answers a request, it locks down the database for the duration of the computation phase. For normal operations, this is a successful strategy, because the server can "get in and out" quickly enough to avoid a backlog of requests. Abnormally large requests, however, can take seconds, sometimes even minutes. If frustrated users press CTRL-C and retry, the problem gets even worse; the server consumes more memory and responds even more slowly.
At sites with very large depots, unrestricted views and unqualified commands make a Perforce server work much harder than it needs to. Users and administrators can ease load on their servers by:
In the loose view, the entire depot was mapped into the client workspace; for most users, this can be "tightened" considerably. The following view, for example, is restricted to specific areas of the depot:
//depot/main/srv/devA/... //workspace/main/srv/devA/... //depot/main/drv/lport/... //workspace/main/dvr/lport/... //depot/rel2.0/srv/devA/bin/... //workspace/rel2.0/srv/devA/bin/... //depot/qa/s6test/dvr/... //workspace/qa/s6test/dvr/...
|
Two of the techniques for script optimization (described in Using branch views and
The temporary client workspace trick) rely on similar techniques. By limiting the size of the view available to a command, fewer commands need to be run, and when run, the commands require fewer resources.
Protections (see Administering Perforce: Protections) are actually another type of Perforce view. Protections are set with the
p4 protect command and control which depot files can be affected by commands run by users.
Unlike client, branch, and label views, however, the views used by protections can be set only by Perforce superusers. (Protections also control read and write permission to depot files, but the permission levels themselves have no impact on server performance.) By assigning protections in Perforce, a Perforce superuser can effectively limit the size of a user's view, even if the user is using "loose" client specifications.
write user sam * //depot/admin/... write group rocketdev * //depot/rocket/main/... write group rocketrel2 * //depot/rocket/rel2.0/...
|
Perforce groups are created by superusers with the p4 group command. Not only do they make it easier to assign protections, they also provide useful fail-safe mechanisms in the form of
maxresults and
maxscanrows, described in the next section.
Each Perforce group has an associated maxresults,
maxscanrows, and
maxlocktime value. The default for each is
unset, but a superuser can use
p4 group to limit it for any given group.
MaxResults prevents the server from using excessive memory by limiting the amount of data buffered during command execution. Users in limited groups are unable to run any commands that buffer more database rows than the group's
MaxResults limit. (For most sites,
MaxResults should be larger than the largest number of files anticipated in any one user's individual client workspace.)
Like MaxResults,
MaxScanRows prevents certain user commands from placing excessive demands on the server. (Typically, the number of rows scanned in a single operation is roughly equal to
MaxResults multiplied by the average number of revisions per file in the depot.)
Finally, MaxLockTime is used to prevent certain commands from locking the database for prolonged periods of time. Set
MaxLockTime to the number of milliseconds for the longest permissible database lock.
To set these limits, fill in the appropriate fields in the p4 group form. If a user is listed in multiple groups, the
highest of the
MaxResults (or
MaxScanRows, or
MaxLockTime) limits (including
unlimited, but
not including the default
unset setting) for those groups is taken as the user's
MaxResults (or
MaxScanRows, or
MaxLockTime) value.
Group: rocketdev MaxResults: 20000 MaxScanRows: 100000 MaxLockTime: 30000 Timeout: 43200 Subgroups: Owners: Users: bill ruth sandy
|
Her sync command is rejected if the depot contains more than 20,000 files. She can work around this limitation either by restricting her client view, or, if she needs all of the files in the view, by syncing smaller sets of files at a time, as follows:
To remove any limits on the number of result lines processed (or database rows scanned, or milliseconds of database locking time) for a particular group, set the
MaxResults or
MaxScanRows, or
MaxLockTime value for that group to
unlimited.
Because these limitations can make life difficult for your users, do not use them unless you find that certain operations are slowing down your server. Because some Perforce client programs can perform large operations, you should typically set
MaxResults no smaller than 10,000, set
MaxScanRows no smaller than 50,000, and
MaxLockTime to somewhere within the1000-30000 (1-30 second) range.
As mentioned earlier, if a user is listed in multiple groups, the highest numeric MaxResults limit of all the groups a user belongs to is the limit that affects the user.
The default value of unset is
not a numeric limit; if a user is in a group where
MaxResults is set to
unset, he or she is still limited by the highest numeric
MaxResults (or
MaxScanRows or
MaxLockTime) setting of the other groups of which he or she is a member.
A user's commands are truly unlimited only when the user belongs to no groups, or when any of the groups of which the user is a member have their
MaxResults set to
unlimited.
The Perforce Command-Line Client, p4, supports the scripting of any command that can be run interactively. The Perforce server can process commands far faster than users can issue them, so in an all-interactive environment, response time is excellent. However,
p4 commands issued by scripts - triggers, review daemons, or command wrappers, for example - can cause performance problems if you haven't paid attention to their efficiency. This is not because
p4 commands are inherently inefficient, but because the way one invokes
p4 as an interactive user isn't necessarily suitable for repeated iterations.
Each Perforce command issued causes a connection thread to be created and a p4d subprocess to be started. Reducing the number of Perforce commands your script runs is the first step to making it more efficient.
To this end, scripts should never iterate through files running Perforce commands when they can accomplish the same thing by running one Perforce command on a list of files and iterating through the command results.
Any Perforce command that accepts a list of files as a command-line argument can also read the same argument list from a file. Scripts can make use of the list input file feature by building up a list of files first, and then passing the list file to
p4 -x.
The -x flag instructs
p4 to read arguments, one per line, from the named file. If the file is specified as
- (a dash), the standard input is read.
Branch views can be used with p4 integrate or
p4 diff2 to reduce the number of Perforce command invocations. For example, you might have a script that runs:
p4 diff2 pathA/src/... pathB/src/...
p4 diff2 pathA/tests/... pathB/tests/...
p4 diff2 pathA/doc/... pathB/doc/...
Branch: pathA-pathB View: pathA/src/... pathB/src/... pathA/tests/... pathB/tests/... pathA/doc/... pathB/doc/...
|
Repeated references to large labels can be particularly costly. Commands that refer to files using labels as revisions will scan the whole label once for each file argument. To keep from hogging the Perforce server, your script should get the labeled files from the server, and then scan the output for the files it needs.
Most Perforce commands can process all the files in the current workspace view with a single command-line argument. By making use of a temporary client workspace with a view that contains only the files on which you want to work, you might be able to reduce the number of commands you have to run, or to reduce the number of file arguments you need to give each command.
Client: XY-temp View: pathA/src/... //XY-temp/pathA/src/... pathB/tests/... //XY-temp/pathB/tests/... pathC/doc/... //XY-temp/pathC/doc/...
|
By default, revisions of files of type binary are compressed when stored on the Perforce server.
Some file formats (for example, .GIF and .JPG images, .MPG and .AVI media content, files compressed with
.gz and
.ZIP compression) include compression as part of the file format. Attempting to compress such files on the Perforce server results in the consumption of server CPU resources with little or no savings in disk space.
To disable server storage compression for these file types, specify such files as type binary+F (binary, stored on the server in full, without compression) either from the command line or from the
p4 typemap table.
For more about p4 typemap, including a sample typemap table, see
Defining filetypes with p4 typemap.
Perforce's internal database stores its data in structures called Bayer trees, more commonly referred to as B-trees. While B-trees are a very common way to structure data for rapid access, over time, the process of adding and deleting elements to and from the trees can eventually lead to imbalances in the data structure.
Eventually, the tree can become sufficiently unbalanced that performance is negatively affected. The Perforce checkpoint and restore processes (see
Backup and recovery concepts) re-create the trees in a balanced manner, and consequently, you might see some increase in server performance following a backup, a removal of the
db.* files, and the re-creation of the
db.* files from a checkpoint.
Rebalancing the trees is normally useful only if the database files have become more than about 10 times the size of the checkpoint. Given the length of time required for the trees to become unbalanced during normal Perforce use, we expect that the majority of sites will never need to restore the database from a checkpoint (that is, rebalance the trees) for performance reasons.
Copyright 1997-2009 Perforce Software.