Giter Site home page Giter Site logo

f4b6a3 / uuid-creator Goto Github PK

View Code? Open in Web Editor NEW
336.0 11.0 42.0 2.01 MB

A UUID library for Java.

License: MIT License

Java 99.91% Shell 0.05% Batchfile 0.04%
uuid guid rfc-4122 id-generator unique-id java guid-generator uuid-generator id identifier

uuid-creator's People

Contributors

ahmadimt avatar chriscurtin avatar dependabot[bot] avatar fabiolimace avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

uuid-creator's Issues

Java Modules

Looks like I can't use your module with a module-info, I think it's missing either an Automatic-Module name or whatever in MANIFEST.mf, although at this point it might be better to just add the module-info.java

UUID URIs

UUIDs can be represented as URIs (specifically URNs) using the standardized scheme in RFC 4122. This basically involes pre-pending 'urn:uuid:' to the UUID text representation eg 'urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6'.

It would be useful to provide code for converting such URIs to UUIDs and converting UUIDs to such URIs. This code isn't directly related to UUID generation but could be stored in a sub-package like f4b6a3.uuid.uri. Again, sorry to spam your project, but I'd love to see all this UUID-related functionality implemented once in a single best of breed library instead of replicated in project after project.

consider the (optional) use of ThreadLocal(Random)

The uuid-creator (and ulid-creator) uses internally java.util.Random . This could lead to contention (and latency) if a very high number of threads generate uuid/ulid at the same time. Because java uses a single shared SecureRandom (and Random) instance to generate the random bits.

The java.util.concurrent.ThreadLocalRandom extends Random to eliminate such issues. Maybe you can include this idea within the Generator-Patterns of uuid and ulid (e.g., .withTreadLocal()).

UuidCreator
.getUlidBasedCreator()
.withTreadLocal()
.withFastRandomGenerator()

Another alternative is to put the SecureRandom (Random) or any other Random derived classes into a ThreadLocal (don't forget to remove() the thread local to avoid memory leaks).

Another alternative is to use a buffer of precreated uuid/ulids:

UuidCreator
.getUlidBasedCreator()
// uses a buffer if available by a previous call or creates one with 1000
// the next caller gets the value from the buffer
.fromBuffer(1000)
.withFastRandomGenerator()

But I think the TreadLocal-approach would be good enough.

Add methods to UuidCreator for generating UUIDs from bytes and from strings

  1. Add methods to UuidCreator:
  • fromBytes(byte[] bytes)
  • fromString(String string)
  1. The new methods must validate the input argument.

  2. Use the existing methods in UuidConverter.

  3. The method UuidConverter#fromString() needs optimization.

  4. The method used in UuidValidator#isValid() needs optimization. The regex is not necessary because the UUID canonical format is simple.

Release version 3.0.0

  1. Change DefaultTimestampStrategy to wait the next millisecond if overrun occurs, instead of throwing exception;
  2. Remove variable "UUIDCREATOR_NODEID" and property "uuidcreator.nodeid";
  3. Remove UuidCreatorException and IllegalUuidException.

Update README.md and javadoc.

Add methods to UuidCreator for generating UUIDs with custom time, nodeid and clock sequence

Methods to add:

  • UuidCreator.getTimeBased(Instant instant, long node, int clockseq);
  • UuidCreator.getTimeBasedWithMac(Instant instant, long node, int clockseq);
  • UuidCreator.getTimeOrdered(Instant instant, long node, int clockseq);
  • UuidCreator.getTimeOrderedWith(Instant instant, long node, int clockseq);

The values passed as arguments to those methods override the default values used by the generator to create UUIDs.

Add new base-n codecs for base-36, base-58 and base-62

List of new alphabets (char sets):

  • base-36: "0123456789abcdefghijklmnopqrstuvwxyz";
  • base-58: "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
  • base-62: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".

The alphabet for base-58 is the same used in Bitcoin.

extractInstant() from Comb-String

One question:

How can I get the Instant from a comb which comes from a String?

var combString = UuidCreator.getPrefixComb().toString();

There is a UuidUtil.extractInstant(), UlidUtil.extractInstant(), but no CombUtil.extractInstant().

Creators in UiidCreator are not thread-safe

The static creators in UiidCreator are lazily initialized but not in a thread-safe manner. (concurrent invocations may lead to incorrect/duplicated initialization of the singleton)

See https://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom for solution.

Here is the current code:

public class UuidCreator {

    private static RandomUuidCreator randomCreator;

    public static UUID getRandom() {
        if (randomCreator == null) {
            randomCreator = getRandomCreator();
        }
        return randomCreator.create();
    }
}

and here is the equivalent with the thread-safe idiom applied:

public class UuidCreator {

    public static UUID getRandom() {
        return RandomCreatorLazyHolder.INSTANCE.create();
    }

    private static class RandomCreatorLazyHolder {
        static final RandomUuidCreator INSTANCE = getRandomCreator();
    }
}

Btw: Really like where you are taking this library. It is on the path to become the UUID library for Java.

UUID Slugs

First off, great lib. The functionality provided and the quality of the code are impressive.

I wonder if you'd be interested in supporting UUID Slugs?

UUID Slugs are a base64 encoding of UUIDs that can be safely included in URLs and even file names. This sort of functionality is very commonly required and I think instead of continuing to replicate it in project after project it should be implemented once in a project like uuid-creator.

A UUID Slug is the string generated by (url safe) Base64 encoding a UUID and then stripping the padding resulting in a 22-character string that can be safely used in filenames and URLs. This functionality isn't directly related to creation but could be stored in a sub-package like f4b6a3.uuid.slug.

See also:

Add system data hash node identifier strategy

Create a node identifier strategy that calculates a node identifier using as many system properties as one can get.

Suggested name: HashNodeIdentifierStrategy.

Note that the same strategy existed in version 1.x.x of uuid-creator, named as FingerprintNodeIdentifierStrategy. It was removed because I thought that no one would use it. But I saw that a similar idea is implemented in the Cassandra's UUIDGen, a very popular generator. So I'll put it back to uuid-creator.

Link for UUIDGen (Cassandra): https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/utils/UUIDGen.java

MAC address: NetworkInterface.getNetworkInterfaces() is expensive

In relation to:

protected long getHardwareAddress() {
    try {
        byte[] mac;
        NetworkInterface nic;
        List<InterfaceAddress> list;
        Enumeration<NetworkInterface> enm;

        enm = NetworkInterface.getNetworkInterfaces(); // VERY EXPENSIVE !!
        while (enm.hasMoreElements()) {
            nic = enm.nextElement();
            list = nic.getInterfaceAddresses();
            mac = nic.getHardwareAddress();
            if ((mac != null) && (!list.isEmpty()) && !(nic.isLoopback() || nic.isVirtual())) {
                return ByteUtil.toNumber(mac);
            }
        }
    } catch (SocketException | NullPointerException e) {
        // (2) return random number
        return getRandomMulticastNodeIdentifier();
    }
    // (2) return random number
    return getRandomMulticastNodeIdentifier();
}

Just a hint about my experience with NetworkInterface.getNetworkInterfaces(). This is a potential long-running operation. On my Windows box it takes 1200 msecs and returns some 45 entries. The reason is that Windows seems to create a lot virtual/bogus network interfaces which you cannot see with ipconfig /all command. From my tests it is the creation of the enumeration which takes time. Traversing the enumeration seems to have no overhead.

It is not a problem per-se in the library's current implementation because it is called only once, but the expensiveness of this call may be noted in the code and relevant places in Javadoc. For UI type applications a delay of 1,2 secs causes a noticeable delay.

Test failing after upgrading to OpenJDK 11

Hi,

After upgrading to OpenJDK 11 (11.0.5) one of the tests if failing:

`
expected:<2020-03-04T13:53:58.516385Z> but was:<2020-03-04T13:53:58.516Z>
Expected :2020-03-04T13:53:58.516385Z
Actual :2020-03-04T13:53:58.516Z

java.lang.AssertionError: expected:<2020-03-04T13:53:58.516385Z> but was:<2020-03-04T13:53:58.516Z>
at org.junit.Assert.fail(Assert.java:88)
at org.junit.Assert.failNotEquals(Assert.java:834)
at org.junit.Assert.assertEquals(Assert.java:118)
at org.junit.Assert.assertEquals(Assert.java:144)
at com.github.f4b6a3.uuid.util.TimestampUtilTest.testToInstantFromInstant(TimestampUtilTest.java:16)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:110)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:38)
at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:62)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
at com.sun.proxy.$Proxy5.processTestClass(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:118)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:175)
at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:157)
at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
at java.base/java.lang.Thread.run(Thread.java:834)`

UUID NCNames

Would be nice to support UUID NCName Encoding.

UUID NCName Encoding provides a mechanism to convert UUIDs to/from strings that are valid NCNames which can be used in XML documents and other contexts. (NCNames are strings not allowed to contain hyphen ('-) characters and not start with a digit.)

One interesting scheme is outlined in this RFC and implemented in p5-data-uuid-ncname.

This functionality isn't directly related to UUID creation but could be implemented in a subpackage like f4b6a3.uuid.name. This sort of functionality gets re-implemented a lot so I always figure it'd be useful to place it in a single "best of breed" library.

New algorithm sequential uuid ?

What about a new non-standard algorithm :
sequential uuid generator ?

See https://www.2ndquadrant.com/en/blog/sequential-uuid-generators/

It is database friendly like COMB but has some advantages :

  • full timestamp stored as prefix/suffix creates security leak about time of generation. This new algorithm is a rolling value over 2 bytes, so it has not this problem
  • Risk of collision is far thinner using this algorithm as we still have 14 bytes of random bytes over 16 and not 10 over 16 with COMB.

A running code is available at https://gist.github.com/bflorat/d7d152059b65844531b3c69e4438d00e

(credit : original code at https://gist.github.com/zenios/72dfaf3a931ad0e4e5e7031d950c3d9c but doesn't work)

v1 and v6 are not entirely threadsafe

Hello. Thanks for this great lib!

I have an issue with thread safety. I'm using v6 (which is slightly modified version of v1 from what I cal tell) and I'm able to generate identical UUIDs from parallel threads.

It seems that the sequence counter is not thread safe at all. My current workaround is to pass the external seq generated by AtomicInteger.

It would be great however if this gets fixed, especially cause the doc is mentioning thread safety.

Cheers!

performance table with comb, ulid, tsid

Hi,

to compare all available generators, it would be nice to include comb.

I did a little benchmark with timebased uuid and ulid (where each of it generates 100 id's):

  • Ulid took approx. 15 millis for generating 100 ID's
  • Time Based UUID took approx. 1 millis for generating 100 ID's

Thanks and greetings!:

Release version 3.1.0

Create:

  • SharedRandom: a shared SecureRandom.
  • MachineId: a new generator of hash-based machine identifiers.

Remove:

  • TlsSecureRandom: the shared random generator doesn't need to be thread local;
  • Fingerprint: it uses too much properties, including software version and locale;
  • NetworkData: it is too complex and unnecessary.

add fast ulid creator in benchmark

The ulid-creator has

UlidCreator.getFastUlid()

coming from

UuidCreator.getUlidBasedCreator().withFastRandomGenerator().create().toString().

Could you add the fast ulid creator in this benchmark?

Throughput.UuidCreator_FastUlidBasedGuid
AverageTime.UuidCreator_FastUlidBasedGuid

Add lazy holders for ulid into uuid-creator

Actually, the codebase from ulid-creator and uuid-creator differs a little bit when it comes to creating the instances. For example, in ulid-creator, there is the lazy holder:

public static String getFastUlid() {
    return FastGuidCreatorLazyHolder.INSTANCE.createUlid();
}

But such lazy holders defined in UlidCreator are missing in uuid-creator project. Maybe you can include or better unify the codebase, so that ulid-creator is a 1:1 extraction from uuid-creator project.

Provide OSGI support

UUID creator could also be used in OSGI environments if MANIFEST.MF would have bundle entries like e.g.

Bundle-ManifestVersion: 2
Bundle-Name: UUID Creator
Bundle-SymbolicName: com.github.f4b6a3.uuid-creator
Bundle-Version: 4.0.0
Export-Package: com.github.f4b6a3.uuid,
  ...

Please provide a solution and UUID creator could be used out of the box.

Create a strategy interface for random-based UUIDs

The current random-based generators use instances of java.util.Random. This new strategy interface will allow usage of alternate random number generators. The strategy will be called RandomStrategy.

The default strategy, called DefaultRandomStrategy, will be implemented with a thread local java.security.SecureRandom generator.

There'll be another implementation, called OtherRandomStrategy, that receives an instance of java.util.Random by constructor.

The developer can also create their custom random strategy. See this example:

import com.github.niceguy.random.AwesomeRandom;
import com.github.f4b6a3.uuid.strategy.RandomStrategy;

public class MyOwnRandomStrategy implements RandomStrategy {

    private final AwesomeRandom awesomeRandom = new AwesomeRandom();

    public void nextBytes(byte[] bytes) {
        this.awesomeRandom.nextBytes(bytes);
    }
}

UNID: as an alternative for ULID

The ULID are derived from UUID (with timezone) creators and hence uses also a string based approach. Please include another alternative to have a number instead of a string for ULID:

UNID-based Number: a Number with 48 bits for Unix milliseconds and 80 bits for randomness. The suffix of 80 bits for randomness can be (secure or fast) random numbers. (Or: 13 digits for millis and 5 or 6 digits for random suffix)

You can call it Unid (Universally Unique Number Sortable Identifier)

This UNID would be a good alternative for ULID because:

  • numbers need not much memory (important for database) in compare to strings
  • the millisecond part from UNID can be easily extracted without string computations (UnidUtil.extractInstant())
  • numbers can be easily compared (sorted) (for example, with java streams)

I had actually used the approach from https://github.com/callicoder/java-snowflake (read more about https://www.callicoder.com/distributed-unique-id-sequence-number-generator/). But the unid-generator would be a very good alternative to include it in uuid-creator and ulid-creator project. Could you do that?

Get MAC address: check if nic is UP is not implemented?

The Javadoc for MacNodeIdentifierStrategy.getNodeIdentifier() says:

It looks for the first MAC that is up and running. If none is up, it
looks for the first MAC.

but I don't see that reflected in the code. It doesn't do nic.isUp().

Also, it says:

It returns ZERO if none is found.

but that too I cannot see in the code. It will never return ZERO as far as I can tell.

Please review.

Java 8 Compatibility

I want to use this library in one of my projects. We are still using Java 8 and the latest version of this library is compatible with JDK 11 and above. Can we please make this JDK 8 compatible. I guess, Java 8 is still widely used.

I can submit a PR for this.

ulid and timebased uuid has different precisions on Instant

I have a question:
I generated an ulid and an timebased uuid to a string. When extracting the time from it, the timebased uuid seems more precise:

// prints 2021-01-17T18:28:14.075
UlidUtil.extractInstant(ulid).atZone(ZoneId.systemDefault()).toLocalDateTime();
// prints 2021-01-17T18:28:14.075011200
UuidUtil.extractInstant(UuidCreator.fromString(timeUUID)).atZone(ZoneId.systemDefault()).toLocalDateTime()

Why is timebased uuid more precise than ulid?

Optimize uuid codecs more

  1. Memory usage optimization: only the base-16 is required by the lib. The other base-n instances should be loaded if the user needs them.

  2. Processing optimization: add base-n codecs for base-16, base-32 and base-36 that encode do UPPER CASE to avoid calling String.toUpperCase().

  3. Add more test cases.

Unecessary dependencies

The library is hard to use because it brings with it too many transitive dependencies. These dependencies may conflict with other parts of your application.

This is a shame, because in itself the library has no dependencies. It is all due to the benchmarking which is part of the library, but shouldn't be. The solution is to put the benchmarking in a separate Maven module.

Temporary workaround

Until this is fixed, people can use the uuid-creator library in the following way in their applications:

<dependency>
	<groupId>com.github.f4b6a3</groupId>
	<artifactId>uuid-creator</artifactId>
	<version>0.9.0</version>
	<exclusions>
		<exclusion> 
			<groupId>org.openjdk.jmh</groupId>
			<artifactId>jmh-core</artifactId>
		</exclusion>
		<exclusion> 
			<groupId>org.openjdk.jmh</groupId>
			<artifactId>jmh-generator-annprocess</artifactId>
		</exclusion>
		<exclusion> 
			<groupId>com.fasterxml.uuid</groupId>
			<artifactId>java-uuid-generator</artifactId>
		</exclusion>
		<exclusion> 
			<groupId>com.eaio.uuid</groupId>
			<artifactId>uuid</artifactId>
		</exclusion>
	</exclusions>   
</dependency>

Remove the xorshift random generator

The implementation of xorshift in this project is not secure, as it depends on the internal parts of java.util.Random. Another problem is that it has not been well tested, although the algorithm is simple.

There are many alternatives to this xorshift on github.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.