{"action":"opened","issue":{"url":"https://api.github.com/repos/alizain/ulid/issues/3","repository_url":"https://api.github.com/repos/alizain/ulid","labels_url":"https://api.github.com/repos/alizain/ulid/issues/3/labels{/name}","comments_url":"https://api.github.com/repos/alizain/ulid/issues/3/comments","events_url":"https://api.github.com/repos/alizain/ulid/issues/3/events","html_url":"https://github.com/alizain/ulid/issues/3","id":169268525,"number":3,"title":"Not sure I like the new spec's \"increment within same ms\" change + more thoughts","user":{"login":"RobThree","id":607888,"avatar_url":"https://avatars.githubusercontent.com/u/607888?v=3","gravatar_id":"","url":"https://api.github.com/users/RobThree","html_url":"https://github.com/RobThree","followers_url":"https://api.github.com/users/RobThree/followers","following_url":"https://api.github.com/users/RobThree/following{/other_user}","gists_url":"https://api.github.com/users/RobThree/gists{/gist_id}","starred_url":"https://api.github.com/users/RobThree/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/RobThree/subscriptions","organizations_url":"https://api.github.com/users/RobThree/orgs","repos_url":"https://api.github.com/users/RobThree/repos","events_url":"https://api.github.com/users/RobThree/events{/privacy}","received_events_url":"https://api.github.com/users/RobThree/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2016-08-04T01:02:21Z","updated_at":"2016-08-04T01:02:21Z","closed_at":null,"body":"You [changed the spec](https://github.com/alizain/ulid/commit/9f01c3ed1d4fdf6acfddb6d9f9cf49e621fa5de9#diff-04c6e90faac2675aa89e2176d2eec7d8R89) to include:\r\n\r\n> To ensure sortability for IDs generated within the same millisecond, implementations should remember the most recently generated randomness string and increment the most significant character that is not the last character in the encoding.\r\n\r\nI don't think you understand the impact of this change; it brings a *whole lot of hurt* into your world. For instance, you can't rely on wall-clock-time (which [you fell for](https://github.com/alizain/ulid/blob/9f01c3ed1d4fdf6acfddb6d9f9cf49e621fa5de9/index.js#L83)). Unless you can get a **reliable, monotonic, strictly increasing** timesource (which is (near?) impossible AFAIK in JS) you'll run into trouble later. Why? Because: [wall-clock-time goes back (DST) / stands still (leap seconds are sometimes implemented as such) / does other weird stuff](http://infiniteundo.com/post/25326999628/falsehoods-programmers-believe-about-time). Trust me, [I know](https://github.com/RobThree/IdGen) :wink: Also: some systems may not even have 'ms-resolution' timers.\r\n\r\nThere's 80 bits of random data; I think it's safe to assume (even with the [birthday paradox](https://en.wikipedia.org/wiki/Birthday_problem) in mind) that the chance on a collision (within any, random, millisecond) is similar to the chance of a GUID collision. However, that would be if the ULID's would be spread evenly across time (which would, in effect, make a ULID similar or even equal to a GUID). So, given that ULID's are typically 'clustered' in a certain timespan the chance on a collision goes up. Worst-case would be a DST chance + some other 'random event' that would cause the same 'millisecond'-point-in-time to exist (say) 3 or 4 times. The chance on a collision would increase a lot but (I haven't done the math yet) would still suffice for most purposes unless you're Google maybe and generating many millions or even billions of ULID's p/ms.\r\n\r\nSo I guess my advice is to leave that part out of the spec (and, let's be honest, [this method](https://github.com/alizain/ulid/blob/master/index.js#L64) is no beauty either (it could be improved but wouldn't be worth the trouble IMHO))  and keep implementations *much* simpler that way. You could compare a ULID it with a [v4 UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_.28random.29) with the only difference that the first 6 bytes (48 bits) are reserved for a timestamp for better ordering. However, it *does* mean that, within the millisecond, the ordering is 'random' so that the spec may need to be more clear about it / reflect that fact.\r\n\r\nFor inspiration about some more of the problems you might run into you might want to look at Twitter's [Snowflake](https://github.com/twitter/snowflake) (retired but [still available](https://github.com/twitter/snowflake/tree/b3f6a3c6ca8e1b6847baa6ff42bf72201e2c2231)) or have a look at my \"Snowflake-alike\" [IdGen](https://github.com/RobThree/IdGen). Both are 64 bit (actually 63\\*) equivalents of ulid.\r\n\r\n\\* Come to think of it: You might also want to steer clear of the sign-bit; when systems would order on the (internal) 128 bit representation / byte-array (for 'speed') the order may 'break' as soon as the sign bit is set to `1`. Twitter thought of it *way* before it happened but I think it's a good idea. Sacrificing 1 bit out of 128 should't be *that* much of a problem (though it does halve your \"ulid-space\" from 2^128 to 2^127).\r\n\r\nI was/am doing a ulid .Net port (waaay more extensive than fvilvers', with all due respect!) and also implemented the binary form, created methods to convert to/from UUID's (since ULID's and UUID's are both 128 bit you can easily one to the other and vice versa). I also implemented a `Parse(...)` method and some others and will publish on GitHub very soon. There are some things I thought of / came across which might need 'agreement' and be put in the spec:\r\n\r\n- ulid's are, IMHO, case-**in**sensitive (e.g. **NOT** case-sensitive)\r\n- We may want to allow / think about / specify a separator for readability. No `{` and `}` mess like (G/U)UID's but something like `ttttt-ttttt-rrrrrr-rrrrr-rrrrr` (lengths 5-5-6-5-5) might make ulid's more readable. Other formats/separators are ofcourse a possibility (as well as none of this ofcourse; I'm just bringing my ideas to the table)\r\n- You/we may want to decide on pronunciation and document it: \"you-lid\"? \"you-el-i-dee\"? \"uhl-id\"? Something else? You/we want to avoid the GIF's [\"Jif\" v.s. \"Gif\"](http://howtoreallypronouncegif.com/) wars\r\n- Besides the pronunciation, same goes for a \"standardized\" writing. I catch myself writing `ulid`, `ULID`, `UlId`, ... so that may have to be standardized too\r\n- I had more... but can't think of it now. Will add here / open new issue when I think of it.\r\n\r\nSo far, for now, another $0.02 of mine :stuck_out_tongue_closed_eyes: "}}
{"actor":{"display_login":"RobThree"}}