diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 128ee13b5f7f2230b46b028a3df8f31b55c122c7..5b58d2e84dcf064c27d433ee29caa3da272bd437 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -646,18 +646,11 @@ postgres   27093  0.0  0.0  30096  2752 ?        Ss   11:34   0:00 postgres: ser
        <itemizedlist>
         <listitem>
          <para>
-          <literal>LWLockNamed</>: The backend is waiting for a specific named
-          lightweight lock.  Each such lock protects a particular data
-          structure in shared memory.  <literal>wait_event</> will contain
-          the name of the lightweight lock.
-         </para>
-        </listitem>
-        <listitem>
-         <para>
-          <literal>LWLockTranche</>: The backend is waiting for one of a
-          group of related lightweight locks.  All locks in the group perform
-          a similar function; <literal>wait_event</> will identify the general
-          purpose of locks in that group.
+          <literal>LWLock</>: The backend is waiting for a lightweight lock.
+          Each such lock protects a particular data structure in shared memory.
+          <literal>wait_event</> will contain a name identifying the purpose
+          of the lightweight lock.  (Some locks have specific names; others
+          are part of a group of locks each with a similar purpose.)
          </para>
         </listitem>
         <listitem>
@@ -825,7 +818,7 @@ postgres   27093  0.0  0.0  30096  2752 ?        Ss   11:34   0:00 postgres: ser
 
       <tbody>
        <row>
-        <entry morerows="41"><literal>LWLockNamed</></entry>
+        <entry morerows="57"><literal>LWLock</></entry>
         <entry><literal>ShmemIndexLock</></entry>
         <entry>Waiting to find or allocate space in shared memory.</entry>
        </row>
@@ -1011,7 +1004,6 @@ postgres   27093  0.0  0.0  30096  2752 ?        Ss   11:34   0:00 postgres: ser
          <entry>Waiting to read or update old snapshot control information.</entry>
         </row>
         <row>
-         <entry morerows="15"><literal>LWLockTranche</></entry>
          <entry><literal>clog</></entry>
          <entry>Waiting for I/O on a clog (transaction status) buffer.</entry>
         </row>
@@ -1279,7 +1271,7 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
  pid  | wait_event_type |  wait_event
 ------+-----------------+---------------
  2540 | Lock            | relation
- 6644 | LWLockNamed     | ProcArrayLock
+ 6644 | LWLock          | ProcArrayLock
 (2 rows)
 </programlisting>
    </para>
@@ -3347,55 +3339,49 @@ SELECT pg_stat_get_backend_pid(s.backendid) AS pid,
     </row>
     <row>
      <entry><literal>lwlock-acquire</literal></entry>
-     <entry><literal>(char *, int, LWLockMode)</literal></entry>
+     <entry><literal>(char *, LWLockMode)</literal></entry>
      <entry>Probe that fires when an LWLock has been acquired.
       arg0 is the LWLock's tranche.
-      arg1 is the LWLock's offset within its tranche.
-      arg2 is the requested lock mode, either exclusive or shared.</entry>
+      arg1 is the requested lock mode, either exclusive or shared.</entry>
     </row>
     <row>
      <entry><literal>lwlock-release</literal></entry>
-     <entry><literal>(char *, int)</literal></entry>
+     <entry><literal>(char *)</literal></entry>
      <entry>Probe that fires when an LWLock has been released (but note
       that any released waiters have not yet been awakened).
-      arg0 is the LWLock's tranche.
-      arg1 is the LWLock's offset within its tranche.</entry>
+      arg0 is the LWLock's tranche.</entry>
     </row>
     <row>
      <entry><literal>lwlock-wait-start</literal></entry>
-     <entry><literal>(char *, int, LWLockMode)</literal></entry>
+     <entry><literal>(char *, LWLockMode)</literal></entry>
      <entry>Probe that fires when an LWLock was not immediately available and
       a server process has begun to wait for the lock to become available.
       arg0 is the LWLock's tranche.
-      arg1 is the LWLock's offset within its tranche.
-      arg2 is the requested lock mode, either exclusive or shared.</entry>
+      arg1 is the requested lock mode, either exclusive or shared.</entry>
     </row>
     <row>
      <entry><literal>lwlock-wait-done</literal></entry>
-     <entry><literal>(char *, int, LWLockMode)</literal></entry>
+     <entry><literal>(char *, LWLockMode)</literal></entry>
      <entry>Probe that fires when a server process has been released from its
       wait for an LWLock (it does not actually have the lock yet).
       arg0 is the LWLock's tranche.
-      arg1 is the LWLock's offset within its tranche.
-      arg2 is the requested lock mode, either exclusive or shared.</entry>
+      arg1 is the requested lock mode, either exclusive or shared.</entry>
     </row>
     <row>
      <entry><literal>lwlock-condacquire</literal></entry>
-     <entry><literal>(char *, int, LWLockMode)</literal></entry>
+     <entry><literal>(char *, LWLockMode)</literal></entry>
      <entry>Probe that fires when an LWLock was successfully acquired when the
       caller specified no waiting.
       arg0 is the LWLock's tranche.
-      arg1 is the LWLock's offset within its tranche.
-      arg2 is the requested lock mode, either exclusive or shared.</entry>
+      arg1 is the requested lock mode, either exclusive or shared.</entry>
     </row>
     <row>
      <entry><literal>lwlock-condacquire-fail</literal></entry>
-     <entry><literal>(char *, int, LWLockMode)</literal></entry>
+     <entry><literal>(char *, LWLockMode)</literal></entry>
      <entry>Probe that fires when an LWLock was not successfully acquired when
       the caller specified no waiting.
       arg0 is the LWLock's tranche.
-      arg1 is the LWLock's offset within its tranche.
-      arg2 is the requested lock mode, either exclusive or shared.</entry>
+      arg1 is the requested lock mode, either exclusive or shared.</entry>
     </row>
     <row>
      <entry><literal>lock-wait-start</literal></entry>
diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c
index bbae5847f2d5dab6d533c921de1aafd1134fc9cb..8b95f35dbaf412c57deb8cf048d9ef9299bb4b6b 100644
--- a/src/backend/access/transam/slru.c
+++ b/src/backend/access/transam/slru.c
@@ -216,9 +216,6 @@ SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns,
 		Assert(strlen(name) + 1 < SLRU_MAX_NAME_LENGTH);
 		strlcpy(shared->lwlock_tranche_name, name, SLRU_MAX_NAME_LENGTH);
 		shared->lwlock_tranche_id = tranche_id;
-		shared->lwlock_tranche.name = shared->lwlock_tranche_name;
-		shared->lwlock_tranche.array_base = shared->buffer_locks;
-		shared->lwlock_tranche.array_stride = sizeof(LWLockPadded);
 
 		ptr += BUFFERALIGN(offset);
 		for (slotno = 0; slotno < nslots; slotno++)
@@ -237,7 +234,8 @@ SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns,
 		Assert(found);
 
 	/* Register SLRU tranche in the main tranches array */
-	LWLockRegisterTranche(shared->lwlock_tranche_id, &shared->lwlock_tranche);
+	LWLockRegisterTranche(shared->lwlock_tranche_id,
+						  shared->lwlock_tranche_name);
 
 	/*
 	 * Initialize the unshared control struct, including directory path. We
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 084401d2f238d729243bca4e3fdad4ff5a82f123..aa9ee5a0dd84cad03895ab3a63e99c97a4eadbd1 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -517,7 +517,6 @@ typedef struct XLogCtlInsert
 	 * WAL insertion locks.
 	 */
 	WALInsertLockPadded *WALInsertLocks;
-	LWLockTranche WALInsertLockTranche;
 } XLogCtlInsert;
 
 /*
@@ -4688,7 +4687,7 @@ XLOGShmemInit(void)
 		/* Initialize local copy of WALInsertLocks and register the tranche */
 		WALInsertLocks = XLogCtl->Insert.WALInsertLocks;
 		LWLockRegisterTranche(LWTRANCHE_WAL_INSERT,
-							  &XLogCtl->Insert.WALInsertLockTranche);
+							  "wal_insert");
 		return;
 	}
 	memset(XLogCtl, 0, sizeof(XLogCtlData));
@@ -4711,11 +4710,7 @@ XLOGShmemInit(void)
 		(WALInsertLockPadded *) allocptr;
 	allocptr += sizeof(WALInsertLockPadded) * NUM_XLOGINSERT_LOCKS;
 
-	XLogCtl->Insert.WALInsertLockTranche.name = "wal_insert";
-	XLogCtl->Insert.WALInsertLockTranche.array_base = WALInsertLocks;
-	XLogCtl->Insert.WALInsertLockTranche.array_stride = sizeof(WALInsertLockPadded);
-
-	LWLockRegisterTranche(LWTRANCHE_WAL_INSERT, &XLogCtl->Insert.WALInsertLockTranche);
+	LWLockRegisterTranche(LWTRANCHE_WAL_INSERT, "wal_insert");
 	for (i = 0; i < NUM_XLOGINSERT_LOCKS; i++)
 	{
 		LWLockInitialize(&WALInsertLocks[i].l.lock, LWTRANCHE_WAL_INSERT);
diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c
index c7584cb1d3492e89684bf986c163e926a86d3bae..61e6a2cd3390e8d56b94572e6103752b0b927d5e 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/postmaster/pgstat.c
@@ -3152,11 +3152,8 @@ pgstat_get_wait_event_type(uint32 wait_event_info)
 
 	switch (classId)
 	{
-		case PG_WAIT_LWLOCK_NAMED:
-			event_type = "LWLockNamed";
-			break;
-		case PG_WAIT_LWLOCK_TRANCHE:
-			event_type = "LWLockTranche";
+		case PG_WAIT_LWLOCK:
+			event_type = "LWLock";
 			break;
 		case PG_WAIT_LOCK:
 			event_type = "Lock";
@@ -3209,8 +3206,7 @@ pgstat_get_wait_event(uint32 wait_event_info)
 
 	switch (classId)
 	{
-		case PG_WAIT_LWLOCK_NAMED:
-		case PG_WAIT_LWLOCK_TRANCHE:
+		case PG_WAIT_LWLOCK:
 			event_name = GetLWLockIdentifier(classId, eventId);
 			break;
 		case PG_WAIT_LOCK:
diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c
index cc2b513236623b39570bb7eb916c4a348a29e249..0deec75dc260a334560d7711c484b751537930cf 100644
--- a/src/backend/replication/logical/origin.c
+++ b/src/backend/replication/logical/origin.c
@@ -143,7 +143,6 @@ typedef struct ReplicationStateOnDisk
 typedef struct ReplicationStateCtl
 {
 	int			tranche_id;
-	LWLockTranche tranche;
 	ReplicationState states[FLEXIBLE_ARRAY_MEMBER];
 } ReplicationStateCtl;
 
@@ -474,11 +473,6 @@ ReplicationOriginShmemInit(void)
 		int			i;
 
 		replication_states_ctl->tranche_id = LWTRANCHE_REPLICATION_ORIGIN;
-		replication_states_ctl->tranche.name = "replication_origin";
-		replication_states_ctl->tranche.array_base =
-			&replication_states[0].lock;
-		replication_states_ctl->tranche.array_stride =
-			sizeof(ReplicationState);
 
 		MemSet(replication_states, 0, ReplicationOriginShmemSize());
 
@@ -488,7 +482,7 @@ ReplicationOriginShmemInit(void)
 	}
 
 	LWLockRegisterTranche(replication_states_ctl->tranche_id,
-						  &replication_states_ctl->tranche);
+						  "replication_origin");
 }
 
 /* ---------------------------------------------------------------------------
diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c
index d8ed005e7ece28243a7db90889a4a21f60db568e..cf814d11a2311f39e437634df9f565c2300e30ba 100644
--- a/src/backend/replication/slot.c
+++ b/src/backend/replication/slot.c
@@ -98,8 +98,6 @@ ReplicationSlot *MyReplicationSlot = NULL;
 int			max_replication_slots = 0;	/* the maximum number of replication
 										 * slots */
 
-static LWLockTranche ReplSlotIOLWLockTranche;
-
 static void ReplicationSlotDropAcquired(void);
 static void ReplicationSlotDropPtr(ReplicationSlot *slot);
 
@@ -141,12 +139,8 @@ ReplicationSlotsShmemInit(void)
 		ShmemInitStruct("ReplicationSlot Ctl", ReplicationSlotsShmemSize(),
 						&found);
 
-	ReplSlotIOLWLockTranche.name = "replication_slot_io";
-	ReplSlotIOLWLockTranche.array_base =
-		((char *) ReplicationSlotCtl) + offsetof(ReplicationSlotCtlData, replication_slots) +offsetof(ReplicationSlot, io_in_progress_lock);
-	ReplSlotIOLWLockTranche.array_stride = sizeof(ReplicationSlot);
 	LWLockRegisterTranche(LWTRANCHE_REPLICATION_SLOT_IO_IN_PROGRESS,
-						  &ReplSlotIOLWLockTranche);
+						  "replication_slot_io");
 
 	if (!found)
 	{
diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c
index a4163cf717d91a85a328c58a00d29852567fb2bf..c507389a050b986a90c5469497405e94e20ebd82 100644
--- a/src/backend/storage/buffer/buf_init.c
+++ b/src/backend/storage/buffer/buf_init.c
@@ -21,8 +21,6 @@
 BufferDescPadded *BufferDescriptors;
 char	   *BufferBlocks;
 LWLockMinimallyPadded *BufferIOLWLockArray = NULL;
-LWLockTranche BufferIOLWLockTranche;
-LWLockTranche BufferContentLWLockTranche;
 WritebackContext BackendWritebackContext;
 CkptSortItem *CkptBufferIds;
 
@@ -90,18 +88,8 @@ InitBufferPool(void)
 						NBuffers * (Size) sizeof(LWLockMinimallyPadded),
 						&foundIOLocks);
 
-	BufferIOLWLockTranche.name = "buffer_io";
-	BufferIOLWLockTranche.array_base = BufferIOLWLockArray;
-	BufferIOLWLockTranche.array_stride = sizeof(LWLockMinimallyPadded);
-	LWLockRegisterTranche(LWTRANCHE_BUFFER_IO_IN_PROGRESS,
-						  &BufferIOLWLockTranche);
-
-	BufferContentLWLockTranche.name = "buffer_content";
-	BufferContentLWLockTranche.array_base =
-		((char *) BufferDescriptors) + offsetof(BufferDesc, content_lock);
-	BufferContentLWLockTranche.array_stride = sizeof(BufferDescPadded);
-	LWLockRegisterTranche(LWTRANCHE_BUFFER_CONTENT,
-						  &BufferContentLWLockTranche);
+	LWLockRegisterTranche(LWTRANCHE_BUFFER_IO_IN_PROGRESS, "buffer_io");
+	LWLockRegisterTranche(LWTRANCHE_BUFFER_CONTENT, "buffer_content");
 
 	/*
 	 * The array used to sort to-be-checkpointed buffer ids is located in
diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c
index bf38470f01d92204d93d9a9632f0df402b88461e..0f637556ccbc94c6fde256032145eb96b17bc351 100644
--- a/src/backend/storage/ipc/procarray.c
+++ b/src/backend/storage/ipc/procarray.c
@@ -106,9 +106,6 @@ static TransactionId *KnownAssignedXids;
 static bool *KnownAssignedXidsValid;
 static TransactionId latestObservedXid = InvalidTransactionId;
 
-/* LWLock tranche for backend locks */
-static LWLockTranche ProcLWLockTranche;
-
 /*
  * If we're in STANDBY_SNAPSHOT_PENDING state, standbySnapshotPendingXmin is
  * the highest xid that might still be running that we don't have in
@@ -266,11 +263,7 @@ CreateSharedProcArray(void)
 	}
 
 	/* Register and initialize fields of ProcLWLockTranche */
-	ProcLWLockTranche.name = "proc";
-	ProcLWLockTranche.array_base = (char *) (ProcGlobal->allProcs) +
-		offsetof(PGPROC, backendLock);
-	ProcLWLockTranche.array_stride = sizeof(PGPROC);
-	LWLockRegisterTranche(LWTRANCHE_PROC, &ProcLWLockTranche);
+	LWLockRegisterTranche(LWTRANCHE_PROC, "proc");
 }
 
 /*
diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c
index 03c4c7825eb37c070bcee8f8ba03f0d564254b69..4b381e4e0cc7a73ab8995d3ca77d3abbd2a0c4d0 100644
--- a/src/backend/storage/lmgr/lwlock.c
+++ b/src/backend/storage/lmgr/lwlock.c
@@ -108,18 +108,14 @@ extern slock_t *ShmemLock;
 #define LW_SHARED_MASK				((uint32) ((1 << 24)-1))
 
 /*
- * This is indexed by tranche ID and stores metadata for all tranches known
+ * This is indexed by tranche ID and stores the names of all tranches known
  * to the current backend.
  */
-static LWLockTranche **LWLockTrancheArray = NULL;
+static char **LWLockTrancheArray = NULL;
 static int	LWLockTranchesAllocated = 0;
 
 #define T_NAME(lock) \
-	(LWLockTrancheArray[(lock)->tranche]->name)
-#define T_ID(lock) \
-	((int) ((((char *) lock) - \
-		((char *) LWLockTrancheArray[(lock)->tranche]->array_base)) / \
-		LWLockTrancheArray[(lock)->tranche]->array_stride))
+	(LWLockTrancheArray[(lock)->tranche])
 
 /*
  * This points to the main array of LWLocks in shared memory.  Backends inherit
@@ -127,10 +123,6 @@ static int	LWLockTranchesAllocated = 0;
  * where we have special measures to pass it down).
  */
 LWLockPadded *MainLWLockArray = NULL;
-static LWLockTranche MainLWLockTranche;
-static LWLockTranche BufMappingLWLockTranche;
-static LWLockTranche LockManagerLWLockTranche;
-static LWLockTranche PredicateLockManagerLWLockTranche;
 
 /*
  * We use this structure to keep track of locked LWLocks for release
@@ -175,7 +167,7 @@ static inline void LWLockReportWaitEnd(void);
 typedef struct lwlock_stats_key
 {
 	int			tranche;
-	int			instance;
+	void	   *instance;
 }	lwlock_stats_key;
 
 typedef struct lwlock_stats
@@ -202,32 +194,18 @@ PRINT_LWDEBUG(const char *where, LWLock *lock, LWLockMode mode)
 	if (Trace_lwlocks)
 	{
 		uint32		state = pg_atomic_read_u32(&lock->state);
-		int			id = T_ID(lock);
-
-		if (lock->tranche == 0 && id < NUM_INDIVIDUAL_LWLOCKS)
-			ereport(LOG,
-					(errhidestmt(true),
-					 errhidecontext(true),
-					 errmsg_internal("%d: %s(%s): excl %u shared %u haswaiters %u waiters %u rOK %d",
-									 MyProcPid,
-									 where, MainLWLockNames[id],
-									 (state & LW_VAL_EXCLUSIVE) != 0,
-									 state & LW_SHARED_MASK,
-									 (state & LW_FLAG_HAS_WAITERS) != 0,
-									 pg_atomic_read_u32(&lock->nwaiters),
-									 (state & LW_FLAG_RELEASE_OK) != 0)));
-		else
-			ereport(LOG,
-					(errhidestmt(true),
-					 errhidecontext(true),
-					 errmsg_internal("%d: %s(%s %d): excl %u shared %u haswaiters %u waiters %u rOK %d",
-									 MyProcPid,
-									 where, T_NAME(lock), id,
-									 (state & LW_VAL_EXCLUSIVE) != 0,
-									 state & LW_SHARED_MASK,
-									 (state & LW_FLAG_HAS_WAITERS) != 0,
-									 pg_atomic_read_u32(&lock->nwaiters),
-									 (state & LW_FLAG_RELEASE_OK) != 0)));
+
+		ereport(LOG,
+				(errhidestmt(true),
+				 errhidecontext(true),
+				 errmsg_internal("%d: %s(%s %p): excl %u shared %u haswaiters %u waiters %u rOK %d",
+								 MyProcPid,
+								 where, T_NAME(lock), lock,
+								 (state & LW_VAL_EXCLUSIVE) != 0,
+								 state & LW_SHARED_MASK,
+								 (state & LW_FLAG_HAS_WAITERS) != 0,
+								 pg_atomic_read_u32(&lock->nwaiters),
+								 (state & LW_FLAG_RELEASE_OK) != 0)));
 	}
 }
 
@@ -237,20 +215,11 @@ LOG_LWDEBUG(const char *where, LWLock *lock, const char *msg)
 	/* hide statement & context here, otherwise the log is just too verbose */
 	if (Trace_lwlocks)
 	{
-		int			id = T_ID(lock);
-
-		if (lock->tranche == 0 && id < NUM_INDIVIDUAL_LWLOCKS)
-			ereport(LOG,
-					(errhidestmt(true),
-					 errhidecontext(true),
-					 errmsg_internal("%s(%s): %s", where,
-									 MainLWLockNames[id], msg)));
-		else
-			ereport(LOG,
-					(errhidestmt(true),
-					 errhidecontext(true),
-					 errmsg_internal("%s(%s %d): %s", where,
-									 T_NAME(lock), id, msg)));
+		ereport(LOG,
+				(errhidestmt(true),
+				 errhidecontext(true),
+				 errmsg_internal("%s(%s %p): %s", where,
+								 T_NAME(lock), lock, msg)));
 	}
 }
 
@@ -315,8 +284,8 @@ print_lwlock_stats(int code, Datum arg)
 	while ((lwstats = (lwlock_stats *) hash_seq_search(&scan)) != NULL)
 	{
 		fprintf(stderr,
-				"PID %d lwlock %s %d: shacq %u exacq %u blk %u spindelay %u dequeue self %u\n",
-				MyProcPid, LWLockTrancheArray[lwstats->key.tranche]->name,
+				"PID %d lwlock %s %p: shacq %u exacq %u blk %u spindelay %u dequeue self %u\n",
+				MyProcPid, LWLockTrancheArray[lwstats->key.tranche],
 				lwstats->key.instance, lwstats->sh_acquire_count,
 				lwstats->ex_acquire_count, lwstats->block_count,
 				lwstats->spin_delay_count, lwstats->dequeue_self_count);
@@ -342,7 +311,7 @@ get_lwlock_stats_entry(LWLock *lock)
 
 	/* Fetch or create the entry. */
 	key.tranche = lock->tranche;
-	key.instance = T_ID(lock);
+	key.instance = lock;
 	lwstats = hash_search(lwlock_stats_htab, &key, HASH_ENTER, &found);
 	if (!found)
 	{
@@ -464,7 +433,7 @@ InitializeLWLocks(void)
 
 	/* Initialize all individual LWLocks in main array */
 	for (id = 0, lock = MainLWLockArray; id < NUM_INDIVIDUAL_LWLOCKS; id++, lock++)
-		LWLockInitialize(&lock->lock, LWTRANCHE_MAIN);
+		LWLockInitialize(&lock->lock, id);
 
 	/* Initialize buffer mapping LWLocks in main array */
 	lock = MainLWLockArray + NUM_INDIVIDUAL_LWLOCKS;
@@ -506,10 +475,8 @@ InitializeLWLocks(void)
 			name = trancheNames;
 			trancheNames += strlen(request->tranche_name) + 1;
 			strcpy(name, request->tranche_name);
-			tranche->lwLockTranche.name = name;
 			tranche->trancheId = LWLockNewTrancheId();
-			tranche->lwLockTranche.array_base = lock;
-			tranche->lwLockTranche.array_stride = sizeof(LWLockPadded);
+			tranche->trancheName = name;
 
 			for (j = 0; j < request->num_lwlocks; j++, lock++)
 				LWLockInitialize(&lock->lock, tranche->trancheId);
@@ -527,39 +494,25 @@ RegisterLWLockTranches(void)
 
 	if (LWLockTrancheArray == NULL)
 	{
-		LWLockTranchesAllocated = 32;
-		LWLockTrancheArray = (LWLockTranche **)
+		LWLockTranchesAllocated = 64;
+		LWLockTrancheArray = (char **)
 			MemoryContextAllocZero(TopMemoryContext,
-						  LWLockTranchesAllocated * sizeof(LWLockTranche *));
+						  LWLockTranchesAllocated * sizeof(char *));
 		Assert(LWLockTranchesAllocated >= LWTRANCHE_FIRST_USER_DEFINED);
 	}
 
-	MainLWLockTranche.name = "main";
-	MainLWLockTranche.array_base = MainLWLockArray;
-	MainLWLockTranche.array_stride = sizeof(LWLockPadded);
-	LWLockRegisterTranche(LWTRANCHE_MAIN, &MainLWLockTranche);
+	for (i = 0; i < NUM_INDIVIDUAL_LWLOCKS; ++i)
+		LWLockRegisterTranche(i, MainLWLockNames[i]);
 
-	BufMappingLWLockTranche.name = "buffer_mapping";
-	BufMappingLWLockTranche.array_base = MainLWLockArray + NUM_INDIVIDUAL_LWLOCKS;
-	BufMappingLWLockTranche.array_stride = sizeof(LWLockPadded);
-	LWLockRegisterTranche(LWTRANCHE_BUFFER_MAPPING, &BufMappingLWLockTranche);
-
-	LockManagerLWLockTranche.name = "lock_manager";
-	LockManagerLWLockTranche.array_base = MainLWLockArray + NUM_INDIVIDUAL_LWLOCKS +
-		NUM_BUFFER_PARTITIONS;
-	LockManagerLWLockTranche.array_stride = sizeof(LWLockPadded);
-	LWLockRegisterTranche(LWTRANCHE_LOCK_MANAGER, &LockManagerLWLockTranche);
-
-	PredicateLockManagerLWLockTranche.name = "predicate_lock_manager";
-	PredicateLockManagerLWLockTranche.array_base = MainLWLockArray + NUM_INDIVIDUAL_LWLOCKS +
-		NUM_BUFFER_PARTITIONS + NUM_LOCK_PARTITIONS;
-	PredicateLockManagerLWLockTranche.array_stride = sizeof(LWLockPadded);
-	LWLockRegisterTranche(LWTRANCHE_PREDICATE_LOCK_MANAGER, &PredicateLockManagerLWLockTranche);
+	LWLockRegisterTranche(LWTRANCHE_BUFFER_MAPPING, "buffer_mapping");
+	LWLockRegisterTranche(LWTRANCHE_LOCK_MANAGER, "lock_manager");
+	LWLockRegisterTranche(LWTRANCHE_PREDICATE_LOCK_MANAGER,
+						  "predicate_lock_manager");
 
 	/* Register named tranches. */
 	for (i = 0; i < NamedLWLockTrancheRequests; i++)
 		LWLockRegisterTranche(NamedLWLockTrancheArray[i].trancheId,
-							  &NamedLWLockTrancheArray[i].lwLockTranche);
+							  NamedLWLockTrancheArray[i].trancheName);
 }
 
 /*
@@ -633,7 +586,7 @@ LWLockNewTrancheId(void)
  * (TopMemoryContext, static variable, or similar).
  */
 void
-LWLockRegisterTranche(int tranche_id, LWLockTranche *tranche)
+LWLockRegisterTranche(int tranche_id, char *tranche_name)
 {
 	Assert(LWLockTrancheArray != NULL);
 
@@ -645,15 +598,14 @@ LWLockRegisterTranche(int tranche_id, LWLockTranche *tranche)
 		while (i <= tranche_id)
 			i *= 2;
 
-		LWLockTrancheArray = (LWLockTranche **)
-			repalloc(LWLockTrancheArray,
-					 i * sizeof(LWLockTranche *));
+		LWLockTrancheArray = (char **)
+			repalloc(LWLockTrancheArray, i * sizeof(char *));
 		LWLockTranchesAllocated = i;
 		while (j < LWLockTranchesAllocated)
 			LWLockTrancheArray[j++] = NULL;
 	}
 
-	LWLockTrancheArray[tranche_id] = tranche;
+	LWLockTrancheArray[tranche_id] = tranche_name;
 }
 
 /*
@@ -729,12 +681,7 @@ LWLockInitialize(LWLock *lock, int tranche_id)
 static inline void
 LWLockReportWaitStart(LWLock *lock)
 {
-	int			lockId = T_ID(lock);
-
-	if (lock->tranche == 0)
-		pgstat_report_wait_start(PG_WAIT_LWLOCK_NAMED | (uint16) lockId);
-	else
-		pgstat_report_wait_start(PG_WAIT_LWLOCK_TRANCHE | lock->tranche);
+	pgstat_report_wait_start(PG_WAIT_LWLOCK | lock->tranche);
 }
 
 /*
@@ -752,10 +699,7 @@ LWLockReportWaitEnd(void)
 const char *
 GetLWLockIdentifier(uint32 classId, uint16 eventId)
 {
-	if (classId == PG_WAIT_LWLOCK_NAMED)
-		return MainLWLockNames[eventId];
-
-	Assert(classId == PG_WAIT_LWLOCK_TRANCHE);
+	Assert(classId == PG_WAIT_LWLOCK);
 
 	/*
 	 * It is quite possible that user has registered tranche in one of the
@@ -763,10 +707,10 @@ GetLWLockIdentifier(uint32 classId, uint16 eventId)
 	 * all of them, so we can't assume the tranche is registered here.
 	 */
 	if (eventId >= LWLockTranchesAllocated ||
-		LWLockTrancheArray[eventId]->name == NULL)
+		LWLockTrancheArray[eventId] == NULL)
 		return "extension";
 
-	return LWLockTrancheArray[eventId]->name;
+	return LWLockTrancheArray[eventId];
 }
 
 /*
@@ -1279,7 +1223,7 @@ LWLockAcquire(LWLock *lock, LWLockMode mode)
 #endif
 
 		LWLockReportWaitStart(lock);
-		TRACE_POSTGRESQL_LWLOCK_WAIT_START(T_NAME(lock), T_ID(lock), mode);
+		TRACE_POSTGRESQL_LWLOCK_WAIT_START(T_NAME(lock), mode);
 
 		for (;;)
 		{
@@ -1301,7 +1245,7 @@ LWLockAcquire(LWLock *lock, LWLockMode mode)
 		}
 #endif
 
-		TRACE_POSTGRESQL_LWLOCK_WAIT_DONE(T_NAME(lock), T_ID(lock), mode);
+		TRACE_POSTGRESQL_LWLOCK_WAIT_DONE(T_NAME(lock), mode);
 		LWLockReportWaitEnd();
 
 		LOG_LWDEBUG("LWLockAcquire", lock, "awakened");
@@ -1310,7 +1254,7 @@ LWLockAcquire(LWLock *lock, LWLockMode mode)
 		result = false;
 	}
 
-	TRACE_POSTGRESQL_LWLOCK_ACQUIRE(T_NAME(lock), T_ID(lock), mode);
+	TRACE_POSTGRESQL_LWLOCK_ACQUIRE(T_NAME(lock), mode);
 
 	/* Add lock to list of locks held by this backend */
 	held_lwlocks[num_held_lwlocks].lock = lock;
@@ -1361,14 +1305,14 @@ LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
 		RESUME_INTERRUPTS();
 
 		LOG_LWDEBUG("LWLockConditionalAcquire", lock, "failed");
-		TRACE_POSTGRESQL_LWLOCK_CONDACQUIRE_FAIL(T_NAME(lock), T_ID(lock), mode);
+		TRACE_POSTGRESQL_LWLOCK_CONDACQUIRE_FAIL(T_NAME(lock), mode);
 	}
 	else
 	{
 		/* Add lock to list of locks held by this backend */
 		held_lwlocks[num_held_lwlocks].lock = lock;
 		held_lwlocks[num_held_lwlocks++].mode = mode;
-		TRACE_POSTGRESQL_LWLOCK_CONDACQUIRE(T_NAME(lock), T_ID(lock), mode);
+		TRACE_POSTGRESQL_LWLOCK_CONDACQUIRE(T_NAME(lock), mode);
 	}
 	return !mustwait;
 }
@@ -1440,7 +1384,7 @@ LWLockAcquireOrWait(LWLock *lock, LWLockMode mode)
 #endif
 
 			LWLockReportWaitStart(lock);
-			TRACE_POSTGRESQL_LWLOCK_WAIT_START(T_NAME(lock), T_ID(lock), mode);
+			TRACE_POSTGRESQL_LWLOCK_WAIT_START(T_NAME(lock), mode);
 
 			for (;;)
 			{
@@ -1458,7 +1402,7 @@ LWLockAcquireOrWait(LWLock *lock, LWLockMode mode)
 				Assert(nwaiters < MAX_BACKENDS);
 			}
 #endif
-			TRACE_POSTGRESQL_LWLOCK_WAIT_DONE(T_NAME(lock), T_ID(lock), mode);
+			TRACE_POSTGRESQL_LWLOCK_WAIT_DONE(T_NAME(lock), mode);
 			LWLockReportWaitEnd();
 
 			LOG_LWDEBUG("LWLockAcquireOrWait", lock, "awakened");
@@ -1488,8 +1432,7 @@ LWLockAcquireOrWait(LWLock *lock, LWLockMode mode)
 		/* Failed to get lock, so release interrupt holdoff */
 		RESUME_INTERRUPTS();
 		LOG_LWDEBUG("LWLockAcquireOrWait", lock, "failed");
-		TRACE_POSTGRESQL_LWLOCK_ACQUIRE_OR_WAIT_FAIL(T_NAME(lock), T_ID(lock),
-													 mode);
+		TRACE_POSTGRESQL_LWLOCK_ACQUIRE_OR_WAIT_FAIL(T_NAME(lock), mode);
 	}
 	else
 	{
@@ -1497,7 +1440,7 @@ LWLockAcquireOrWait(LWLock *lock, LWLockMode mode)
 		/* Add lock to list of locks held by this backend */
 		held_lwlocks[num_held_lwlocks].lock = lock;
 		held_lwlocks[num_held_lwlocks++].mode = mode;
-		TRACE_POSTGRESQL_LWLOCK_ACQUIRE_OR_WAIT(T_NAME(lock), T_ID(lock), mode);
+		TRACE_POSTGRESQL_LWLOCK_ACQUIRE_OR_WAIT(T_NAME(lock), mode);
 	}
 
 	return !mustwait;
@@ -1657,8 +1600,7 @@ LWLockWaitForVar(LWLock *lock, uint64 *valptr, uint64 oldval, uint64 *newval)
 #endif
 
 		LWLockReportWaitStart(lock);
-		TRACE_POSTGRESQL_LWLOCK_WAIT_START(T_NAME(lock), T_ID(lock),
-										   LW_EXCLUSIVE);
+		TRACE_POSTGRESQL_LWLOCK_WAIT_START(T_NAME(lock), LW_EXCLUSIVE);
 
 		for (;;)
 		{
@@ -1677,8 +1619,7 @@ LWLockWaitForVar(LWLock *lock, uint64 *valptr, uint64 oldval, uint64 *newval)
 		}
 #endif
 
-		TRACE_POSTGRESQL_LWLOCK_WAIT_DONE(T_NAME(lock), T_ID(lock),
-										  LW_EXCLUSIVE);
+		TRACE_POSTGRESQL_LWLOCK_WAIT_DONE(T_NAME(lock), LW_EXCLUSIVE);
 		LWLockReportWaitEnd();
 
 		LOG_LWDEBUG("LWLockWaitForVar", lock, "awakened");
@@ -1686,7 +1627,7 @@ LWLockWaitForVar(LWLock *lock, uint64 *valptr, uint64 oldval, uint64 *newval)
 		/* Now loop back and check the status of the lock again. */
 	}
 
-	TRACE_POSTGRESQL_LWLOCK_ACQUIRE(T_NAME(lock), T_ID(lock), LW_EXCLUSIVE);
+	TRACE_POSTGRESQL_LWLOCK_ACQUIRE(T_NAME(lock), LW_EXCLUSIVE);
 
 	/*
 	 * Fix the process wait semaphore's count for any absorbed wakeups.
@@ -1784,7 +1725,7 @@ LWLockRelease(LWLock *lock)
 			break;
 
 	if (i < 0)
-		elog(ERROR, "lock %s %d is not held", T_NAME(lock), T_ID(lock));
+		elog(ERROR, "lock %s is not held", T_NAME(lock));
 
 	mode = held_lwlocks[i].mode;
 
@@ -1829,7 +1770,7 @@ LWLockRelease(LWLock *lock)
 		LWLockWakeup(lock);
 	}
 
-	TRACE_POSTGRESQL_LWLOCK_RELEASE(T_NAME(lock), T_ID(lock));
+	TRACE_POSTGRESQL_LWLOCK_RELEASE(T_NAME(lock));
 
 	/*
 	 * Now okay to allow cancel/die interrupts.
diff --git a/src/backend/utils/mmgr/dsa.c b/src/backend/utils/mmgr/dsa.c
index abe3f1a63d19729c3b15bd0dadc41e365080e1b1..988a2970b2d77121269c8ec7ddb3f5e91062ee76 100644
--- a/src/backend/utils/mmgr/dsa.c
+++ b/src/backend/utils/mmgr/dsa.c
@@ -362,9 +362,6 @@ struct dsa_area
 	/* Pointer to the control object in shared memory. */
 	dsa_area_control *control;
 
-	/* The lock tranche for this process. */
-	LWLockTranche lwlock_tranche;
-
 	/* Has the mapping been pinned? */
 	bool		mapping_pinned;
 
@@ -1207,10 +1204,8 @@ create_internal(void *place, size_t size,
 	area->mapping_pinned = false;
 	memset(area->segment_maps, 0, sizeof(dsa_segment_map) * DSA_MAX_SEGMENTS);
 	area->high_segment_index = 0;
-	area->lwlock_tranche.array_base = &area->control->pools[0];
-	area->lwlock_tranche.array_stride = sizeof(dsa_area_pool);
-	area->lwlock_tranche.name = control->lwlock_tranche_name;
-	LWLockRegisterTranche(control->lwlock_tranche_id, &area->lwlock_tranche);
+	LWLockRegisterTranche(control->lwlock_tranche_id,
+						  control->lwlock_tranche_name);
 	LWLockInitialize(&control->lock, control->lwlock_tranche_id);
 	for (i = 0; i < DSA_NUM_SIZE_CLASSES; ++i)
 		LWLockInitialize(DSA_SCLASS_LOCK(area, i),
@@ -1267,10 +1262,8 @@ attach_internal(void *place, dsm_segment *segment, dsa_handle handle)
 	memset(&area->segment_maps[0], 0,
 		   sizeof(dsa_segment_map) * DSA_MAX_SEGMENTS);
 	area->high_segment_index = 0;
-	area->lwlock_tranche.array_base = &area->control->pools[0];
-	area->lwlock_tranche.array_stride = sizeof(dsa_area_pool);
-	area->lwlock_tranche.name = control->lwlock_tranche_name;
-	LWLockRegisterTranche(control->lwlock_tranche_id, &area->lwlock_tranche);
+	LWLockRegisterTranche(control->lwlock_tranche_id,
+						  control->lwlock_tranche_name);
 
 	/* Set up the segment map for this process's mapping. */
 	segment_map = &area->segment_maps[0];
diff --git a/src/backend/utils/probes.d b/src/backend/utils/probes.d
index 2f92dfa9adb00e921bee1d4b32022b52bb36f8d5..adcebe2e055b24e4a5f4374c66496fae6861c560 100644
--- a/src/backend/utils/probes.d
+++ b/src/backend/utils/probes.d
@@ -28,14 +28,14 @@ provider postgresql {
 	probe transaction__commit(LocalTransactionId);
 	probe transaction__abort(LocalTransactionId);
 
-	probe lwlock__acquire(const char *, int, LWLockMode);
-	probe lwlock__release(const char *, int);
-	probe lwlock__wait__start(const char *, int, LWLockMode);
-	probe lwlock__wait__done(const char *, int, LWLockMode);
-	probe lwlock__condacquire(const char *, int, LWLockMode);
-	probe lwlock__condacquire__fail(const char *, int, LWLockMode);
-	probe lwlock__acquire__or__wait(const char *, int, LWLockMode);
-	probe lwlock__acquire__or__wait__fail(const char *, int, LWLockMode);
+	probe lwlock__acquire(const char *, LWLockMode);
+	probe lwlock__release(const char *);
+	probe lwlock__wait__start(const char *, LWLockMode);
+	probe lwlock__wait__done(const char *, LWLockMode);
+	probe lwlock__condacquire(const char *, LWLockMode);
+	probe lwlock__condacquire__fail(const char *, LWLockMode);
+	probe lwlock__acquire__or__wait(const char *, LWLockMode);
+	probe lwlock__acquire__or__wait__fail(const char *, LWLockMode);
 
 	probe lock__wait__start(unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, LOCKMODE);
 	probe lock__wait__done(unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, LOCKMODE);
diff --git a/src/include/access/slru.h b/src/include/access/slru.h
index 5fcebc52fba4a38e694798608cc3f4ccc4964235..ca8ab7ba5248d5aebaf32688f1ea1d144de2adcc 100644
--- a/src/include/access/slru.h
+++ b/src/include/access/slru.h
@@ -104,7 +104,6 @@ typedef struct SlruSharedData
 
 	/* LWLocks */
 	int			lwlock_tranche_id;
-	LWLockTranche lwlock_tranche;
 	char		lwlock_tranche_name[SLRU_MAX_NAME_LENGTH];
 	LWLockPadded *buffer_locks;
 } SlruSharedData;
diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index 152ff0620852133323edda179e17539893fbe539..282f8aeccd2ebaea771d813fbc0401903c891a78 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -715,8 +715,7 @@ typedef enum BackendState
  * Wait Classes
  * ----------
  */
-#define PG_WAIT_LWLOCK_NAMED		0x01000000U
-#define PG_WAIT_LWLOCK_TRANCHE		0x02000000U
+#define PG_WAIT_LWLOCK				0x01000000U
 #define PG_WAIT_LOCK				0x03000000U
 #define PG_WAIT_BUFFER_PIN			0x04000000U
 #define PG_WAIT_ACTIVITY			0x05000000U
diff --git a/src/include/storage/lwlock.h b/src/include/storage/lwlock.h
index 9a2d86975cad72971c07764bd786fc893a11b07a..db1c687e21e8398bb201666b833c5eb6991d82e5 100644
--- a/src/include/storage/lwlock.h
+++ b/src/include/storage/lwlock.h
@@ -24,32 +24,6 @@
 
 struct PGPROC;
 
-/*
- * Prior to PostgreSQL 9.4, every lightweight lock in the system was stored
- * in a single array.  For convenience and for compatibility with past
- * releases, we still have a main array, but it's now also permissible to
- * store LWLocks elsewhere in the main shared memory segment or in a dynamic
- * shared memory segment.  Each array of lwlocks forms a separate "tranche".
- *
- * It's occasionally necessary to identify a particular LWLock "by name"; e.g.
- * because we wish to report the lock to dtrace.  We could store a name or
- * other identifying information in the lock itself, but since it's common
- * to have many nearly-identical locks (e.g. one per buffer) this would end
- * up wasting significant amounts of memory.  Instead, each lwlock stores a
- * tranche ID which tells us which array it's part of.  Based on that, we can
- * figure out where the lwlock lies within the array using the data structure
- * shown below; the lock is then identified based on the tranche name and
- * computed array index.  We need the array stride because the array might not
- * be an array of lwlocks, but rather some larger data structure that includes
- * one or more lwlocks per element.
- */
-typedef struct LWLockTranche
-{
-	const char *name;
-	void	   *array_base;
-	Size		array_stride;
-} LWLockTranche;
-
 /*
  * Code outside of lwlock.c should not manipulate the contents of this
  * structure directly, but we have to declare it here to allow LWLocks to be
@@ -118,8 +92,8 @@ extern char *MainLWLockNames[];
 /* struct for storing named tranche information */
 typedef struct NamedLWLockTranche
 {
-	LWLockTranche lwLockTranche;
 	int			trancheId;
+	char	   *trancheName;
 } NamedLWLockTranche;
 
 extern PGDLLIMPORT NamedLWLockTranche *NamedLWLockTrancheArray;
@@ -199,9 +173,9 @@ extern LWLockPadded *GetNamedLWLockTranche(const char *tranche_name);
  * There is another, more flexible method of obtaining lwlocks. First, call
  * LWLockNewTrancheId just once to obtain a tranche ID; this allocates from
  * a shared counter.  Next, each individual process using the tranche should
- * call LWLockRegisterTranche() to associate that tranche ID with appropriate
- * metadata.  Finally, LWLockInitialize should be called just once per lwlock,
- * passing the tranche ID as an argument.
+ * call LWLockRegisterTranche() to associate that tranche ID with a name.
+ * Finally, LWLockInitialize should be called just once per lwlock, passing
+ * the tranche ID as an argument.
  *
  * It may seem strange that each process using the tranche must register it
  * separately, but dynamic shared memory segments aren't guaranteed to be
@@ -209,17 +183,18 @@ extern LWLockPadded *GetNamedLWLockTranche(const char *tranche_name);
  * registration in the main shared memory segment wouldn't work for that case.
  */
 extern int	LWLockNewTrancheId(void);
-extern void LWLockRegisterTranche(int tranche_id, LWLockTranche *tranche);
+extern void LWLockRegisterTranche(int tranche_id, char *tranche_name);
 extern void LWLockInitialize(LWLock *lock, int tranche_id);
 
 /*
- * We reserve a few predefined tranche IDs.  A call to LWLockNewTrancheId
- * will never return a value less than LWTRANCHE_FIRST_USER_DEFINED.
+ * Every tranche ID less than NUM_INDIVIDUAL_LWLOCKS is reserved; also,
+ * we reserve additional tranche IDs for builtin tranches not included in
+ * the set of individual LWLocks.  A call to LWLockNewTrancheId will never
+ * return a value less than LWTRANCHE_FIRST_USER_DEFINED.
  */
 typedef enum BuiltinTrancheIds
 {
-	LWTRANCHE_MAIN,
-	LWTRANCHE_CLOG_BUFFERS,
+	LWTRANCHE_CLOG_BUFFERS = NUM_INDIVIDUAL_LWLOCKS,
 	LWTRANCHE_COMMITTS_BUFFERS,
 	LWTRANCHE_SUBTRANS_BUFFERS,
 	LWTRANCHE_MXACTOFFSET_BUFFERS,