From owner-freebsd-hackers@freebsd.org Wed Mar 20 01:01:39 2019 Return-Path: Delivered-To: freebsd-hackers@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 7672F154314B for ; Wed, 20 Mar 2019 01:01:39 +0000 (UTC) (envelope-from markjdb@gmail.com) Received: from mail-it1-x142.google.com (mail-it1-x142.google.com [IPv6:2607:f8b0:4864:20::142]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (Client CN "smtp.gmail.com", Issuer "GTS CA 1O1" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 7938676BEA for ; Wed, 20 Mar 2019 01:01:38 +0000 (UTC) (envelope-from markjdb@gmail.com) Received: by mail-it1-x142.google.com with SMTP id h9so7885405itl.1 for ; Tue, 19 Mar 2019 18:01:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:date:from:to:cc:subject:message-id:references:mime-version :content-disposition:content-transfer-encoding:in-reply-to :user-agent; bh=BW9QCfCQCd8XajAXVaVwDVWNoBB9ucVYSk9VfF9n980=; b=Drx+xtY6cNkxelW7bBbQsGztXl84l25pEm46EDQqIpCofL8llwtuYNTp/efs5OD23r ws31jkJtA23uFLBaXidhOB+ArZ7VWYowfw5LMpfp5DcBvSGDlmMTkJcPi54u9FKdjJxn BNZr7V0STq9h7369oIXbwvch8qN1LwxHeK5xC8Yf0HCl9zol7psVTJ41xmQGbxdPCpyg FPZvyMM2hMFsV7HYMVygb02x4yLqhKgm10VOgJ/65hKQB0PomB5IGYH+HuYwHUT64Roq XUjdF8ost+UzKfiU7ZAi9ROEnS2l6RDS1vYL/YLDI/eg7LoDiVexQ+GdFyjTD0yOEVZs psmg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:from:to:cc:subject:message-id :references:mime-version:content-disposition :content-transfer-encoding:in-reply-to:user-agent; bh=BW9QCfCQCd8XajAXVaVwDVWNoBB9ucVYSk9VfF9n980=; b=TqM6jJPP9Uqgwfd7pyqCCww0ePVTDK2t/X1u6g44HYwXS4yHSSzdtlVrBLHilAYga8 d98Cgy1fE4BGztArc27H5jGQkAvBwnZtK8ZlRfdTMNkEFfabn0KHsT0fgVPvg4vWQZLx v+odFrsyYAyMKFbELucG40wBsSlVVEwcB3BCFf98nBmWk9eMA+60rW9Vz0IaeSvpHq6+ /Qb1qLVy45PPoPXcujMy/91WtPnLkaMkt7gq1pEBflPGk2TPLNV3i1PfxeR3gjTbiO2V utHn6s5p7xKWqUxRlK/+yLJqXXcOliEEz6JJ38RGfcazZ1/QisUAr0TATWTw3DFBu3u4 AafA== X-Gm-Message-State: APjAAAWvdy+gorgTLIuJyyqkN0030KsH6hXiOPW+15Ql6/RmjqBrvOxR I3IwqOm+zNfXatDfS2/ZSHXFFU1X X-Google-Smtp-Source: APXvYqzxz3yAW+cvPhWb/gXxBfQo6v2H8CRGP3roWsKExpFjRYD7ndDYuO4XYL8PQRS9TIOuCLDmtg== X-Received: by 2002:a24:390a:: with SMTP id l10mr2724350ita.145.1553043697674; Tue, 19 Mar 2019 18:01:37 -0700 (PDT) Received: from raichu (toroon0560w-lp140-01-69-159-36-102.dsl.bell.ca. [69.159.36.102]) by smtp.gmail.com with ESMTPSA id t23sm284935ioj.19.2019.03.19.18.01.36 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 19 Mar 2019 18:01:36 -0700 (PDT) Sender: Mark Johnston Date: Tue, 19 Mar 2019 21:01:34 -0400 From: Mark Johnston To: =?utf-8?Q?Mi=C5=82osz?= Kaniewski Cc: freebsd-hackers@freebsd.org Subject: Re: sched_pickcpu() and a pinned thread. Message-ID: <20190320010134.GD74753@raichu> References: MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: User-Agent: Mutt/1.11.3 (2019-02-01) X-Rspamd-Queue-Id: 7938676BEA X-Spamd-Bar: --- Authentication-Results: mx1.freebsd.org; dkim=pass header.d=gmail.com header.s=20161025 header.b=Drx+xtY6; spf=pass (mx1.freebsd.org: domain of markjdb@gmail.com designates 2607:f8b0:4864:20::142 as permitted sender) smtp.mailfrom=markjdb@gmail.com X-Spamd-Result: default: False [-3.20 / 15.00]; RCVD_VIA_SMTP_AUTH(0.00)[]; TO_DN_SOME(0.00)[]; R_SPF_ALLOW(-0.20)[+ip6:2607:f8b0:4000::/36]; RCVD_COUNT_THREE(0.00)[3]; DKIM_TRACE(0.00)[gmail.com:+]; MX_GOOD(-0.01)[cached: alt3.gmail-smtp-in.l.google.com]; RCPT_COUNT_TWO(0.00)[2]; NEURAL_HAM_SHORT(-0.92)[-0.924,0]; FORGED_SENDER(0.30)[markj@freebsd.org,markjdb@gmail.com]; MIME_TRACE(0.00)[0:+]; RCVD_TLS_LAST(0.00)[]; FREEMAIL_ENVFROM(0.00)[gmail.com]; ASN(0.00)[asn:15169, ipnet:2607:f8b0::/32, country:US]; FROM_NEQ_ENVFROM(0.00)[markj@freebsd.org,markjdb@gmail.com]; ARC_NA(0.00)[]; NEURAL_HAM_MEDIUM(-1.00)[-0.998,0]; R_DKIM_ALLOW(-0.20)[gmail.com:s=20161025]; FROM_HAS_DN(0.00)[]; NEURAL_HAM_LONG(-1.00)[-1.000,0]; MIME_GOOD(-0.10)[text/plain]; PREVIOUSLY_DELIVERED(0.00)[freebsd-hackers@freebsd.org]; DMARC_NA(0.00)[freebsd.org]; TO_MATCH_ENVRCPT_SOME(0.00)[]; RCVD_IN_DNSWL_NONE(0.00)[2.4.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.0.4.6.8.4.0.b.8.f.7.0.6.2.list.dnswl.org : 127.0.5.0]; IP_SCORE(-0.57)[ip: (2.11), ipnet: 2607:f8b0::/32(-2.79), asn: 15169(-2.11), country: US(-0.07)]; MID_RHS_NOT_FQDN(0.50)[] X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 20 Mar 2019 01:01:39 -0000 On Tue, Mar 19, 2019 at 10:10:21PM +0100, MiƂosz Kaniewski wrote: > Hi, > > I have an application which exchanges packets between two NIC ports. > Most of a CPU time is therefore consumed by the userspace process and > two IRQ threads. All of them are pinned to the same CPU using > cpu_setaffinity() function so I expect that the scheduler usage should > be minimal even on a high network load when a lot of interrupts are > generated. > I recently find out that my application spends a lot of time in > cpu_search_lowest() function. A backtrace shown me that > cpu_search_lowest() is called by sched_pickcpu(). I tried to analyze > this second function but I don't know what exactly should I expect > from it if my thread is pinned to a specific CPU. I assume that the > function should get to a point where ts->ts_cpu is returned. However > it doesn't do it and sched_pickcpu() always ends looking for the > lowest busy CPU using cpu_search_lowest(). In result it finds the CPU > that the thread is pinned to but it is very time consuming process. > Therefore I suspect that sched_pickcpu() should return before that > happens. > > For interrupt threads I see that there is a special case at the > beginning of sched_pickcpu(): > /* > * Prefer to run interrupt threads on the processors that generate > * the interrupt. > */ > pri = td->td_priority; > if (td->td_priority <= PRI_MAX_ITHD && THREAD_CAN_SCHED(td, self) && > curthread->td_intr_nesting_level && ts->ts_cpu != self) { > SCHED_STAT_INC(pickcpu_intrbind); > ts->ts_cpu = self; > if (TDQ_CPU(self)->tdq_lowpri > pri) { > SCHED_STAT_INC(pickcpu_affinity); > return (ts->ts_cpu); > } > } > However IRQ threads from the NIC doesn't fall into this case because > ts->ts_cpu == self (these variables are equal to the CPU to which my > threads are pinned). Is this check required? > > For non-interrupt threads there are some other possible options where > ts->ts_cpu is returned however I am not sure which should handle a > pinned thread. > > I would be grateful if someone would give me some clue how should I > understand the sched_pickcpu() function and when it should return in > case of a pinned thread. sched_pickcpu() fetches the current cpuset's mask immediately before calling sched_lowest(). In sched_search(), we skip over CPUs that aren't in the mask with the check CPU_ISSET(cpu, &lgroup.cs_mask). So eventually it finds the CPU to which the threads are pinned, but the current algorithm does seem rather inefficient for your case. As an experiment you can try the hack below to see how much better you can do if sched_search() is avoided entirely. I did not test it at all, so be careful if you try it. diff --git a/sys/kern/sched_ule.c b/sys/kern/sched_ule.c index b20604d11274..0f105480a871 100644 --- a/sys/kern/sched_ule.c +++ b/sys/kern/sched_ule.c @@ -1314,7 +1314,9 @@ sched_pickcpu(struct thread *td, int flags) cpu = -1; /* Search the group for the less loaded idle CPU we can run now. */ mask = td->td_cpuset->cs_mask; - if (cg != NULL && cg != cpu_top && + if (CPU_COUNT(&mask) == 1) + cpu = CPU_FFS(&mask) - 1; + if (cpu == -1 && cg != NULL && cg != cpu_top && CPU_CMP(&cg->cg_mask, &cpu_top->cg_mask) != 0) cpu = sched_lowest(cg, mask, max(pri, PRI_MAX_TIMESHARE), INT_MAX, ts->ts_cpu);