www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - synchronized performance

A synthetic benchmark for the synchronized, in D and Java:

  LDC with synchronized:     8.96
  LDC without synchronized:  0.02
  Java with synchronized:    0.68 (-server)
  Java without synchronized: 0.27 (-server)

Defining Foo as "scope" in D produces similar timings.

// D version
version (Tango) import tango.stdc.stdio: printf;
final class Foo {
    int x;
    this(int x) { this.x = x; }
    public synchronized int next() {
        return x;
void main() {
    auto f = new Foo(0);
    int res;
    for (int i = 0; i < 100000000; i++)
        res = f.next();
    printf("%d\n", res);


// Java version
final class Foo {
    int x;
    public Foo(int x) { this.x = x; }
    public synchronized int next() {
        return x;
public final class Sync {
    public static void main(String args[]) {
        Foo f = new Foo(0);
        int res = 0;
        for (int i = 0; i < 100000000; i++)
            res = f.next();

Asm produced by LDC (next() is inlined):

	pushl	%ebx
	pushl	%edi
	pushl	%esi
	subl	$8, %esp
	movl	$_D6test_d3Foo7__ClassZ, (%esp)
	call	_d_allocclass
	movl	$_D6test_d3Foo6__vtblZ, (%eax)
	movl	$0, 4(%eax)
	movl	$0, 8(%eax)
	movl	$100000000, %esi
	movl	%eax, %edi
	.align	16
	movl	%edi, (%esp)
	call	_d_monitorenter
	movl	8(%edi), %ebx
	incl	%ebx
	movl	%ebx, 8(%edi)
	movl	%edi, (%esp)
	call	_d_monitorexit
	decl	%esi
	jne	.LBB3_1
	movl	%ebx, 4(%esp)
	movl	$.str1, (%esp)
	call	printf
	xorl	%eax, %eax
	addl	$8, %esp
	popl	%esi
	popl	%edi
	popl	%ebx
	ret	$8

This is from the disassembly of the inner loop with "scope" (compiled with LDC
with link-time optimization), the code is about the same:

 80495d0:	mov    %edi,(%esp)
 80495d3:	call   804d030 <_d_monitorenter>
 80495d8:	mov    0x10(%esp),%ebx
 80495dc:	inc    %ebx
 80495dd:	mov    %ebx,0x10(%esp)
 80495e1:	mov    %edi,(%esp)
 80495e4:	call   804d070 <_d_monitorexit>
 80495e9:	inc    %esi
 80495ea:	cmp    $0x5f5e0ff,%esi
 80495f0:	jle    80495d0 <_Dmain+0x30>

The disassembly of _d_monitorenter and _d_monitorexit, that contain several
other calls:

0804d030 <_d_monitorenter>:
 804d030:	push   %edi
 804d031:	push   %esi
 804d032:	sub    $0x4,%esp
 804d035:	mov    0x10(%esp),%esi
 804d039:	mov    0x4(%esi),%eax
 804d03c:	test   %eax,%eax
 804d03e:	jne    804d04b <_d_monitorenter+0x1b>
 804d040:	mov    %esi,(%esp)
 804d043:	call   804e9c0 <_d_monitor_create>
 804d048:	mov    0x4(%esi),%eax
 804d04b:	mov    (%eax),%edi
 804d04d:	test   %edi,%edi
 804d04f:	jne    804d05f <_d_monitorenter+0x2f>
 804d051:	mov    %esi,(%esp)
 804d054:	call   804e900 <_d_monitor_lock>
 804d059:	add    $0x4,%esp
 804d05c:	pop    %esi
 804d05d:	pop    %edi
 804d05e:	ret    
 804d05f:	mov    %edi,(%esp)
 804d062:	call   8057620 <_d_toObject>
 804d067:	mov    (%edi),%ecx
 804d069:	call   *0x4(%ecx)
 804d06c:	jmp    804d059 <_d_monitorenter+0x29>
 804d06e:	xchg   %ax,%ax

0804d070 <_d_monitorexit>:
 804d070:	push   %esi
 804d071:	sub    $0x8,%esp
 804d074:	mov    0x10(%esp),%eax
 804d078:	mov    0x4(%eax),%ecx
 804d07b:	mov    (%ecx),%esi
 804d07d:	test   %esi,%esi
 804d07f:	jne    804d08e <_d_monitorexit+0x1e>
 804d081:	mov    %eax,(%esp)
 804d084:	call   804e8b0 <_d_monitor_unlock>
 804d089:	add    $0x8,%esp
 804d08c:	pop    %esi
 804d08d:	ret    
 804d08e:	mov    %esi,(%esp)
 804d091:	call   8057620 <_d_toObject>
 804d096:	mov    (%esi),%ecx
 804d098:	call   *0x8(%ecx)
 804d09b:	jmp    804d089 <_d_monitorexit+0x19>
 804d09d:	lea    0x0(%esi),%esi

Nov 05 2009