{"id":6489,"date":"2018-08-23T15:28:20","date_gmt":"2018-08-23T14:28:20","guid":{"rendered":"http:\/\/blog.capdata.fr\/?p=6489"},"modified":"2022-12-01T17:52:18","modified_gmt":"2022-12-01T16:52:18","slug":"context-switch-et-switch-context-2","status":"publish","type":"post","link":"https:\/\/blog.capdata.fr\/index.php\/context-switch-et-switch-context-2\/","title":{"rendered":"Context switch et switch Context"},"content":{"rendered":"<a class=\"synved-social-button synved-social-button-share synved-social-size-24 synved-social-resolution-single synved-social-provider-twitter nolightbox\" data-provider=\"twitter\" target=\"_blank\" rel=\"nofollow\" title=\"Share on Twitter\" href=\"https:\/\/twitter.com\/intent\/tweet?url=https%3A%2F%2Fblog.capdata.fr%2Findex.php%2Fwp-json%2Fwp%2Fv2%2Fposts%2F6489&#038;text=Article%20sur%20le%20blog%20de%20la%20Capdata%20Tech%20Team%20%3A%20\" style=\"font-size: 0px;width:24px;height:24px;margin:0;margin-bottom:5px;margin-right:5px\"><img loading=\"lazy\" decoding=\"async\" alt=\"twitter\" title=\"Share on Twitter\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"24\" height=\"24\" style=\"display: inline;width:24px;height:24px;margin: 0;padding: 0;border: none;box-shadow: none\" src=\"https:\/\/blog.capdata.fr\/wp-content\/plugins\/social-media-feather\/synved-social\/image\/social\/regular\/48x48\/twitter.png\" \/><\/a><a class=\"synved-social-button synved-social-button-share synved-social-size-24 synved-social-resolution-single synved-social-provider-linkedin nolightbox\" data-provider=\"linkedin\" target=\"_blank\" rel=\"nofollow\" title=\"Share on Linkedin\" href=\"https:\/\/www.linkedin.com\/shareArticle?mini=true&#038;url=https%3A%2F%2Fblog.capdata.fr%2Findex.php%2Fwp-json%2Fwp%2Fv2%2Fposts%2F6489&#038;title=Context%20switch%20et%20switch%20Context\" style=\"font-size: 0px;width:24px;height:24px;margin:0;margin-bottom:5px;margin-right:5px\"><img loading=\"lazy\" decoding=\"async\" alt=\"linkedin\" title=\"Share on Linkedin\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"24\" height=\"24\" style=\"display: inline;width:24px;height:24px;margin: 0;padding: 0;border: none;box-shadow: none\" src=\"https:\/\/blog.capdata.fr\/wp-content\/plugins\/social-media-feather\/synved-social\/image\/social\/regular\/48x48\/linkedin.png\" \/><\/a><a class=\"synved-social-button synved-social-button-share synved-social-size-24 synved-social-resolution-single synved-social-provider-mail nolightbox\" data-provider=\"mail\" rel=\"nofollow\" title=\"Share by email\" href=\"mailto:?subject=Context%20switch%20et%20switch%20Context&#038;body=Article%20sur%20le%20blog%20de%20la%20Capdata%20Tech%20Team%20%3A%20:%20https%3A%2F%2Fblog.capdata.fr%2Findex.php%2Fwp-json%2Fwp%2Fv2%2Fposts%2F6489\" style=\"font-size: 0px;width:24px;height:24px;margin:0;margin-bottom:5px\"><img loading=\"lazy\" decoding=\"async\" alt=\"mail\" title=\"Share by email\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"24\" height=\"24\" style=\"display: inline;width:24px;height:24px;margin: 0;padding: 0;border: none;box-shadow: none\" src=\"https:\/\/blog.capdata.fr\/wp-content\/plugins\/social-media-feather\/synved-social\/image\/social\/regular\/48x48\/mail.png\" \/><\/a><p>L&#8217;article avait \u00e9t\u00e9 perdu suite \u00e0 migration de version de WP, le revoici :<\/p>\n<p>Pour alimenter le d\u00e9bat, la d\u00e9finition de ces 2 colonnes de <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/ms177526.aspx?f=255&amp;amp;MSPPError=-2147217396\">sys.dm_os_schedulers<\/a> :<\/p>\n<p><em>&#8211; <strong>context_switches_count<\/strong> : Number of context switches that have occurred on this scheduler. Is not nullable. To allow for other workers to run, the current running worker has to relinquish control of the scheduler or switch context. Note: If a worker yields the scheduler and puts itself into the runnable queue and then finds no other workers, the worker will select itself. In this case, the context_switches_count is not updated, but the yield_count is updated.<\/em><br \/>\n<em>&#8211; <strong>preemptive_switches_count<\/strong> : Number of times that workers on this scheduler have switched to the preemptive mode. To execute code that is outside SQL Server (for example, extended stored procedures and distributed queries), a thread has to execute outside the control of the non-preemptive scheduler. To do this, a worker switches to preemptive mode.<\/em><\/p>\n<h2>Changement de contexte et pr\u00e9emption :<\/h2>\n<p>Les probl\u00e8mes de scheduling vous les c\u00f4toyez peut \u00eatre sans le savoir toutes les semaines \u00e0 la caisse du supermarch\u00e9 :<br \/>\nVous \u00eates dans la file d\u2019attente d&#8217;une caisse prioritaire.<\/p>\n<ul>\n<li>La caissi\u00e8re a d\u00e9j\u00e0 pass\u00e9 devant le lecteur une demi-douzaine de vos articles lorsqu&#8217;une femme enceinte arrive derri\u00e8re vous avec son caddie rempli d\u2019articles. Vous \u00eates un gentleman \u00e0 n&#8217;en pas douter, donc vous la laissez passer devant vous. (1)<\/li>\n<li>Lorsqu\u2019elle a fini d\u2019encaisser la femme enceinte, la caissi\u00e8re peut enfin terminer de passer vos articles devant le lecteur.<\/li>\n<li>Lors du passage d\u2019un des derniers articles, le code barre n\u2019est pas lisible et la caissi\u00e8re doit demander par t\u00e9l\u00e9phone un prix \u00e0 un autre employ\u00e9 qui peut se d\u00e9placer dans les rayons. Vous \u00eates mis en attente<\/li>\n<li>Il y a un probl\u00e8me avec le code barre en rayon, et la personne d\u00e9p\u00each\u00e9e sur place ne parvient pas non plus \u00e0 d\u00e9terminer le prix. S\u2019il se passe trop de temps (2) pour r\u00e9cup\u00e9rer le prix, la caissi\u00e8re peut vous mettre en attente sur le c\u00f4t\u00e9 et commencer \u00e0 traiter la personne qui se trouvait derri\u00e8re vous dans la file d\u2019attente. (3)<\/li>\n<\/ul>\n<p><em><strong>(1)<\/strong> : La femme enceinte passe devant vous \u00e0 la caisse parce que sa priorit\u00e9 de passage est sup\u00e9rieure \u00e0 la v\u00f4tre. C\u2019est une <strong>pr\u00e9emption<\/strong>. Vous ne repartez pas au fond de la file d\u2019attente, vous conservez votre rang de passage \u00e0 votre niveau de priorit\u00e9. S\u2019il n\u2019y a pas d\u2019autre personne b\u00e9n\u00e9ficiant d\u2019un passage prioritaire \u00e0 la caisse, vous \u00eates toujours la prochaine personne sur la liste. A cet instant, la caissi\u00e8re cr\u00e9\u00e9 une nouvelle s\u00e9quence d\u2019encaissement apr\u00e8s avoir sauvegard\u00e9 la v\u00f4tre, pour pouvoir revenir \u00e0 l\u2019article correspondant au moment o\u00f9 la femme enceinte est pass\u00e9 devant vous. C&#8217;est un <strong>changement de contexte<\/strong>. Les deux notions interviennent donc dans la m\u00eame s\u00e9quence.<\/em><\/p>\n<p><em><strong>(2)<\/strong> : La valeur de temps a son importance, nous l&#8217;appellerons quanti\u00e8me ou quantum en anglais.<\/em><\/p>\n<p><em><strong>(3)<\/strong> : Vous bloquez donc sur une ressource particuli\u00e8re qui est le prix de l&#8217;article. Pour ne pas p\u00e9naliser les clients de m\u00eame priorit\u00e9 derri\u00e8re vous, la caissi\u00e8re vous remet en attente et commence \u00e0 encaisser une autre personne. Elle recr\u00e9\u00e9 une nouvelle s\u00e9quence d\u2019encaissement apr\u00e8s avoir sauvegard\u00e9 la v\u00f4tre. C\u2019est \u00e0 nouveau un <strong>changement de contexte<\/strong>.<\/em><\/p>\n<p>Deux choses \u00e0 retenir de cet exemple :<\/p>\n<p>&#8211; Une <strong>pr\u00e9emption<\/strong> implique un changement de contexte. En revanche, un <strong>changement de contexte<\/strong> peut survenir dans d&#8217;autres cas que des diff\u00e9rences de priorit\u00e9, comme par exemple l&#8217;expiration d&#8217;un d\u00e9lai imparti ou le blocage sur une ressource.<\/p>\n<p>&#8211; L\u2019un comme l\u2019autre vous affectent car globalement ils rallongent votre temps de passage en caisse.<\/p>\n<p>On l\u2019aura compris ces notions existent pour garantir une plus grande \u00e9quit\u00e9 sur l\u2019utilisation des ressources qui sont partag\u00e9es par plusieurs utilisateurs. Chaque personne de m\u00eame priorit\u00e9 doit pouvoir acc\u00e9der aux services de caisse dans les m\u00eames conditions et d\u00e9lais, autant que possible.<\/p>\n<h2>Partage du temps CPU :<\/h2>\n<p>La raison d\u2019\u00eatre de ces m\u00e9canismes vient du d\u00e9s\u00e9quilibre permanent qui existe entre les ressources et les clients de ces ressources. Il n\u2019y qu\u2019une seule caisse pour 5 ou 6 clients qui attendent dans la file. Il faut donc pouvoir accorder le m\u00eame temps de passage \u00e0 chaque client.<br \/>\nCombien d\u2019applications sont d\u00e9marr\u00e9es sur votre PC ?<\/p>\n<pre class=\"brush: powershell; title: ; notranslate\" title=\"\">PS C:\\Users\\dbaffaleuf : get-process | measure-object\r\nCount : 143\r\nAverage :\r\nSum :\r\nMaximum :\r\nMinimum :\r\nProperty :<\/pre>\n<p>143 processus, pour combien de processeurs ? Dans mon cas, seulement 4.<\/p>\n<p>On l&#8217;a \u00e9voqu\u00e9 bri\u00e8vement, il existe une notion suppl\u00e9mentaire pour parfaire encore ce principe d\u2019\u00e9quit\u00e9 (<em>fairness<\/em>): le <strong>quanti\u00e8me<\/strong> ou <strong>quantum<\/strong>.<\/p>\n<p>Sur Windows, c&#8217;est un bail de temps qui est octroy\u00e9 \u00e0 chaque thread de m\u00eame priorit\u00e9 pour s\u2019ex\u00e9cuter. Au-del\u00e0 de ce temps, le thread sera context-switch\u00e9 pour un autre thread de priorit\u00e9 \u00e9quivalente. Lorsque cela arrive, le thread qui a \u00e9t\u00e9 interrompu retourne au fond de la file d\u2019attente <em>Ready to Run<\/em>. Il est en quelque sorte &#8216;puni&#8217;, et paye le prix d&#8217;avoir utilis\u00e9 tout son quanti\u00e8me de temps.<\/p>\n<p>Dans l&#8217;exemple, lorsque la caissi\u00e8re ne parvient pas \u00e0 d\u00e9terminer le prix de l&#8217;article manquant dans le quanti\u00e8me imparti, elle vous met en attente pour ne pas bloquer le client suivant. La diff\u00e9rence avec Windows, c&#8217;est que vous ne repartez pas \u00e0 la fin de la file avec les articles qui vous restent. Le quanti\u00e8me rend les choses plus \u00e9quitables encore, car cela emp\u00eache un seul client de monopoliser le temps de passage en caisse.<\/p>\n<p>Sur la version cliente de windows, le quantum est v\u00e9rifi\u00e9 tous les 2 cycles d\u2019horloge, sur la version serveur, tous les 12 cycles. Plus il y a de temps pour ex\u00e9cuter une t\u00e2che et plus on minimise nos fameux changements de contexte. La v\u00e9ritable valeur du quantum est fonction de la r\u00e9solution de la fr\u00e9quence d\u2019horloge sur le syst\u00e8me et du nombre de cycle CPU par seconde. Le passage de l\u2019un \u00e0 l\u2019autre est modifiable via les propri\u00e9t\u00e9s de performance du syst\u00e8me :<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-6132\" src=\"https:\/\/blog.capdata.fr\/wp-content\/uploads\/2016\/07\/fairness.png\" alt=\"\" width=\"456\" height=\"177\" srcset=\"https:\/\/blog.capdata.fr\/wp-content\/uploads\/2016\/07\/fairness.png 456w, https:\/\/blog.capdata.fr\/wp-content\/uploads\/2016\/07\/fairness-300x116.png 300w\" sizes=\"auto, (max-width: 456px) 100vw, 456px\" \/><\/p>\n<p>&#8211; Meilleures performances pour les programmes = 2 cycles d\u2019horloge.<br \/>\n&#8211; Meilleures performances pour les services d\u2019arri\u00e8re-plan = 12 cycles.<\/p>\n<h2>Co\u00fbt d\u2019un changement de contexte :<\/h2>\n<p>La majeure partie du code de Windows est \u00e9crite en C, certaines parties en C++. Plus rarement, on trouvera des parties en assembleur, souvent pour optimiser encore les performances \u00e0 l\u2019ex\u00e9cution et minimiser le co\u00fbt en cycles CPU. La routine de changement de contexte fait partie de ces cas de figure.<\/p>\n<p>Tout d\u2019abord, pour les threads (donc hormis fibers et UMS threads), un changement de contexte se d\u00e9roule en kernel mode. A chaque fois, le pointeur d\u2019instruction (la fonction en cours d\u2019ex\u00e9cution) et le pointeur de la pile d\u2019ex\u00e9cution sont sauvegard\u00e9s avec un troisi\u00e8me pointeur vers l\u2019espace d\u2019adressage du processus p\u00e8re. Puis ces m\u00eames informations sont restaur\u00e9es pour le thread qui entre en ex\u00e9cution.<\/p>\n<p>En outre, la structure qui d\u00e9crit l\u2019\u00e9tat courant du dispatcher doit \u00eatre mise \u00e0 jour car un nouveau thread va \u00eatre planifi\u00e9. Cela n\u00e9cessite une \u00e9l\u00e9vation du niveau d\u2019interruption vers DPC\/Dispatch et avant Windows 7, un co\u00fbteux acc\u00e8s au dispatcher lock (qui n\u2019est plus syst\u00e9matique depuis gr\u00e2ce au travail d\u2019<a href=\"https:\/\/channel9.msdn.com\/shows\/Going+Deep\/Arun-Kishan-Farewell-to-the-Windows-Kernel-Dispatcher-Lock\/\">Arun Kishan<\/a>).<\/p>\n<p>Tout ce temps, m\u00eame s\u2019il est optimis\u00e9 via du code tr\u00e8s sp\u00e9cialis\u00e9, repr\u00e9sente tout de m\u00eame des cycles CPU qui ne sont pas productifs. Il faut donc essayer de les minimiser autant que possible.<\/p>\n<h2>Exemple d&#8217;une surcharge CPU:<\/h2>\n<p>Ci-dessous un petit bout de code simple qui va permettre de montrer ce qui se passe lorsque que l&#8217;on lance plus de t\u00e2ches de m\u00eame niveau de priorit\u00e9 qu&#8217;il n&#8217;y a de CPU disponibles.<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n\/\/ contextswitchdemo.cpp : Defines the entry point for the console application.\r\n\/\/ a x64 based code so affinity is not capped to 32 processors as on syswow64 \/ 32 bits\r\n\/\/ ref : https:\/\/msdn.microsoft.com\/en-us\/library\/aa384228(v=VS.85).aspx\r\n\/\/\t\thttps:\/\/blogs.msdn.microsoft.com\/ddperf\/2010\/04\/04\/measuring-processor-utilization-and-queuing-delays-in-windows-applications\/\r\n\/\/\t\thttps:\/\/msdn.microsoft.com\/query\/dev11.query?appId=Dev11IDEF1l=EN-USk=k(vs.cv.threads.timeline.preemption)rd=true\r\n\/\/\t\thttps:\/\/technet.microsoft.com\/en-us\/library\/cc938613.aspx\r\n\/\/\r\n\r\n#include &quot;stdafx.h&quot;\r\n#include &quot;stdio.h&quot;\r\n#include &quot;stdlib.h&quot;\r\n#include &quot;windows.h&quot;\r\n#include &quot;process.h&quot;\r\n#include &quot;math.h&quot;\r\n\r\n#define SUMTOTAL 3000000000 \/\/Total of each summation\r\n\/\/#define __DEBUG\r\n\r\nstruct arglist {\r\n\tint\t\t\tthid;\r\n\tDWORD_PTR\taffinity;\r\n};\r\n\r\nHANDLE *events;\r\nHANDLE *threads;\r\nHANDLE privheap;\r\n\r\n\/\/ THREAD ENTRY POINT ------------------------------------------------------------------------------\r\nunsigned __stdcall justDoIt(LPVOID list)\r\n{\r\n\tint i = 0;\r\n\tHANDLE thhandle;\r\n\tDWORD DEBTH, FINTH;\r\n\r\n\tthhandle = GetCurrentThread();\r\n\tDEBTH=GetTickCount();\r\n\r\n\t\/\/Get info from the list struct --\r\n\targlist * curlist = (arglist *)list;\r\n\r\n\t\/\/ Set affinity for the thread\r\n\t\/*if (!SetThreadAffinityMask (thhandle, curlist-&amp;amp;amp;amp;amp;gt;affinity))\r\n\t{\r\n\t\tprintf(&quot;Failed to set affinity mask for thid : %d, Error : (%d)\\n&quot;, curlist-&amp;amp;amp;amp;amp;gt;thid, GetLastError());\r\n\t}*\/\r\n\r\n\tif (!SetThreadPriorityBoost(thhandle,TRUE))\r\n\t{\r\n\t\tprintf(&quot;Failed to disable priorty boost for thread id %d, Error : (%d)\\n&quot;, curlist-&amp;amp;amp;amp;amp;gt;thid, GetLastError());\r\n\t}\r\n\r\n\tif (!SetThreadPriority(thhandle,THREAD_PRIORITY_ABOVE_NORMAL))\r\n\t{\r\n\t\tprintf(&quot;Failed to raise priority for thid : %d, Error : (%d)\\n&quot;, curlist-&amp;amp;amp;amp;amp;gt;thid, GetLastError());\r\n\t}\r\n\r\n\tprintf(&quot;Thread id (%d) created with priority %d, affinity mask : %f\\n&quot;,curlist-&amp;amp;amp;amp;amp;gt;thid, GetThreadPriority(thhandle), (DOUBLE) curlist-&amp;amp;amp;amp;amp;gt;affinity);\r\n\r\n\twhile(i&amp;amp;amp;amp;amp;lt;SUMTOTAL) { i++; } FINTH=GetTickCount(); printf(&quot;Thread id (%d) Done in %d ms!\\n&quot;,curlist-&amp;amp;amp;amp;amp;gt;thid, FINTH-DEBTH);\r\n\r\n\tSetEvent(events[curlist-&amp;amp;amp;amp;amp;gt;thid]);\r\n\treturn 0;\r\n}\r\n\r\n\/\/ MAIN --------------------------------------------------------------------------------------------\r\nint _tmain(int argc, TCHAR* argv[])\r\n{\r\n\t__int64 numberOfThreads=1;\r\n\tint i;\r\n\tDWORD DEBUT, FIN;\r\n\tunsigned ThreadID;\r\n\tSYSTEM_INFO mysysteminfo;\r\n\tint CPUs;\r\n\r\n\t\/\/argument = numberOfThreads\r\n\tif (argc != 2) {\r\n\t\tprintf(&quot;Usage : contextswitchdemo &amp;amp;amp;amp;amp;lt;nb of concurrent threads&amp;amp;amp;amp;amp;gt;\\n&quot;);\r\n\t\treturn(0);\r\n\t} else {\r\n\t\tnumberOfThreads = _wtoi64 (argv[1]);\r\n\t}\r\n\t#ifdef __DEBUG\r\n\t\tprintf (&quot;Number of Threads is : %d\\n&quot;,numberOfThreads);\r\n\t#endif\r\n\r\n\t\/\/ Allocate for events table on a private heap so it is clean -------------------------------------\r\n\tprivheap\t= HeapCreate(HEAP_GENERATE_EXCEPTIONS,0,0);\r\n\tevents\t\t= (HANDLE *) HeapAlloc(privheap,HEAP_ZERO_MEMORY,numberOfThreads * sizeof(HANDLE *));\r\n\tthreads\t\t= (HANDLE *) HeapAlloc(privheap,HEAP_ZERO_MEMORY,numberOfThreads * sizeof(HANDLE *));\r\n\r\n\t\/\/ Retrieve the number of CPU on the box\r\n\tGetSystemInfo(&amp;amp;amp;amp;amp;mysysteminfo);\r\n\tCPUs=mysysteminfo.dwNumberOfProcessors;\r\n\r\n\t\/\/ First we need to disable dynamic priority boosting, --------------------------------------------\r\n\t\/\/ as we want to keep our hands on this\r\n\tif (!SetProcessPriorityBoost(GetCurrentProcess(),TRUE))\r\n\t{\r\n\t\tprintf(&quot;Failed to disable dynamic priority boost (%d)\\n&quot;, GetLastError());\r\n\t}\r\n\r\n\tDEBUT=GetTickCount();\r\n\r\n\t\/\/ L O O P ----------------------------------------------------------------------------------------\r\n\tfor (i=0;i&amp;amp;amp;amp;amp;lt;numberOfThreads;i++) { arglist *newarglist = new arglist; DWORD_PTR thaffinity; int thpriority; \r\n\r\n        \t\/\/\r\n\t\t\/\/ 1th :\t1^4 - 1\r\n\t\t\/\/ 2th :\t1^4 - 1, 2^4 - 2\r\n\t\t\/\/ 3th :\t1^4 - 1, 2^4 - 2, 3^4 - 3\r\n\t\t\/\/ 4th :\t1^4 - 1, 2^4 - 2, 3^4 - 3, 4^4 - 0\r\n\t\t\/\/ 5th :\t1^4 - 1, 2^4 - 2, 3^4 - 3, 4^4 - 0\r\n\t\t\/\/\t\t\t5^4 - 1\r\n\t\t\/\/ ...\r\n\t\t\/\/ 8th :\t1^4 - 1, 2^4 - 2, 3^4 - 3, 4^4 - 0\r\n\t\t\/\/\t\t\t5^4 - 1, 6^4 - 2, 7^4 - 3, 8^4 - 0\r\n\t\t\/\/ etc...\r\n\t\t\/\/ \r\n\t\tthaffinity= (DWORD_PTR) pow(2.0,i%CPUs);\r\n\r\n\t\t\/\/ update the list  struct\r\n\t\tnewarglist-&amp;amp;amp;amp;amp;gt;thid=i;\r\n\t\tnewarglist-&amp;amp;amp;amp;amp;amp;gt;affinity=thaffinity;\t\r\n\r\n\t\t\/\/ create event \/ thread pair\r\n\t\tevents[i]\t= CreateEvent(NULL,false,false,NULL);\r\n\t\tthreads[i]\t= (HANDLE) _beginthreadex(NULL,0,justDoIt,newarglist,0,&amp;amp;amp;amp;amp;amp;amp;ThreadID);\r\n\r\n\t\tif (!threads[i])\r\n\t\t{\r\n\t\t\tprintf(&quot;Fatal: could not create thread, errno:%d\\n&quot;,GetLastError()) ;\r\n\t\t\treturn(3);\r\n\t\t}\r\n\t}\r\n\r\n\t\/\/ The main thread waits for all threads to finish and exits-----------------------------------------------------------------------------\r\n\tWaitForMultipleObjects(numberOfThreads,events,true,INFINITE);\r\n\tFIN=GetTickCount();\r\n\tprintf(&quot;%d threads, all sums done in %d ms\\n&quot;,numberOfThreads,(int)FIN-DEBUT);\r\n\r\n\t\/\/Clean --------------------------------------------------------------------------------------------------------------------------------\r\n\tHeapDestroy(privheap);\r\n\r\n\treturn 0;\r\n}\r\n\r\n<\/pre>\n<p>Les aspects importants:<\/p>\n<p>&#8211; Le programme prend en argument le nombre de threads \u00e0 ex\u00e9cuter en parall\u00e8le: 1,2,3,4, 5, etc&#8230;<br \/>\n&#8211; Chaque thread ex\u00e9cute une somme d&#8217;entiers jusqu&#8217;\u00e0 3 milliards.<br \/>\n&#8211; Le niveau de priorit\u00e9 des threads est \u00e9lev\u00e9 par rapport \u00e0 la priorit\u00e9 de base pour qu&#8217;ils ne soient en comp\u00e9tition qu&#8217;entre eux pour l&#8217;acc\u00e8s aux ressources.<br \/>\n&#8211; L&#8217;affinit\u00e9 est appliqu\u00e9e en round-robin : le thread 0 a l&#8217;affinit\u00e9 0001, le 1 a l&#8217;affinit\u00e9 0010, le 2 a l&#8217;affinit\u00e9 0100, le 3 l&#8217;affinit\u00e9 1000, et le 4 l&#8217;affinit\u00e9 0001 etc&#8230;<br \/>\n&#8211; le <a href=\"https:\/\/msdn.microsoft.com\/fr-fr\/library\/windows\/desktop\/ms684828(v=vs.85).aspx\">boost dynamique<\/a> est d\u00e9sactiv\u00e9 &nbsp;pour que \u00e7a ne perturbe pas les r\u00e9sultats.<\/p>\n<p>Dans les faits il y a 4 CPU sur la machine, non HT (un vieux <a href=\"https:\/\/ark.intel.com\/products\/53446\/Intel-Core-i5-2320-Processor-6M-Cache-up-to-3_30-GHz?q=core%20i5%202320\">core i5 2320<\/a>). Ci-dessous les r\u00e9sultats des temps d&#8217;ex\u00e9cution de chaque sommation pour 1,2,3 et 4 threads concurrents:<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">E:\\CAPDATA\\DEV\\CPP\\contextswitchdemo\\x64\\Debug : contextswitchdemo.exe 1\r\nThread id (0) created with priority 1, affinity mask : 1.000000\r\nThread id (0) Done in 7286 ms!\r\n1 threads, all sums done in 7286 ms\r\n\r\nE:\\CAPDATA\\DEV\\CPP\\contextswitchdemo\\x64\\Debug : contextswitchdemo.exe 2\r\nThread id (0) created with priority 1, affinity mask : 1.000000\r\nThread id (1) created with priority 1, affinity mask : 2.000000\r\nThread id (0) Done in 7379 ms!\r\nThread id (1) Done in 7457 ms!\r\n2 threads, all sums done in 7457 ms\r\n\r\nE:\\CAPDATA\\DEV\\CPP\\contextswitchdemo\\x64\\Debug : contextswitchdemo.exe 3\r\nThread id (0) created with priority 1, affinity mask : 1.000000\r\nThread id (1) created with priority 1, affinity mask : 2.000000\r\nThread id (2) created with priority 1, affinity mask : 4.000000\r\nThread id (1) Done in 7488 ms!\r\nThread id (0) Done in 7550 ms!\r\nThread id (2) Done in 7628 ms!\r\n3 threads, all sums done in 7628 ms\r\n\r\nE:\\CAPDATA\\DEV\\CPP\\contextswitchdemo\\x64\\Debug : contextswitchdemo.exe 4\r\nThread id (0) created with priority 1, affinity mask : 1.000000\r\nThread id (1) created with priority 1, affinity mask : 2.000000\r\nThread id (2) created with priority 1, affinity mask : 4.000000\r\nThread id (3) created with priority 1, affinity mask : 8.000000\r\nThread id (0) Done in 6989 ms!\r\nThread id (2) Done in 7176 ms!\r\nThread id (1) Done in 7238 ms!\r\nThread id (3) Done in 7301 ms!\r\n4 threads, all sums done in 7301 ms<\/pre>\n<p>Entre 7.2s et 7.6s, les temps restent constants, mais qu&#8217;est-ce qui se passe si je rajoute un thread suppl\u00e9mentaire:<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">E:\\CAPDATA\\DEV\\CPP\\contextswitchdemo\\x64\\Debug : contextswitchdemo.exe 5\r\nThread id (0) created with priority 1, affinity mask : 1.000000\r\nThread id (2) created with priority 1, affinity mask : 4.000000\r\nThread id (3) created with priority 1, affinity mask : 8.000000\r\nThread id (1) created with priority 1, affinity mask : 2.000000\r\nThread id (4) created with priority 1, affinity mask : 1.000000\r\nThread id (2) Done in 7223 ms!\r\nThread id (1) Done in 7254 ms!\r\nThread id (3) Done in 7286 ms!\r\nThread id (0) Done in 14306 ms!\r\nThread id (4) Done in 14415 ms!\r\n5 threads, all sums done in 14415 ms<\/pre>\n<p>Trois threads conservent leur temps de r\u00e9f\u00e9rence, en revanche le 4 et le 0 mettent pr\u00e9cis\u00e9ment deux fois plus de temps. Utilisons le <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/dd537632.aspx\">Concurrency Visualizer<\/a> de Visual Studio &nbsp;pour y voir plus clair: Lors de l&#8217;ex\u00e9cution \u00e0 4 threads, on voit que le temps d&#8217;ex\u00e9cution est optimis\u00e9: chaque thread &nbsp;a son core d\u00e9di\u00e9 sur lequel l&#8217;affinit\u00e9 a \u00e9t\u00e9 \u00e9tablie, et seul le thread p\u00e8re passe son temps en synchronisation (en rose) sur <em>WaitForMultipleObjects<\/em>, les autres passent leur temps en ex\u00e9cution. Les stries sur la partie verte indiquent qu&#8217;il y a cependant des changements de contexte en raison du d\u00e9passement r\u00e9gulier du quantum. Les histogrammes en dessous montrent cependant que le temps pass\u00e9 sur ces changements de contexte est infinit\u00e9simal par rapport au temps pass\u00e9 en ex\u00e9cution, chaque thread \u00e9tant resch\u00e9dul\u00e9 lui-m\u00eame sur son core affili\u00e9:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-6196\" src=\"https:\/\/blog.capdata.fr\/wp-content\/uploads\/2016\/09\/4cores_th1-1024x474.png\" alt=\"\" width=\"1024\" height=\"474\" srcset=\"https:\/\/blog.capdata.fr\/wp-content\/uploads\/2016\/09\/4cores_th1-1024x474.png 1024w, https:\/\/blog.capdata.fr\/wp-content\/uploads\/2016\/09\/4cores_th1-300x138.png 300w, https:\/\/blog.capdata.fr\/wp-content\/uploads\/2016\/09\/4cores_th1-768x356.png 768w, https:\/\/blog.capdata.fr\/wp-content\/uploads\/2016\/09\/4cores_th1.png 1609w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/p>\n<p>Lors de l&#8217;ex\u00e9cution \u00e0 5 threads, on retrouve nos 3 threads \u00e0 7 secondes, et le 0 et le 4 qui ont la m\u00eame affinit\u00e9 (<em>0001<\/em>) s&#8217;\u00e9changent leur CPU \u00e0 tour de r\u00f4le, en passant d&#8217;un \u00e9tat <em>running<\/em> \u00e0 un \u00e9tat <em>preempted<\/em>.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-6195\" src=\"https:\/\/blog.capdata.fr\/wp-content\/uploads\/2016\/09\/5cores_th-1024x481.png\" alt=\"\" width=\"1024\" height=\"481\" srcset=\"https:\/\/blog.capdata.fr\/wp-content\/uploads\/2016\/09\/5cores_th-1024x481.png 1024w, https:\/\/blog.capdata.fr\/wp-content\/uploads\/2016\/09\/5cores_th-300x141.png 300w, https:\/\/blog.capdata.fr\/wp-content\/uploads\/2016\/09\/5cores_th-768x361.png 768w, https:\/\/blog.capdata.fr\/wp-content\/uploads\/2016\/09\/5cores_th.png 1587w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/p>\n<p>Alors attention \u00e0 l&#8217;utilisation du terme <em>Preempted<\/em> dans le contexte du Concurrency Visualizer. \u00c7a ne veut pas dire qu&#8217;il y a un thread de plus forte priorit\u00e9, mais simplement un d\u00e9passement de quantum au profit d&#8217;un autre thread, c&#8217;est \u00e9crit dans la <a href=\"https:\/\/msdn.microsoft.com\/query\/dev11.query?appId=Dev11IDEF1&amp;l=EN-US&amp;k=k(vs.cv.threads.timeline.preemption)&amp;rd=true\">doc<\/a>&nbsp;et je trouve que la formulation est assez mal choisie. Bref ce n&#8217;est pas une vraie pr\u00e9emption, tous les threads \u00e9voluant au m\u00eame niveau de priorit\u00e9, simplement une fa\u00e7on d&#8217;indiquer que le temps CPU est partag\u00e9 \u00e0 50-50 entre le thread 0 et le thread 4. D&#8217;ailleurs lorsque l&#8217;on s\u00e9lectionne une zone jaune sur la piste du thread 0 ou 4, la stack nous indique qu&#8217;il s&#8217;agit bien d&#8217;un d\u00e9passement de quantum:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-6198\" src=\"https:\/\/blog.capdata.fr\/wp-content\/uploads\/2016\/09\/5cores_preemption_explained.png\" alt=\"\" width=\"440\" height=\"239\" srcset=\"https:\/\/blog.capdata.fr\/wp-content\/uploads\/2016\/09\/5cores_preemption_explained.png 440w, https:\/\/blog.capdata.fr\/wp-content\/uploads\/2016\/09\/5cores_preemption_explained-300x162.png 300w\" sizes=\"auto, (max-width: 440px) 100vw, 440px\" \/><\/p>\n<p>Si on continue d&#8217;augmenter le nombre de threads concurrents, on continue d&#8217;augmenter le temps d&#8217;ex\u00e9cution des diff\u00e9rents threads car ils sont de plus en plus nombreux \u00e0 vouloir acc\u00e9der \u00e0 la CPU. Pour 8 threads par exemple, ils se retrouvent presque tous avec un temps d&#8217;ex\u00e9cution logiquement multipli\u00e9 par deux (14s) puisqu&#8217;il n&#8217;y a plus que 1 CPU pour 2 threads:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-6199\" src=\"https:\/\/blog.capdata.fr\/wp-content\/uploads\/2016\/09\/8cores_th-1024x470.png\" alt=\"\" width=\"1024\" height=\"470\" srcset=\"https:\/\/blog.capdata.fr\/wp-content\/uploads\/2016\/09\/8cores_th-1024x470.png 1024w, https:\/\/blog.capdata.fr\/wp-content\/uploads\/2016\/09\/8cores_th-300x137.png 300w, https:\/\/blog.capdata.fr\/wp-content\/uploads\/2016\/09\/8cores_th-768x353.png 768w, https:\/\/blog.capdata.fr\/wp-content\/uploads\/2016\/09\/8cores_th.png 1612w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/p>\n<p>Et le temps d&#8217;ex\u00e9cution moyen augmente avec le nombre de threads en concurrence:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-6300\" src=\"https:\/\/blog.capdata.fr\/wp-content\/uploads\/2016\/09\/contextsw_graph1.png\" alt=\"\" width=\"716\" height=\"364\" srcset=\"https:\/\/blog.capdata.fr\/wp-content\/uploads\/2016\/09\/contextsw_graph1.png 716w, https:\/\/blog.capdata.fr\/wp-content\/uploads\/2016\/09\/contextsw_graph1-300x152.png 300w\" sizes=\"auto, (max-width: 716px) 100vw, 716px\" \/><\/p>\n<h2><strong>Quel rapport avec SQL Server ?<\/strong><\/h2>\n<p>On est bien d\u2019accord que jusqu\u2019ici, on ne parle que du point de vue de Windows.<\/p>\n<p>Pourtant tout au d\u00e9but, <em>sys.dm_os_schedulers<\/em> nous renvoie vers ces m\u00eames notions (pr\u00e9emption, context switch), alors quel est le lien entre un context switch windows et un context switch SQL Server&nbsp;?<\/p>\n<p>R\u00e9ponse et c&#8217;est l&#8217;objectif de cet article: <strong><u>aucun lien<\/u><\/strong>. Si la d\u00e9finition du changement de contexte est la m\u00eame dans les deux cas, ce sont bien deux \u00e9v\u00e9nements distincts qui n\u2019interviennent pas du tout au m\u00eame niveau.<\/p>\n<p>Parce que SQL Server dispose de son propre syst\u00e8me d\u2019exploitation (SQLOS), il utilise les m\u00eames fonctionnalit\u00e9s, et notamment dans le domaine de la planification&nbsp;: des workers (= des threads), des quantums, des CPUs logiques (les schedulers de sys.dm_os_schedulers). Simplement il remod\u00e8le les concepts en rapport avec ses besoins&nbsp;:<\/p>\n<p>&#8211; Il sait que ses workers ont besoin de plus de temps pour travailler. Le temps accord\u00e9 par windows seul n\u2019est pas suffisant et il lui faut un quanti\u00e8me de temps plus long pour aller au bout de son batch<\/p>\n<p>&#8211; Il sait mieux que l\u2019OS \u00e0 quel endroit et quel moment il peut se permettre de rel\u00e2cher volontairement la CPU pour un autre worker.<\/p>\n<p>&#8211; Et surtout, la d\u00e9cision de partager le temps CPU n\u2019est plus la volont\u00e9 arbitraire d\u2019un seul composant comme c\u2019est le cas sur Windows. C\u2019est \u00e0 la charge de chaque petit worker. D\u2019o\u00f9 la notion de scheduler <em>coop\u00e9ratif<\/em> sur SQL Server <em>vs<\/em> scheduler <em>pr\u00e9emptif<\/em> sur Windows.<\/p>\n<p>Tout un syst\u00e8me coop\u00e9ratif ne signifie pas pour autant permettre \u00e0 un worker de garder la main trois heures sur un scheduler. Il faut donc trouver un compromis entre pure coop\u00e9ration o\u00f9 chaque worker passe autant de temps qu\u2019il en a besoin sur un scheduler quitte \u00e0 le monopoliser, et la notion d\u2019\u00e9quit\u00e9 que l\u2019on retrouve dans Windows. D\u2019o\u00f9 les notions de quantum et de changements de contexte au niveau de SQLOS. (En r\u00e9f\u00e9rence le vieux <a href=\"https:\/\/technet.microsoft.com\/en-us\/library\/aa175393(v=sql.80).aspx\">Inside the User Mode Scheduler<\/a> de Ken Henderson, toujours un classique)<\/p>\n<p>Quand \u00e0 la notion de pr\u00e9emption, elle n&#8217;a pas du tout le m\u00eame sens, ce n&#8217;est pas une histoire de priorit\u00e9 mais de laisser le thread s&#8217;ex\u00e9cuter en dehors du contexte de SQLOS, lorsque celui-ci va ex\u00e9cuter des actions non contr\u00f4lables par exemple une proc\u00e9dure stock\u00e9e \u00e9tendue.<\/p>\n<p>Un exemple classique&nbsp;: un worker effectue un long range scan en m\u00e9moire. Il ne bloque sur aucune ressource (verrou, latch, IO), il a une autoroute ouverte devant lui mais plusieurs centaines de m\u00e9gaoctets \u00e0 parcourir quand m\u00eame. Pour \u00e9viter qu\u2019il ne monopolise le scheduler, il dispose d\u2019un bail de 4ms par d\u00e9faut, au-del\u00e0 duquel il s\u2019interrompra spontan\u00e9ment (<em>coop\u00e9ratif<\/em>) pour c\u00e9der sa place au prochain thread runnable. Il va comptabiliser une attente sur SOS_SCHEDULER_YIELD, puis va se replacer tout seul au fond de la <em>runnable list<\/em>.<\/p>\n<p>Lorsqu\u2019il c\u00e8de sa place, il y a un changement de contexte au niveau de son scheduler, qui viendra incr\u00e9menter le compteur que l\u2019on a vu en d\u00e9but de ce post. On comprend bien ici que tout se passe en usermode et que ce changement de contexte se fait bien au niveau de SQL Server et pas au niveau de Windows. Ci-dessous un exemple de gros range scan d&#8217;index qui tient en m\u00e9moire:<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">select ProductID, transactionDate from bigTransactionHistory\r\nwhere productID between 1000 and 24000;\r\n\r\n\/*\r\n|--Index Seek(OBJECT:([SCE3].[dbo].[bigTransactionHistory].[IX_ProductId_TransactionDate]), SEEK:([SCE3].[dbo].[bigTransactionHistory].[ProductID] &amp;amp;amp;amp;gt;= CONVERT_IMPLICIT(int,[@1],0) AND [SCE3].[dbo].[bigTransactionHistory].[ProductID]\r\n\r\n(12697128 row(s) affected)\r\nTable 'bigTransactionHistory'. Scan count 1, logical reads 53539, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.\r\n\r\n(1 row(s) affected)\r\n*\/<\/pre>\n<p>Et le d\u00e9compte des context switches par seconde c\u00f4t\u00e9 SQLOS avec une DMV et c\u00f4t\u00e9 windows via perfmon (Threads\\Context Switches\/sec):<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">declare @ctx1 bigint, @ctx2 bigint;\r\nset @ctx1=0;\r\nset @ctx2=0;\r\n\r\nif (object_id('tempdb.dbo.#capture') is not null)\r\n\tdrop table #capture ;\r\ncreate table #capture (curdate datetime, ctxsw bigint) ;\r\n\r\nwhile (1=1)\r\nBEGIN\r\n\tselect @ctx1 = W.context_switch_count\r\n\tfrom sys.dm_os_workers W\r\n\tjoin sys.dm_os_tasks TA on TA.task_address = W.task_address\r\n\twhere TA.session_id = 54 ;\r\n\twaitfor delay '00:00:01'\r\n\tselect @ctx2 = W.context_switch_count\r\n\tfrom sys.dm_os_workers W\r\n\tjoin sys.dm_os_tasks TA on TA.task_address = W.task_address\r\n\twhere TA.session_id = 54 ;\r\n\r\n\tinsert into #capture (curdate,ctxsw) select getutcdate(), (@ctx2-@ctx1) ;\r\nEND;\r\n\r\nselect * from #capture order by curdate asc ;<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-6271\" src=\"https:\/\/blog.capdata.fr\/wp-content\/uploads\/2016\/09\/ctxswpersec1.png\" alt=\"\" width=\"611\" height=\"363\" srcset=\"https:\/\/blog.capdata.fr\/wp-content\/uploads\/2016\/09\/ctxswpersec1.png 611w, https:\/\/blog.capdata.fr\/wp-content\/uploads\/2016\/09\/ctxswpersec1-300x178.png 300w\" sizes=\"auto, (max-width: 611px) 100vw, 611px\" \/><\/p>\n<p>Pour le m\u00eame thread, les valeurs de changement de contexte SQLOS et Windows ne sont pas comparables. Le worker est context-switch\u00e9 par SQLOS, et le thread sur lequel il s&#8217;appuie est context switch\u00e9 par Windows, ce sont deux \u00e9v\u00e8nements distincts et les d\u00e9cisions de context switcher sont prises ind\u00e9pendamment l&#8217;une de l&#8217;autre.<\/p>\n<h2><strong>Conclusion&nbsp;:<\/strong><\/h2>\n<p>Nous avons vu que la notion de changement de contexte est utilis\u00e9e \u00e0 la fois par le dispatcher Windows et dans SQL Server par SQLOS, pour des raisons d\u2019\u00e9quit\u00e9 dans les deux cas, <strong><u>mais \u00e0 des niveaux tr\u00e8s diff\u00e9rents<\/u><\/strong>.<\/p>\n<p>Donc on affirmer sans d\u00e9tours que&nbsp;:&nbsp;<strong>Context switch Windows&nbsp;!= context switch SQLOS.<\/strong><\/p>\n<p>A+<\/p>\n<a class=\"synved-social-button synved-social-button-share synved-social-size-24 synved-social-resolution-single synved-social-provider-twitter nolightbox\" data-provider=\"twitter\" target=\"_blank\" rel=\"nofollow\" title=\"Share on Twitter\" href=\"https:\/\/twitter.com\/intent\/tweet?url=https%3A%2F%2Fblog.capdata.fr%2Findex.php%2Fwp-json%2Fwp%2Fv2%2Fposts%2F6489&#038;text=Article%20sur%20le%20blog%20de%20la%20Capdata%20Tech%20Team%20%3A%20\" style=\"font-size: 0px;width:24px;height:24px;margin:0;margin-bottom:5px;margin-right:5px\"><img loading=\"lazy\" decoding=\"async\" alt=\"twitter\" title=\"Share on Twitter\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"24\" height=\"24\" style=\"display: inline;width:24px;height:24px;margin: 0;padding: 0;border: none;box-shadow: none\" src=\"https:\/\/blog.capdata.fr\/wp-content\/plugins\/social-media-feather\/synved-social\/image\/social\/regular\/48x48\/twitter.png\" \/><\/a><a class=\"synved-social-button synved-social-button-share synved-social-size-24 synved-social-resolution-single synved-social-provider-linkedin nolightbox\" data-provider=\"linkedin\" target=\"_blank\" rel=\"nofollow\" title=\"Share on Linkedin\" href=\"https:\/\/www.linkedin.com\/shareArticle?mini=true&#038;url=https%3A%2F%2Fblog.capdata.fr%2Findex.php%2Fwp-json%2Fwp%2Fv2%2Fposts%2F6489&#038;title=Context%20switch%20et%20switch%20Context\" style=\"font-size: 0px;width:24px;height:24px;margin:0;margin-bottom:5px;margin-right:5px\"><img loading=\"lazy\" decoding=\"async\" alt=\"linkedin\" title=\"Share on Linkedin\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"24\" height=\"24\" style=\"display: inline;width:24px;height:24px;margin: 0;padding: 0;border: none;box-shadow: none\" src=\"https:\/\/blog.capdata.fr\/wp-content\/plugins\/social-media-feather\/synved-social\/image\/social\/regular\/48x48\/linkedin.png\" \/><\/a><a class=\"synved-social-button synved-social-button-share synved-social-size-24 synved-social-resolution-single synved-social-provider-mail nolightbox\" data-provider=\"mail\" rel=\"nofollow\" title=\"Share by email\" href=\"mailto:?subject=Context%20switch%20et%20switch%20Context&#038;body=Article%20sur%20le%20blog%20de%20la%20Capdata%20Tech%20Team%20%3A%20:%20https%3A%2F%2Fblog.capdata.fr%2Findex.php%2Fwp-json%2Fwp%2Fv2%2Fposts%2F6489\" style=\"font-size: 0px;width:24px;height:24px;margin:0;margin-bottom:5px\"><img loading=\"lazy\" decoding=\"async\" alt=\"mail\" title=\"Share by email\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"24\" height=\"24\" style=\"display: inline;width:24px;height:24px;margin: 0;padding: 0;border: none;box-shadow: none\" src=\"https:\/\/blog.capdata.fr\/wp-content\/plugins\/social-media-feather\/synved-social\/image\/social\/regular\/48x48\/mail.png\" \/><\/a>","protected":false},"excerpt":{"rendered":"<p>L&#8217;article avait \u00e9t\u00e9 perdu suite \u00e0 migration de version de WP, le revoici : Pour alimenter le d\u00e9bat, la d\u00e9finition de ces 2 colonnes de sys.dm_os_schedulers : &#8211; context_switches_count : Number of context switches that have occurred on this scheduler.&hellip; <a href=\"https:\/\/blog.capdata.fr\/index.php\/context-switch-et-switch-context-2\/\" class=\"more-link\">Continuer la lecture <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":6199,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[173],"tags":[38,174],"class_list":["post-6489","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-operating-system","tag-internals","tag-win32"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v20.8 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Context switch et switch Context - Capdata TECH BLOG<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/blog.capdata.fr\/index.php\/context-switch-et-switch-context-2\/\" \/>\n<meta property=\"og:locale\" content=\"fr_FR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Context switch et switch Context - Capdata TECH BLOG\" \/>\n<meta property=\"og:description\" content=\"L&#8217;article avait \u00e9t\u00e9 perdu suite \u00e0 migration de version de WP, le revoici : Pour alimenter le d\u00e9bat, la d\u00e9finition de ces 2 colonnes de sys.dm_os_schedulers : &#8211; context_switches_count : Number of context switches that have occurred on this scheduler.&hellip; Continuer la lecture &rarr;\" \/>\n<meta property=\"og:url\" content=\"https:\/\/blog.capdata.fr\/index.php\/context-switch-et-switch-context-2\/\" \/>\n<meta property=\"og:site_name\" content=\"Capdata TECH BLOG\" \/>\n<meta property=\"article:published_time\" content=\"2018-08-23T14:28:20+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2022-12-01T16:52:18+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/blog.capdata.fr\/wp-content\/uploads\/2016\/09\/8cores_th.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1612\" \/>\n\t<meta property=\"og:image:height\" content=\"740\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"David Baffaleuf\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u00c9crit par\" \/>\n\t<meta name=\"twitter:data1\" content=\"David Baffaleuf\" \/>\n\t<meta name=\"twitter:label2\" content=\"Dur\u00e9e de lecture estim\u00e9e\" \/>\n\t<meta name=\"twitter:data2\" content=\"19 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/blog.capdata.fr\/index.php\/context-switch-et-switch-context-2\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/blog.capdata.fr\/index.php\/context-switch-et-switch-context-2\/\"},\"author\":{\"name\":\"David Baffaleuf\",\"@id\":\"https:\/\/blog.capdata.fr\/#\/schema\/person\/136297da9f61d6e4878abe0f48bc5fbf\"},\"headline\":\"Context switch et switch Context\",\"datePublished\":\"2018-08-23T14:28:20+00:00\",\"dateModified\":\"2022-12-01T16:52:18+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/blog.capdata.fr\/index.php\/context-switch-et-switch-context-2\/\"},\"wordCount\":3706,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/blog.capdata.fr\/#organization\"},\"keywords\":[\"internals\",\"win32\"],\"articleSection\":[\"Operating System\"],\"inLanguage\":\"fr-FR\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/blog.capdata.fr\/index.php\/context-switch-et-switch-context-2\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/blog.capdata.fr\/index.php\/context-switch-et-switch-context-2\/\",\"url\":\"https:\/\/blog.capdata.fr\/index.php\/context-switch-et-switch-context-2\/\",\"name\":\"Context switch et switch Context - Capdata TECH BLOG\",\"isPartOf\":{\"@id\":\"https:\/\/blog.capdata.fr\/#website\"},\"datePublished\":\"2018-08-23T14:28:20+00:00\",\"dateModified\":\"2022-12-01T16:52:18+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/blog.capdata.fr\/index.php\/context-switch-et-switch-context-2\/#breadcrumb\"},\"inLanguage\":\"fr-FR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/blog.capdata.fr\/index.php\/context-switch-et-switch-context-2\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/blog.capdata.fr\/index.php\/context-switch-et-switch-context-2\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Accueil\",\"item\":\"https:\/\/blog.capdata.fr\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Context switch et switch Context\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/blog.capdata.fr\/#website\",\"url\":\"https:\/\/blog.capdata.fr\/\",\"name\":\"Capdata TECH BLOG\",\"description\":\"Le blog technique sur les bases de donn\u00e9es de CAP DATA Consulting\",\"publisher\":{\"@id\":\"https:\/\/blog.capdata.fr\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/blog.capdata.fr\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"fr-FR\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/blog.capdata.fr\/#organization\",\"name\":\"Capdata TECH BLOG\",\"url\":\"https:\/\/blog.capdata.fr\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"fr-FR\",\"@id\":\"https:\/\/blog.capdata.fr\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/blog.capdata.fr\/wp-content\/uploads\/2023\/01\/logo_capdata.webp\",\"contentUrl\":\"https:\/\/blog.capdata.fr\/wp-content\/uploads\/2023\/01\/logo_capdata.webp\",\"width\":800,\"height\":254,\"caption\":\"Capdata TECH BLOG\"},\"image\":{\"@id\":\"https:\/\/blog.capdata.fr\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.linkedin.com\/company\/cap-data-consulting\/mycompany\/\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/blog.capdata.fr\/#\/schema\/person\/136297da9f61d6e4878abe0f48bc5fbf\",\"name\":\"David Baffaleuf\",\"sameAs\":[\"http:\/\/www.capdata.fr\"],\"url\":\"https:\/\/blog.capdata.fr\/index.php\/author\/dbaffaleuf\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Context switch et switch Context - Capdata TECH BLOG","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/blog.capdata.fr\/index.php\/context-switch-et-switch-context-2\/","og_locale":"fr_FR","og_type":"article","og_title":"Context switch et switch Context - Capdata TECH BLOG","og_description":"L&#8217;article avait \u00e9t\u00e9 perdu suite \u00e0 migration de version de WP, le revoici : Pour alimenter le d\u00e9bat, la d\u00e9finition de ces 2 colonnes de sys.dm_os_schedulers : &#8211; context_switches_count : Number of context switches that have occurred on this scheduler.&hellip; Continuer la lecture &rarr;","og_url":"https:\/\/blog.capdata.fr\/index.php\/context-switch-et-switch-context-2\/","og_site_name":"Capdata TECH BLOG","article_published_time":"2018-08-23T14:28:20+00:00","article_modified_time":"2022-12-01T16:52:18+00:00","og_image":[{"width":1612,"height":740,"url":"https:\/\/blog.capdata.fr\/wp-content\/uploads\/2016\/09\/8cores_th.png","type":"image\/png"}],"author":"David Baffaleuf","twitter_card":"summary_large_image","twitter_misc":{"\u00c9crit par":"David Baffaleuf","Dur\u00e9e de lecture estim\u00e9e":"19 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/blog.capdata.fr\/index.php\/context-switch-et-switch-context-2\/#article","isPartOf":{"@id":"https:\/\/blog.capdata.fr\/index.php\/context-switch-et-switch-context-2\/"},"author":{"name":"David Baffaleuf","@id":"https:\/\/blog.capdata.fr\/#\/schema\/person\/136297da9f61d6e4878abe0f48bc5fbf"},"headline":"Context switch et switch Context","datePublished":"2018-08-23T14:28:20+00:00","dateModified":"2022-12-01T16:52:18+00:00","mainEntityOfPage":{"@id":"https:\/\/blog.capdata.fr\/index.php\/context-switch-et-switch-context-2\/"},"wordCount":3706,"commentCount":0,"publisher":{"@id":"https:\/\/blog.capdata.fr\/#organization"},"keywords":["internals","win32"],"articleSection":["Operating System"],"inLanguage":"fr-FR","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/blog.capdata.fr\/index.php\/context-switch-et-switch-context-2\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/blog.capdata.fr\/index.php\/context-switch-et-switch-context-2\/","url":"https:\/\/blog.capdata.fr\/index.php\/context-switch-et-switch-context-2\/","name":"Context switch et switch Context - Capdata TECH BLOG","isPartOf":{"@id":"https:\/\/blog.capdata.fr\/#website"},"datePublished":"2018-08-23T14:28:20+00:00","dateModified":"2022-12-01T16:52:18+00:00","breadcrumb":{"@id":"https:\/\/blog.capdata.fr\/index.php\/context-switch-et-switch-context-2\/#breadcrumb"},"inLanguage":"fr-FR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blog.capdata.fr\/index.php\/context-switch-et-switch-context-2\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/blog.capdata.fr\/index.php\/context-switch-et-switch-context-2\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Accueil","item":"https:\/\/blog.capdata.fr\/"},{"@type":"ListItem","position":2,"name":"Context switch et switch Context"}]},{"@type":"WebSite","@id":"https:\/\/blog.capdata.fr\/#website","url":"https:\/\/blog.capdata.fr\/","name":"Capdata TECH BLOG","description":"Le blog technique sur les bases de donn\u00e9es de CAP DATA Consulting","publisher":{"@id":"https:\/\/blog.capdata.fr\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blog.capdata.fr\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"fr-FR"},{"@type":"Organization","@id":"https:\/\/blog.capdata.fr\/#organization","name":"Capdata TECH BLOG","url":"https:\/\/blog.capdata.fr\/","logo":{"@type":"ImageObject","inLanguage":"fr-FR","@id":"https:\/\/blog.capdata.fr\/#\/schema\/logo\/image\/","url":"https:\/\/blog.capdata.fr\/wp-content\/uploads\/2023\/01\/logo_capdata.webp","contentUrl":"https:\/\/blog.capdata.fr\/wp-content\/uploads\/2023\/01\/logo_capdata.webp","width":800,"height":254,"caption":"Capdata TECH BLOG"},"image":{"@id":"https:\/\/blog.capdata.fr\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.linkedin.com\/company\/cap-data-consulting\/mycompany\/"]},{"@type":"Person","@id":"https:\/\/blog.capdata.fr\/#\/schema\/person\/136297da9f61d6e4878abe0f48bc5fbf","name":"David Baffaleuf","sameAs":["http:\/\/www.capdata.fr"],"url":"https:\/\/blog.capdata.fr\/index.php\/author\/dbaffaleuf\/"}]}},"_links":{"self":[{"href":"https:\/\/blog.capdata.fr\/index.php\/wp-json\/wp\/v2\/posts\/6489","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.capdata.fr\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.capdata.fr\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.capdata.fr\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.capdata.fr\/index.php\/wp-json\/wp\/v2\/comments?post=6489"}],"version-history":[{"count":14,"href":"https:\/\/blog.capdata.fr\/index.php\/wp-json\/wp\/v2\/posts\/6489\/revisions"}],"predecessor-version":[{"id":9541,"href":"https:\/\/blog.capdata.fr\/index.php\/wp-json\/wp\/v2\/posts\/6489\/revisions\/9541"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.capdata.fr\/index.php\/wp-json\/wp\/v2\/media\/6199"}],"wp:attachment":[{"href":"https:\/\/blog.capdata.fr\/index.php\/wp-json\/wp\/v2\/media?parent=6489"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.capdata.fr\/index.php\/wp-json\/wp\/v2\/categories?post=6489"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.capdata.fr\/index.php\/wp-json\/wp\/v2\/tags?post=6489"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}