diff --git a/contrib/uuid-ossp/uuid-ossp.c b/contrib/uuid-ossp/uuid-ossp.c
index d4fc62bd4f33b5f6aec75e3c0c247a9f67c88bd5..71bdfa15fa34e068b9799a251e11bb0791e897aa 100644
--- a/contrib/uuid-ossp/uuid-ossp.c
+++ b/contrib/uuid-ossp/uuid-ossp.c
@@ -79,6 +79,42 @@ pguuid_complain(uuid_rc_t rc)
 				 errmsg("OSSP uuid library failure: error code %d", rc)));
 }
 
+/*
+ * We create a uuid_t object just once per session and re-use it for all
+ * operations in this module.  OSSP UUID caches the system MAC address and
+ * other state in this object.  Reusing the object has a number of benefits:
+ * saving the cycles needed to fetch the system MAC address over and over,
+ * reducing the amount of entropy we draw from /dev/urandom, and providing a
+ * positive guarantee that successive generated V1-style UUIDs don't collide.
+ * (On a machine fast enough to generate multiple UUIDs per microsecond,
+ * or whatever the system's wall-clock resolution is, we'd otherwise risk
+ * collisions whenever random initialization of the uuid_t's clock sequence
+ * value chanced to produce duplicates.)
+ *
+ * However: when we're doing V3 or V5 UUID creation, uuid_make needs two
+ * uuid_t objects, one holding the namespace UUID and one for the result.
+ * It's unspecified whether it's safe to use the same uuid_t for both cases,
+ * so let's cache a second uuid_t for use as the namespace holder object.
+ */
+static uuid_t *
+get_cached_uuid_t(int which)
+{
+	static uuid_t *cached_uuid[2] = {NULL, NULL};
+
+	if (cached_uuid[which] == NULL)
+	{
+		uuid_rc_t	rc;
+
+		rc = uuid_create(&cached_uuid[which]);
+		if (rc != UUID_RC_OK)
+		{
+			cached_uuid[which] = NULL;
+			pguuid_complain(rc);
+		}
+	}
+	return cached_uuid[which];
+}
+
 static char *
 uuid_to_string(const uuid_t *uuid)
 {
@@ -109,20 +145,14 @@ string_to_uuid(const char *str, uuid_t *uuid)
 static Datum
 special_uuid_value(const char *name)
 {
-	uuid_t	   *uuid;
+	uuid_t	   *uuid = get_cached_uuid_t(0);
 	char	   *str;
 	uuid_rc_t	rc;
 
-	rc = uuid_create(&uuid);
-	if (rc != UUID_RC_OK)
-		pguuid_complain(rc);
 	rc = uuid_load(uuid, name);
 	if (rc != UUID_RC_OK)
 		pguuid_complain(rc);
 	str = uuid_to_string(uuid);
-	rc = uuid_destroy(uuid);
-	if (rc != UUID_RC_OK)
-		pguuid_complain(rc);
 
 	return DirectFunctionCall1(uuid_in, CStringGetDatum(str));
 }
@@ -166,20 +196,14 @@ uuid_ns_x500(PG_FUNCTION_ARGS)
 static Datum
 uuid_generate_internal(int mode, const uuid_t *ns, const char *name)
 {
-	uuid_t	   *uuid;
+	uuid_t	   *uuid = get_cached_uuid_t(0);
 	char	   *str;
 	uuid_rc_t	rc;
 
-	rc = uuid_create(&uuid);
-	if (rc != UUID_RC_OK)
-		pguuid_complain(rc);
 	rc = uuid_make(uuid, mode, ns, name);
 	if (rc != UUID_RC_OK)
 		pguuid_complain(rc);
 	str = uuid_to_string(uuid);
-	rc = uuid_destroy(uuid);
-	if (rc != UUID_RC_OK)
-		pguuid_complain(rc);
 
 	return DirectFunctionCall1(uuid_in, CStringGetDatum(str));
 }
@@ -202,25 +226,15 @@ uuid_generate_v1mc(PG_FUNCTION_ARGS)
 static Datum
 uuid_generate_v35_internal(int mode, pg_uuid_t *ns, text *name)
 {
-	uuid_t	   *ns_uuid;
-	Datum		result;
-	uuid_rc_t	rc;
+	uuid_t	   *ns_uuid = get_cached_uuid_t(1);
 
-	rc = uuid_create(&ns_uuid);
-	if (rc != UUID_RC_OK)
-		pguuid_complain(rc);
-	string_to_uuid(DatumGetCString(DirectFunctionCall1(uuid_out, UUIDPGetDatum(ns))),
+	string_to_uuid(DatumGetCString(DirectFunctionCall1(uuid_out,
+													   UUIDPGetDatum(ns))),
 				   ns_uuid);
 
-	result = uuid_generate_internal(mode,
-									ns_uuid,
-									text_to_cstring(name));
-
-	rc = uuid_destroy(ns_uuid);
-	if (rc != UUID_RC_OK)
-		pguuid_complain(rc);
-
-	return result;
+	return uuid_generate_internal(mode,
+								  ns_uuid,
+								  text_to_cstring(name));
 }