* Performance and Image Quality

The level of image compression in TurboVNC can be adjusted to balance the
(sometimes conflicting) goals of high image quality and high performance.
There are four options that control the manner in which TurboVNC compresses
images:

	Allow JPEG compression :: {:}
		If this option is enabled, then TurboVNC will use JPEG compression for
		subrectangles that have a high number of unique colors, and it will use
		indexed color subencoding for subrectangles that have a low number of
		unique colors.  If this option is disabled, then TurboVNC will select
		between indexed color or raw subencoding, depending on the size of the
		subrectangle and its color count.

	JPEG image quality :: {:}
		Lower quality levels produce grainier JPEG images with more noticeable
		compression artifacts, but lower quality levels also use less network
		bandwidth and CPU time.

	JPEG chrominance subsampling :: {:}
		When compressing an image using JPEG, the RGB pixels are first converted to
		the YCbCr colorspace, a colorspace in which each pixel is represented as a
		brightness (Y, or "luminance") value and a pair of color (Cb & Cr, or
		"chrominance") values.  After this colorspace conversion, chrominance
		subsampling can be used to discard some of the chrominance components in
		order to save bandwidth.  This works because the human eye is more
		sensitive to changes in brightness than to changes in color.  1X
		subsampling (the default in TurboVNC) retains the chrominance components
		for all pixels, and thus it provides the best image quality but also uses
		the most network bandwidth and CPU time.  2X subsampling retains the
		chrominance components for every other pixel, and 4X subsampling retains
		the chrominance components for every fourth pixel (this is typically
		implemented as 2X subsampling in both X and Y directions.)  Grayscale
		throws out all of the chrominance components, leaving only luminance.  2X
		and 4X subsampling will typically produce noticeable blurring of lines and
		other sharp features, but with photographic or other "smooth" image
		content, it may be difficult to detect any difference between 1X, 2X, and
		4X.

	Compression level :: {:}
		In TurboVNC, the compression level specifies:
		{list type=ol:
			{item: the level of zlib compression that will be used with indexed
				color, mono, and raw subrectangles}
			{item: the "palette threshold" (the minimum number of colors that a
				subrectangle must have before it is encoded as JPEG or raw instead of
				indexed color)}
			{item: whether or not [[#InterframeComparison][interframe comparison]]
				should be used}
		}
		See {ref prefix="Section ": AdvancedCompression} below for more details.

These parameters can be adjusted by accessing the TurboVNC Viewer Options
dialog box (click on the "Options" button in the "TurboVNC Connection" dialog
box or, after connecting to the server, click on the Connection Options button
in the toolbar.)

The TurboVNC Viewer provides five preset "encoding methods", corresponding
to the most useful combinations of the image compression options described
above:

|| Encoding method || Allow JPEG || JPEG image quality || \
	JPEG chrominance subsampling || Compression level || Notes ||
| "Tight + Perceptually Lossless JPEG" | Yes | 95 | 1x | 1 | \
	This encoding method should be perceptually lossless (that is, any image \
	compression artifacts it produces should be imperceptible to human vision) \
	under most viewing conditions.  This encoding method requires a great \
	deal of network bandwidth, however, and is generally not recommended except \
	on 50 Megabit/second and faster networks. |
| "Tight + Medium-Quality JPEG" | Yes | 80 | 2x | 6 | \
	For subrectangles that have a high number of unique colors, this encoding method \
	produces some minor, but generally not very noticeable, image compression \
	artifacts.  All else being equal, this encoding method typically uses about \
	twice the network bandwidth of the "Tight + Low-Quality JPEG" encoding \
	method and about half the bandwidth of the "Tight + Perceptually Lossless \
	JPEG" encoding method, making it appropriate for medium-speed networks such \
	as 10 Megabit Ethernet.  Interframe comparison is enabled with this \
	encoding method (Compression Level 6 = Compression Level 1 + interframe \
	comparison.) |
| "Tight + Low-Quality JPEG" | Yes | 30 | 4x | 7 | \
	For subrectangles that have a high number of unique colors, this encoding method \
	produces very noticeable image compression artifacts.  However, it performs \
	optimally on low-bandwidth connections.  If image quality is more critical \
	than performance, then use one of the other encoding methods or take \
	advantage of the [[#LR][Lossless Refresh feature]].  In addition to \
	reducing the JPEG quality to a "minimum usable" level, this encoding method \
	also enables interframe comparison and Compression Level 2 (CL 7 = CL 2 + \
	interframe comparison.)  Compression Level 2 can reduce bandwidth for \
	low-color application workloads that are not good candidates for JPEG \
	compression. |
| "Lossless Tight" | No | N/A | N/A | 0 | \
	This encoding method uses indexed color subencoding for subrectangles that have \
	a low number of unique colors, but it otherwise does not perform any image \
	compression at all.  Lossless Tight is thus suitable only for gigabit and faster \
	networks.  This encoding method uses significantly less CPU time than any \
	of the JPEG-based encoding methods.  Lossless Tight requires an RFB \
	protocol extension that is, as of this writing, only supported by the \
	TurboVNC Viewer. |
| "Lossless Tight + Zlib" | No | N/A | N/A | 6 | \
	This encoding method uses indexed color subencoding for subrectangles that have \
	a low number of unique colors and raw subencoding for subrectangles that have a \
	high number of unique colors.  It compresses all subrectangles using zlib \
	with zlib compression level 1.  For certain types of low-color workloads (CAD \
	applications, in particular), this encoding method may use less network \
	bandwidth than the "Tight + Perceptually Lossless JPEG" encoding method, \
	but it also uses significantly more CPU time than any of the JPEG-based \
	encoding methods.  Interframe comparison is enabled with this encoding \
	method (Compression Level 6 = Compression Level 1 + interframe \
	comparison.) |
#CAP: TurboVNC Encoding Methods

The encoding method can be set in the TurboVNC Viewer Options dialog box (click
on the "Options" button in the "TurboVNC Connection" dialog box or, after
connecting to the server, click on the Connection Options button in the
toolbar.)

** Interframe Comparison
{anchor: InterframeComparison}

Certain ill-behaved applications can sometimes draw the same thing over and
over again, and this can cause redundant framebuffer updates to be sent to the
VNC viewer.  The TurboVNC Server can guard against this by maintaining a copy
of the remote framebuffer for each connected viewer, comparing each new
framebuffer update rectangle against the pixels in the framebuffer copy, and
discarding any redundant portions of the rectangle before they are sent to the
viewer.

Interframe comparison has some tradeoffs associated with it.  Perhaps the most
important of these is that it increases the memory usage of the TurboVNC Server
by a factor of N, where N is the number of connected viewers.  This can prove
to be quite significant if the remote desktop size is relatively large.

2D applications are most often the ones that generate duplicate framebuffer
updates, so using interframe comparison with such applications can
significantly reduce the network usage and the server CPU usage (since fewer
rectangles are actually being encoded.)  However, with 3D applications, the
benefits of interframe comparison are less clear, since it is less common for
those applications to generate duplicate framebuffer updates.  Interframe
comparison may benefit certain classes of 3D applications, such as design
applications that render a model against a static background-- particularly
when the model is not zoomed in enough to fill the entire window.  In
real-world tests, however, interframe comparison rarely reduces the network
usage for 3D applications by more than 5-10%.  Furthermore, with games and
other immersive applications that modify most of the pixels on the screen each
time a frame is rendered, interframe comparison can actually increase both CPU
usage and network usage.  Furthermore, the effects of duplicate framebuffer
updates are not typically noticeable on high-speed networks, but an increase in
server CPU usage might be.

For these reasons, interframe comparison is not enabled by default and should
not generally be enabled except on low-bandwidth networks and with applications
for which it can be shown to be beneficial.  Interframe comparison can be
enabled by either passing an argument of ''-interframe'' to ''vncserver'' when
starting a TurboVNC Server session or by requesting a compression level of 5 or
higher from the viewer (see below.)

** Advanced Compression Options
{anchor: AdvancedCompression}

One of the underlying principles of TurboVNC's design is to expose only the
options that have proven to be useful (that is, the options that have proven to
have good performance tradeoffs.)  Thus, the TurboVNC Viewer GUI will normally
only allow you to select Compression Levels 1-2 if JPEG subencoding is enabled
(6-7 if interframe comparison is also enabled) or Compression Levels 0-1 if
JPEG subencoding is disabled (5-6 if interframe comparison is enabled.)  Other
compression levels can, however, be specified on the command line (or as a
parameter, if using the Java TurboVNC Viewer), and doing so will enable a
compatibility mode in the TurboVNC Viewer GUI that allows any compression level
from 0 to 9 to be requested.

When connecting to a TurboVNC server, requesting a particular compression level
has the following effect:

|| Compression level || Zlib compression level (non-JPEG subrectangles) || \
	Palette threshold || Interframe comparison || Notes ||
| 0 | 1 | 24 | No | Same as Compression Level 1.  Bypassing zlib when JPEG is \
	enabled would only reduce the CPU usage for non-JPEG subrectangles, which \
	is of limited usefulness.  Further, bypassing zlib requires an RFB protocol \
	extension that is not supported by non-TurboVNC viewers.  It is presumed \
	that, if one wants to reduce the CPU usage, then one wants to do so for all \
	subrectangles, so CL 0 without JPEG (AKA "Lossless Tight") should be used. |
| 1 | 1 | 24 | No | See the description of the "Tight + JPEG" encoding \
	methods above. |
| 2 | 3 | 96 | No | A higher palette threshold causes indexed color \
	subencoding to be used more often than with CL 1, and indexed color \
	subrectangles are compressed using a higher zlib compression level.  This \
	can provide typically 20-40% better compression than CL 1 (with a \
	commensurate increase in CPU usage) for workloads that have a low number of \
	unique colors.  However, Compression Level 2 can increase the CPU usage \
	for some high-color workloads without providing significantly better \
	compression. |
| 3-4 | 3 | 96 | No | Same as Compression Level 2 (reserved for future expansion) |
| 5-6 | 1 | 24 | Yes | Same as Compression Level 1, but with interframe \
	comparison enabled |
| 7-8 | 3 | 96 | Yes | Same as Compression Level 2, but with interframe \
	comparison enabled |
| 9 | 7 | 256 | Yes | This mode is included only for backward compatibility \
	with TightVNC.  It provides approximately the same level of compression for \
	2D applications as Compression Level 9 in TightVNC 1.3.x, while using much less \
	CPU time.  It also provides much better compression than TightVNC for 3D \
	and video applications.  However, relative to Compression Level 2, this \
	mode uses approximately twice as much CPU time and only achieves about \
	10-20% better average compression for 2D apps (and has no noticeable \
	benefit for 3D and video apps.)  Thus, its usefulness is generally very \
	limited. |
#CAP: Compression Levels Supported by the TurboVNC Server (JPEG Enabled)

{:}

|| Compression Level || Zlib compression level (indexed color subrectangles) \
	|| Zlib compression level (raw subrectangles) || Palette threshold \
	|| Interframe comparison || Notes ||
| 0 | None | None | Subrectangle size / 4 | No | See the description \
	of the "Lossless Tight" encoding method above. |
| 1 | 1 | 1 | Subrectangle size / 96 | No | See the description of the \
	"Lossless Tight + Zlib" encoding method above. |
| 2-4 | 1 | 1 | Subrectangle size / 96 | No | Same as Compression Level 1 (reserved for future expansion) |
| 5 | None | None | Subrectangle size / 4 | Yes | Same as Compression Level \
	0, but with interframe comparison enabled |
| 6-8 | 1 | 1 | Subrectangle size / 96 | Yes | Same as Compression Level 1, \
	but with interframe comparison enabled |
| 9 | 7 | 5 | Subrectangle size / 96 | Yes | This mode is included only for \
	backward compatibility with TightVNC.  It provides approximately the same \
	level of compression for 2D applications as Compression Level 9 in \
	TightVNC 1.3.x, while using much less CPU time.  It also provides much better \
	compression than TightVNC for 3D and video applications.  However, relative \
	to Compression Level 1, this mode uses approximately twice as much CPU time \
	and only achieves about 10% better average compression for 2D apps (and \
	has no noticeable benefit for 3D and video apps.)  Thus, its usefulness is \
	generally very limited. |
#CAP: Compression Levels Supported by the TurboVNC Server (JPEG Disabled)

** Lossless Refresh
{anchor: LR}

Since both of TurboVNC's mathematically lossless encoding methods have
performance drawbacks, another option for image-quality-critical applications
is the "Lossless Refresh" feature.  When a lossless refresh is requested by a
TurboVNC viewer, the server will send a mathematically lossless image of the
current TurboVNC desktop to the requesting viewer.  So, for instance, a user
can rotate/pan/zoom an object in their 3D application using a very low-quality
JPEG setting, then when that user is ready to interpret or analyze the object,
they can request a lossless refresh of TurboVNC's virtual screen.

To perform a lossless refresh, press CTRL-ALT-SHIFT-L or click on the Lossless
Refresh toolbar icon.

** Automatic Lossless Refresh
{anchor: ALR}

Passing an argument of ''-alr ''__''{timeout}''__ to ''vncserver'' will
enable the automatic lossless refresh (ALR) feature for the TurboVNC
session.  ALR will monitor all of the VNC viewer connections, and if more than
__''{timeout}''__ seconds have elapsed since the last framebuffer update was
sent to a given viewer, then the TurboVNC Server will send to that viewer a
mathematically lossless copy of any "ALR-eligible" screen regions that have
been affected by lossy compression.  You can also pass arguments of
''-alrqual'' and ''-alrsamp'' to ''vncserver'' to specify that automatic
lossless refreshes should be sent using JPEG instead (see the ''Xvnc'' man page
for details.)

The ALR feature is designed mainly for use with interactive visualization
applications.  The idea is that, on a low-bandwidth connection, low-quality
JPEG can be used while the 3D scene is rotated/panned/zoomed, but when the
motion stops, a fully lossless copy of the 3D image is sent and can be studied
in detail.

The default is for any regions drawn with ''X[Shm]PutImage()'' to be
ALR-eligible, as well as any regions drawn with CopyRect, if the source of the
CopyRect operation was affected by lossy compression (CopyRect is an RFB
encoding that allows the server to request that the viewer move a rectangle of
pixels from one location to another.)  When used with VirtualGL, this means
that ALRs will mainly be sent for just the 3D screen regions.  This should be
fine for most 3D applications, since the 3D regions are the ones that are
quality-critical.  The default ALR behavior also prevents what might best be
called the "blinking cursor dilemma."  Certain ill-behaved window managers
update a small region of the taskbar continuously, even though none of the
pixels in that region have changed.  Also, certain programs have a blinking
cursor that may update more frequently than the ALR timeout.  Since an ALR is
triggered based on a period of inactivity relative to the last framebuffer
update, these continuous updates prevent an ALR from ever being sent.
Fortunately, these ill-behaved window managers and blinking cursors do not
typically use ''X[Shm]PutImage()'' to perform their updates, so the problem is
effectively worked around by limiting the ALR-eligible regions to just the
subset of regions that were drawn with ''X[Shm]PutImage()'' and CopyRect.

You can override the default ALR behavior, thus making all screen regions
eligible for ALR, by setting the ''TVNC_ALRALL'' environment variable to ''1''
on the TurboVNC server machine prior to starting a TurboVNC session.  You can
also set ''TVNC_ALRCOPYRECT'' to ''0'' to make CopyRect regions ALR-ineligible,
which approximates the behavior of TurboVNC 1.2.1 and prior.

** Multithreading
{anchor: Multithreading}

The TurboVNC Server can use multiple threads to perform image encoding and
compression, thus allowing it to take advantage of multi-core or
multi-processor systems.  The server splits the screen vertically into N tiles,
where N is the number of threads, and assigns each tile to a separate thread.
The scalability of this algorithm is nearly linear when used with demanding 3D
or video applications that fill most of the screen.  However, whether or not
multithreading improves the overall performance of TurboVNC depends largely on
the performance of the viewer and the network.  If either the viewer or the
network is the primary performance bottleneck, then multithreading the server
will not help.  It will almost certainly have no effect on networks slower than
100 Megabit Ethernet or when using the Java TurboVNC Viewer as an applet.

To enable server-side multithreading, set the ''TVNC_MT'' environment variable
to ''1'' on the server prior to starting ''vncserver''.  The default behavior
is to use as many threads as there are cores on the server machine, but you can
set the ''TVNC_NTHREADS'' environment variable to override this.

** Maximizing the Performance of the Java TurboVNC Viewer

*** Accelerated JPEG Decoding
#OPT: noList! plain!

The Java TurboVNC Viewer can be used as a standalone app, in which case it
provides most of the same features as the native TurboVNC viewer.  It can also
load libjpeg-turbo through JNI to accelerate JPEG decoding, which gives the
Java viewer similar performance to the native viewer in most cases.  The
TurboVNC Viewer on Mac and Linux/Un*x platforms is simply the Java TurboVNC
Viewer packaged in such a way that it behaves like a native viewer.  On
Windows, the Java TurboVNC Viewer is packaged similarly, but it is included
alongside the native TurboVNC Viewer, giving users a choice between the two.
The Java TurboVNC Viewer packaging includes the libjpeg-turbo JNI library,
which is automatically loaded when you launch the TurboVNC Viewer app on Mac,
run the ''vncviewer'' script on Linux/Un*x, run the ''vncviewer-java.bat''
script on Windows, or launch "Java TurboVNC Viewer" from the Windows Start
Menu.  Thus, if you are running the Java TurboVNC Viewer in one of those ways,
then no further action is needed to accelerate it.

If you suspect for whatever reason that JPEG decoding is not being accelerated,
then the easiest way to check is to open the "Connection Info" dialog (after
the connection to the server has been established) and verify that the "JPEG
decompression" field says "Turbo".  If you are launching the Java TurboVNC
Viewer from the command line, then it will also print a warning if it is unable
to load libjpeg-turbo.

*** Windows Blitting Performance
#OPT: noList! plain!

The default in Java 2D on Windows platforms is to use Direct3D for blitting,
but in the case of TurboVNC, using GDI blitting is almost always much faster.
If you are using Java 7 or later, or if you are running the Java TurboVNC
Viewer using the ''vncviewer-java.bat'' script or launching it using the
Windows Start Menu shortcut, then Direct3D blitting will be disabled by
default, and no further action is necessary.  Otherwise, you should consider
setting the ''sun.java2d.d3d'' system property to ''false'' (for instance, by
passing ''-Dsun.java2d.d3d=false'' as an argument to ''java''.)  You can use
the ImageDrawTest benchmark to verify whether Direct3D blitting is enabled or
disabled.  To do this, execute the following command:

	#Verb: <<---
	java -Dsun.java2d.trace=count -cp "c:\Program Files\TurboVNC\Java\VncViewer.jar" com.turbovnc.vncviewer.ImageDrawTest
	---

Let the benchmark run for 15 or 20 seconds, then abort it with CTRL-C.  Looking
at the Java 2D trace output will reveal which underlying API (such as Windows
GDI, OpenGL, Direct3D, etc.) is being used to draw the images.

*** Mac Blitting Performance
#OPT: noList! plain!
{anchor: MacJavaPerf}

The Oracle Java plugin (Java 7 or later) is used on OS X 10.7 and later when
launching the Java TurboVNC Viewer as an applet or using Java Web Start.  When
using TurboVNC as a standalone application, there are two packages provided:
one that uses the afore-mentioned Oracle Java plugin and one that uses Apple's
distribution of Java (Java for OS X.)  The tradeoffs between the two Java
flavors are as follows:

Java for OS X:

	* Pre-installed on OS X 10.6 and earlier (can be installed on later OS X
	releases by downloading the Java for OS X package from Apple Support)
	* Includes a Quartz-accelerated Java 2D blitter that provides optimal
	performance for TurboVNC on older Macs (those containing nVidia and Intel HD
	Graphics GPUs, specifically)

Oracle Java 7 and later:

	* Requires OS X 10.7 or later
	* Uses OpenGL for Java 2D blitting, which provides optimal performance for
	TurboVNC on newer Macs (those containing Intel Iris GPUs, specifically--
	Java for OS X does not appear to include Java 2D hardware acceleration for
	those GPUs)

If you are unsure which package to use, then you can compare the performance
of both of them using the ImageDrawTest benchmark:

	#Verb: <<---
	java -cp /Applications/TurboVNC/TurboVNC\ Viewer.app/Contents/Resources/Java/VncViewer.jar com.turbovnc.vncviewer.ImageDrawTest
	---

	!!! NOTE: if you intend to use the desktop scaling feature in the Java
	TurboVNC Viewer along with the Oracle Java plugin, then upgrade the plugin
	to Java 8 Update 40 or later.  Java 8 Update 40 includes a fix for a severe
	performance issue in the OpenGL Java 2D blitter that affected scaled
	blitting.

*** Using the Server VM
#OPT: noList! plain!

Passing an argument of ''-server'' to ''java'' when launching the Java TurboVNC
Viewer is recommended.  This enables the adaptive compiler, which performs
aggressive code optimizations and actually learns how to better optimize a
piece of code the more times it encounters it.  Such optimizations greatly
improve the decoding performance for non-JPEG subrectangles.  If you are
launching the Java TurboVNC Viewer using the Mac app, the
''vncviewer'' or''vncviewer-java.bat'' scripts, or the Windows Start Menu
shortcut, then the Server VM is automatically enabled.
