{"id":26143,"date":"2007-07-05T10:00:00","date_gmt":"2007-07-05T10:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2007\/07\/05\/queryperformancecounter-is-not-a-source-for-unique-identifiers\/"},"modified":"2007-07-05T10:00:00","modified_gmt":"2007-07-05T10:00:00","slug":"queryperformancecounter-is-not-a-source-for-unique-identifiers","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20070705-00\/?p=26143","title":{"rendered":"QueryPerformanceCounter is not a source for unique identifiers"},"content":{"rendered":"<p>\n<a HREF=\"http:\/\/geekswithblogs.net\/marcel\/archive\/2006\/09\/29\/92729.aspx\">\nThis article<\/a> happened to catch my eye:\n<\/p>\n<blockquote CLASS=\"q\">\n<p>\nI needed to generate some unique number in my application.\nI could use GUID, but it was too large for me\n(I need to keep lots of unique identifiers). I found something like this:\n<\/p>\n<pre>\n[System.Runtime.InteropServices.DllImport(\"Kernel32.dll\")]\nprivate static extern int\n    QueryPerformanceFrequency(ref System.Int64 frequency);\n[System.Runtime.InteropServices.DllImport(\"Kernel32.dll\")]\nprivate static extern int\n    QueryPerformanceCounter(ref System.Int64 performanceCount);\npublic static long GenerateUniqueId()\n{\n      System.Int64 id = 0;\n      QueryPerformanceFrequency(ref id);\n      QueryPerformanceCounter(ref id);\n      return id;\n}\n<\/pre>\n<p>\nThis code generates Int64 (long) unique number (at least I hope it is unique).\nThe uniqueness is in the scope of process.\nSo two processes can generate the same number,\nbut it should be always unique in a single process\n(I am not sure about two threads invoking the same GenerateUniqueId() method.\n<\/p>\n<\/blockquote>\n<p>\n<code>QueryPerformanceCounter<\/code> retrieves the current value of\nthe high-resolution performance counter, but there is no guarantee that every\ncall to the function will return a different number.\n<\/p>\n<p>\nThe frequency of the high-resolution performance counter\nis determined by the HAL.\nYou might think that the <code>RDTSC<\/code> instruction would be\nperfect for this purpose, since it returns the number of CPU clock\nticks, a value that always increases at a very high rate.\nBut\n<a HREF=\"http:\/\/msdn.microsoft.com\/library\/en-us\/directx9_c\/Game_Timing_and_Multicore_Processors.asp\">\nthere are many problems with <code>RDTSC<\/code><\/a>.\nFor example,\nvariable-speed processors mean that the rate at which CPU clock elapse\nvaries over time.\nA million clock ticks might take one millisecond when the computer is running\non wall power, but two milliseconds when running on battery power.\n<\/p>\n<p>\nIf the HAL can&#8217;t use <code>RDTSC<\/code>, what does it use instead?\nWell, as I said, it&#8217;s up to the HAL to find something suitable.\nOlder motherboards have to make do with the programmable interval timer\nwhich runs at 1,193,182 ticks per second (approximately 0.8 microseconds\nper tick).\nNewer motherboards can use the ACPI timer\nwhich runs at 3,579,545 ticks per second (approximately 0.3 microseconds\nper tick).\n<\/p>\n<p>\nOne of the machines in my office uses the ACPI timer for its\nhigh-resolution performance counter, so I threw together a quick program\nto see how close I can get to outracing the ACPI timer by calling\n<code>QueryPerformanceCounter<\/code> in rapid succession.\nWith a 1.80GHz processor, the computer manages to call\n<code>QueryPerformanceCounter<\/code> quickly enough that only\nfour ticks of the ACPI timer elapse between consecutive calls.\nWe&#8217;re getting into shouting range of being able to call\n<code>QueryPerformanceCounter<\/code> twice and getting the same\nvalue back from the ACPI timer.\nOf course, if the computer had been using the programmable interval\ntimer, it would have been within spitting distance,\nand upgrading to a 3GHz processor would have taken us over the top.\n<\/p>\n<p>\nIn other words, you may be lucky today that your CPU isn&#8217;t fast enough\nto call <code>QueryPerformanceCounter<\/code> twice and get the same\nvalue back, but it sure looks like we&#8217;re threatening to get there soon.\n<\/p>\n<p>\nThen again, all this back-of-the-envelope calculation is superfluous.\nAll you need is a machine with multiple processors.\nGet two of the processors to call <code>QueryPerformanceCounter<\/code>\nat the same time (or nearly so),\nand they&#8217;ll get the same timer value back.\n<\/p>\n<p>\nIf you want to generate unique 64-bit values,\nyou can just use\n<code>InterlockedIncrement64<\/code>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This article happened to catch my eye: I needed to generate some unique number in my application. I could use GUID, but it was too large for me (I need to keep lots of unique identifiers). I found something like this: [System.Runtime.InteropServices.DllImport(&#8220;Kernel32.dll&#8221;)] private static extern int QueryPerformanceFrequency(ref System.Int64 frequency); [System.Runtime.InteropServices.DllImport(&#8220;Kernel32.dll&#8221;)] private static extern int QueryPerformanceCounter(ref [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-26143","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>This article happened to catch my eye: I needed to generate some unique number in my application. I could use GUID, but it was too large for me (I need to keep lots of unique identifiers). I found something like this: [System.Runtime.InteropServices.DllImport(&#8220;Kernel32.dll&#8221;)] private static extern int QueryPerformanceFrequency(ref System.Int64 frequency); [System.Runtime.InteropServices.DllImport(&#8220;Kernel32.dll&#8221;)] private static extern int QueryPerformanceCounter(ref [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/26143","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=26143"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/26143\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=26143"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=26143"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=26143"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}