Showing posts with label Performance. Show all posts
Showing posts with label Performance. Show all posts

27.6.13

Disk Performance




Test on my old Linux PC, with a SATA drive:

  Model: "Hitachi HTS54168"
  Vendor: "Hitachi"
  Device: "HTS54168"
  Revision: "SB2O"
  Driver: "ahci", "sd"
  Driver Modules: "ahci"
  Device File: /dev/sda
  Size: 156301488 sectors a 512 bytes
  Attached to: #16 (SATA controller)

$ dd if=/dev/zero of=zero.bin bs=512 count=1MB conv=notrunc
1000000+0 records in
1000000+0 records out
512000000 bytes (512 MB) copied, 13.8759 s, 36.9 MB/s

Then I tested on a VM:

# dd if=/dev/zero of=zero.bin bs=512 count=1MB conv=notrunc
1000000+0 records in
1000000+0 records out
512000000 bytes (512 MB) copied, 4.3586 seconds, 117 MB/s

# dd if=/dev/zero of=zero.bin bs=512 count=1MB conv=notrunc
1000000+0 records in
1000000+0 records out
512000000 bytes (512 MB) copied, 2.21377 seconds, 231 MB/s

# time dd if=/dev/zero bs=1M count=10K of=dd.out
10240+0 records in
10240+0 records out
10737418240 bytes (11 GB) copied, 9.63733 seconds, 1.1 GB/s

Test with a simple Java program:
* PC/SATA: 
* Server: 913MB/sec

Is it too fast?

26.12.11

Performance Object


The Windows Server 2003 family of operating systems obtains performance data from components in your computer as those components are utilized. That data is described as a performance object and is typically named for the component generating the data. For example, the Processor object is a collection of performance data about processors on your system.

Performance objects are built into the operating system, typically corresponding to the major hardware components such as memory, processors, and so on. Other programs might install their own performance objects. For example, services such as Windows Internet Name Service (WINS) or server programs such as Microsoft Exchange provide performance objects, and performance graphs and logs can monitor these objects.

Each performance object provides performance counters that represent data on specific aspects of a system or service. For example, the Pages/sec counter provided by the Memory object tracks the rate of memory paging.

13.12.11

Let Your Applications Talk to You | Javalobby

Let Your Applications Talk to You | Javalobby

Plumbr | We find your memory leaks!
Amdahl's law - Wikipedia, the free encyclopedia

Every developer tries to solve them differently.
  • Some begin with vmstat or top, 
  • others with a CPU profiler 
  • or a DB load monitoring tool. 
  • Many of them turn to different APM products, like 
    • CA APM, 
    • AppDynamics, 
    • dynaTrace, etc.
And you can get the info without relying on indirect metrics of the operating system or the JVM.

You should take into account 2 things:
  1. When method1 calls method2, which calls method3, which in turn calls method4, then the cumulative total time formethod1 in the table above will contain cumulative times for method2, method3 and method4. So the winner of the chart is not always the method that calls for optimization. But, as a rule of thumb, the top10 will almost always be the right place to look.
  2. Optimize one thing at a time, and after every change re-run your application and gather usage data again. Changing runtime characteristics of one method can change the whole TOP list.
Our preferable way to gather such data is to augment every method in the application with a stop-watch. Just measure the method call time and return time and log the difference alongside with the method name. Such monitoring code can be inserted into the application using different ways: bytecode manipulation, AOP frameworks like Spring AOP or AspectJ, or a manual dynamic proxy.

29.11.11

Stupid performance trick in Java | Javalobby


This class defines six categories of operations upon byte buffers:
  • Absolute and relative get and put methods that read and write single bytes;
  • Relative bulk get methods that transfer contiguous sequences of bytes from this buffer into an array;
  • Relative bulk put methods that transfer contiguous sequences of bytes from a byte array or some other byte buffer into this buffer;
  • Absolute and relative get and put methods that read and write values of other primitive types, translating them to and from sequences of bytes in a particular byte order;
  • Methods for creating view buffers, which allow a byte buffer to be viewed as a buffer containing values of some other primitive type; and
  • Methods for compacting, duplicating, and slicing a byte buffer.
Byte buffers can be created either by allocation, which allocates space for the buffer's content, or by wrapping an existing byte array into a buffer.

Other Useful Information

  • Direct vs. non-direct buffers
  • Access to binary data
  • Invocation chaining

ByteBuffer.compact()


public abstract ByteBuffer compact()
Compacts this buffer  (optional operation).The bytes between the buffer's current position and its limit, if any, are copied to the beginning of the buffer. That is, the byte at index p = position() is copied to index zero, the byte at index p + 1 is copied to index one, and so forth until the byte at index limit() - 1 is copied to index n = limit() - 1 - p. The buffer's position is then set to n+1 and its limit is set to its capacity. The mark, if defined, is discarded.
The buffer's position is set to the number of bytes copied, rather than to zero, so that an invocation of this method can be followed immediately by an invocation of another relative put method.
Invoke this method after writing data from a buffer in case the write was incomplete. The following loop, for example, copies bytes from one channel to another via the buffer buf:
 buf.clear();          // Prepare buffer for use
 for (;;) {
     if (in.read(buf) < 0 && !buf.hasRemaining())
         break;        // No more bytes to transfer
     buf.flip();
     out.write(buf);
     buf.compact();    // In case of partial write
 }

Buffer.clear()

public final Buffer clear()
Clears this buffer. The position is set to zero, the limit is set to the capacity, and the mark is discarded.Invoke this method before using a sequence of channel-read or put operations to fill this buffer. For example:
 buf.clear();     // Prepare buffer for reading
 in.read(buf);    // Read data
This method does not actually erase the data in the buffer, but it is named as if it did because it will most often be used in situations in which that might as well be the case.
Returns:
This buffer

Comparing byte[], direct ByteBuffer, and heap ByteBuffer

Direct ByteBuffers provide very efficient I/O, but getting data into and out of them is more expensive than byte[] arrays. Thus, the fastest choice is going to be application dependent. Amazingly, in my tests, if the buffer size is at least 2048 bytes, it is actually faster to fill a byte[] array, copy it into a direct ByteBuffer, then write that, then to write the byte[] array directly. However for small writes (512 bytes or less), writing the byte[] array using OutputStream is slightly faster. Generally, using NIO can be a performance win, particularly for large writes. You want to allocate a single direct ByteBuffer, and reuse it for all I/O to and from a particular channel. However, you should serialize and deserialize your data using byte[] arrays, since accessing individual elements from a ByteBuffer is slow.

Strangely, these results also seem to suggest that it could be faster to provide an implementation of FileOutputStream that is implemented on top of FileOutputChannel, rather than using the native code that it currently uses. It also seems like it may be possible to provide a JNI library for non-blocking I/O that uses byte[] arrays instead of ByteBuffers, which could be faster. While GetByteArrayElements always makes a copy (see DEFINE_GETSCALARARRAYELEMENTS in JDK7 jni.cpp), GetPrimitiveArrayCritical obtains a pointer, which could then be used for non-blocking I/O. This would trade the overhead of copying for the overhead of pinning/unpinning the garbage collector, so it is unclear if this will be faster, particularly for small writes. It also would introduce the pain of dealing with your own JNI code, and all the portability issues that come with it. However, if you have a very I/O intensive Java application, this could be worth investigating.

28.11.11

Biased Locking, OSR, and Benchmarking Fun | Javalobby

Biased Locking, OSR, and Benchmarking Fun | Javalobby

Java Lock Implementations
Dr. Cliff Click's Blog | Azul Systems
What the heck is OSR and why is it Bad (or Good)? by Dr. Cliff Click | Azul Systems: Blogs
A short conversation on Biased Locking by Dr. Cliff Click | Azul Systems: Blogs

  • In the last post I concluded, based on my experiments, that biased locking was no longer necessary on modern CPUs. 
  • it was not valid because the experiment did not take account of some JVM warm up behaviour that I was unaware of.
  • Cliff Click pointed out that it is much harder for a runtime to optimise a loop part way through, and especially difficult if nested.  For example, bounds checking within the loop may not be possible to eliminate.
  • Dave Dice pointed out that Hotspot does not enable objects for biased locking in the first few seconds (4s at present) of JVM startup.
  • -XX:BiasedLockingStartupDelay=0
My (Martin's) tests in the last post are invalid for the testing of an un-contended biased lock, because the lock was not actually biased.  If you are designing code following the single writer principle, and therefore having un-contended locks when using 3rd party libraries, then having biased locking enabled is a significant performance boost.

23.11.11

Java Lock Implementations | Javalobby

Java Lock Implementations | Javalobby


Mechanical Sympathy: Java Lock Implementations

I would like to quote something from the post here:

JDK locks come with two implementations.  One uses atomic CAS style instructions to manage the claim process.  CAS instructions tend to be the most expensive type of CPU instructions and on x86 have memory ordering semantics.  Often locks are un-contended which gives rise to a possible optimisation whereby a lock can be biased to the un-contended thread using techniques to avoid the use of atomic instructions.  This biasing allows a lock in theory to be quickly reacquired by the same thread.  If the lock turns out to be contended by multiple threads the algorithm with revert from being biased and fall back to the standard approach using atomic instructions.  Biased locking became the default lock implementation with Java 6.

I found that my un-contended thread was incurring a bit more cost than I expected from the lock.




I think some time later, I need to do this test by myself and get back to this post.

22.11.11

InfoQ: State of Performance and Stability in Java 7 Update 1

InfoQ: State of Performance and Stability in Java 7 Update 1


Good to know that Java 7 Update 1 is there now, and it has been there for quite some time.


  • On October 18th, Oracle released Java 7 Update 1, bringing Java 7 much needed stability and fixing a performance optimization issue in which the HotSpot compiler could occasionally lead to incorrect results or could even SIGSEV crashes, as we previously reported. 
  • The same issue is fixed in JDK 6 with Update 29 where it occurred only when -XX:+AggressiveOpts or -XX:+OptimizeStringConcat were used, which is not recommended for production servers.