Thread overview
multithread GC more slower?
Jun 15, 2009
zsxxsz
Jun 15, 2009
zsxxsz
Jun 17, 2009
Sean Kelly
June 15, 2009
I start two threads, one is producter and the other is consumer. I found if GC was enable, the time cost was 24 seconds, and if GC was disable, the time cost was 4 seconds. Why is GC so slowly in multi-threads?
Please see the attatchment.


June 15, 2009
== Quote from zsxxsz (zhengshuxin@hexun.com)'s article
> I start two threads, one is producter and the other is consumer. I found if GC
was enable, the time cost was 24 seconds, and if GC was disable, the time cost was 4 seconds. Why is GC so slowly in multi-threads?

I'm so sorry, the attatchment I post was base64-encoded by the newsgroup, so I show it below:

module test_cond;
import core.sync.mutex;
import core.sync.condition;
import core.thread;
import core.sys.posix.pthread;
import std.c.stdio;
import std.c.stdlib;
import std.c.string;
import std.c.time;
import std.stream;
import core.memory;

private struct Job
{
	Job *next;
	int   i;
}

const bool gc_disable = true;

void test_cond()
{
	Mutex m_mutex = new Mutex;
	Condition m_cond = new Condition(m_mutex);
	Job* m_jobHead = null, m_jobTail = null;
	File fp = new File("out.txt", FileMode.Out | FileMode.In);
	int  max = 1000000;
	time_t begin, end;

	static if (gc_disable) {
		GC.disable();
	}
	void threadProducter()
	{
		for (int i = 0; i < max; i++) {
			Job *job = new Job;
			job.i = i;
			m_mutex.lock();
			if (m_jobHead == null)
				m_jobHead = job;
			else
				m_jobTail.next = job;
			m_jobTail = job;
			m_mutex.unlock();
			m_cond.notify();
		}
	}

	void threadConsummer()
	{
		char buf[256];
		m_mutex.lock();
		for (;;) {
			while (m_jobHead == null) {
				m_cond.wait();
			}
			Job *job = m_jobHead;
			if (job != null)
				m_jobHead = job.next;
			m_mutex.unlock();
			snprintf(cast(char*) buf, buf.sizeof,
				cast(const char*) "doJob thread id: %u, n: %d\n",
				pthread_self(), job.i);
			fp.writeBlock(buf.ptr, strlen(buf.ptr));
			m_mutex.lock();
			if (job.i == max - 1) {
				static if (gc_disable) {
					delete job;
				}
				break;
			}
			static if (gc_disable) {
				delete job;
			}
		}
	}

	Thread consummer = new Thread(&threadConsummer);
	Thread producter = new Thread(&threadProducter);

	begin = time(null);

	producter.start();
	consummer.start();
	producter.join();
	consummer.join();

	end = time(null);

	static if (gc_disable) {
		printf("not use gc: write over, time: %ld\r\n", end - begin);
		GC.enable();
	} else {
		printf("use gc: write over, time: %ld\r\n", end - begin);
	}

	delete fp;
}

June 17, 2009
zsxxsz wrote:
> I start two threads, one is producter and the other is consumer. I found if GC was enable, the time cost was 24 seconds, and if GC was disable, the time cost was 4 seconds. Why is GC so slowly in multi-threads?

If the GC is disabled then no collections will occur until the app is no longer able to obtain any additional memory from the OS.  It's these collections that are adding run time.  You might want to consider deleting the job objects even if the GC is enabled to avoid unnecessary collections.