예제 #1
0
def main(host, user, pw, m, n):
	print "* connecting to", host

	print "* connect to iotdm and clear tree"
	z = iotdm.connect(host, auth=(user, pw))
	r = z.kill()
	print "* delete complete... delaying 2 seconds for iotdm to settle"
	time.sleep(2)
	z = iotdm.connect(host, auth=(user, pw))

	t1 = time.time()
	print "* baseline-process.py start %d processes with %d CRUDs each @ %8.8f" % (m, n, t1)

	procs = []
	q = Queue()
	for i in range(0,m):
		p = Process(target=test, args=(q, host, (user,pw), n,))
		procs.append(p)
		p.start()

	for i in range(0,m):
		procs[i].join()
		if mp.active_children() < 1:
			print i
			break

	while True:
		if q.empty():
			break
		r = q.get()
		print r

	t2 = time.time()
	print "baseline-process.py end @ %8.8f (%8.8f sec)" % (t2, t2-t1)
예제 #2
0
def test(queue, host, a, n):
	cerr = 0
	cttl = 0
	rerr = 0
	rttl = 0
	uerr = 0
	uttl = 0
	derr = 0
	dttl = 0

	resid = None
	tid = os.getpid()

	c = iotdm.connect(host, auth=a)

	if c is None:
		print "- can't connect :", c.error
		return

	queue.put([tid, "start", time.time()])

	for i in range(0, n):
		# create an AE
		q = c.create("InCSE1", iotdm.application)
		if fail(q):
			cerr += 1
			continue
		else:
			resid = iotdm.resid(q)
			cttl += 1

		if resid is None:
			continue

		# retrieve the contentInstance we just created
		q = c.retrieve(resid)
		if fail(q):
			rerr += 1
		else:
			rttl += 1

		# update the container with a new label "b"
		q = c.update(resid, attr={"lbl":["b"]})
		if fail(q):
			uerr += 1
		else:
			uttl += 1

		# delete the contentInstance
		q = c.delete(resid)
		if fail(q):
			derr += 1
		else:
			dttl += 1

	queue.put([tid, "end", time.time(), n, cttl, cerr, rttl, rerr, uttl, uerr, dttl, derr])
예제 #3
0
def test(queue, index, imported, host, a, trans_count):
	tid = os.getpid()

	conn = iotdm.connect(host, auth=a)

	if conn is None:
		print "- can't connect :", conn.error
		return

	t0 = time.time()

	conn.tron()

	argv = None
	if 'args' in imported: argv = imported['args']
	if 'per' in imported: imported['per'](tid, index, conn, trans_count, args=argv)
	if 'run' in imported: imported['run'](tid, index, conn, trans_count, args=argv)

	t1 = time.time()

	file = "%s-%d.pickle" % (script, tid)
	pickle.dump([tid, "end", t0, t1, conn.troff()], open(file, "wb"))
	queue.put([tid, "end", file])
예제 #4
0
		pw = sys.argv[i]
	elif i == 4:
		n = int(sys.argv[i])
	elif i == 5:
		m = int(sys.argv[i])

def fail(r):
	try:
		if r.status_code < 200 or r.status_code > 299:
			return True
	except:
		return True
	return None

print "* connect to iotdm and clear tree"
c = iotdm.connect(host, auth=(user, pw))
c.kill()
print "* delete complete... delaying 2 seconds for iotdm to settle"
time.sleep(2)

t1 = time.time()

print "* depth.py start @ %8.8f" % (t1)

print "* make top AE *"
x = c.create("InCSE1", iotdm.application)
if fail(x):
	print "* can't create top AE"
	exit()
ae = iotdm.resid(x)
print "* top AE ID", ae
예제 #5
0
def connect_to_iotdm(host, user, pw, p):
    return iotdm.connect(host, base="InCSE1", auth=(user, pw), protocol=p)
예제 #6
0
def main(script, host, user, pw, process_count, trans_count, argv):

	print "* validating environment"
	imported = {}
	try: imported['top'] = getattr(__import__(script, fromlist=["top"]), "top")
	except: pass
	try: imported['per'] = getattr(__import__(script, fromlist=["per"]), "per")
	except: pass
	try: imported['fin'] = getattr(__import__(script, fromlist=["fin"]), "fin")
	except: pass
	try: imported['run'] = getattr(__import__(script, fromlist=["run"]), "run")
	except:
		print "! can't find a 'run' method in %s" % (script)
		exit(1)

	print "* connecting to", host
	try: conn = iotdm.connect(host, auth=(user, pw))
	except:
		print "! can't connect"
		exit(0)

	t0 = time.time()
	print "* run '%s' with %d processes and %d iterations @ %8.8f" % (script, process_count, trans_count, t0)

	procs = []
	q = Queue()

	if 'top' in imported: imported['args'] = imported['top'](conn, argv)
	else:
		print "* no 'top' function so clearing tree"
		conn.kill()
		print "* delete complete... delaying 2 seconds for iotdm to settle"
		time.sleep(2)

	if not 'args' in imported: imported['args'] = argv

	print "* starting processes",

	for i in range(0, process_count):
		p = Process(target=test, args=(q, i, imported, host, (user,pw), trans_count,))
		p.daemon = True
		procs.append(p)
		p.start()
		print "%d" % (p.pid),
	print "[done]"

	print "# monitoring"
	while True:
		dead = 0
		for i in range(0, process_count):
			print "%f" % (time.time()),
			print psutil.cpu_percent(interval=.25, percpu=True), "                \r",
			sys.stdout.flush()
			# put cpu sampling info here
			if not procs[i].is_alive(): dead += 1
		if dead == process_count: break
	print ""
	print "# joining"
	for i in range(0, process_count):
		procs[i].join()
		if mp.active_children() < 1:
			print i
			break
	print "# joined"

	trace = {}
	trace['create'] = []
	trace['retrieve'] = []
	trace['update'] = []
	trace['delete'] = []

	pc = 0

	while True:
		if q.empty():
			break
		try:
			r = q.get(block=True, timeout=.25)
		except:
			print "timeout?"
			continue
		if r[1] == "end":
			file = r[2]
			r = pickle.load(open(file, "rb"))
			#os.remove(file)
			trace['create'] += r[4]['create']
			trace['retrieve'] += r[4]['retrieve']
			trace['update'] += r[4]['update']
			trace['delete'] += r[4]['delete']
		else:
			print "timeout?"
			continue
	t1 = time.time()

	# [tid, "end", t0, t1, {['create']=[], ..}]
	# 0     1      2   3   4

	# make flags for zero length arrays
	verb_list = ['create', 'retrieve', 'update', 'delete']

	cf = True
	rf = True
	uf = True
	df = True
	af = True

	attempts = {}
	attempts['combined'] = 0
	errors = {}
	errors['combined'] = 0
	ts = {}
	rt = {}
	for verb in verb_list:
		attempts[verb] = len(trace[verb])
		errors[verb] = 0
		ts[verb] = []
		rt[verb] = []
		for (status_code, time_stamp, round_trip) in trace[verb]:
			if fail(status_code): errors[verb] += 1
			ts[verb].append(time_stamp)
			rt[verb].append(round_trip)
		attempts['combined'] += attempts[verb]
		errors['combined'] += errors[verb]
	
	create_attempts = len(trace['create'])
	retrieve_attempts = len(trace['retrieve'])
	update_attempts = len(trace['update'])
	delete_attempts = len(trace['delete'])

	if create_attempts == 0: cf = None
	if retrieve_attempts == 0: rf = None
	if update_attempts == 0: uf = None
	if delete_attempts == 0: df = None

	verb_attempts = create_attempts + retrieve_attempts + update_attempts + delete_attempts
	if verb_attempts == 0: af = None

	# unwind tuples into individual arrays
	cts = []
	rts = []
	uts = []
	dts = []
	crtt = []
	rrtt = []
	urtt = []
	drtt = []

	create_errors = 0
	retrieve_errors = 0
	update_errors = 0
	delete_errors = 0

	for n in trace['create']:
		(status_code, time_stamp, round_trip) = n
		if fail(status_code): create_errors += 1
		cts.append(time_stamp)
		crtt.append(round_trip)
	for n in trace['retrieve']:
		(status_code, time_stamp, round_trip) = n
		if fail(status_code): retrieve_errors += 1
		rts.append(time_stamp)
		rrtt.append(round_trip)
	for n in trace['update']:
		(status_code, time_stamp, round_trip) = n
		if fail(status_code): update_errors += 1
		uts.append(time_stamp)
		urtt.append(round_trip)
	for n in trace['delete']:
		(status_code, time_stamp, round_trip) = n
		if fail(status_code): delete_errors += 1
		dts.append(time_stamp)
		drtt.append(round_trip)

	verb_errors = create_errors + retrieve_errors + update_errors + delete_errors

	print "* attempted verbs : %d" % (verb_attempts)
	print "* performed verbs : %d" % (verb_attempts - verb_errors)
	for verb in verb_list:
		if attempts[verb] > 0:
			print "  total %8ss : %-6d errors : %-6d mean : %f" % (verb, attempts[verb], errors[verb], numpy.mean(rt[verb]))

	print "* per transaction timing"
	for verb in verb_list:
		if attempts[verb] > 0:
			print "  %8s %f per second" % (verb, attempts[verb] / numpy.sum(rt[verb]))

	'''
	print "* throughput timing (individual stats are likely the same, unless errors occured)"
	if cf: print "  create", create_attempts/(t1-t0)
	if rf: print "retrieve", retrieve_attempts/(t1-t0)
	if uf: print "  update", update_attempts/(t1-t0)
	if df: print "  delete", delete_attempts/(t1-t0)
	if af: print "combined", create_attempts + retrieve_attempts + update_attempts + delete_attempts / (t1-t0)
	'''

	symbol = {"create":"*", "retrieve":"o", "update":"v", "delete":"d"}
	if attempts['combined'] > 0:
		print "* plotting round-trip graph"
		for verb in verb_list:
			if attempts[verb] > 0: plt.plot(ts[verb], rt[verb], symbol[verb], label=verb)
		plt.title("%s round-trip : %d processes, %d total verbs" % (script, process_count, attempts['combined']))
		plt.ylabel('API round-trip time (sec)')
		plt.xlabel('Elapsed time')
		plt.legend(loc='best')
		plt.grid(True)
		plt.savefig("%s-rtt.png" % (script))
		#plt.savefig("%s-rtt.pdf" % (script))
		plt.close()

		print "* creating quantized tables"
		quant = {}
		for verb in verb_list:
			if attempts[verb] > 0:
				quant[verb] = quantize(ts[verb])
				if not 'combined' in quant:
					quant['combined'] = []
					for n in quant[verb]:
						quant['combined'].append(n)
				else:
					for i in range(0, len(quant[verb])):
						quant['combined'][i] += quant[verb][i]

		print "* transactions per second quantized to a whole second"
		for verb in verb_list:
			if attempts[verb] > 0:
				print "%8s" % verb, quant[verb], numpy.sum(quant[verb])
		print "combined", quant['combined'], numpy.sum(quant['combined'])

		print "* plotting transactions per second graph"
		plt.grid(True)
		#fig = plt.figure()
		#ax = plt.subplots()
		n_groups = 0
		for verb in verb_list:
			if attempts[verb] > 0:
				n_groups += len(quant[verb])
				break
		index = numpy.arange(n_groups)
		bar_width = 0.15
		bar_color = {"create":"b", "retrieve":"g", "update":"r", "delete":"c"}
		bc = 0
		for verb in verb_list:
			if attempts[verb] > 0:
				plt.bar(index + bar_width * bc, tuple(quant[verb]), bar_width, color=bar_color[verb], label=verb)
				bc += 1
		if attempts['combined'] > 0:
			plt.bar(index + bar_width * bc, tuple(quant['combined']), bar_width, color='m', label="combined")

		#box = ax.get_position()
		#ax.set_position([box.x0, box.y0 + box.height * 0.1, box.width, box.height * 0.9])

		plt.title("%s TPS : %d processes, %d total verbs" % (script, process_count, attempts['combined']))
		plt.ylabel('Transactions per second')
		plt.xlabel('Elapsed time')
		plt.legend(loc='best')

		# plt.tight_layout()

		plt.savefig("%s-tps.png" % (script))
		#plt.savefig("%s-tps.pdf" % (script))
		plt.close()
	else:
		print "* nothing to plot"

	'''
	if af:
		print "* plotting round-trip graph"
		if cf: plt.plot(cts, crtt, '*', label='create')
		if rf: plt.plot(rts, rrtt, 'o', label='retrieve')
		if uf: plt.plot(uts, urtt, 'v', label='update')
		if df: plt.plot(dts, drtt, 'd', label='delete')
		plt.title("%s round-trip : %d processes, %d total verbs" % (script, process_count, verb_attempts))
		plt.ylabel('API round-trip time (sec)')
		plt.xlabel('Elapsed time')
		plt.legend(loc='best')
		plt.grid(True)
		plt.savefig("%s-rtt.png" % (script))
		#plt.savefig("%s-rtt.pdf" % (script))
		plt.close()

		print "* creating quantized tables"
		if cf: ncts = quantize(cts)
		if rf: nrts = quantize(rts)
		if uf: nuts = quantize(uts)
		if df: ndts = quantize(dts)
		if af: nall = quantize(cts + rts + uts + dts)

		print "* transactions per second quantized to a whole second"
		if cf: print "  create", ncts, numpy.sum(ncts)
		if rf: print "retrieve", nrts, numpy.sum(nrts)
		if uf: print "  update", nuts, numpy.sum(nuts)
		if df: print "  delete", ndts, numpy.sum(ndts)
		if af: print "combined", nall, numpy.sum(nall)

		print "* plotting transactions per second graph"
		plt.grid(True)
		#fig = plt.figure()
		#ax = plt.subplots()

		n_groups = 0
		if cf: n_groups = len(ncts)
		elif rf: n_groups = len(nrts)
		elif uf: n_groups = len(nuts)
		elif df: n_groups = len(ndts)
		index = numpy.arange(n_groups)
		bar_width = 0.15
		if cf: plt.bar(index + bar_width * 0, tuple(ncts), bar_width, color='b', label="create")
		if rf: plt.bar(index + bar_width * 1, tuple(nrts), bar_width, color='g', label="retrieve")
		if uf: plt.bar(index + bar_width * 2, tuple(nuts), bar_width, color='r', label="update")
		if df: plt.bar(index + bar_width * 3, tuple(ndts), bar_width, color='c', label="delete")
		if af: plt.bar(index + bar_width * 4, tuple(nall), bar_width, color='m', label="combined")

		#box = ax.get_position()
		#ax.set_position([box.x0, box.y0 + box.height * 0.1, box.width, box.height * 0.9])
		
		plt.title("%s TPS : %d processes, %d total verbs" % (script, process_count, verb_attempts))
		plt.ylabel('Transactions per second')
		plt.xlabel('Elapsed time')
		plt.legend(loc='best')

		# plt.tight_layout()

		plt.savefig("%s-tps.png" % (script))
		#plt.savefig("%s-tps.pdf" % (script))
		plt.close()
	else:
		print "* nothing to plot"
	'''

	if 'fin' in imported: imported['fin'](conn, args=imported['args'])

	print "'%s' ends @ %8.8f (%8.8f sec)" % (script, t1, t1-t0)
예제 #7
0
def connect_to_iotdm(host, user, pw, p):
    return iotdm.connect(host, base="InCSE1", auth=(user, pw), protocol=p)
예제 #8
0
#!/usr/bin/env python

import iotdm
c = iotdm.connect()
r = c.tree()
print r
if r == None:
	print c.error
예제 #9
0
def test(queue, base_time, host, a, trans_count):
    tid = os.getpid()
    queue.put([tid, "start"])

    ce = True
    re = True
    ue = True
    de = True

    if os.environ.get("CRUD"):
        tmp = str.upper(os.environ.get("CRUD"))
        if "C" not in tmp:
            ce = None
        if "R" not in tmp:
            re = None
        if "U" not in tmp:
            ue = None
        if "D" not in tmp:
            de = None

    name = ""
    if ce:
        name += "C"
    if re:
        name += "R"
    if ue:
        name += "U"
    if de:
        name += "D"

    crtt = []
    rrtt = []
    urtt = []
    drtt = []

    cts = []
    rts = []
    uts = []
    dts = []

    resid = None

    conn = iotdm.connect(host, auth=a)

    if conn is None:
        print "- can't connect :", conn.error
        return

        # make a resource in case create is disabled
    resid = "InCSE1/tid%d" % (tid)
    if not ce:
        conn.create("InCSE1", iotdm.application, str(tid))

    t0 = time.time()

    for i in range(0, trans_count):
        if ce:
            # create an AE
            nt = btime()
            resp = conn.create("InCSE1", iotdm.application)
            if fail(resp):
                continue
            resid = iotdm.resid(resp)
            if elap(resp):
                crtt.append(elap(resp))
                cts.append(nt - base_time)
            if resid is None:
                continue

        if re:
            # retrieve the resource we just created
            nt = btime()
            resp = conn.retrieve(resid)
            if elap(resp):
                rrtt.append(elap(resp))
                rts.append(nt - base_time)

        if ue:
            # update the resource with a new label "b"
            nt = btime()
            resp = conn.update(resid, attr={"lbl": ["b"]})
            if elap(resp):
                urtt.append(elap(resp))
                uts.append(nt - base_time)

        if de:
            # delete the resource
            nt = btime()
            resp = conn.delete(resid)
            if elap(resp):
                drtt.append(elap(resp))
                dts.append(nt - base_time)

    t1 = time.time()

    file = "b1-save.%d" % (tid)
    pickle.dump([tid, "end", t0, t1, crtt, cts, rrtt, rts, urtt, uts, drtt, dts], open(file, "wb"))
    queue.put([tid, "end", file])
예제 #10
0
def main(host, user, pw, thread_count, trans_count):
    print "* connecting to", host

    print "* connect to iotdm and clear tree"
    conn = iotdm.connect(host, auth=(user, pw))
    conn.kill()
    print "* delete complete... delaying 2 seconds for iotdm to settle"
    time.sleep(2)

    t0 = time.time()
    print "* baseline-process.py start %d processes with %d verbs each @ %8.8f" % (thread_count, trans_count, t0)

    procs = []
    q = Queue()

    base_time = btime()

    for i in range(0, thread_count):
        p = Process(target=test, args=(q, base_time, host, (user, pw), trans_count))
        procs.append(p)
        p.start()

    for i in range(0, thread_count):
        procs[i].join()
        if mp.active_children() < 1:
            print i
            break

    crtt = []
    rrtt = []
    urtt = []
    drtt = []

    cts = []
    rts = []
    uts = []
    dts = []

    pc = 0

    print ("* starting processes"),
    while True:
        if q.empty():
            break
        r = q.get()
        if r[1] == "start":
            print (r[0]),
            pc = pc + 1
            if pc == thread_count:
                print "[done]"
        else:
            file = r[2]
            r = pickle.load(open(file, "rb"))
            os.remove(file)
            crtt += r[4]
            rrtt += r[6]
            urtt += r[8]
            drtt += r[10]
            cts += r[5]
            rts += r[7]
            uts += r[9]
            dts += r[11]

    t1 = time.time()

    # [tid, "end", t0, t1, crtt, cts, rrtt, rts, urtt, uts, drtt, dts]
    # 0     1      2   3   4     5    6     7    8     9    10    11

    # make flags for zero length arrays
    cf = True
    rf = True
    uf = True
    df = True
    af = True
    tmp = 4
    if len(crtt) == 0 or len(cts) == 0:
        cf = None
        tmp -= 1
    if len(rrtt) == 0 or len(rts) == 0:
        rf = None
        tmp -= 1
    if len(urtt) == 0 or len(uts) == 0:
        uf = None
        tmp -= 1
    if len(drtt) == 0 or len(dts) == 0:
        df = None
        tmp -= 1

    if tmp <= 1:
        af = None

    trans_count = trans_count * thread_count
    print "* attempted verbs : %d" % (trans_count * 4)
    if cf:
        print "  total creates : %-6d errors : %-6d avg : %f mean : %f time :%f " % (
            len(crtt),
            trans_count - len(crtt),
            numpy.average(crtt),
            numpy.mean(crtt),
            numpy.sum(crtt),
        )
    if rf:
        print "total retrieves : %-6d errors : %-6d avg : %f mean : %f time :%f " % (
            len(rrtt),
            trans_count - len(crtt),
            numpy.average(rrtt),
            numpy.mean(rrtt),
            numpy.sum(rrtt),
        )
    if uf:
        print "  total updates : %-6d errors : %-6d avg : %f mean : %f time :%f " % (
            len(urtt),
            trans_count - len(urtt),
            numpy.average(urtt),
            numpy.mean(urtt),
            numpy.sum(urtt),
        )
    if df:
        print "  total deletes : %-6d errors : %-6d avg : %f mean : %f time :%f " % (
            len(drtt),
            trans_count - len(drtt),
            numpy.average(drtt),
            numpy.mean(drtt),
            numpy.sum(drtt),
        )

    print "* per transaction timing"
    if cf:
        print "  create", len(crtt) / numpy.sum(crtt), "per second"
    if rf:
        print "retrieve", len(rrtt) / numpy.sum(rrtt), "per second"
    if uf:
        print "  update", len(urtt) / numpy.sum(urtt), "per second"
    if df:
        print "  delete", len(drtt) / numpy.sum(drtt), "per second"
    # print "combined", len(crtt + rrtt + urtt +drtt)/numpy.sum(crtt + rrtt + urtt +drtt), "per second"

    print "* throughput timing (individual stats are likely the same, unless errors occured)"
    if cf:
        print "  create", len(crtt) / (t1 - t0)
    if rf:
        print "retrieve", len(rrtt) / (t1 - t0)
    if uf:
        print "  update", len(urtt) / (t1 - t0)
    if df:
        print "  delete", len(drtt) / (t1 - t0)
    if af:
        print "combined", len(crtt + rrtt + urtt + drtt) / (t1 - t0)

    print "* plotting round-trip graphs"
    for i in range(1, 5):
        if cf and i == 1 or i == 2:
            plt.plot(cts, crtt, "*", label="create")
        if rf and i == 1 or i == 3:
            plt.plot(rts, rrtt, "o", label="retrieve")
        if uf and i == 1 or i == 4:
            plt.plot(uts, urtt, "v", label="update")
        if df and i == 1 or i == 5:
            plt.plot(dts, drtt, "d", label="delete")
        plt.title(
            "Baseline round-trip : %d processes, %d transactions/verb" % (thread_count, trans_count / thread_count)
        )
        plt.ylabel("API round-trip time (sec)")
        plt.xlabel("Elapsed time")
        plt.legend(loc="best")
        plt.grid(True)
        plt.savefig("b1-%d.png" % (i))
        plt.savefig("b1-%d.pdf" % (i))
        plt.close()

    print "* creating quantized tables"
    if cf:
        ncts = quantize(cts)
    if rf:
        nrts = quantize(rts)
    if uf:
        nuts = quantize(uts)
    if df:
        ndts = quantize(dts)
    if af:
        nall = quantize(cts + rts + uts + dts)

    print "* transactions per second quantized to a whole second"
    if cf:
        print "  create", ncts, numpy.sum(ncts)
    if rf:
        print "retrieve", nrts, numpy.sum(nrts)
    if uf:
        print "  update", nuts, numpy.sum(nuts)
    if df:
        print "  delete", ndts, numpy.sum(ndts)
    if af:
        print "combined", nall, numpy.sum(nall)

    print "* plotting transactions per second graph"
    plt.grid(True)
    # fig = plt.figure()
    # ax = plt.subplots()

    n_groups = 0
    if cf:
        n_groups = len(ncts)
    elif rf:
        n_groups = len(nrts)
    elif uf:
        n_groups = len(nuts)
    elif df:
        n_groups = len(ndts)
    index = numpy.arange(n_groups)
    bar_width = 0.15
    if cf:
        plt.bar(index + bar_width * 0, tuple(ncts), bar_width, color="b", label="create")
    if rf:
        plt.bar(index + bar_width * 1, tuple(nrts), bar_width, color="g", label="retrieve")
    if uf:
        plt.bar(index + bar_width * 2, tuple(nuts), bar_width, color="r", label="update")
    if df:
        plt.bar(index + bar_width * 3, tuple(ndts), bar_width, color="c", label="delete")
    if af:
        plt.bar(index + bar_width * 4, tuple(nall), bar_width, color="m", label="combined")

    # box = ax.get_position()
    # ax.set_position([box.x0, box.y0 + box.height * 0.1, box.width, box.height * 0.9])

    plt.title("Baseline TPS : %d processes, %d transactions/verb" % (thread_count, trans_count / thread_count))
    plt.ylabel("Transactions per second")
    plt.xlabel("Elapsed time")
    plt.legend(loc="best")

    # plt.tight_layout()

    plt.savefig("b1-6.png")
    plt.savefig("b1-6.pdf")
    plt.close()

    print "baseline-process.py end @ %8.8f (%8.8f sec)" % (t1, t1 - t0)