3 ms·
My thinking is the same. I doubt this is an oversight. Making the String constructor thread-safe would likely slow things significantly. Great point about thing
by neandrake 3y ago
My thinking is the same. I doubt this is an oversight. Making the String constructor thread-safe would likely slow things significantly. Great point about things being assumed not thread-safe. The JDK is pretty thorough with documenting thread-safety.
- neandrake 3y agoComing back to this the answer is probably not strictly about concurrency and so there is a possibility something would need addressed about this.
- masklinn 3y ago> Making the String constructor thread-safe would likely slow things significantly. By my reckoning it would speed things up, at least going by the Java code.
- neandrake 3y agoBy what means? The only ways I would expect are either unconditionally duplicating the array or mutex, and I don’t think the mutex wouldn’t be simple. Adding a sync block on the input could be done but that’s assuming nothing else is locked on it (but probably points to there being a race condition elsewhere if there is..). Unconditionally duplicating the array would use more memory and wouldn’t be faster.
- masklinn 3y agoInlining `StringUTF16.compress` and `StringUTF16.bytes what the code currently does is essentially this (using python as pseudocode): latin1 = bytearray(len(input)) for i in range(len(input)): c = input[i] if c > 255: latin1 = None break latin1[i] = c if latin1 is not None: return LATIN1, latin1 utf16 = bytearray(len(input)*2) for i in range(0, len(input)): c = input[i] utf16[2*i] = c >> HI_BYTE_SHIFT utf16[2*i+1] = c >> LO_BYTE_SHIFT return UTF16, utf16 The issue occurs because `input` can be mutated between the moment it finds a char that's above 255 in the first loop and the moment it visits that same char in the second loop. The solution is to not do that, but instead something like: latin1 = bytearray(len(input)) for i in range(len(input)): c = input[i] if c <= 255: latin1[i] = c continue utf16 = bytearray(len(input)*2) for j in range(i): utf16[2*j] = latin1[j] latin1 = None utf16[2*i] = c utf16[2*i+1] = c >> 8 for j in range(i+1, len(input)): c = input[j] utf16[2*i] = c utf16[2*i+1] = c >> 8 return UTF16, utf16 return LATIN1, latin1 This means if you find a char that's above 255 you will always append that char to the UTF16 array, there's no possibility that someone will change it under you because you append the exact same char you tested. So you can not get into the situation the essay describes, a utf16 string will always contain at least one non-latin1-code unit. Non-vectorised performances should an improvement as latin1 to utf16 is a trivial operation (just copy every byte of the input to every other byte of the output) Though if you vectorised the char to utf16 conversion you now vectorise two loops on bailout (latin1 -> utf16 up to i, then char -> utf16) which is probably less efficient. I don't know if the JDK has vectorised optimisations, the source has "HotSpotIntrinsicCandidate" annotations but I don't know to what extent the intrinsics go.