Java: counting / profiling synchronization calls

I am looking for a way to list all the synchronization calls of a running parallel Java application in order to detect scalability issues (in terms of threads / cores). As I understand it, every time a synchronized block is entered, the machine needs to synchronize caches. This affects all running processors (in several ways, for example, memory bandwidth), even if running tasks are not blocked by entering a synchronized area.

Setup:

I have a large application that is parallelized at a higher level, that is, it performs complex tasks that are performed in parallel. Parallelization works in the sense that all cores are under load and I have no blocked threads. However, performance does not scale with kernels, which may have several reasons. The specific possible reason I'm interested in is that there are many synchronization calls (e.g. entering a synchronized block using a lock, etc.).

Task

I would like to know what places in my code (which are actually being executed) have such a synchronization call and how often each synchronization is performed. There are many libraries with links, so it’s impossible to use a regular code search by the synchronization keyword or something like that, because it will lead to a search for a large number of never-executable code and cause a lot of false positives. The ideal solution is to have a profiler that lists all the synchronization locations that are running and the number of calls. However, the profilers I tried only allow you to count method calls. Therefore, the problem is to find all the methods that are really relevant.

, , - ( ). , .. . , .

, .

.

+4
4

, . synchronized CAS no-op, UseBiasedLocking . Instrumentation API, .

- . JVM (. ). JVMTI.

. . . , @PeterLawrey , , .

+3

. , , , , , . , .

, , , . , , , . , .

; , , , , Java , , , -5 -10, , .

+3

java, jdk jdk1.8.XX.XX\bin. visualVM jmc ( java) , . (log4j ), .

+1

, . , BufferedOutputStream 1/4 . 100 nop. .

import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class BenchmarkTest {

    public static void main( String[] args ) throws IOException {
        while( true ) {
//            testNop();
            testSync();
            testNoSync();
        }
    }

    static void testNop() throws IOException {
        BenchmarkTest test = new BenchmarkTest();
        test.out = new OutputStream() {
            @Override
            public void write( int b ) throws IOException {
                // nop
            }
        };
        test.run( "            nop OutputStream" );
    }

    static void testSync() throws IOException {
        BenchmarkTest test = new BenchmarkTest();
        test.out = new BufferedOutputStream( new OutputStream() {
            @Override
            public void write( int b ) throws IOException {
                // nop
            }
        }, 32768 );
        test.run( "   sync BufferedOutputStream" );
    }

    static void testNoSync() throws IOException {
        BenchmarkTest test = new BenchmarkTest();
        test.out = new FastBufferedOutputStream( new OutputStream() {
            @Override
            public void write( int b ) throws IOException {
                // nop
            }
        }, 32768 );
        test.run( "no sync BufferedOutputStream" );
    }

    private OutputStream out;

    void run( String testName ) throws IOException {
        long time = System.currentTimeMillis();
        for( int i = 0; i < 100_000_000; i++ ) {
            out.write( i );
        }
        System.out.println( testName + " time: " + (System.currentTimeMillis() - time) );
    }

    static public class FastBufferedOutputStream extends OutputStream {
        private byte[]       buf;

        private int          count;

        private OutputStream out;

        /**
         * Creates a BufferedOutputStream without synchronized.
         *
         * @param out the underlying output stream.
         */
        public FastBufferedOutputStream( OutputStream out ) {
            this( out, 8192 );
        }

        /**
         * Creates a BufferedOutputStream without synchronized.
         *
         * @param out the underlying output stream.
         * @param size the buffer size.
         * @exception IllegalArgumentException if size &lt;= 0.
         */
        public FastBufferedOutputStream( OutputStream out, int size ) {
            this.out = out;
            this.buf = new byte[size];
        }

        /**
         * Flush the internal buffer
         * 
         * @throws IOException if any I/O error occur
         */
        private void flushBuffer() throws IOException {
            if( count > 0 ) {
                out.write( buf, 0, count );
                count = 0;
            }
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public void write( int b ) throws IOException {
            if( count >= buf.length ) {
                flushBuffer();
            }
            buf[count++] = (byte)b;
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public void write( byte[] b, int off, int len ) throws IOException {
            if( len >= buf.length ) {
                /* If the request length exceeds the size of the output buffer,
                   flush the output buffer and then write the data directly.
                   In this way buffered streams will cascade harmlessly. */
                flushBuffer();
                out.write( b, off, len );
                return;
            }
            if( len > buf.length - count ) {
                flushBuffer();
            }
            System.arraycopy( b, off, buf, count, len );
            count += len;
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public void flush() throws IOException {
            flushBuffer();
            out.flush();
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public void close() throws IOException {
            flushBuffer();
            out.close();
        }
    }
}
0

Source: https://habr.com/ru/post/1616245/


All Articles