Add the ability to limit the amount of memory that can be allocated to backends.

Started by Reid Thompsonover 3 years ago83 messages
#1Reid Thompson
reid.thompson@crunchydata.com
2 attachment(s)

Hi Hackers,

Add the ability to limit the amount of memory that can be allocated to
backends.

This builds on the work that adds backend memory allocated to
pg_stat_activity
/messages/by-id/67bb5c15c0489cb499723b0340f16e10c22485ec.camel@crunchydata.com
Both patches are attached.

Add GUC variable max_total_backend_memory.

Specifies a limit to the amount of memory (MB) that may be allocated to
backends in total (i.e. this is not a per user or per backend limit).
If unset, or set to 0 it is disabled. It is intended as a resource to
help avoid the OOM killer. A backend request that would push the total
over the limit will be denied with an out of memory error causing that
backends current query/transaction to fail. Due to the dynamic nature
of memory allocations, this limit is not exact. If within 1.5MB of the
limit and two backends request 1MB each at the same time both may be
allocated exceeding the limit. Further requests will not be allocated
until dropping below the limit. Keep this in mind when setting this
value to avoid the OOM killer. Currently, this limit does not affect
auxiliary backend processes, this list of non-affected backend
processes is open for discussion as to what should/should not be
included. Backend memory allocations are displayed in the
pg_stat_activity view.

--
Reid Thompson
Senior Software Engineer
Crunchy Data, Inc.

reid.thompson@crunchydata.com
www.crunchydata.com

Attachments:

001-dev-max-memory.patchtext/x-patch; charset=UTF-8; name=001-dev-max-memory.patchDownload
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index a5cd4e44c7..caf958310a 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -2079,6 +2079,32 @@ include_dir 'conf.d'
       </listitem>
      </varlistentry>
 
+     <varlistentry id="guc-max-total-backend-memory" xreflabel="max_total_backend_memory">
+      <term><varname>max_total_backend_memory</varname> (<type>integer</type>)
+      <indexterm>
+       <primary><varname>max_total_backend_memory</varname> configuration parameter</primary>
+      </indexterm>
+      </term>
+      <listitem>
+       <para>
+        Specifies a limit to the amount of memory (MB) that may be allocated to
+        backends in total (i.e. this is not a per user or per backend limit).
+        If unset, or set to 0 it is disabled.  A backend request that would push
+        the total over the limit will be denied with an out of memory error
+        causing that backends current query/transaction to fail. Due to the dynamic
+        nature of memory allocations, this limit is not exact. If within 1.5MB of
+        the limit and two backends request 1MB each at the same time both may be
+        allocated exceeding the limit. Further requests will not be allocated until
+        dropping below the limit. Keep this in mind when setting this value. This
+        limit does not affect auxiliary backend processes
+        <xref linkend="glossary-auxiliary-proc"/> . Backend memory allocations
+        (<varname>backend_mem_allocated</varname>) are displayed in the
+        <link linkend="monitoring-pg-stat-activity-view"><structname>pg_stat_activity</structname></link>
+        view.
+       </para>
+      </listitem>
+     </varlistentry>
+
      </variablelist>
      </sect2>
 
diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c
index 269ad2fe53..808ffe75f2 100644
--- a/src/backend/storage/ipc/dsm_impl.c
+++ b/src/backend/storage/ipc/dsm_impl.c
@@ -253,6 +253,10 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 		return true;
 	}
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+		return false;
+
 	/*
 	 * Create new segment or open an existing one for attach.
 	 *
@@ -524,6 +528,10 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 		int			flags = IPCProtection;
 		size_t		segsize;
 
+		/* Do not exceed maximum allowed memory allocation */
+		if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+			return false;
+
 		/*
 		 * Allocate the memory BEFORE acquiring the resource, so that we don't
 		 * leak the resource if memory allocation fails.
@@ -718,6 +726,10 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 		return true;
 	}
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+		return false;
+
 	/* Create new segment or open an existing one for attach. */
 	if (op == DSM_OP_CREATE)
 	{
diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c
index 17a00587f8..9137a000ae 100644
--- a/src/backend/utils/activity/backend_status.c
+++ b/src/backend/utils/activity/backend_status.c
@@ -44,6 +44,8 @@
  */
 bool		pgstat_track_activities = false;
 int			pgstat_track_activity_query_size = 1024;
+/* Max backend memory allocation allowed (MB). 0 = disabled */
+int			max_total_bkend_mem = 0;
 
 
 /* exposed so that backend_progress.c can access it */
@@ -1253,3 +1255,107 @@ pgstat_report_backend_mem_allocated_decrease(uint64 deallocation)
 	beentry->backend_mem_allocated -= deallocation;
 	PGSTAT_END_WRITE_ACTIVITY(beentry);
 }
+
+/* ----------
+ * pgstat_get_all_backend_memory_allocated() -
+ *
+ *	Return a uint64 representing the current shared memory allocated to all
+ *	backends.  This looks directly at the BackendStatusArray, and so will
+ *	provide current information regardless of the age of our transaction's
+ *	snapshot of the status array.
+ *	In the future we will likely utilize additional values - perhaps limit
+ *	backend allocation by user/role, etc.
+ * ----------
+ */
+uint64
+pgstat_get_all_backend_memory_allocated(void)
+{
+	PgBackendStatus *beentry;
+	int			i;
+	uint64		all_backend_memory_allocated = 0;
+
+	beentry = BackendStatusArray;
+
+	/*
+	 * We probably shouldn't get here before shared memory has been set up,
+	 * but be safe.
+	 */
+	if (beentry == NULL || BackendActivityBuffer == NULL)
+		return 0;
+
+	/*
+	 * We include AUX procs in all backend memory calculation
+	 */
+	for (i = 1; i <= NumBackendStatSlots; i++)
+	{
+		/*
+		 * We use a volatile pointer here to ensure the compiler doesn't try to
+		 * get cute.
+		 */
+		volatile PgBackendStatus *vbeentry = beentry;
+		bool		found;
+		uint64		backend_mem_allocated = 0;
+
+		for (;;)
+		{
+			int			before_changecount;
+			int			after_changecount;
+
+			pgstat_begin_read_activity(vbeentry, before_changecount);
+
+			/* Ignore invalid entries, which may contain invalid data.
+			 * See pgstat_beshutdown_hook()
+			 */
+			if (vbeentry->st_procpid > 0)
+				backend_mem_allocated = vbeentry->backend_mem_allocated;
+
+			pgstat_end_read_activity(vbeentry, after_changecount);
+
+			if ((found = pgstat_read_activity_complete(before_changecount,
+													   after_changecount)))
+				break;
+
+			/* Make sure we can break out of loop if stuck... */
+			CHECK_FOR_INTERRUPTS();
+		}
+
+		if (found)
+			all_backend_memory_allocated += backend_mem_allocated;
+
+		beentry++;
+	}
+
+	return all_backend_memory_allocated;
+}
+
+/*
+ * Determine if allocation request will exceed max backend memory allowed.
+ * Do not apply to auxiliary processes.
+ */
+bool
+exceeds_max_total_bkend_mem(uint64 allocation_request)
+{
+	bool result = false;
+
+	if (MyAuxProcType != NotAnAuxProcess)
+		return result;
+
+	/* Convert max_total_bkend_mem to bytes for comparison */
+	if (max_total_bkend_mem &&
+		pgstat_get_all_backend_memory_allocated() +
+		allocation_request > (uint64)max_total_bkend_mem * 1024 * 1024)
+	{
+		/*
+		 * Explicitely identify the OOM being a result of this
+		 * configuration parameter vs a system failure to allocate OOM.
+		 */
+		elog(WARNING,
+			 "request will exceed postgresql.conf defined max_total_backend_memory limit (%lu > %lu)",
+			 pgstat_get_all_backend_memory_allocated() +
+			 allocation_request, (uint64)max_total_bkend_mem * 1024 * 1024);
+
+		result = true;
+	}
+
+	return result;
+}
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 9fbbfb1be5..ab8d83c235 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -3664,6 +3664,17 @@ static struct config_int ConfigureNamesInt[] =
 		NULL, NULL, NULL
 	},
 
+	{
+		{"max_total_backend_memory", PGC_SIGHUP, RESOURCES_MEM,
+			gettext_noop("Restrict total backend memory allocations to this max."),
+			gettext_noop("0 turns this feature off."),
+			GUC_UNIT_MB
+		},
+		&max_total_bkend_mem,
+		0, 0, INT_MAX,
+		NULL, NULL, NULL
+	},
+
 	/* End-of-list marker */
 	{
 		{NULL, 0, 0, NULL, NULL}, NULL, 0, 0, 0, NULL, NULL, NULL
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 90bec0502c..8e944f6511 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -155,6 +155,9 @@
 					#   mmap
 					# (change requires restart)
 #min_dynamic_shared_memory = 0MB	# (change requires restart)
+#max_total_backend_memory = 0MB		# Restrict total backend memory allocations
+									# to this max (in MB). 0 turns this feature
+									# off.
 
 # - Disk -
 
diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index c91f8efa4d..ac9a1ced3f 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -428,6 +428,10 @@ AllocSetContextCreateInternal(MemoryContext parent,
 	else
 		firstBlockSize = Max(firstBlockSize, initBlockSize);
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (exceeds_max_total_bkend_mem(firstBlockSize))
+		return NULL;
+
 	/*
 	 * Allocate the initial block.  Unlike other aset.c blocks, it starts with
 	 * the context header and its block header follows that.
@@ -720,6 +724,11 @@ AllocSetAlloc(MemoryContext context, Size size)
 	{
 		chunk_size = MAXALIGN(size);
 		blksize = chunk_size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
+
+		/* Do not exceed maximum allowed memory allocation */
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		block = (AllocBlock) malloc(blksize);
 		if (block == NULL)
 			return NULL;
@@ -911,6 +920,10 @@ AllocSetAlloc(MemoryContext context, Size size)
 		while (blksize < required_size)
 			blksize <<= 1;
 
+		/* Do not exceed maximum allowed memory allocation */
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		/* Try to allocate it */
 		block = (AllocBlock) malloc(blksize);
 
@@ -1133,6 +1146,10 @@ AllocSetRealloc(void *pointer, Size size)
 		blksize = chksize + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
 		oldblksize = block->endptr - ((char *) block);
 
+		/* Do not exceed maximum allowed memory allocation */
+		if (blksize > oldblksize && exceeds_max_total_bkend_mem(blksize - oldblksize))
+			return NULL;
+
 		block = (AllocBlock) realloc(block, blksize);
 		if (block == NULL)
 		{
diff --git a/src/backend/utils/mmgr/generation.c b/src/backend/utils/mmgr/generation.c
index 36e5b3f94d..1d5720836c 100644
--- a/src/backend/utils/mmgr/generation.c
+++ b/src/backend/utils/mmgr/generation.c
@@ -192,6 +192,9 @@ GenerationContextCreate(MemoryContext parent,
 	else
 		allocSize = Max(allocSize, initBlockSize);
 
+	if (exceeds_max_total_bkend_mem(allocSize))
+		return NULL;
+
 	/*
 	 * Allocate the initial block.  Unlike other generation.c blocks, it
 	 * starts with the context header and its block header follows that.
@@ -361,6 +364,9 @@ GenerationAlloc(MemoryContext context, Size size)
 	{
 		Size		blksize = required_size + Generation_BLOCKHDRSZ;
 
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		block = (GenerationBlock *) malloc(blksize);
 		if (block == NULL)
 			return NULL;
@@ -464,6 +470,9 @@ GenerationAlloc(MemoryContext context, Size size)
 			if (blksize < required_size)
 				blksize = pg_nextpower2_size_t(required_size);
 
+			if (exceeds_max_total_bkend_mem(blksize))
+				return NULL;
+
 			block = (GenerationBlock *) malloc(blksize);
 
 			if (block == NULL)
diff --git a/src/backend/utils/mmgr/slab.c b/src/backend/utils/mmgr/slab.c
index efc8bcfaa7..5cf0cfff86 100644
--- a/src/backend/utils/mmgr/slab.c
+++ b/src/backend/utils/mmgr/slab.c
@@ -177,6 +177,10 @@ SlabContextCreate(MemoryContext parent,
 	headerSize += chunksPerBlock * sizeof(bool);
 #endif
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (exceeds_max_total_bkend_mem(headerSize))
+		return NULL;
+
 	slab = (SlabContext *) malloc(headerSize);
 	if (slab == NULL)
 	{
@@ -331,6 +335,10 @@ SlabAlloc(MemoryContext context, Size size)
 	 */
 	if (slab->minFreeChunks == 0)
 	{
+		/* Do not exceed maximum allowed memory allocation */
+		if (exceeds_max_total_bkend_mem(slab->blockSize))
+			return NULL;
+
 		block = (SlabBlock *) malloc(slab->blockSize);
 
 		if (block == NULL)
diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h
index 9bdc4197bd..3b940ff98e 100644
--- a/src/include/utils/backend_status.h
+++ b/src/include/utils/backend_status.h
@@ -270,6 +270,7 @@ typedef struct LocalPgBackendStatus
  */
 extern PGDLLIMPORT bool pgstat_track_activities;
 extern PGDLLIMPORT int pgstat_track_activity_query_size;
+extern PGDLLIMPORT int max_total_bkend_mem;
 
 
 /* ----------
@@ -321,6 +322,7 @@ extern int	pgstat_fetch_stat_numbackends(void);
 extern PgBackendStatus *pgstat_fetch_stat_beentry(int beid);
 extern LocalPgBackendStatus *pgstat_fetch_stat_local_beentry(int beid);
 extern char *pgstat_clip_activity(const char *raw_activity);
+extern bool exceeds_max_total_bkend_mem(uint64 allocation_request);
 
 
 #endif							/* BACKEND_STATUS_H */
001-pg-stat-activity-backend-memory-allocated.patchtext/x-patch; charset=UTF-8; name=001-pg-stat-activity-backend-memory-allocated.patchDownload
diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 1d9509a2f6..40ae638f25 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -947,6 +947,18 @@ postgres   27093  0.0  0.0  30096  2752 ?        Ss   11:34   0:00 postgres: ser
      </para></entry>
     </row>
 
+    <row>
+     <entry role="catalog_table_entry"><para role="column_definition">
+      <structfield>backend_mem_allocated</structfield> <type>bigint</type>
+     </para>
+     <para>
+      The byte count of memory allocated to this backend. Dynamic shared memory
+      allocations are included only in the value displayed for the backend that
+      created them, they are not included in the value for backends that are
+      attached to them to avoid double counting.
+     </para></entry>
+    </row>
+
      <row>
       <entry role="catalog_table_entry"><para role="column_definition">
        <structfield>query</structfield> <type>text</type>
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 5a844b63a1..d23f0e9dbb 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -863,6 +863,7 @@ CREATE VIEW pg_stat_activity AS
             S.backend_xid,
             s.backend_xmin,
             S.query_id,
+            S.backend_mem_allocated,
             S.query,
             S.backend_type
     FROM pg_stat_get_activity(NULL) AS S
diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c
index e1b90c5de4..269ad2fe53 100644
--- a/src/backend/storage/ipc/dsm_impl.c
+++ b/src/backend/storage/ipc/dsm_impl.c
@@ -66,6 +66,7 @@
 #include "postmaster/postmaster.h"
 #include "storage/dsm_impl.h"
 #include "storage/fd.h"
+#include "utils/backend_status.h"
 #include "utils/guc.h"
 #include "utils/memutils.h"
 
@@ -232,6 +233,13 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pgstat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_backend_mem_allocated_decrease(*mapped_size);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && shm_unlink(name) != 0)
@@ -332,6 +340,36 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pgstat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+	{
+		/*
+		 * Posix creation calls dsm_impl_posix_resize implying that resizing
+		 * occurs or may be added in the future. As implemented
+		 * dsm_impl_posix_resize utilizes fallocate or truncate, passing the
+		 * whole new size as input, growing the allocation as needed * (only
+		 * truncate supports shrinking). We update by replacing the * old
+		 * allocation with the new.
+		 */
+#if defined(HAVE_POSIX_FALLOCATE) && defined(__linux__)
+		/*
+		 * posix_fallocate does not shrink allocations, adjust only on
+		 * allocation increase.
+		 */
+		if (request_size > *mapped_size)
+		{
+			pgstat_report_backend_mem_allocated_decrease(*mapped_size);
+			pgstat_report_backend_mem_allocated_increase(request_size);
+		}
+#else
+		pgstat_report_backend_mem_allocated_decrease(*mapped_size);
+		pgstat_report_backend_mem_allocated_increase(request_size);
+#endif
+	}
 	*mapped_address = address;
 	*mapped_size = request_size;
 	close(fd);
@@ -537,6 +575,14 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pgstat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_backend_mem_allocated_decrease(*mapped_size);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && shmctl(ident, IPC_RMID, NULL) < 0)
@@ -584,6 +630,13 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pgstat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_backend_mem_allocated_increase(request_size);
 	*mapped_address = address;
 	*mapped_size = request_size;
 
@@ -652,6 +705,13 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 			return false;
 		}
 
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pgstat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_backend_mem_allocated_decrease(*mapped_size);
 		*impl_private = NULL;
 		*mapped_address = NULL;
 		*mapped_size = 0;
@@ -768,6 +828,12 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 		return false;
 	}
 
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pgstat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_backend_mem_allocated_increase(info.RegionSize);
 	*mapped_address = address;
 	*mapped_size = info.RegionSize;
 	*impl_private = hmap;
@@ -812,6 +878,13 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pgstat_activity when the creator destroys the
+		 * allocation.
+		 */
+		pgstat_report_backend_mem_allocated_decrease(*mapped_size);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && unlink(name) != 0)
@@ -933,6 +1006,13 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pgstat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_backend_mem_allocated_increase(request_size);
 	*mapped_address = address;
 	*mapped_size = request_size;
 
diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c
index c7ed1e6d7a..17a00587f8 100644
--- a/src/backend/utils/activity/backend_status.c
+++ b/src/backend/utils/activity/backend_status.c
@@ -49,6 +49,8 @@ int			pgstat_track_activity_query_size = 1024;
 /* exposed so that backend_progress.c can access it */
 PgBackendStatus *MyBEEntry = NULL;
 
+/* Memory allocated to this backend prior to pgstats initialization */
+uint64		backend_mem_allocated = 0;
 
 static PgBackendStatus *BackendStatusArray = NULL;
 static char *BackendAppnameBuffer = NULL;
@@ -400,6 +402,13 @@ pgstat_bestart(void)
 	lbeentry.st_progress_command_target = InvalidOid;
 	lbeentry.st_query_id = UINT64CONST(0);
 
+	/*
+	 * Move sum of memory allocated prior to pgstats initialization to pgstats
+	 * and zero the local variable.
+	 */
+	lbeentry.backend_mem_allocated = backend_mem_allocated;
+	backend_mem_allocated = 0;
+
 	/*
 	 * we don't zero st_progress_param here to save cycles; nobody should
 	 * examine it until st_progress_command has been set to something other
@@ -1148,3 +1157,99 @@ pgstat_clip_activity(const char *raw_activity)
 
 	return activity;
 }
+
+/* --------
+ * pgstat_report_backend_mem_allocated_increase() -
+ *
+ * Called to report increase in memory allocated for this backend
+ * --------
+ */
+void
+pgstat_report_backend_mem_allocated_increase(uint64 allocation)
+{
+	volatile PgBackendStatus *beentry = MyBEEntry;
+
+	if (!beentry || !pgstat_track_activities)
+	{
+		/*
+		 * Account for memory before pgstats is initialized. This will be
+		 * migrated to pgstats on initialization.
+		 */
+		backend_mem_allocated += allocation;
+
+		return;
+	}
+
+	/*
+	 * Update my status entry, following the protocol of bumping
+	 * st_changecount before and after.  We use a volatile pointer here to
+	 * ensure the compiler doesn't try to get cute.
+	 */
+	PGSTAT_BEGIN_WRITE_ACTIVITY(beentry);
+	beentry->backend_mem_allocated += allocation;
+	PGSTAT_END_WRITE_ACTIVITY(beentry);
+}
+
+/* --------
+ * pgstat_report_backend_mem_allocated_decrease() -
+ *
+ * Called to report decrease in memory allocated for this backend
+ * --------
+ */
+void
+pgstat_report_backend_mem_allocated_decrease(uint64 deallocation)
+{
+	volatile PgBackendStatus *beentry = MyBEEntry;
+
+	/*
+	 * Cases may occur where shared memory from a previous postmaster
+	 * invocation still exist. These are cleaned up at startup by
+	 * dsm_cleanup_using_control_segment. Limit decreasing memory allocated to
+	 * zero in case no corresponding prior increase exists or decrease has
+	 * already been accounted for.
+	 */
+
+	if (!beentry || !pgstat_track_activities)
+	{
+		/*
+		 * Account for memory before pgstats is initialized. This will be
+		 * migrated to pgstats on initialization. Do not allow
+		 * backend_mem_allocated to go below zero. If pgstats has not been
+		 * initialized, we are in startup and we set backend_mem_allocated to
+		 * zero in cases where it would go negative and skip generating an
+		 * ereport.
+		 */
+		if (deallocation > backend_mem_allocated)
+			backend_mem_allocated = 0;
+		else
+			backend_mem_allocated -= deallocation;
+
+		return;
+	}
+
+	/*
+	 * Do not allow backend_mem_allocated to go below zero. ereport if we
+	 * would have. There's no need for a lock around the read here asit's
+	 * being referenced from the same backend which means that there shouldn't
+	 * be concurrent writes. We want to generate an ereport in these cases.
+	 */
+	if (deallocation > beentry->backend_mem_allocated)
+	{
+		ereport(LOG, (errmsg("decrease reduces reported backend memory allocated below zero; setting reported to 0")));
+
+		/*
+		 * Overwrite deallocation with current backend_mem_allocated so we end
+		 * up at zero.
+		 */
+		deallocation = beentry->backend_mem_allocated;
+	}
+
+	/*
+	 * Update my status entry, following the protocol of bumping
+	 * st_changecount before and after.  We use a volatile pointer here to
+	 * ensure the compiler doesn't try to get cute.
+	 */
+	PGSTAT_BEGIN_WRITE_ACTIVITY(beentry);
+	beentry->backend_mem_allocated -= deallocation;
+	PGSTAT_END_WRITE_ACTIVITY(beentry);
+}
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 4cca30aae7..1574aa8049 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -536,7 +536,7 @@ pg_stat_get_progress_info(PG_FUNCTION_ARGS)
 Datum
 pg_stat_get_activity(PG_FUNCTION_ARGS)
 {
-#define PG_STAT_GET_ACTIVITY_COLS	30
+#define PG_STAT_GET_ACTIVITY_COLS	31
 	int			num_backends = pgstat_fetch_stat_numbackends();
 	int			curr_backend;
 	int			pid = PG_ARGISNULL(0) ? -1 : PG_GETARG_INT32(0);
@@ -610,6 +610,8 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
 		else
 			nulls[16] = true;
 
+		values[30] = UInt64GetDatum(beentry->backend_mem_allocated);
+
 		/* Values only available to role member or pg_read_all_stats */
 		if (HAS_PGSTAT_PERMISSIONS(beentry->st_userid))
 		{
diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index b6eeb8abab..c91f8efa4d 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -47,6 +47,7 @@
 #include "postgres.h"
 
 #include "port/pg_bitutils.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -509,6 +510,7 @@ AllocSetContextCreateInternal(MemoryContext parent,
 						name);
 
 	((MemoryContext) set)->mem_allocated = firstBlockSize;
+	pgstat_report_backend_mem_allocated_increase(firstBlockSize);
 
 	return (MemoryContext) set;
 }
@@ -532,6 +534,7 @@ AllocSetReset(MemoryContext context)
 	AllocBlock	block;
 	Size		keepersize PG_USED_FOR_ASSERTS_ONLY
 	= set->keeper->endptr - ((char *) set);
+	uint64		deallocation = 0;
 
 	AssertArg(AllocSetIsValid(set));
 
@@ -571,6 +574,7 @@ AllocSetReset(MemoryContext context)
 		{
 			/* Normal case, release the block */
 			context->mem_allocated -= block->endptr - ((char *) block);
+			deallocation += block->endptr - ((char *) block);
 
 #ifdef CLOBBER_FREED_MEMORY
 			wipe_mem(block, block->freeptr - ((char *) block));
@@ -581,6 +585,7 @@ AllocSetReset(MemoryContext context)
 	}
 
 	Assert(context->mem_allocated == keepersize);
+	pgstat_report_backend_mem_allocated_decrease(deallocation);
 
 	/* Reset block size allocation sequence, too */
 	set->nextBlockSize = set->initBlockSize;
@@ -600,6 +605,7 @@ AllocSetDelete(MemoryContext context)
 	AllocBlock	block = set->blocks;
 	Size		keepersize PG_USED_FOR_ASSERTS_ONLY
 	= set->keeper->endptr - ((char *) set);
+	uint64		deallocation = 0;
 
 	AssertArg(AllocSetIsValid(set));
 
@@ -635,11 +641,13 @@ AllocSetDelete(MemoryContext context)
 
 				freelist->first_free = (AllocSetContext *) oldset->header.nextchild;
 				freelist->num_free--;
+				deallocation += oldset->header.mem_allocated;
 
 				/* All that remains is to free the header/initial block */
 				free(oldset);
 			}
 			Assert(freelist->num_free == 0);
+			pgstat_report_backend_mem_allocated_decrease(deallocation);
 		}
 
 		/* Now add the just-deleted context to the freelist. */
@@ -656,7 +664,10 @@ AllocSetDelete(MemoryContext context)
 		AllocBlock	next = block->next;
 
 		if (block != set->keeper)
+		{
 			context->mem_allocated -= block->endptr - ((char *) block);
+			deallocation += block->endptr - ((char *) block);
+		}
 
 #ifdef CLOBBER_FREED_MEMORY
 		wipe_mem(block, block->freeptr - ((char *) block));
@@ -669,6 +680,8 @@ AllocSetDelete(MemoryContext context)
 	}
 
 	Assert(context->mem_allocated == keepersize);
+	pgstat_report_backend_mem_allocated_decrease(deallocation +
+												 context->mem_allocated);
 
 	/* Finally, free the context header, including the keeper block */
 	free(set);
@@ -712,6 +725,7 @@ AllocSetAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_backend_mem_allocated_increase(blksize);
 
 		block->aset = set;
 		block->freeptr = block->endptr = ((char *) block) + blksize;
@@ -916,6 +930,7 @@ AllocSetAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_backend_mem_allocated_increase(blksize);
 
 		block->aset = set;
 		block->freeptr = ((char *) block) + ALLOC_BLOCKHDRSZ;
@@ -1016,6 +1031,7 @@ AllocSetFree(void *pointer)
 			block->next->prev = block->prev;
 
 		set->header.mem_allocated -= block->endptr - ((char *) block);
+		pgstat_report_backend_mem_allocated_decrease(block->endptr - ((char *) block));
 
 #ifdef CLOBBER_FREED_MEMORY
 		wipe_mem(block, block->freeptr - ((char *) block));
@@ -1127,7 +1143,9 @@ AllocSetRealloc(void *pointer, Size size)
 
 		/* updated separately, not to underflow when (oldblksize > blksize) */
 		set->header.mem_allocated -= oldblksize;
+		pgstat_report_backend_mem_allocated_decrease(oldblksize);
 		set->header.mem_allocated += blksize;
+		pgstat_report_backend_mem_allocated_increase(blksize);
 
 		block->freeptr = block->endptr = ((char *) block) + blksize;
 
diff --git a/src/backend/utils/mmgr/generation.c b/src/backend/utils/mmgr/generation.c
index b39894ec94..36e5b3f94d 100644
--- a/src/backend/utils/mmgr/generation.c
+++ b/src/backend/utils/mmgr/generation.c
@@ -37,6 +37,7 @@
 
 #include "lib/ilist.h"
 #include "port/pg_bitutils.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -258,6 +259,7 @@ GenerationContextCreate(MemoryContext parent,
 						name);
 
 	((MemoryContext) set)->mem_allocated = firstBlockSize;
+	pgstat_report_backend_mem_allocated_increase(firstBlockSize);
 
 	return (MemoryContext) set;
 }
@@ -274,6 +276,7 @@ GenerationReset(MemoryContext context)
 {
 	GenerationContext *set = (GenerationContext *) context;
 	dlist_mutable_iter miter;
+	uint64	deallocation = 0;
 
 	AssertArg(GenerationIsValid(set));
 
@@ -296,9 +299,14 @@ GenerationReset(MemoryContext context)
 		if (block == set->keeper)
 			GenerationBlockMarkEmpty(block);
 		else
+		{
+			deallocation += block->blksize;
 			GenerationBlockFree(set, block);
+		}
 	}
 
+	pgstat_report_backend_mem_allocated_decrease(deallocation);
+
 	/* set it so new allocations to make use of the keeper block */
 	set->block = set->keeper;
 
@@ -319,6 +327,9 @@ GenerationDelete(MemoryContext context)
 {
 	/* Reset to release all releasable GenerationBlocks */
 	GenerationReset(context);
+
+	pgstat_report_backend_mem_allocated_decrease(context->mem_allocated);
+
 	/* And free the context header and keeper block */
 	free(context);
 }
@@ -355,6 +366,7 @@ GenerationAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_backend_mem_allocated_increase(blksize);
 
 		/* block with a single (used) chunk */
 		block->context = set;
@@ -458,6 +470,7 @@ GenerationAlloc(MemoryContext context, Size size)
 				return NULL;
 
 			context->mem_allocated += blksize;
+			pgstat_report_backend_mem_allocated_increase(blksize);
 
 			/* initialize the new block */
 			GenerationBlockInit(set, block, blksize);
@@ -691,6 +704,8 @@ GenerationFree(void *pointer)
 	dlist_delete(&block->node);
 
 	set->header.mem_allocated -= block->blksize;
+	pgstat_report_backend_mem_allocated_decrease(block->blksize);
+
 	free(block);
 }
 
diff --git a/src/backend/utils/mmgr/slab.c b/src/backend/utils/mmgr/slab.c
index 2d70adef09..efc8bcfaa7 100644
--- a/src/backend/utils/mmgr/slab.c
+++ b/src/backend/utils/mmgr/slab.c
@@ -53,6 +53,7 @@
 #include "postgres.h"
 
 #include "lib/ilist.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -218,6 +219,12 @@ SlabContextCreate(MemoryContext parent,
 						parent,
 						name);
 
+	/*
+	 * If SlabContextCreate is updated to add headerSize to
+	 * context->mem_allocated, then update here and SlabDelete appropriately
+	 */
+	pgstat_report_backend_mem_allocated_increase(headerSize);
+
 	return (MemoryContext) slab;
 }
 
@@ -233,6 +240,7 @@ SlabReset(MemoryContext context)
 {
 	int			i;
 	SlabContext *slab = castNode(SlabContext, context);
+	uint64		deallocation = 0;
 
 	Assert(slab);
 
@@ -258,9 +266,11 @@ SlabReset(MemoryContext context)
 			free(block);
 			slab->nblocks--;
 			context->mem_allocated -= slab->blockSize;
+			deallocation += slab->blockSize;
 		}
 	}
 
+	pgstat_report_backend_mem_allocated_decrease(deallocation);
 	slab->minFreeChunks = 0;
 
 	Assert(slab->nblocks == 0);
@@ -274,8 +284,17 @@ SlabReset(MemoryContext context)
 void
 SlabDelete(MemoryContext context)
 {
+	/*
+	 * Until header allocation is included in context->mem_allocated cast to
+	 * slab and decrement the headerSize
+	 */
+	SlabContext *slab = castNode(SlabContext, context);
+
 	/* Reset to release all the SlabBlocks */
 	SlabReset(context);
+
+	pgstat_report_backend_mem_allocated_decrease(slab->headerSize);
+
 	/* And free the context header */
 	free(context);
 }
@@ -344,6 +363,7 @@ SlabAlloc(MemoryContext context, Size size)
 		slab->minFreeChunks = slab->chunksPerBlock;
 		slab->nblocks += 1;
 		context->mem_allocated += slab->blockSize;
+		pgstat_report_backend_mem_allocated_increase(slab->blockSize);
 	}
 
 	/* grab the block from the freelist (even the new block is there) */
@@ -511,6 +531,7 @@ SlabFree(void *pointer)
 		free(block);
 		slab->nblocks--;
 		slab->header.mem_allocated -= slab->blockSize;
+		pgstat_report_backend_mem_allocated_decrease(slab->blockSize);
 	}
 	else
 		dlist_push_head(&slab->freelist[block->nfree], &block->node);
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index be47583122..e1bfb85b25 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -5340,9 +5340,9 @@
   proname => 'pg_stat_get_activity', prorows => '100', proisstrict => 'f',
   proretset => 't', provolatile => 's', proparallel => 'r',
   prorettype => 'record', proargtypes => 'int4',
-  proallargtypes => '{int4,oid,int4,oid,text,text,text,text,text,timestamptz,timestamptz,timestamptz,timestamptz,inet,text,int4,xid,xid,text,bool,text,text,int4,text,numeric,text,bool,text,bool,int4,int8}',
-  proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
-  proargnames => '{pid,datid,pid,usesysid,application_name,state,query,wait_event_type,wait_event,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,backend_type,ssl,sslversion,sslcipher,sslbits,ssl_client_dn,ssl_client_serial,ssl_issuer_dn,gss_auth,gss_princ,gss_enc,leader_pid,query_id}',
+  proallargtypes => '{int4,oid,int4,oid,text,text,text,text,text,timestamptz,timestamptz,timestamptz,timestamptz,inet,text,int4,xid,xid,text,bool,text,text,int4,text,numeric,text,bool,text,bool,int4,int8,int8}',
+  proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
+  proargnames => '{pid,datid,pid,usesysid,application_name,state,query,wait_event_type,wait_event,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,backend_type,ssl,sslversion,sslcipher,sslbits,ssl_client_dn,ssl_client_serial,ssl_issuer_dn,gss_auth,gss_princ,gss_enc,leader_pid,query_id,backend_mem_allocated}',
   prosrc => 'pg_stat_get_activity' },
 { oid => '3318',
   descr => 'statistics: information about progress of backends running maintenance command',
diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h
index 7403bca25e..9bdc4197bd 100644
--- a/src/include/utils/backend_status.h
+++ b/src/include/utils/backend_status.h
@@ -168,6 +168,9 @@ typedef struct PgBackendStatus
 
 	/* query identifier, optionally computed using post_parse_analyze_hook */
 	uint64		st_query_id;
+
+	/* Current memory allocated to this backend */
+	uint64		backend_mem_allocated;
 } PgBackendStatus;
 
 
@@ -305,7 +308,9 @@ extern const char *pgstat_get_backend_current_activity(int pid, bool checkUser);
 extern const char *pgstat_get_crashed_backend_activity(int pid, char *buffer,
 													   int buflen);
 extern uint64 pgstat_get_my_query_id(void);
-
+extern void pgstat_report_backend_mem_allocated_increase(uint64 allocation);
+extern void pgstat_report_backend_mem_allocated_decrease(uint64 deallocation);
+extern uint64 pgstat_get_all_backend_memory_allocated(void);
 
 /* ----------
  * Support functions for the SQL-callable functions to
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index 7ec3d2688f..674e5c6fe7 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1757,9 +1757,10 @@ pg_stat_activity| SELECT s.datid,
     s.backend_xid,
     s.backend_xmin,
     s.query_id,
+    s.backend_mem_allocated,
     s.query,
     s.backend_type
-   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, backend_mem_allocated)
      LEFT JOIN pg_database d ON ((s.datid = d.oid)))
      LEFT JOIN pg_authid u ON ((s.usesysid = u.oid)));
 pg_stat_all_indexes| SELECT c.oid AS relid,
@@ -1871,7 +1872,7 @@ pg_stat_gssapi| SELECT s.pid,
     s.gss_auth AS gss_authenticated,
     s.gss_princ AS principal,
     s.gss_enc AS encrypted
-   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, backend_mem_allocated)
   WHERE (s.client_port IS NOT NULL);
 pg_stat_progress_analyze| SELECT s.pid,
     s.datid,
@@ -2052,7 +2053,7 @@ pg_stat_replication| SELECT s.pid,
     w.sync_priority,
     w.sync_state,
     w.reply_time
-   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, backend_mem_allocated)
      JOIN pg_stat_get_wal_senders() w(pid, state, sent_lsn, write_lsn, flush_lsn, replay_lsn, write_lag, flush_lag, replay_lag, sync_priority, sync_state, reply_time) ON ((s.pid = w.pid)))
      LEFT JOIN pg_authid u ON ((s.usesysid = u.oid)));
 pg_stat_replication_slots| SELECT s.slot_name,
@@ -2086,7 +2087,7 @@ pg_stat_ssl| SELECT s.pid,
     s.ssl_client_dn AS client_dn,
     s.ssl_client_serial AS client_serial,
     s.ssl_issuer_dn AS issuer_dn
-   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, backend_mem_allocated)
   WHERE (s.client_port IS NOT NULL);
 pg_stat_subscription| SELECT su.oid AS subid,
     su.subname,
#2Justin Pryzby
pryzby@telsasoft.com
In reply to: Reid Thompson (#1)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On Wed, Aug 31, 2022 at 12:50:19PM -0400, Reid Thompson wrote:

Hi Hackers,

Add the ability to limit the amount of memory that can be allocated to
backends.

This builds on the work that adds backend memory allocated to
pg_stat_activity
/messages/by-id/67bb5c15c0489cb499723b0340f16e10c22485ec.camel@crunchydata.com
Both patches are attached.

You should name the patches with different prefixes, like
001,002,003 Otherwise, cfbot may try to apply them in the wrong order.
git format-patch is the usual tool for that.

+ Specifies a limit to the amount of memory (MB) that may be allocated to

MB are just the default unit, right ?
The user should be allowed to write max_total_backend_memory='2GB'

+        backends in total (i.e. this is not a per user or per backend limit).
+        If unset, or set to 0 it is disabled.  A backend request that would push
+        the total over the limit will be denied with an out of memory error
+        causing that backends current query/transaction to fail. Due to the dynamic

backend's

+        nature of memory allocations, this limit is not exact. If within 1.5MB of
+        the limit and two backends request 1MB each at the same time both may be
+        allocated exceeding the limit. Further requests will not be allocated until

allocated, and exceed the limit

+bool
+exceeds_max_total_bkend_mem(uint64 allocation_request)
+{
+	bool result = false;
+
+	if (MyAuxProcType != NotAnAuxProcess)
+		return result;

The double negative is confusing, so could use a comment.

+	/* Convert max_total_bkend_mem to bytes for comparison */
+	if (max_total_bkend_mem &&
+		pgstat_get_all_backend_memory_allocated() +
+		allocation_request > (uint64)max_total_bkend_mem * 1024 * 1024)
+	{
+		/*
+		 * Explicitely identify the OOM being a result of this
+		 * configuration parameter vs a system failure to allocate OOM.
+		 */
+		elog(WARNING,
+			 "request will exceed postgresql.conf defined max_total_backend_memory limit (%lu > %lu)",
+			 pgstat_get_all_backend_memory_allocated() +
+			 allocation_request, (uint64)max_total_bkend_mem * 1024 * 1024);

I think it should be ereport() rather than elog(), which is
internal-only, and not-translated.

+               {"max_total_backend_memory", PGC_SIGHUP, RESOURCES_MEM,
+                       gettext_noop("Restrict total backend memory allocations to this max."),
+                       gettext_noop("0 turns this feature off."),
+                       GUC_UNIT_MB
+               },
+               &max_total_bkend_mem,
+               0, 0, INT_MAX,
+               NULL, NULL, NULL

I think this needs a maximum like INT_MAX/1024/1024

+uint64
+pgstat_get_all_backend_memory_allocated(void)
+{

...

+	for (i = 1; i <= NumBackendStatSlots; i++)
+	{

It's looping over every backend for each allocation.
Do you know if there's any performance impact of that ?

I think it may be necessary to track the current allocation size in
shared memory (with atomic increments?). Maybe decrements would need to
be exactly accounted for, or otherwise Assert() that the value is not
negative. I don't know how expensive it'd be to have conditionals for
each decrement, but maybe the value would only be decremented at
strategic times, like at transaction commit or backend shutdown.

--
Justin

#3Kyotaro Horiguchi
horikyota.ntt@gmail.com
In reply to: Reid Thompson (#1)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

At Wed, 31 Aug 2022 12:50:19 -0400, Reid Thompson <reid.thompson@crunchydata.com> wrote in

Hi Hackers,

Add the ability to limit the amount of memory that can be allocated to
backends.

The patch seems to limit both of memory-context allocations and DSM
allocations happen on a specific process by the same budget. In the
fist place I don't think it's sensible to cap the amount of DSM
allocations by per-process budget.

DSM is used by pgstats subsystem. There can be cases where pgstat
complains for denial of DSM allocation after the budget has been
exhausted by memory-context allocations, or every command complains
for denial of memory-context allocation after once the per-process
budget is exhausted by DSM allocations. That doesn't seem reasonable.

regards.

--
Kyotaro Horiguchi
NTT Open Source Software Center

#4Drouvot, Bertrand
bdrouvot@amazon.com
In reply to: Reid Thompson (#1)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

Hi,

On 8/31/22 6:50 PM, Reid Thompson wrote:

Hi Hackers,

Add the ability to limit the amount of memory that can be allocated to
backends.

Thanks for the patch.

+ 1 on the idea.

Specifies a limit to the amount of memory (MB) that may be allocated to
backends in total (i.e. this is not a per user or per backend limit).
If unset, or set to 0 it is disabled. It is intended as a resource to
help avoid the OOM killer. A backend request that would push the total
over the limit will be denied with an out of memory error causing that
backends current query/transaction to fail.

I'm not sure we are choosing the right victims here (aka the ones that
are doing the request that will push the total over the limit).

Imagine an extreme case where a single backend consumes say 99% of the
limit, shouldn't it be the one to be "punished"? (and somehow forced to
give the memory back).

The problem that i see with the current approach is that a "bad" backend
could impact all the others and continue to do so.

what about punishing say the highest consumer , what do you think? (just
speaking about the general idea here, not about the implementation)

Regards,

--

Bertrand Drouvot
PostgreSQL Contributors Team
RDS Open Source Databases
Amazon Web Services: https://aws.amazon.com

#5David Rowley
dgrowleyml@gmail.com
In reply to: Reid Thompson (#1)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On Thu, 1 Sept 2022 at 04:52, Reid Thompson
<reid.thompson@crunchydata.com> wrote:

Add the ability to limit the amount of memory that can be allocated to
backends.

Are you aware that relcache entries are stored in backend local memory
and that once we've added a relcache entry for a relation that we have
no current code which attempts to reduce the memory consumption used
by cache entries when there's memory pressure?

It seems to me that if we had this feature as you propose that a
backend could hit the limit and stay there just from the memory
requirements of the relation cache after some number of tables have
been accessed from the given backend. It's not hard to imagine a
situation where the palloc() would start to fail during parse, which
might make it quite infuriating for anyone trying to do something
like:

SET max_total_backend_memory TO 0;

or

ALTER SYSTEM SET max_total_backend_memory TO 0;

I think a better solution to this problem would be to have "memory
grants", where we configure some amount of "pool" memory that backends
are allowed to use for queries. The planner would have to add the
expected number of work_mem that the given query is expected to use
and before that query starts, the executor would have to "checkout"
that amount of memory from the pool and return it when finished. If
there is not enough memory in the pool then the query would have to
wait until enough memory is available. This creates a deadlocking
hazard that the deadlock detector would need to be made aware of.

I know Thomas Munro has mentioned this "memory grant" or "memory pool"
feature to me previously and I think he even has some work in progress
code for it. It's a very tricky problem, however, as aside from the
deadlocking issue, it requires working out how much memory a given
plan will use concurrently. That's not as simple as counting the nodes
that use work_mem and summing those up.

There is some discussion about the feature in [1]/messages/by-id/20220713222342.GE18011@telsasoft.com. I was unable to
find what Thomas mentioned on the list about this. I've included him
here in case he has any extra information to share.

David

[1]: /messages/by-id/20220713222342.GE18011@telsasoft.com

#6Reid Thompson
reid.thompson@crunchydata.com
In reply to: Justin Pryzby (#2)
2 attachment(s)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On Wed, 2022-08-31 at 12:34 -0500, Justin Pryzby wrote:

You should name the patches with different prefixes, like
001,002,003  Otherwise, cfbot may try to apply them in the wrong
order.
git format-patch is the usual tool for that.

Thanks for the pointer. My experience with git in the past has been
minimal and basic.

+        Specifies a limit to the amount of memory (MB) that may be
allocated to

MB are just the default unit, right ?
The user should be allowed to write max_total_backend_memory='2GB'

Correct. Default units are MB. Other unit types are converted to MB.

+        causing that backends current query/transaction to fail.

backend's

+        allocated exceeding the limit. Further requests will not

allocated, and exceed the limit

+       if (MyAuxProcType != NotAnAuxProcess)

The double negative is confusing, so could use a comment.

+               elog(WARNING,

I think it should be ereport() rather than elog(), which is
internal-only, and not-translated.

Corrected/added the the above items. Attached patches with the corrections.

+               0, 0, INT_MAX,
+               NULL, NULL, NULL

I think this needs a maximum like INT_MAX/1024/1024

Is this noting that we'd set a ceiling of 2048MB?

+       for (i = 1; i <= NumBackendStatSlots; i++)
+       {

It's looping over every backend for each allocation.
Do you know if there's any performance impact of that ?

I'm not very familiar with how to test performance impact, I'm open to
suggestions. I have performed the below pgbench tests and noted the basic
tps differences in the table.

Test 1:
branch master
CFLAGS="-I/usr/include/python3.8/ " /home/rthompso/src/git/postgres/configure --silent --prefix=/home/rthompso/src/git/postgres/install/master --with-openssl --with-tcl --with-tclconfig=/usr/lib/tcl8.6 --with-perl --with-libxml --with-libxslt --with-python --with-gssapi --with-systemd --with-ldap --enable-nls
make -s -j12 && make -s install
initdb
default postgresql.conf settings
init pgbench pgbench -U rthompso -p 5433 -h localhost -i -s 50 testpgbench
10 iterations
for ctr in {1..10}; do { time pgbench -p 5433 -h localhost -c 10 -j 10 -t 50000 testpgbench; } 2>&1 | tee -a pgstatsResultsNoLimitSet; done

Test 2:
branch pg-stat-activity-backend-memory-allocated
CFLAGS="-I/usr/include/python3.8/ " /home/rthompso/src/git/postgres/configure --silent --prefix=/home/rthompso/src/git/postgres/install/pg-stats-memory/ --with-openssl --with-tcl --with-tclconfig=/usr/lib/tcl8.6 --with-perl --with-libxml --with-libxslt --with-python --with-gssapi --with-systemd --with-ldap --enable-nls
make -s -j12 && make -s install
initdb
default postgresql.conf settings
init pgbench pgbench -U rthompso -p 5433 -h localhost -i -s 50
testpgbench
10 iterations
for ctr in {1..10}; do { time pgbench -p 5433 -h localhost -c 10 -j 10 -t 50000 testpgbench; } 2>&1 | tee -a pgstatsResultsPg-stats-memory; done

Test 3:
branch dev-max-memory
CFLAGS="-I/usr/include/python3.8/ " /home/rthompso/src/git/postgres/configure --silent --prefix=/home/rthompso/src/git/postgres/install/dev-max-memory/ --with-openssl --with-tcl --with-tclconfig=/usr/lib/tcl8.6 --with-perl --with-libxml --with-libxslt --with-python --with-gssapi --with-systemd --with-ldap --enable-nls
make -s -j12 && make -s install
initdb
default postgresql.conf settings
init pgbench pgbench -U rthompso -p 5433 -h localhost -i -s 50 testpgbench
10 iterations
for ctr in {1..10}; do { time pgbench -p 5433 -h localhost -c 10 -j 10 -t 50000 testpgbench; } 2>&1 | tee -a pgstatsResultsDev-max-memory; done

Test 4:
branch dev-max-memory
CFLAGS="-I/usr/include/python3.8/ " /home/rthompso/src/git/postgres/configure --silent --prefix=/home/rthompso/src/git/postgres/install/dev-max-memory/ --with-openssl --with-tcl --with-tclconfig=/usr/lib/tcl8.6 --with-perl --with-libxml --with-libxslt --with-python --with-gssapi --with-systemd --with-ldap --enable-nls
make -s -j12 && make -s install
initdb
non-default postgresql.conf setting for max_total_backend_memory = 100MB
init pgbench pgbench -U rthompso -p 5433 -h localhost -i -s 50 testpgbench
10 iterations
for ctr in {1..10}; do { time pgbench -p 5433 -h localhost -c 10 -j 10 -t 50000 testpgbench; } 2>&1 | tee -a pgstatsResultsDev-max-memory100MB; done

Laptop
11th Gen Intel(R) Core(TM) i7-11850H @ 2.50GHz 8 Cores 16 threads
32GB RAM
SSD drive

Averages from the 10 runs and tps difference over the 10 runs
|------------------+------------------+------------------------+-------------------+------------------+-------------------+---------------+------------------|
| Test Run | Master | Track Memory Allocated | Diff from Master | Max Mem off | Diff from Master | Max Mem 100MB | Diff from Master |
| Set 1 | Test 1 | Test 2 | | Test 3 | | Test 4 | |
| latency average | 2.43390909090909 | 2.44327272727273 | | 2.44381818181818 | | 2.6843 | |
| tps inc conn est | 3398.99291372727 | 3385.40984336364 | -13.583070363637 | 3385.08184309091 | -13.9110706363631 | 3729.5363413 | 330.54342757273 |
| tps exc conn est | 3399.12185727273 | 3385.52527490909 | -13.5965823636366 | 3385.22100872727 | -13.9008485454547 | 3729.7097607 | 330.58790342727 |
|------------------+------------------+------------------------+-------------------+------------------+-------------------+---------------+------------------|
| Set 2 | | | | | | | |
| latency average | 2.691 | 2.6895 | 2 | 2.69 | 3 | 2.6827 | 4 |
| tps inc conn est | 3719.56 | 3721.7587106 | 2.1987106 | 3720.3 | .74 | 3730.86 | 11.30 |
| tps exc conn est | 3719.71 | 3721.9268465 | 2.2168465 | 3720.47 | .76 | 3731.02 | 11.31 |
|------------------+------------------+------------------------+-------------------+------------------+-------------------+---------------+------------------|

I think it may be necessary to track the current allocation size in
shared memory (with atomic increments?).  Maybe decrements would need
to
be exactly accounted for, or otherwise Assert() that the value is not
negative.  I don't know how expensive it'd be to have conditionals
for
each decrement, but maybe the value would only be decremented at
strategic times, like at transaction commit or backend shutdown.

--
Reid Thompson
Senior Software Engineer
Crunchy Data, Inc.

reid.thompson@crunchydata.com
www.crunchydata.com

Attachments:

0002-Add-the-ability-to-limit-the-amount-of-memory-that-c.patchtext/x-patch; charset=UTF-8; name=0002-Add-the-ability-to-limit-the-amount-of-memory-that-c.patchDownload
From 57a79b5f72af510f8c4b9ea65f5ffb4fe1fb7798 Mon Sep 17 00:00:00 2001
From: Reid Thompson <jreidthompson@nc.rr.com>
Date: Sat, 4 Jun 2022 22:23:59 -0400
Subject: [PATCH 2/2] Add the ability to limit the amount of memory that can be
 allocated to backends.

This builds on the work that adds backend memory allocated to pg_stat_activity.

Add GUC variable max_total_backend_memory.

Specifies a limit to the amount of memory (MB) that may be allocated to backends
in total (i.e. this is not a per user or per backend limit). If unset, or set to
0 it is disabled. It is intended as a resource to help avoid the OOM killer on
LINUX and manage resources in general. A backend request that would push the
total over the limit will be denied with an out of memory error causing that
backend's current query/transaction to fail. Due to the dynamic nature of memory
allocations, this limit is not exact. If within 1.5MB of the limit and two
backends request 1MB each at the same time both may be allocated, and exceed the
limit. Further requests will not be allocated until dropping below the limit.
Keep this in mind when setting this value. This limit does not affect auxiliary
backend processes. Backend memory allocations are displayed in the
pg_stat_activity view.
---
 doc/src/sgml/config.sgml                      |  26 +++++
 src/backend/storage/ipc/dsm_impl.c            |  12 ++
 src/backend/utils/activity/backend_status.c   | 107 ++++++++++++++++++
 src/backend/utils/misc/guc.c                  |  11 ++
 src/backend/utils/misc/postgresql.conf.sample |   3 +
 src/backend/utils/mmgr/aset.c                 |  17 +++
 src/backend/utils/mmgr/generation.c           |   9 ++
 src/backend/utils/mmgr/slab.c                 |   8 ++
 src/include/utils/backend_status.h            |   2 +
 9 files changed, 195 insertions(+)

diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index a5cd4e44c7..e70ea71ba1 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -2079,6 +2079,32 @@ include_dir 'conf.d'
       </listitem>
      </varlistentry>
 
+     <varlistentry id="guc-max-total-backend-memory" xreflabel="max_total_backend_memory">
+      <term><varname>max_total_backend_memory</varname> (<type>integer</type>)
+      <indexterm>
+       <primary><varname>max_total_backend_memory</varname> configuration parameter</primary>
+      </indexterm>
+      </term>
+      <listitem>
+       <para>
+        Specifies a limit to the amount of memory (MB) that may be allocated to
+        backends in total (i.e. this is not a per user or per backend limit).
+        If unset, or set to 0 it is disabled.  A backend request that would
+        push the total over the limit will be denied with an out of memory
+        error causing that backend's current query/transaction to fail. Due to
+        the dynamic nature of memory allocations, this limit is not exact. If
+        within 1.5MB of the limit and two backends request 1MB each at the same
+        time both may be allocated, and exceed the limit. Further requests will
+        not be allocated until dropping below the limit. Keep this in mind when
+        setting this value. This limit does not affect auxiliary backend
+        processes <xref linkend="glossary-auxiliary-proc"/> . Backend memory
+        allocations (<varname>backend_mem_allocated</varname>) are displayed in
+        the <link linkend="monitoring-pg-stat-activity-view"><structname>pg_stat_activity</structname></link>
+        view.
+       </para>
+      </listitem>
+     </varlistentry>
+
      </variablelist>
      </sect2>
 
diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c
index 3356bb65b5..cc061056a3 100644
--- a/src/backend/storage/ipc/dsm_impl.c
+++ b/src/backend/storage/ipc/dsm_impl.c
@@ -253,6 +253,10 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 		return true;
 	}
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+		return false;
+
 	/*
 	 * Create new segment or open an existing one for attach.
 	 *
@@ -524,6 +528,10 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 		int			flags = IPCProtection;
 		size_t		segsize;
 
+		/* Do not exceed maximum allowed memory allocation */
+		if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+			return false;
+
 		/*
 		 * Allocate the memory BEFORE acquiring the resource, so that we don't
 		 * leak the resource if memory allocation fails.
@@ -718,6 +726,10 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 		return true;
 	}
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+		return false;
+
 	/* Create new segment or open an existing one for attach. */
 	if (op == DSM_OP_CREATE)
 	{
diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c
index 45da3af213..8ef9b0ffd5 100644
--- a/src/backend/utils/activity/backend_status.c
+++ b/src/backend/utils/activity/backend_status.c
@@ -44,6 +44,8 @@
  */
 bool		pgstat_track_activities = false;
 int			pgstat_track_activity_query_size = 1024;
+/* Max backend memory allocation allowed (MB). 0 = disabled */
+int			max_total_bkend_mem = 0;
 
 
 /* exposed so that backend_progress.c can access it */
@@ -1253,3 +1255,108 @@ pgstat_report_backend_mem_allocated_decrease(uint64 deallocation)
 	beentry->backend_mem_allocated -= deallocation;
 	PGSTAT_END_WRITE_ACTIVITY(beentry);
 }
+
+/* ----------
+ * pgstat_get_all_backend_memory_allocated() -
+ *
+ *	Return a uint64 representing the current shared memory allocated to all
+ *	backends.  This looks directly at the BackendStatusArray, and so will
+ *	provide current information regardless of the age of our transaction's
+ *	snapshot of the status array.
+ *	In the future we will likely utilize additional values - perhaps limit
+ *	backend allocation by user/role, etc.
+ * ----------
+ */
+uint64
+pgstat_get_all_backend_memory_allocated(void)
+{
+	PgBackendStatus *beentry;
+	int			i;
+	uint64		all_backend_memory_allocated = 0;
+
+	beentry = BackendStatusArray;
+
+	/*
+	 * We probably shouldn't get here before shared memory has been set up,
+	 * but be safe.
+	 */
+	if (beentry == NULL || BackendActivityBuffer == NULL)
+		return 0;
+
+	/*
+	 * We include AUX procs in all backend memory calculation
+	 */
+	for (i = 1; i <= NumBackendStatSlots; i++)
+	{
+		/*
+		 * We use a volatile pointer here to ensure the compiler doesn't try to
+		 * get cute.
+		 */
+		volatile PgBackendStatus *vbeentry = beentry;
+		bool		found;
+		uint64		backend_mem_allocated = 0;
+
+		for (;;)
+		{
+			int			before_changecount;
+			int			after_changecount;
+
+			pgstat_begin_read_activity(vbeentry, before_changecount);
+
+			/* Ignore invalid entries, which may contain invalid data.
+			 * See pgstat_beshutdown_hook()
+			 */
+			if (vbeentry->st_procpid > 0)
+				backend_mem_allocated = vbeentry->backend_mem_allocated;
+
+			pgstat_end_read_activity(vbeentry, after_changecount);
+
+			if ((found = pgstat_read_activity_complete(before_changecount,
+													   after_changecount)))
+				break;
+
+			/* Make sure we can break out of loop if stuck... */
+			CHECK_FOR_INTERRUPTS();
+		}
+
+		if (found)
+			all_backend_memory_allocated += backend_mem_allocated;
+
+		beentry++;
+	}
+
+	return all_backend_memory_allocated;
+}
+
+/*
+ * Determine if allocation request will exceed max backend memory allowed.
+ * Do not apply to auxiliary processes.
+ */
+bool
+exceeds_max_total_bkend_mem(uint64 allocation_request)
+{
+	bool result = false;
+
+	/* Exclude auxiliary processes from the check */
+	if (MyAuxProcType != NotAnAuxProcess)
+		return result;
+
+	/* Convert max_total_bkend_mem to bytes for comparison */
+	if (max_total_bkend_mem &&
+		pgstat_get_all_backend_memory_allocated() +
+		allocation_request > (uint64)max_total_bkend_mem * 1024 * 1024)
+	{
+		/*
+		 * Explicitely identify the OOM being a result of this
+		 * configuration parameter vs a system failure to allocate OOM.
+		 */
+		ereport(WARNING,
+			 errmsg("request will exceed postgresql.conf defined max_total_backend_memory limit (%lu > %lu)",
+			 pgstat_get_all_backend_memory_allocated() +
+			 allocation_request, (uint64)max_total_bkend_mem * 1024 * 1024));
+
+		result = true;
+	}
+
+	return result;
+}
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 9fbbfb1be5..ab8d83c235 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -3664,6 +3664,17 @@ static struct config_int ConfigureNamesInt[] =
 		NULL, NULL, NULL
 	},
 
+	{
+		{"max_total_backend_memory", PGC_SIGHUP, RESOURCES_MEM,
+			gettext_noop("Restrict total backend memory allocations to this max."),
+			gettext_noop("0 turns this feature off."),
+			GUC_UNIT_MB
+		},
+		&max_total_bkend_mem,
+		0, 0, INT_MAX,
+		NULL, NULL, NULL
+	},
+
 	/* End-of-list marker */
 	{
 		{NULL, 0, 0, NULL, NULL}, NULL, 0, 0, 0, NULL, NULL, NULL
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 90bec0502c..8e944f6511 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -155,6 +155,9 @@
 					#   mmap
 					# (change requires restart)
 #min_dynamic_shared_memory = 0MB	# (change requires restart)
+#max_total_backend_memory = 0MB		# Restrict total backend memory allocations
+									# to this max (in MB). 0 turns this feature
+									# off.
 
 # - Disk -
 
diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index c91f8efa4d..ac9a1ced3f 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -428,6 +428,10 @@ AllocSetContextCreateInternal(MemoryContext parent,
 	else
 		firstBlockSize = Max(firstBlockSize, initBlockSize);
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (exceeds_max_total_bkend_mem(firstBlockSize))
+		return NULL;
+
 	/*
 	 * Allocate the initial block.  Unlike other aset.c blocks, it starts with
 	 * the context header and its block header follows that.
@@ -720,6 +724,11 @@ AllocSetAlloc(MemoryContext context, Size size)
 	{
 		chunk_size = MAXALIGN(size);
 		blksize = chunk_size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
+
+		/* Do not exceed maximum allowed memory allocation */
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		block = (AllocBlock) malloc(blksize);
 		if (block == NULL)
 			return NULL;
@@ -911,6 +920,10 @@ AllocSetAlloc(MemoryContext context, Size size)
 		while (blksize < required_size)
 			blksize <<= 1;
 
+		/* Do not exceed maximum allowed memory allocation */
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		/* Try to allocate it */
 		block = (AllocBlock) malloc(blksize);
 
@@ -1133,6 +1146,10 @@ AllocSetRealloc(void *pointer, Size size)
 		blksize = chksize + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
 		oldblksize = block->endptr - ((char *) block);
 
+		/* Do not exceed maximum allowed memory allocation */
+		if (blksize > oldblksize && exceeds_max_total_bkend_mem(blksize - oldblksize))
+			return NULL;
+
 		block = (AllocBlock) realloc(block, blksize);
 		if (block == NULL)
 		{
diff --git a/src/backend/utils/mmgr/generation.c b/src/backend/utils/mmgr/generation.c
index 36e5b3f94d..1d5720836c 100644
--- a/src/backend/utils/mmgr/generation.c
+++ b/src/backend/utils/mmgr/generation.c
@@ -192,6 +192,9 @@ GenerationContextCreate(MemoryContext parent,
 	else
 		allocSize = Max(allocSize, initBlockSize);
 
+	if (exceeds_max_total_bkend_mem(allocSize))
+		return NULL;
+
 	/*
 	 * Allocate the initial block.  Unlike other generation.c blocks, it
 	 * starts with the context header and its block header follows that.
@@ -361,6 +364,9 @@ GenerationAlloc(MemoryContext context, Size size)
 	{
 		Size		blksize = required_size + Generation_BLOCKHDRSZ;
 
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		block = (GenerationBlock *) malloc(blksize);
 		if (block == NULL)
 			return NULL;
@@ -464,6 +470,9 @@ GenerationAlloc(MemoryContext context, Size size)
 			if (blksize < required_size)
 				blksize = pg_nextpower2_size_t(required_size);
 
+			if (exceeds_max_total_bkend_mem(blksize))
+				return NULL;
+
 			block = (GenerationBlock *) malloc(blksize);
 
 			if (block == NULL)
diff --git a/src/backend/utils/mmgr/slab.c b/src/backend/utils/mmgr/slab.c
index e0e69b394e..63c07120dd 100644
--- a/src/backend/utils/mmgr/slab.c
+++ b/src/backend/utils/mmgr/slab.c
@@ -177,6 +177,10 @@ SlabContextCreate(MemoryContext parent,
 	headerSize += chunksPerBlock * sizeof(bool);
 #endif
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (exceeds_max_total_bkend_mem(headerSize))
+		return NULL;
+
 	slab = (SlabContext *) malloc(headerSize);
 	if (slab == NULL)
 	{
@@ -331,6 +335,10 @@ SlabAlloc(MemoryContext context, Size size)
 	 */
 	if (slab->minFreeChunks == 0)
 	{
+		/* Do not exceed maximum allowed memory allocation */
+		if (exceeds_max_total_bkend_mem(slab->blockSize))
+			return NULL;
+
 		block = (SlabBlock *) malloc(slab->blockSize);
 
 		if (block == NULL)
diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h
index 9bdc4197bd..3b940ff98e 100644
--- a/src/include/utils/backend_status.h
+++ b/src/include/utils/backend_status.h
@@ -270,6 +270,7 @@ typedef struct LocalPgBackendStatus
  */
 extern PGDLLIMPORT bool pgstat_track_activities;
 extern PGDLLIMPORT int pgstat_track_activity_query_size;
+extern PGDLLIMPORT int max_total_bkend_mem;
 
 
 /* ----------
@@ -321,6 +322,7 @@ extern int	pgstat_fetch_stat_numbackends(void);
 extern PgBackendStatus *pgstat_fetch_stat_beentry(int beid);
 extern LocalPgBackendStatus *pgstat_fetch_stat_local_beentry(int beid);
 extern char *pgstat_clip_activity(const char *raw_activity);
+extern bool exceeds_max_total_bkend_mem(uint64 allocation_request);
 
 
 #endif							/* BACKEND_STATUS_H */
-- 
2.25.1

0001-Add-tracking-of-backend-memory-allocated-to-pg_stat_.patchtext/x-patch; charset=UTF-8; name=0001-Add-tracking-of-backend-memory-allocated-to-pg_stat_.patchDownload
From 584a04f1b53948049e73165a4ffdd544c950ab0d Mon Sep 17 00:00:00 2001
From: Reid Thompson <jreidthompson@nc.rr.com>
Date: Thu, 11 Aug 2022 12:01:25 -0400
Subject: [PATCH 1/2] Add tracking of backend memory allocated to
 pg_stat_activity

This new field displays the current bytes of memory allocated to the
backend process. It is updated as memory for the process is
malloc'd/free'd. Memory allocated to items on the freelist is included in
the displayed value.  Dynamic shared memory allocations are included
only in the value displayed for the backend that created them, they are
not included in the value for backends that are attached to them to
avoid double counting. On occasion, orphaned memory segments may be
cleaned up on postmaster startup. This may result in decreasing the sum
without a prior increment. We limit the floor of backend_mem_allocated
to zero. Updated pg_stat_activity documentation for the new column.
---
 doc/src/sgml/monitoring.sgml                |  12 +++
 src/backend/catalog/system_views.sql        |   1 +
 src/backend/storage/ipc/dsm_impl.c          |  80 +++++++++++++++
 src/backend/utils/activity/backend_status.c | 105 ++++++++++++++++++++
 src/backend/utils/adt/pgstatfuncs.c         |   4 +-
 src/backend/utils/mmgr/aset.c               |  18 ++++
 src/backend/utils/mmgr/generation.c         |  15 +++
 src/backend/utils/mmgr/slab.c               |  21 ++++
 src/include/catalog/pg_proc.dat             |   6 +-
 src/include/utils/backend_status.h          |   7 +-
 src/test/regress/expected/rules.out         |   9 +-
 11 files changed, 269 insertions(+), 9 deletions(-)

diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 1d9509a2f6..40ae638f25 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -947,6 +947,18 @@ postgres   27093  0.0  0.0  30096  2752 ?        Ss   11:34   0:00 postgres: ser
      </para></entry>
     </row>
 
+    <row>
+     <entry role="catalog_table_entry"><para role="column_definition">
+      <structfield>backend_mem_allocated</structfield> <type>bigint</type>
+     </para>
+     <para>
+      The byte count of memory allocated to this backend. Dynamic shared memory
+      allocations are included only in the value displayed for the backend that
+      created them, they are not included in the value for backends that are
+      attached to them to avoid double counting.
+     </para></entry>
+    </row>
+
      <row>
       <entry role="catalog_table_entry"><para role="column_definition">
        <structfield>query</structfield> <type>text</type>
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 5a844b63a1..d23f0e9dbb 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -863,6 +863,7 @@ CREATE VIEW pg_stat_activity AS
             S.backend_xid,
             s.backend_xmin,
             S.query_id,
+            S.backend_mem_allocated,
             S.query,
             S.backend_type
     FROM pg_stat_get_activity(NULL) AS S
diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c
index e1b90c5de4..3356bb65b5 100644
--- a/src/backend/storage/ipc/dsm_impl.c
+++ b/src/backend/storage/ipc/dsm_impl.c
@@ -66,6 +66,7 @@
 #include "postmaster/postmaster.h"
 #include "storage/dsm_impl.h"
 #include "storage/fd.h"
+#include "utils/backend_status.h"
 #include "utils/guc.h"
 #include "utils/memutils.h"
 
@@ -232,6 +233,13 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_backend_mem_allocated_decrease(*mapped_size);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && shm_unlink(name) != 0)
@@ -332,6 +340,36 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+	{
+		/*
+		 * Posix creation calls dsm_impl_posix_resize implying that resizing
+		 * occurs or may be added in the future. As implemented
+		 * dsm_impl_posix_resize utilizes fallocate or truncate, passing the
+		 * whole new size as input, growing the allocation as needed (only
+		 * truncate supports shrinking). We update by replacing the old
+		 * allocation with the new.
+		 */
+#if defined(HAVE_POSIX_FALLOCATE) && defined(__linux__)
+		/*
+		 * posix_fallocate does not shrink allocations, adjust only on
+		 * allocation increase.
+		 */
+		if (request_size > *mapped_size)
+		{
+			pgstat_report_backend_mem_allocated_decrease(*mapped_size);
+			pgstat_report_backend_mem_allocated_increase(request_size);
+		}
+#else
+		pgstat_report_backend_mem_allocated_decrease(*mapped_size);
+		pgstat_report_backend_mem_allocated_increase(request_size);
+#endif
+	}
 	*mapped_address = address;
 	*mapped_size = request_size;
 	close(fd);
@@ -537,6 +575,14 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_backend_mem_allocated_decrease(*mapped_size);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && shmctl(ident, IPC_RMID, NULL) < 0)
@@ -584,6 +630,13 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_backend_mem_allocated_increase(request_size);
 	*mapped_address = address;
 	*mapped_size = request_size;
 
@@ -652,6 +705,13 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 			return false;
 		}
 
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_backend_mem_allocated_decrease(*mapped_size);
 		*impl_private = NULL;
 		*mapped_address = NULL;
 		*mapped_size = 0;
@@ -768,6 +828,12 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 		return false;
 	}
 
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_backend_mem_allocated_increase(info.RegionSize);
 	*mapped_address = address;
 	*mapped_size = info.RegionSize;
 	*impl_private = hmap;
@@ -812,6 +878,13 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		pgstat_report_backend_mem_allocated_decrease(*mapped_size);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && unlink(name) != 0)
@@ -933,6 +1006,13 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_backend_mem_allocated_increase(request_size);
 	*mapped_address = address;
 	*mapped_size = request_size;
 
diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c
index c7ed1e6d7a..45da3af213 100644
--- a/src/backend/utils/activity/backend_status.c
+++ b/src/backend/utils/activity/backend_status.c
@@ -49,6 +49,8 @@ int			pgstat_track_activity_query_size = 1024;
 /* exposed so that backend_progress.c can access it */
 PgBackendStatus *MyBEEntry = NULL;
 
+/* Memory allocated to this backend prior to pgstats initialization */
+uint64		backend_mem_allocated = 0;
 
 static PgBackendStatus *BackendStatusArray = NULL;
 static char *BackendAppnameBuffer = NULL;
@@ -400,6 +402,13 @@ pgstat_bestart(void)
 	lbeentry.st_progress_command_target = InvalidOid;
 	lbeentry.st_query_id = UINT64CONST(0);
 
+	/*
+	 * Move sum of memory allocated prior to pgstats initialization to pgstats
+	 * and zero the local variable.
+	 */
+	lbeentry.backend_mem_allocated = backend_mem_allocated;
+	backend_mem_allocated = 0;
+
 	/*
 	 * we don't zero st_progress_param here to save cycles; nobody should
 	 * examine it until st_progress_command has been set to something other
@@ -1148,3 +1157,99 @@ pgstat_clip_activity(const char *raw_activity)
 
 	return activity;
 }
+
+/* --------
+ * pgstat_report_backend_mem_allocated_increase() -
+ *
+ * Called to report increase in memory allocated for this backend
+ * --------
+ */
+void
+pgstat_report_backend_mem_allocated_increase(uint64 allocation)
+{
+	volatile PgBackendStatus *beentry = MyBEEntry;
+
+	if (!beentry || !pgstat_track_activities)
+	{
+		/*
+		 * Account for memory before pgstats is initialized. This will be
+		 * migrated to pgstats on initialization.
+		 */
+		backend_mem_allocated += allocation;
+
+		return;
+	}
+
+	/*
+	 * Update my status entry, following the protocol of bumping
+	 * st_changecount before and after.  We use a volatile pointer here to
+	 * ensure the compiler doesn't try to get cute.
+	 */
+	PGSTAT_BEGIN_WRITE_ACTIVITY(beentry);
+	beentry->backend_mem_allocated += allocation;
+	PGSTAT_END_WRITE_ACTIVITY(beentry);
+}
+
+/* --------
+ * pgstat_report_backend_mem_allocated_decrease() -
+ *
+ * Called to report decrease in memory allocated for this backend
+ * --------
+ */
+void
+pgstat_report_backend_mem_allocated_decrease(uint64 deallocation)
+{
+	volatile PgBackendStatus *beentry = MyBEEntry;
+
+	/*
+	 * Cases may occur where shared memory from a previous postmaster
+	 * invocation still exist. These are cleaned up at startup by
+	 * dsm_cleanup_using_control_segment. Limit decreasing memory allocated to
+	 * zero in case no corresponding prior increase exists or decrease has
+	 * already been accounted for.
+	 */
+
+	if (!beentry || !pgstat_track_activities)
+	{
+		/*
+		 * Account for memory before pgstats is initialized. This will be
+		 * migrated to pgstats on initialization. Do not allow
+		 * backend_mem_allocated to go below zero. If pgstats has not been
+		 * initialized, we are in startup and we set backend_mem_allocated to
+		 * zero in cases where it would go negative and skip generating an
+		 * ereport.
+		 */
+		if (deallocation > backend_mem_allocated)
+			backend_mem_allocated = 0;
+		else
+			backend_mem_allocated -= deallocation;
+
+		return;
+	}
+
+	/*
+	 * Do not allow backend_mem_allocated to go below zero. ereport if we
+	 * would have. There's no need for a lock around the read here as it's
+	 * being referenced from the same backend which means that there shouldn't
+	 * be concurrent writes. We want to generate an ereport in these cases.
+	 */
+	if (deallocation > beentry->backend_mem_allocated)
+	{
+		ereport(LOG, errmsg("decrease reduces reported backend memory allocated below zero; setting reported to 0"));
+
+		/*
+		 * Overwrite deallocation with current backend_mem_allocated so we end
+		 * up at zero.
+		 */
+		deallocation = beentry->backend_mem_allocated;
+	}
+
+	/*
+	 * Update my status entry, following the protocol of bumping
+	 * st_changecount before and after.  We use a volatile pointer here to
+	 * ensure the compiler doesn't try to get cute.
+	 */
+	PGSTAT_BEGIN_WRITE_ACTIVITY(beentry);
+	beentry->backend_mem_allocated -= deallocation;
+	PGSTAT_END_WRITE_ACTIVITY(beentry);
+}
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 4cca30aae7..1574aa8049 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -536,7 +536,7 @@ pg_stat_get_progress_info(PG_FUNCTION_ARGS)
 Datum
 pg_stat_get_activity(PG_FUNCTION_ARGS)
 {
-#define PG_STAT_GET_ACTIVITY_COLS	30
+#define PG_STAT_GET_ACTIVITY_COLS	31
 	int			num_backends = pgstat_fetch_stat_numbackends();
 	int			curr_backend;
 	int			pid = PG_ARGISNULL(0) ? -1 : PG_GETARG_INT32(0);
@@ -610,6 +610,8 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
 		else
 			nulls[16] = true;
 
+		values[30] = UInt64GetDatum(beentry->backend_mem_allocated);
+
 		/* Values only available to role member or pg_read_all_stats */
 		if (HAS_PGSTAT_PERMISSIONS(beentry->st_userid))
 		{
diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index b6eeb8abab..c91f8efa4d 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -47,6 +47,7 @@
 #include "postgres.h"
 
 #include "port/pg_bitutils.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -509,6 +510,7 @@ AllocSetContextCreateInternal(MemoryContext parent,
 						name);
 
 	((MemoryContext) set)->mem_allocated = firstBlockSize;
+	pgstat_report_backend_mem_allocated_increase(firstBlockSize);
 
 	return (MemoryContext) set;
 }
@@ -532,6 +534,7 @@ AllocSetReset(MemoryContext context)
 	AllocBlock	block;
 	Size		keepersize PG_USED_FOR_ASSERTS_ONLY
 	= set->keeper->endptr - ((char *) set);
+	uint64		deallocation = 0;
 
 	AssertArg(AllocSetIsValid(set));
 
@@ -571,6 +574,7 @@ AllocSetReset(MemoryContext context)
 		{
 			/* Normal case, release the block */
 			context->mem_allocated -= block->endptr - ((char *) block);
+			deallocation += block->endptr - ((char *) block);
 
 #ifdef CLOBBER_FREED_MEMORY
 			wipe_mem(block, block->freeptr - ((char *) block));
@@ -581,6 +585,7 @@ AllocSetReset(MemoryContext context)
 	}
 
 	Assert(context->mem_allocated == keepersize);
+	pgstat_report_backend_mem_allocated_decrease(deallocation);
 
 	/* Reset block size allocation sequence, too */
 	set->nextBlockSize = set->initBlockSize;
@@ -600,6 +605,7 @@ AllocSetDelete(MemoryContext context)
 	AllocBlock	block = set->blocks;
 	Size		keepersize PG_USED_FOR_ASSERTS_ONLY
 	= set->keeper->endptr - ((char *) set);
+	uint64		deallocation = 0;
 
 	AssertArg(AllocSetIsValid(set));
 
@@ -635,11 +641,13 @@ AllocSetDelete(MemoryContext context)
 
 				freelist->first_free = (AllocSetContext *) oldset->header.nextchild;
 				freelist->num_free--;
+				deallocation += oldset->header.mem_allocated;
 
 				/* All that remains is to free the header/initial block */
 				free(oldset);
 			}
 			Assert(freelist->num_free == 0);
+			pgstat_report_backend_mem_allocated_decrease(deallocation);
 		}
 
 		/* Now add the just-deleted context to the freelist. */
@@ -656,7 +664,10 @@ AllocSetDelete(MemoryContext context)
 		AllocBlock	next = block->next;
 
 		if (block != set->keeper)
+		{
 			context->mem_allocated -= block->endptr - ((char *) block);
+			deallocation += block->endptr - ((char *) block);
+		}
 
 #ifdef CLOBBER_FREED_MEMORY
 		wipe_mem(block, block->freeptr - ((char *) block));
@@ -669,6 +680,8 @@ AllocSetDelete(MemoryContext context)
 	}
 
 	Assert(context->mem_allocated == keepersize);
+	pgstat_report_backend_mem_allocated_decrease(deallocation +
+												 context->mem_allocated);
 
 	/* Finally, free the context header, including the keeper block */
 	free(set);
@@ -712,6 +725,7 @@ AllocSetAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_backend_mem_allocated_increase(blksize);
 
 		block->aset = set;
 		block->freeptr = block->endptr = ((char *) block) + blksize;
@@ -916,6 +930,7 @@ AllocSetAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_backend_mem_allocated_increase(blksize);
 
 		block->aset = set;
 		block->freeptr = ((char *) block) + ALLOC_BLOCKHDRSZ;
@@ -1016,6 +1031,7 @@ AllocSetFree(void *pointer)
 			block->next->prev = block->prev;
 
 		set->header.mem_allocated -= block->endptr - ((char *) block);
+		pgstat_report_backend_mem_allocated_decrease(block->endptr - ((char *) block));
 
 #ifdef CLOBBER_FREED_MEMORY
 		wipe_mem(block, block->freeptr - ((char *) block));
@@ -1127,7 +1143,9 @@ AllocSetRealloc(void *pointer, Size size)
 
 		/* updated separately, not to underflow when (oldblksize > blksize) */
 		set->header.mem_allocated -= oldblksize;
+		pgstat_report_backend_mem_allocated_decrease(oldblksize);
 		set->header.mem_allocated += blksize;
+		pgstat_report_backend_mem_allocated_increase(blksize);
 
 		block->freeptr = block->endptr = ((char *) block) + blksize;
 
diff --git a/src/backend/utils/mmgr/generation.c b/src/backend/utils/mmgr/generation.c
index b39894ec94..36e5b3f94d 100644
--- a/src/backend/utils/mmgr/generation.c
+++ b/src/backend/utils/mmgr/generation.c
@@ -37,6 +37,7 @@
 
 #include "lib/ilist.h"
 #include "port/pg_bitutils.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -258,6 +259,7 @@ GenerationContextCreate(MemoryContext parent,
 						name);
 
 	((MemoryContext) set)->mem_allocated = firstBlockSize;
+	pgstat_report_backend_mem_allocated_increase(firstBlockSize);
 
 	return (MemoryContext) set;
 }
@@ -274,6 +276,7 @@ GenerationReset(MemoryContext context)
 {
 	GenerationContext *set = (GenerationContext *) context;
 	dlist_mutable_iter miter;
+	uint64	deallocation = 0;
 
 	AssertArg(GenerationIsValid(set));
 
@@ -296,9 +299,14 @@ GenerationReset(MemoryContext context)
 		if (block == set->keeper)
 			GenerationBlockMarkEmpty(block);
 		else
+		{
+			deallocation += block->blksize;
 			GenerationBlockFree(set, block);
+		}
 	}
 
+	pgstat_report_backend_mem_allocated_decrease(deallocation);
+
 	/* set it so new allocations to make use of the keeper block */
 	set->block = set->keeper;
 
@@ -319,6 +327,9 @@ GenerationDelete(MemoryContext context)
 {
 	/* Reset to release all releasable GenerationBlocks */
 	GenerationReset(context);
+
+	pgstat_report_backend_mem_allocated_decrease(context->mem_allocated);
+
 	/* And free the context header and keeper block */
 	free(context);
 }
@@ -355,6 +366,7 @@ GenerationAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_backend_mem_allocated_increase(blksize);
 
 		/* block with a single (used) chunk */
 		block->context = set;
@@ -458,6 +470,7 @@ GenerationAlloc(MemoryContext context, Size size)
 				return NULL;
 
 			context->mem_allocated += blksize;
+			pgstat_report_backend_mem_allocated_increase(blksize);
 
 			/* initialize the new block */
 			GenerationBlockInit(set, block, blksize);
@@ -691,6 +704,8 @@ GenerationFree(void *pointer)
 	dlist_delete(&block->node);
 
 	set->header.mem_allocated -= block->blksize;
+	pgstat_report_backend_mem_allocated_decrease(block->blksize);
+
 	free(block);
 }
 
diff --git a/src/backend/utils/mmgr/slab.c b/src/backend/utils/mmgr/slab.c
index 2d70adef09..e0e69b394e 100644
--- a/src/backend/utils/mmgr/slab.c
+++ b/src/backend/utils/mmgr/slab.c
@@ -53,6 +53,7 @@
 #include "postgres.h"
 
 #include "lib/ilist.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -218,6 +219,12 @@ SlabContextCreate(MemoryContext parent,
 						parent,
 						name);
 
+	/*
+	 * If SlabContextCreate is updated to add headerSize to
+	 * context->mem_allocated, then update here and SlabDelete appropriately
+	 */
+	pgstat_report_backend_mem_allocated_increase(headerSize);
+
 	return (MemoryContext) slab;
 }
 
@@ -233,6 +240,7 @@ SlabReset(MemoryContext context)
 {
 	int			i;
 	SlabContext *slab = castNode(SlabContext, context);
+	uint64		deallocation = 0;
 
 	Assert(slab);
 
@@ -258,9 +266,11 @@ SlabReset(MemoryContext context)
 			free(block);
 			slab->nblocks--;
 			context->mem_allocated -= slab->blockSize;
+			deallocation += slab->blockSize;
 		}
 	}
 
+	pgstat_report_backend_mem_allocated_decrease(deallocation);
 	slab->minFreeChunks = 0;
 
 	Assert(slab->nblocks == 0);
@@ -274,8 +284,17 @@ SlabReset(MemoryContext context)
 void
 SlabDelete(MemoryContext context)
 {
+	/*
+	 * Until header allocation is included in context->mem_allocated, cast to
+	 * slab and decrement the headerSize
+	 */
+	SlabContext *slab = castNode(SlabContext, context);
+
 	/* Reset to release all the SlabBlocks */
 	SlabReset(context);
+
+	pgstat_report_backend_mem_allocated_decrease(slab->headerSize);
+
 	/* And free the context header */
 	free(context);
 }
@@ -344,6 +363,7 @@ SlabAlloc(MemoryContext context, Size size)
 		slab->minFreeChunks = slab->chunksPerBlock;
 		slab->nblocks += 1;
 		context->mem_allocated += slab->blockSize;
+		pgstat_report_backend_mem_allocated_increase(slab->blockSize);
 	}
 
 	/* grab the block from the freelist (even the new block is there) */
@@ -511,6 +531,7 @@ SlabFree(void *pointer)
 		free(block);
 		slab->nblocks--;
 		slab->header.mem_allocated -= slab->blockSize;
+		pgstat_report_backend_mem_allocated_decrease(slab->blockSize);
 	}
 	else
 		dlist_push_head(&slab->freelist[block->nfree], &block->node);
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index be47583122..e1bfb85b25 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -5340,9 +5340,9 @@
   proname => 'pg_stat_get_activity', prorows => '100', proisstrict => 'f',
   proretset => 't', provolatile => 's', proparallel => 'r',
   prorettype => 'record', proargtypes => 'int4',
-  proallargtypes => '{int4,oid,int4,oid,text,text,text,text,text,timestamptz,timestamptz,timestamptz,timestamptz,inet,text,int4,xid,xid,text,bool,text,text,int4,text,numeric,text,bool,text,bool,int4,int8}',
-  proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
-  proargnames => '{pid,datid,pid,usesysid,application_name,state,query,wait_event_type,wait_event,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,backend_type,ssl,sslversion,sslcipher,sslbits,ssl_client_dn,ssl_client_serial,ssl_issuer_dn,gss_auth,gss_princ,gss_enc,leader_pid,query_id}',
+  proallargtypes => '{int4,oid,int4,oid,text,text,text,text,text,timestamptz,timestamptz,timestamptz,timestamptz,inet,text,int4,xid,xid,text,bool,text,text,int4,text,numeric,text,bool,text,bool,int4,int8,int8}',
+  proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
+  proargnames => '{pid,datid,pid,usesysid,application_name,state,query,wait_event_type,wait_event,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,backend_type,ssl,sslversion,sslcipher,sslbits,ssl_client_dn,ssl_client_serial,ssl_issuer_dn,gss_auth,gss_princ,gss_enc,leader_pid,query_id,backend_mem_allocated}',
   prosrc => 'pg_stat_get_activity' },
 { oid => '3318',
   descr => 'statistics: information about progress of backends running maintenance command',
diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h
index 7403bca25e..9bdc4197bd 100644
--- a/src/include/utils/backend_status.h
+++ b/src/include/utils/backend_status.h
@@ -168,6 +168,9 @@ typedef struct PgBackendStatus
 
 	/* query identifier, optionally computed using post_parse_analyze_hook */
 	uint64		st_query_id;
+
+	/* Current memory allocated to this backend */
+	uint64		backend_mem_allocated;
 } PgBackendStatus;
 
 
@@ -305,7 +308,9 @@ extern const char *pgstat_get_backend_current_activity(int pid, bool checkUser);
 extern const char *pgstat_get_crashed_backend_activity(int pid, char *buffer,
 													   int buflen);
 extern uint64 pgstat_get_my_query_id(void);
-
+extern void pgstat_report_backend_mem_allocated_increase(uint64 allocation);
+extern void pgstat_report_backend_mem_allocated_decrease(uint64 deallocation);
+extern uint64 pgstat_get_all_backend_memory_allocated(void);
 
 /* ----------
  * Support functions for the SQL-callable functions to
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index 7ec3d2688f..674e5c6fe7 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1757,9 +1757,10 @@ pg_stat_activity| SELECT s.datid,
     s.backend_xid,
     s.backend_xmin,
     s.query_id,
+    s.backend_mem_allocated,
     s.query,
     s.backend_type
-   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, backend_mem_allocated)
      LEFT JOIN pg_database d ON ((s.datid = d.oid)))
      LEFT JOIN pg_authid u ON ((s.usesysid = u.oid)));
 pg_stat_all_indexes| SELECT c.oid AS relid,
@@ -1871,7 +1872,7 @@ pg_stat_gssapi| SELECT s.pid,
     s.gss_auth AS gss_authenticated,
     s.gss_princ AS principal,
     s.gss_enc AS encrypted
-   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, backend_mem_allocated)
   WHERE (s.client_port IS NOT NULL);
 pg_stat_progress_analyze| SELECT s.pid,
     s.datid,
@@ -2052,7 +2053,7 @@ pg_stat_replication| SELECT s.pid,
     w.sync_priority,
     w.sync_state,
     w.reply_time
-   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, backend_mem_allocated)
      JOIN pg_stat_get_wal_senders() w(pid, state, sent_lsn, write_lsn, flush_lsn, replay_lsn, write_lag, flush_lag, replay_lag, sync_priority, sync_state, reply_time) ON ((s.pid = w.pid)))
      LEFT JOIN pg_authid u ON ((s.usesysid = u.oid)));
 pg_stat_replication_slots| SELECT s.slot_name,
@@ -2086,7 +2087,7 @@ pg_stat_ssl| SELECT s.pid,
     s.ssl_client_dn AS client_dn,
     s.ssl_client_serial AS client_serial,
     s.ssl_issuer_dn AS issuer_dn
-   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, backend_mem_allocated)
   WHERE (s.client_port IS NOT NULL);
 pg_stat_subscription| SELECT su.oid AS subid,
     su.subname,
-- 
2.25.1

#7Reid Thompson
reid.thompson@crunchydata.com
In reply to: Kyotaro Horiguchi (#3)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On Thu, 2022-09-01 at 11:48 +0900, Kyotaro Horiguchi wrote:

The patch seems to limit both of memory-context allocations and DSM
allocations happen on a specific process by the same budget. In the
fist place I don't think it's sensible to cap the amount of DSM
allocations by per-process budget.

DSM is used by pgstats subsystem. There can be cases where pgstat
complains for denial of DSM allocation after the budget has been
exhausted by memory-context allocations, or every command complains
for denial of memory-context allocation after once the per-process
budget is exhausted by DSM allocations. That doesn't seem
reasonable.
regards.

It's intended as a mechanism for administrators to limit total
postgresql memory consumption to avoid the OOM killer causing a crash
and restart, or to ensure that resources are available for other
processes on shared hosts, etc. It limits all types of allocations in
order to accomplish this.  Our documentation will note this, so that
administrators that have the need to set it are aware that it can
affect all non-auxiliary processes and what the effect is.

#8Reid Thompson
reid.thompson@crunchydata.com
In reply to: Drouvot, Bertrand (#4)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On Fri, 2022-09-02 at 09:30 +0200, Drouvot, Bertrand wrote:

Hi,

I'm not sure we are choosing the right victims here (aka the ones
that are doing the request that will push the total over the limit).

Imagine an extreme case where a single backend consumes say 99% of
the limit, shouldn't it be the one to be "punished"? (and somehow forced
to give the memory back).

The problem that i see with the current approach is that a "bad"
backend could impact all the others and continue to do so.

what about punishing say the highest consumer , what do you think?
(just speaking about the general idea here, not about the implementation)

Initially, we believe that punishing the detector is reasonable if we
can help administrators avoid the OOM killer/resource starvation. But
we can and should expand on this idea.

Another thought is, rather than just failing the query/transaction we
have the affected backend do a clean exit, freeing all it's resources.

--
Reid Thompson
Senior Software Engineer
Crunchy Data, Inc.

reid.thompson@crunchydata.com
www.crunchydata.com

#9Stephen Frost
sfrost@snowman.net
In reply to: David Rowley (#5)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

Greetings,

* David Rowley (dgrowleyml@gmail.com) wrote:

On Thu, 1 Sept 2022 at 04:52, Reid Thompson
<reid.thompson@crunchydata.com> wrote:

Add the ability to limit the amount of memory that can be allocated to
backends.

Are you aware that relcache entries are stored in backend local memory
and that once we've added a relcache entry for a relation that we have
no current code which attempts to reduce the memory consumption used
by cache entries when there's memory pressure?

Short answer to this is yes, and that's an issue, but it isn't this
patch's problem to deal with- that's an issue that the relcache system
needs to be changed to address.

It seems to me that if we had this feature as you propose that a
backend could hit the limit and stay there just from the memory
requirements of the relation cache after some number of tables have
been accessed from the given backend. It's not hard to imagine a
situation where the palloc() would start to fail during parse, which
might make it quite infuriating for anyone trying to do something
like:

Agreed that this could happen but I don't imagine it to be super likely-
and even if it does, this is probably a better position to be in as the
backend could then be disconnected from and would then go away and its
memory free'd, unlike the current OOM-killer situation where we crash
and go through recovery. We should note this in the documentation
though, sure, so that administrators understand how this can occur and
can take action to address it.

I think a better solution to this problem would be to have "memory
grants", where we configure some amount of "pool" memory that backends
are allowed to use for queries. The planner would have to add the
expected number of work_mem that the given query is expected to use
and before that query starts, the executor would have to "checkout"
that amount of memory from the pool and return it when finished. If
there is not enough memory in the pool then the query would have to
wait until enough memory is available. This creates a deadlocking
hazard that the deadlock detector would need to be made aware of.

Sure, that also sounds great and a query acceptance system would be
wonderful. If someone is working on that with an expectation of it
landing before v16, great. Otherwise, I don't see it as relevant to
the question about if we should include this feature or not, and I'm not
even sure that we'd refuse this feature even if we already had an
acceptance system as a stop-gap should we guess wrong and not realize it
until it's too late.

Thanks,

Stephen

#10Justin Pryzby
pryzby@telsasoft.com
In reply to: Reid Thompson (#6)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On Sat, Sep 03, 2022 at 11:40:03PM -0400, Reid Thompson wrote:

+�������������� 0, 0, INT_MAX,
+�������������� NULL, NULL, NULL

I think this needs a maximum like INT_MAX/1024/1024

Is this noting that we'd set a ceiling of 2048MB?

The reason is that you're later multiplying it by 1024*1024, so you need
to limit it to avoid overflowing. Compare with
min_dynamic_shared_memory, Log_RotationSize, maintenance_work_mem,
autovacuum_work_mem.

typo: Explicitely

+ errmsg("request will exceed postgresql.conf defined max_total_backend_memory limit (%lu > %lu)",

I wouldn't mention postgresql.conf - it could be in
postgresql.auto.conf, or an include file, or a -c parameter.
Suggest: allocation would exceed max_total_backend_memory limit...

+ ereport(LOG, errmsg("decrease reduces reported backend memory allocated below zero; setting reported to 0"));

Suggest: deallocation would decrease backend memory below zero;

+ {"max_total_backend_memory", PGC_SIGHUP, RESOURCES_MEM,

Should this be PGC_SU_BACKEND to allow a superuser to set a higher
limit (or no limit)?

There's compilation warning under mingw cross compile due to
sizeof(long). See d914eb347 and other recent commits which I guess is
the current way to handle this.
http://cfbot.cputube.org/reid-thompson.html

For performance test, you'd want to check what happens with a large
number of max_connections (and maybe a large number of clients). TPS
isn't the only thing that matters. For example, a utility command might
sometimes do a lot of allocations (or deallocations), or a
"parameterized nested loop" may loop over over many outer tuples and
reset for each. There's also a lot of places that reset to a
"per-tuple" context. I started looking at its performance, but nothing
to show yet.

Would you keep people copied on your replies ("reply all") ? Otherwise
I (at least) may miss them. I think that's what's typical on these
lists (and the list tool is smart enough not to send duplicates to
people who are direct recipients).

--
Justin

#11Reid Thompson
reid.thompson@crunchydata.com
In reply to: Justin Pryzby (#10)
2 attachment(s)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On Fri, 2022-09-09 at 12:14 -0500, Justin Pryzby wrote:

On Sat, Sep 03, 2022 at 11:40:03PM -0400, Reid Thompson wrote:

+               0, 0, INT_MAX,
+               NULL, NULL, NULL

I think this needs a maximum like INT_MAX/1024/1024

Is this noting that we'd set a ceiling of 2048MB?

The reason is that you're later multiplying it by 1024*1024, so you
need
to limit it to avoid overflowing.  Compare with
min_dynamic_shared_memory, Log_RotationSize, maintenance_work_mem,
autovacuum_work_mem.

What I originally attempted to implement is:
GUC "max_total_backend_memory" max value as INT_MAX = 2147483647 MB
(2251799812636672 bytes). And the other variables and comparisons as
bytes represented as uint64 to avoid overflow.

Is this invalid?

typo: Explicitely

corrected

+                        errmsg("request will exceed postgresql.conf
defined max_total_backend_memory limit (%lu > %lu)",

I wouldn't mention postgresql.conf - it could be in
postgresql.auto.conf, or an include file, or a -c parameter.
Suggest: allocation would exceed max_total_backend_memory limit...

updated

+               ereport(LOG, errmsg("decrease reduces reported
backend memory allocated below zero; setting reported to 0"));

Suggest: deallocation would decrease backend memory below zero;

updated

+               {"max_total_backend_memory", PGC_SIGHUP,
RESOURCES_MEM,                                                       
                                                                     
                               

Should this be PGC_SU_BACKEND to allow a superuser to set a higher
limit (or no limit)?

Sounds good to me. I'll update to that.
Would PGC_SUSET be too open?

There's compilation warning under mingw cross compile due to
sizeof(long).  See d914eb347 and other recent commits which I guess
is
the current way to handle this.
http://cfbot.cputube.org/reid-thompson.html

updated %lu to %llu and changed cast from uint64 to 
unsigned long long in the ereport call

For performance test, you'd want to check what happens with a large
number of max_connections (and maybe a large number of clients).  TPS
isn't the only thing that matters.  For example, a utility command
might
sometimes do a lot of allocations (or deallocations), or a
"parameterized nested loop" may loop over over many outer tuples and
reset for each.  There's also a lot of places that reset to a
"per-tuple" context.  I started looking at its performance, but
nothing
to show yet.

Thanks

Would you keep people copied on your replies ("reply all") ? 
Otherwise
I (at least) may miss them.  I think that's what's typical on these
lists (and the list tool is smart enough not to send duplicates to
people who are direct recipients).

Ok - will do, thanks.

--
Reid Thompson
Senior Software Engineer
Crunchy Data, Inc.

reid.thompson@crunchydata.com
www.crunchydata.com

Attachments:

0001-Add-tracking-of-backend-memory-allocated-to-pg_stat_.patchtext/x-patch; charset=UTF-8; name=0001-Add-tracking-of-backend-memory-allocated-to-pg_stat_.patchDownload
From 584a04f1b53948049e73165a4ffdd544c950ab0d Mon Sep 17 00:00:00 2001
From: Reid Thompson <jreidthompson@nc.rr.com>
Date: Thu, 11 Aug 2022 12:01:25 -0400
Subject: [PATCH 1/2] Add tracking of backend memory allocated to
 pg_stat_activity

This new field displays the current bytes of memory allocated to the
backend process. It is updated as memory for the process is
malloc'd/free'd. Memory allocated to items on the freelist is included in
the displayed value.  Dynamic shared memory allocations are included
only in the value displayed for the backend that created them, they are
not included in the value for backends that are attached to them to
avoid double counting. On occasion, orphaned memory segments may be
cleaned up on postmaster startup. This may result in decreasing the sum
without a prior increment. We limit the floor of backend_mem_allocated
to zero. Updated pg_stat_activity documentation for the new column.
---
 doc/src/sgml/monitoring.sgml                |  12 +++
 src/backend/catalog/system_views.sql        |   1 +
 src/backend/storage/ipc/dsm_impl.c          |  80 +++++++++++++++
 src/backend/utils/activity/backend_status.c | 105 ++++++++++++++++++++
 src/backend/utils/adt/pgstatfuncs.c         |   4 +-
 src/backend/utils/mmgr/aset.c               |  18 ++++
 src/backend/utils/mmgr/generation.c         |  15 +++
 src/backend/utils/mmgr/slab.c               |  21 ++++
 src/include/catalog/pg_proc.dat             |   6 +-
 src/include/utils/backend_status.h          |   7 +-
 src/test/regress/expected/rules.out         |   9 +-
 11 files changed, 269 insertions(+), 9 deletions(-)

diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 1d9509a2f6..40ae638f25 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -947,6 +947,18 @@ postgres   27093  0.0  0.0  30096  2752 ?        Ss   11:34   0:00 postgres: ser
      </para></entry>
     </row>
 
+    <row>
+     <entry role="catalog_table_entry"><para role="column_definition">
+      <structfield>backend_mem_allocated</structfield> <type>bigint</type>
+     </para>
+     <para>
+      The byte count of memory allocated to this backend. Dynamic shared memory
+      allocations are included only in the value displayed for the backend that
+      created them, they are not included in the value for backends that are
+      attached to them to avoid double counting.
+     </para></entry>
+    </row>
+
      <row>
       <entry role="catalog_table_entry"><para role="column_definition">
        <structfield>query</structfield> <type>text</type>
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 5a844b63a1..d23f0e9dbb 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -863,6 +863,7 @@ CREATE VIEW pg_stat_activity AS
             S.backend_xid,
             s.backend_xmin,
             S.query_id,
+            S.backend_mem_allocated,
             S.query,
             S.backend_type
     FROM pg_stat_get_activity(NULL) AS S
diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c
index e1b90c5de4..3356bb65b5 100644
--- a/src/backend/storage/ipc/dsm_impl.c
+++ b/src/backend/storage/ipc/dsm_impl.c
@@ -66,6 +66,7 @@
 #include "postmaster/postmaster.h"
 #include "storage/dsm_impl.h"
 #include "storage/fd.h"
+#include "utils/backend_status.h"
 #include "utils/guc.h"
 #include "utils/memutils.h"
 
@@ -232,6 +233,13 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_backend_mem_allocated_decrease(*mapped_size);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && shm_unlink(name) != 0)
@@ -332,6 +340,36 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+	{
+		/*
+		 * Posix creation calls dsm_impl_posix_resize implying that resizing
+		 * occurs or may be added in the future. As implemented
+		 * dsm_impl_posix_resize utilizes fallocate or truncate, passing the
+		 * whole new size as input, growing the allocation as needed (only
+		 * truncate supports shrinking). We update by replacing the old
+		 * allocation with the new.
+		 */
+#if defined(HAVE_POSIX_FALLOCATE) && defined(__linux__)
+		/*
+		 * posix_fallocate does not shrink allocations, adjust only on
+		 * allocation increase.
+		 */
+		if (request_size > *mapped_size)
+		{
+			pgstat_report_backend_mem_allocated_decrease(*mapped_size);
+			pgstat_report_backend_mem_allocated_increase(request_size);
+		}
+#else
+		pgstat_report_backend_mem_allocated_decrease(*mapped_size);
+		pgstat_report_backend_mem_allocated_increase(request_size);
+#endif
+	}
 	*mapped_address = address;
 	*mapped_size = request_size;
 	close(fd);
@@ -537,6 +575,14 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_backend_mem_allocated_decrease(*mapped_size);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && shmctl(ident, IPC_RMID, NULL) < 0)
@@ -584,6 +630,13 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_backend_mem_allocated_increase(request_size);
 	*mapped_address = address;
 	*mapped_size = request_size;
 
@@ -652,6 +705,13 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 			return false;
 		}
 
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_backend_mem_allocated_decrease(*mapped_size);
 		*impl_private = NULL;
 		*mapped_address = NULL;
 		*mapped_size = 0;
@@ -768,6 +828,12 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 		return false;
 	}
 
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_backend_mem_allocated_increase(info.RegionSize);
 	*mapped_address = address;
 	*mapped_size = info.RegionSize;
 	*impl_private = hmap;
@@ -812,6 +878,13 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		pgstat_report_backend_mem_allocated_decrease(*mapped_size);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && unlink(name) != 0)
@@ -933,6 +1006,13 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_backend_mem_allocated_increase(request_size);
 	*mapped_address = address;
 	*mapped_size = request_size;
 
diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c
index c7ed1e6d7a..45da3af213 100644
--- a/src/backend/utils/activity/backend_status.c
+++ b/src/backend/utils/activity/backend_status.c
@@ -49,6 +49,8 @@ int			pgstat_track_activity_query_size = 1024;
 /* exposed so that backend_progress.c can access it */
 PgBackendStatus *MyBEEntry = NULL;
 
+/* Memory allocated to this backend prior to pgstats initialization */
+uint64		backend_mem_allocated = 0;
 
 static PgBackendStatus *BackendStatusArray = NULL;
 static char *BackendAppnameBuffer = NULL;
@@ -400,6 +402,13 @@ pgstat_bestart(void)
 	lbeentry.st_progress_command_target = InvalidOid;
 	lbeentry.st_query_id = UINT64CONST(0);
 
+	/*
+	 * Move sum of memory allocated prior to pgstats initialization to pgstats
+	 * and zero the local variable.
+	 */
+	lbeentry.backend_mem_allocated = backend_mem_allocated;
+	backend_mem_allocated = 0;
+
 	/*
 	 * we don't zero st_progress_param here to save cycles; nobody should
 	 * examine it until st_progress_command has been set to something other
@@ -1148,3 +1157,99 @@ pgstat_clip_activity(const char *raw_activity)
 
 	return activity;
 }
+
+/* --------
+ * pgstat_report_backend_mem_allocated_increase() -
+ *
+ * Called to report increase in memory allocated for this backend
+ * --------
+ */
+void
+pgstat_report_backend_mem_allocated_increase(uint64 allocation)
+{
+	volatile PgBackendStatus *beentry = MyBEEntry;
+
+	if (!beentry || !pgstat_track_activities)
+	{
+		/*
+		 * Account for memory before pgstats is initialized. This will be
+		 * migrated to pgstats on initialization.
+		 */
+		backend_mem_allocated += allocation;
+
+		return;
+	}
+
+	/*
+	 * Update my status entry, following the protocol of bumping
+	 * st_changecount before and after.  We use a volatile pointer here to
+	 * ensure the compiler doesn't try to get cute.
+	 */
+	PGSTAT_BEGIN_WRITE_ACTIVITY(beentry);
+	beentry->backend_mem_allocated += allocation;
+	PGSTAT_END_WRITE_ACTIVITY(beentry);
+}
+
+/* --------
+ * pgstat_report_backend_mem_allocated_decrease() -
+ *
+ * Called to report decrease in memory allocated for this backend
+ * --------
+ */
+void
+pgstat_report_backend_mem_allocated_decrease(uint64 deallocation)
+{
+	volatile PgBackendStatus *beentry = MyBEEntry;
+
+	/*
+	 * Cases may occur where shared memory from a previous postmaster
+	 * invocation still exist. These are cleaned up at startup by
+	 * dsm_cleanup_using_control_segment. Limit decreasing memory allocated to
+	 * zero in case no corresponding prior increase exists or decrease has
+	 * already been accounted for.
+	 */
+
+	if (!beentry || !pgstat_track_activities)
+	{
+		/*
+		 * Account for memory before pgstats is initialized. This will be
+		 * migrated to pgstats on initialization. Do not allow
+		 * backend_mem_allocated to go below zero. If pgstats has not been
+		 * initialized, we are in startup and we set backend_mem_allocated to
+		 * zero in cases where it would go negative and skip generating an
+		 * ereport.
+		 */
+		if (deallocation > backend_mem_allocated)
+			backend_mem_allocated = 0;
+		else
+			backend_mem_allocated -= deallocation;
+
+		return;
+	}
+
+	/*
+	 * Do not allow backend_mem_allocated to go below zero. ereport if we
+	 * would have. There's no need for a lock around the read here as it's
+	 * being referenced from the same backend which means that there shouldn't
+	 * be concurrent writes. We want to generate an ereport in these cases.
+	 */
+	if (deallocation > beentry->backend_mem_allocated)
+	{
+		ereport(LOG, errmsg("decrease reduces reported backend memory allocated below zero; setting reported to 0"));
+
+		/*
+		 * Overwrite deallocation with current backend_mem_allocated so we end
+		 * up at zero.
+		 */
+		deallocation = beentry->backend_mem_allocated;
+	}
+
+	/*
+	 * Update my status entry, following the protocol of bumping
+	 * st_changecount before and after.  We use a volatile pointer here to
+	 * ensure the compiler doesn't try to get cute.
+	 */
+	PGSTAT_BEGIN_WRITE_ACTIVITY(beentry);
+	beentry->backend_mem_allocated -= deallocation;
+	PGSTAT_END_WRITE_ACTIVITY(beentry);
+}
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 4cca30aae7..1574aa8049 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -536,7 +536,7 @@ pg_stat_get_progress_info(PG_FUNCTION_ARGS)
 Datum
 pg_stat_get_activity(PG_FUNCTION_ARGS)
 {
-#define PG_STAT_GET_ACTIVITY_COLS	30
+#define PG_STAT_GET_ACTIVITY_COLS	31
 	int			num_backends = pgstat_fetch_stat_numbackends();
 	int			curr_backend;
 	int			pid = PG_ARGISNULL(0) ? -1 : PG_GETARG_INT32(0);
@@ -610,6 +610,8 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
 		else
 			nulls[16] = true;
 
+		values[30] = UInt64GetDatum(beentry->backend_mem_allocated);
+
 		/* Values only available to role member or pg_read_all_stats */
 		if (HAS_PGSTAT_PERMISSIONS(beentry->st_userid))
 		{
diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index b6eeb8abab..c91f8efa4d 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -47,6 +47,7 @@
 #include "postgres.h"
 
 #include "port/pg_bitutils.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -509,6 +510,7 @@ AllocSetContextCreateInternal(MemoryContext parent,
 						name);
 
 	((MemoryContext) set)->mem_allocated = firstBlockSize;
+	pgstat_report_backend_mem_allocated_increase(firstBlockSize);
 
 	return (MemoryContext) set;
 }
@@ -532,6 +534,7 @@ AllocSetReset(MemoryContext context)
 	AllocBlock	block;
 	Size		keepersize PG_USED_FOR_ASSERTS_ONLY
 	= set->keeper->endptr - ((char *) set);
+	uint64		deallocation = 0;
 
 	AssertArg(AllocSetIsValid(set));
 
@@ -571,6 +574,7 @@ AllocSetReset(MemoryContext context)
 		{
 			/* Normal case, release the block */
 			context->mem_allocated -= block->endptr - ((char *) block);
+			deallocation += block->endptr - ((char *) block);
 
 #ifdef CLOBBER_FREED_MEMORY
 			wipe_mem(block, block->freeptr - ((char *) block));
@@ -581,6 +585,7 @@ AllocSetReset(MemoryContext context)
 	}
 
 	Assert(context->mem_allocated == keepersize);
+	pgstat_report_backend_mem_allocated_decrease(deallocation);
 
 	/* Reset block size allocation sequence, too */
 	set->nextBlockSize = set->initBlockSize;
@@ -600,6 +605,7 @@ AllocSetDelete(MemoryContext context)
 	AllocBlock	block = set->blocks;
 	Size		keepersize PG_USED_FOR_ASSERTS_ONLY
 	= set->keeper->endptr - ((char *) set);
+	uint64		deallocation = 0;
 
 	AssertArg(AllocSetIsValid(set));
 
@@ -635,11 +641,13 @@ AllocSetDelete(MemoryContext context)
 
 				freelist->first_free = (AllocSetContext *) oldset->header.nextchild;
 				freelist->num_free--;
+				deallocation += oldset->header.mem_allocated;
 
 				/* All that remains is to free the header/initial block */
 				free(oldset);
 			}
 			Assert(freelist->num_free == 0);
+			pgstat_report_backend_mem_allocated_decrease(deallocation);
 		}
 
 		/* Now add the just-deleted context to the freelist. */
@@ -656,7 +664,10 @@ AllocSetDelete(MemoryContext context)
 		AllocBlock	next = block->next;
 
 		if (block != set->keeper)
+		{
 			context->mem_allocated -= block->endptr - ((char *) block);
+			deallocation += block->endptr - ((char *) block);
+		}
 
 #ifdef CLOBBER_FREED_MEMORY
 		wipe_mem(block, block->freeptr - ((char *) block));
@@ -669,6 +680,8 @@ AllocSetDelete(MemoryContext context)
 	}
 
 	Assert(context->mem_allocated == keepersize);
+	pgstat_report_backend_mem_allocated_decrease(deallocation +
+												 context->mem_allocated);
 
 	/* Finally, free the context header, including the keeper block */
 	free(set);
@@ -712,6 +725,7 @@ AllocSetAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_backend_mem_allocated_increase(blksize);
 
 		block->aset = set;
 		block->freeptr = block->endptr = ((char *) block) + blksize;
@@ -916,6 +930,7 @@ AllocSetAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_backend_mem_allocated_increase(blksize);
 
 		block->aset = set;
 		block->freeptr = ((char *) block) + ALLOC_BLOCKHDRSZ;
@@ -1016,6 +1031,7 @@ AllocSetFree(void *pointer)
 			block->next->prev = block->prev;
 
 		set->header.mem_allocated -= block->endptr - ((char *) block);
+		pgstat_report_backend_mem_allocated_decrease(block->endptr - ((char *) block));
 
 #ifdef CLOBBER_FREED_MEMORY
 		wipe_mem(block, block->freeptr - ((char *) block));
@@ -1127,7 +1143,9 @@ AllocSetRealloc(void *pointer, Size size)
 
 		/* updated separately, not to underflow when (oldblksize > blksize) */
 		set->header.mem_allocated -= oldblksize;
+		pgstat_report_backend_mem_allocated_decrease(oldblksize);
 		set->header.mem_allocated += blksize;
+		pgstat_report_backend_mem_allocated_increase(blksize);
 
 		block->freeptr = block->endptr = ((char *) block) + blksize;
 
diff --git a/src/backend/utils/mmgr/generation.c b/src/backend/utils/mmgr/generation.c
index b39894ec94..36e5b3f94d 100644
--- a/src/backend/utils/mmgr/generation.c
+++ b/src/backend/utils/mmgr/generation.c
@@ -37,6 +37,7 @@
 
 #include "lib/ilist.h"
 #include "port/pg_bitutils.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -258,6 +259,7 @@ GenerationContextCreate(MemoryContext parent,
 						name);
 
 	((MemoryContext) set)->mem_allocated = firstBlockSize;
+	pgstat_report_backend_mem_allocated_increase(firstBlockSize);
 
 	return (MemoryContext) set;
 }
@@ -274,6 +276,7 @@ GenerationReset(MemoryContext context)
 {
 	GenerationContext *set = (GenerationContext *) context;
 	dlist_mutable_iter miter;
+	uint64	deallocation = 0;
 
 	AssertArg(GenerationIsValid(set));
 
@@ -296,9 +299,14 @@ GenerationReset(MemoryContext context)
 		if (block == set->keeper)
 			GenerationBlockMarkEmpty(block);
 		else
+		{
+			deallocation += block->blksize;
 			GenerationBlockFree(set, block);
+		}
 	}
 
+	pgstat_report_backend_mem_allocated_decrease(deallocation);
+
 	/* set it so new allocations to make use of the keeper block */
 	set->block = set->keeper;
 
@@ -319,6 +327,9 @@ GenerationDelete(MemoryContext context)
 {
 	/* Reset to release all releasable GenerationBlocks */
 	GenerationReset(context);
+
+	pgstat_report_backend_mem_allocated_decrease(context->mem_allocated);
+
 	/* And free the context header and keeper block */
 	free(context);
 }
@@ -355,6 +366,7 @@ GenerationAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_backend_mem_allocated_increase(blksize);
 
 		/* block with a single (used) chunk */
 		block->context = set;
@@ -458,6 +470,7 @@ GenerationAlloc(MemoryContext context, Size size)
 				return NULL;
 
 			context->mem_allocated += blksize;
+			pgstat_report_backend_mem_allocated_increase(blksize);
 
 			/* initialize the new block */
 			GenerationBlockInit(set, block, blksize);
@@ -691,6 +704,8 @@ GenerationFree(void *pointer)
 	dlist_delete(&block->node);
 
 	set->header.mem_allocated -= block->blksize;
+	pgstat_report_backend_mem_allocated_decrease(block->blksize);
+
 	free(block);
 }
 
diff --git a/src/backend/utils/mmgr/slab.c b/src/backend/utils/mmgr/slab.c
index 2d70adef09..e0e69b394e 100644
--- a/src/backend/utils/mmgr/slab.c
+++ b/src/backend/utils/mmgr/slab.c
@@ -53,6 +53,7 @@
 #include "postgres.h"
 
 #include "lib/ilist.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -218,6 +219,12 @@ SlabContextCreate(MemoryContext parent,
 						parent,
 						name);
 
+	/*
+	 * If SlabContextCreate is updated to add headerSize to
+	 * context->mem_allocated, then update here and SlabDelete appropriately
+	 */
+	pgstat_report_backend_mem_allocated_increase(headerSize);
+
 	return (MemoryContext) slab;
 }
 
@@ -233,6 +240,7 @@ SlabReset(MemoryContext context)
 {
 	int			i;
 	SlabContext *slab = castNode(SlabContext, context);
+	uint64		deallocation = 0;
 
 	Assert(slab);
 
@@ -258,9 +266,11 @@ SlabReset(MemoryContext context)
 			free(block);
 			slab->nblocks--;
 			context->mem_allocated -= slab->blockSize;
+			deallocation += slab->blockSize;
 		}
 	}
 
+	pgstat_report_backend_mem_allocated_decrease(deallocation);
 	slab->minFreeChunks = 0;
 
 	Assert(slab->nblocks == 0);
@@ -274,8 +284,17 @@ SlabReset(MemoryContext context)
 void
 SlabDelete(MemoryContext context)
 {
+	/*
+	 * Until header allocation is included in context->mem_allocated, cast to
+	 * slab and decrement the headerSize
+	 */
+	SlabContext *slab = castNode(SlabContext, context);
+
 	/* Reset to release all the SlabBlocks */
 	SlabReset(context);
+
+	pgstat_report_backend_mem_allocated_decrease(slab->headerSize);
+
 	/* And free the context header */
 	free(context);
 }
@@ -344,6 +363,7 @@ SlabAlloc(MemoryContext context, Size size)
 		slab->minFreeChunks = slab->chunksPerBlock;
 		slab->nblocks += 1;
 		context->mem_allocated += slab->blockSize;
+		pgstat_report_backend_mem_allocated_increase(slab->blockSize);
 	}
 
 	/* grab the block from the freelist (even the new block is there) */
@@ -511,6 +531,7 @@ SlabFree(void *pointer)
 		free(block);
 		slab->nblocks--;
 		slab->header.mem_allocated -= slab->blockSize;
+		pgstat_report_backend_mem_allocated_decrease(slab->blockSize);
 	}
 	else
 		dlist_push_head(&slab->freelist[block->nfree], &block->node);
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index be47583122..e1bfb85b25 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -5340,9 +5340,9 @@
   proname => 'pg_stat_get_activity', prorows => '100', proisstrict => 'f',
   proretset => 't', provolatile => 's', proparallel => 'r',
   prorettype => 'record', proargtypes => 'int4',
-  proallargtypes => '{int4,oid,int4,oid,text,text,text,text,text,timestamptz,timestamptz,timestamptz,timestamptz,inet,text,int4,xid,xid,text,bool,text,text,int4,text,numeric,text,bool,text,bool,int4,int8}',
-  proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
-  proargnames => '{pid,datid,pid,usesysid,application_name,state,query,wait_event_type,wait_event,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,backend_type,ssl,sslversion,sslcipher,sslbits,ssl_client_dn,ssl_client_serial,ssl_issuer_dn,gss_auth,gss_princ,gss_enc,leader_pid,query_id}',
+  proallargtypes => '{int4,oid,int4,oid,text,text,text,text,text,timestamptz,timestamptz,timestamptz,timestamptz,inet,text,int4,xid,xid,text,bool,text,text,int4,text,numeric,text,bool,text,bool,int4,int8,int8}',
+  proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
+  proargnames => '{pid,datid,pid,usesysid,application_name,state,query,wait_event_type,wait_event,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,backend_type,ssl,sslversion,sslcipher,sslbits,ssl_client_dn,ssl_client_serial,ssl_issuer_dn,gss_auth,gss_princ,gss_enc,leader_pid,query_id,backend_mem_allocated}',
   prosrc => 'pg_stat_get_activity' },
 { oid => '3318',
   descr => 'statistics: information about progress of backends running maintenance command',
diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h
index 7403bca25e..9bdc4197bd 100644
--- a/src/include/utils/backend_status.h
+++ b/src/include/utils/backend_status.h
@@ -168,6 +168,9 @@ typedef struct PgBackendStatus
 
 	/* query identifier, optionally computed using post_parse_analyze_hook */
 	uint64		st_query_id;
+
+	/* Current memory allocated to this backend */
+	uint64		backend_mem_allocated;
 } PgBackendStatus;
 
 
@@ -305,7 +308,9 @@ extern const char *pgstat_get_backend_current_activity(int pid, bool checkUser);
 extern const char *pgstat_get_crashed_backend_activity(int pid, char *buffer,
 													   int buflen);
 extern uint64 pgstat_get_my_query_id(void);
-
+extern void pgstat_report_backend_mem_allocated_increase(uint64 allocation);
+extern void pgstat_report_backend_mem_allocated_decrease(uint64 deallocation);
+extern uint64 pgstat_get_all_backend_memory_allocated(void);
 
 /* ----------
  * Support functions for the SQL-callable functions to
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index 7ec3d2688f..674e5c6fe7 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1757,9 +1757,10 @@ pg_stat_activity| SELECT s.datid,
     s.backend_xid,
     s.backend_xmin,
     s.query_id,
+    s.backend_mem_allocated,
     s.query,
     s.backend_type
-   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, backend_mem_allocated)
      LEFT JOIN pg_database d ON ((s.datid = d.oid)))
      LEFT JOIN pg_authid u ON ((s.usesysid = u.oid)));
 pg_stat_all_indexes| SELECT c.oid AS relid,
@@ -1871,7 +1872,7 @@ pg_stat_gssapi| SELECT s.pid,
     s.gss_auth AS gss_authenticated,
     s.gss_princ AS principal,
     s.gss_enc AS encrypted
-   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, backend_mem_allocated)
   WHERE (s.client_port IS NOT NULL);
 pg_stat_progress_analyze| SELECT s.pid,
     s.datid,
@@ -2052,7 +2053,7 @@ pg_stat_replication| SELECT s.pid,
     w.sync_priority,
     w.sync_state,
     w.reply_time
-   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, backend_mem_allocated)
      JOIN pg_stat_get_wal_senders() w(pid, state, sent_lsn, write_lsn, flush_lsn, replay_lsn, write_lag, flush_lag, replay_lag, sync_priority, sync_state, reply_time) ON ((s.pid = w.pid)))
      LEFT JOIN pg_authid u ON ((s.usesysid = u.oid)));
 pg_stat_replication_slots| SELECT s.slot_name,
@@ -2086,7 +2087,7 @@ pg_stat_ssl| SELECT s.pid,
     s.ssl_client_dn AS client_dn,
     s.ssl_client_serial AS client_serial,
     s.ssl_issuer_dn AS issuer_dn
-   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, backend_mem_allocated)
   WHERE (s.client_port IS NOT NULL);
 pg_stat_subscription| SELECT su.oid AS subid,
     su.subname,
-- 
2.25.1

0002-Add-the-ability-to-limit-the-amount-of-memory-that-c.patchtext/x-patch; charset=UTF-8; name=0002-Add-the-ability-to-limit-the-amount-of-memory-that-c.patchDownload
From 23d33838e3780ef02daad2bc737290d9905745a7 Mon Sep 17 00:00:00 2001
From: Reid Thompson <jreidthompson@nc.rr.com>
Date: Sat, 4 Jun 2022 22:23:59 -0400
Subject: [PATCH 2/2] Add the ability to limit the amount of memory that can be
 allocated to backends.

This builds on the work that adds backend memory allocated to pg_stat_activity.

Add GUC variable max_total_backend_memory.

Specifies a limit to the amount of memory (in MB) that may be allocated to
backends in total (i.e. this is not a per user or per backend limit). If unset,
or set to 0 it is disabled. It is intended as a resource to help avoid the OOM
killer on LINUX and manage resources in general. A backend request that would
push the total over the limit will be denied with an out of memory error causing
that backend's current query/transaction to fail. Due to the dynamic nature of
memory allocations, this limit is not exact. If within 1.5MB of the limit and
two backends request 1MB each at the same time both may be allocated, and exceed
the limit. Further requests will not be allocated until dropping below the
limit. Keep this in mind when setting this value. This limit does not affect
auxiliary backend processes. Backend memory allocations are displayed in the
pg_stat_activity view.
---
 doc/src/sgml/config.sgml                      |  26 +++++
 src/backend/storage/ipc/dsm_impl.c            |  12 ++
 src/backend/utils/activity/backend_status.c   | 109 +++++++++++++++++-
 src/backend/utils/misc/guc.c                  |  11 ++
 src/backend/utils/misc/postgresql.conf.sample |   3 +
 src/backend/utils/mmgr/aset.c                 |  17 +++
 src/backend/utils/mmgr/generation.c           |   9 ++
 src/backend/utils/mmgr/slab.c                 |   8 ++
 src/include/utils/backend_status.h            |   2 +
 9 files changed, 196 insertions(+), 1 deletion(-)

diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index a5cd4e44c7..e70ea71ba1 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -2079,6 +2079,32 @@ include_dir 'conf.d'
       </listitem>
      </varlistentry>
 
+     <varlistentry id="guc-max-total-backend-memory" xreflabel="max_total_backend_memory">
+      <term><varname>max_total_backend_memory</varname> (<type>integer</type>)
+      <indexterm>
+       <primary><varname>max_total_backend_memory</varname> configuration parameter</primary>
+      </indexterm>
+      </term>
+      <listitem>
+       <para>
+        Specifies a limit to the amount of memory (MB) that may be allocated to
+        backends in total (i.e. this is not a per user or per backend limit).
+        If unset, or set to 0 it is disabled.  A backend request that would
+        push the total over the limit will be denied with an out of memory
+        error causing that backend's current query/transaction to fail. Due to
+        the dynamic nature of memory allocations, this limit is not exact. If
+        within 1.5MB of the limit and two backends request 1MB each at the same
+        time both may be allocated, and exceed the limit. Further requests will
+        not be allocated until dropping below the limit. Keep this in mind when
+        setting this value. This limit does not affect auxiliary backend
+        processes <xref linkend="glossary-auxiliary-proc"/> . Backend memory
+        allocations (<varname>backend_mem_allocated</varname>) are displayed in
+        the <link linkend="monitoring-pg-stat-activity-view"><structname>pg_stat_activity</structname></link>
+        view.
+       </para>
+      </listitem>
+     </varlistentry>
+
      </variablelist>
      </sect2>
 
diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c
index 3356bb65b5..cc061056a3 100644
--- a/src/backend/storage/ipc/dsm_impl.c
+++ b/src/backend/storage/ipc/dsm_impl.c
@@ -253,6 +253,10 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 		return true;
 	}
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+		return false;
+
 	/*
 	 * Create new segment or open an existing one for attach.
 	 *
@@ -524,6 +528,10 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 		int			flags = IPCProtection;
 		size_t		segsize;
 
+		/* Do not exceed maximum allowed memory allocation */
+		if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+			return false;
+
 		/*
 		 * Allocate the memory BEFORE acquiring the resource, so that we don't
 		 * leak the resource if memory allocation fails.
@@ -718,6 +726,10 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 		return true;
 	}
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+		return false;
+
 	/* Create new segment or open an existing one for attach. */
 	if (op == DSM_OP_CREATE)
 	{
diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c
index 45da3af213..9c2fc2f07c 100644
--- a/src/backend/utils/activity/backend_status.c
+++ b/src/backend/utils/activity/backend_status.c
@@ -44,6 +44,8 @@
  */
 bool		pgstat_track_activities = false;
 int			pgstat_track_activity_query_size = 1024;
+/* Max backend memory allocation allowed (MB). 0 = disabled */
+int			max_total_bkend_mem = 0;
 
 
 /* exposed so that backend_progress.c can access it */
@@ -1235,7 +1237,7 @@ pgstat_report_backend_mem_allocated_decrease(uint64 deallocation)
 	 */
 	if (deallocation > beentry->backend_mem_allocated)
 	{
-		ereport(LOG, errmsg("decrease reduces reported backend memory allocated below zero; setting reported to 0"));
+		ereport(LOG, errmsg("deallocation would decrease backend memory below zero; setting reported to 0"));
 
 		/*
 		 * Overwrite deallocation with current backend_mem_allocated so we end
@@ -1253,3 +1255,108 @@ pgstat_report_backend_mem_allocated_decrease(uint64 deallocation)
 	beentry->backend_mem_allocated -= deallocation;
 	PGSTAT_END_WRITE_ACTIVITY(beentry);
 }
+
+/* ----------
+ * pgstat_get_all_backend_memory_allocated() -
+ *
+ *	Return a uint64 representing the current shared memory allocated to all
+ *	backends.  This looks directly at the BackendStatusArray, and so will
+ *	provide current information regardless of the age of our transaction's
+ *	snapshot of the status array.
+ *	In the future we will likely utilize additional values - perhaps limit
+ *	backend allocation by user/role, etc.
+ * ----------
+ */
+uint64
+pgstat_get_all_backend_memory_allocated(void)
+{
+	PgBackendStatus *beentry;
+	int			i;
+	uint64		all_backend_memory_allocated = 0;
+
+	beentry = BackendStatusArray;
+
+	/*
+	 * We probably shouldn't get here before shared memory has been set up,
+	 * but be safe.
+	 */
+	if (beentry == NULL || BackendActivityBuffer == NULL)
+		return 0;
+
+	/*
+	 * We include AUX procs in all backend memory calculation
+	 */
+	for (i = 1; i <= NumBackendStatSlots; i++)
+	{
+		/*
+		 * We use a volatile pointer here to ensure the compiler doesn't try to
+		 * get cute.
+		 */
+		volatile PgBackendStatus *vbeentry = beentry;
+		bool		found;
+		uint64		backend_mem_allocated = 0;
+
+		for (;;)
+		{
+			int			before_changecount;
+			int			after_changecount;
+
+			pgstat_begin_read_activity(vbeentry, before_changecount);
+
+			/* Ignore invalid entries, which may contain invalid data.
+			 * See pgstat_beshutdown_hook()
+			 */
+			if (vbeentry->st_procpid > 0)
+				backend_mem_allocated = vbeentry->backend_mem_allocated;
+
+			pgstat_end_read_activity(vbeentry, after_changecount);
+
+			if ((found = pgstat_read_activity_complete(before_changecount,
+													   after_changecount)))
+				break;
+
+			/* Make sure we can break out of loop if stuck... */
+			CHECK_FOR_INTERRUPTS();
+		}
+
+		if (found)
+			all_backend_memory_allocated += backend_mem_allocated;
+
+		beentry++;
+	}
+
+	return all_backend_memory_allocated;
+}
+
+/*
+ * Determine if allocation request will exceed max backend memory allowed.
+ * Do not apply to auxiliary processes.
+ */
+bool
+exceeds_max_total_bkend_mem(uint64 allocation_request)
+{
+	bool result = false;
+
+	/* Exclude auxiliary processes from the check */
+	if (MyAuxProcType != NotAnAuxProcess)
+		return result;
+
+	/* Convert max_total_bkend_mem to bytes for comparison */
+	if (max_total_bkend_mem &&
+		pgstat_get_all_backend_memory_allocated() +
+		allocation_request > (uint64)max_total_bkend_mem * 1024 * 1024)
+	{
+		/*
+		 * Explicitly identify the OOM being a result of this configuration
+		 * parameter vs a system failure to allocate OOM.
+		 */
+		ereport(WARNING,
+			 errmsg("allocation would exceed max_total_backend_memory limit (%llu > %llu)",
+			 (unsigned long long)pgstat_get_all_backend_memory_allocated() +
+			 allocation_request, (unsigned long long)max_total_bkend_mem * 1024 * 1024));
+
+		result = true;
+	}
+
+	return result;
+}
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 9fbbfb1be5..4e256a77d5 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -3664,6 +3664,17 @@ static struct config_int ConfigureNamesInt[] =
 		NULL, NULL, NULL
 	},
 
+	{
+		{"max_total_backend_memory", PGC_SU_BACKEND, RESOURCES_MEM,
+			gettext_noop("Restrict total backend memory allocations to this max."),
+			gettext_noop("0 turns this feature off."),
+			GUC_UNIT_MB
+		},
+		&max_total_bkend_mem,
+		0, 0, INT_MAX,
+		NULL, NULL, NULL
+	},
+
 	/* End-of-list marker */
 	{
 		{NULL, 0, 0, NULL, NULL}, NULL, 0, 0, 0, NULL, NULL, NULL
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 90bec0502c..8e944f6511 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -155,6 +155,9 @@
 					#   mmap
 					# (change requires restart)
 #min_dynamic_shared_memory = 0MB	# (change requires restart)
+#max_total_backend_memory = 0MB		# Restrict total backend memory allocations
+									# to this max (in MB). 0 turns this feature
+									# off.
 
 # - Disk -
 
diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index c91f8efa4d..ac9a1ced3f 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -428,6 +428,10 @@ AllocSetContextCreateInternal(MemoryContext parent,
 	else
 		firstBlockSize = Max(firstBlockSize, initBlockSize);
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (exceeds_max_total_bkend_mem(firstBlockSize))
+		return NULL;
+
 	/*
 	 * Allocate the initial block.  Unlike other aset.c blocks, it starts with
 	 * the context header and its block header follows that.
@@ -720,6 +724,11 @@ AllocSetAlloc(MemoryContext context, Size size)
 	{
 		chunk_size = MAXALIGN(size);
 		blksize = chunk_size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
+
+		/* Do not exceed maximum allowed memory allocation */
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		block = (AllocBlock) malloc(blksize);
 		if (block == NULL)
 			return NULL;
@@ -911,6 +920,10 @@ AllocSetAlloc(MemoryContext context, Size size)
 		while (blksize < required_size)
 			blksize <<= 1;
 
+		/* Do not exceed maximum allowed memory allocation */
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		/* Try to allocate it */
 		block = (AllocBlock) malloc(blksize);
 
@@ -1133,6 +1146,10 @@ AllocSetRealloc(void *pointer, Size size)
 		blksize = chksize + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
 		oldblksize = block->endptr - ((char *) block);
 
+		/* Do not exceed maximum allowed memory allocation */
+		if (blksize > oldblksize && exceeds_max_total_bkend_mem(blksize - oldblksize))
+			return NULL;
+
 		block = (AllocBlock) realloc(block, blksize);
 		if (block == NULL)
 		{
diff --git a/src/backend/utils/mmgr/generation.c b/src/backend/utils/mmgr/generation.c
index 36e5b3f94d..1d5720836c 100644
--- a/src/backend/utils/mmgr/generation.c
+++ b/src/backend/utils/mmgr/generation.c
@@ -192,6 +192,9 @@ GenerationContextCreate(MemoryContext parent,
 	else
 		allocSize = Max(allocSize, initBlockSize);
 
+	if (exceeds_max_total_bkend_mem(allocSize))
+		return NULL;
+
 	/*
 	 * Allocate the initial block.  Unlike other generation.c blocks, it
 	 * starts with the context header and its block header follows that.
@@ -361,6 +364,9 @@ GenerationAlloc(MemoryContext context, Size size)
 	{
 		Size		blksize = required_size + Generation_BLOCKHDRSZ;
 
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		block = (GenerationBlock *) malloc(blksize);
 		if (block == NULL)
 			return NULL;
@@ -464,6 +470,9 @@ GenerationAlloc(MemoryContext context, Size size)
 			if (blksize < required_size)
 				blksize = pg_nextpower2_size_t(required_size);
 
+			if (exceeds_max_total_bkend_mem(blksize))
+				return NULL;
+
 			block = (GenerationBlock *) malloc(blksize);
 
 			if (block == NULL)
diff --git a/src/backend/utils/mmgr/slab.c b/src/backend/utils/mmgr/slab.c
index e0e69b394e..63c07120dd 100644
--- a/src/backend/utils/mmgr/slab.c
+++ b/src/backend/utils/mmgr/slab.c
@@ -177,6 +177,10 @@ SlabContextCreate(MemoryContext parent,
 	headerSize += chunksPerBlock * sizeof(bool);
 #endif
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (exceeds_max_total_bkend_mem(headerSize))
+		return NULL;
+
 	slab = (SlabContext *) malloc(headerSize);
 	if (slab == NULL)
 	{
@@ -331,6 +335,10 @@ SlabAlloc(MemoryContext context, Size size)
 	 */
 	if (slab->minFreeChunks == 0)
 	{
+		/* Do not exceed maximum allowed memory allocation */
+		if (exceeds_max_total_bkend_mem(slab->blockSize))
+			return NULL;
+
 		block = (SlabBlock *) malloc(slab->blockSize);
 
 		if (block == NULL)
diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h
index 9bdc4197bd..3b940ff98e 100644
--- a/src/include/utils/backend_status.h
+++ b/src/include/utils/backend_status.h
@@ -270,6 +270,7 @@ typedef struct LocalPgBackendStatus
  */
 extern PGDLLIMPORT bool pgstat_track_activities;
 extern PGDLLIMPORT int pgstat_track_activity_query_size;
+extern PGDLLIMPORT int max_total_bkend_mem;
 
 
 /* ----------
@@ -321,6 +322,7 @@ extern int	pgstat_fetch_stat_numbackends(void);
 extern PgBackendStatus *pgstat_fetch_stat_beentry(int beid);
 extern LocalPgBackendStatus *pgstat_fetch_stat_local_beentry(int beid);
 extern char *pgstat_clip_activity(const char *raw_activity);
+extern bool exceeds_max_total_bkend_mem(uint64 allocation_request);
 
 
 #endif							/* BACKEND_STATUS_H */
-- 
2.25.1

#12Ibrar Ahmed
ibrar.ahmad@gmail.com
In reply to: Reid Thompson (#11)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On Mon, Sep 12, 2022 at 8:30 PM Reid Thompson <reid.thompson@crunchydata.com>
wrote:

On Fri, 2022-09-09 at 12:14 -0500, Justin Pryzby wrote:

On Sat, Sep 03, 2022 at 11:40:03PM -0400, Reid Thompson wrote:

+ 0, 0, INT_MAX,
+ NULL, NULL, NULL

I think this needs a maximum like INT_MAX/1024/1024

Is this noting that we'd set a ceiling of 2048MB?

The reason is that you're later multiplying it by 1024*1024, so you
need
to limit it to avoid overflowing. Compare with
min_dynamic_shared_memory, Log_RotationSize, maintenance_work_mem,
autovacuum_work_mem.

What I originally attempted to implement is:
GUC "max_total_backend_memory" max value as INT_MAX = 2147483647 MB
(2251799812636672 bytes). And the other variables and comparisons as
bytes represented as uint64 to avoid overflow.

Is this invalid?

typo: Explicitely

corrected

+ errmsg("request will exceed postgresql.conf
defined max_total_backend_memory limit (%lu > %lu)",

I wouldn't mention postgresql.conf - it could be in
postgresql.auto.conf, or an include file, or a -c parameter.
Suggest: allocation would exceed max_total_backend_memory limit...

updated

+ ereport(LOG, errmsg("decrease reduces reported
backend memory allocated below zero; setting reported to 0"));

Suggest: deallocation would decrease backend memory below zero;

updated

+ {"max_total_backend_memory", PGC_SIGHUP,
RESOURCES_MEM,

Should this be PGC_SU_BACKEND to allow a superuser to set a higher
limit (or no limit)?

Sounds good to me. I'll update to that.
Would PGC_SUSET be too open?

There's compilation warning under mingw cross compile due to
sizeof(long). See d914eb347 and other recent commits which I guess
is
the current way to handle this.
http://cfbot.cputube.org/reid-thompson.html

updated %lu to %llu and changed cast from uint64 to
unsigned long long in the ereport call

For performance test, you'd want to check what happens with a large
number of max_connections (and maybe a large number of clients). TPS
isn't the only thing that matters. For example, a utility command
might
sometimes do a lot of allocations (or deallocations), or a
"parameterized nested loop" may loop over over many outer tuples and
reset for each. There's also a lot of places that reset to a
"per-tuple" context. I started looking at its performance, but
nothing
to show yet.

Thanks

Would you keep people copied on your replies ("reply all") ?
Otherwise
I (at least) may miss them. I think that's what's typical on these
lists (and the list tool is smart enough not to send duplicates to
people who are direct recipients).

Ok - will do, thanks.

--
Reid Thompson
Senior Software Engineer
Crunchy Data, Inc.

reid.thompson@crunchydata.com
www.crunchydata.com

The patch does not apply; please rebase the patch.

patching file src/backend/utils/misc/guc.c
Hunk #1 FAILED at 3664.
1 out of 1 hunk FAILED -- saving rejects to file
src/backend/utils/misc/guc.c.rej

patching file src/backend/utils/misc/postgresql.conf.sample

--
Ibrar Ahmed

#13Reid Thompson
reid.thompson@crunchydata.com
In reply to: Ibrar Ahmed (#12)
2 attachment(s)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On Thu, 2022-09-15 at 12:07 +0400, Ibrar Ahmed wrote:

The patch does not apply; please rebase the patch.

patching file src/backend/utils/misc/guc.c
Hunk #1 FAILED at 3664.
1 out of 1 hunk FAILED -- saving rejects to file
src/backend/utils/misc/guc.c.rej 

patching file src/backend/utils/misc/postgresql.conf.sample

rebased patches attached.

Thanks,
Reid

Attachments:

0001-Add-tracking-of-backend-memory-allocated-to-pg_stat_.patchtext/x-patch; charset=UTF-8; name=0001-Add-tracking-of-backend-memory-allocated-to-pg_stat_.patchDownload
From 0e7010c53508d5a396edd16fd9166abe431f5dbe Mon Sep 17 00:00:00 2001
From: Reid Thompson <jreidthompson@nc.rr.com>
Date: Thu, 11 Aug 2022 12:01:25 -0400
Subject: [PATCH 1/2] Add tracking of backend memory allocated to
 pg_stat_activity

This new field displays the current bytes of memory allocated to the
backend process. It is updated as memory for the process is
malloc'd/free'd. Memory allocated to items on the freelist is included in
the displayed value.  Dynamic shared memory allocations are included
only in the value displayed for the backend that created them, they are
not included in the value for backends that are attached to them to
avoid double counting. On occasion, orphaned memory segments may be
cleaned up on postmaster startup. This may result in decreasing the sum
without a prior increment. We limit the floor of backend_mem_allocated
to zero. Updated pg_stat_activity documentation for the new column.
---
 doc/src/sgml/monitoring.sgml                |  12 +++
 src/backend/catalog/system_views.sql        |   1 +
 src/backend/storage/ipc/dsm_impl.c          |  80 +++++++++++++++
 src/backend/utils/activity/backend_status.c | 105 ++++++++++++++++++++
 src/backend/utils/adt/pgstatfuncs.c         |   4 +-
 src/backend/utils/mmgr/aset.c               |  18 ++++
 src/backend/utils/mmgr/generation.c         |  15 +++
 src/backend/utils/mmgr/slab.c               |  21 ++++
 src/include/catalog/pg_proc.dat             |   6 +-
 src/include/utils/backend_status.h          |   7 +-
 src/test/regress/expected/rules.out         |   9 +-
 11 files changed, 269 insertions(+), 9 deletions(-)

diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 1d9509a2f6..40ae638f25 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -947,6 +947,18 @@ postgres   27093  0.0  0.0  30096  2752 ?        Ss   11:34   0:00 postgres: ser
      </para></entry>
     </row>
 
+    <row>
+     <entry role="catalog_table_entry"><para role="column_definition">
+      <structfield>backend_mem_allocated</structfield> <type>bigint</type>
+     </para>
+     <para>
+      The byte count of memory allocated to this backend. Dynamic shared memory
+      allocations are included only in the value displayed for the backend that
+      created them, they are not included in the value for backends that are
+      attached to them to avoid double counting.
+     </para></entry>
+    </row>
+
      <row>
       <entry role="catalog_table_entry"><para role="column_definition">
        <structfield>query</structfield> <type>text</type>
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 55f7ec79e0..a78750ab12 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -862,6 +862,7 @@ CREATE VIEW pg_stat_activity AS
             S.backend_xid,
             s.backend_xmin,
             S.query_id,
+            S.backend_mem_allocated,
             S.query,
             S.backend_type
     FROM pg_stat_get_activity(NULL) AS S
diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c
index e1b90c5de4..3356bb65b5 100644
--- a/src/backend/storage/ipc/dsm_impl.c
+++ b/src/backend/storage/ipc/dsm_impl.c
@@ -66,6 +66,7 @@
 #include "postmaster/postmaster.h"
 #include "storage/dsm_impl.h"
 #include "storage/fd.h"
+#include "utils/backend_status.h"
 #include "utils/guc.h"
 #include "utils/memutils.h"
 
@@ -232,6 +233,13 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_backend_mem_allocated_decrease(*mapped_size);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && shm_unlink(name) != 0)
@@ -332,6 +340,36 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+	{
+		/*
+		 * Posix creation calls dsm_impl_posix_resize implying that resizing
+		 * occurs or may be added in the future. As implemented
+		 * dsm_impl_posix_resize utilizes fallocate or truncate, passing the
+		 * whole new size as input, growing the allocation as needed (only
+		 * truncate supports shrinking). We update by replacing the old
+		 * allocation with the new.
+		 */
+#if defined(HAVE_POSIX_FALLOCATE) && defined(__linux__)
+		/*
+		 * posix_fallocate does not shrink allocations, adjust only on
+		 * allocation increase.
+		 */
+		if (request_size > *mapped_size)
+		{
+			pgstat_report_backend_mem_allocated_decrease(*mapped_size);
+			pgstat_report_backend_mem_allocated_increase(request_size);
+		}
+#else
+		pgstat_report_backend_mem_allocated_decrease(*mapped_size);
+		pgstat_report_backend_mem_allocated_increase(request_size);
+#endif
+	}
 	*mapped_address = address;
 	*mapped_size = request_size;
 	close(fd);
@@ -537,6 +575,14 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_backend_mem_allocated_decrease(*mapped_size);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && shmctl(ident, IPC_RMID, NULL) < 0)
@@ -584,6 +630,13 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_backend_mem_allocated_increase(request_size);
 	*mapped_address = address;
 	*mapped_size = request_size;
 
@@ -652,6 +705,13 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 			return false;
 		}
 
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_backend_mem_allocated_decrease(*mapped_size);
 		*impl_private = NULL;
 		*mapped_address = NULL;
 		*mapped_size = 0;
@@ -768,6 +828,12 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 		return false;
 	}
 
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_backend_mem_allocated_increase(info.RegionSize);
 	*mapped_address = address;
 	*mapped_size = info.RegionSize;
 	*impl_private = hmap;
@@ -812,6 +878,13 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		pgstat_report_backend_mem_allocated_decrease(*mapped_size);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && unlink(name) != 0)
@@ -933,6 +1006,13 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_backend_mem_allocated_increase(request_size);
 	*mapped_address = address;
 	*mapped_size = request_size;
 
diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c
index c7ed1e6d7a..45da3af213 100644
--- a/src/backend/utils/activity/backend_status.c
+++ b/src/backend/utils/activity/backend_status.c
@@ -49,6 +49,8 @@ int			pgstat_track_activity_query_size = 1024;
 /* exposed so that backend_progress.c can access it */
 PgBackendStatus *MyBEEntry = NULL;
 
+/* Memory allocated to this backend prior to pgstats initialization */
+uint64		backend_mem_allocated = 0;
 
 static PgBackendStatus *BackendStatusArray = NULL;
 static char *BackendAppnameBuffer = NULL;
@@ -400,6 +402,13 @@ pgstat_bestart(void)
 	lbeentry.st_progress_command_target = InvalidOid;
 	lbeentry.st_query_id = UINT64CONST(0);
 
+	/*
+	 * Move sum of memory allocated prior to pgstats initialization to pgstats
+	 * and zero the local variable.
+	 */
+	lbeentry.backend_mem_allocated = backend_mem_allocated;
+	backend_mem_allocated = 0;
+
 	/*
 	 * we don't zero st_progress_param here to save cycles; nobody should
 	 * examine it until st_progress_command has been set to something other
@@ -1148,3 +1157,99 @@ pgstat_clip_activity(const char *raw_activity)
 
 	return activity;
 }
+
+/* --------
+ * pgstat_report_backend_mem_allocated_increase() -
+ *
+ * Called to report increase in memory allocated for this backend
+ * --------
+ */
+void
+pgstat_report_backend_mem_allocated_increase(uint64 allocation)
+{
+	volatile PgBackendStatus *beentry = MyBEEntry;
+
+	if (!beentry || !pgstat_track_activities)
+	{
+		/*
+		 * Account for memory before pgstats is initialized. This will be
+		 * migrated to pgstats on initialization.
+		 */
+		backend_mem_allocated += allocation;
+
+		return;
+	}
+
+	/*
+	 * Update my status entry, following the protocol of bumping
+	 * st_changecount before and after.  We use a volatile pointer here to
+	 * ensure the compiler doesn't try to get cute.
+	 */
+	PGSTAT_BEGIN_WRITE_ACTIVITY(beentry);
+	beentry->backend_mem_allocated += allocation;
+	PGSTAT_END_WRITE_ACTIVITY(beentry);
+}
+
+/* --------
+ * pgstat_report_backend_mem_allocated_decrease() -
+ *
+ * Called to report decrease in memory allocated for this backend
+ * --------
+ */
+void
+pgstat_report_backend_mem_allocated_decrease(uint64 deallocation)
+{
+	volatile PgBackendStatus *beentry = MyBEEntry;
+
+	/*
+	 * Cases may occur where shared memory from a previous postmaster
+	 * invocation still exist. These are cleaned up at startup by
+	 * dsm_cleanup_using_control_segment. Limit decreasing memory allocated to
+	 * zero in case no corresponding prior increase exists or decrease has
+	 * already been accounted for.
+	 */
+
+	if (!beentry || !pgstat_track_activities)
+	{
+		/*
+		 * Account for memory before pgstats is initialized. This will be
+		 * migrated to pgstats on initialization. Do not allow
+		 * backend_mem_allocated to go below zero. If pgstats has not been
+		 * initialized, we are in startup and we set backend_mem_allocated to
+		 * zero in cases where it would go negative and skip generating an
+		 * ereport.
+		 */
+		if (deallocation > backend_mem_allocated)
+			backend_mem_allocated = 0;
+		else
+			backend_mem_allocated -= deallocation;
+
+		return;
+	}
+
+	/*
+	 * Do not allow backend_mem_allocated to go below zero. ereport if we
+	 * would have. There's no need for a lock around the read here as it's
+	 * being referenced from the same backend which means that there shouldn't
+	 * be concurrent writes. We want to generate an ereport in these cases.
+	 */
+	if (deallocation > beentry->backend_mem_allocated)
+	{
+		ereport(LOG, errmsg("decrease reduces reported backend memory allocated below zero; setting reported to 0"));
+
+		/*
+		 * Overwrite deallocation with current backend_mem_allocated so we end
+		 * up at zero.
+		 */
+		deallocation = beentry->backend_mem_allocated;
+	}
+
+	/*
+	 * Update my status entry, following the protocol of bumping
+	 * st_changecount before and after.  We use a volatile pointer here to
+	 * ensure the compiler doesn't try to get cute.
+	 */
+	PGSTAT_BEGIN_WRITE_ACTIVITY(beentry);
+	beentry->backend_mem_allocated -= deallocation;
+	PGSTAT_END_WRITE_ACTIVITY(beentry);
+}
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index be15b4b2e5..35d497a12e 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -536,7 +536,7 @@ pg_stat_get_progress_info(PG_FUNCTION_ARGS)
 Datum
 pg_stat_get_activity(PG_FUNCTION_ARGS)
 {
-#define PG_STAT_GET_ACTIVITY_COLS	30
+#define PG_STAT_GET_ACTIVITY_COLS	31
 	int			num_backends = pgstat_fetch_stat_numbackends();
 	int			curr_backend;
 	int			pid = PG_ARGISNULL(0) ? -1 : PG_GETARG_INT32(0);
@@ -610,6 +610,8 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
 		else
 			nulls[16] = true;
 
+		values[30] = UInt64GetDatum(beentry->backend_mem_allocated);
+
 		/* Values only available to role member or pg_read_all_stats */
 		if (HAS_PGSTAT_PERMISSIONS(beentry->st_userid))
 		{
diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index ec423375ae..2ac6f10e12 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -47,6 +47,7 @@
 #include "postgres.h"
 
 #include "port/pg_bitutils.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -509,6 +510,7 @@ AllocSetContextCreateInternal(MemoryContext parent,
 						name);
 
 	((MemoryContext) set)->mem_allocated = firstBlockSize;
+	pgstat_report_backend_mem_allocated_increase(firstBlockSize);
 
 	return (MemoryContext) set;
 }
@@ -532,6 +534,7 @@ AllocSetReset(MemoryContext context)
 	AllocBlock	block;
 	Size		keepersize PG_USED_FOR_ASSERTS_ONLY
 	= set->keeper->endptr - ((char *) set);
+	uint64		deallocation = 0;
 
 	AssertArg(AllocSetIsValid(set));
 
@@ -571,6 +574,7 @@ AllocSetReset(MemoryContext context)
 		{
 			/* Normal case, release the block */
 			context->mem_allocated -= block->endptr - ((char *) block);
+			deallocation += block->endptr - ((char *) block);
 
 #ifdef CLOBBER_FREED_MEMORY
 			wipe_mem(block, block->freeptr - ((char *) block));
@@ -581,6 +585,7 @@ AllocSetReset(MemoryContext context)
 	}
 
 	Assert(context->mem_allocated == keepersize);
+	pgstat_report_backend_mem_allocated_decrease(deallocation);
 
 	/* Reset block size allocation sequence, too */
 	set->nextBlockSize = set->initBlockSize;
@@ -600,6 +605,7 @@ AllocSetDelete(MemoryContext context)
 	AllocBlock	block = set->blocks;
 	Size		keepersize PG_USED_FOR_ASSERTS_ONLY
 	= set->keeper->endptr - ((char *) set);
+	uint64		deallocation = 0;
 
 	AssertArg(AllocSetIsValid(set));
 
@@ -635,11 +641,13 @@ AllocSetDelete(MemoryContext context)
 
 				freelist->first_free = (AllocSetContext *) oldset->header.nextchild;
 				freelist->num_free--;
+				deallocation += oldset->header.mem_allocated;
 
 				/* All that remains is to free the header/initial block */
 				free(oldset);
 			}
 			Assert(freelist->num_free == 0);
+			pgstat_report_backend_mem_allocated_decrease(deallocation);
 		}
 
 		/* Now add the just-deleted context to the freelist. */
@@ -656,7 +664,10 @@ AllocSetDelete(MemoryContext context)
 		AllocBlock	next = block->next;
 
 		if (block != set->keeper)
+		{
 			context->mem_allocated -= block->endptr - ((char *) block);
+			deallocation += block->endptr - ((char *) block);
+		}
 
 #ifdef CLOBBER_FREED_MEMORY
 		wipe_mem(block, block->freeptr - ((char *) block));
@@ -669,6 +680,8 @@ AllocSetDelete(MemoryContext context)
 	}
 
 	Assert(context->mem_allocated == keepersize);
+	pgstat_report_backend_mem_allocated_decrease(deallocation +
+												 context->mem_allocated);
 
 	/* Finally, free the context header, including the keeper block */
 	free(set);
@@ -718,6 +731,7 @@ AllocSetAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_backend_mem_allocated_increase(blksize);
 
 		block->aset = set;
 		block->freeptr = block->endptr = ((char *) block) + blksize;
@@ -928,6 +942,7 @@ AllocSetAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_backend_mem_allocated_increase(blksize);
 
 		block->aset = set;
 		block->freeptr = ((char *) block) + ALLOC_BLOCKHDRSZ;
@@ -1028,6 +1043,7 @@ AllocSetFree(void *pointer)
 			block->next->prev = block->prev;
 
 		set->header.mem_allocated -= block->endptr - ((char *) block);
+		pgstat_report_backend_mem_allocated_decrease(block->endptr - ((char *) block));
 
 #ifdef CLOBBER_FREED_MEMORY
 		wipe_mem(block, block->freeptr - ((char *) block));
@@ -1144,7 +1160,9 @@ AllocSetRealloc(void *pointer, Size size)
 
 		/* updated separately, not to underflow when (oldblksize > blksize) */
 		set->header.mem_allocated -= oldblksize;
+		pgstat_report_backend_mem_allocated_decrease(oldblksize);
 		set->header.mem_allocated += blksize;
+		pgstat_report_backend_mem_allocated_increase(blksize);
 
 		block->freeptr = block->endptr = ((char *) block) + blksize;
 
diff --git a/src/backend/utils/mmgr/generation.c b/src/backend/utils/mmgr/generation.c
index c743b24fa7..34b11392ff 100644
--- a/src/backend/utils/mmgr/generation.c
+++ b/src/backend/utils/mmgr/generation.c
@@ -37,6 +37,7 @@
 
 #include "lib/ilist.h"
 #include "port/pg_bitutils.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -258,6 +259,7 @@ GenerationContextCreate(MemoryContext parent,
 						name);
 
 	((MemoryContext) set)->mem_allocated = firstBlockSize;
+	pgstat_report_backend_mem_allocated_increase(firstBlockSize);
 
 	return (MemoryContext) set;
 }
@@ -274,6 +276,7 @@ GenerationReset(MemoryContext context)
 {
 	GenerationContext *set = (GenerationContext *) context;
 	dlist_mutable_iter miter;
+	uint64	deallocation = 0;
 
 	AssertArg(GenerationIsValid(set));
 
@@ -296,9 +299,14 @@ GenerationReset(MemoryContext context)
 		if (block == set->keeper)
 			GenerationBlockMarkEmpty(block);
 		else
+		{
+			deallocation += block->blksize;
 			GenerationBlockFree(set, block);
+		}
 	}
 
+	pgstat_report_backend_mem_allocated_decrease(deallocation);
+
 	/* set it so new allocations to make use of the keeper block */
 	set->block = set->keeper;
 
@@ -319,6 +327,9 @@ GenerationDelete(MemoryContext context)
 {
 	/* Reset to release all releasable GenerationBlocks */
 	GenerationReset(context);
+
+	pgstat_report_backend_mem_allocated_decrease(context->mem_allocated);
+
 	/* And free the context header and keeper block */
 	free(context);
 }
@@ -363,6 +374,7 @@ GenerationAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_backend_mem_allocated_increase(blksize);
 
 		/* block with a single (used) chunk */
 		block->context = set;
@@ -466,6 +478,7 @@ GenerationAlloc(MemoryContext context, Size size)
 				return NULL;
 
 			context->mem_allocated += blksize;
+			pgstat_report_backend_mem_allocated_increase(blksize);
 
 			/* initialize the new block */
 			GenerationBlockInit(set, block, blksize);
@@ -699,6 +712,8 @@ GenerationFree(void *pointer)
 	dlist_delete(&block->node);
 
 	set->header.mem_allocated -= block->blksize;
+	pgstat_report_backend_mem_allocated_decrease(block->blksize);
+
 	free(block);
 }
 
diff --git a/src/backend/utils/mmgr/slab.c b/src/backend/utils/mmgr/slab.c
index 9149aaafcb..72376da82e 100644
--- a/src/backend/utils/mmgr/slab.c
+++ b/src/backend/utils/mmgr/slab.c
@@ -53,6 +53,7 @@
 #include "postgres.h"
 
 #include "lib/ilist.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -223,6 +224,12 @@ SlabContextCreate(MemoryContext parent,
 						parent,
 						name);
 
+	/*
+	 * If SlabContextCreate is updated to add headerSize to
+	 * context->mem_allocated, then update here and SlabDelete appropriately
+	 */
+	pgstat_report_backend_mem_allocated_increase(headerSize);
+
 	return (MemoryContext) slab;
 }
 
@@ -238,6 +245,7 @@ SlabReset(MemoryContext context)
 {
 	int			i;
 	SlabContext *slab = castNode(SlabContext, context);
+	uint64		deallocation = 0;
 
 	Assert(slab);
 
@@ -263,9 +271,11 @@ SlabReset(MemoryContext context)
 			free(block);
 			slab->nblocks--;
 			context->mem_allocated -= slab->blockSize;
+			deallocation += slab->blockSize;
 		}
 	}
 
+	pgstat_report_backend_mem_allocated_decrease(deallocation);
 	slab->minFreeChunks = 0;
 
 	Assert(slab->nblocks == 0);
@@ -279,8 +289,17 @@ SlabReset(MemoryContext context)
 void
 SlabDelete(MemoryContext context)
 {
+	/*
+	 * Until header allocation is included in context->mem_allocated, cast to
+	 * slab and decrement the headerSize
+	 */
+	SlabContext *slab = castNode(SlabContext, context);
+
 	/* Reset to release all the SlabBlocks */
 	SlabReset(context);
+
+	pgstat_report_backend_mem_allocated_decrease(slab->headerSize);
+
 	/* And free the context header */
 	free(context);
 }
@@ -349,6 +368,7 @@ SlabAlloc(MemoryContext context, Size size)
 		slab->minFreeChunks = slab->chunksPerBlock;
 		slab->nblocks += 1;
 		context->mem_allocated += slab->blockSize;
+		pgstat_report_backend_mem_allocated_increase(slab->blockSize);
 	}
 
 	/* grab the block from the freelist (even the new block is there) */
@@ -514,6 +534,7 @@ SlabFree(void *pointer)
 		free(block);
 		slab->nblocks--;
 		slab->header.mem_allocated -= slab->blockSize;
+		pgstat_report_backend_mem_allocated_decrease(slab->blockSize);
 	}
 	else
 		dlist_push_head(&slab->freelist[block->nfree], &block->node);
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index a07e737a33..363d92e9f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -5340,9 +5340,9 @@
   proname => 'pg_stat_get_activity', prorows => '100', proisstrict => 'f',
   proretset => 't', provolatile => 's', proparallel => 'r',
   prorettype => 'record', proargtypes => 'int4',
-  proallargtypes => '{int4,oid,int4,oid,text,text,text,text,text,timestamptz,timestamptz,timestamptz,timestamptz,inet,text,int4,xid,xid,text,bool,text,text,int4,text,numeric,text,bool,text,bool,int4,int8}',
-  proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
-  proargnames => '{pid,datid,pid,usesysid,application_name,state,query,wait_event_type,wait_event,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,backend_type,ssl,sslversion,sslcipher,sslbits,ssl_client_dn,ssl_client_serial,ssl_issuer_dn,gss_auth,gss_princ,gss_enc,leader_pid,query_id}',
+  proallargtypes => '{int4,oid,int4,oid,text,text,text,text,text,timestamptz,timestamptz,timestamptz,timestamptz,inet,text,int4,xid,xid,text,bool,text,text,int4,text,numeric,text,bool,text,bool,int4,int8,int8}',
+  proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
+  proargnames => '{pid,datid,pid,usesysid,application_name,state,query,wait_event_type,wait_event,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,backend_type,ssl,sslversion,sslcipher,sslbits,ssl_client_dn,ssl_client_serial,ssl_issuer_dn,gss_auth,gss_princ,gss_enc,leader_pid,query_id,backend_mem_allocated}',
   prosrc => 'pg_stat_get_activity' },
 { oid => '3318',
   descr => 'statistics: information about progress of backends running maintenance command',
diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h
index 7403bca25e..9bdc4197bd 100644
--- a/src/include/utils/backend_status.h
+++ b/src/include/utils/backend_status.h
@@ -168,6 +168,9 @@ typedef struct PgBackendStatus
 
 	/* query identifier, optionally computed using post_parse_analyze_hook */
 	uint64		st_query_id;
+
+	/* Current memory allocated to this backend */
+	uint64		backend_mem_allocated;
 } PgBackendStatus;
 
 
@@ -305,7 +308,9 @@ extern const char *pgstat_get_backend_current_activity(int pid, bool checkUser);
 extern const char *pgstat_get_crashed_backend_activity(int pid, char *buffer,
 													   int buflen);
 extern uint64 pgstat_get_my_query_id(void);
-
+extern void pgstat_report_backend_mem_allocated_increase(uint64 allocation);
+extern void pgstat_report_backend_mem_allocated_decrease(uint64 deallocation);
+extern uint64 pgstat_get_all_backend_memory_allocated(void);
 
 /* ----------
  * Support functions for the SQL-callable functions to
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index 9dd137415e..4588d71c8a 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1752,9 +1752,10 @@ pg_stat_activity| SELECT s.datid,
     s.backend_xid,
     s.backend_xmin,
     s.query_id,
+    s.backend_mem_allocated,
     s.query,
     s.backend_type
-   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, backend_mem_allocated)
      LEFT JOIN pg_database d ON ((s.datid = d.oid)))
      LEFT JOIN pg_authid u ON ((s.usesysid = u.oid)));
 pg_stat_all_indexes| SELECT c.oid AS relid,
@@ -1866,7 +1867,7 @@ pg_stat_gssapi| SELECT s.pid,
     s.gss_auth AS gss_authenticated,
     s.gss_princ AS principal,
     s.gss_enc AS encrypted
-   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, backend_mem_allocated)
   WHERE (s.client_port IS NOT NULL);
 pg_stat_progress_analyze| SELECT s.pid,
     s.datid,
@@ -2047,7 +2048,7 @@ pg_stat_replication| SELECT s.pid,
     w.sync_priority,
     w.sync_state,
     w.reply_time
-   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, backend_mem_allocated)
      JOIN pg_stat_get_wal_senders() w(pid, state, sent_lsn, write_lsn, flush_lsn, replay_lsn, write_lag, flush_lag, replay_lag, sync_priority, sync_state, reply_time) ON ((s.pid = w.pid)))
      LEFT JOIN pg_authid u ON ((s.usesysid = u.oid)));
 pg_stat_replication_slots| SELECT s.slot_name,
@@ -2081,7 +2082,7 @@ pg_stat_ssl| SELECT s.pid,
     s.ssl_client_dn AS client_dn,
     s.ssl_client_serial AS client_serial,
     s.ssl_issuer_dn AS issuer_dn
-   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, backend_mem_allocated)
   WHERE (s.client_port IS NOT NULL);
 pg_stat_subscription| SELECT su.oid AS subid,
     su.subname,
-- 
2.25.1

0002-Add-the-ability-to-limit-the-amount-of-memory-that-c.patchtext/x-patch; charset=UTF-8; name=0002-Add-the-ability-to-limit-the-amount-of-memory-that-c.patchDownload
From bb8e1a2bbb9425eb7667a97dc49beebe8f9bf327 Mon Sep 17 00:00:00 2001
From: Reid Thompson <jreidthompson@nc.rr.com>
Date: Sat, 4 Jun 2022 22:23:59 -0400
Subject: [PATCH 2/2] Add the ability to limit the amount of memory that can be
 allocated to backends.

This builds on the work that adds backend memory allocated to pg_stat_activity.

Add GUC variable max_total_backend_memory.

Specifies a limit to the amount of memory (in MB) that may be allocated to
backends in total (i.e. this is not a per user or per backend limit). If unset,
or set to 0 it is disabled. It is intended as a resource to help avoid the OOM
killer on LINUX and manage resources in general. A backend request that would
push the total over the limit will be denied with an out of memory error causing
that backend's current query/transaction to fail. Due to the dynamic nature of
memory allocations, this limit is not exact. If within 1.5MB of the limit and
two backends request 1MB each at the same time both may be allocated, and exceed
the limit. Further requests will not be allocated until dropping below the
limit. Keep this in mind when setting this value. This limit does not affect
auxiliary backend processes. Backend memory allocations are displayed in the
pg_stat_activity view.
---
 doc/src/sgml/config.sgml                      |  26 ++++
 src/backend/storage/ipc/dsm_impl.c            |  12 ++
 src/backend/utils/activity/backend_status.c   | 111 +++++++++++++++++-
 src/backend/utils/misc/guc_tables.c           |  11 ++
 src/backend/utils/misc/postgresql.conf.sample |   3 +
 src/backend/utils/mmgr/aset.c                 |  17 +++
 src/backend/utils/mmgr/generation.c           |  11 +-
 src/backend/utils/mmgr/slab.c                 |   8 ++
 src/include/utils/backend_status.h            |   2 +
 9 files changed, 199 insertions(+), 2 deletions(-)

diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 700914684d..ce8e35daee 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -2079,6 +2079,32 @@ include_dir 'conf.d'
       </listitem>
      </varlistentry>
 
+     <varlistentry id="guc-max-total-backend-memory" xreflabel="max_total_backend_memory">
+      <term><varname>max_total_backend_memory</varname> (<type>integer</type>)
+      <indexterm>
+       <primary><varname>max_total_backend_memory</varname> configuration parameter</primary>
+      </indexterm>
+      </term>
+      <listitem>
+       <para>
+        Specifies a limit to the amount of memory (MB) that may be allocated to
+        backends in total (i.e. this is not a per user or per backend limit).
+        If unset, or set to 0 it is disabled.  A backend request that would
+        push the total over the limit will be denied with an out of memory
+        error causing that backend's current query/transaction to fail. Due to
+        the dynamic nature of memory allocations, this limit is not exact. If
+        within 1.5MB of the limit and two backends request 1MB each at the same
+        time both may be allocated, and exceed the limit. Further requests will
+        not be allocated until dropping below the limit. Keep this in mind when
+        setting this value. This limit does not affect auxiliary backend
+        processes <xref linkend="glossary-auxiliary-proc"/> . Backend memory
+        allocations (<varname>backend_mem_allocated</varname>) are displayed in
+        the <link linkend="monitoring-pg-stat-activity-view"><structname>pg_stat_activity</structname></link>
+        view.
+       </para>
+      </listitem>
+     </varlistentry>
+
      </variablelist>
      </sect2>
 
diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c
index 3356bb65b5..cc061056a3 100644
--- a/src/backend/storage/ipc/dsm_impl.c
+++ b/src/backend/storage/ipc/dsm_impl.c
@@ -253,6 +253,10 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 		return true;
 	}
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+		return false;
+
 	/*
 	 * Create new segment or open an existing one for attach.
 	 *
@@ -524,6 +528,10 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 		int			flags = IPCProtection;
 		size_t		segsize;
 
+		/* Do not exceed maximum allowed memory allocation */
+		if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+			return false;
+
 		/*
 		 * Allocate the memory BEFORE acquiring the resource, so that we don't
 		 * leak the resource if memory allocation fails.
@@ -718,6 +726,10 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 		return true;
 	}
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+		return false;
+
 	/* Create new segment or open an existing one for attach. */
 	if (op == DSM_OP_CREATE)
 	{
diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c
index 45da3af213..7820c55489 100644
--- a/src/backend/utils/activity/backend_status.c
+++ b/src/backend/utils/activity/backend_status.c
@@ -45,6 +45,9 @@
 bool		pgstat_track_activities = false;
 int			pgstat_track_activity_query_size = 1024;
 
+/* Max backend memory allocation allowed (MB). 0 = disabled */
+int			max_total_bkend_mem = 0;
+
 
 /* exposed so that backend_progress.c can access it */
 PgBackendStatus *MyBEEntry = NULL;
@@ -1235,7 +1238,7 @@ pgstat_report_backend_mem_allocated_decrease(uint64 deallocation)
 	 */
 	if (deallocation > beentry->backend_mem_allocated)
 	{
-		ereport(LOG, errmsg("decrease reduces reported backend memory allocated below zero; setting reported to 0"));
+		ereport(LOG, errmsg("deallocation would decrease backend memory below zero; setting reported to 0"));
 
 		/*
 		 * Overwrite deallocation with current backend_mem_allocated so we end
@@ -1253,3 +1256,109 @@ pgstat_report_backend_mem_allocated_decrease(uint64 deallocation)
 	beentry->backend_mem_allocated -= deallocation;
 	PGSTAT_END_WRITE_ACTIVITY(beentry);
 }
+
+/* ----------
+ * pgstat_get_all_backend_memory_allocated() -
+ *
+ *	Return a uint64 representing the current shared memory allocated to all
+ *	backends.  This looks directly at the BackendStatusArray, and so will
+ *	provide current information regardless of the age of our transaction's
+ *	snapshot of the status array.
+ *	In the future we will likely utilize additional values - perhaps limit
+ *	backend allocation by user/role, etc.
+ * ----------
+ */
+uint64
+pgstat_get_all_backend_memory_allocated(void)
+{
+	PgBackendStatus *beentry;
+	int			i;
+	uint64		all_backend_memory_allocated = 0;
+
+	beentry = BackendStatusArray;
+
+	/*
+	 * We probably shouldn't get here before shared memory has been set up,
+	 * but be safe.
+	 */
+	if (beentry == NULL || BackendActivityBuffer == NULL)
+		return 0;
+
+	/*
+	 * We include AUX procs in all backend memory calculation
+	 */
+	for (i = 1; i <= NumBackendStatSlots; i++)
+	{
+		/*
+		 * We use a volatile pointer here to ensure the compiler doesn't try
+		 * to get cute.
+		 */
+		volatile PgBackendStatus *vbeentry = beentry;
+		bool		found;
+		uint64		backend_mem_allocated = 0;
+
+		for (;;)
+		{
+			int			before_changecount;
+			int			after_changecount;
+
+			pgstat_begin_read_activity(vbeentry, before_changecount);
+
+			/*
+			 * Ignore invalid entries, which may contain invalid data.
+			 * See pgstat_beshutdown_hook()
+			 */
+			if (vbeentry->st_procpid > 0)
+				backend_mem_allocated = vbeentry->backend_mem_allocated;
+
+			pgstat_end_read_activity(vbeentry, after_changecount);
+
+			if ((found = pgstat_read_activity_complete(before_changecount,
+													   after_changecount)))
+				break;
+
+			/* Make sure we can break out of loop if stuck... */
+			CHECK_FOR_INTERRUPTS();
+		}
+
+		if (found)
+			all_backend_memory_allocated += backend_mem_allocated;
+
+		beentry++;
+	}
+
+	return all_backend_memory_allocated;
+}
+
+/*
+ * Determine if allocation request will exceed max backend memory allowed.
+ * Do not apply to auxiliary processes.
+ */
+bool
+exceeds_max_total_bkend_mem(uint64 allocation_request)
+{
+	bool		result = false;
+
+	/* Exclude auxiliary processes from the check */
+	if (MyAuxProcType != NotAnAuxProcess)
+		return result;
+
+	/* Convert max_total_bkend_mem to bytes for comparison */
+	if (max_total_bkend_mem &&
+		pgstat_get_all_backend_memory_allocated() +
+		allocation_request > (uint64) max_total_bkend_mem * 1024 * 1024)
+	{
+		/*
+		 * Explicitly identify the OOM being a result of this configuration
+		 * parameter vs a system failure to allocate OOM.
+		 */
+		ereport(WARNING,
+				errmsg("allocation would exceed max_total_backend_memory limit (%llu > %llu)",
+					   (unsigned long long) pgstat_get_all_backend_memory_allocated() +
+					   allocation_request, (unsigned long long) max_total_bkend_mem * 1024 * 1024));
+
+		result = true;
+	}
+
+	return result;
+}
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index 550e95056c..7d4dc8677a 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -3415,6 +3415,17 @@ struct config_int ConfigureNamesInt[] =
 		NULL, NULL, NULL
 	},
 
+	{
+		{"max_total_backend_memory", PGC_SU_BACKEND, RESOURCES_MEM,
+			gettext_noop("Restrict total backend memory allocations to this max."),
+			gettext_noop("0 turns this feature off."),
+			GUC_UNIT_MB
+		},
+		&max_total_bkend_mem,
+		0, 0, INT_MAX,
+		NULL, NULL, NULL
+	},
+
 	/* End-of-list marker */
 	{
 		{NULL, 0, 0, NULL, NULL}, NULL, 0, 0, 0, NULL, NULL, NULL
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 2ae76e5cfb..8a0b383eb7 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -155,6 +155,9 @@
 					#   mmap
 					# (change requires restart)
 #min_dynamic_shared_memory = 0MB	# (change requires restart)
+#max_total_backend_memory = 0MB		# Restrict total backend memory allocations
+									# to this max (in MB). 0 turns this feature
+									# off.
 
 # - Disk -
 
diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index 2ac6f10e12..509b93faa1 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -428,6 +428,10 @@ AllocSetContextCreateInternal(MemoryContext parent,
 	else
 		firstBlockSize = Max(firstBlockSize, initBlockSize);
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (exceeds_max_total_bkend_mem(firstBlockSize))
+		return NULL;
+
 	/*
 	 * Allocate the initial block.  Unlike other aset.c blocks, it starts with
 	 * the context header and its block header follows that.
@@ -726,6 +730,11 @@ AllocSetAlloc(MemoryContext context, Size size)
 #endif
 
 		blksize = chunk_size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
+
+		/* Do not exceed maximum allowed memory allocation */
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		block = (AllocBlock) malloc(blksize);
 		if (block == NULL)
 			return NULL;
@@ -923,6 +932,10 @@ AllocSetAlloc(MemoryContext context, Size size)
 		while (blksize < required_size)
 			blksize <<= 1;
 
+		/* Do not exceed maximum allowed memory allocation */
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		/* Try to allocate it */
 		block = (AllocBlock) malloc(blksize);
 
@@ -1150,6 +1163,10 @@ AllocSetRealloc(void *pointer, Size size)
 		blksize = chksize + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
 		oldblksize = block->endptr - ((char *) block);
 
+		/* Do not exceed maximum allowed memory allocation */
+		if (blksize > oldblksize && exceeds_max_total_bkend_mem(blksize - oldblksize))
+			return NULL;
+
 		block = (AllocBlock) realloc(block, blksize);
 		if (block == NULL)
 		{
diff --git a/src/backend/utils/mmgr/generation.c b/src/backend/utils/mmgr/generation.c
index 34b11392ff..6256e84d48 100644
--- a/src/backend/utils/mmgr/generation.c
+++ b/src/backend/utils/mmgr/generation.c
@@ -192,6 +192,9 @@ GenerationContextCreate(MemoryContext parent,
 	else
 		allocSize = Max(allocSize, initBlockSize);
 
+	if (exceeds_max_total_bkend_mem(allocSize))
+		return NULL;
+
 	/*
 	 * Allocate the initial block.  Unlike other generation.c blocks, it
 	 * starts with the context header and its block header follows that.
@@ -276,7 +279,7 @@ GenerationReset(MemoryContext context)
 {
 	GenerationContext *set = (GenerationContext *) context;
 	dlist_mutable_iter miter;
-	uint64	deallocation = 0;
+	uint64		deallocation = 0;
 
 	AssertArg(GenerationIsValid(set));
 
@@ -369,6 +372,9 @@ GenerationAlloc(MemoryContext context, Size size)
 	{
 		Size		blksize = required_size + Generation_BLOCKHDRSZ;
 
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		block = (GenerationBlock *) malloc(blksize);
 		if (block == NULL)
 			return NULL;
@@ -472,6 +478,9 @@ GenerationAlloc(MemoryContext context, Size size)
 			if (blksize < required_size)
 				blksize = pg_nextpower2_size_t(required_size);
 
+			if (exceeds_max_total_bkend_mem(blksize))
+				return NULL;
+
 			block = (GenerationBlock *) malloc(blksize);
 
 			if (block == NULL)
diff --git a/src/backend/utils/mmgr/slab.c b/src/backend/utils/mmgr/slab.c
index 72376da82e..364c9eb795 100644
--- a/src/backend/utils/mmgr/slab.c
+++ b/src/backend/utils/mmgr/slab.c
@@ -182,6 +182,10 @@ SlabContextCreate(MemoryContext parent,
 	headerSize += chunksPerBlock * sizeof(bool);
 #endif
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (exceeds_max_total_bkend_mem(headerSize))
+		return NULL;
+
 	slab = (SlabContext *) malloc(headerSize);
 	if (slab == NULL)
 	{
@@ -336,6 +340,10 @@ SlabAlloc(MemoryContext context, Size size)
 	 */
 	if (slab->minFreeChunks == 0)
 	{
+		/* Do not exceed maximum allowed memory allocation */
+		if (exceeds_max_total_bkend_mem(slab->blockSize))
+			return NULL;
+
 		block = (SlabBlock *) malloc(slab->blockSize);
 
 		if (block == NULL)
diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h
index 9bdc4197bd..3b940ff98e 100644
--- a/src/include/utils/backend_status.h
+++ b/src/include/utils/backend_status.h
@@ -270,6 +270,7 @@ typedef struct LocalPgBackendStatus
  */
 extern PGDLLIMPORT bool pgstat_track_activities;
 extern PGDLLIMPORT int pgstat_track_activity_query_size;
+extern PGDLLIMPORT int max_total_bkend_mem;
 
 
 /* ----------
@@ -321,6 +322,7 @@ extern int	pgstat_fetch_stat_numbackends(void);
 extern PgBackendStatus *pgstat_fetch_stat_beentry(int beid);
 extern LocalPgBackendStatus *pgstat_fetch_stat_local_beentry(int beid);
 extern char *pgstat_clip_activity(const char *raw_activity);
+extern bool exceeds_max_total_bkend_mem(uint64 allocation_request);
 
 
 #endif							/* BACKEND_STATUS_H */
-- 
2.25.1

#14Arne Roland
A.Roland@index.de
In reply to: Reid Thompson (#13)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

Hello Reid,

could you rebase the patch again? It doesn't apply currently (http://cfbot.cputube.org/patch_40_3867.log). Thanks!

You mention, that you want to prevent the compiler from getting cute.

I don't think this comments are exactly helpful in the current state. I think probably fine to just omit them.

I don't understand the purpose of the result variable in exceeds_max_total_bkend_mem. What purpose does it serve?

I really like the simplicity of the suggestion here to prevent oom.

I intent to play around with a lot of backends, once I get a rebased patch.

Regards

Arne

________________________________
From: Reid Thompson <reid.thompson@crunchydata.com>
Sent: Thursday, September 15, 2022 4:58:19 PM
To: Ibrar Ahmed; pgsql-hackers@lists.postgresql.org
Cc: reid.thompson@crunchydata.com; Justin Pryzby
Subject: Re: Add the ability to limit the amount of memory that can be allocated to backends.

On Thu, 2022-09-15 at 12:07 +0400, Ibrar Ahmed wrote:

The patch does not apply; please rebase the patch.

patching file src/backend/utils/misc/guc.c
Hunk #1 FAILED at 3664.
1 out of 1 hunk FAILED -- saving rejects to file
src/backend/utils/misc/guc.c.rej

patching file src/backend/utils/misc/postgresql.conf.sample

rebased patches attached.

Thanks,
Reid

#15Reid Thompson
reid.thompson@crunchydata.com
In reply to: Arne Roland (#14)
2 attachment(s)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

Hi Arne,

On Mon, 2022-10-24 at 15:27 +0000, Arne Roland wrote:

Hello Reid,

could you rebase the patch again? It doesn't apply currently
(http://cfbot.cputube.org/patch_40_3867.log). Thanks!

rebased patches attached.

You mention, that you want to prevent the compiler from getting
cute.I don't think this comments are exactly helpful in the current
state. I think probably fine to just omit them.

I attempted to follow previous convention when adding code and these
comments have been consistently applied throughout backend_status.c
where a volatile pointer is being used.

I don't understand the purpose of the result variable in
exceeds_max_total_bkend_mem. What purpose does it serve?

I really like the simplicity of the suggestion here to prevent oom.

If max_total_backend_memory is configured, exceeds_max_total_bkend_mem()
will return true if an allocation request will push total backend memory
allocated over the configured value.

exceeds_max_total_bkend_mem() is implemented in the various allocators
along the lines of
...snip...
/* Do not exceed maximum allowed memory allocation */
if (exceeds_max_total_bkend_mem('new request size'))
return NULL;
...snip...
Do not allocate the memory requested, return NULL instead. PG already
had code in place to handle NULL returns from allocation requests.

The allocation code in aset.c, slab.c, generation.c, dsm_impl.c utilizes
exceeds_max_total_bkend_mem()

max_total_backend_memory (integer)
Specifies a limit to the amount of memory (MB) that may be allocated
to backends in total (i.e. this is not a per user or per backend limit).
If unset, or set to 0 it is disabled. A backend request that would push
the total over the limit will be denied with an out of memory error
causing that backend's current query/transaction to fail. Due to the
dynamic nature of memory allocations, this limit is not exact. If within
1.5MB of the limit and two backends request 1MB each at the same time
both may be allocated, and exceed the limit. Further requests will not
be allocated until dropping below the limit. Keep this in mind when
setting this value. This limit does not affect auxiliary backend
processes Auxiliary process . Backend memory allocations
(backend_mem_allocated) are displayed in the pg_stat_activity view.

Show quoted text

I intent to play around with a lot of backends, once I get a rebased
patch.

Regards
Arne

Attachments:

0001-Add-tracking-of-backend-memory-allocated-to-pg_stat_.patchtext/x-patch; charset=UTF-8; name=0001-Add-tracking-of-backend-memory-allocated-to-pg_stat_.patchDownload
From ab654a48ec7bfbc3bc377c5757a04f1756e72e79 Mon Sep 17 00:00:00 2001
From: Reid Thompson <jreidthompson@nc.rr.com>
Date: Thu, 11 Aug 2022 12:01:25 -0400
Subject: [PATCH 1/2] Add tracking of backend memory allocated to
 pg_stat_activity

This new field displays the current bytes of memory allocated to the
backend process. It is updated as memory for the process is
malloc'd/free'd. Memory allocated to items on the freelist is included in
the displayed value.  Dynamic shared memory allocations are included
only in the value displayed for the backend that created them, they are
not included in the value for backends that are attached to them to
avoid double counting. On occasion, orphaned memory segments may be
cleaned up on postmaster startup. This may result in decreasing the sum
without a prior increment. We limit the floor of backend_mem_allocated
to zero. Updated pg_stat_activity documentation for the new column.
---
 doc/src/sgml/monitoring.sgml                |  12 +++
 src/backend/catalog/system_views.sql        |   1 +
 src/backend/storage/ipc/dsm_impl.c          |  80 +++++++++++++++
 src/backend/utils/activity/backend_status.c | 105 ++++++++++++++++++++
 src/backend/utils/adt/pgstatfuncs.c         |   4 +-
 src/backend/utils/mmgr/aset.c               |  18 ++++
 src/backend/utils/mmgr/generation.c         |  15 +++
 src/backend/utils/mmgr/slab.c               |  21 ++++
 src/include/catalog/pg_proc.dat             |   6 +-
 src/include/utils/backend_status.h          |   7 +-
 src/test/regress/expected/rules.out         |   9 +-
 11 files changed, 269 insertions(+), 9 deletions(-)

diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index e5d622d514..4983bbc814 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -947,6 +947,18 @@ postgres   27093  0.0  0.0  30096  2752 ?        Ss   11:34   0:00 postgres: ser
      </para></entry>
     </row>
 
+    <row>
+     <entry role="catalog_table_entry"><para role="column_definition">
+      <structfield>backend_mem_allocated</structfield> <type>bigint</type>
+     </para>
+     <para>
+      The byte count of memory allocated to this backend. Dynamic shared memory
+      allocations are included only in the value displayed for the backend that
+      created them, they are not included in the value for backends that are
+      attached to them to avoid double counting.
+     </para></entry>
+    </row>
+
      <row>
       <entry role="catalog_table_entry"><para role="column_definition">
        <structfield>query</structfield> <type>text</type>
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 2d8104b090..cbf804625c 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -865,6 +865,7 @@ CREATE VIEW pg_stat_activity AS
             S.backend_xid,
             s.backend_xmin,
             S.query_id,
+            S.backend_mem_allocated,
             S.query,
             S.backend_type
     FROM pg_stat_get_activity(NULL) AS S
diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c
index e1b90c5de4..3356bb65b5 100644
--- a/src/backend/storage/ipc/dsm_impl.c
+++ b/src/backend/storage/ipc/dsm_impl.c
@@ -66,6 +66,7 @@
 #include "postmaster/postmaster.h"
 #include "storage/dsm_impl.h"
 #include "storage/fd.h"
+#include "utils/backend_status.h"
 #include "utils/guc.h"
 #include "utils/memutils.h"
 
@@ -232,6 +233,13 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_backend_mem_allocated_decrease(*mapped_size);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && shm_unlink(name) != 0)
@@ -332,6 +340,36 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+	{
+		/*
+		 * Posix creation calls dsm_impl_posix_resize implying that resizing
+		 * occurs or may be added in the future. As implemented
+		 * dsm_impl_posix_resize utilizes fallocate or truncate, passing the
+		 * whole new size as input, growing the allocation as needed (only
+		 * truncate supports shrinking). We update by replacing the old
+		 * allocation with the new.
+		 */
+#if defined(HAVE_POSIX_FALLOCATE) && defined(__linux__)
+		/*
+		 * posix_fallocate does not shrink allocations, adjust only on
+		 * allocation increase.
+		 */
+		if (request_size > *mapped_size)
+		{
+			pgstat_report_backend_mem_allocated_decrease(*mapped_size);
+			pgstat_report_backend_mem_allocated_increase(request_size);
+		}
+#else
+		pgstat_report_backend_mem_allocated_decrease(*mapped_size);
+		pgstat_report_backend_mem_allocated_increase(request_size);
+#endif
+	}
 	*mapped_address = address;
 	*mapped_size = request_size;
 	close(fd);
@@ -537,6 +575,14 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_backend_mem_allocated_decrease(*mapped_size);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && shmctl(ident, IPC_RMID, NULL) < 0)
@@ -584,6 +630,13 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_backend_mem_allocated_increase(request_size);
 	*mapped_address = address;
 	*mapped_size = request_size;
 
@@ -652,6 +705,13 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 			return false;
 		}
 
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_backend_mem_allocated_decrease(*mapped_size);
 		*impl_private = NULL;
 		*mapped_address = NULL;
 		*mapped_size = 0;
@@ -768,6 +828,12 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 		return false;
 	}
 
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_backend_mem_allocated_increase(info.RegionSize);
 	*mapped_address = address;
 	*mapped_size = info.RegionSize;
 	*impl_private = hmap;
@@ -812,6 +878,13 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		pgstat_report_backend_mem_allocated_decrease(*mapped_size);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && unlink(name) != 0)
@@ -933,6 +1006,13 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_backend_mem_allocated_increase(request_size);
 	*mapped_address = address;
 	*mapped_size = request_size;
 
diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c
index 1146a6c33c..5c33824eb8 100644
--- a/src/backend/utils/activity/backend_status.c
+++ b/src/backend/utils/activity/backend_status.c
@@ -49,6 +49,8 @@ int			pgstat_track_activity_query_size = 1024;
 /* exposed so that backend_progress.c can access it */
 PgBackendStatus *MyBEEntry = NULL;
 
+/* Memory allocated to this backend prior to pgstats initialization */
+uint64		backend_mem_allocated = 0;
 
 static PgBackendStatus *BackendStatusArray = NULL;
 static char *BackendAppnameBuffer = NULL;
@@ -400,6 +402,13 @@ pgstat_bestart(void)
 	lbeentry.st_progress_command_target = InvalidOid;
 	lbeentry.st_query_id = UINT64CONST(0);
 
+	/*
+	 * Move sum of memory allocated prior to pgstats initialization to pgstats
+	 * and zero the local variable.
+	 */
+	lbeentry.backend_mem_allocated = backend_mem_allocated;
+	backend_mem_allocated = 0;
+
 	/*
 	 * we don't zero st_progress_param here to save cycles; nobody should
 	 * examine it until st_progress_command has been set to something other
@@ -1191,3 +1200,99 @@ pgstat_clip_activity(const char *raw_activity)
 
 	return activity;
 }
+
+/* --------
+ * pgstat_report_backend_mem_allocated_increase() -
+ *
+ * Called to report increase in memory allocated for this backend
+ * --------
+ */
+void
+pgstat_report_backend_mem_allocated_increase(uint64 allocation)
+{
+	volatile PgBackendStatus *beentry = MyBEEntry;
+
+	if (!beentry || !pgstat_track_activities)
+	{
+		/*
+		 * Account for memory before pgstats is initialized. This will be
+		 * migrated to pgstats on initialization.
+		 */
+		backend_mem_allocated += allocation;
+
+		return;
+	}
+
+	/*
+	 * Update my status entry, following the protocol of bumping
+	 * st_changecount before and after.  We use a volatile pointer here to
+	 * ensure the compiler doesn't try to get cute.
+	 */
+	PGSTAT_BEGIN_WRITE_ACTIVITY(beentry);
+	beentry->backend_mem_allocated += allocation;
+	PGSTAT_END_WRITE_ACTIVITY(beentry);
+}
+
+/* --------
+ * pgstat_report_backend_mem_allocated_decrease() -
+ *
+ * Called to report decrease in memory allocated for this backend
+ * --------
+ */
+void
+pgstat_report_backend_mem_allocated_decrease(uint64 deallocation)
+{
+	volatile PgBackendStatus *beentry = MyBEEntry;
+
+	/*
+	 * Cases may occur where shared memory from a previous postmaster
+	 * invocation still exist. These are cleaned up at startup by
+	 * dsm_cleanup_using_control_segment. Limit decreasing memory allocated to
+	 * zero in case no corresponding prior increase exists or decrease has
+	 * already been accounted for.
+	 */
+
+	if (!beentry || !pgstat_track_activities)
+	{
+		/*
+		 * Account for memory before pgstats is initialized. This will be
+		 * migrated to pgstats on initialization. Do not allow
+		 * backend_mem_allocated to go below zero. If pgstats has not been
+		 * initialized, we are in startup and we set backend_mem_allocated to
+		 * zero in cases where it would go negative and skip generating an
+		 * ereport.
+		 */
+		if (deallocation > backend_mem_allocated)
+			backend_mem_allocated = 0;
+		else
+			backend_mem_allocated -= deallocation;
+
+		return;
+	}
+
+	/*
+	 * Do not allow backend_mem_allocated to go below zero. ereport if we
+	 * would have. There's no need for a lock around the read here as it's
+	 * being referenced from the same backend which means that there shouldn't
+	 * be concurrent writes. We want to generate an ereport in these cases.
+	 */
+	if (deallocation > beentry->backend_mem_allocated)
+	{
+		ereport(LOG, errmsg("decrease reduces reported backend memory allocated below zero; setting reported to 0"));
+
+		/*
+		 * Overwrite deallocation with current backend_mem_allocated so we end
+		 * up at zero.
+		 */
+		deallocation = beentry->backend_mem_allocated;
+	}
+
+	/*
+	 * Update my status entry, following the protocol of bumping
+	 * st_changecount before and after.  We use a volatile pointer here to
+	 * ensure the compiler doesn't try to get cute.
+	 */
+	PGSTAT_BEGIN_WRITE_ACTIVITY(beentry);
+	beentry->backend_mem_allocated -= deallocation;
+	PGSTAT_END_WRITE_ACTIVITY(beentry);
+}
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 96bffc0f2a..692ed1df18 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -553,7 +553,7 @@ pg_stat_get_progress_info(PG_FUNCTION_ARGS)
 Datum
 pg_stat_get_activity(PG_FUNCTION_ARGS)
 {
-#define PG_STAT_GET_ACTIVITY_COLS	30
+#define PG_STAT_GET_ACTIVITY_COLS	31
 	int			num_backends = pgstat_fetch_stat_numbackends();
 	int			curr_backend;
 	int			pid = PG_ARGISNULL(0) ? -1 : PG_GETARG_INT32(0);
@@ -609,6 +609,8 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
 		else
 			nulls[16] = true;
 
+		values[30] = UInt64GetDatum(beentry->backend_mem_allocated);
+
 		/* Values only available to role member or pg_read_all_stats */
 		if (HAS_PGSTAT_PERMISSIONS(beentry->st_userid))
 		{
diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index db402e3a41..f6d1333f3d 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -47,6 +47,7 @@
 #include "postgres.h"
 
 #include "port/pg_bitutils.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -521,6 +522,7 @@ AllocSetContextCreateInternal(MemoryContext parent,
 						name);
 
 	((MemoryContext) set)->mem_allocated = firstBlockSize;
+	pgstat_report_backend_mem_allocated_increase(firstBlockSize);
 
 	return (MemoryContext) set;
 }
@@ -543,6 +545,7 @@ AllocSetReset(MemoryContext context)
 	AllocSet	set = (AllocSet) context;
 	AllocBlock	block;
 	Size		keepersize PG_USED_FOR_ASSERTS_ONLY;
+	uint64		deallocation = 0;
 
 	AssertArg(AllocSetIsValid(set));
 
@@ -585,6 +588,7 @@ AllocSetReset(MemoryContext context)
 		{
 			/* Normal case, release the block */
 			context->mem_allocated -= block->endptr - ((char *) block);
+			deallocation += block->endptr - ((char *) block);
 
 #ifdef CLOBBER_FREED_MEMORY
 			wipe_mem(block, block->freeptr - ((char *) block));
@@ -595,6 +599,7 @@ AllocSetReset(MemoryContext context)
 	}
 
 	Assert(context->mem_allocated == keepersize);
+	pgstat_report_backend_mem_allocated_decrease(deallocation);
 
 	/* Reset block size allocation sequence, too */
 	set->nextBlockSize = set->initBlockSize;
@@ -613,6 +618,7 @@ AllocSetDelete(MemoryContext context)
 	AllocSet	set = (AllocSet) context;
 	AllocBlock	block = set->blocks;
 	Size		keepersize PG_USED_FOR_ASSERTS_ONLY;
+	uint64		deallocation = 0;
 
 	AssertArg(AllocSetIsValid(set));
 
@@ -651,11 +657,13 @@ AllocSetDelete(MemoryContext context)
 
 				freelist->first_free = (AllocSetContext *) oldset->header.nextchild;
 				freelist->num_free--;
+				deallocation += oldset->header.mem_allocated;
 
 				/* All that remains is to free the header/initial block */
 				free(oldset);
 			}
 			Assert(freelist->num_free == 0);
+			pgstat_report_backend_mem_allocated_decrease(deallocation);
 		}
 
 		/* Now add the just-deleted context to the freelist. */
@@ -672,7 +680,10 @@ AllocSetDelete(MemoryContext context)
 		AllocBlock	next = block->next;
 
 		if (block != set->keeper)
+		{
 			context->mem_allocated -= block->endptr - ((char *) block);
+			deallocation += block->endptr - ((char *) block);
+		}
 
 #ifdef CLOBBER_FREED_MEMORY
 		wipe_mem(block, block->freeptr - ((char *) block));
@@ -685,6 +696,8 @@ AllocSetDelete(MemoryContext context)
 	}
 
 	Assert(context->mem_allocated == keepersize);
+	pgstat_report_backend_mem_allocated_decrease(deallocation +
+												 context->mem_allocated);
 
 	/* Finally, free the context header, including the keeper block */
 	free(set);
@@ -734,6 +747,7 @@ AllocSetAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_backend_mem_allocated_increase(blksize);
 
 		block->aset = set;
 		block->freeptr = block->endptr = ((char *) block) + blksize;
@@ -944,6 +958,7 @@ AllocSetAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_backend_mem_allocated_increase(blksize);
 
 		block->aset = set;
 		block->freeptr = ((char *) block) + ALLOC_BLOCKHDRSZ;
@@ -1043,6 +1058,7 @@ AllocSetFree(void *pointer)
 			block->next->prev = block->prev;
 
 		set->header.mem_allocated -= block->endptr - ((char *) block);
+		pgstat_report_backend_mem_allocated_decrease(block->endptr - ((char *) block));
 
 #ifdef CLOBBER_FREED_MEMORY
 		wipe_mem(block, block->freeptr - ((char *) block));
@@ -1173,7 +1189,9 @@ AllocSetRealloc(void *pointer, Size size)
 
 		/* updated separately, not to underflow when (oldblksize > blksize) */
 		set->header.mem_allocated -= oldblksize;
+		pgstat_report_backend_mem_allocated_decrease(oldblksize);
 		set->header.mem_allocated += blksize;
+		pgstat_report_backend_mem_allocated_increase(blksize);
 
 		block->freeptr = block->endptr = ((char *) block) + blksize;
 
diff --git a/src/backend/utils/mmgr/generation.c b/src/backend/utils/mmgr/generation.c
index 4cb75f493f..7bb9175f6d 100644
--- a/src/backend/utils/mmgr/generation.c
+++ b/src/backend/utils/mmgr/generation.c
@@ -37,6 +37,7 @@
 
 #include "lib/ilist.h"
 #include "port/pg_bitutils.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -267,6 +268,7 @@ GenerationContextCreate(MemoryContext parent,
 						name);
 
 	((MemoryContext) set)->mem_allocated = firstBlockSize;
+	pgstat_report_backend_mem_allocated_increase(firstBlockSize);
 
 	return (MemoryContext) set;
 }
@@ -283,6 +285,7 @@ GenerationReset(MemoryContext context)
 {
 	GenerationContext *set = (GenerationContext *) context;
 	dlist_mutable_iter miter;
+	uint64	deallocation = 0;
 
 	AssertArg(GenerationIsValid(set));
 
@@ -305,9 +308,14 @@ GenerationReset(MemoryContext context)
 		if (block == set->keeper)
 			GenerationBlockMarkEmpty(block);
 		else
+		{
+			deallocation += block->blksize;
 			GenerationBlockFree(set, block);
+		}
 	}
 
+	pgstat_report_backend_mem_allocated_decrease(deallocation);
+
 	/* set it so new allocations to make use of the keeper block */
 	set->block = set->keeper;
 
@@ -328,6 +336,9 @@ GenerationDelete(MemoryContext context)
 {
 	/* Reset to release all releasable GenerationBlocks */
 	GenerationReset(context);
+
+	pgstat_report_backend_mem_allocated_decrease(context->mem_allocated);
+
 	/* And free the context header and keeper block */
 	free(context);
 }
@@ -374,6 +385,7 @@ GenerationAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_backend_mem_allocated_increase(blksize);
 
 		/* block with a single (used) chunk */
 		block->context = set;
@@ -477,6 +489,7 @@ GenerationAlloc(MemoryContext context, Size size)
 				return NULL;
 
 			context->mem_allocated += blksize;
+			pgstat_report_backend_mem_allocated_increase(blksize);
 
 			/* initialize the new block */
 			GenerationBlockInit(set, block, blksize);
@@ -726,6 +739,8 @@ GenerationFree(void *pointer)
 	dlist_delete(&block->node);
 
 	set->header.mem_allocated -= block->blksize;
+	pgstat_report_backend_mem_allocated_decrease(block->blksize);
+
 	free(block);
 }
 
diff --git a/src/backend/utils/mmgr/slab.c b/src/backend/utils/mmgr/slab.c
index 1a0b28f9ea..efdc2736c1 100644
--- a/src/backend/utils/mmgr/slab.c
+++ b/src/backend/utils/mmgr/slab.c
@@ -53,6 +53,7 @@
 #include "postgres.h"
 
 #include "lib/ilist.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -238,6 +239,12 @@ SlabContextCreate(MemoryContext parent,
 						parent,
 						name);
 
+	/*
+	 * If SlabContextCreate is updated to add headerSize to
+	 * context->mem_allocated, then update here and SlabDelete appropriately
+	 */
+	pgstat_report_backend_mem_allocated_increase(headerSize);
+
 	return (MemoryContext) slab;
 }
 
@@ -253,6 +260,7 @@ SlabReset(MemoryContext context)
 {
 	SlabContext *slab = (SlabContext *) context;
 	int			i;
+	uint64		deallocation = 0;
 
 	AssertArg(SlabIsValid(slab));
 
@@ -278,9 +286,11 @@ SlabReset(MemoryContext context)
 			free(block);
 			slab->nblocks--;
 			context->mem_allocated -= slab->blockSize;
+			deallocation += slab->blockSize;
 		}
 	}
 
+	pgstat_report_backend_mem_allocated_decrease(deallocation);
 	slab->minFreeChunks = 0;
 
 	Assert(slab->nblocks == 0);
@@ -294,8 +304,17 @@ SlabReset(MemoryContext context)
 void
 SlabDelete(MemoryContext context)
 {
+	/*
+	 * Until header allocation is included in context->mem_allocated, cast to
+	 * slab and decrement the headerSize
+	 */
+	SlabContext *slab = castNode(SlabContext, context);
+
 	/* Reset to release all the SlabBlocks */
 	SlabReset(context);
+
+	pgstat_report_backend_mem_allocated_decrease(slab->headerSize);
+
 	/* And free the context header */
 	free(context);
 }
@@ -364,6 +383,7 @@ SlabAlloc(MemoryContext context, Size size)
 		slab->minFreeChunks = slab->chunksPerBlock;
 		slab->nblocks += 1;
 		context->mem_allocated += slab->blockSize;
+		pgstat_report_backend_mem_allocated_increase(slab->blockSize);
 	}
 
 	/* grab the block from the freelist (even the new block is there) */
@@ -537,6 +557,7 @@ SlabFree(void *pointer)
 		free(block);
 		slab->nblocks--;
 		slab->header.mem_allocated -= slab->blockSize;
+		pgstat_report_backend_mem_allocated_decrease(slab->blockSize);
 	}
 	else
 		dlist_push_head(&slab->freelist[block->nfree], &block->node);
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 62a5b8e655..737a7c5034 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -5347,9 +5347,9 @@
   proname => 'pg_stat_get_activity', prorows => '100', proisstrict => 'f',
   proretset => 't', provolatile => 's', proparallel => 'r',
   prorettype => 'record', proargtypes => 'int4',
-  proallargtypes => '{int4,oid,int4,oid,text,text,text,text,text,timestamptz,timestamptz,timestamptz,timestamptz,inet,text,int4,xid,xid,text,bool,text,text,int4,text,numeric,text,bool,text,bool,int4,int8}',
-  proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
-  proargnames => '{pid,datid,pid,usesysid,application_name,state,query,wait_event_type,wait_event,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,backend_type,ssl,sslversion,sslcipher,sslbits,ssl_client_dn,ssl_client_serial,ssl_issuer_dn,gss_auth,gss_princ,gss_enc,leader_pid,query_id}',
+  proallargtypes => '{int4,oid,int4,oid,text,text,text,text,text,timestamptz,timestamptz,timestamptz,timestamptz,inet,text,int4,xid,xid,text,bool,text,text,int4,text,numeric,text,bool,text,bool,int4,int8,int8}',
+  proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
+  proargnames => '{pid,datid,pid,usesysid,application_name,state,query,wait_event_type,wait_event,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,backend_type,ssl,sslversion,sslcipher,sslbits,ssl_client_dn,ssl_client_serial,ssl_issuer_dn,gss_auth,gss_princ,gss_enc,leader_pid,query_id,backend_mem_allocated}',
   prosrc => 'pg_stat_get_activity' },
 { oid => '3318',
   descr => 'statistics: information about progress of backends running maintenance command',
diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h
index b582b46e9f..d59a1d50f6 100644
--- a/src/include/utils/backend_status.h
+++ b/src/include/utils/backend_status.h
@@ -169,6 +169,9 @@ typedef struct PgBackendStatus
 
 	/* query identifier, optionally computed using post_parse_analyze_hook */
 	uint64		st_query_id;
+
+	/* Current memory allocated to this backend */
+	uint64		backend_mem_allocated;
 } PgBackendStatus;
 
 
@@ -313,7 +316,9 @@ extern const char *pgstat_get_backend_current_activity(int pid, bool checkUser);
 extern const char *pgstat_get_crashed_backend_activity(int pid, char *buffer,
 													   int buflen);
 extern uint64 pgstat_get_my_query_id(void);
-
+extern void pgstat_report_backend_mem_allocated_increase(uint64 allocation);
+extern void pgstat_report_backend_mem_allocated_decrease(uint64 deallocation);
+extern uint64 pgstat_get_all_backend_memory_allocated(void);
 
 /* ----------
  * Support functions for the SQL-callable functions to
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index bfcd8ac9a0..36947c636d 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1752,9 +1752,10 @@ pg_stat_activity| SELECT s.datid,
     s.backend_xid,
     s.backend_xmin,
     s.query_id,
+    s.backend_mem_allocated,
     s.query,
     s.backend_type
-   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, backend_mem_allocated)
      LEFT JOIN pg_database d ON ((s.datid = d.oid)))
      LEFT JOIN pg_authid u ON ((s.usesysid = u.oid)));
 pg_stat_all_indexes| SELECT c.oid AS relid,
@@ -1869,7 +1870,7 @@ pg_stat_gssapi| SELECT s.pid,
     s.gss_auth AS gss_authenticated,
     s.gss_princ AS principal,
     s.gss_enc AS encrypted
-   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, backend_mem_allocated)
   WHERE (s.client_port IS NOT NULL);
 pg_stat_progress_analyze| SELECT s.pid,
     s.datid,
@@ -2050,7 +2051,7 @@ pg_stat_replication| SELECT s.pid,
     w.sync_priority,
     w.sync_state,
     w.reply_time
-   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, backend_mem_allocated)
      JOIN pg_stat_get_wal_senders() w(pid, state, sent_lsn, write_lsn, flush_lsn, replay_lsn, write_lag, flush_lag, replay_lag, sync_priority, sync_state, reply_time) ON ((s.pid = w.pid)))
      LEFT JOIN pg_authid u ON ((s.usesysid = u.oid)));
 pg_stat_replication_slots| SELECT s.slot_name,
@@ -2084,7 +2085,7 @@ pg_stat_ssl| SELECT s.pid,
     s.ssl_client_dn AS client_dn,
     s.ssl_client_serial AS client_serial,
     s.ssl_issuer_dn AS issuer_dn
-   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, backend_mem_allocated)
   WHERE (s.client_port IS NOT NULL);
 pg_stat_subscription| SELECT su.oid AS subid,
     su.subname,
-- 
2.25.1

0002-Add-the-ability-to-limit-the-amount-of-memory-that-c.patchtext/x-patch; charset=UTF-8; name=0002-Add-the-ability-to-limit-the-amount-of-memory-that-c.patchDownload
From 7c6735a34d22fde1a5103bd962d0a45f1322e87d Mon Sep 17 00:00:00 2001
From: Reid Thompson <jreidthompson@nc.rr.com>
Date: Sat, 4 Jun 2022 22:23:59 -0400
Subject: [PATCH 2/2] Add the ability to limit the amount of memory that can be
 allocated to backends.

This builds on the work that adds backend memory allocated to pg_stat_activity.

Add GUC variable max_total_backend_memory.

Specifies a limit to the amount of memory (in MB) that may be allocated to
backends in total (i.e. this is not a per user or per backend limit). If unset,
or set to 0 it is disabled. It is intended as a resource to help avoid the OOM
killer on LINUX and manage resources in general. A backend request that would
push the total over the limit will be denied with an out of memory error causing
that backend's current query/transaction to fail. Due to the dynamic nature of
memory allocations, this limit is not exact. If within 1.5MB of the limit and
two backends request 1MB each at the same time both may be allocated, and exceed
the limit. Further requests will not be allocated until dropping below the
limit. Keep this in mind when setting this value. This limit does not affect
auxiliary backend processes. Backend memory allocations are displayed in the
pg_stat_activity view.
---
 doc/src/sgml/config.sgml                      |  26 ++++
 src/backend/storage/ipc/dsm_impl.c            |  12 ++
 src/backend/utils/activity/backend_status.c   | 111 +++++++++++++++++-
 src/backend/utils/misc/guc_tables.c           |  11 ++
 src/backend/utils/misc/postgresql.conf.sample |   3 +
 src/backend/utils/mmgr/aset.c                 |  17 +++
 src/backend/utils/mmgr/generation.c           |  11 +-
 src/backend/utils/mmgr/slab.c                 |   8 ++
 src/include/utils/backend_status.h            |   2 +
 9 files changed, 199 insertions(+), 2 deletions(-)

diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 559eb898a9..4d22491a7e 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -2079,6 +2079,32 @@ include_dir 'conf.d'
       </listitem>
      </varlistentry>
 
+     <varlistentry id="guc-max-total-backend-memory" xreflabel="max_total_backend_memory">
+      <term><varname>max_total_backend_memory</varname> (<type>integer</type>)
+      <indexterm>
+       <primary><varname>max_total_backend_memory</varname> configuration parameter</primary>
+      </indexterm>
+      </term>
+      <listitem>
+       <para>
+        Specifies a limit to the amount of memory (MB) that may be allocated to
+        backends in total (i.e. this is not a per user or per backend limit).
+        If unset, or set to 0 it is disabled.  A backend request that would
+        push the total over the limit will be denied with an out of memory
+        error causing that backend's current query/transaction to fail. Due to
+        the dynamic nature of memory allocations, this limit is not exact. If
+        within 1.5MB of the limit and two backends request 1MB each at the same
+        time both may be allocated, and exceed the limit. Further requests will
+        not be allocated until dropping below the limit. Keep this in mind when
+        setting this value. This limit does not affect auxiliary backend
+        processes <xref linkend="glossary-auxiliary-proc"/> . Backend memory
+        allocations (<varname>backend_mem_allocated</varname>) are displayed in
+        the <link linkend="monitoring-pg-stat-activity-view"><structname>pg_stat_activity</structname></link>
+        view.
+       </para>
+      </listitem>
+     </varlistentry>
+
      </variablelist>
      </sect2>
 
diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c
index 3356bb65b5..cc061056a3 100644
--- a/src/backend/storage/ipc/dsm_impl.c
+++ b/src/backend/storage/ipc/dsm_impl.c
@@ -253,6 +253,10 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 		return true;
 	}
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+		return false;
+
 	/*
 	 * Create new segment or open an existing one for attach.
 	 *
@@ -524,6 +528,10 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 		int			flags = IPCProtection;
 		size_t		segsize;
 
+		/* Do not exceed maximum allowed memory allocation */
+		if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+			return false;
+
 		/*
 		 * Allocate the memory BEFORE acquiring the resource, so that we don't
 		 * leak the resource if memory allocation fails.
@@ -718,6 +726,10 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 		return true;
 	}
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+		return false;
+
 	/* Create new segment or open an existing one for attach. */
 	if (op == DSM_OP_CREATE)
 	{
diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c
index 5c33824eb8..872fe66188 100644
--- a/src/backend/utils/activity/backend_status.c
+++ b/src/backend/utils/activity/backend_status.c
@@ -45,6 +45,9 @@
 bool		pgstat_track_activities = false;
 int			pgstat_track_activity_query_size = 1024;
 
+/* Max backend memory allocation allowed (MB). 0 = disabled */
+int			max_total_bkend_mem = 0;
+
 
 /* exposed so that backend_progress.c can access it */
 PgBackendStatus *MyBEEntry = NULL;
@@ -1278,7 +1281,7 @@ pgstat_report_backend_mem_allocated_decrease(uint64 deallocation)
 	 */
 	if (deallocation > beentry->backend_mem_allocated)
 	{
-		ereport(LOG, errmsg("decrease reduces reported backend memory allocated below zero; setting reported to 0"));
+		ereport(LOG, errmsg("deallocation would decrease backend memory below zero; setting reported to 0"));
 
 		/*
 		 * Overwrite deallocation with current backend_mem_allocated so we end
@@ -1296,3 +1299,109 @@ pgstat_report_backend_mem_allocated_decrease(uint64 deallocation)
 	beentry->backend_mem_allocated -= deallocation;
 	PGSTAT_END_WRITE_ACTIVITY(beentry);
 }
+
+/* ----------
+ * pgstat_get_all_backend_memory_allocated() -
+ *
+ *	Return a uint64 representing the current shared memory allocated to all
+ *	backends.  This looks directly at the BackendStatusArray, and so will
+ *	provide current information regardless of the age of our transaction's
+ *	snapshot of the status array.
+ *	In the future we will likely utilize additional values - perhaps limit
+ *	backend allocation by user/role, etc.
+ * ----------
+ */
+uint64
+pgstat_get_all_backend_memory_allocated(void)
+{
+	PgBackendStatus *beentry;
+	int			i;
+	uint64		all_backend_memory_allocated = 0;
+
+	beentry = BackendStatusArray;
+
+	/*
+	 * We probably shouldn't get here before shared memory has been set up,
+	 * but be safe.
+	 */
+	if (beentry == NULL || BackendActivityBuffer == NULL)
+		return 0;
+
+	/*
+	 * We include AUX procs in all backend memory calculation
+	 */
+	for (i = 1; i <= NumBackendStatSlots; i++)
+	{
+		/*
+		 * We use a volatile pointer here to ensure the compiler doesn't try
+		 * to get cute.
+		 */
+		volatile PgBackendStatus *vbeentry = beentry;
+		bool		found;
+		uint64		backend_mem_allocated = 0;
+
+		for (;;)
+		{
+			int			before_changecount;
+			int			after_changecount;
+
+			pgstat_begin_read_activity(vbeentry, before_changecount);
+
+			/*
+			 * Ignore invalid entries, which may contain invalid data.
+			 * See pgstat_beshutdown_hook()
+			 */
+			if (vbeentry->st_procpid > 0)
+				backend_mem_allocated = vbeentry->backend_mem_allocated;
+
+			pgstat_end_read_activity(vbeentry, after_changecount);
+
+			if ((found = pgstat_read_activity_complete(before_changecount,
+													   after_changecount)))
+				break;
+
+			/* Make sure we can break out of loop if stuck... */
+			CHECK_FOR_INTERRUPTS();
+		}
+
+		if (found)
+			all_backend_memory_allocated += backend_mem_allocated;
+
+		beentry++;
+	}
+
+	return all_backend_memory_allocated;
+}
+
+/*
+ * Determine if allocation request will exceed max backend memory allowed.
+ * Do not apply to auxiliary processes.
+ */
+bool
+exceeds_max_total_bkend_mem(uint64 allocation_request)
+{
+	bool		result = false;
+
+	/* Exclude auxiliary processes from the check */
+	if (MyAuxProcType != NotAnAuxProcess)
+		return result;
+
+	/* Convert max_total_bkend_mem to bytes for comparison */
+	if (max_total_bkend_mem &&
+		pgstat_get_all_backend_memory_allocated() +
+		allocation_request > (uint64) max_total_bkend_mem * 1024 * 1024)
+	{
+		/*
+		 * Explicitly identify the OOM being a result of this configuration
+		 * parameter vs a system failure to allocate OOM.
+		 */
+		ereport(WARNING,
+				errmsg("allocation would exceed max_total_backend_memory limit (%llu > %llu)",
+					   (unsigned long long) pgstat_get_all_backend_memory_allocated() +
+					   allocation_request, (unsigned long long) max_total_bkend_mem * 1024 * 1024));
+
+		result = true;
+	}
+
+	return result;
+}
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index 05ab087934..745cc2ca9c 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -3405,6 +3405,17 @@ struct config_int ConfigureNamesInt[] =
 		NULL, NULL, NULL
 	},
 
+	{
+		{"max_total_backend_memory", PGC_SU_BACKEND, RESOURCES_MEM,
+			gettext_noop("Restrict total backend memory allocations to this max."),
+			gettext_noop("0 turns this feature off."),
+			GUC_UNIT_MB
+		},
+		&max_total_bkend_mem,
+		0, 0, INT_MAX,
+		NULL, NULL, NULL
+	},
+
 	/* End-of-list marker */
 	{
 		{NULL, 0, 0, NULL, NULL}, NULL, 0, 0, 0, NULL, NULL, NULL
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 868d21c351..1ce0dee6d0 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -155,6 +155,9 @@
 					#   mmap
 					# (change requires restart)
 #min_dynamic_shared_memory = 0MB	# (change requires restart)
+#max_total_backend_memory = 0MB		# Restrict total backend memory allocations
+									# to this max (in MB). 0 turns this feature
+									# off.
 
 # - Disk -
 
diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index f6d1333f3d..5c659dc0fc 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -440,6 +440,10 @@ AllocSetContextCreateInternal(MemoryContext parent,
 	else
 		firstBlockSize = Max(firstBlockSize, initBlockSize);
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (exceeds_max_total_bkend_mem(firstBlockSize))
+		return NULL;
+
 	/*
 	 * Allocate the initial block.  Unlike other aset.c blocks, it starts with
 	 * the context header and its block header follows that.
@@ -742,6 +746,11 @@ AllocSetAlloc(MemoryContext context, Size size)
 #endif
 
 		blksize = chunk_size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
+
+		/* Do not exceed maximum allowed memory allocation */
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		block = (AllocBlock) malloc(blksize);
 		if (block == NULL)
 			return NULL;
@@ -939,6 +948,10 @@ AllocSetAlloc(MemoryContext context, Size size)
 		while (blksize < required_size)
 			blksize <<= 1;
 
+		/* Do not exceed maximum allowed memory allocation */
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		/* Try to allocate it */
 		block = (AllocBlock) malloc(blksize);
 
@@ -1179,6 +1192,10 @@ AllocSetRealloc(void *pointer, Size size)
 		blksize = chksize + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
 		oldblksize = block->endptr - ((char *) block);
 
+		/* Do not exceed maximum allowed memory allocation */
+		if (blksize > oldblksize && exceeds_max_total_bkend_mem(blksize - oldblksize))
+			return NULL;
+
 		block = (AllocBlock) realloc(block, blksize);
 		if (block == NULL)
 		{
diff --git a/src/backend/utils/mmgr/generation.c b/src/backend/utils/mmgr/generation.c
index 7bb9175f6d..ef2e11aefc 100644
--- a/src/backend/utils/mmgr/generation.c
+++ b/src/backend/utils/mmgr/generation.c
@@ -201,6 +201,9 @@ GenerationContextCreate(MemoryContext parent,
 	else
 		allocSize = Max(allocSize, initBlockSize);
 
+	if (exceeds_max_total_bkend_mem(allocSize))
+		return NULL;
+
 	/*
 	 * Allocate the initial block.  Unlike other generation.c blocks, it
 	 * starts with the context header and its block header follows that.
@@ -285,7 +288,7 @@ GenerationReset(MemoryContext context)
 {
 	GenerationContext *set = (GenerationContext *) context;
 	dlist_mutable_iter miter;
-	uint64	deallocation = 0;
+	uint64		deallocation = 0;
 
 	AssertArg(GenerationIsValid(set));
 
@@ -380,6 +383,9 @@ GenerationAlloc(MemoryContext context, Size size)
 	{
 		Size		blksize = required_size + Generation_BLOCKHDRSZ;
 
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		block = (GenerationBlock *) malloc(blksize);
 		if (block == NULL)
 			return NULL;
@@ -483,6 +489,9 @@ GenerationAlloc(MemoryContext context, Size size)
 			if (blksize < required_size)
 				blksize = pg_nextpower2_size_t(required_size);
 
+			if (exceeds_max_total_bkend_mem(blksize))
+				return NULL;
+
 			block = (GenerationBlock *) malloc(blksize);
 
 			if (block == NULL)
diff --git a/src/backend/utils/mmgr/slab.c b/src/backend/utils/mmgr/slab.c
index efdc2736c1..6ec512defd 100644
--- a/src/backend/utils/mmgr/slab.c
+++ b/src/backend/utils/mmgr/slab.c
@@ -197,6 +197,10 @@ SlabContextCreate(MemoryContext parent,
 	headerSize += chunksPerBlock * sizeof(bool);
 #endif
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (exceeds_max_total_bkend_mem(headerSize))
+		return NULL;
+
 	slab = (SlabContext *) malloc(headerSize);
 	if (slab == NULL)
 	{
@@ -351,6 +355,10 @@ SlabAlloc(MemoryContext context, Size size)
 	 */
 	if (slab->minFreeChunks == 0)
 	{
+		/* Do not exceed maximum allowed memory allocation */
+		if (exceeds_max_total_bkend_mem(slab->blockSize))
+			return NULL;
+
 		block = (SlabBlock *) malloc(slab->blockSize);
 
 		if (block == NULL)
diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h
index d59a1d50f6..0403a24eef 100644
--- a/src/include/utils/backend_status.h
+++ b/src/include/utils/backend_status.h
@@ -278,6 +278,7 @@ typedef struct LocalPgBackendStatus
  */
 extern PGDLLIMPORT bool pgstat_track_activities;
 extern PGDLLIMPORT int pgstat_track_activity_query_size;
+extern PGDLLIMPORT int max_total_bkend_mem;
 
 
 /* ----------
@@ -329,6 +330,7 @@ extern int	pgstat_fetch_stat_numbackends(void);
 extern PgBackendStatus *pgstat_fetch_stat_beentry(BackendId beid);
 extern LocalPgBackendStatus *pgstat_fetch_stat_local_beentry(int beid);
 extern char *pgstat_clip_activity(const char *raw_activity);
+extern bool exceeds_max_total_bkend_mem(uint64 allocation_request);
 
 
 #endif							/* BACKEND_STATUS_H */
-- 
2.25.1

#16Reid Thompson
reid.thompson@crunchydata.com
In reply to: Reid Thompson (#15)
2 attachment(s)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On Tue, 2022-10-25 at 11:49 -0400, Reid Thompson wrote:

Hi Arne,

On Mon, 2022-10-24 at 15:27 +0000, Arne Roland wrote:

Hello Reid,

could you rebase the patch again? It doesn't apply currently
(http://cfbot.cputube.org/patch_40_3867.log). Thanks!

rebased patches attached.

Rebased to current. Add a couple changes per conversation with D
Christensen (include units in field name, group field with backend_xid
and backend_xmin fields in pg_stat_activity view, rather than between
query_id and query)

--
Reid Thompson
Senior Software Engineer
Crunchy Data, Inc.

reid.thompson@crunchydata.com
www.crunchydata.com

Attachments:

0002-Add-the-ability-to-limit-the-amount-of-memory-that-c.patchtext/x-patch; charset=UTF-8; name=0002-Add-the-ability-to-limit-the-amount-of-memory-that-c.patchDownload
From 9cf35c79be107feedb63f6f674ac9d2347d1875e Mon Sep 17 00:00:00 2001
From: Reid Thompson <jreidthompson@nc.rr.com>
Date: Sat, 4 Jun 2022 22:23:59 -0400
Subject: [PATCH 2/2] Add the ability to limit the amount of memory that can be
 allocated to backends.

This builds on the work that adds backend memory allocated to pg_stat_activity.

Add GUC variable max_total_backend_memory.

Specifies a limit to the amount of memory (in MB) that may be allocated to
backends in total (i.e. this is not a per user or per backend limit). If unset,
or set to 0 it is disabled. It is intended as a resource to help avoid the OOM
killer on LINUX and manage resources in general. A backend request that would
push the total over the limit will be denied with an out of memory error causing
that backend's current query/transaction to fail. Due to the dynamic nature of
memory allocations, this limit is not exact. If within 1.5MB of the limit and
two backends request 1MB each at the same time both may be allocated, and exceed
the limit. Further requests will not be allocated until dropping below the
limit. Keep this in mind when setting this value. This limit does not affect
auxiliary backend processes. Backend memory allocations are displayed in the
pg_stat_activity view.
---
 doc/src/sgml/config.sgml                      |  26 ++++
 src/backend/storage/ipc/dsm_impl.c            |  12 ++
 src/backend/utils/activity/backend_status.c   | 111 +++++++++++++++++-
 src/backend/utils/misc/guc_tables.c           |  11 ++
 src/backend/utils/misc/postgresql.conf.sample |   3 +
 src/backend/utils/mmgr/aset.c                 |  17 +++
 src/backend/utils/mmgr/generation.c           |   9 ++
 src/backend/utils/mmgr/slab.c                 |   8 ++
 src/include/utils/backend_status.h            |   2 +
 9 files changed, 198 insertions(+), 1 deletion(-)

diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 559eb898a9..5762999fa5 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -2079,6 +2079,32 @@ include_dir 'conf.d'
       </listitem>
      </varlistentry>
 
+     <varlistentry id="guc-max-total-backend-memory" xreflabel="max_total_backend_memory">
+      <term><varname>max_total_backend_memory</varname> (<type>integer</type>)
+      <indexterm>
+       <primary><varname>max_total_backend_memory</varname> configuration parameter</primary>
+      </indexterm>
+      </term>
+      <listitem>
+       <para>
+        Specifies a limit to the amount of memory (MB) that may be allocated to
+        backends in total (i.e. this is not a per user or per backend limit).
+        If unset, or set to 0 it is disabled.  A backend request that would
+        push the total over the limit will be denied with an out of memory
+        error causing that backend's current query/transaction to fail. Due to
+        the dynamic nature of memory allocations, this limit is not exact. If
+        within 1.5MB of the limit and two backends request 1MB each at the same
+        time both may be allocated, and exceed the limit. Further requests will
+        not be allocated until dropping below the limit. Keep this in mind when
+        setting this value. This limit does not affect auxiliary backend
+        processes <xref linkend="glossary-auxiliary-proc"/> . Backend memory
+        allocations (<varname>backend_allocated_bytes</varname>) are displayed in
+        the <link linkend="monitoring-pg-stat-activity-view"><structname>pg_stat_activity</structname></link>
+        view.
+       </para>
+      </listitem>
+     </varlistentry>
+
      </variablelist>
      </sect2>
 
diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c
index eae03159c3..aaf74e9486 100644
--- a/src/backend/storage/ipc/dsm_impl.c
+++ b/src/backend/storage/ipc/dsm_impl.c
@@ -254,6 +254,10 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 		return true;
 	}
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+		return false;
+
 	/*
 	 * Create new segment or open an existing one for attach.
 	 *
@@ -525,6 +529,10 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 		int			flags = IPCProtection;
 		size_t		segsize;
 
+		/* Do not exceed maximum allowed memory allocation */
+		if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+			return false;
+
 		/*
 		 * Allocate the memory BEFORE acquiring the resource, so that we don't
 		 * leak the resource if memory allocation fails.
@@ -719,6 +727,10 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 		return true;
 	}
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+		return false;
+
 	/* Create new segment or open an existing one for attach. */
 	if (op == DSM_OP_CREATE)
 	{
diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c
index 30a89e899a..5500ed4f37 100644
--- a/src/backend/utils/activity/backend_status.c
+++ b/src/backend/utils/activity/backend_status.c
@@ -45,6 +45,9 @@
 bool		pgstat_track_activities = false;
 int			pgstat_track_activity_query_size = 1024;
 
+/* Max backend memory allocation allowed (MB). 0 = disabled */
+int			max_total_bkend_mem = 0;
+
 
 /* exposed so that backend_progress.c can access it */
 PgBackendStatus *MyBEEntry = NULL;
@@ -1278,7 +1281,7 @@ pgstat_report_backend_allocated_bytes_decrease(uint64 deallocation)
 	 */
 	if (deallocation > beentry->backend_allocated_bytes)
 	{
-		ereport(LOG, errmsg("decrease reduces reported backend memory allocated below zero; setting reported to 0"));
+		ereport(LOG, errmsg("deallocation would decrease backend memory below zero; setting reported to 0"));
 
 		/*
 		 * Overwrite deallocation with current backend_allocated_bytes so we
@@ -1296,3 +1299,109 @@ pgstat_report_backend_allocated_bytes_decrease(uint64 deallocation)
 	beentry->backend_allocated_bytes -= deallocation;
 	PGSTAT_END_WRITE_ACTIVITY(beentry);
 }
+
+/* ----------
+ * pgstat_get_all_backend_memory_allocated() -
+ *
+ *	Return a uint64 representing the current shared memory allocated to all
+ *	backends.  This looks directly at the BackendStatusArray, and so will
+ *	provide current information regardless of the age of our transaction's
+ *	snapshot of the status array.
+ *	In the future we will likely utilize additional values - perhaps limit
+ *	backend allocation by user/role, etc.
+ * ----------
+ */
+uint64
+pgstat_get_all_backend_memory_allocated(void)
+{
+	PgBackendStatus *beentry;
+	int			i;
+	uint64		all_backend_memory_allocated = 0;
+
+	beentry = BackendStatusArray;
+
+	/*
+	 * We probably shouldn't get here before shared memory has been set up,
+	 * but be safe.
+	 */
+	if (beentry == NULL || BackendActivityBuffer == NULL)
+		return 0;
+
+	/*
+	 * We include AUX procs in all backend memory calculation
+	 */
+	for (i = 1; i <= NumBackendStatSlots; i++)
+	{
+		/*
+		 * We use a volatile pointer here to ensure the compiler doesn't try
+		 * to get cute.
+		 */
+		volatile PgBackendStatus *vbeentry = beentry;
+		bool		found;
+		uint64		backend_allocated_bytes = 0;
+
+		for (;;)
+		{
+			int			before_changecount;
+			int			after_changecount;
+
+			pgstat_begin_read_activity(vbeentry, before_changecount);
+
+			/*
+			 * Ignore invalid entries, which may contain invalid data.
+			 * See pgstat_beshutdown_hook()
+			 */
+			if (vbeentry->st_procpid > 0)
+				backend_allocated_bytes = vbeentry->backend_allocated_bytes;
+
+			pgstat_end_read_activity(vbeentry, after_changecount);
+
+			if ((found = pgstat_read_activity_complete(before_changecount,
+													   after_changecount)))
+				break;
+
+			/* Make sure we can break out of loop if stuck... */
+			CHECK_FOR_INTERRUPTS();
+		}
+
+		if (found)
+			all_backend_memory_allocated += backend_allocated_bytes;
+
+		beentry++;
+	}
+
+	return all_backend_memory_allocated;
+}
+
+/*
+ * Determine if allocation request will exceed max backend memory allowed.
+ * Do not apply to auxiliary processes.
+ */
+bool
+exceeds_max_total_bkend_mem(uint64 allocation_request)
+{
+	bool		result = false;
+
+	/* Exclude auxiliary processes from the check */
+	if (MyAuxProcType != NotAnAuxProcess)
+		return result;
+
+	/* Convert max_total_bkend_mem to bytes for comparison */
+	if (max_total_bkend_mem &&
+		pgstat_get_all_backend_memory_allocated() +
+		allocation_request > (uint64) max_total_bkend_mem * 1024 * 1024)
+	{
+		/*
+		 * Explicitly identify the OOM being a result of this configuration
+		 * parameter vs a system failure to allocate OOM.
+		 */
+		ereport(WARNING,
+				errmsg("allocation would exceed max_total_backend_memory limit (%llu > %llu)",
+					   (unsigned long long) pgstat_get_all_backend_memory_allocated() +
+					   allocation_request, (unsigned long long) max_total_bkend_mem * 1024 * 1024));
+
+		result = true;
+	}
+
+	return result;
+}
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index 836b49484a..0e09766949 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -3403,6 +3403,17 @@ struct config_int ConfigureNamesInt[] =
 		NULL, NULL, NULL
 	},
 
+	{
+		{"max_total_backend_memory", PGC_SU_BACKEND, RESOURCES_MEM,
+			gettext_noop("Restrict total backend memory allocations to this max."),
+			gettext_noop("0 turns this feature off."),
+			GUC_UNIT_MB
+		},
+		&max_total_bkend_mem,
+		0, 0, INT_MAX,
+		NULL, NULL, NULL
+	},
+
 	/* End-of-list marker */
 	{
 		{NULL, 0, 0, NULL, NULL}, NULL, 0, 0, 0, NULL, NULL, NULL
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 868d21c351..1ce0dee6d0 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -155,6 +155,9 @@
 					#   mmap
 					# (change requires restart)
 #min_dynamic_shared_memory = 0MB	# (change requires restart)
+#max_total_backend_memory = 0MB		# Restrict total backend memory allocations
+									# to this max (in MB). 0 turns this feature
+									# off.
 
 # - Disk -
 
diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index 81e62e4981..cc865a89e0 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -440,6 +440,10 @@ AllocSetContextCreateInternal(MemoryContext parent,
 	else
 		firstBlockSize = Max(firstBlockSize, initBlockSize);
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (exceeds_max_total_bkend_mem(firstBlockSize))
+		return NULL;
+
 	/*
 	 * Allocate the initial block.  Unlike other aset.c blocks, it starts with
 	 * the context header and its block header follows that.
@@ -742,6 +746,11 @@ AllocSetAlloc(MemoryContext context, Size size)
 #endif
 
 		blksize = chunk_size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
+
+		/* Do not exceed maximum allowed memory allocation */
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		block = (AllocBlock) malloc(blksize);
 		if (block == NULL)
 			return NULL;
@@ -939,6 +948,10 @@ AllocSetAlloc(MemoryContext context, Size size)
 		while (blksize < required_size)
 			blksize <<= 1;
 
+		/* Do not exceed maximum allowed memory allocation */
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		/* Try to allocate it */
 		block = (AllocBlock) malloc(blksize);
 
@@ -1179,6 +1192,10 @@ AllocSetRealloc(void *pointer, Size size)
 		blksize = chksize + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
 		oldblksize = block->endptr - ((char *) block);
 
+		/* Do not exceed maximum allowed memory allocation */
+		if (blksize > oldblksize && exceeds_max_total_bkend_mem(blksize - oldblksize))
+			return NULL;
+
 		block = (AllocBlock) realloc(block, blksize);
 		if (block == NULL)
 		{
diff --git a/src/backend/utils/mmgr/generation.c b/src/backend/utils/mmgr/generation.c
index df3007edfb..495665d3b0 100644
--- a/src/backend/utils/mmgr/generation.c
+++ b/src/backend/utils/mmgr/generation.c
@@ -201,6 +201,9 @@ GenerationContextCreate(MemoryContext parent,
 	else
 		allocSize = Max(allocSize, initBlockSize);
 
+	if (exceeds_max_total_bkend_mem(allocSize))
+		return NULL;
+
 	/*
 	 * Allocate the initial block.  Unlike other generation.c blocks, it
 	 * starts with the context header and its block header follows that.
@@ -380,6 +383,9 @@ GenerationAlloc(MemoryContext context, Size size)
 	{
 		Size		blksize = required_size + Generation_BLOCKHDRSZ;
 
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		block = (GenerationBlock *) malloc(blksize);
 		if (block == NULL)
 			return NULL;
@@ -483,6 +489,9 @@ GenerationAlloc(MemoryContext context, Size size)
 			if (blksize < required_size)
 				blksize = pg_nextpower2_size_t(required_size);
 
+			if (exceeds_max_total_bkend_mem(blksize))
+				return NULL;
+
 			block = (GenerationBlock *) malloc(blksize);
 
 			if (block == NULL)
diff --git a/src/backend/utils/mmgr/slab.c b/src/backend/utils/mmgr/slab.c
index 532c038973..5b98176654 100644
--- a/src/backend/utils/mmgr/slab.c
+++ b/src/backend/utils/mmgr/slab.c
@@ -197,6 +197,10 @@ SlabContextCreate(MemoryContext parent,
 	headerSize += chunksPerBlock * sizeof(bool);
 #endif
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (exceeds_max_total_bkend_mem(headerSize))
+		return NULL;
+
 	slab = (SlabContext *) malloc(headerSize);
 	if (slab == NULL)
 	{
@@ -351,6 +355,10 @@ SlabAlloc(MemoryContext context, Size size)
 	 */
 	if (slab->minFreeChunks == 0)
 	{
+		/* Do not exceed maximum allowed memory allocation */
+		if (exceeds_max_total_bkend_mem(slab->blockSize))
+			return NULL;
+
 		block = (SlabBlock *) malloc(slab->blockSize);
 
 		if (block == NULL)
diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h
index 75d87e8308..c8beb116b8 100644
--- a/src/include/utils/backend_status.h
+++ b/src/include/utils/backend_status.h
@@ -278,6 +278,7 @@ typedef struct LocalPgBackendStatus
  */
 extern PGDLLIMPORT bool pgstat_track_activities;
 extern PGDLLIMPORT int pgstat_track_activity_query_size;
+extern PGDLLIMPORT int max_total_bkend_mem;
 
 
 /* ----------
@@ -329,6 +330,7 @@ extern int	pgstat_fetch_stat_numbackends(void);
 extern PgBackendStatus *pgstat_fetch_stat_beentry(BackendId beid);
 extern LocalPgBackendStatus *pgstat_fetch_stat_local_beentry(int beid);
 extern char *pgstat_clip_activity(const char *raw_activity);
+extern bool exceeds_max_total_bkend_mem(uint64 allocation_request);
 
 
 #endif							/* BACKEND_STATUS_H */
-- 
2.25.1

0001-Add-tracking-of-backend-memory-allocated-to-pg_stat_.patchtext/x-patch; charset=UTF-8; name=0001-Add-tracking-of-backend-memory-allocated-to-pg_stat_.patchDownload
From 8f729c59c3aa1a02d008795159a748e1592a9916 Mon Sep 17 00:00:00 2001
From: Reid Thompson <jreidthompson@nc.rr.com>
Date: Thu, 11 Aug 2022 12:01:25 -0400
Subject: [PATCH 1/2] Add tracking of backend memory allocated to
 pg_stat_activity

This new field displays the current bytes of memory allocated to the
backend process. It is updated as memory for the process is
malloc'd/free'd. Memory allocated to items on the freelist is included in
the displayed value.  Dynamic shared memory allocations are included
only in the value displayed for the backend that created them, they are
not included in the value for backends that are attached to them to
avoid double counting. On occasion, orphaned memory segments may be
cleaned up on postmaster startup. This may result in decreasing the sum
without a prior increment. We limit the floor of backend_mem_allocated
to zero. Updated pg_stat_activity documentation for the new column.
---
 doc/src/sgml/monitoring.sgml                |  12 +++
 src/backend/catalog/system_views.sql        |   1 +
 src/backend/storage/ipc/dsm_impl.c          |  81 +++++++++++++++
 src/backend/utils/activity/backend_status.c | 105 ++++++++++++++++++++
 src/backend/utils/adt/pgstatfuncs.c         |   4 +-
 src/backend/utils/mmgr/aset.c               |  18 ++++
 src/backend/utils/mmgr/generation.c         |  15 +++
 src/backend/utils/mmgr/slab.c               |  21 ++++
 src/include/catalog/pg_proc.dat             |   6 +-
 src/include/utils/backend_status.h          |   7 +-
 src/test/regress/expected/rules.out         |   9 +-
 11 files changed, 270 insertions(+), 9 deletions(-)

diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index e5d622d514..972805b85a 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -947,6 +947,18 @@ postgres   27093  0.0  0.0  30096  2752 ?        Ss   11:34   0:00 postgres: ser
      </para></entry>
     </row>
 
+    <row>
+     <entry role="catalog_table_entry"><para role="column_definition">
+      <structfield>backend_allocated_bytes</structfield> <type>bigint</type>
+     </para>
+     <para>
+      The byte count of memory allocated to this backend. Dynamic shared memory
+      allocations are included only in the value displayed for the backend that
+      created them, they are not included in the value for backends that are
+      attached to them to avoid double counting.
+     </para></entry>
+    </row>
+
      <row>
       <entry role="catalog_table_entry"><para role="column_definition">
        <structfield>query</structfield> <type>text</type>
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 2d8104b090..84d462aa97 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -864,6 +864,7 @@ CREATE VIEW pg_stat_activity AS
             S.state,
             S.backend_xid,
             s.backend_xmin,
+            S.backend_allocated_bytes,
             S.query_id,
             S.query,
             S.backend_type
diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c
index 6ddd46a4e7..eae03159c3 100644
--- a/src/backend/storage/ipc/dsm_impl.c
+++ b/src/backend/storage/ipc/dsm_impl.c
@@ -66,6 +66,7 @@
 #include "postmaster/postmaster.h"
 #include "storage/dsm_impl.h"
 #include "storage/fd.h"
+#include "utils/backend_status.h"
 #include "utils/guc.h"
 #include "utils/memutils.h"
 
@@ -232,6 +233,14 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_backend_allocated_bytes_decrease(*mapped_size);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && shm_unlink(name) != 0)
@@ -332,6 +341,36 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+	{
+		/*
+		 * Posix creation calls dsm_impl_posix_resize implying that resizing
+		 * occurs or may be added in the future. As implemented
+		 * dsm_impl_posix_resize utilizes fallocate or truncate, passing the
+		 * whole new size as input, growing the allocation as needed (only
+		 * truncate supports shrinking). We update by replacing the old
+		 * allocation with the new.
+		 */
+#if defined(HAVE_POSIX_FALLOCATE) && defined(__linux__)
+		/*
+		 * posix_fallocate does not shrink allocations, adjust only on
+		 * allocation increase.
+		 */
+		if (request_size > *mapped_size)
+		{
+			pgstat_report_backend_allocated_bytes_decrease(*mapped_size);
+			pgstat_report_backend_allocated_bytes_increase(request_size);
+		}
+#else
+		pgstat_report_backend_allocated_bytes_decrease(*mapped_size);
+		pgstat_report_backend_allocated_bytes_increase(request_size);
+#endif
+	}
 	*mapped_address = address;
 	*mapped_size = request_size;
 	close(fd);
@@ -537,6 +576,14 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_backend_allocated_bytes_decrease(*mapped_size);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && shmctl(ident, IPC_RMID, NULL) < 0)
@@ -584,6 +631,13 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_backend_allocated_bytes_increase(request_size);
 	*mapped_address = address;
 	*mapped_size = request_size;
 
@@ -652,6 +706,13 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 			return false;
 		}
 
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_backend_allocated_bytes_decrease(*mapped_size);
 		*impl_private = NULL;
 		*mapped_address = NULL;
 		*mapped_size = 0;
@@ -768,6 +829,12 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 		return false;
 	}
 
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_backend_allocated_bytes_increase(info.RegionSize);
 	*mapped_address = address;
 	*mapped_size = info.RegionSize;
 	*impl_private = hmap;
@@ -812,6 +879,13 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		pgstat_report_backend_allocated_bytes_decrease(*mapped_size);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && unlink(name) != 0)
@@ -933,6 +1007,13 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_backend_allocated_bytes_increase(request_size);
 	*mapped_address = address;
 	*mapped_size = request_size;
 
diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c
index 1146a6c33c..30a89e899a 100644
--- a/src/backend/utils/activity/backend_status.c
+++ b/src/backend/utils/activity/backend_status.c
@@ -49,6 +49,8 @@ int			pgstat_track_activity_query_size = 1024;
 /* exposed so that backend_progress.c can access it */
 PgBackendStatus *MyBEEntry = NULL;
 
+/* Memory allocated to this backend prior to pgstats initialization */
+uint64		backend_allocated_bytes = 0;
 
 static PgBackendStatus *BackendStatusArray = NULL;
 static char *BackendAppnameBuffer = NULL;
@@ -400,6 +402,13 @@ pgstat_bestart(void)
 	lbeentry.st_progress_command_target = InvalidOid;
 	lbeentry.st_query_id = UINT64CONST(0);
 
+	/*
+	 * Move sum of memory allocated prior to pgstats initialization to pgstats
+	 * and zero the local variable.
+	 */
+	lbeentry.backend_allocated_bytes = backend_allocated_bytes;
+	backend_allocated_bytes = 0;
+
 	/*
 	 * we don't zero st_progress_param here to save cycles; nobody should
 	 * examine it until st_progress_command has been set to something other
@@ -1191,3 +1200,99 @@ pgstat_clip_activity(const char *raw_activity)
 
 	return activity;
 }
+
+/* --------
+ * pgstat_report_backend_allocated_bytes_increase() -
+ *
+ * Called to report increase in memory allocated for this backend
+ * --------
+ */
+void
+pgstat_report_backend_allocated_bytes_increase(uint64 allocation)
+{
+	volatile PgBackendStatus *beentry = MyBEEntry;
+
+	if (!beentry || !pgstat_track_activities)
+	{
+		/*
+		 * Account for memory before pgstats is initialized. This will be
+		 * migrated to pgstats on initialization.
+		 */
+		backend_allocated_bytes += allocation;
+
+		return;
+	}
+
+	/*
+	 * Update my status entry, following the protocol of bumping
+	 * st_changecount before and after.  We use a volatile pointer here to
+	 * ensure the compiler doesn't try to get cute.
+	 */
+	PGSTAT_BEGIN_WRITE_ACTIVITY(beentry);
+	beentry->backend_allocated_bytes += allocation;
+	PGSTAT_END_WRITE_ACTIVITY(beentry);
+}
+
+/* --------
+ * pgstat_report_backend_allocated_bytes_decrease() -
+ *
+ * Called to report decrease in memory allocated for this backend
+ * --------
+ */
+void
+pgstat_report_backend_allocated_bytes_decrease(uint64 deallocation)
+{
+	volatile PgBackendStatus *beentry = MyBEEntry;
+
+	/*
+	 * Cases may occur where shared memory from a previous postmaster
+	 * invocation still exist. These are cleaned up at startup by
+	 * dsm_cleanup_using_control_segment. Limit decreasing memory allocated to
+	 * zero in case no corresponding prior increase exists or decrease has
+	 * already been accounted for.
+	 */
+
+	if (!beentry || !pgstat_track_activities)
+	{
+		/*
+		 * Account for memory before pgstats is initialized. This will be
+		 * migrated to pgstats on initialization. Do not allow
+		 * backend_allocated_bytes to go below zero. If pgstats has not been
+		 * initialized, we are in startup and we set backend_allocated_bytes
+		 * to zero in cases where it would go negative and skip generating an
+		 * ereport.
+		 */
+		if (deallocation > backend_allocated_bytes)
+			backend_allocated_bytes = 0;
+		else
+			backend_allocated_bytes -= deallocation;
+
+		return;
+	}
+
+	/*
+	 * Do not allow backend_allocated_bytes to go below zero. ereport if we
+	 * would have. There's no need for a lock around the read here as it's
+	 * being referenced from the same backend which means that there shouldn't
+	 * be concurrent writes. We want to generate an ereport in these cases.
+	 */
+	if (deallocation > beentry->backend_allocated_bytes)
+	{
+		ereport(LOG, errmsg("decrease reduces reported backend memory allocated below zero; setting reported to 0"));
+
+		/*
+		 * Overwrite deallocation with current backend_allocated_bytes so we
+		 * end up at zero.
+		 */
+		deallocation = beentry->backend_allocated_bytes;
+	}
+
+	/*
+	 * Update my status entry, following the protocol of bumping
+	 * st_changecount before and after.  We use a volatile pointer here to
+	 * ensure the compiler doesn't try to get cute.
+	 */
+	PGSTAT_BEGIN_WRITE_ACTIVITY(beentry);
+	beentry->backend_allocated_bytes -= deallocation;
+	PGSTAT_END_WRITE_ACTIVITY(beentry);
+}
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 96bffc0f2a..b6d135ad2f 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -553,7 +553,7 @@ pg_stat_get_progress_info(PG_FUNCTION_ARGS)
 Datum
 pg_stat_get_activity(PG_FUNCTION_ARGS)
 {
-#define PG_STAT_GET_ACTIVITY_COLS	30
+#define PG_STAT_GET_ACTIVITY_COLS	31
 	int			num_backends = pgstat_fetch_stat_numbackends();
 	int			curr_backend;
 	int			pid = PG_ARGISNULL(0) ? -1 : PG_GETARG_INT32(0);
@@ -609,6 +609,8 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
 		else
 			nulls[16] = true;
 
+		values[30] = UInt64GetDatum(beentry->backend_allocated_bytes);
+
 		/* Values only available to role member or pg_read_all_stats */
 		if (HAS_PGSTAT_PERMISSIONS(beentry->st_userid))
 		{
diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index b6a8bbcd59..81e62e4981 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -47,6 +47,7 @@
 #include "postgres.h"
 
 #include "port/pg_bitutils.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -521,6 +522,7 @@ AllocSetContextCreateInternal(MemoryContext parent,
 						name);
 
 	((MemoryContext) set)->mem_allocated = firstBlockSize;
+	pgstat_report_backend_allocated_bytes_increase(firstBlockSize);
 
 	return (MemoryContext) set;
 }
@@ -543,6 +545,7 @@ AllocSetReset(MemoryContext context)
 	AllocSet	set = (AllocSet) context;
 	AllocBlock	block;
 	Size		keepersize PG_USED_FOR_ASSERTS_ONLY;
+	uint64		deallocation = 0;
 
 	Assert(AllocSetIsValid(set));
 
@@ -585,6 +588,7 @@ AllocSetReset(MemoryContext context)
 		{
 			/* Normal case, release the block */
 			context->mem_allocated -= block->endptr - ((char *) block);
+			deallocation += block->endptr - ((char *) block);
 
 #ifdef CLOBBER_FREED_MEMORY
 			wipe_mem(block, block->freeptr - ((char *) block));
@@ -595,6 +599,7 @@ AllocSetReset(MemoryContext context)
 	}
 
 	Assert(context->mem_allocated == keepersize);
+	pgstat_report_backend_allocated_bytes_decrease(deallocation);
 
 	/* Reset block size allocation sequence, too */
 	set->nextBlockSize = set->initBlockSize;
@@ -613,6 +618,7 @@ AllocSetDelete(MemoryContext context)
 	AllocSet	set = (AllocSet) context;
 	AllocBlock	block = set->blocks;
 	Size		keepersize PG_USED_FOR_ASSERTS_ONLY;
+	uint64		deallocation = 0;
 
 	Assert(AllocSetIsValid(set));
 
@@ -651,11 +657,13 @@ AllocSetDelete(MemoryContext context)
 
 				freelist->first_free = (AllocSetContext *) oldset->header.nextchild;
 				freelist->num_free--;
+				deallocation += oldset->header.mem_allocated;
 
 				/* All that remains is to free the header/initial block */
 				free(oldset);
 			}
 			Assert(freelist->num_free == 0);
+			pgstat_report_backend_allocated_bytes_decrease(deallocation);
 		}
 
 		/* Now add the just-deleted context to the freelist. */
@@ -672,7 +680,10 @@ AllocSetDelete(MemoryContext context)
 		AllocBlock	next = block->next;
 
 		if (block != set->keeper)
+		{
 			context->mem_allocated -= block->endptr - ((char *) block);
+			deallocation += block->endptr - ((char *) block);
+		}
 
 #ifdef CLOBBER_FREED_MEMORY
 		wipe_mem(block, block->freeptr - ((char *) block));
@@ -685,6 +696,8 @@ AllocSetDelete(MemoryContext context)
 	}
 
 	Assert(context->mem_allocated == keepersize);
+	pgstat_report_backend_allocated_bytes_decrease(deallocation +
+												   context->mem_allocated);
 
 	/* Finally, free the context header, including the keeper block */
 	free(set);
@@ -734,6 +747,7 @@ AllocSetAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_backend_allocated_bytes_increase(blksize);
 
 		block->aset = set;
 		block->freeptr = block->endptr = ((char *) block) + blksize;
@@ -944,6 +958,7 @@ AllocSetAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_backend_allocated_bytes_increase(blksize);
 
 		block->aset = set;
 		block->freeptr = ((char *) block) + ALLOC_BLOCKHDRSZ;
@@ -1043,6 +1058,7 @@ AllocSetFree(void *pointer)
 			block->next->prev = block->prev;
 
 		set->header.mem_allocated -= block->endptr - ((char *) block);
+		pgstat_report_backend_allocated_bytes_decrease(block->endptr - ((char *) block));
 
 #ifdef CLOBBER_FREED_MEMORY
 		wipe_mem(block, block->freeptr - ((char *) block));
@@ -1173,7 +1189,9 @@ AllocSetRealloc(void *pointer, Size size)
 
 		/* updated separately, not to underflow when (oldblksize > blksize) */
 		set->header.mem_allocated -= oldblksize;
+		pgstat_report_backend_allocated_bytes_decrease(oldblksize);
 		set->header.mem_allocated += blksize;
+		pgstat_report_backend_allocated_bytes_increase(blksize);
 
 		block->freeptr = block->endptr = ((char *) block) + blksize;
 
diff --git a/src/backend/utils/mmgr/generation.c b/src/backend/utils/mmgr/generation.c
index b432a92be3..df3007edfb 100644
--- a/src/backend/utils/mmgr/generation.c
+++ b/src/backend/utils/mmgr/generation.c
@@ -37,6 +37,7 @@
 
 #include "lib/ilist.h"
 #include "port/pg_bitutils.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -267,6 +268,7 @@ GenerationContextCreate(MemoryContext parent,
 						name);
 
 	((MemoryContext) set)->mem_allocated = firstBlockSize;
+	pgstat_report_backend_allocated_bytes_increase(firstBlockSize);
 
 	return (MemoryContext) set;
 }
@@ -283,6 +285,7 @@ GenerationReset(MemoryContext context)
 {
 	GenerationContext *set = (GenerationContext *) context;
 	dlist_mutable_iter miter;
+	uint64		deallocation = 0;
 
 	Assert(GenerationIsValid(set));
 
@@ -305,9 +308,14 @@ GenerationReset(MemoryContext context)
 		if (block == set->keeper)
 			GenerationBlockMarkEmpty(block);
 		else
+		{
+			deallocation += block->blksize;
 			GenerationBlockFree(set, block);
+		}
 	}
 
+	pgstat_report_backend_allocated_bytes_decrease(deallocation);
+
 	/* set it so new allocations to make use of the keeper block */
 	set->block = set->keeper;
 
@@ -328,6 +336,9 @@ GenerationDelete(MemoryContext context)
 {
 	/* Reset to release all releasable GenerationBlocks */
 	GenerationReset(context);
+
+	pgstat_report_backend_allocated_bytes_decrease(context->mem_allocated);
+
 	/* And free the context header and keeper block */
 	free(context);
 }
@@ -374,6 +385,7 @@ GenerationAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_backend_allocated_bytes_increase(blksize);
 
 		/* block with a single (used) chunk */
 		block->context = set;
@@ -477,6 +489,7 @@ GenerationAlloc(MemoryContext context, Size size)
 				return NULL;
 
 			context->mem_allocated += blksize;
+			pgstat_report_backend_allocated_bytes_increase(blksize);
 
 			/* initialize the new block */
 			GenerationBlockInit(set, block, blksize);
@@ -726,6 +739,8 @@ GenerationFree(void *pointer)
 	dlist_delete(&block->node);
 
 	set->header.mem_allocated -= block->blksize;
+	pgstat_report_backend_allocated_bytes_decrease(block->blksize);
+
 	free(block);
 }
 
diff --git a/src/backend/utils/mmgr/slab.c b/src/backend/utils/mmgr/slab.c
index 6df0839b6a..532c038973 100644
--- a/src/backend/utils/mmgr/slab.c
+++ b/src/backend/utils/mmgr/slab.c
@@ -53,6 +53,7 @@
 #include "postgres.h"
 
 #include "lib/ilist.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -238,6 +239,12 @@ SlabContextCreate(MemoryContext parent,
 						parent,
 						name);
 
+	/*
+	 * If SlabContextCreate is updated to add headerSize to
+	 * context->mem_allocated, then update here and SlabDelete appropriately
+	 */
+	pgstat_report_backend_allocated_bytes_increase(headerSize);
+
 	return (MemoryContext) slab;
 }
 
@@ -253,6 +260,7 @@ SlabReset(MemoryContext context)
 {
 	SlabContext *slab = (SlabContext *) context;
 	int			i;
+	uint64		deallocation = 0;
 
 	Assert(SlabIsValid(slab));
 
@@ -278,9 +286,11 @@ SlabReset(MemoryContext context)
 			free(block);
 			slab->nblocks--;
 			context->mem_allocated -= slab->blockSize;
+			deallocation += slab->blockSize;
 		}
 	}
 
+	pgstat_report_backend_allocated_bytes_decrease(deallocation);
 	slab->minFreeChunks = 0;
 
 	Assert(slab->nblocks == 0);
@@ -294,8 +304,17 @@ SlabReset(MemoryContext context)
 void
 SlabDelete(MemoryContext context)
 {
+	/*
+	 * Until header allocation is included in context->mem_allocated, cast to
+	 * slab and decrement the headerSize
+	 */
+	SlabContext *slab = castNode(SlabContext, context);
+
 	/* Reset to release all the SlabBlocks */
 	SlabReset(context);
+
+	pgstat_report_backend_allocated_bytes_decrease(slab->headerSize);
+
 	/* And free the context header */
 	free(context);
 }
@@ -364,6 +383,7 @@ SlabAlloc(MemoryContext context, Size size)
 		slab->minFreeChunks = slab->chunksPerBlock;
 		slab->nblocks += 1;
 		context->mem_allocated += slab->blockSize;
+		pgstat_report_backend_allocated_bytes_increase(slab->blockSize);
 	}
 
 	/* grab the block from the freelist (even the new block is there) */
@@ -537,6 +557,7 @@ SlabFree(void *pointer)
 		free(block);
 		slab->nblocks--;
 		slab->header.mem_allocated -= slab->blockSize;
+		pgstat_report_backend_allocated_bytes_decrease(slab->blockSize);
 	}
 	else
 		dlist_push_head(&slab->freelist[block->nfree], &block->node);
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 20f5aa56ea..1c37f7db5d 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -5347,9 +5347,9 @@
   proname => 'pg_stat_get_activity', prorows => '100', proisstrict => 'f',
   proretset => 't', provolatile => 's', proparallel => 'r',
   prorettype => 'record', proargtypes => 'int4',
-  proallargtypes => '{int4,oid,int4,oid,text,text,text,text,text,timestamptz,timestamptz,timestamptz,timestamptz,inet,text,int4,xid,xid,text,bool,text,text,int4,text,numeric,text,bool,text,bool,int4,int8}',
-  proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
-  proargnames => '{pid,datid,pid,usesysid,application_name,state,query,wait_event_type,wait_event,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,backend_type,ssl,sslversion,sslcipher,sslbits,ssl_client_dn,ssl_client_serial,ssl_issuer_dn,gss_auth,gss_princ,gss_enc,leader_pid,query_id}',
+  proallargtypes => '{int4,oid,int4,oid,text,text,text,text,text,timestamptz,timestamptz,timestamptz,timestamptz,inet,text,int4,xid,xid,text,bool,text,text,int4,text,numeric,text,bool,text,bool,int4,int8,int8}',
+  proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
+  proargnames => '{pid,datid,pid,usesysid,application_name,state,query,wait_event_type,wait_event,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,backend_type,ssl,sslversion,sslcipher,sslbits,ssl_client_dn,ssl_client_serial,ssl_issuer_dn,gss_auth,gss_princ,gss_enc,leader_pid,query_id,backend_allocated_bytes}',
   prosrc => 'pg_stat_get_activity' },
 { oid => '3318',
   descr => 'statistics: information about progress of backends running maintenance command',
diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h
index b582b46e9f..75d87e8308 100644
--- a/src/include/utils/backend_status.h
+++ b/src/include/utils/backend_status.h
@@ -169,6 +169,9 @@ typedef struct PgBackendStatus
 
 	/* query identifier, optionally computed using post_parse_analyze_hook */
 	uint64		st_query_id;
+
+	/* Current memory allocated to this backend */
+	uint64		backend_allocated_bytes;
 } PgBackendStatus;
 
 
@@ -313,7 +316,9 @@ extern const char *pgstat_get_backend_current_activity(int pid, bool checkUser);
 extern const char *pgstat_get_crashed_backend_activity(int pid, char *buffer,
 													   int buflen);
 extern uint64 pgstat_get_my_query_id(void);
-
+extern void pgstat_report_backend_allocated_bytes_increase(uint64 allocation);
+extern void pgstat_report_backend_allocated_bytes_decrease(uint64 deallocation);
+extern uint64 pgstat_get_all_backend_memory_allocated(void);
 
 /* ----------
  * Support functions for the SQL-callable functions to
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index 624d0e5aae..ba9f494806 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1753,10 +1753,11 @@ pg_stat_activity| SELECT s.datid,
     s.state,
     s.backend_xid,
     s.backend_xmin,
+    s.backend_allocated_bytes,
     s.query_id,
     s.query,
     s.backend_type
-   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, backend_allocated_bytes)
      LEFT JOIN pg_database d ON ((s.datid = d.oid)))
      LEFT JOIN pg_authid u ON ((s.usesysid = u.oid)));
 pg_stat_all_indexes| SELECT c.oid AS relid,
@@ -1871,7 +1872,7 @@ pg_stat_gssapi| SELECT s.pid,
     s.gss_auth AS gss_authenticated,
     s.gss_princ AS principal,
     s.gss_enc AS encrypted
-   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, backend_allocated_bytes)
   WHERE (s.client_port IS NOT NULL);
 pg_stat_progress_analyze| SELECT s.pid,
     s.datid,
@@ -2052,7 +2053,7 @@ pg_stat_replication| SELECT s.pid,
     w.sync_priority,
     w.sync_state,
     w.reply_time
-   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, backend_allocated_bytes)
      JOIN pg_stat_get_wal_senders() w(pid, state, sent_lsn, write_lsn, flush_lsn, replay_lsn, write_lag, flush_lag, replay_lag, sync_priority, sync_state, reply_time) ON ((s.pid = w.pid)))
      LEFT JOIN pg_authid u ON ((s.usesysid = u.oid)));
 pg_stat_replication_slots| SELECT s.slot_name,
@@ -2086,7 +2087,7 @@ pg_stat_ssl| SELECT s.pid,
     s.ssl_client_dn AS client_dn,
     s.ssl_client_serial AS client_serial,
     s.ssl_issuer_dn AS issuer_dn
-   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, backend_allocated_bytes)
   WHERE (s.client_port IS NOT NULL);
 pg_stat_subscription| SELECT su.oid AS subid,
     su.subname,
-- 
2.25.1

#17Reid Thompson
reid.thompson@crunchydata.com
In reply to: Reid Thompson (#16)
2 attachment(s)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On Thu, 2022-11-03 at 11:48 -0400, Reid Thompson wrote:

On Tue, 2022-10-25 at 11:49 -0400, Reid Thompson wrote:

Rebased to current. Add a couple changes per conversation with D
Christensen (include units in field name, group field with
backend_xid
and backend_xmin fields in pg_stat_activity view, rather than between
query_id and query)

rebased/patched to current master && current pg-stat-activity-backend-memory-allocated

--
Reid Thompson
Senior Software Engineer
Crunchy Data, Inc.

reid.thompson@crunchydata.com
www.crunchydata.com

Attachments:

0002-Add-the-ability-to-limit-the-amount-of-memory-that-c.patchtext/x-patch; charset=UTF-8; name=0002-Add-the-ability-to-limit-the-amount-of-memory-that-c.patchDownload
From 1470f45e086bef0757cc262d10e08904e46b9a88 Mon Sep 17 00:00:00 2001
From: Reid Thompson <jreidthompson@nc.rr.com>
Date: Sat, 4 Jun 2022 22:23:59 -0400
Subject: [PATCH 2/2] Add the ability to limit the amount of memory that can be
 allocated to backends.

This builds on the work that adds backend memory allocated to pg_stat_activity.

Add GUC variable max_total_backend_memory.

Specifies a limit to the amount of memory (in MB) that may be allocated to
backends in total (i.e. this is not a per user or per backend limit). If unset,
or set to 0 it is disabled. It is intended as a resource to help avoid the OOM
killer on LINUX and manage resources in general. A backend request that would
push the total over the limit will be denied with an out of memory error causing
that backend's current query/transaction to fail. Due to the dynamic nature of
memory allocations, this limit is not exact. If within 1.5MB of the limit and
two backends request 1MB each at the same time both may be allocated, and exceed
the limit. Further requests will not be allocated until dropping below the
limit. Keep this in mind when setting this value. This limit does not affect
auxiliary backend processes. Backend memory allocations are displayed in the
pg_stat_activity view.
---
 doc/src/sgml/config.sgml                      |  26 +++++
 src/backend/storage/ipc/dsm_impl.c            |  12 ++
 src/backend/utils/activity/backend_status.c   | 108 ++++++++++++++++++
 src/backend/utils/misc/guc_tables.c           |  11 ++
 src/backend/utils/misc/postgresql.conf.sample |   3 +
 src/backend/utils/mmgr/aset.c                 |  17 +++
 src/backend/utils/mmgr/generation.c           |   9 ++
 src/backend/utils/mmgr/slab.c                 |   8 ++
 src/include/utils/backend_status.h            |   3 +
 9 files changed, 197 insertions(+)

diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 24b1624bad..c2db3ace7a 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -2079,6 +2079,32 @@ include_dir 'conf.d'
       </listitem>
      </varlistentry>
 
+     <varlistentry id="guc-max-total-backend-memory" xreflabel="max_total_backend_memory">
+      <term><varname>max_total_backend_memory</varname> (<type>integer</type>)
+      <indexterm>
+       <primary><varname>max_total_backend_memory</varname> configuration parameter</primary>
+      </indexterm>
+      </term>
+      <listitem>
+       <para>
+        Specifies a limit to the amount of memory (MB) that may be allocated to
+        backends in total (i.e. this is not a per user or per backend limit).
+        If unset, or set to 0 it is disabled.  A backend request that would
+        push the total over the limit will be denied with an out of memory
+        error causing that backend's current query/transaction to fail. Due to
+        the dynamic nature of memory allocations, this limit is not exact. If
+        within 1.5MB of the limit and two backends request 1MB each at the same
+        time both may be allocated, and exceed the limit. Further requests will
+        not be allocated until dropping below the limit. Keep this in mind when
+        setting this value. This limit does not affect auxiliary backend
+        processes <xref linkend="glossary-auxiliary-proc"/> . Backend memory
+        allocations (<varname>allocated_bytes</varname>) are displayed in the
+        <link linkend="monitoring-pg-stat-activity-view"><structname>pg_stat_activity</structname></link>
+        view.
+       </para>
+      </listitem>
+     </varlistentry>
+
      </variablelist>
      </sect2>
 
diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c
index 65d59fc43e..8d9df676af 100644
--- a/src/backend/storage/ipc/dsm_impl.c
+++ b/src/backend/storage/ipc/dsm_impl.c
@@ -254,6 +254,10 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 		return true;
 	}
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+		return false;
+
 	/*
 	 * Create new segment or open an existing one for attach.
 	 *
@@ -525,6 +529,10 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 		int			flags = IPCProtection;
 		size_t		segsize;
 
+		/* Do not exceed maximum allowed memory allocation */
+		if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+			return false;
+
 		/*
 		 * Allocate the memory BEFORE acquiring the resource, so that we don't
 		 * leak the resource if memory allocation fails.
@@ -719,6 +727,10 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 		return true;
 	}
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+		return false;
+
 	/* Create new segment or open an existing one for attach. */
 	if (op == DSM_OP_CREATE)
 	{
diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c
index 3785e8af53..07dfd8f490 100644
--- a/src/backend/utils/activity/backend_status.c
+++ b/src/backend/utils/activity/backend_status.c
@@ -45,6 +45,9 @@
 bool		pgstat_track_activities = false;
 int			pgstat_track_activity_query_size = 1024;
 
+/* Max backend memory allocation allowed (MB). 0 = disabled */
+int			max_total_bkend_mem = 0;
+
 
 /* exposed so that backend_progress.c can access it */
 PgBackendStatus *MyBEEntry = NULL;
@@ -1236,3 +1239,108 @@ pgstat_reset_allocated_bytes_storage(void)
 	my_allocated_bytes = &local_my_allocated_bytes;
 }
 
+/* ----------
+ * pgstat_get_all_memory_allocated() -
+ *
+ *	Return a uint64 representing the current shared memory allocated to all
+ *	backends.  This looks directly at the BackendStatusArray, and so will
+ *	provide current information regardless of the age of our transaction's
+ *	snapshot of the status array.
+ *	In the future we will likely utilize additional values - perhaps limit
+ *	backend allocation by user/role, etc.
+ * ----------
+ */
+uint64
+pgstat_get_all_backend_memory_allocated(void)
+{
+	PgBackendStatus *beentry;
+	int			i;
+	uint64		all_memory_allocated = 0;
+
+	beentry = BackendStatusArray;
+
+	/*
+	 * We probably shouldn't get here before shared memory has been set up,
+	 * but be safe.
+	 */
+	if (beentry == NULL || BackendActivityBuffer == NULL)
+		return 0;
+
+	/*
+	 * We include AUX procs in all backend memory calculation
+	 */
+	for (i = 1; i <= NumBackendStatSlots; i++)
+	{
+		/*
+		 * We use a volatile pointer here to ensure the compiler doesn't try
+		 * to get cute.
+		 */
+		volatile PgBackendStatus *vbeentry = beentry;
+		bool		found;
+		uint64		allocated_bytes = 0;
+
+		for (;;)
+		{
+			int			before_changecount;
+			int			after_changecount;
+
+			pgstat_begin_read_activity(vbeentry, before_changecount);
+
+			/*
+			 * Ignore invalid entries, which may contain invalid data.
+			 * See pgstat_beshutdown_hook()
+			 */
+			if (vbeentry->st_procpid > 0)
+				allocated_bytes = vbeentry->allocated_bytes;
+
+			pgstat_end_read_activity(vbeentry, after_changecount);
+
+			if ((found = pgstat_read_activity_complete(before_changecount,
+													   after_changecount)))
+				break;
+
+			/* Make sure we can break out of loop if stuck... */
+			CHECK_FOR_INTERRUPTS();
+		}
+
+		if (found)
+			all_memory_allocated += allocated_bytes;
+
+		beentry++;
+	}
+
+	return all_memory_allocated;
+}
+
+/*
+ * Determine if allocation request will exceed max backend memory allowed.
+ * Do not apply to auxiliary processes.
+ */
+bool
+exceeds_max_total_bkend_mem(uint64 allocation_request)
+{
+	bool		result = false;
+
+	/* Exclude auxiliary processes from the check */
+	if (MyAuxProcType != NotAnAuxProcess)
+		return result;
+
+	/* Convert max_total_bkend_mem to bytes for comparison */
+	if (max_total_bkend_mem &&
+		pgstat_get_all_backend_memory_allocated() +
+		allocation_request > (uint64) max_total_bkend_mem * 1024 * 1024)
+	{
+		/*
+		 * Explicitly identify the OOM being a result of this configuration
+		 * parameter vs a system failure to allocate OOM.
+		 */
+		ereport(WARNING,
+				errmsg("allocation would exceed max_total_memory limit (%llu > %llu)",
+					   (unsigned long long) pgstat_get_all_backend_memory_allocated() +
+					   allocation_request, (unsigned long long) max_total_bkend_mem * 1024 * 1024));
+
+		result = true;
+	}
+
+	return result;
+}
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index 349dd6a537..c20a656310 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -3423,6 +3423,17 @@ struct config_int ConfigureNamesInt[] =
 		NULL, NULL, NULL
 	},
 
+	{
+		{"max_total_backend_memory", PGC_SU_BACKEND, RESOURCES_MEM,
+			gettext_noop("Restrict total backend memory allocations to this max."),
+			gettext_noop("0 turns this feature off."),
+			GUC_UNIT_MB
+		},
+		&max_total_bkend_mem,
+		0, 0, INT_MAX,
+		NULL, NULL, NULL
+	},
+
 	/* End-of-list marker */
 	{
 		{NULL, 0, 0, NULL, NULL}, NULL, 0, 0, 0, NULL, NULL, NULL
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 868d21c351..1ce0dee6d0 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -155,6 +155,9 @@
 					#   mmap
 					# (change requires restart)
 #min_dynamic_shared_memory = 0MB	# (change requires restart)
+#max_total_backend_memory = 0MB		# Restrict total backend memory allocations
+									# to this max (in MB). 0 turns this feature
+									# off.
 
 # - Disk -
 
diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index b202e115b6..596f1db408 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -440,6 +440,10 @@ AllocSetContextCreateInternal(MemoryContext parent,
 	else
 		firstBlockSize = Max(firstBlockSize, initBlockSize);
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (exceeds_max_total_bkend_mem(firstBlockSize))
+		return NULL;
+
 	/*
 	 * Allocate the initial block.  Unlike other aset.c blocks, it starts with
 	 * the context header and its block header follows that.
@@ -741,6 +745,11 @@ AllocSetAlloc(MemoryContext context, Size size)
 #endif
 
 		blksize = chunk_size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
+
+		/* Do not exceed maximum allowed memory allocation */
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		block = (AllocBlock) malloc(blksize);
 		if (block == NULL)
 			return NULL;
@@ -938,6 +947,10 @@ AllocSetAlloc(MemoryContext context, Size size)
 		while (blksize < required_size)
 			blksize <<= 1;
 
+		/* Do not exceed maximum allowed memory allocation */
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		/* Try to allocate it */
 		block = (AllocBlock) malloc(blksize);
 
@@ -1178,6 +1191,10 @@ AllocSetRealloc(void *pointer, Size size)
 		blksize = chksize + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
 		oldblksize = block->endptr - ((char *) block);
 
+		/* Do not exceed maximum allowed memory allocation */
+		if (blksize > oldblksize && exceeds_max_total_bkend_mem(blksize - oldblksize))
+			return NULL;
+
 		block = (AllocBlock) realloc(block, blksize);
 		if (block == NULL)
 		{
diff --git a/src/backend/utils/mmgr/generation.c b/src/backend/utils/mmgr/generation.c
index 459eb985d6..145409cf21 100644
--- a/src/backend/utils/mmgr/generation.c
+++ b/src/backend/utils/mmgr/generation.c
@@ -201,6 +201,9 @@ GenerationContextCreate(MemoryContext parent,
 	else
 		allocSize = Max(allocSize, initBlockSize);
 
+	if (exceeds_max_total_bkend_mem(allocSize))
+		return NULL;
+
 	/*
 	 * Allocate the initial block.  Unlike other generation.c blocks, it
 	 * starts with the context header and its block header follows that.
@@ -380,6 +383,9 @@ GenerationAlloc(MemoryContext context, Size size)
 	{
 		Size		blksize = required_size + Generation_BLOCKHDRSZ;
 
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		block = (GenerationBlock *) malloc(blksize);
 		if (block == NULL)
 			return NULL;
@@ -483,6 +489,9 @@ GenerationAlloc(MemoryContext context, Size size)
 			if (blksize < required_size)
 				blksize = pg_nextpower2_size_t(required_size);
 
+			if (exceeds_max_total_bkend_mem(blksize))
+				return NULL;
+
 			block = (GenerationBlock *) malloc(blksize);
 
 			if (block == NULL)
diff --git a/src/backend/utils/mmgr/slab.c b/src/backend/utils/mmgr/slab.c
index f38256f6f3..9304e13638 100644
--- a/src/backend/utils/mmgr/slab.c
+++ b/src/backend/utils/mmgr/slab.c
@@ -197,6 +197,10 @@ SlabContextCreate(MemoryContext parent,
 	headerSize += chunksPerBlock * sizeof(bool);
 #endif
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (exceeds_max_total_bkend_mem(headerSize))
+		return NULL;
+
 	slab = (SlabContext *) malloc(headerSize);
 	if (slab == NULL)
 	{
@@ -351,6 +355,10 @@ SlabAlloc(MemoryContext context, Size size)
 	 */
 	if (slab->minFreeChunks == 0)
 	{
+		/* Do not exceed maximum allowed memory allocation */
+		if (exceeds_max_total_bkend_mem(slab->blockSize))
+			return NULL;
+
 		block = (SlabBlock *) malloc(slab->blockSize);
 
 		if (block == NULL)
diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h
index e5aa90b101..94528aa650 100644
--- a/src/include/utils/backend_status.h
+++ b/src/include/utils/backend_status.h
@@ -286,6 +286,7 @@ typedef struct LocalPgBackendStatus
  */
 extern PGDLLIMPORT bool pgstat_track_activities;
 extern PGDLLIMPORT int pgstat_track_activity_query_size;
+extern PGDLLIMPORT int max_total_bkend_mem;
 
 
 /* ----------
@@ -325,6 +326,7 @@ extern const char *pgstat_get_backend_current_activity(int pid, bool checkUser);
 extern const char *pgstat_get_crashed_backend_activity(int pid, char *buffer,
 													   int buflen);
 extern uint64 pgstat_get_my_query_id(void);
+extern uint64 pgstat_get_all_backend_memory_allocated(void);
 extern void pgstat_set_allocated_bytes_storage(uint64 *allocated_bytes);
 extern void pgstat_reset_allocated_bytes_storage(void);
 
@@ -337,6 +339,7 @@ extern int	pgstat_fetch_stat_numbackends(void);
 extern PgBackendStatus *pgstat_fetch_stat_beentry(BackendId beid);
 extern LocalPgBackendStatus *pgstat_fetch_stat_local_beentry(int beid);
 extern char *pgstat_clip_activity(const char *raw_activity);
+extern bool exceeds_max_total_bkend_mem(uint64 allocation_request);
 
 /* ----------
  * pgstat_report_allocated_bytes() -
-- 
2.25.1

0001-Add-tracking-of-backend-memory-allocated-to-pg_stat_.patchtext/x-patch; charset=UTF-8; name=0001-Add-tracking-of-backend-memory-allocated-to-pg_stat_.patchDownload
From 3d772d8620faba4bd4e091d6618c63557fbf6749 Mon Sep 17 00:00:00 2001
From: Reid Thompson <jreidthompson@nc.rr.com>
Date: Thu, 11 Aug 2022 12:01:25 -0400
Subject: [PATCH 1/2] Add tracking of backend memory allocated to
 pg_stat_activity

This new field displays the current bytes of memory allocated to the
backend process. It is updated as memory for the process is
malloc'd/free'd. Memory allocated to items on the freelist is included in
the displayed value.  Dynamic shared memory allocations are included
only in the value displayed for the backend that created them, they are
not included in the value for backends that are attached to them to
avoid double counting. On occasion, orphaned memory segments may be
cleaned up on postmaster startup. This may result in decreasing the sum
without a prior increment. We limit the floor of backend_mem_allocated
to zero. Updated pg_stat_activity documentation for the new column.
---
 doc/src/sgml/monitoring.sgml                | 15 ++++
 src/backend/catalog/system_views.sql        |  1 +
 src/backend/postmaster/autovacuum.c         |  6 ++
 src/backend/postmaster/postmaster.c         | 13 ++++
 src/backend/postmaster/syslogger.c          |  3 +
 src/backend/storage/ipc/dsm_impl.c          | 81 +++++++++++++++++++++
 src/backend/utils/activity/backend_status.c | 45 ++++++++++++
 src/backend/utils/adt/pgstatfuncs.c         |  4 +-
 src/backend/utils/mmgr/aset.c               | 17 +++++
 src/backend/utils/mmgr/generation.c         | 15 ++++
 src/backend/utils/mmgr/slab.c               | 21 ++++++
 src/include/catalog/pg_proc.dat             |  6 +-
 src/include/utils/backend_status.h          | 59 ++++++++++++++-
 src/test/regress/expected/rules.out         |  9 ++-
 src/test/regress/expected/stats.out         | 11 +++
 src/test/regress/sql/stats.sql              |  3 +
 16 files changed, 300 insertions(+), 9 deletions(-)

diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 5579b8b9e0..ffe7d2566c 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -947,6 +947,21 @@ postgres   27093  0.0  0.0  30096  2752 ?        Ss   11:34   0:00 postgres: ser
      </para></entry>
     </row>
 
+    <row>
+     <entry role="catalog_table_entry"><para role="column_definition">
+      <structfield>allocated_bytes</structfield> <type>bigint</type>
+     </para>
+     <para>
+      Memory currently allocated to this backend in bytes. This is the balance
+      of bytes allocated and freed by this backend. Dynamic shared memory
+      allocations are included only in the value displayed for the backend that
+      created them, they are not included in the value for backends that are
+      attached to them to avoid double counting. Use <function>pg_size_pretty</function>
+      described in <xref linkend="functions-admin-dbsize"/> to make this value
+      more easily readable.
+     </para></entry>
+    </row>
+
      <row>
       <entry role="catalog_table_entry"><para role="column_definition">
        <structfield>query</structfield> <type>text</type>
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 2d8104b090..9ea8f78c95 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -864,6 +864,7 @@ CREATE VIEW pg_stat_activity AS
             S.state,
             S.backend_xid,
             s.backend_xmin,
+            S.allocated_bytes,
             S.query_id,
             S.query,
             S.backend_type
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index 601834d4b4..f54606104d 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -407,6 +407,9 @@ StartAutoVacLauncher(void)
 
 #ifndef EXEC_BACKEND
 		case 0:
+			/* Zero allocated bytes to avoid double counting parent allocation */
+			pgstat_zero_my_allocated_bytes();
+
 			/* in postmaster child ... */
 			InitPostmasterChild();
 
@@ -1485,6 +1488,9 @@ StartAutoVacWorker(void)
 
 #ifndef EXEC_BACKEND
 		case 0:
+			/* Zero allocated bytes to avoid double counting parent allocation */
+			pgstat_zero_my_allocated_bytes();
+
 			/* in postmaster child ... */
 			InitPostmasterChild();
 
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index a8a246921f..89a6caec78 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -4102,6 +4102,9 @@ BackendStartup(Port *port)
 	{
 		free(bn);
 
+		/* Zero allocated bytes to avoid double counting parent allocation */
+		pgstat_zero_my_allocated_bytes();
+
 		/* Detangle from postmaster */
 		InitPostmasterChild();
 
@@ -5307,6 +5310,11 @@ StartChildProcess(AuxProcType type)
 		MemoryContextDelete(PostmasterContext);
 		PostmasterContext = NULL;
 
+		/* Zero allocated bytes to avoid double counting parent allocation.
+		 * Needs to be after the MemoryContextDelete(PostmasterContext) above.
+		 */
+		pgstat_zero_my_allocated_bytes();
+
 		AuxiliaryProcessMain(type); /* does not return */
 	}
 #endif							/* EXEC_BACKEND */
@@ -5700,6 +5708,11 @@ do_start_bgworker(RegisteredBgWorker *rw)
 			MemoryContextDelete(PostmasterContext);
 			PostmasterContext = NULL;
 
+			/* Zero allocated bytes to avoid double counting parent allocation.
+			 * Needs to be after the MemoryContextDelete(PostmasterContext) above.
+			 */
+			pgstat_zero_my_allocated_bytes();
+
 			StartBackgroundWorker();
 
 			exit(1);			/* should not get here */
diff --git a/src/backend/postmaster/syslogger.c b/src/backend/postmaster/syslogger.c
index d6d02e3c63..4cbc59cda5 100644
--- a/src/backend/postmaster/syslogger.c
+++ b/src/backend/postmaster/syslogger.c
@@ -679,6 +679,9 @@ SysLogger_Start(void)
 
 #ifndef EXEC_BACKEND
 		case 0:
+			/* Zero allocated bytes to avoid double counting parent allocation */
+			pgstat_zero_my_allocated_bytes();
+
 			/* in postmaster child ... */
 			InitPostmasterChild();
 
diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c
index 6ddd46a4e7..65d59fc43e 100644
--- a/src/backend/storage/ipc/dsm_impl.c
+++ b/src/backend/storage/ipc/dsm_impl.c
@@ -66,6 +66,7 @@
 #include "postmaster/postmaster.h"
 #include "storage/dsm_impl.h"
 #include "storage/fd.h"
+#include "utils/backend_status.h"
 #include "utils/guc.h"
 #include "utils/memutils.h"
 
@@ -232,6 +233,14 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_allocated_bytes(*mapped_size, DECREASE);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && shm_unlink(name) != 0)
@@ -332,6 +341,36 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+	{
+		/*
+		 * Posix creation calls dsm_impl_posix_resize implying that resizing
+		 * occurs or may be added in the future. As implemented
+		 * dsm_impl_posix_resize utilizes fallocate or truncate, passing the
+		 * whole new size as input, growing the allocation as needed (only
+		 * truncate supports shrinking). We update by replacing the old
+		 * allocation with the new.
+		 */
+#if defined(HAVE_POSIX_FALLOCATE) && defined(__linux__)
+		/*
+		 * posix_fallocate does not shrink allocations, adjust only on
+		 * allocation increase.
+		 */
+		if (request_size > *mapped_size)
+		{
+			pgstat_report_allocated_bytes(*mapped_size, DECREASE);
+			pgstat_report_allocated_bytes(request_size, INCREASE);
+		}
+#else
+		pgstat_report_allocated_bytes(*mapped_size, DECREASE);
+		pgstat_report_allocated_bytes(request_size, INCREASE);
+#endif
+	}
 	*mapped_address = address;
 	*mapped_size = request_size;
 	close(fd);
@@ -537,6 +576,14 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_allocated_bytes(*mapped_size, DECREASE);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && shmctl(ident, IPC_RMID, NULL) < 0)
@@ -584,6 +631,13 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_allocated_bytes(request_size, INCREASE);
 	*mapped_address = address;
 	*mapped_size = request_size;
 
@@ -652,6 +706,13 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 			return false;
 		}
 
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_allocated_bytes(*mapped_size, DECREASE);
 		*impl_private = NULL;
 		*mapped_address = NULL;
 		*mapped_size = 0;
@@ -768,6 +829,12 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 		return false;
 	}
 
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_allocated_bytes(info.RegionSize, INCREASE);
 	*mapped_address = address;
 	*mapped_size = info.RegionSize;
 	*impl_private = hmap;
@@ -812,6 +879,13 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		pgstat_report_allocated_bytes(*mapped_size, DECREASE);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && unlink(name) != 0)
@@ -933,6 +1007,13 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_allocated_bytes(request_size, INCREASE);
 	*mapped_address = address;
 	*mapped_size = request_size;
 
diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c
index 1146a6c33c..3785e8af53 100644
--- a/src/backend/utils/activity/backend_status.c
+++ b/src/backend/utils/activity/backend_status.c
@@ -49,6 +49,9 @@ int			pgstat_track_activity_query_size = 1024;
 /* exposed so that backend_progress.c can access it */
 PgBackendStatus *MyBEEntry = NULL;
 
+/* Memory allocated to this backend prior to pgstats initialization */
+uint64	local_my_allocated_bytes = 0;
+uint64	*my_allocated_bytes = &local_my_allocated_bytes;
 
 static PgBackendStatus *BackendStatusArray = NULL;
 static char *BackendAppnameBuffer = NULL;
@@ -400,6 +403,15 @@ pgstat_bestart(void)
 	lbeentry.st_progress_command_target = InvalidOid;
 	lbeentry.st_query_id = UINT64CONST(0);
 
+	/* Alter allocation reporting from local_my_allocated_bytes to shared memory */
+	pgstat_set_allocated_bytes_storage(&MyBEEntry->allocated_bytes);
+
+	/* Populate sum of memory allocated prior to pgstats initialization to pgstats
+	 * and zero the local variable.
+	 */
+	lbeentry.allocated_bytes += local_my_allocated_bytes;
+	local_my_allocated_bytes = 0;
+
 	/*
 	 * we don't zero st_progress_param here to save cycles; nobody should
 	 * examine it until st_progress_command has been set to something other
@@ -459,6 +471,11 @@ pgstat_beshutdown_hook(int code, Datum arg)
 {
 	volatile PgBackendStatus *beentry = MyBEEntry;
 
+	/*
+	 * Stop reporting memory allocation changes to &MyBEEntry->allocated_bytes
+	 */
+	pgstat_reset_allocated_bytes_storage();
+
 	/*
 	 * Clear my status entry, following the protocol of bumping st_changecount
 	 * before and after.  We use a volatile pointer here to ensure the
@@ -1191,3 +1208,31 @@ pgstat_clip_activity(const char *raw_activity)
 
 	return activity;
 }
+
+/*
+ * Configure bytes allocated reporting to report allocated bytes to
+ * *allocated_bytes.  *allocated_bytes needs to be valid until
+ * pgstat_set_allocated_bytes_storage() is called.
+ *
+ * Expected to be called during backend startup (in pgstat_bestart), to point
+ * my_allocated_bytes into shared memory.
+ */
+void
+pgstat_set_allocated_bytes_storage(uint64 *new_allocated_bytes)
+{
+	my_allocated_bytes = new_allocated_bytes;
+	*new_allocated_bytes = local_my_allocated_bytes;
+}
+
+/*
+ * Reset allocated bytes storage location.
+ *
+ * Expected to be called during backend shutdown, before the location set up
+ * by pgstat_set_allocated_bytes_storage() becomes invalid.
+ */
+void
+pgstat_reset_allocated_bytes_storage(void)
+{
+	my_allocated_bytes = &local_my_allocated_bytes;
+}
+
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index ae3365d917..170d60df8b 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -559,7 +559,7 @@ pg_stat_get_progress_info(PG_FUNCTION_ARGS)
 Datum
 pg_stat_get_activity(PG_FUNCTION_ARGS)
 {
-#define PG_STAT_GET_ACTIVITY_COLS	30
+#define PG_STAT_GET_ACTIVITY_COLS	31
 	int			num_backends = pgstat_fetch_stat_numbackends();
 	int			curr_backend;
 	int			pid = PG_ARGISNULL(0) ? -1 : PG_GETARG_INT32(0);
@@ -615,6 +615,8 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
 		else
 			nulls[16] = true;
 
+		values[30] = UInt64GetDatum(beentry->allocated_bytes);
+
 		/* Values only available to role member or pg_read_all_stats */
 		if (HAS_PGSTAT_PERMISSIONS(beentry->st_userid))
 		{
diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index b6a8bbcd59..b202e115b6 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -47,6 +47,7 @@
 #include "postgres.h"
 
 #include "port/pg_bitutils.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -521,6 +522,7 @@ AllocSetContextCreateInternal(MemoryContext parent,
 						name);
 
 	((MemoryContext) set)->mem_allocated = firstBlockSize;
+	pgstat_report_allocated_bytes(firstBlockSize, INCREASE);
 
 	return (MemoryContext) set;
 }
@@ -543,6 +545,7 @@ AllocSetReset(MemoryContext context)
 	AllocSet	set = (AllocSet) context;
 	AllocBlock	block;
 	Size		keepersize PG_USED_FOR_ASSERTS_ONLY;
+	uint64		deallocation = 0;
 
 	Assert(AllocSetIsValid(set));
 
@@ -585,6 +588,7 @@ AllocSetReset(MemoryContext context)
 		{
 			/* Normal case, release the block */
 			context->mem_allocated -= block->endptr - ((char *) block);
+			deallocation += block->endptr - ((char *) block);
 
 #ifdef CLOBBER_FREED_MEMORY
 			wipe_mem(block, block->freeptr - ((char *) block));
@@ -595,6 +599,7 @@ AllocSetReset(MemoryContext context)
 	}
 
 	Assert(context->mem_allocated == keepersize);
+	pgstat_report_allocated_bytes(deallocation, DECREASE);
 
 	/* Reset block size allocation sequence, too */
 	set->nextBlockSize = set->initBlockSize;
@@ -613,6 +618,7 @@ AllocSetDelete(MemoryContext context)
 	AllocSet	set = (AllocSet) context;
 	AllocBlock	block = set->blocks;
 	Size		keepersize PG_USED_FOR_ASSERTS_ONLY;
+	uint64		deallocation = 0;
 
 	Assert(AllocSetIsValid(set));
 
@@ -651,11 +657,13 @@ AllocSetDelete(MemoryContext context)
 
 				freelist->first_free = (AllocSetContext *) oldset->header.nextchild;
 				freelist->num_free--;
+				deallocation += oldset->header.mem_allocated;
 
 				/* All that remains is to free the header/initial block */
 				free(oldset);
 			}
 			Assert(freelist->num_free == 0);
+			pgstat_report_allocated_bytes(deallocation, DECREASE);
 		}
 
 		/* Now add the just-deleted context to the freelist. */
@@ -672,7 +680,10 @@ AllocSetDelete(MemoryContext context)
 		AllocBlock	next = block->next;
 
 		if (block != set->keeper)
+		{
 			context->mem_allocated -= block->endptr - ((char *) block);
+			deallocation += block->endptr - ((char *) block);
+		}
 
 #ifdef CLOBBER_FREED_MEMORY
 		wipe_mem(block, block->freeptr - ((char *) block));
@@ -685,6 +696,7 @@ AllocSetDelete(MemoryContext context)
 	}
 
 	Assert(context->mem_allocated == keepersize);
+	pgstat_report_allocated_bytes(deallocation + context->mem_allocated, DECREASE);
 
 	/* Finally, free the context header, including the keeper block */
 	free(set);
@@ -734,6 +746,7 @@ AllocSetAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_allocated_bytes(blksize, INCREASE);
 
 		block->aset = set;
 		block->freeptr = block->endptr = ((char *) block) + blksize;
@@ -944,6 +957,7 @@ AllocSetAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_allocated_bytes(blksize, INCREASE);
 
 		block->aset = set;
 		block->freeptr = ((char *) block) + ALLOC_BLOCKHDRSZ;
@@ -1043,6 +1057,7 @@ AllocSetFree(void *pointer)
 			block->next->prev = block->prev;
 
 		set->header.mem_allocated -= block->endptr - ((char *) block);
+		pgstat_report_allocated_bytes(block->endptr - ((char *) block), DECREASE);
 
 #ifdef CLOBBER_FREED_MEMORY
 		wipe_mem(block, block->freeptr - ((char *) block));
@@ -1173,7 +1188,9 @@ AllocSetRealloc(void *pointer, Size size)
 
 		/* updated separately, not to underflow when (oldblksize > blksize) */
 		set->header.mem_allocated -= oldblksize;
+		pgstat_report_allocated_bytes(oldblksize, DECREASE);
 		set->header.mem_allocated += blksize;
+		pgstat_report_allocated_bytes(blksize, INCREASE);
 
 		block->freeptr = block->endptr = ((char *) block) + blksize;
 
diff --git a/src/backend/utils/mmgr/generation.c b/src/backend/utils/mmgr/generation.c
index b432a92be3..459eb985d6 100644
--- a/src/backend/utils/mmgr/generation.c
+++ b/src/backend/utils/mmgr/generation.c
@@ -37,6 +37,7 @@
 
 #include "lib/ilist.h"
 #include "port/pg_bitutils.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -267,6 +268,7 @@ GenerationContextCreate(MemoryContext parent,
 						name);
 
 	((MemoryContext) set)->mem_allocated = firstBlockSize;
+	pgstat_report_allocated_bytes(firstBlockSize, INCREASE);
 
 	return (MemoryContext) set;
 }
@@ -283,6 +285,7 @@ GenerationReset(MemoryContext context)
 {
 	GenerationContext *set = (GenerationContext *) context;
 	dlist_mutable_iter miter;
+	uint64		deallocation = 0;
 
 	Assert(GenerationIsValid(set));
 
@@ -305,9 +308,14 @@ GenerationReset(MemoryContext context)
 		if (block == set->keeper)
 			GenerationBlockMarkEmpty(block);
 		else
+		{
+			deallocation += block->blksize;
 			GenerationBlockFree(set, block);
+		}
 	}
 
+	pgstat_report_allocated_bytes(deallocation, DECREASE);
+
 	/* set it so new allocations to make use of the keeper block */
 	set->block = set->keeper;
 
@@ -328,6 +336,9 @@ GenerationDelete(MemoryContext context)
 {
 	/* Reset to release all releasable GenerationBlocks */
 	GenerationReset(context);
+
+	pgstat_report_allocated_bytes(context->mem_allocated, DECREASE);
+
 	/* And free the context header and keeper block */
 	free(context);
 }
@@ -374,6 +385,7 @@ GenerationAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_allocated_bytes(blksize, INCREASE);
 
 		/* block with a single (used) chunk */
 		block->context = set;
@@ -477,6 +489,7 @@ GenerationAlloc(MemoryContext context, Size size)
 				return NULL;
 
 			context->mem_allocated += blksize;
+			pgstat_report_allocated_bytes(blksize, INCREASE);
 
 			/* initialize the new block */
 			GenerationBlockInit(set, block, blksize);
@@ -726,6 +739,8 @@ GenerationFree(void *pointer)
 	dlist_delete(&block->node);
 
 	set->header.mem_allocated -= block->blksize;
+	pgstat_report_allocated_bytes(block->blksize, DECREASE);
+
 	free(block);
 }
 
diff --git a/src/backend/utils/mmgr/slab.c b/src/backend/utils/mmgr/slab.c
index 6df0839b6a..f38256f6f3 100644
--- a/src/backend/utils/mmgr/slab.c
+++ b/src/backend/utils/mmgr/slab.c
@@ -53,6 +53,7 @@
 #include "postgres.h"
 
 #include "lib/ilist.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -238,6 +239,12 @@ SlabContextCreate(MemoryContext parent,
 						parent,
 						name);
 
+	/*
+	 * If SlabContextCreate is updated to add headerSize to
+	 * context->mem_allocated, then update here and SlabDelete appropriately
+	 */
+	pgstat_report_allocated_bytes(headerSize, INCREASE);
+
 	return (MemoryContext) slab;
 }
 
@@ -253,6 +260,7 @@ SlabReset(MemoryContext context)
 {
 	SlabContext *slab = (SlabContext *) context;
 	int			i;
+	uint64		deallocation = 0;
 
 	Assert(SlabIsValid(slab));
 
@@ -278,9 +286,11 @@ SlabReset(MemoryContext context)
 			free(block);
 			slab->nblocks--;
 			context->mem_allocated -= slab->blockSize;
+			deallocation += slab->blockSize;
 		}
 	}
 
+	pgstat_report_allocated_bytes(deallocation, DECREASE);
 	slab->minFreeChunks = 0;
 
 	Assert(slab->nblocks == 0);
@@ -294,8 +304,17 @@ SlabReset(MemoryContext context)
 void
 SlabDelete(MemoryContext context)
 {
+	/*
+	 * Until header allocation is included in context->mem_allocated, cast to
+	 * slab and decrement the headerSize
+	 */
+	SlabContext *slab = castNode(SlabContext, context);
+
 	/* Reset to release all the SlabBlocks */
 	SlabReset(context);
+
+	pgstat_report_allocated_bytes(slab->headerSize, DECREASE);
+
 	/* And free the context header */
 	free(context);
 }
@@ -364,6 +383,7 @@ SlabAlloc(MemoryContext context, Size size)
 		slab->minFreeChunks = slab->chunksPerBlock;
 		slab->nblocks += 1;
 		context->mem_allocated += slab->blockSize;
+		pgstat_report_allocated_bytes(slab->blockSize, INCREASE);
 	}
 
 	/* grab the block from the freelist (even the new block is there) */
@@ -537,6 +557,7 @@ SlabFree(void *pointer)
 		free(block);
 		slab->nblocks--;
 		slab->header.mem_allocated -= slab->blockSize;
+		pgstat_report_allocated_bytes(slab->blockSize, DECREASE);
 	}
 	else
 		dlist_push_head(&slab->freelist[block->nfree], &block->node);
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index f9301b2627..1bf02758d4 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -5373,9 +5373,9 @@
   proname => 'pg_stat_get_activity', prorows => '100', proisstrict => 'f',
   proretset => 't', provolatile => 's', proparallel => 'r',
   prorettype => 'record', proargtypes => 'int4',
-  proallargtypes => '{int4,oid,int4,oid,text,text,text,text,text,timestamptz,timestamptz,timestamptz,timestamptz,inet,text,int4,xid,xid,text,bool,text,text,int4,text,numeric,text,bool,text,bool,int4,int8}',
-  proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
-  proargnames => '{pid,datid,pid,usesysid,application_name,state,query,wait_event_type,wait_event,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,backend_type,ssl,sslversion,sslcipher,sslbits,ssl_client_dn,ssl_client_serial,ssl_issuer_dn,gss_auth,gss_princ,gss_enc,leader_pid,query_id}',
+  proallargtypes => '{int4,oid,int4,oid,text,text,text,text,text,timestamptz,timestamptz,timestamptz,timestamptz,inet,text,int4,xid,xid,text,bool,text,text,int4,text,numeric,text,bool,text,bool,int4,int8,int8}',
+  proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
+  proargnames => '{pid,datid,pid,usesysid,application_name,state,query,wait_event_type,wait_event,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,backend_type,ssl,sslversion,sslcipher,sslbits,ssl_client_dn,ssl_client_serial,ssl_issuer_dn,gss_auth,gss_princ,gss_enc,leader_pid,query_id,allocated_bytes}',
   prosrc => 'pg_stat_get_activity' },
 { oid => '3318',
   descr => 'statistics: information about progress of backends running maintenance command',
diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h
index b582b46e9f..e5aa90b101 100644
--- a/src/include/utils/backend_status.h
+++ b/src/include/utils/backend_status.h
@@ -15,6 +15,7 @@
 #include "miscadmin.h"			/* for BackendType */
 #include "storage/backendid.h"
 #include "utils/backend_progress.h"
+#include "common/int.h"
 
 
 /* ----------
@@ -32,6 +33,13 @@ typedef enum BackendState
 	STATE_DISABLED
 } BackendState;
 
+/* Enum helper for reporting memory allocated bytes */
+enum allocation_direction
+{
+	DECREASE = -1,
+	IGNORE,
+	INCREASE,
+};
 
 /* ----------
  * Shared-memory data structures
@@ -169,6 +177,9 @@ typedef struct PgBackendStatus
 
 	/* query identifier, optionally computed using post_parse_analyze_hook */
 	uint64		st_query_id;
+
+	/* Current memory allocated to this backend */
+	uint64		allocated_bytes;
 } PgBackendStatus;
 
 
@@ -282,6 +293,7 @@ extern PGDLLIMPORT int pgstat_track_activity_query_size;
  * ----------
  */
 extern PGDLLIMPORT PgBackendStatus *MyBEEntry;
+extern PGDLLIMPORT uint64 *my_allocated_bytes;
 
 
 /* ----------
@@ -313,7 +325,8 @@ extern const char *pgstat_get_backend_current_activity(int pid, bool checkUser);
 extern const char *pgstat_get_crashed_backend_activity(int pid, char *buffer,
 													   int buflen);
 extern uint64 pgstat_get_my_query_id(void);
-
+extern void pgstat_set_allocated_bytes_storage(uint64 *allocated_bytes);
+extern void pgstat_reset_allocated_bytes_storage(void);
 
 /* ----------
  * Support functions for the SQL-callable functions to
@@ -325,5 +338,49 @@ extern PgBackendStatus *pgstat_fetch_stat_beentry(BackendId beid);
 extern LocalPgBackendStatus *pgstat_fetch_stat_local_beentry(int beid);
 extern char *pgstat_clip_activity(const char *raw_activity);
 
+/* ----------
+ * pgstat_report_allocated_bytes() -
+ *
+ *  Called to report change in memory allocated for this backend.
+ *
+ * my_allocated_bytes initially points to local memory, making it safe to call
+ * this before pgstats has been initialized. allocation_direction is a
+ * positive/negative multiplier enum defined above.
+ * ----------
+ */
+static inline void
+pgstat_report_allocated_bytes(uint64 allocated_bytes, int allocation_direction)
+{
+	uint64 temp;
+
+	/* Avoid *my_allocated_bytes unsigned integer overflow on DECREASE */
+	if (allocation_direction == DECREASE &&
+		pg_sub_u64_overflow(*my_allocated_bytes, allocated_bytes, &temp))
+	{
+		*my_allocated_bytes = 0;
+		ereport(LOG,
+				errmsg("Backend %d deallocated %ld bytes, exceeding the %ld bytes it is currently reporting allocated. Setting reported to 0.",
+					   MyProcPid, allocated_bytes, *my_allocated_bytes));
+	}
+	else
+		*my_allocated_bytes += (allocated_bytes) * allocation_direction;
+
+	return;
+}
+
+/* ---------
+ * pgstat_zero_my_allocated_bytes() -
+ *
+ * Called to zero out local allocated bytes variable after fork to avoid double
+ * counting allocations.
+ * ---------
+ */
+static inline void
+pgstat_zero_my_allocated_bytes(void)
+{
+	*my_allocated_bytes = 0;
+
+    return;
+}
 
 #endif							/* BACKEND_STATUS_H */
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index 37c1c86473..5263294ad4 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1756,10 +1756,11 @@ pg_stat_activity| SELECT s.datid,
     s.state,
     s.backend_xid,
     s.backend_xmin,
+    s.allocated_bytes,
     s.query_id,
     s.query,
     s.backend_type
-   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, allocated_bytes)
      LEFT JOIN pg_database d ON ((s.datid = d.oid)))
      LEFT JOIN pg_authid u ON ((s.usesysid = u.oid)));
 pg_stat_all_indexes| SELECT c.oid AS relid,
@@ -1874,7 +1875,7 @@ pg_stat_gssapi| SELECT s.pid,
     s.gss_auth AS gss_authenticated,
     s.gss_princ AS principal,
     s.gss_enc AS encrypted
-   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, allocated_bytes)
   WHERE (s.client_port IS NOT NULL);
 pg_stat_progress_analyze| SELECT s.pid,
     s.datid,
@@ -2055,7 +2056,7 @@ pg_stat_replication| SELECT s.pid,
     w.sync_priority,
     w.sync_state,
     w.reply_time
-   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, allocated_bytes)
      JOIN pg_stat_get_wal_senders() w(pid, state, sent_lsn, write_lsn, flush_lsn, replay_lsn, write_lag, flush_lag, replay_lag, sync_priority, sync_state, reply_time) ON ((s.pid = w.pid)))
      LEFT JOIN pg_authid u ON ((s.usesysid = u.oid)));
 pg_stat_replication_slots| SELECT s.slot_name,
@@ -2089,7 +2090,7 @@ pg_stat_ssl| SELECT s.pid,
     s.ssl_client_dn AS client_dn,
     s.ssl_client_serial AS client_serial,
     s.ssl_issuer_dn AS issuer_dn
-   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, allocated_bytes)
   WHERE (s.client_port IS NOT NULL);
 pg_stat_subscription| SELECT su.oid AS subid,
     su.subname,
diff --git a/src/test/regress/expected/stats.out b/src/test/regress/expected/stats.out
index 1d84407a03..ab7e95c367 100644
--- a/src/test/regress/expected/stats.out
+++ b/src/test/regress/expected/stats.out
@@ -1126,4 +1126,15 @@ SELECT pg_stat_get_subscription_stats(NULL);
  
 (1 row)
 
+-- ensure that allocated_bytes exist for backends
+SELECT allocated_bytes > 0 AS result FROM pg_stat_activity WHERE backend_type
+IN ('checkpointer', 'background writer', 'walwriter', 'autovacuum launcher');
+ result 
+--------
+ t
+ t
+ t
+ t
+(4 rows)
+
 -- End of Stats Test
diff --git a/src/test/regress/sql/stats.sql b/src/test/regress/sql/stats.sql
index b4d6753c71..2f0b1cc9d8 100644
--- a/src/test/regress/sql/stats.sql
+++ b/src/test/regress/sql/stats.sql
@@ -535,5 +535,8 @@ SET enable_seqscan TO on;
 SELECT pg_stat_get_replication_slot(NULL);
 SELECT pg_stat_get_subscription_stats(NULL);
 
+-- ensure that allocated_bytes exist for backends
+SELECT allocated_bytes > 0 AS result FROM pg_stat_activity WHERE backend_type
+IN ('checkpointer', 'background writer', 'walwriter', 'autovacuum launcher');
 
 -- End of Stats Test
-- 
2.25.1

#18Andres Freund
andres@anarazel.de
In reply to: Reid Thompson (#17)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

Hi,

On 2022-11-26 22:22:15 -0500, Reid Thompson wrote:

rebased/patched to current master && current pg-stat-activity-backend-memory-allocated

This version fails to build with msvc, and builds with warnings on other
platforms.
https://cirrus-ci.com/build/5410696721072128
msvc:
[20:26:51.286] c:\cirrus\src\include\utils/backend_status.h(40): error C2059: syntax error: 'constant'

mingw cross:
[20:26:26.358] from /usr/share/mingw-w64/include/winsock2.h:23,
[20:26:26.358] from ../../src/include/port/win32_port.h:60,
[20:26:26.358] from ../../src/include/port.h:24,
[20:26:26.358] from ../../src/include/c.h:1306,
[20:26:26.358] from ../../src/include/postgres.h:47,
[20:26:26.358] from controldata_utils.c:18:
[20:26:26.358] ../../src/include/utils/backend_status.h:40:2: error: expected identifier before numeric constant
[20:26:26.358] 40 | IGNORE,
[20:26:26.358] | ^~~~~~
[20:26:26.358] In file included from ../../src/include/postgres.h:48,
[20:26:26.358] from controldata_utils.c:18:
[20:26:26.358] ../../src/include/utils/backend_status.h: In function ‘pgstat_report_allocated_bytes’:
[20:26:26.358] ../../src/include/utils/backend_status.h:365:12: error: format ‘%ld’ expects argument of type ‘long int’, but argument 3 has type ‘uint64’ {aka ‘long long unsigned int’} [-Werror=format=]
[20:26:26.358] 365 | errmsg("Backend %d deallocated %ld bytes, exceeding the %ld bytes it is currently reporting allocated. Setting reported to 0.",
[20:26:26.358] | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[20:26:26.358] 366 | MyProcPid, allocated_bytes, *my_allocated_bytes));
[20:26:26.358] | ~~~~~~~~~~~~~~~
[20:26:26.358] | |
[20:26:26.358] | uint64 {aka long long unsigned int}

Due to windows having long be 32bit, you need to use %lld. Our custom to deal
with that is to cast the argument to errmsg as long long unsigned and use
%llu.

Btw, given that the argument is uint64, it doesn't seem correct to use %ld,
that's signed. Not that it's going to matter, but ...

Greetings,

Andres Freund

#19Reid Thompson
reid.thompson@crunchydata.com
In reply to: Andres Freund (#18)
2 attachment(s)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On Tue, 2022-12-06 at 10:32 -0800, Andres Freund wrote:

Hi,

On 2022-11-26 22:22:15 -0500, Reid Thompson wrote:

rebased/patched to current master && current pg-stat-activity-
backend-memory-allocated

This version fails to build with msvc, and builds with warnings on
other
platforms.
https://cirrus-ci.com/build/5410696721072128
msvc:

Andres Freund

updated patches

--
Reid Thompson
Senior Software Engineer
Crunchy Data, Inc.

reid.thompson@crunchydata.com
www.crunchydata.com

Attachments:

0002-Add-the-ability-to-limit-the-amount-of-memory-that-c.patchtext/x-patch; charset=UTF-8; name=0002-Add-the-ability-to-limit-the-amount-of-memory-that-c.patchDownload
From e48292eaf402bfe397f1c2fdc1b3efd8cd0a9137 Mon Sep 17 00:00:00 2001
From: Reid Thompson <jreidthompson@nc.rr.com>
Date: Sat, 4 Jun 2022 22:23:59 -0400
Subject: [PATCH 2/2] Add the ability to limit the amount of memory that can be
 allocated to backends.

This builds on the work that adds backend memory allocated to pg_stat_activity.

Add GUC variable max_total_backend_memory.

Specifies a limit to the amount of memory (in MB) that may be allocated to
backends in total (i.e. this is not a per user or per backend limit). If unset,
or set to 0 it is disabled. It is intended as a resource to help avoid the OOM
killer on LINUX and manage resources in general. A backend request that would
push the total over the limit will be denied with an out of memory error causing
that backend's current query/transaction to fail. Due to the dynamic nature of
memory allocations, this limit is not exact. If within 1.5MB of the limit and
two backends request 1MB each at the same time both may be allocated, and exceed
the limit. Further requests will not be allocated until dropping below the
limit. Keep this in mind when setting this value. This limit does not affect
auxiliary backend processes. Backend memory allocations are displayed in the
pg_stat_activity view.
---
 doc/src/sgml/config.sgml                      |  26 +++++
 src/backend/storage/ipc/dsm_impl.c            |  12 ++
 src/backend/utils/activity/backend_status.c   | 108 ++++++++++++++++++
 src/backend/utils/misc/guc_tables.c           |  11 ++
 src/backend/utils/misc/postgresql.conf.sample |   3 +
 src/backend/utils/mmgr/aset.c                 |  17 +++
 src/backend/utils/mmgr/generation.c           |   9 ++
 src/backend/utils/mmgr/slab.c                 |   8 ++
 src/include/utils/backend_status.h            |   3 +
 9 files changed, 197 insertions(+)

diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index ff6fcd902a..2899f109ac 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -2079,6 +2079,32 @@ include_dir 'conf.d'
       </listitem>
      </varlistentry>
 
+     <varlistentry id="guc-max-total-backend-memory" xreflabel="max_total_backend_memory">
+      <term><varname>max_total_backend_memory</varname> (<type>integer</type>)
+      <indexterm>
+       <primary><varname>max_total_backend_memory</varname> configuration parameter</primary>
+      </indexterm>
+      </term>
+      <listitem>
+       <para>
+        Specifies a limit to the amount of memory (MB) that may be allocated to
+        backends in total (i.e. this is not a per user or per backend limit).
+        If unset, or set to 0 it is disabled.  A backend request that would
+        push the total over the limit will be denied with an out of memory
+        error causing that backend's current query/transaction to fail. Due to
+        the dynamic nature of memory allocations, this limit is not exact. If
+        within 1.5MB of the limit and two backends request 1MB each at the same
+        time both may be allocated, and exceed the limit. Further requests will
+        not be allocated until dropping below the limit. Keep this in mind when
+        setting this value. This limit does not affect auxiliary backend
+        processes <xref linkend="glossary-auxiliary-proc"/> . Backend memory
+        allocations (<varname>allocated_bytes</varname>) are displayed in the
+        <link linkend="monitoring-pg-stat-activity-view"><structname>pg_stat_activity</structname></link>
+        view.
+       </para>
+      </listitem>
+     </varlistentry>
+
      </variablelist>
      </sect2>
 
diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c
index 36ef3e425e..58fb690c69 100644
--- a/src/backend/storage/ipc/dsm_impl.c
+++ b/src/backend/storage/ipc/dsm_impl.c
@@ -254,6 +254,10 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 		return true;
 	}
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+		return false;
+
 	/*
 	 * Create new segment or open an existing one for attach.
 	 *
@@ -525,6 +529,10 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 		int			flags = IPCProtection;
 		size_t		segsize;
 
+		/* Do not exceed maximum allowed memory allocation */
+		if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+			return false;
+
 		/*
 		 * Allocate the memory BEFORE acquiring the resource, so that we don't
 		 * leak the resource if memory allocation fails.
@@ -719,6 +727,10 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 		return true;
 	}
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+		return false;
+
 	/* Create new segment or open an existing one for attach. */
 	if (op == DSM_OP_CREATE)
 	{
diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c
index 3785e8af53..07dfd8f490 100644
--- a/src/backend/utils/activity/backend_status.c
+++ b/src/backend/utils/activity/backend_status.c
@@ -45,6 +45,9 @@
 bool		pgstat_track_activities = false;
 int			pgstat_track_activity_query_size = 1024;
 
+/* Max backend memory allocation allowed (MB). 0 = disabled */
+int			max_total_bkend_mem = 0;
+
 
 /* exposed so that backend_progress.c can access it */
 PgBackendStatus *MyBEEntry = NULL;
@@ -1236,3 +1239,108 @@ pgstat_reset_allocated_bytes_storage(void)
 	my_allocated_bytes = &local_my_allocated_bytes;
 }
 
+/* ----------
+ * pgstat_get_all_memory_allocated() -
+ *
+ *	Return a uint64 representing the current shared memory allocated to all
+ *	backends.  This looks directly at the BackendStatusArray, and so will
+ *	provide current information regardless of the age of our transaction's
+ *	snapshot of the status array.
+ *	In the future we will likely utilize additional values - perhaps limit
+ *	backend allocation by user/role, etc.
+ * ----------
+ */
+uint64
+pgstat_get_all_backend_memory_allocated(void)
+{
+	PgBackendStatus *beentry;
+	int			i;
+	uint64		all_memory_allocated = 0;
+
+	beentry = BackendStatusArray;
+
+	/*
+	 * We probably shouldn't get here before shared memory has been set up,
+	 * but be safe.
+	 */
+	if (beentry == NULL || BackendActivityBuffer == NULL)
+		return 0;
+
+	/*
+	 * We include AUX procs in all backend memory calculation
+	 */
+	for (i = 1; i <= NumBackendStatSlots; i++)
+	{
+		/*
+		 * We use a volatile pointer here to ensure the compiler doesn't try
+		 * to get cute.
+		 */
+		volatile PgBackendStatus *vbeentry = beentry;
+		bool		found;
+		uint64		allocated_bytes = 0;
+
+		for (;;)
+		{
+			int			before_changecount;
+			int			after_changecount;
+
+			pgstat_begin_read_activity(vbeentry, before_changecount);
+
+			/*
+			 * Ignore invalid entries, which may contain invalid data.
+			 * See pgstat_beshutdown_hook()
+			 */
+			if (vbeentry->st_procpid > 0)
+				allocated_bytes = vbeentry->allocated_bytes;
+
+			pgstat_end_read_activity(vbeentry, after_changecount);
+
+			if ((found = pgstat_read_activity_complete(before_changecount,
+													   after_changecount)))
+				break;
+
+			/* Make sure we can break out of loop if stuck... */
+			CHECK_FOR_INTERRUPTS();
+		}
+
+		if (found)
+			all_memory_allocated += allocated_bytes;
+
+		beentry++;
+	}
+
+	return all_memory_allocated;
+}
+
+/*
+ * Determine if allocation request will exceed max backend memory allowed.
+ * Do not apply to auxiliary processes.
+ */
+bool
+exceeds_max_total_bkend_mem(uint64 allocation_request)
+{
+	bool		result = false;
+
+	/* Exclude auxiliary processes from the check */
+	if (MyAuxProcType != NotAnAuxProcess)
+		return result;
+
+	/* Convert max_total_bkend_mem to bytes for comparison */
+	if (max_total_bkend_mem &&
+		pgstat_get_all_backend_memory_allocated() +
+		allocation_request > (uint64) max_total_bkend_mem * 1024 * 1024)
+	{
+		/*
+		 * Explicitly identify the OOM being a result of this configuration
+		 * parameter vs a system failure to allocate OOM.
+		 */
+		ereport(WARNING,
+				errmsg("allocation would exceed max_total_memory limit (%llu > %llu)",
+					   (unsigned long long) pgstat_get_all_backend_memory_allocated() +
+					   allocation_request, (unsigned long long) max_total_bkend_mem * 1024 * 1024));
+
+		result = true;
+	}
+
+	return result;
+}
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index 1bf14eec66..bfde338a8d 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -3423,6 +3423,17 @@ struct config_int ConfigureNamesInt[] =
 		NULL, NULL, NULL
 	},
 
+	{
+		{"max_total_backend_memory", PGC_SU_BACKEND, RESOURCES_MEM,
+			gettext_noop("Restrict total backend memory allocations to this max."),
+			gettext_noop("0 turns this feature off."),
+			GUC_UNIT_MB
+		},
+		&max_total_bkend_mem,
+		0, 0, INT_MAX,
+		NULL, NULL, NULL
+	},
+
 	/* End-of-list marker */
 	{
 		{NULL, 0, 0, NULL, NULL}, NULL, 0, 0, 0, NULL, NULL, NULL
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 043864597f..75ea0c9af1 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -155,6 +155,9 @@
 					#   mmap
 					# (change requires restart)
 #min_dynamic_shared_memory = 0MB	# (change requires restart)
+#max_total_backend_memory = 0MB		# Restrict total backend memory allocations
+									# to this max (in MB). 0 turns this feature
+									# off.
 
 # - Disk -
 
diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index cc10dfd609..3ce2191555 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -440,6 +440,10 @@ AllocSetContextCreateInternal(MemoryContext parent,
 	else
 		firstBlockSize = Max(firstBlockSize, initBlockSize);
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (exceeds_max_total_bkend_mem(firstBlockSize))
+		return NULL;
+
 	/*
 	 * Allocate the initial block.  Unlike other aset.c blocks, it starts with
 	 * the context header and its block header follows that.
@@ -741,6 +745,11 @@ AllocSetAlloc(MemoryContext context, Size size)
 #endif
 
 		blksize = chunk_size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
+
+		/* Do not exceed maximum allowed memory allocation */
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		block = (AllocBlock) malloc(blksize);
 		if (block == NULL)
 			return NULL;
@@ -938,6 +947,10 @@ AllocSetAlloc(MemoryContext context, Size size)
 		while (blksize < required_size)
 			blksize <<= 1;
 
+		/* Do not exceed maximum allowed memory allocation */
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		/* Try to allocate it */
 		block = (AllocBlock) malloc(blksize);
 
@@ -1178,6 +1191,10 @@ AllocSetRealloc(void *pointer, Size size)
 		blksize = chksize + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
 		oldblksize = block->endptr - ((char *) block);
 
+		/* Do not exceed maximum allowed memory allocation */
+		if (blksize > oldblksize && exceeds_max_total_bkend_mem(blksize - oldblksize))
+			return NULL;
+
 		block = (AllocBlock) realloc(block, blksize);
 		if (block == NULL)
 		{
diff --git a/src/backend/utils/mmgr/generation.c b/src/backend/utils/mmgr/generation.c
index b0460d97c2..3183c9a8dc 100644
--- a/src/backend/utils/mmgr/generation.c
+++ b/src/backend/utils/mmgr/generation.c
@@ -201,6 +201,9 @@ GenerationContextCreate(MemoryContext parent,
 	else
 		allocSize = Max(allocSize, initBlockSize);
 
+	if (exceeds_max_total_bkend_mem(allocSize))
+		return NULL;
+
 	/*
 	 * Allocate the initial block.  Unlike other generation.c blocks, it
 	 * starts with the context header and its block header follows that.
@@ -380,6 +383,9 @@ GenerationAlloc(MemoryContext context, Size size)
 	{
 		Size		blksize = required_size + Generation_BLOCKHDRSZ;
 
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		block = (GenerationBlock *) malloc(blksize);
 		if (block == NULL)
 			return NULL;
@@ -483,6 +489,9 @@ GenerationAlloc(MemoryContext context, Size size)
 			if (blksize < required_size)
 				blksize = pg_nextpower2_size_t(required_size);
 
+			if (exceeds_max_total_bkend_mem(blksize))
+				return NULL;
+
 			block = (GenerationBlock *) malloc(blksize);
 
 			if (block == NULL)
diff --git a/src/backend/utils/mmgr/slab.c b/src/backend/utils/mmgr/slab.c
index 08bb013f7c..2074f3853a 100644
--- a/src/backend/utils/mmgr/slab.c
+++ b/src/backend/utils/mmgr/slab.c
@@ -197,6 +197,10 @@ SlabContextCreate(MemoryContext parent,
 	headerSize += chunksPerBlock * sizeof(bool);
 #endif
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (exceeds_max_total_bkend_mem(headerSize))
+		return NULL;
+
 	slab = (SlabContext *) malloc(headerSize);
 	if (slab == NULL)
 	{
@@ -351,6 +355,10 @@ SlabAlloc(MemoryContext context, Size size)
 	 */
 	if (slab->minFreeChunks == 0)
 	{
+		/* Do not exceed maximum allowed memory allocation */
+		if (exceeds_max_total_bkend_mem(slab->blockSize))
+			return NULL;
+
 		block = (SlabBlock *) malloc(slab->blockSize);
 
 		if (block == NULL)
diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h
index 3ba479cb0d..1787d75ace 100644
--- a/src/include/utils/backend_status.h
+++ b/src/include/utils/backend_status.h
@@ -286,6 +286,7 @@ typedef struct LocalPgBackendStatus
  */
 extern PGDLLIMPORT bool pgstat_track_activities;
 extern PGDLLIMPORT int pgstat_track_activity_query_size;
+extern PGDLLIMPORT int max_total_bkend_mem;
 
 
 /* ----------
@@ -325,6 +326,7 @@ extern const char *pgstat_get_backend_current_activity(int pid, bool checkUser);
 extern const char *pgstat_get_crashed_backend_activity(int pid, char *buffer,
 													   int buflen);
 extern uint64 pgstat_get_my_query_id(void);
+extern uint64 pgstat_get_all_backend_memory_allocated(void);
 extern void pgstat_set_allocated_bytes_storage(uint64 *allocated_bytes);
 extern void pgstat_reset_allocated_bytes_storage(void);
 
@@ -337,6 +339,7 @@ extern int	pgstat_fetch_stat_numbackends(void);
 extern PgBackendStatus *pgstat_fetch_stat_beentry(BackendId beid);
 extern LocalPgBackendStatus *pgstat_fetch_stat_local_beentry(int beid);
 extern char *pgstat_clip_activity(const char *raw_activity);
+extern bool exceeds_max_total_bkend_mem(uint64 allocation_request);
 
 /* ----------
  * pgstat_report_allocated_bytes() -
-- 
2.25.1

0001-Add-tracking-of-backend-memory-allocated-to-pg_stat_.patchtext/x-patch; charset=UTF-8; name=0001-Add-tracking-of-backend-memory-allocated-to-pg_stat_.patchDownload
From fdb7e6d5bb653e9c5031fd058bf168bdf80a20eb Mon Sep 17 00:00:00 2001
From: Reid Thompson <jreidthompson@nc.rr.com>
Date: Thu, 11 Aug 2022 12:01:25 -0400
Subject: [PATCH 1/2] Add tracking of backend memory allocated to
 pg_stat_activity

This new field displays the current bytes of memory allocated to the
backend process. It is updated as memory for the process is
malloc'd/free'd. Memory allocated to items on the freelist is included in
the displayed value.  Dynamic shared memory allocations are included
only in the value displayed for the backend that created them, they are
not included in the value for backends that are attached to them to
avoid double counting. On occasion, orphaned memory segments may be
cleaned up on postmaster startup. This may result in decreasing the sum
without a prior increment. We limit the floor of backend_mem_allocated
to zero. Updated pg_stat_activity documentation for the new column.
---
 doc/src/sgml/monitoring.sgml                | 15 ++++
 src/backend/catalog/system_views.sql        |  1 +
 src/backend/postmaster/autovacuum.c         |  6 ++
 src/backend/postmaster/postmaster.c         | 13 ++++
 src/backend/postmaster/syslogger.c          |  3 +
 src/backend/storage/ipc/dsm_impl.c          | 81 +++++++++++++++++++++
 src/backend/utils/activity/backend_status.c | 45 ++++++++++++
 src/backend/utils/adt/pgstatfuncs.c         |  4 +-
 src/backend/utils/mmgr/aset.c               | 17 +++++
 src/backend/utils/mmgr/generation.c         | 15 ++++
 src/backend/utils/mmgr/slab.c               | 21 ++++++
 src/include/catalog/pg_proc.dat             |  6 +-
 src/include/utils/backend_status.h          | 59 ++++++++++++++-
 src/test/regress/expected/rules.out         |  9 ++-
 src/test/regress/expected/stats.out         | 11 +++
 src/test/regress/sql/stats.sql              |  3 +
 16 files changed, 300 insertions(+), 9 deletions(-)

diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 11a8ebe5ec..13ecbe5877 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -948,6 +948,21 @@ postgres   27093  0.0  0.0  30096  2752 ?        Ss   11:34   0:00 postgres: ser
      </para></entry>
     </row>
 
+    <row>
+     <entry role="catalog_table_entry"><para role="column_definition">
+      <structfield>allocated_bytes</structfield> <type>bigint</type>
+     </para>
+     <para>
+      Memory currently allocated to this backend in bytes. This is the balance
+      of bytes allocated and freed by this backend. Dynamic shared memory
+      allocations are included only in the value displayed for the backend that
+      created them, they are not included in the value for backends that are
+      attached to them to avoid double counting. Use <function>pg_size_pretty</function>
+      described in <xref linkend="functions-admin-dbsize"/> to make this value
+      more easily readable.
+     </para></entry>
+    </row>
+
      <row>
       <entry role="catalog_table_entry"><para role="column_definition">
        <structfield>query</structfield> <type>text</type>
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 2d8104b090..9ea8f78c95 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -864,6 +864,7 @@ CREATE VIEW pg_stat_activity AS
             S.state,
             S.backend_xid,
             s.backend_xmin,
+            S.allocated_bytes,
             S.query_id,
             S.query,
             S.backend_type
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index 0746d80224..f6b6f71cdb 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -407,6 +407,9 @@ StartAutoVacLauncher(void)
 
 #ifndef EXEC_BACKEND
 		case 0:
+			/* Zero allocated bytes to avoid double counting parent allocation */
+			pgstat_zero_my_allocated_bytes();
+
 			/* in postmaster child ... */
 			InitPostmasterChild();
 
@@ -1485,6 +1488,9 @@ StartAutoVacWorker(void)
 
 #ifndef EXEC_BACKEND
 		case 0:
+			/* Zero allocated bytes to avoid double counting parent allocation */
+			pgstat_zero_my_allocated_bytes();
+
 			/* in postmaster child ... */
 			InitPostmasterChild();
 
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index a8a246921f..89a6caec78 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -4102,6 +4102,9 @@ BackendStartup(Port *port)
 	{
 		free(bn);
 
+		/* Zero allocated bytes to avoid double counting parent allocation */
+		pgstat_zero_my_allocated_bytes();
+
 		/* Detangle from postmaster */
 		InitPostmasterChild();
 
@@ -5307,6 +5310,11 @@ StartChildProcess(AuxProcType type)
 		MemoryContextDelete(PostmasterContext);
 		PostmasterContext = NULL;
 
+		/* Zero allocated bytes to avoid double counting parent allocation.
+		 * Needs to be after the MemoryContextDelete(PostmasterContext) above.
+		 */
+		pgstat_zero_my_allocated_bytes();
+
 		AuxiliaryProcessMain(type); /* does not return */
 	}
 #endif							/* EXEC_BACKEND */
@@ -5700,6 +5708,11 @@ do_start_bgworker(RegisteredBgWorker *rw)
 			MemoryContextDelete(PostmasterContext);
 			PostmasterContext = NULL;
 
+			/* Zero allocated bytes to avoid double counting parent allocation.
+			 * Needs to be after the MemoryContextDelete(PostmasterContext) above.
+			 */
+			pgstat_zero_my_allocated_bytes();
+
 			StartBackgroundWorker();
 
 			exit(1);			/* should not get here */
diff --git a/src/backend/postmaster/syslogger.c b/src/backend/postmaster/syslogger.c
index d6d02e3c63..4cbc59cda5 100644
--- a/src/backend/postmaster/syslogger.c
+++ b/src/backend/postmaster/syslogger.c
@@ -679,6 +679,9 @@ SysLogger_Start(void)
 
 #ifndef EXEC_BACKEND
 		case 0:
+			/* Zero allocated bytes to avoid double counting parent allocation */
+			pgstat_zero_my_allocated_bytes();
+
 			/* in postmaster child ... */
 			InitPostmasterChild();
 
diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c
index 6ddd46a4e7..36ef3e425e 100644
--- a/src/backend/storage/ipc/dsm_impl.c
+++ b/src/backend/storage/ipc/dsm_impl.c
@@ -66,6 +66,7 @@
 #include "postmaster/postmaster.h"
 #include "storage/dsm_impl.h"
 #include "storage/fd.h"
+#include "utils/backend_status.h"
 #include "utils/guc.h"
 #include "utils/memutils.h"
 
@@ -232,6 +233,14 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_allocated_bytes(*mapped_size, PG_ALLOC_DECREASE);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && shm_unlink(name) != 0)
@@ -332,6 +341,36 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+	{
+		/*
+		 * Posix creation calls dsm_impl_posix_resize implying that resizing
+		 * occurs or may be added in the future. As implemented
+		 * dsm_impl_posix_resize utilizes fallocate or truncate, passing the
+		 * whole new size as input, growing the allocation as needed (only
+		 * truncate supports shrinking). We update by replacing the old
+		 * allocation with the new.
+		 */
+#if defined(HAVE_POSIX_FALLOCATE) && defined(__linux__)
+		/*
+		 * posix_fallocate does not shrink allocations, adjust only on
+		 * allocation increase.
+		 */
+		if (request_size > *mapped_size)
+		{
+			pgstat_report_allocated_bytes(request_size - *mapped_size,
+										  PG_ALLOC_INCREASE);
+		}
+#else
+		pgstat_report_allocated_bytes(*mapped_size, PG_ALLOC_DECREASE);
+		pgstat_report_allocated_bytes(request_size, PG_ALLOC_INCREASE);
+#endif
+	}
 	*mapped_address = address;
 	*mapped_size = request_size;
 	close(fd);
@@ -537,6 +576,14 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_allocated_bytes(*mapped_size, PG_ALLOC_DECREASE);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && shmctl(ident, IPC_RMID, NULL) < 0)
@@ -584,6 +631,13 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_allocated_bytes(request_size, PG_ALLOC_INCREASE);
 	*mapped_address = address;
 	*mapped_size = request_size;
 
@@ -652,6 +706,13 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 			return false;
 		}
 
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_allocated_bytes(*mapped_size, PG_ALLOC_DECREASE);
 		*impl_private = NULL;
 		*mapped_address = NULL;
 		*mapped_size = 0;
@@ -768,6 +829,12 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 		return false;
 	}
 
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_allocated_bytes(info.RegionSize, PG_ALLOC_INCREASE);
 	*mapped_address = address;
 	*mapped_size = info.RegionSize;
 	*impl_private = hmap;
@@ -812,6 +879,13 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		pgstat_report_allocated_bytes(*mapped_size, PG_ALLOC_DECREASE);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && unlink(name) != 0)
@@ -933,6 +1007,13 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_allocated_bytes(request_size, PG_ALLOC_INCREASE);
 	*mapped_address = address;
 	*mapped_size = request_size;
 
diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c
index 1146a6c33c..3785e8af53 100644
--- a/src/backend/utils/activity/backend_status.c
+++ b/src/backend/utils/activity/backend_status.c
@@ -49,6 +49,9 @@ int			pgstat_track_activity_query_size = 1024;
 /* exposed so that backend_progress.c can access it */
 PgBackendStatus *MyBEEntry = NULL;
 
+/* Memory allocated to this backend prior to pgstats initialization */
+uint64	local_my_allocated_bytes = 0;
+uint64	*my_allocated_bytes = &local_my_allocated_bytes;
 
 static PgBackendStatus *BackendStatusArray = NULL;
 static char *BackendAppnameBuffer = NULL;
@@ -400,6 +403,15 @@ pgstat_bestart(void)
 	lbeentry.st_progress_command_target = InvalidOid;
 	lbeentry.st_query_id = UINT64CONST(0);
 
+	/* Alter allocation reporting from local_my_allocated_bytes to shared memory */
+	pgstat_set_allocated_bytes_storage(&MyBEEntry->allocated_bytes);
+
+	/* Populate sum of memory allocated prior to pgstats initialization to pgstats
+	 * and zero the local variable.
+	 */
+	lbeentry.allocated_bytes += local_my_allocated_bytes;
+	local_my_allocated_bytes = 0;
+
 	/*
 	 * we don't zero st_progress_param here to save cycles; nobody should
 	 * examine it until st_progress_command has been set to something other
@@ -459,6 +471,11 @@ pgstat_beshutdown_hook(int code, Datum arg)
 {
 	volatile PgBackendStatus *beentry = MyBEEntry;
 
+	/*
+	 * Stop reporting memory allocation changes to &MyBEEntry->allocated_bytes
+	 */
+	pgstat_reset_allocated_bytes_storage();
+
 	/*
 	 * Clear my status entry, following the protocol of bumping st_changecount
 	 * before and after.  We use a volatile pointer here to ensure the
@@ -1191,3 +1208,31 @@ pgstat_clip_activity(const char *raw_activity)
 
 	return activity;
 }
+
+/*
+ * Configure bytes allocated reporting to report allocated bytes to
+ * *allocated_bytes.  *allocated_bytes needs to be valid until
+ * pgstat_set_allocated_bytes_storage() is called.
+ *
+ * Expected to be called during backend startup (in pgstat_bestart), to point
+ * my_allocated_bytes into shared memory.
+ */
+void
+pgstat_set_allocated_bytes_storage(uint64 *new_allocated_bytes)
+{
+	my_allocated_bytes = new_allocated_bytes;
+	*new_allocated_bytes = local_my_allocated_bytes;
+}
+
+/*
+ * Reset allocated bytes storage location.
+ *
+ * Expected to be called during backend shutdown, before the location set up
+ * by pgstat_set_allocated_bytes_storage() becomes invalid.
+ */
+void
+pgstat_reset_allocated_bytes_storage(void)
+{
+	my_allocated_bytes = &local_my_allocated_bytes;
+}
+
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 25a159b5e5..c4350cfa50 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -302,7 +302,7 @@ pg_stat_get_progress_info(PG_FUNCTION_ARGS)
 Datum
 pg_stat_get_activity(PG_FUNCTION_ARGS)
 {
-#define PG_STAT_GET_ACTIVITY_COLS	30
+#define PG_STAT_GET_ACTIVITY_COLS	31
 	int			num_backends = pgstat_fetch_stat_numbackends();
 	int			curr_backend;
 	int			pid = PG_ARGISNULL(0) ? -1 : PG_GETARG_INT32(0);
@@ -358,6 +358,8 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
 		else
 			nulls[16] = true;
 
+		values[30] = UInt64GetDatum(beentry->allocated_bytes);
+
 		/* Values only available to role member or pg_read_all_stats */
 		if (HAS_PGSTAT_PERMISSIONS(beentry->st_userid))
 		{
diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index b6a8bbcd59..cc10dfd609 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -47,6 +47,7 @@
 #include "postgres.h"
 
 #include "port/pg_bitutils.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -521,6 +522,7 @@ AllocSetContextCreateInternal(MemoryContext parent,
 						name);
 
 	((MemoryContext) set)->mem_allocated = firstBlockSize;
+	pgstat_report_allocated_bytes(firstBlockSize, PG_ALLOC_INCREASE);
 
 	return (MemoryContext) set;
 }
@@ -543,6 +545,7 @@ AllocSetReset(MemoryContext context)
 	AllocSet	set = (AllocSet) context;
 	AllocBlock	block;
 	Size		keepersize PG_USED_FOR_ASSERTS_ONLY;
+	uint64		deallocation = 0;
 
 	Assert(AllocSetIsValid(set));
 
@@ -585,6 +588,7 @@ AllocSetReset(MemoryContext context)
 		{
 			/* Normal case, release the block */
 			context->mem_allocated -= block->endptr - ((char *) block);
+			deallocation += block->endptr - ((char *) block);
 
 #ifdef CLOBBER_FREED_MEMORY
 			wipe_mem(block, block->freeptr - ((char *) block));
@@ -595,6 +599,7 @@ AllocSetReset(MemoryContext context)
 	}
 
 	Assert(context->mem_allocated == keepersize);
+	pgstat_report_allocated_bytes(deallocation, PG_ALLOC_DECREASE);
 
 	/* Reset block size allocation sequence, too */
 	set->nextBlockSize = set->initBlockSize;
@@ -613,6 +618,7 @@ AllocSetDelete(MemoryContext context)
 	AllocSet	set = (AllocSet) context;
 	AllocBlock	block = set->blocks;
 	Size		keepersize PG_USED_FOR_ASSERTS_ONLY;
+	uint64		deallocation = 0;
 
 	Assert(AllocSetIsValid(set));
 
@@ -651,11 +657,13 @@ AllocSetDelete(MemoryContext context)
 
 				freelist->first_free = (AllocSetContext *) oldset->header.nextchild;
 				freelist->num_free--;
+				deallocation += oldset->header.mem_allocated;
 
 				/* All that remains is to free the header/initial block */
 				free(oldset);
 			}
 			Assert(freelist->num_free == 0);
+			pgstat_report_allocated_bytes(deallocation, PG_ALLOC_DECREASE);
 		}
 
 		/* Now add the just-deleted context to the freelist. */
@@ -672,7 +680,10 @@ AllocSetDelete(MemoryContext context)
 		AllocBlock	next = block->next;
 
 		if (block != set->keeper)
+		{
 			context->mem_allocated -= block->endptr - ((char *) block);
+			deallocation += block->endptr - ((char *) block);
+		}
 
 #ifdef CLOBBER_FREED_MEMORY
 		wipe_mem(block, block->freeptr - ((char *) block));
@@ -685,6 +696,7 @@ AllocSetDelete(MemoryContext context)
 	}
 
 	Assert(context->mem_allocated == keepersize);
+	pgstat_report_allocated_bytes(deallocation + context->mem_allocated, PG_ALLOC_DECREASE);
 
 	/* Finally, free the context header, including the keeper block */
 	free(set);
@@ -734,6 +746,7 @@ AllocSetAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_allocated_bytes(blksize, PG_ALLOC_INCREASE);
 
 		block->aset = set;
 		block->freeptr = block->endptr = ((char *) block) + blksize;
@@ -944,6 +957,7 @@ AllocSetAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_allocated_bytes(blksize, PG_ALLOC_INCREASE);
 
 		block->aset = set;
 		block->freeptr = ((char *) block) + ALLOC_BLOCKHDRSZ;
@@ -1043,6 +1057,7 @@ AllocSetFree(void *pointer)
 			block->next->prev = block->prev;
 
 		set->header.mem_allocated -= block->endptr - ((char *) block);
+		pgstat_report_allocated_bytes(block->endptr - ((char *) block), PG_ALLOC_DECREASE);
 
 #ifdef CLOBBER_FREED_MEMORY
 		wipe_mem(block, block->freeptr - ((char *) block));
@@ -1173,7 +1188,9 @@ AllocSetRealloc(void *pointer, Size size)
 
 		/* updated separately, not to underflow when (oldblksize > blksize) */
 		set->header.mem_allocated -= oldblksize;
+		pgstat_report_allocated_bytes(oldblksize, PG_ALLOC_DECREASE);
 		set->header.mem_allocated += blksize;
+		pgstat_report_allocated_bytes(blksize, PG_ALLOC_INCREASE);
 
 		block->freeptr = block->endptr = ((char *) block) + blksize;
 
diff --git a/src/backend/utils/mmgr/generation.c b/src/backend/utils/mmgr/generation.c
index b432a92be3..b0460d97c2 100644
--- a/src/backend/utils/mmgr/generation.c
+++ b/src/backend/utils/mmgr/generation.c
@@ -37,6 +37,7 @@
 
 #include "lib/ilist.h"
 #include "port/pg_bitutils.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -267,6 +268,7 @@ GenerationContextCreate(MemoryContext parent,
 						name);
 
 	((MemoryContext) set)->mem_allocated = firstBlockSize;
+	pgstat_report_allocated_bytes(firstBlockSize, PG_ALLOC_INCREASE);
 
 	return (MemoryContext) set;
 }
@@ -283,6 +285,7 @@ GenerationReset(MemoryContext context)
 {
 	GenerationContext *set = (GenerationContext *) context;
 	dlist_mutable_iter miter;
+	uint64		deallocation = 0;
 
 	Assert(GenerationIsValid(set));
 
@@ -305,9 +308,14 @@ GenerationReset(MemoryContext context)
 		if (block == set->keeper)
 			GenerationBlockMarkEmpty(block);
 		else
+		{
+			deallocation += block->blksize;
 			GenerationBlockFree(set, block);
+		}
 	}
 
+	pgstat_report_allocated_bytes(deallocation, PG_ALLOC_DECREASE);
+
 	/* set it so new allocations to make use of the keeper block */
 	set->block = set->keeper;
 
@@ -328,6 +336,9 @@ GenerationDelete(MemoryContext context)
 {
 	/* Reset to release all releasable GenerationBlocks */
 	GenerationReset(context);
+
+	pgstat_report_allocated_bytes(context->mem_allocated, PG_ALLOC_DECREASE);
+
 	/* And free the context header and keeper block */
 	free(context);
 }
@@ -374,6 +385,7 @@ GenerationAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_allocated_bytes(blksize, PG_ALLOC_INCREASE);
 
 		/* block with a single (used) chunk */
 		block->context = set;
@@ -477,6 +489,7 @@ GenerationAlloc(MemoryContext context, Size size)
 				return NULL;
 
 			context->mem_allocated += blksize;
+			pgstat_report_allocated_bytes(blksize, PG_ALLOC_INCREASE);
 
 			/* initialize the new block */
 			GenerationBlockInit(set, block, blksize);
@@ -726,6 +739,8 @@ GenerationFree(void *pointer)
 	dlist_delete(&block->node);
 
 	set->header.mem_allocated -= block->blksize;
+	pgstat_report_allocated_bytes(block->blksize, PG_ALLOC_DECREASE);
+
 	free(block);
 }
 
diff --git a/src/backend/utils/mmgr/slab.c b/src/backend/utils/mmgr/slab.c
index 6df0839b6a..08bb013f7c 100644
--- a/src/backend/utils/mmgr/slab.c
+++ b/src/backend/utils/mmgr/slab.c
@@ -53,6 +53,7 @@
 #include "postgres.h"
 
 #include "lib/ilist.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -238,6 +239,12 @@ SlabContextCreate(MemoryContext parent,
 						parent,
 						name);
 
+	/*
+	 * If SlabContextCreate is updated to add headerSize to
+	 * context->mem_allocated, then update here and SlabDelete appropriately
+	 */
+	pgstat_report_allocated_bytes(headerSize, PG_ALLOC_INCREASE);
+
 	return (MemoryContext) slab;
 }
 
@@ -253,6 +260,7 @@ SlabReset(MemoryContext context)
 {
 	SlabContext *slab = (SlabContext *) context;
 	int			i;
+	uint64		deallocation = 0;
 
 	Assert(SlabIsValid(slab));
 
@@ -278,9 +286,11 @@ SlabReset(MemoryContext context)
 			free(block);
 			slab->nblocks--;
 			context->mem_allocated -= slab->blockSize;
+			deallocation += slab->blockSize;
 		}
 	}
 
+	pgstat_report_allocated_bytes(deallocation, PG_ALLOC_DECREASE);
 	slab->minFreeChunks = 0;
 
 	Assert(slab->nblocks == 0);
@@ -294,8 +304,17 @@ SlabReset(MemoryContext context)
 void
 SlabDelete(MemoryContext context)
 {
+	/*
+	 * Until header allocation is included in context->mem_allocated, cast to
+	 * slab and decrement the headerSize
+	 */
+	SlabContext *slab = castNode(SlabContext, context);
+
 	/* Reset to release all the SlabBlocks */
 	SlabReset(context);
+
+	pgstat_report_allocated_bytes(slab->headerSize, PG_ALLOC_DECREASE);
+
 	/* And free the context header */
 	free(context);
 }
@@ -364,6 +383,7 @@ SlabAlloc(MemoryContext context, Size size)
 		slab->minFreeChunks = slab->chunksPerBlock;
 		slab->nblocks += 1;
 		context->mem_allocated += slab->blockSize;
+		pgstat_report_allocated_bytes(slab->blockSize, PG_ALLOC_INCREASE);
 	}
 
 	/* grab the block from the freelist (even the new block is there) */
@@ -537,6 +557,7 @@ SlabFree(void *pointer)
 		free(block);
 		slab->nblocks--;
 		slab->header.mem_allocated -= slab->blockSize;
+		pgstat_report_allocated_bytes(slab->blockSize, PG_ALLOC_DECREASE);
 	}
 	else
 		dlist_push_head(&slab->freelist[block->nfree], &block->node);
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index f9301b2627..1bf02758d4 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -5373,9 +5373,9 @@
   proname => 'pg_stat_get_activity', prorows => '100', proisstrict => 'f',
   proretset => 't', provolatile => 's', proparallel => 'r',
   prorettype => 'record', proargtypes => 'int4',
-  proallargtypes => '{int4,oid,int4,oid,text,text,text,text,text,timestamptz,timestamptz,timestamptz,timestamptz,inet,text,int4,xid,xid,text,bool,text,text,int4,text,numeric,text,bool,text,bool,int4,int8}',
-  proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
-  proargnames => '{pid,datid,pid,usesysid,application_name,state,query,wait_event_type,wait_event,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,backend_type,ssl,sslversion,sslcipher,sslbits,ssl_client_dn,ssl_client_serial,ssl_issuer_dn,gss_auth,gss_princ,gss_enc,leader_pid,query_id}',
+  proallargtypes => '{int4,oid,int4,oid,text,text,text,text,text,timestamptz,timestamptz,timestamptz,timestamptz,inet,text,int4,xid,xid,text,bool,text,text,int4,text,numeric,text,bool,text,bool,int4,int8,int8}',
+  proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
+  proargnames => '{pid,datid,pid,usesysid,application_name,state,query,wait_event_type,wait_event,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,backend_type,ssl,sslversion,sslcipher,sslbits,ssl_client_dn,ssl_client_serial,ssl_issuer_dn,gss_auth,gss_princ,gss_enc,leader_pid,query_id,allocated_bytes}',
   prosrc => 'pg_stat_get_activity' },
 { oid => '3318',
   descr => 'statistics: information about progress of backends running maintenance command',
diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h
index b582b46e9f..3ba479cb0d 100644
--- a/src/include/utils/backend_status.h
+++ b/src/include/utils/backend_status.h
@@ -15,6 +15,7 @@
 #include "miscadmin.h"			/* for BackendType */
 #include "storage/backendid.h"
 #include "utils/backend_progress.h"
+#include "common/int.h"
 
 
 /* ----------
@@ -32,6 +33,13 @@ typedef enum BackendState
 	STATE_DISABLED
 } BackendState;
 
+/* Enum helper for reporting memory allocated bytes */
+enum allocation_direction
+{
+	PG_ALLOC_DECREASE = -1,
+	PG_ALLOC_IGNORE,
+	PG_ALLOC_INCREASE,
+};
 
 /* ----------
  * Shared-memory data structures
@@ -169,6 +177,9 @@ typedef struct PgBackendStatus
 
 	/* query identifier, optionally computed using post_parse_analyze_hook */
 	uint64		st_query_id;
+
+	/* Current memory allocated to this backend */
+	uint64		allocated_bytes;
 } PgBackendStatus;
 
 
@@ -282,6 +293,7 @@ extern PGDLLIMPORT int pgstat_track_activity_query_size;
  * ----------
  */
 extern PGDLLIMPORT PgBackendStatus *MyBEEntry;
+extern PGDLLIMPORT uint64 *my_allocated_bytes;
 
 
 /* ----------
@@ -313,7 +325,8 @@ extern const char *pgstat_get_backend_current_activity(int pid, bool checkUser);
 extern const char *pgstat_get_crashed_backend_activity(int pid, char *buffer,
 													   int buflen);
 extern uint64 pgstat_get_my_query_id(void);
-
+extern void pgstat_set_allocated_bytes_storage(uint64 *allocated_bytes);
+extern void pgstat_reset_allocated_bytes_storage(void);
 
 /* ----------
  * Support functions for the SQL-callable functions to
@@ -325,5 +338,49 @@ extern PgBackendStatus *pgstat_fetch_stat_beentry(BackendId beid);
 extern LocalPgBackendStatus *pgstat_fetch_stat_local_beentry(int beid);
 extern char *pgstat_clip_activity(const char *raw_activity);
 
+/* ----------
+ * pgstat_report_allocated_bytes() -
+ *
+ *  Called to report change in memory allocated for this backend.
+ *
+ * my_allocated_bytes initially points to local memory, making it safe to call
+ * this before pgstats has been initialized. allocation_direction is a
+ * positive/negative multiplier enum defined above.
+ * ----------
+ */
+static inline void
+pgstat_report_allocated_bytes(int64 allocated_bytes, int allocation_direction)
+{
+	uint64 temp;
+
+	/* Avoid *my_allocated_bytes unsigned integer overflow on PG_ALLOC_DECREASE */
+	if (allocation_direction == PG_ALLOC_DECREASE &&
+		pg_sub_u64_overflow(*my_allocated_bytes, allocated_bytes, &temp))
+	{
+		*my_allocated_bytes = 0;
+		ereport(LOG,
+				errmsg("Backend %d deallocated %lld bytes, exceeding the %llu bytes it is currently reporting allocated. Setting reported to 0.",
+					   MyProcPid, (long long)allocated_bytes, (unsigned long long)*my_allocated_bytes));
+	}
+	else
+		*my_allocated_bytes += (allocated_bytes) * allocation_direction;
+
+	return;
+}
+
+/* ---------
+ * pgstat_zero_my_allocated_bytes() -
+ *
+ * Called to zero out local allocated bytes variable after fork to avoid double
+ * counting allocations.
+ * ---------
+ */
+static inline void
+pgstat_zero_my_allocated_bytes(void)
+{
+	*my_allocated_bytes = 0;
+
+    return;
+}
 
 #endif							/* BACKEND_STATUS_H */
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index fb9f936d43..5f854aab18 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1756,10 +1756,11 @@ pg_stat_activity| SELECT s.datid,
     s.state,
     s.backend_xid,
     s.backend_xmin,
+    s.allocated_bytes,
     s.query_id,
     s.query,
     s.backend_type
-   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, allocated_bytes)
      LEFT JOIN pg_database d ON ((s.datid = d.oid)))
      LEFT JOIN pg_authid u ON ((s.usesysid = u.oid)));
 pg_stat_all_indexes| SELECT c.oid AS relid,
@@ -1874,7 +1875,7 @@ pg_stat_gssapi| SELECT s.pid,
     s.gss_auth AS gss_authenticated,
     s.gss_princ AS principal,
     s.gss_enc AS encrypted
-   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, allocated_bytes)
   WHERE (s.client_port IS NOT NULL);
 pg_stat_progress_analyze| SELECT s.pid,
     s.datid,
@@ -2055,7 +2056,7 @@ pg_stat_replication| SELECT s.pid,
     w.sync_priority,
     w.sync_state,
     w.reply_time
-   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, allocated_bytes)
      JOIN pg_stat_get_wal_senders() w(pid, state, sent_lsn, write_lsn, flush_lsn, replay_lsn, write_lag, flush_lag, replay_lag, sync_priority, sync_state, reply_time) ON ((s.pid = w.pid)))
      LEFT JOIN pg_authid u ON ((s.usesysid = u.oid)));
 pg_stat_replication_slots| SELECT s.slot_name,
@@ -2089,7 +2090,7 @@ pg_stat_ssl| SELECT s.pid,
     s.ssl_client_dn AS client_dn,
     s.ssl_client_serial AS client_serial,
     s.ssl_issuer_dn AS issuer_dn
-   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, allocated_bytes)
   WHERE (s.client_port IS NOT NULL);
 pg_stat_subscription| SELECT su.oid AS subid,
     su.subname,
diff --git a/src/test/regress/expected/stats.out b/src/test/regress/expected/stats.out
index 1d84407a03..ab7e95c367 100644
--- a/src/test/regress/expected/stats.out
+++ b/src/test/regress/expected/stats.out
@@ -1126,4 +1126,15 @@ SELECT pg_stat_get_subscription_stats(NULL);
  
 (1 row)
 
+-- ensure that allocated_bytes exist for backends
+SELECT allocated_bytes > 0 AS result FROM pg_stat_activity WHERE backend_type
+IN ('checkpointer', 'background writer', 'walwriter', 'autovacuum launcher');
+ result 
+--------
+ t
+ t
+ t
+ t
+(4 rows)
+
 -- End of Stats Test
diff --git a/src/test/regress/sql/stats.sql b/src/test/regress/sql/stats.sql
index b4d6753c71..2f0b1cc9d8 100644
--- a/src/test/regress/sql/stats.sql
+++ b/src/test/regress/sql/stats.sql
@@ -535,5 +535,8 @@ SET enable_seqscan TO on;
 SELECT pg_stat_get_replication_slot(NULL);
 SELECT pg_stat_get_subscription_stats(NULL);
 
+-- ensure that allocated_bytes exist for backends
+SELECT allocated_bytes > 0 AS result FROM pg_stat_activity WHERE backend_type
+IN ('checkpointer', 'background writer', 'walwriter', 'autovacuum launcher');
 
 -- End of Stats Test
-- 
2.25.1

#20vignesh C
vignesh21@gmail.com
In reply to: Reid Thompson (#19)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On Fri, 9 Dec 2022 at 20:41, Reid Thompson
<reid.thompson@crunchydata.com> wrote:

On Tue, 2022-12-06 at 10:32 -0800, Andres Freund wrote:

Hi,

On 2022-11-26 22:22:15 -0500, Reid Thompson wrote:

rebased/patched to current master && current pg-stat-activity-
backend-memory-allocated

This version fails to build with msvc, and builds with warnings on
other
platforms.
https://cirrus-ci.com/build/5410696721072128
msvc:

Andres Freund

updated patches

The patch does not apply on top of HEAD as in [1]http://cfbot.cputube.org/patch_41_3867.log, please post a rebased patch:
=== Applying patches on top of PostgreSQL commit ID
92957ed98c5c565362ce665266132a7f08f6b0c0 ===
=== applying patch
./0001-Add-tracking-of-backend-memory-allocated-to-pg_stat_.patch
...
patching file src/backend/utils/mmgr/slab.c
Hunk #1 succeeded at 69 (offset 16 lines).
Hunk #2 succeeded at 414 (offset 175 lines).
Hunk #3 succeeded at 436 with fuzz 2 (offset 176 lines).
Hunk #4 FAILED at 286.
Hunk #5 succeeded at 488 (offset 186 lines).
Hunk #6 FAILED at 381.
Hunk #7 FAILED at 554.
3 out of 7 hunks FAILED -- saving rejects to file
src/backend/utils/mmgr/slab.c.rej

[1]: http://cfbot.cputube.org/patch_41_3867.log

Regards,
Vignesh

#21Reid Thompson
reid.thompson@crunchydata.com
In reply to: vignesh C (#20)
2 attachment(s)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On Tue, 2023-01-03 at 16:22 +0530, vignesh C wrote:

....
The patch does not apply on top of HEAD as in [1], please post a
rebased patch:
...
Regards,
Vignesh

Attached is rebased patch, with some updates related to committed changes.

Thanks,
Reid

--
Reid Thompson
Senior Software Engineer
Crunchy Data, Inc.

reid.thompson@crunchydata.com
www.crunchydata.com

Attachments:

0002-Add-the-ability-to-limit-the-amount-of-memory-that-c.patchtext/x-patch; charset=UTF-8; name=0002-Add-the-ability-to-limit-the-amount-of-memory-that-c.patchDownload
From 69516942b71d5d41850fbc00b971db7476c7a01a Mon Sep 17 00:00:00 2001
From: Reid Thompson <jreidthompson@nc.rr.com>
Date: Sat, 4 Jun 2022 22:23:59 -0400
Subject: [PATCH 2/2] Add the ability to limit the amount of memory that can be
 allocated to backends.

This builds on the work that adds backend memory allocated to pg_stat_activity.

Add GUC variable max_total_backend_memory.

Specifies a limit to the amount of memory (in MB) that may be allocated to
backends in total (i.e. this is not a per user or per backend limit). If unset,
or set to 0 it is disabled. It is intended as a resource to help avoid the OOM
killer on LINUX and manage resources in general. A backend request that would
push the total over the limit will be denied with an out of memory error causing
that backend's current query/transaction to fail. Due to the dynamic nature of
memory allocations, this limit is not exact. If within 1.5MB of the limit and
two backends request 1MB each at the same time both may be allocated, and exceed
the limit. Further requests will not be allocated until dropping below the
limit. Keep this in mind when setting this value. This limit does not affect
auxiliary backend processes. Backend memory allocations are displayed in the
pg_stat_activity view.
---
 doc/src/sgml/config.sgml                      |  26 +++++
 src/backend/storage/ipc/dsm_impl.c            |  12 ++
 src/backend/utils/activity/backend_status.c   | 108 ++++++++++++++++++
 src/backend/utils/misc/guc_tables.c           |  11 ++
 src/backend/utils/misc/postgresql.conf.sample |   3 +
 src/backend/utils/mmgr/aset.c                 |  17 +++
 src/backend/utils/mmgr/generation.c           |   9 ++
 src/backend/utils/mmgr/slab.c                 |   9 +-
 src/include/utils/backend_status.h            |   3 +
 9 files changed, 197 insertions(+), 1 deletion(-)

diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 05b3862d09..0362f26451 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -2079,6 +2079,32 @@ include_dir 'conf.d'
       </listitem>
      </varlistentry>
 
+     <varlistentry id="guc-max-total-backend-memory" xreflabel="max_total_backend_memory">
+      <term><varname>max_total_backend_memory</varname> (<type>integer</type>)
+      <indexterm>
+       <primary><varname>max_total_backend_memory</varname> configuration parameter</primary>
+      </indexterm>
+      </term>
+      <listitem>
+       <para>
+        Specifies a limit to the amount of memory (MB) that may be allocated to
+        backends in total (i.e. this is not a per user or per backend limit).
+        If unset, or set to 0 it is disabled.  A backend request that would
+        push the total over the limit will be denied with an out of memory
+        error causing that backend's current query/transaction to fail. Due to
+        the dynamic nature of memory allocations, this limit is not exact. If
+        within 1.5MB of the limit and two backends request 1MB each at the same
+        time both may be allocated, and exceed the limit. Further requests will
+        not be allocated until dropping below the limit. Keep this in mind when
+        setting this value. This limit does not affect auxiliary backend
+        processes <xref linkend="glossary-auxiliary-proc"/> . Backend memory
+        allocations (<varname>allocated_bytes</varname>) are displayed in the
+        <link linkend="monitoring-pg-stat-activity-view"><structname>pg_stat_activity</structname></link>
+        view.
+       </para>
+      </listitem>
+     </varlistentry>
+
      </variablelist>
      </sect2>
 
diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c
index 22885c7bd2..f7047107d5 100644
--- a/src/backend/storage/ipc/dsm_impl.c
+++ b/src/backend/storage/ipc/dsm_impl.c
@@ -254,6 +254,10 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 		return true;
 	}
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+		return false;
+
 	/*
 	 * Create new segment or open an existing one for attach.
 	 *
@@ -525,6 +529,10 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 		int			flags = IPCProtection;
 		size_t		segsize;
 
+		/* Do not exceed maximum allowed memory allocation */
+		if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+			return false;
+
 		/*
 		 * Allocate the memory BEFORE acquiring the resource, so that we don't
 		 * leak the resource if memory allocation fails.
@@ -719,6 +727,10 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 		return true;
 	}
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+		return false;
+
 	/* Create new segment or open an existing one for attach. */
 	if (op == DSM_OP_CREATE)
 	{
diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c
index 7baf2db57d..da2b5fb042 100644
--- a/src/backend/utils/activity/backend_status.c
+++ b/src/backend/utils/activity/backend_status.c
@@ -45,6 +45,9 @@
 bool		pgstat_track_activities = false;
 int			pgstat_track_activity_query_size = 1024;
 
+/* Max backend memory allocation allowed (MB). 0 = disabled */
+int			max_total_bkend_mem = 0;
+
 
 /* exposed so that backend_progress.c can access it */
 PgBackendStatus *MyBEEntry = NULL;
@@ -1239,3 +1242,108 @@ pgstat_reset_allocated_bytes_storage(void)
 	my_allocated_bytes = &local_my_allocated_bytes;
 }
 
+/* ----------
+ * pgstat_get_all_memory_allocated() -
+ *
+ *	Return a uint64 representing the current shared memory allocated to all
+ *	backends.  This looks directly at the BackendStatusArray, and so will
+ *	provide current information regardless of the age of our transaction's
+ *	snapshot of the status array.
+ *	In the future we will likely utilize additional values - perhaps limit
+ *	backend allocation by user/role, etc.
+ * ----------
+ */
+uint64
+pgstat_get_all_backend_memory_allocated(void)
+{
+	PgBackendStatus *beentry;
+	int			i;
+	uint64		all_memory_allocated = 0;
+
+	beentry = BackendStatusArray;
+
+	/*
+	 * We probably shouldn't get here before shared memory has been set up,
+	 * but be safe.
+	 */
+	if (beentry == NULL || BackendActivityBuffer == NULL)
+		return 0;
+
+	/*
+	 * We include AUX procs in all backend memory calculation
+	 */
+	for (i = 1; i <= NumBackendStatSlots; i++)
+	{
+		/*
+		 * We use a volatile pointer here to ensure the compiler doesn't try
+		 * to get cute.
+		 */
+		volatile PgBackendStatus *vbeentry = beentry;
+		bool		found;
+		uint64		allocated_bytes = 0;
+
+		for (;;)
+		{
+			int			before_changecount;
+			int			after_changecount;
+
+			pgstat_begin_read_activity(vbeentry, before_changecount);
+
+			/*
+			 * Ignore invalid entries, which may contain invalid data.
+			 * See pgstat_beshutdown_hook()
+			 */
+			if (vbeentry->st_procpid > 0)
+				allocated_bytes = vbeentry->allocated_bytes;
+
+			pgstat_end_read_activity(vbeentry, after_changecount);
+
+			if ((found = pgstat_read_activity_complete(before_changecount,
+													   after_changecount)))
+				break;
+
+			/* Make sure we can break out of loop if stuck... */
+			CHECK_FOR_INTERRUPTS();
+		}
+
+		if (found)
+			all_memory_allocated += allocated_bytes;
+
+		beentry++;
+	}
+
+	return all_memory_allocated;
+}
+
+/*
+ * Determine if allocation request will exceed max backend memory allowed.
+ * Do not apply to auxiliary processes.
+ */
+bool
+exceeds_max_total_bkend_mem(uint64 allocation_request)
+{
+	bool		result = false;
+
+	/* Exclude auxiliary processes from the check */
+	if (MyAuxProcType != NotAnAuxProcess)
+		return result;
+
+	/* Convert max_total_bkend_mem to bytes for comparison */
+	if (max_total_bkend_mem &&
+		pgstat_get_all_backend_memory_allocated() +
+		allocation_request > (uint64) max_total_bkend_mem * 1024 * 1024)
+	{
+		/*
+		 * Explicitly identify the OOM being a result of this configuration
+		 * parameter vs a system failure to allocate OOM.
+		 */
+		ereport(WARNING,
+				errmsg("allocation would exceed max_total_memory limit (%llu > %llu)",
+					   (unsigned long long) pgstat_get_all_backend_memory_allocated() +
+					   allocation_request, (unsigned long long) max_total_bkend_mem * 1024 * 1024));
+
+		result = true;
+	}
+
+	return result;
+}
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index 68328b1402..5e58d6c1bc 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -3444,6 +3444,17 @@ struct config_int ConfigureNamesInt[] =
 		NULL, NULL, NULL
 	},
 
+	{
+		{"max_total_backend_memory", PGC_SU_BACKEND, RESOURCES_MEM,
+			gettext_noop("Restrict total backend memory allocations to this max."),
+			gettext_noop("0 turns this feature off."),
+			GUC_UNIT_MB
+		},
+		&max_total_bkend_mem,
+		0, 0, INT_MAX,
+		NULL, NULL, NULL
+	},
+
 	/* End-of-list marker */
 	{
 		{NULL, 0, 0, NULL, NULL}, NULL, 0, 0, 0, NULL, NULL, NULL
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 5afdeb04de..1f1eaac5f4 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -155,6 +155,9 @@
 					#   mmap
 					# (change requires restart)
 #min_dynamic_shared_memory = 0MB	# (change requires restart)
+#max_total_backend_memory = 0MB		# Restrict total backend memory allocations
+									# to this max (in MB). 0 turns this feature
+									# off.
 
 # - Disk -
 
diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index 94e5f4b5be..6ae78acc41 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -440,6 +440,10 @@ AllocSetContextCreateInternal(MemoryContext parent,
 	else
 		firstBlockSize = Max(firstBlockSize, initBlockSize);
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (exceeds_max_total_bkend_mem(firstBlockSize))
+		return NULL;
+
 	/*
 	 * Allocate the initial block.  Unlike other aset.c blocks, it starts with
 	 * the context header and its block header follows that.
@@ -741,6 +745,11 @@ AllocSetAlloc(MemoryContext context, Size size)
 #endif
 
 		blksize = chunk_size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
+
+		/* Do not exceed maximum allowed memory allocation */
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		block = (AllocBlock) malloc(blksize);
 		if (block == NULL)
 			return NULL;
@@ -938,6 +947,10 @@ AllocSetAlloc(MemoryContext context, Size size)
 		while (blksize < required_size)
 			blksize <<= 1;
 
+		/* Do not exceed maximum allowed memory allocation */
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		/* Try to allocate it */
 		block = (AllocBlock) malloc(blksize);
 
@@ -1178,6 +1191,10 @@ AllocSetRealloc(void *pointer, Size size)
 		blksize = chksize + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
 		oldblksize = block->endptr - ((char *) block);
 
+		/* Do not exceed maximum allowed memory allocation */
+		if (blksize > oldblksize && exceeds_max_total_bkend_mem(blksize - oldblksize))
+			return NULL;
+
 		block = (AllocBlock) realloc(block, blksize);
 		if (block == NULL)
 		{
diff --git a/src/backend/utils/mmgr/generation.c b/src/backend/utils/mmgr/generation.c
index 97007ca0ee..4d8b250cb4 100644
--- a/src/backend/utils/mmgr/generation.c
+++ b/src/backend/utils/mmgr/generation.c
@@ -201,6 +201,9 @@ GenerationContextCreate(MemoryContext parent,
 	else
 		allocSize = Max(allocSize, initBlockSize);
 
+	if (exceeds_max_total_bkend_mem(allocSize))
+		return NULL;
+
 	/*
 	 * Allocate the initial block.  Unlike other generation.c blocks, it
 	 * starts with the context header and its block header follows that.
@@ -380,6 +383,9 @@ GenerationAlloc(MemoryContext context, Size size)
 	{
 		Size		blksize = required_size + Generation_BLOCKHDRSZ;
 
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		block = (GenerationBlock *) malloc(blksize);
 		if (block == NULL)
 			return NULL;
@@ -483,6 +489,9 @@ GenerationAlloc(MemoryContext context, Size size)
 			if (blksize < required_size)
 				blksize = pg_nextpower2_size_t(required_size);
 
+			if (exceeds_max_total_bkend_mem(blksize))
+				return NULL;
+
 			block = (GenerationBlock *) malloc(blksize);
 
 			if (block == NULL)
diff --git a/src/backend/utils/mmgr/slab.c b/src/backend/utils/mmgr/slab.c
index e314f8f343..adc88e0047 100644
--- a/src/backend/utils/mmgr/slab.c
+++ b/src/backend/utils/mmgr/slab.c
@@ -356,9 +356,12 @@ SlabContextCreate(MemoryContext parent,
 		elog(ERROR, "block size %zu for slab is too small for %zu-byte chunks",
 			 blockSize, chunkSize);
 
-
+	/* Do not exceed maximum allowed memory allocation */
+	if (exceeds_max_total_bkend_mem(Slab_CONTEXT_HDRSZ(chunksPerBlock)))
+		return NULL;
 
 	slab = (SlabContext *) malloc(Slab_CONTEXT_HDRSZ(chunksPerBlock));
+
 	if (slab == NULL)
 	{
 		MemoryContextStats(TopMemoryContext);
@@ -559,6 +562,10 @@ SlabAlloc(MemoryContext context, Size size)
 		}
 		else
 		{
+			/* Do not exceed maximum allowed memory allocation */
+			if (exceeds_max_total_bkend_mem(slab->blockSize))
+				return NULL;
+
 			block = (SlabBlock *) malloc(slab->blockSize);
 
 			if (unlikely(block == NULL))
diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h
index 754ff0dc62..33269eb11b 100644
--- a/src/include/utils/backend_status.h
+++ b/src/include/utils/backend_status.h
@@ -297,6 +297,7 @@ typedef struct LocalPgBackendStatus
  */
 extern PGDLLIMPORT bool pgstat_track_activities;
 extern PGDLLIMPORT int pgstat_track_activity_query_size;
+extern PGDLLIMPORT int max_total_bkend_mem;
 
 
 /* ----------
@@ -336,6 +337,7 @@ extern const char *pgstat_get_backend_current_activity(int pid, bool checkUser);
 extern const char *pgstat_get_crashed_backend_activity(int pid, char *buffer,
 													   int buflen);
 extern uint64 pgstat_get_my_query_id(void);
+extern uint64 pgstat_get_all_backend_memory_allocated(void);
 extern void pgstat_set_allocated_bytes_storage(uint64 *allocated_bytes);
 extern void pgstat_reset_allocated_bytes_storage(void);
 
@@ -348,6 +350,7 @@ extern int	pgstat_fetch_stat_numbackends(void);
 extern PgBackendStatus *pgstat_fetch_stat_beentry(BackendId beid);
 extern LocalPgBackendStatus *pgstat_fetch_stat_local_beentry(int beid);
 extern char *pgstat_clip_activity(const char *raw_activity);
+extern bool exceeds_max_total_bkend_mem(uint64 allocation_request);
 
 /* ----------
  * pgstat_report_allocated_bytes() -
-- 
2.25.1

0001-Add-tracking-of-backend-memory-allocated-to-pg_stat_.patchtext/x-patch; charset=UTF-8; name=0001-Add-tracking-of-backend-memory-allocated-to-pg_stat_.patchDownload
From 0a6b152e0559a250dddd33bd7d43eb0959432e0d Mon Sep 17 00:00:00 2001
From: Reid Thompson <jreidthompson@nc.rr.com>
Date: Thu, 11 Aug 2022 12:01:25 -0400
Subject: [PATCH 1/2] Add tracking of backend memory allocated to
 pg_stat_activity

This new field displays the current bytes of memory allocated to the
backend process. It is updated as memory for the process is
malloc'd/free'd. Memory allocated to items on the freelist is included in
the displayed value.  Dynamic shared memory allocations are included
only in the value displayed for the backend that created them, they are
not included in the value for backends that are attached to them to
avoid double counting. On occasion, orphaned memory segments may be
cleaned up on postmaster startup. This may result in decreasing the sum
without a prior increment. We limit the floor of backend_mem_allocated
to zero. Updated pg_stat_activity documentation for the new column.
---
 doc/src/sgml/monitoring.sgml                | 15 ++++
 src/backend/catalog/system_views.sql        |  1 +
 src/backend/postmaster/autovacuum.c         |  6 ++
 src/backend/postmaster/postmaster.c         | 13 ++++
 src/backend/postmaster/syslogger.c          |  3 +
 src/backend/storage/ipc/dsm_impl.c          | 81 +++++++++++++++++++++
 src/backend/utils/activity/backend_status.c | 45 ++++++++++++
 src/backend/utils/adt/pgstatfuncs.c         |  4 +-
 src/backend/utils/mmgr/aset.c               | 17 +++++
 src/backend/utils/mmgr/generation.c         | 15 ++++
 src/backend/utils/mmgr/slab.c               | 22 ++++++
 src/include/catalog/pg_proc.dat             |  6 +-
 src/include/utils/backend_status.h          | 63 +++++++++++++++-
 src/test/regress/expected/rules.out         |  9 ++-
 src/test/regress/expected/stats.out         | 11 +++
 src/test/regress/sql/stats.sql              |  3 +
 16 files changed, 305 insertions(+), 9 deletions(-)

diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 5bcba0fdec..63d2357d71 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -955,6 +955,21 @@ postgres   27093  0.0  0.0  30096  2752 ?        Ss   11:34   0:00 postgres: ser
      </para></entry>
     </row>
 
+    <row>
+     <entry role="catalog_table_entry"><para role="column_definition">
+      <structfield>allocated_bytes</structfield> <type>bigint</type>
+     </para>
+     <para>
+      Memory currently allocated to this backend in bytes. This is the balance
+      of bytes allocated and freed by this backend. Dynamic shared memory
+      allocations are included only in the value displayed for the backend that
+      created them, they are not included in the value for backends that are
+      attached to them to avoid double counting. Use <function>pg_size_pretty</function>
+      described in <xref linkend="functions-admin-dbsize"/> to make this value
+      more easily readable.
+     </para></entry>
+    </row>
+
      <row>
       <entry role="catalog_table_entry"><para role="column_definition">
        <structfield>query</structfield> <type>text</type>
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 447c9b970f..9ba7073fa1 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -864,6 +864,7 @@ CREATE VIEW pg_stat_activity AS
             S.state,
             S.backend_xid,
             s.backend_xmin,
+            S.allocated_bytes,
             S.query_id,
             S.query,
             S.backend_type
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index e40bd39b3f..a7953c548d 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -407,6 +407,9 @@ StartAutoVacLauncher(void)
 
 #ifndef EXEC_BACKEND
 		case 0:
+			/* Zero allocated bytes to avoid double counting parent allocation */
+			pgstat_zero_my_allocated_bytes();
+
 			/* in postmaster child ... */
 			InitPostmasterChild();
 
@@ -1485,6 +1488,9 @@ StartAutoVacWorker(void)
 
 #ifndef EXEC_BACKEND
 		case 0:
+			/* Zero allocated bytes to avoid double counting parent allocation */
+			pgstat_zero_my_allocated_bytes();
+
 			/* in postmaster child ... */
 			InitPostmasterChild();
 
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index eac3450774..24278e5c18 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -4102,6 +4102,9 @@ BackendStartup(Port *port)
 	{
 		free(bn);
 
+		/* Zero allocated bytes to avoid double counting parent allocation */
+		pgstat_zero_my_allocated_bytes();
+
 		/* Detangle from postmaster */
 		InitPostmasterChild();
 
@@ -5307,6 +5310,11 @@ StartChildProcess(AuxProcType type)
 		MemoryContextDelete(PostmasterContext);
 		PostmasterContext = NULL;
 
+		/* Zero allocated bytes to avoid double counting parent allocation.
+		 * Needs to be after the MemoryContextDelete(PostmasterContext) above.
+		 */
+		pgstat_zero_my_allocated_bytes();
+
 		AuxiliaryProcessMain(type); /* does not return */
 	}
 #endif							/* EXEC_BACKEND */
@@ -5700,6 +5708,11 @@ do_start_bgworker(RegisteredBgWorker *rw)
 			MemoryContextDelete(PostmasterContext);
 			PostmasterContext = NULL;
 
+			/* Zero allocated bytes to avoid double counting parent allocation.
+			 * Needs to be after the MemoryContextDelete(PostmasterContext) above.
+			 */
+			pgstat_zero_my_allocated_bytes();
+
 			StartBackgroundWorker();
 
 			exit(1);			/* should not get here */
diff --git a/src/backend/postmaster/syslogger.c b/src/backend/postmaster/syslogger.c
index a876d02c6f..0d51af6fd8 100644
--- a/src/backend/postmaster/syslogger.c
+++ b/src/backend/postmaster/syslogger.c
@@ -679,6 +679,9 @@ SysLogger_Start(void)
 
 #ifndef EXEC_BACKEND
 		case 0:
+			/* Zero allocated bytes to avoid double counting parent allocation */
+			pgstat_zero_my_allocated_bytes();
+
 			/* in postmaster child ... */
 			InitPostmasterChild();
 
diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c
index f0965c3481..22885c7bd2 100644
--- a/src/backend/storage/ipc/dsm_impl.c
+++ b/src/backend/storage/ipc/dsm_impl.c
@@ -66,6 +66,7 @@
 #include "postmaster/postmaster.h"
 #include "storage/dsm_impl.h"
 #include "storage/fd.h"
+#include "utils/backend_status.h"
 #include "utils/guc.h"
 #include "utils/memutils.h"
 
@@ -232,6 +233,14 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_allocated_bytes(*mapped_size, PG_ALLOC_DECREASE);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && shm_unlink(name) != 0)
@@ -332,6 +341,36 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+	{
+		/*
+		 * Posix creation calls dsm_impl_posix_resize implying that resizing
+		 * occurs or may be added in the future. As implemented
+		 * dsm_impl_posix_resize utilizes fallocate or truncate, passing the
+		 * whole new size as input, growing the allocation as needed (only
+		 * truncate supports shrinking). We update by replacing the old
+		 * allocation with the new.
+		 */
+#if defined(HAVE_POSIX_FALLOCATE) && defined(__linux__)
+		/*
+		 * posix_fallocate does not shrink allocations, adjust only on
+		 * allocation increase.
+		 */
+		if (request_size > *mapped_size)
+		{
+			pgstat_report_allocated_bytes(request_size - *mapped_size,
+										  PG_ALLOC_INCREASE);
+		}
+#else
+		pgstat_report_allocated_bytes(*mapped_size, PG_ALLOC_DECREASE);
+		pgstat_report_allocated_bytes(request_size, PG_ALLOC_INCREASE);
+#endif
+	}
 	*mapped_address = address;
 	*mapped_size = request_size;
 	close(fd);
@@ -537,6 +576,14 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_allocated_bytes(*mapped_size, PG_ALLOC_DECREASE);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && shmctl(ident, IPC_RMID, NULL) < 0)
@@ -584,6 +631,13 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_allocated_bytes(request_size, PG_ALLOC_INCREASE);
 	*mapped_address = address;
 	*mapped_size = request_size;
 
@@ -652,6 +706,13 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 			return false;
 		}
 
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_allocated_bytes(*mapped_size, PG_ALLOC_DECREASE);
 		*impl_private = NULL;
 		*mapped_address = NULL;
 		*mapped_size = 0;
@@ -768,6 +829,12 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 		return false;
 	}
 
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_allocated_bytes(info.RegionSize, PG_ALLOC_INCREASE);
 	*mapped_address = address;
 	*mapped_size = info.RegionSize;
 	*impl_private = hmap;
@@ -812,6 +879,13 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		pgstat_report_allocated_bytes(*mapped_size, PG_ALLOC_DECREASE);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && unlink(name) != 0)
@@ -933,6 +1007,13 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_allocated_bytes(request_size, PG_ALLOC_INCREASE);
 	*mapped_address = address;
 	*mapped_size = request_size;
 
diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c
index 608d01ea0d..7baf2db57d 100644
--- a/src/backend/utils/activity/backend_status.c
+++ b/src/backend/utils/activity/backend_status.c
@@ -49,6 +49,9 @@ int			pgstat_track_activity_query_size = 1024;
 /* exposed so that backend_progress.c can access it */
 PgBackendStatus *MyBEEntry = NULL;
 
+/* Memory allocated to this backend prior to pgstats initialization */
+uint64	local_my_allocated_bytes = 0;
+uint64	*my_allocated_bytes = &local_my_allocated_bytes;
 
 static PgBackendStatus *BackendStatusArray = NULL;
 static char *BackendAppnameBuffer = NULL;
@@ -400,6 +403,15 @@ pgstat_bestart(void)
 	lbeentry.st_progress_command_target = InvalidOid;
 	lbeentry.st_query_id = UINT64CONST(0);
 
+	/* Alter allocation reporting from local_my_allocated_bytes to shared memory */
+	pgstat_set_allocated_bytes_storage(&MyBEEntry->allocated_bytes);
+
+	/* Populate sum of memory allocated prior to pgstats initialization to pgstats
+	 * and zero the local variable.
+	 */
+	lbeentry.allocated_bytes += local_my_allocated_bytes;
+	local_my_allocated_bytes = 0;
+
 	/*
 	 * we don't zero st_progress_param here to save cycles; nobody should
 	 * examine it until st_progress_command has been set to something other
@@ -459,6 +471,11 @@ pgstat_beshutdown_hook(int code, Datum arg)
 {
 	volatile PgBackendStatus *beentry = MyBEEntry;
 
+	/*
+	 * Stop reporting memory allocation changes to &MyBEEntry->allocated_bytes
+	 */
+	pgstat_reset_allocated_bytes_storage();
+
 	/*
 	 * Clear my status entry, following the protocol of bumping st_changecount
 	 * before and after.  We use a volatile pointer here to ensure the
@@ -1194,3 +1211,31 @@ pgstat_clip_activity(const char *raw_activity)
 
 	return activity;
 }
+
+/*
+ * Configure bytes allocated reporting to report allocated bytes to
+ * *allocated_bytes.  *allocated_bytes needs to be valid until
+ * pgstat_set_allocated_bytes_storage() is called.
+ *
+ * Expected to be called during backend startup (in pgstat_bestart), to point
+ * my_allocated_bytes into shared memory.
+ */
+void
+pgstat_set_allocated_bytes_storage(uint64 *new_allocated_bytes)
+{
+	my_allocated_bytes = new_allocated_bytes;
+	*new_allocated_bytes = local_my_allocated_bytes;
+}
+
+/*
+ * Reset allocated bytes storage location.
+ *
+ * Expected to be called during backend shutdown, before the location set up
+ * by pgstat_set_allocated_bytes_storage() becomes invalid.
+ */
+void
+pgstat_reset_allocated_bytes_storage(void)
+{
+	my_allocated_bytes = &local_my_allocated_bytes;
+}
+
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 6cddd74aa7..2d672101f0 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -302,7 +302,7 @@ pg_stat_get_progress_info(PG_FUNCTION_ARGS)
 Datum
 pg_stat_get_activity(PG_FUNCTION_ARGS)
 {
-#define PG_STAT_GET_ACTIVITY_COLS	30
+#define PG_STAT_GET_ACTIVITY_COLS	31
 	int			num_backends = pgstat_fetch_stat_numbackends();
 	int			curr_backend;
 	int			pid = PG_ARGISNULL(0) ? -1 : PG_GETARG_INT32(0);
@@ -358,6 +358,8 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
 		else
 			nulls[16] = true;
 
+		values[30] = UInt64GetDatum(beentry->allocated_bytes);
+
 		/* Values only available to role member or pg_read_all_stats */
 		if (HAS_PGSTAT_PERMISSIONS(beentry->st_userid))
 		{
diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index ef10bb1690..94e5f4b5be 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -47,6 +47,7 @@
 #include "postgres.h"
 
 #include "port/pg_bitutils.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -521,6 +522,7 @@ AllocSetContextCreateInternal(MemoryContext parent,
 						name);
 
 	((MemoryContext) set)->mem_allocated = firstBlockSize;
+	pgstat_report_allocated_bytes(firstBlockSize, PG_ALLOC_INCREASE);
 
 	return (MemoryContext) set;
 }
@@ -543,6 +545,7 @@ AllocSetReset(MemoryContext context)
 	AllocSet	set = (AllocSet) context;
 	AllocBlock	block;
 	Size		keepersize PG_USED_FOR_ASSERTS_ONLY;
+	uint64		deallocation = 0;
 
 	Assert(AllocSetIsValid(set));
 
@@ -585,6 +588,7 @@ AllocSetReset(MemoryContext context)
 		{
 			/* Normal case, release the block */
 			context->mem_allocated -= block->endptr - ((char *) block);
+			deallocation += block->endptr - ((char *) block);
 
 #ifdef CLOBBER_FREED_MEMORY
 			wipe_mem(block, block->freeptr - ((char *) block));
@@ -595,6 +599,7 @@ AllocSetReset(MemoryContext context)
 	}
 
 	Assert(context->mem_allocated == keepersize);
+	pgstat_report_allocated_bytes(deallocation, PG_ALLOC_DECREASE);
 
 	/* Reset block size allocation sequence, too */
 	set->nextBlockSize = set->initBlockSize;
@@ -613,6 +618,7 @@ AllocSetDelete(MemoryContext context)
 	AllocSet	set = (AllocSet) context;
 	AllocBlock	block = set->blocks;
 	Size		keepersize PG_USED_FOR_ASSERTS_ONLY;
+	uint64		deallocation = 0;
 
 	Assert(AllocSetIsValid(set));
 
@@ -651,11 +657,13 @@ AllocSetDelete(MemoryContext context)
 
 				freelist->first_free = (AllocSetContext *) oldset->header.nextchild;
 				freelist->num_free--;
+				deallocation += oldset->header.mem_allocated;
 
 				/* All that remains is to free the header/initial block */
 				free(oldset);
 			}
 			Assert(freelist->num_free == 0);
+			pgstat_report_allocated_bytes(deallocation, PG_ALLOC_DECREASE);
 		}
 
 		/* Now add the just-deleted context to the freelist. */
@@ -672,7 +680,10 @@ AllocSetDelete(MemoryContext context)
 		AllocBlock	next = block->next;
 
 		if (block != set->keeper)
+		{
 			context->mem_allocated -= block->endptr - ((char *) block);
+			deallocation += block->endptr - ((char *) block);
+		}
 
 #ifdef CLOBBER_FREED_MEMORY
 		wipe_mem(block, block->freeptr - ((char *) block));
@@ -685,6 +696,7 @@ AllocSetDelete(MemoryContext context)
 	}
 
 	Assert(context->mem_allocated == keepersize);
+	pgstat_report_allocated_bytes(deallocation + context->mem_allocated, PG_ALLOC_DECREASE);
 
 	/* Finally, free the context header, including the keeper block */
 	free(set);
@@ -734,6 +746,7 @@ AllocSetAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_allocated_bytes(blksize, PG_ALLOC_INCREASE);
 
 		block->aset = set;
 		block->freeptr = block->endptr = ((char *) block) + blksize;
@@ -944,6 +957,7 @@ AllocSetAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_allocated_bytes(blksize, PG_ALLOC_INCREASE);
 
 		block->aset = set;
 		block->freeptr = ((char *) block) + ALLOC_BLOCKHDRSZ;
@@ -1043,6 +1057,7 @@ AllocSetFree(void *pointer)
 			block->next->prev = block->prev;
 
 		set->header.mem_allocated -= block->endptr - ((char *) block);
+		pgstat_report_allocated_bytes(block->endptr - ((char *) block), PG_ALLOC_DECREASE);
 
 #ifdef CLOBBER_FREED_MEMORY
 		wipe_mem(block, block->freeptr - ((char *) block));
@@ -1173,7 +1188,9 @@ AllocSetRealloc(void *pointer, Size size)
 
 		/* updated separately, not to underflow when (oldblksize > blksize) */
 		set->header.mem_allocated -= oldblksize;
+		pgstat_report_allocated_bytes(oldblksize, PG_ALLOC_DECREASE);
 		set->header.mem_allocated += blksize;
+		pgstat_report_allocated_bytes(blksize, PG_ALLOC_INCREASE);
 
 		block->freeptr = block->endptr = ((char *) block) + blksize;
 
diff --git a/src/backend/utils/mmgr/generation.c b/src/backend/utils/mmgr/generation.c
index 93825265a1..97007ca0ee 100644
--- a/src/backend/utils/mmgr/generation.c
+++ b/src/backend/utils/mmgr/generation.c
@@ -37,6 +37,7 @@
 
 #include "lib/ilist.h"
 #include "port/pg_bitutils.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -267,6 +268,7 @@ GenerationContextCreate(MemoryContext parent,
 						name);
 
 	((MemoryContext) set)->mem_allocated = firstBlockSize;
+	pgstat_report_allocated_bytes(firstBlockSize, PG_ALLOC_INCREASE);
 
 	return (MemoryContext) set;
 }
@@ -283,6 +285,7 @@ GenerationReset(MemoryContext context)
 {
 	GenerationContext *set = (GenerationContext *) context;
 	dlist_mutable_iter miter;
+	uint64		deallocation = 0;
 
 	Assert(GenerationIsValid(set));
 
@@ -305,9 +308,14 @@ GenerationReset(MemoryContext context)
 		if (block == set->keeper)
 			GenerationBlockMarkEmpty(block);
 		else
+		{
+			deallocation += block->blksize;
 			GenerationBlockFree(set, block);
+		}
 	}
 
+	pgstat_report_allocated_bytes(deallocation, PG_ALLOC_DECREASE);
+
 	/* set it so new allocations to make use of the keeper block */
 	set->block = set->keeper;
 
@@ -328,6 +336,9 @@ GenerationDelete(MemoryContext context)
 {
 	/* Reset to release all releasable GenerationBlocks */
 	GenerationReset(context);
+
+	pgstat_report_allocated_bytes(context->mem_allocated, PG_ALLOC_DECREASE);
+
 	/* And free the context header and keeper block */
 	free(context);
 }
@@ -374,6 +385,7 @@ GenerationAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_allocated_bytes(blksize, PG_ALLOC_INCREASE);
 
 		/* block with a single (used) chunk */
 		block->context = set;
@@ -477,6 +489,7 @@ GenerationAlloc(MemoryContext context, Size size)
 				return NULL;
 
 			context->mem_allocated += blksize;
+			pgstat_report_allocated_bytes(blksize, PG_ALLOC_INCREASE);
 
 			/* initialize the new block */
 			GenerationBlockInit(set, block, blksize);
@@ -726,6 +739,8 @@ GenerationFree(void *pointer)
 	dlist_delete(&block->node);
 
 	set->header.mem_allocated -= block->blksize;
+	pgstat_report_allocated_bytes(block->blksize, PG_ALLOC_DECREASE);
+
 	free(block);
 }
 
diff --git a/src/backend/utils/mmgr/slab.c b/src/backend/utils/mmgr/slab.c
index 33dca0f37c..e314f8f343 100644
--- a/src/backend/utils/mmgr/slab.c
+++ b/src/backend/utils/mmgr/slab.c
@@ -69,6 +69,7 @@
 #include "postgres.h"
 
 #include "lib/ilist.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -413,6 +414,13 @@ SlabContextCreate(MemoryContext parent,
 						parent,
 						name);
 
+	/*
+	 * If SlabContextCreate is updated to add context header size to
+	 * context->mem_allocated, then update here and SlabDelete appropriately
+	 */
+	pgstat_report_allocated_bytes(Slab_CONTEXT_HDRSZ(slab->chunksPerBlock),
+								  PG_ALLOC_INCREASE);
+
 	return (MemoryContext) slab;
 }
 
@@ -429,6 +437,7 @@ SlabReset(MemoryContext context)
 	SlabContext *slab = (SlabContext *) context;
 	dlist_mutable_iter miter;
 	int			i;
+	uint64		deallocation = 0;
 
 	Assert(SlabIsValid(slab));
 
@@ -465,9 +474,11 @@ SlabReset(MemoryContext context)
 #endif
 			free(block);
 			context->mem_allocated -= slab->blockSize;
+			deallocation += slab->blockSize;
 		}
 	}
 
+	pgstat_report_allocated_bytes(deallocation, PG_ALLOC_DECREASE);
 	slab->curBlocklistIndex = 0;
 
 	Assert(context->mem_allocated == 0);
@@ -480,8 +491,17 @@ SlabReset(MemoryContext context)
 void
 SlabDelete(MemoryContext context)
 {
+
 	/* Reset to release all the SlabBlocks */
 	SlabReset(context);
+
+	/*
+	 * Until context header allocation is included in context->mem_allocated,
+	 * cast to slab and decrement the header allocation
+	 */
+	pgstat_report_allocated_bytes(Slab_CONTEXT_HDRSZ(((SlabContext *)context)->chunksPerBlock),
+								  PG_ALLOC_DECREASE);
+
 	/* And free the context header */
 	free(context);
 }
@@ -546,6 +566,7 @@ SlabAlloc(MemoryContext context, Size size)
 
 			block->slab = slab;
 			context->mem_allocated += slab->blockSize;
+			pgstat_report_allocated_bytes(slab->blockSize, PG_ALLOC_INCREASE);
 
 			/* use the first chunk in the new block */
 			chunk = SlabBlockGetChunk(slab, block, 0);
@@ -732,6 +753,7 @@ SlabFree(void *pointer)
 #endif
 			free(block);
 			slab->header.mem_allocated -= slab->blockSize;
+			pgstat_report_allocated_bytes(slab->blockSize, PG_ALLOC_DECREASE);
 		}
 
 		/*
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 7be9a50147..f8a3f2ffa2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -5373,9 +5373,9 @@
   proname => 'pg_stat_get_activity', prorows => '100', proisstrict => 'f',
   proretset => 't', provolatile => 's', proparallel => 'r',
   prorettype => 'record', proargtypes => 'int4',
-  proallargtypes => '{int4,oid,int4,oid,text,text,text,text,text,timestamptz,timestamptz,timestamptz,timestamptz,inet,text,int4,xid,xid,text,bool,text,text,int4,text,numeric,text,bool,text,bool,int4,int8}',
-  proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
-  proargnames => '{pid,datid,pid,usesysid,application_name,state,query,wait_event_type,wait_event,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,backend_type,ssl,sslversion,sslcipher,sslbits,ssl_client_dn,ssl_client_serial,ssl_issuer_dn,gss_auth,gss_princ,gss_enc,leader_pid,query_id}',
+  proallargtypes => '{int4,oid,int4,oid,text,text,text,text,text,timestamptz,timestamptz,timestamptz,timestamptz,inet,text,int4,xid,xid,text,bool,text,text,int4,text,numeric,text,bool,text,bool,int4,int8,int8}',
+  proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
+  proargnames => '{pid,datid,pid,usesysid,application_name,state,query,wait_event_type,wait_event,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,backend_type,ssl,sslversion,sslcipher,sslbits,ssl_client_dn,ssl_client_serial,ssl_issuer_dn,gss_auth,gss_princ,gss_enc,leader_pid,query_id,allocated_bytes}',
   prosrc => 'pg_stat_get_activity' },
 { oid => '3318',
   descr => 'statistics: information about progress of backends running maintenance command',
diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h
index f7bd83113a..754ff0dc62 100644
--- a/src/include/utils/backend_status.h
+++ b/src/include/utils/backend_status.h
@@ -15,6 +15,7 @@
 #include "miscadmin.h"			/* for BackendType */
 #include "storage/backendid.h"
 #include "utils/backend_progress.h"
+#include "common/int.h"
 
 
 /* ----------
@@ -32,6 +33,13 @@ typedef enum BackendState
 	STATE_DISABLED
 } BackendState;
 
+/* Enum helper for reporting memory allocated bytes */
+enum allocation_direction
+{
+	PG_ALLOC_DECREASE = -1,
+	PG_ALLOC_IGNORE,
+	PG_ALLOC_INCREASE,
+};
 
 /* ----------
  * Shared-memory data structures
@@ -169,6 +177,9 @@ typedef struct PgBackendStatus
 
 	/* query identifier, optionally computed using post_parse_analyze_hook */
 	uint64		st_query_id;
+
+	/* Current memory allocated to this backend */
+	uint64		allocated_bytes;
 } PgBackendStatus;
 
 
@@ -293,6 +304,7 @@ extern PGDLLIMPORT int pgstat_track_activity_query_size;
  * ----------
  */
 extern PGDLLIMPORT PgBackendStatus *MyBEEntry;
+extern PGDLLIMPORT uint64 *my_allocated_bytes;
 
 
 /* ----------
@@ -324,7 +336,8 @@ extern const char *pgstat_get_backend_current_activity(int pid, bool checkUser);
 extern const char *pgstat_get_crashed_backend_activity(int pid, char *buffer,
 													   int buflen);
 extern uint64 pgstat_get_my_query_id(void);
-
+extern void pgstat_set_allocated_bytes_storage(uint64 *allocated_bytes);
+extern void pgstat_reset_allocated_bytes_storage(void);
 
 /* ----------
  * Support functions for the SQL-callable functions to
@@ -336,5 +349,53 @@ extern PgBackendStatus *pgstat_fetch_stat_beentry(BackendId beid);
 extern LocalPgBackendStatus *pgstat_fetch_stat_local_beentry(int beid);
 extern char *pgstat_clip_activity(const char *raw_activity);
 
+/* ----------
+ * pgstat_report_allocated_bytes() -
+ *
+ *  Called to report change in memory allocated for this backend.
+ *
+ * my_allocated_bytes initially points to local memory, making it safe to call
+ * this before pgstats has been initialized. allocation_direction is a
+ * positive/negative multiplier enum defined above.
+ * ----------
+ */
+static inline void
+pgstat_report_allocated_bytes(int64 allocated_bytes, int allocation_direction)
+{
+	uint64		temp;
+
+	/*
+	 * Avoid *my_allocated_bytes unsigned integer overflow on
+	 * PG_ALLOC_DECREASE
+	 */
+	if (allocation_direction == PG_ALLOC_DECREASE &&
+		pg_sub_u64_overflow(*my_allocated_bytes, allocated_bytes, &temp))
+	{
+		*my_allocated_bytes = 0;
+		ereport(LOG,
+				errmsg("Backend %d deallocated %lld bytes, exceeding the %llu bytes it is currently reporting allocated. Setting reported to 0.",
+					   MyProcPid, (long long) allocated_bytes,
+					   (unsigned long long) *my_allocated_bytes));
+	}
+	else
+		*my_allocated_bytes += (allocated_bytes) * allocation_direction;
+
+	return;
+}
+
+/* ---------
+ * pgstat_zero_my_allocated_bytes() -
+ *
+ * Called to zero out local allocated bytes variable after fork to avoid double
+ * counting allocations.
+ * ---------
+ */
+static inline void
+pgstat_zero_my_allocated_bytes(void)
+{
+	*my_allocated_bytes = 0;
+
+	return;
+}
 
 #endif							/* BACKEND_STATUS_H */
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index fb9f936d43..5f854aab18 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1756,10 +1756,11 @@ pg_stat_activity| SELECT s.datid,
     s.state,
     s.backend_xid,
     s.backend_xmin,
+    s.allocated_bytes,
     s.query_id,
     s.query,
     s.backend_type
-   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, allocated_bytes)
      LEFT JOIN pg_database d ON ((s.datid = d.oid)))
      LEFT JOIN pg_authid u ON ((s.usesysid = u.oid)));
 pg_stat_all_indexes| SELECT c.oid AS relid,
@@ -1874,7 +1875,7 @@ pg_stat_gssapi| SELECT s.pid,
     s.gss_auth AS gss_authenticated,
     s.gss_princ AS principal,
     s.gss_enc AS encrypted
-   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, allocated_bytes)
   WHERE (s.client_port IS NOT NULL);
 pg_stat_progress_analyze| SELECT s.pid,
     s.datid,
@@ -2055,7 +2056,7 @@ pg_stat_replication| SELECT s.pid,
     w.sync_priority,
     w.sync_state,
     w.reply_time
-   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, allocated_bytes)
      JOIN pg_stat_get_wal_senders() w(pid, state, sent_lsn, write_lsn, flush_lsn, replay_lsn, write_lag, flush_lag, replay_lag, sync_priority, sync_state, reply_time) ON ((s.pid = w.pid)))
      LEFT JOIN pg_authid u ON ((s.usesysid = u.oid)));
 pg_stat_replication_slots| SELECT s.slot_name,
@@ -2089,7 +2090,7 @@ pg_stat_ssl| SELECT s.pid,
     s.ssl_client_dn AS client_dn,
     s.ssl_client_serial AS client_serial,
     s.ssl_issuer_dn AS issuer_dn
-   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, allocated_bytes)
   WHERE (s.client_port IS NOT NULL);
 pg_stat_subscription| SELECT su.oid AS subid,
     su.subname,
diff --git a/src/test/regress/expected/stats.out b/src/test/regress/expected/stats.out
index 1d84407a03..ab7e95c367 100644
--- a/src/test/regress/expected/stats.out
+++ b/src/test/regress/expected/stats.out
@@ -1126,4 +1126,15 @@ SELECT pg_stat_get_subscription_stats(NULL);
  
 (1 row)
 
+-- ensure that allocated_bytes exist for backends
+SELECT allocated_bytes > 0 AS result FROM pg_stat_activity WHERE backend_type
+IN ('checkpointer', 'background writer', 'walwriter', 'autovacuum launcher');
+ result 
+--------
+ t
+ t
+ t
+ t
+(4 rows)
+
 -- End of Stats Test
diff --git a/src/test/regress/sql/stats.sql b/src/test/regress/sql/stats.sql
index b4d6753c71..2f0b1cc9d8 100644
--- a/src/test/regress/sql/stats.sql
+++ b/src/test/regress/sql/stats.sql
@@ -535,5 +535,8 @@ SET enable_seqscan TO on;
 SELECT pg_stat_get_replication_slot(NULL);
 SELECT pg_stat_get_subscription_stats(NULL);
 
+-- ensure that allocated_bytes exist for backends
+SELECT allocated_bytes > 0 AS result FROM pg_stat_activity WHERE backend_type
+IN ('checkpointer', 'background writer', 'walwriter', 'autovacuum launcher');
 
 -- End of Stats Test
-- 
2.25.1

#22Andres Freund
andres@anarazel.de
In reply to: Reid Thompson (#21)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

Hi,

On 2023-01-05 13:44:20 -0500, Reid Thompson wrote:

From 0a6b152e0559a250dddd33bd7d43eb0959432e0d Mon Sep 17 00:00:00 2001
From: Reid Thompson <jreidthompson@nc.rr.com>
Date: Thu, 11 Aug 2022 12:01:25 -0400
Subject: [PATCH 1/2] Add tracking of backend memory allocated to
pg_stat_activity

This new field displays the current bytes of memory allocated to the
backend process. It is updated as memory for the process is
malloc'd/free'd. Memory allocated to items on the freelist is included in
the displayed value.

It doesn't actually malloc/free. It tracks palloc/pfree.

Dynamic shared memory allocations are included only in the value displayed
for the backend that created them, they are not included in the value for
backends that are attached to them to avoid double counting.

As mentioned before, I don't think accounting DSM this way makes sense.

--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -407,6 +407,9 @@ StartAutoVacLauncher(void)
#ifndef EXEC_BACKEND
case 0:
+			/* Zero allocated bytes to avoid double counting parent allocation */
+			pgstat_zero_my_allocated_bytes();
+
/* in postmaster child ... */
InitPostmasterChild();

@@ -1485,6 +1488,9 @@ StartAutoVacWorker(void)

#ifndef EXEC_BACKEND
case 0:
+			/* Zero allocated bytes to avoid double counting parent allocation */
+			pgstat_zero_my_allocated_bytes();
+
/* in postmaster child ... */
InitPostmasterChild();
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index eac3450774..24278e5c18 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -4102,6 +4102,9 @@ BackendStartup(Port *port)
{
free(bn);
+		/* Zero allocated bytes to avoid double counting parent allocation */
+		pgstat_zero_my_allocated_bytes();
+
/* Detangle from postmaster */
InitPostmasterChild();

It doesn't at all seem right to call pgstat_zero_my_allocated_bytes() here,
before even InitPostmasterChild() is called. Nor does it seem right to add the
call to so many places.

Note that this is before we even delete postmaster's memory, see e.g.:
/*
* If the PostmasterContext is still around, recycle the space; we don't
* need it anymore after InitPostgres completes. Note this does not trash
* *MyProcPort, because ConnCreate() allocated that space with malloc()
* ... else we'd need to copy the Port data first. Also, subsidiary data
* such as the username isn't lost either; see ProcessStartupPacket().
*/
if (PostmasterContext)
{
MemoryContextDelete(PostmasterContext);
PostmasterContext = NULL;
}

calling pgstat_zero_my_allocated_bytes() before we do this will lead to
undercounting memory usage, afaict.

+/* Enum helper for reporting memory allocated bytes */
+enum allocation_direction
+{
+	PG_ALLOC_DECREASE = -1,
+	PG_ALLOC_IGNORE,
+	PG_ALLOC_INCREASE,
+};

What's the point of this?

+/* ----------
+ * pgstat_report_allocated_bytes() -
+ *
+ *  Called to report change in memory allocated for this backend.
+ *
+ * my_allocated_bytes initially points to local memory, making it safe to call
+ * this before pgstats has been initialized. allocation_direction is a
+ * positive/negative multiplier enum defined above.
+ * ----------
+ */
+static inline void
+pgstat_report_allocated_bytes(int64 allocated_bytes, int allocation_direction)

I don't think this should take allocation_direction as a parameter, I'd make
it two different functions.

+{
+	uint64		temp;
+
+	/*
+	 * Avoid *my_allocated_bytes unsigned integer overflow on
+	 * PG_ALLOC_DECREASE
+	 */
+	if (allocation_direction == PG_ALLOC_DECREASE &&
+		pg_sub_u64_overflow(*my_allocated_bytes, allocated_bytes, &temp))
+	{
+		*my_allocated_bytes = 0;
+		ereport(LOG,
+				errmsg("Backend %d deallocated %lld bytes, exceeding the %llu bytes it is currently reporting allocated. Setting reported to 0.",
+					   MyProcPid, (long long) allocated_bytes,
+					   (unsigned long long) *my_allocated_bytes));

We certainly shouldn't have an ereport in here. This stuff really needs to be
cheap.

+	}
+	else
+		*my_allocated_bytes += (allocated_bytes) * allocation_direction;

Superfluous parens?

+/* ----------
+ * pgstat_get_all_memory_allocated() -
+ *
+ *	Return a uint64 representing the current shared memory allocated to all
+ *	backends.  This looks directly at the BackendStatusArray, and so will
+ *	provide current information regardless of the age of our transaction's
+ *	snapshot of the status array.
+ *	In the future we will likely utilize additional values - perhaps limit
+ *	backend allocation by user/role, etc.
+ * ----------
+ */
+uint64
+pgstat_get_all_backend_memory_allocated(void)
+{
+	PgBackendStatus *beentry;
+	int			i;
+	uint64		all_memory_allocated = 0;
+
+	beentry = BackendStatusArray;
+
+	/*
+	 * We probably shouldn't get here before shared memory has been set up,
+	 * but be safe.
+	 */
+	if (beentry == NULL || BackendActivityBuffer == NULL)
+		return 0;
+
+	/*
+	 * We include AUX procs in all backend memory calculation
+	 */
+	for (i = 1; i <= NumBackendStatSlots; i++)
+	{
+		/*
+		 * We use a volatile pointer here to ensure the compiler doesn't try
+		 * to get cute.
+		 */
+		volatile PgBackendStatus *vbeentry = beentry;
+		bool		found;
+		uint64		allocated_bytes = 0;
+
+		for (;;)
+		{
+			int			before_changecount;
+			int			after_changecount;
+
+			pgstat_begin_read_activity(vbeentry, before_changecount);
+
+			/*
+			 * Ignore invalid entries, which may contain invalid data.
+			 * See pgstat_beshutdown_hook()
+			 */
+			if (vbeentry->st_procpid > 0)
+				allocated_bytes = vbeentry->allocated_bytes;
+
+			pgstat_end_read_activity(vbeentry, after_changecount);
+
+			if ((found = pgstat_read_activity_complete(before_changecount,
+													   after_changecount)))
+				break;
+
+			/* Make sure we can break out of loop if stuck... */
+			CHECK_FOR_INTERRUPTS();
+		}
+
+		if (found)
+			all_memory_allocated += allocated_bytes;
+
+		beentry++;
+	}
+
+	return all_memory_allocated;
+}
+
+/*
+ * Determine if allocation request will exceed max backend memory allowed.
+ * Do not apply to auxiliary processes.
+ */
+bool
+exceeds_max_total_bkend_mem(uint64 allocation_request)
+{
+	bool		result = false;
+
+	/* Exclude auxiliary processes from the check */
+	if (MyAuxProcType != NotAnAuxProcess)
+		return result;
+
+	/* Convert max_total_bkend_mem to bytes for comparison */
+	if (max_total_bkend_mem &&
+		pgstat_get_all_backend_memory_allocated() +
+		allocation_request > (uint64) max_total_bkend_mem * 1024 * 1024)
+	{
+		/*
+		 * Explicitly identify the OOM being a result of this configuration
+		 * parameter vs a system failure to allocate OOM.
+		 */
+		ereport(WARNING,
+				errmsg("allocation would exceed max_total_memory limit (%llu > %llu)",
+					   (unsigned long long) pgstat_get_all_backend_memory_allocated() +
+					   allocation_request, (unsigned long long) max_total_bkend_mem * 1024 * 1024));
+
+		result = true;
+	}

I think it's completely unfeasible to execute something as expensive as
pgstat_get_all_backend_memory_allocated() on every allocation. Like,
seriously, no.

And we absolutely definitely shouldn't just add CHECK_FOR_INTERRUPT() calls
into the middle of allocator code.

Greetings,

Andres Freund

#23Reid Thompson
reid.thompson@crunchydata.com
In reply to: Andres Freund (#22)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On Mon, 2023-01-09 at 18:31 -0800, Andres Freund wrote:

Hi,

On 2023-01-05 13:44:20 -0500, Reid Thompson wrote:

This new field displays the current bytes of memory allocated to the
backend process. It is updated as memory for the process is
malloc'd/free'd. Memory allocated to items on the freelist is included in
the displayed value.

It doesn't actually malloc/free. It tracks palloc/pfree.

I will update the message

Dynamic shared memory allocations are included only in the value displayed
for the backend that created them, they are not included in the value for
backends that are attached to them to avoid double counting.

As mentioned before, I don't think accounting DSM this way makes sense.

Understood, previously you noted 'There are a few uses of DSMs that track
shared resources, with the biggest likely being the stats for relations
etc'. I'd like to come up with a solution to address this; identifying the
long term allocations to shared state and accounting for them such that they
don't get 'lost' when the allocating backend exits. Any guidance or
direction would be appreciated.

--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -407,6 +407,9 @@ StartAutoVacLauncher(void)
#ifndef EXEC_BACKEND
case 0:
+			/* Zero allocated bytes to avoid double counting parent allocation */
+			pgstat_zero_my_allocated_bytes();
+
/* in postmaster child ... */
InitPostmasterChild();

@@ -1485,6 +1488,9 @@ StartAutoVacWorker(void)

#ifndef EXEC_BACKEND
case 0:
+			/* Zero allocated bytes to avoid double counting parent allocation */
+			pgstat_zero_my_allocated_bytes();
+
/* in postmaster child ... */
InitPostmasterChild();
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index eac3450774..24278e5c18 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -4102,6 +4102,9 @@ BackendStartup(Port *port)
{
free(bn);
+		/* Zero allocated bytes to avoid double counting parent allocation */
+		pgstat_zero_my_allocated_bytes();
+
/* Detangle from postmaster */
InitPostmasterChild();

It doesn't at all seem right to call pgstat_zero_my_allocated_bytes() here,
before even InitPostmasterChild() is called. Nor does it seem right to add the
call to so many places.

Note that this is before we even delete postmaster's memory, see e.g.:
/*
* If the PostmasterContext is still around, recycle the space; we don't
* need it anymore after InitPostgres completes. Note this does not trash
* *MyProcPort, because ConnCreate() allocated that space with malloc()
* ... else we'd need to copy the Port data first. Also, subsidiary data
* such as the username isn't lost either; see ProcessStartupPacket().
*/
if (PostmasterContext)
{
MemoryContextDelete(PostmasterContext);
PostmasterContext = NULL;
}

calling pgstat_zero_my_allocated_bytes() before we do this will lead to
undercounting memory usage, afaict.

OK - I'll trace back through these and see if I can better locate and reduce the
number of invocations.

+/* Enum helper for reporting memory allocated bytes */
+enum allocation_direction
+{
+	PG_ALLOC_DECREASE = -1,
+	PG_ALLOC_IGNORE,
+	PG_ALLOC_INCREASE,
+};

What's the point of this?

+/* ----------
+ * pgstat_report_allocated_bytes() -
+ *
+ *  Called to report change in memory allocated for this backend.
+ *
+ * my_allocated_bytes initially points to local memory, making it safe to call
+ * this before pgstats has been initialized. allocation_direction is a
+ * positive/negative multiplier enum defined above.
+ * ----------
+ */
+static inline void
+pgstat_report_allocated_bytes(int64 allocated_bytes, int allocation_direction)

I don't think this should take allocation_direction as a parameter, I'd make
it two different functions.

Originally it was two functions, a suggestion was made in the thread to
maybe consolidate them to a single function with a direction indicator,
hence the above. I'm fine with converting it back to separate functions.

+	if (allocation_direction == PG_ALLOC_DECREASE &&
+		pg_sub_u64_overflow(*my_allocated_bytes, allocated_bytes, &temp))
+	{
+		*my_allocated_bytes = 0;
+		ereport(LOG,
+				errmsg("Backend %d deallocated %lld bytes, exceeding the %llu bytes it is currently reporting allocated. Setting reported to 0.",
+					   MyProcPid, (long long) allocated_bytes,
+					   (unsigned long long) *my_allocated_bytes));

We certainly shouldn't have an ereport in here. This stuff really needs to be
cheap.

I will remove the ereport.

+ *my_allocated_bytes += (allocated_bytes) * allocation_direction;

Superfluous parens?

I will remove these.

+/* ----------
+ * pgstat_get_all_memory_allocated() -
+ *
+ *	Return a uint64 representing the current shared memory allocated to all
+ *	backends.  This looks directly at the BackendStatusArray, and so will
+ *	provide current information regardless of the age of our transaction's
+ *	snapshot of the status array.
+ *	In the future we will likely utilize additional values - perhaps limit
+ *	backend allocation by user/role, etc.
+ * ----------

I think it's completely unfeasible to execute something as expensive as
pgstat_get_all_backend_memory_allocated() on every allocation. Like,
seriously, no.

Ok. Do we check every nth allocation/try to implement a scheme of checking
more often as we we get closer to the declared max_total_bkend_mem?

And we absolutely definitely shouldn't just add CHECK_FOR_INTERRUPT() calls
into the middle of allocator code.

I'm open to guidance/suggestions/pointers to remedying these.

Greetings,

Andres Freund

Thanks,
Reid

#24Andres Freund
andres@anarazel.de
In reply to: Reid Thompson (#23)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

Hi,

On 2023-01-13 09:15:10 -0500, Reid Thompson wrote:

On Mon, 2023-01-09 at 18:31 -0800, Andres Freund wrote:

Dynamic shared memory allocations are included only in the value displayed
for the backend that created them, they are not included in the value for
backends that are attached to them to avoid double counting.

As mentioned before, I don't think accounting DSM this way makes sense.

Understood, previously you noted 'There are a few uses of DSMs that track
shared resources, with the biggest likely being the stats for relations
etc'. I'd like to come up with a solution to address this; identifying the
long term allocations to shared state and accounting for them such that they
don't get 'lost' when the allocating backend exits. Any guidance or
direction would be appreciated.

Tracking it as backend memory usage doesn't seem helpful to me, particularly
because some of it is for server wide data tracking (pgstats, some
caches). But that doesn't mean you couldn't track and report it
separately.

+/* ----------
+ * pgstat_get_all_memory_allocated() -
+ *
+ *	Return a uint64 representing the current shared memory allocated to all
+ *	backends.  This looks directly at the BackendStatusArray, and so will
+ *	provide current information regardless of the age of our transaction's
+ *	snapshot of the status array.
+ *	In the future we will likely utilize additional values - perhaps limit
+ *	backend allocation by user/role, etc.
+ * ----------

I think it's completely unfeasible to execute something as expensive as
pgstat_get_all_backend_memory_allocated() on every allocation. Like,
seriously, no.

Ok. Do we check every nth allocation/try to implement a scheme of checking
more often as we we get closer to the declared max_total_bkend_mem?

I think it's just not acceptable to do O(connections) work as part of
something critical as memory allocation. Even if amortized imo.

What you could do is to have a single, imprecise, shared counter for the total
memory allocation, and have a backend-local "allowance". When the allowance is
used up, refill it from the shared counter (a single atomic op).

But honestly, I think we first need to have the accounting for a while before
it makes sense to go for the memory limiting patch. And I doubt a single GUC
will suffice to make this usable.

And we absolutely definitely shouldn't just add CHECK_FOR_INTERRUPT() calls
into the middle of allocator code.

I'm open to guidance/suggestions/pointers to remedying these.

Well, just don't have the CHECK_FOR_INTERRUPT(). Nor the O(N) operation.

You also can't do the ereport(WARNING) there, that itself allocates memory,
and could lead to recursion in some edge cases.

Greetings,

Andres Freund

#25vignesh C
vignesh21@gmail.com
In reply to: Reid Thompson (#21)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On Fri, 6 Jan 2023 at 00:19, Reid Thompson
<reid.thompson@crunchydata.com> wrote:

On Tue, 2023-01-03 at 16:22 +0530, vignesh C wrote:

....
The patch does not apply on top of HEAD as in [1], please post a
rebased patch:
...
Regards,
Vignesh

Attached is rebased patch, with some updates related to committed changes.

The patch does not apply on top of HEAD as in [1]http://cfbot.cputube.org/patch_41_3867.log, please post a rebased patch:
=== Applying patches on top of PostgreSQL commit ID
48880840f18cb75fcaecc77b5e7816b92c27157b ===
=== applying patch
./0001-Add-tracking-of-backend-memory-allocated-to-pg_stat_.patch
....
patching file src/test/regress/expected/rules.out
Hunk #2 FAILED at 1875.
Hunk #4 FAILED at 2090.
2 out of 4 hunks FAILED -- saving rejects to file
src/test/regress/expected/rules.out.rej

[1]: http://cfbot.cputube.org/patch_41_3867.log

Regards,
Vignesh

#26Reid Thompson
reid.thompson@crunchydata.com
In reply to: vignesh C (#25)
2 attachment(s)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On Thu, 2023-01-19 at 16:50 +0530, vignesh C wrote:

The patch does not apply on top of HEAD as in [1], please post a rebased patch:

Regards,
Vignesh

rebased patch attached

Thanks,
Reid

Attachments:

0002-Add-the-ability-to-limit-the-amount-of-memory-that-c.patchtext/x-patch; charset=UTF-8; name=0002-Add-the-ability-to-limit-the-amount-of-memory-that-c.patchDownload
From b32a346d6e0e00c568e9a285ad15fc2703998c26 Mon Sep 17 00:00:00 2001
From: Reid Thompson <jreidthompson@nc.rr.com>
Date: Sat, 4 Jun 2022 22:23:59 -0400
Subject: [PATCH 2/2] Add the ability to limit the amount of memory that can be
 allocated to backends.

This builds on the work that adds backend memory allocated to pg_stat_activity.

Add GUC variable max_total_backend_memory.

Specifies a limit to the amount of memory (in MB) that may be allocated to
backends in total (i.e. this is not a per user or per backend limit). If unset,
or set to 0 it is disabled. It is intended as a resource to help avoid the OOM
killer on LINUX and manage resources in general. A backend request that would
push the total over the limit will be denied with an out of memory error causing
that backend's current query/transaction to fail. Due to the dynamic nature of
memory allocations, this limit is not exact. If within 1.5MB of the limit and
two backends request 1MB each at the same time both may be allocated, and exceed
the limit. Further requests will not be allocated until dropping below the
limit. Keep this in mind when setting this value. This limit does not affect
auxiliary backend processes. Backend memory allocations are displayed in the
pg_stat_activity view.
---
 doc/src/sgml/config.sgml                      |  26 +++++
 src/backend/storage/ipc/dsm_impl.c            |  12 ++
 src/backend/utils/activity/backend_status.c   | 108 ++++++++++++++++++
 src/backend/utils/misc/guc_tables.c           |  11 ++
 src/backend/utils/misc/postgresql.conf.sample |   3 +
 src/backend/utils/mmgr/aset.c                 |  17 +++
 src/backend/utils/mmgr/generation.c           |   9 ++
 src/backend/utils/mmgr/slab.c                 |   9 +-
 src/include/utils/backend_status.h            |   3 +
 9 files changed, 197 insertions(+), 1 deletion(-)

diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index f985afc009..51ed4623be 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -2113,6 +2113,32 @@ include_dir 'conf.d'
       </listitem>
      </varlistentry>
 
+     <varlistentry id="guc-max-total-backend-memory" xreflabel="max_total_backend_memory">
+      <term><varname>max_total_backend_memory</varname> (<type>integer</type>)
+      <indexterm>
+       <primary><varname>max_total_backend_memory</varname> configuration parameter</primary>
+      </indexterm>
+      </term>
+      <listitem>
+       <para>
+        Specifies a limit to the amount of memory (MB) that may be allocated to
+        backends in total (i.e. this is not a per user or per backend limit).
+        If unset, or set to 0 it is disabled.  A backend request that would
+        push the total over the limit will be denied with an out of memory
+        error causing that backend's current query/transaction to fail. Due to
+        the dynamic nature of memory allocations, this limit is not exact. If
+        within 1.5MB of the limit and two backends request 1MB each at the same
+        time both may be allocated, and exceed the limit. Further requests will
+        not be allocated until dropping below the limit. Keep this in mind when
+        setting this value. This limit does not affect auxiliary backend
+        processes <xref linkend="glossary-auxiliary-proc"/> . Backend memory
+        allocations (<varname>allocated_bytes</varname>) are displayed in the
+        <link linkend="monitoring-pg-stat-activity-view"><structname>pg_stat_activity</structname></link>
+        view.
+       </para>
+      </listitem>
+     </varlistentry>
+
      </variablelist>
      </sect2>
 
diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c
index 22885c7bd2..f7047107d5 100644
--- a/src/backend/storage/ipc/dsm_impl.c
+++ b/src/backend/storage/ipc/dsm_impl.c
@@ -254,6 +254,10 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 		return true;
 	}
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+		return false;
+
 	/*
 	 * Create new segment or open an existing one for attach.
 	 *
@@ -525,6 +529,10 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 		int			flags = IPCProtection;
 		size_t		segsize;
 
+		/* Do not exceed maximum allowed memory allocation */
+		if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+			return false;
+
 		/*
 		 * Allocate the memory BEFORE acquiring the resource, so that we don't
 		 * leak the resource if memory allocation fails.
@@ -719,6 +727,10 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 		return true;
 	}
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+		return false;
+
 	/* Create new segment or open an existing one for attach. */
 	if (op == DSM_OP_CREATE)
 	{
diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c
index 7baf2db57d..da2b5fb042 100644
--- a/src/backend/utils/activity/backend_status.c
+++ b/src/backend/utils/activity/backend_status.c
@@ -45,6 +45,9 @@
 bool		pgstat_track_activities = false;
 int			pgstat_track_activity_query_size = 1024;
 
+/* Max backend memory allocation allowed (MB). 0 = disabled */
+int			max_total_bkend_mem = 0;
+
 
 /* exposed so that backend_progress.c can access it */
 PgBackendStatus *MyBEEntry = NULL;
@@ -1239,3 +1242,108 @@ pgstat_reset_allocated_bytes_storage(void)
 	my_allocated_bytes = &local_my_allocated_bytes;
 }
 
+/* ----------
+ * pgstat_get_all_memory_allocated() -
+ *
+ *	Return a uint64 representing the current shared memory allocated to all
+ *	backends.  This looks directly at the BackendStatusArray, and so will
+ *	provide current information regardless of the age of our transaction's
+ *	snapshot of the status array.
+ *	In the future we will likely utilize additional values - perhaps limit
+ *	backend allocation by user/role, etc.
+ * ----------
+ */
+uint64
+pgstat_get_all_backend_memory_allocated(void)
+{
+	PgBackendStatus *beentry;
+	int			i;
+	uint64		all_memory_allocated = 0;
+
+	beentry = BackendStatusArray;
+
+	/*
+	 * We probably shouldn't get here before shared memory has been set up,
+	 * but be safe.
+	 */
+	if (beentry == NULL || BackendActivityBuffer == NULL)
+		return 0;
+
+	/*
+	 * We include AUX procs in all backend memory calculation
+	 */
+	for (i = 1; i <= NumBackendStatSlots; i++)
+	{
+		/*
+		 * We use a volatile pointer here to ensure the compiler doesn't try
+		 * to get cute.
+		 */
+		volatile PgBackendStatus *vbeentry = beentry;
+		bool		found;
+		uint64		allocated_bytes = 0;
+
+		for (;;)
+		{
+			int			before_changecount;
+			int			after_changecount;
+
+			pgstat_begin_read_activity(vbeentry, before_changecount);
+
+			/*
+			 * Ignore invalid entries, which may contain invalid data.
+			 * See pgstat_beshutdown_hook()
+			 */
+			if (vbeentry->st_procpid > 0)
+				allocated_bytes = vbeentry->allocated_bytes;
+
+			pgstat_end_read_activity(vbeentry, after_changecount);
+
+			if ((found = pgstat_read_activity_complete(before_changecount,
+													   after_changecount)))
+				break;
+
+			/* Make sure we can break out of loop if stuck... */
+			CHECK_FOR_INTERRUPTS();
+		}
+
+		if (found)
+			all_memory_allocated += allocated_bytes;
+
+		beentry++;
+	}
+
+	return all_memory_allocated;
+}
+
+/*
+ * Determine if allocation request will exceed max backend memory allowed.
+ * Do not apply to auxiliary processes.
+ */
+bool
+exceeds_max_total_bkend_mem(uint64 allocation_request)
+{
+	bool		result = false;
+
+	/* Exclude auxiliary processes from the check */
+	if (MyAuxProcType != NotAnAuxProcess)
+		return result;
+
+	/* Convert max_total_bkend_mem to bytes for comparison */
+	if (max_total_bkend_mem &&
+		pgstat_get_all_backend_memory_allocated() +
+		allocation_request > (uint64) max_total_bkend_mem * 1024 * 1024)
+	{
+		/*
+		 * Explicitly identify the OOM being a result of this configuration
+		 * parameter vs a system failure to allocate OOM.
+		 */
+		ereport(WARNING,
+				errmsg("allocation would exceed max_total_memory limit (%llu > %llu)",
+					   (unsigned long long) pgstat_get_all_backend_memory_allocated() +
+					   allocation_request, (unsigned long long) max_total_bkend_mem * 1024 * 1024));
+
+		result = true;
+	}
+
+	return result;
+}
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index 4ac808ed22..d6f3b4e262 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -3467,6 +3467,17 @@ struct config_int ConfigureNamesInt[] =
 		NULL, NULL, NULL
 	},
 
+	{
+		{"max_total_backend_memory", PGC_SU_BACKEND, RESOURCES_MEM,
+			gettext_noop("Restrict total backend memory allocations to this max."),
+			gettext_noop("0 turns this feature off."),
+			GUC_UNIT_MB
+		},
+		&max_total_bkend_mem,
+		0, 0, INT_MAX,
+		NULL, NULL, NULL
+	},
+
 	/* End-of-list marker */
 	{
 		{NULL, 0, 0, NULL, NULL}, NULL, 0, 0, 0, NULL, NULL, NULL
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index d06074b86f..bc2d449c87 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -156,6 +156,9 @@
 					#   mmap
 					# (change requires restart)
 #min_dynamic_shared_memory = 0MB	# (change requires restart)
+#max_total_backend_memory = 0MB		# Restrict total backend memory allocations
+									# to this max (in MB). 0 turns this feature
+									# off.
 
 # - Disk -
 
diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index 37e82bcd70..7e50971f58 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -440,6 +440,10 @@ AllocSetContextCreateInternal(MemoryContext parent,
 	else
 		firstBlockSize = Max(firstBlockSize, initBlockSize);
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (exceeds_max_total_bkend_mem(firstBlockSize))
+		return NULL;
+
 	/*
 	 * Allocate the initial block.  Unlike other aset.c blocks, it starts with
 	 * the context header and its block header follows that.
@@ -741,6 +745,11 @@ AllocSetAlloc(MemoryContext context, Size size)
 #endif
 
 		blksize = chunk_size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
+
+		/* Do not exceed maximum allowed memory allocation */
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		block = (AllocBlock) malloc(blksize);
 		if (block == NULL)
 			return NULL;
@@ -938,6 +947,10 @@ AllocSetAlloc(MemoryContext context, Size size)
 		while (blksize < required_size)
 			blksize <<= 1;
 
+		/* Do not exceed maximum allowed memory allocation */
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		/* Try to allocate it */
 		block = (AllocBlock) malloc(blksize);
 
@@ -1176,6 +1189,10 @@ AllocSetRealloc(void *pointer, Size size)
 		blksize = chksize + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
 		oldblksize = block->endptr - ((char *) block);
 
+		/* Do not exceed maximum allowed memory allocation */
+		if (blksize > oldblksize && exceeds_max_total_bkend_mem(blksize - oldblksize))
+			return NULL;
+
 		block = (AllocBlock) realloc(block, blksize);
 		if (block == NULL)
 		{
diff --git a/src/backend/utils/mmgr/generation.c b/src/backend/utils/mmgr/generation.c
index b06fb0c6a4..18d43d52bd 100644
--- a/src/backend/utils/mmgr/generation.c
+++ b/src/backend/utils/mmgr/generation.c
@@ -201,6 +201,9 @@ GenerationContextCreate(MemoryContext parent,
 	else
 		allocSize = Max(allocSize, initBlockSize);
 
+	if (exceeds_max_total_bkend_mem(allocSize))
+		return NULL;
+
 	/*
 	 * Allocate the initial block.  Unlike other generation.c blocks, it
 	 * starts with the context header and its block header follows that.
@@ -380,6 +383,9 @@ GenerationAlloc(MemoryContext context, Size size)
 	{
 		Size		blksize = required_size + Generation_BLOCKHDRSZ;
 
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		block = (GenerationBlock *) malloc(blksize);
 		if (block == NULL)
 			return NULL;
@@ -483,6 +489,9 @@ GenerationAlloc(MemoryContext context, Size size)
 			if (blksize < required_size)
 				blksize = pg_nextpower2_size_t(required_size);
 
+			if (exceeds_max_total_bkend_mem(blksize))
+				return NULL;
+
 			block = (GenerationBlock *) malloc(blksize);
 
 			if (block == NULL)
diff --git a/src/backend/utils/mmgr/slab.c b/src/backend/utils/mmgr/slab.c
index e314f8f343..adc88e0047 100644
--- a/src/backend/utils/mmgr/slab.c
+++ b/src/backend/utils/mmgr/slab.c
@@ -356,9 +356,12 @@ SlabContextCreate(MemoryContext parent,
 		elog(ERROR, "block size %zu for slab is too small for %zu-byte chunks",
 			 blockSize, chunkSize);
 
-
+	/* Do not exceed maximum allowed memory allocation */
+	if (exceeds_max_total_bkend_mem(Slab_CONTEXT_HDRSZ(chunksPerBlock)))
+		return NULL;
 
 	slab = (SlabContext *) malloc(Slab_CONTEXT_HDRSZ(chunksPerBlock));
+
 	if (slab == NULL)
 	{
 		MemoryContextStats(TopMemoryContext);
@@ -559,6 +562,10 @@ SlabAlloc(MemoryContext context, Size size)
 		}
 		else
 		{
+			/* Do not exceed maximum allowed memory allocation */
+			if (exceeds_max_total_bkend_mem(slab->blockSize))
+				return NULL;
+
 			block = (SlabBlock *) malloc(slab->blockSize);
 
 			if (unlikely(block == NULL))
diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h
index 754ff0dc62..33269eb11b 100644
--- a/src/include/utils/backend_status.h
+++ b/src/include/utils/backend_status.h
@@ -297,6 +297,7 @@ typedef struct LocalPgBackendStatus
  */
 extern PGDLLIMPORT bool pgstat_track_activities;
 extern PGDLLIMPORT int pgstat_track_activity_query_size;
+extern PGDLLIMPORT int max_total_bkend_mem;
 
 
 /* ----------
@@ -336,6 +337,7 @@ extern const char *pgstat_get_backend_current_activity(int pid, bool checkUser);
 extern const char *pgstat_get_crashed_backend_activity(int pid, char *buffer,
 													   int buflen);
 extern uint64 pgstat_get_my_query_id(void);
+extern uint64 pgstat_get_all_backend_memory_allocated(void);
 extern void pgstat_set_allocated_bytes_storage(uint64 *allocated_bytes);
 extern void pgstat_reset_allocated_bytes_storage(void);
 
@@ -348,6 +350,7 @@ extern int	pgstat_fetch_stat_numbackends(void);
 extern PgBackendStatus *pgstat_fetch_stat_beentry(BackendId beid);
 extern LocalPgBackendStatus *pgstat_fetch_stat_local_beentry(int beid);
 extern char *pgstat_clip_activity(const char *raw_activity);
+extern bool exceeds_max_total_bkend_mem(uint64 allocation_request);
 
 /* ----------
  * pgstat_report_allocated_bytes() -
-- 
2.25.1

0001-Add-tracking-of-backend-memory-allocated-to-pg_stat_.patchtext/x-patch; charset=UTF-8; name=0001-Add-tracking-of-backend-memory-allocated-to-pg_stat_.patchDownload
From fe8ea9bc008df25f439048d6c653de8439ce5baa Mon Sep 17 00:00:00 2001
From: Reid Thompson <jreidthompson@nc.rr.com>
Date: Thu, 11 Aug 2022 12:01:25 -0400
Subject: [PATCH 1/2] Add tracking of backend memory allocated to
 pg_stat_activity

This new field displays the current bytes of memory allocated to the
backend process. It is updated as memory for the process is
palloc'd/pfree'd. Memory allocated to items on the freelist is included in
the displayed value.  Dynamic shared memory allocations are included
only in the value displayed for the backend that created them, they are
not included in the value for backends that are attached to them to
avoid double counting. On occasion, orphaned memory segments may be
cleaned up on postmaster startup. This may result in decreasing the sum
without a prior increment. We limit the floor of backend_mem_allocated
to zero. Updated pg_stat_activity documentation for the new column.
---
 doc/src/sgml/monitoring.sgml                | 15 ++++
 src/backend/catalog/system_views.sql        |  1 +
 src/backend/postmaster/autovacuum.c         |  6 ++
 src/backend/postmaster/postmaster.c         | 13 ++++
 src/backend/postmaster/syslogger.c          |  3 +
 src/backend/storage/ipc/dsm_impl.c          | 81 +++++++++++++++++++++
 src/backend/utils/activity/backend_status.c | 45 ++++++++++++
 src/backend/utils/adt/pgstatfuncs.c         |  4 +-
 src/backend/utils/mmgr/aset.c               | 17 +++++
 src/backend/utils/mmgr/generation.c         | 15 ++++
 src/backend/utils/mmgr/slab.c               | 22 ++++++
 src/include/catalog/pg_proc.dat             |  6 +-
 src/include/utils/backend_status.h          | 63 +++++++++++++++-
 src/test/regress/expected/rules.out         |  9 ++-
 src/test/regress/expected/stats.out         | 11 +++
 src/test/regress/sql/stats.sql              |  3 +
 16 files changed, 305 insertions(+), 9 deletions(-)

diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 1756f1a4b6..844d9019dd 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -957,6 +957,21 @@ postgres   27093  0.0  0.0  30096  2752 ?        Ss   11:34   0:00 postgres: ser
      </para></entry>
     </row>
 
+    <row>
+     <entry role="catalog_table_entry"><para role="column_definition">
+      <structfield>allocated_bytes</structfield> <type>bigint</type>
+     </para>
+     <para>
+      Memory currently allocated to this backend in bytes. This is the balance
+      of bytes allocated and freed by this backend. Dynamic shared memory
+      allocations are included only in the value displayed for the backend that
+      created them, they are not included in the value for backends that are
+      attached to them to avoid double counting. Use <function>pg_size_pretty</function>
+      described in <xref linkend="functions-admin-dbsize"/> to make this value
+      more easily readable.
+     </para></entry>
+    </row>
+
      <row>
       <entry role="catalog_table_entry"><para role="column_definition">
        <structfield>query</structfield> <type>text</type>
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 8608e3fa5b..aacd269b01 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -863,6 +863,7 @@ CREATE VIEW pg_stat_activity AS
             S.state,
             S.backend_xid,
             s.backend_xmin,
+            S.allocated_bytes,
             S.query_id,
             S.query,
             S.backend_type
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f5ea381c53..09f5624ade 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -407,6 +407,9 @@ StartAutoVacLauncher(void)
 
 #ifndef EXEC_BACKEND
 		case 0:
+			/* Zero allocated bytes to avoid double counting parent allocation */
+			pgstat_zero_my_allocated_bytes();
+
 			/* in postmaster child ... */
 			InitPostmasterChild();
 
@@ -1485,6 +1488,9 @@ StartAutoVacWorker(void)
 
 #ifndef EXEC_BACKEND
 		case 0:
+			/* Zero allocated bytes to avoid double counting parent allocation */
+			pgstat_zero_my_allocated_bytes();
+
 			/* in postmaster child ... */
 			InitPostmasterChild();
 
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 711efc35e3..226d6c0a6f 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -4161,6 +4161,9 @@ BackendStartup(Port *port)
 	{
 		free(bn);
 
+		/* Zero allocated bytes to avoid double counting parent allocation */
+		pgstat_zero_my_allocated_bytes();
+
 		/* Detangle from postmaster */
 		InitPostmasterChild();
 
@@ -5368,6 +5371,11 @@ StartChildProcess(AuxProcType type)
 		MemoryContextDelete(PostmasterContext);
 		PostmasterContext = NULL;
 
+		/* Zero allocated bytes to avoid double counting parent allocation.
+		 * Needs to be after the MemoryContextDelete(PostmasterContext) above.
+		 */
+		pgstat_zero_my_allocated_bytes();
+
 		AuxiliaryProcessMain(type); /* does not return */
 	}
 #endif							/* EXEC_BACKEND */
@@ -5761,6 +5769,11 @@ do_start_bgworker(RegisteredBgWorker *rw)
 			MemoryContextDelete(PostmasterContext);
 			PostmasterContext = NULL;
 
+			/* Zero allocated bytes to avoid double counting parent allocation.
+			 * Needs to be after the MemoryContextDelete(PostmasterContext) above.
+			 */
+			pgstat_zero_my_allocated_bytes();
+
 			StartBackgroundWorker();
 
 			exit(1);			/* should not get here */
diff --git a/src/backend/postmaster/syslogger.c b/src/backend/postmaster/syslogger.c
index a876d02c6f..0d51af6fd8 100644
--- a/src/backend/postmaster/syslogger.c
+++ b/src/backend/postmaster/syslogger.c
@@ -679,6 +679,9 @@ SysLogger_Start(void)
 
 #ifndef EXEC_BACKEND
 		case 0:
+			/* Zero allocated bytes to avoid double counting parent allocation */
+			pgstat_zero_my_allocated_bytes();
+
 			/* in postmaster child ... */
 			InitPostmasterChild();
 
diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c
index f0965c3481..22885c7bd2 100644
--- a/src/backend/storage/ipc/dsm_impl.c
+++ b/src/backend/storage/ipc/dsm_impl.c
@@ -66,6 +66,7 @@
 #include "postmaster/postmaster.h"
 #include "storage/dsm_impl.h"
 #include "storage/fd.h"
+#include "utils/backend_status.h"
 #include "utils/guc.h"
 #include "utils/memutils.h"
 
@@ -232,6 +233,14 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_allocated_bytes(*mapped_size, PG_ALLOC_DECREASE);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && shm_unlink(name) != 0)
@@ -332,6 +341,36 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+	{
+		/*
+		 * Posix creation calls dsm_impl_posix_resize implying that resizing
+		 * occurs or may be added in the future. As implemented
+		 * dsm_impl_posix_resize utilizes fallocate or truncate, passing the
+		 * whole new size as input, growing the allocation as needed (only
+		 * truncate supports shrinking). We update by replacing the old
+		 * allocation with the new.
+		 */
+#if defined(HAVE_POSIX_FALLOCATE) && defined(__linux__)
+		/*
+		 * posix_fallocate does not shrink allocations, adjust only on
+		 * allocation increase.
+		 */
+		if (request_size > *mapped_size)
+		{
+			pgstat_report_allocated_bytes(request_size - *mapped_size,
+										  PG_ALLOC_INCREASE);
+		}
+#else
+		pgstat_report_allocated_bytes(*mapped_size, PG_ALLOC_DECREASE);
+		pgstat_report_allocated_bytes(request_size, PG_ALLOC_INCREASE);
+#endif
+	}
 	*mapped_address = address;
 	*mapped_size = request_size;
 	close(fd);
@@ -537,6 +576,14 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_allocated_bytes(*mapped_size, PG_ALLOC_DECREASE);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && shmctl(ident, IPC_RMID, NULL) < 0)
@@ -584,6 +631,13 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_allocated_bytes(request_size, PG_ALLOC_INCREASE);
 	*mapped_address = address;
 	*mapped_size = request_size;
 
@@ -652,6 +706,13 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 			return false;
 		}
 
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_allocated_bytes(*mapped_size, PG_ALLOC_DECREASE);
 		*impl_private = NULL;
 		*mapped_address = NULL;
 		*mapped_size = 0;
@@ -768,6 +829,12 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 		return false;
 	}
 
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_allocated_bytes(info.RegionSize, PG_ALLOC_INCREASE);
 	*mapped_address = address;
 	*mapped_size = info.RegionSize;
 	*impl_private = hmap;
@@ -812,6 +879,13 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		pgstat_report_allocated_bytes(*mapped_size, PG_ALLOC_DECREASE);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && unlink(name) != 0)
@@ -933,6 +1007,13 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_allocated_bytes(request_size, PG_ALLOC_INCREASE);
 	*mapped_address = address;
 	*mapped_size = request_size;
 
diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c
index 608d01ea0d..7baf2db57d 100644
--- a/src/backend/utils/activity/backend_status.c
+++ b/src/backend/utils/activity/backend_status.c
@@ -49,6 +49,9 @@ int			pgstat_track_activity_query_size = 1024;
 /* exposed so that backend_progress.c can access it */
 PgBackendStatus *MyBEEntry = NULL;
 
+/* Memory allocated to this backend prior to pgstats initialization */
+uint64	local_my_allocated_bytes = 0;
+uint64	*my_allocated_bytes = &local_my_allocated_bytes;
 
 static PgBackendStatus *BackendStatusArray = NULL;
 static char *BackendAppnameBuffer = NULL;
@@ -400,6 +403,15 @@ pgstat_bestart(void)
 	lbeentry.st_progress_command_target = InvalidOid;
 	lbeentry.st_query_id = UINT64CONST(0);
 
+	/* Alter allocation reporting from local_my_allocated_bytes to shared memory */
+	pgstat_set_allocated_bytes_storage(&MyBEEntry->allocated_bytes);
+
+	/* Populate sum of memory allocated prior to pgstats initialization to pgstats
+	 * and zero the local variable.
+	 */
+	lbeentry.allocated_bytes += local_my_allocated_bytes;
+	local_my_allocated_bytes = 0;
+
 	/*
 	 * we don't zero st_progress_param here to save cycles; nobody should
 	 * examine it until st_progress_command has been set to something other
@@ -459,6 +471,11 @@ pgstat_beshutdown_hook(int code, Datum arg)
 {
 	volatile PgBackendStatus *beentry = MyBEEntry;
 
+	/*
+	 * Stop reporting memory allocation changes to &MyBEEntry->allocated_bytes
+	 */
+	pgstat_reset_allocated_bytes_storage();
+
 	/*
 	 * Clear my status entry, following the protocol of bumping st_changecount
 	 * before and after.  We use a volatile pointer here to ensure the
@@ -1194,3 +1211,31 @@ pgstat_clip_activity(const char *raw_activity)
 
 	return activity;
 }
+
+/*
+ * Configure bytes allocated reporting to report allocated bytes to
+ * *allocated_bytes.  *allocated_bytes needs to be valid until
+ * pgstat_set_allocated_bytes_storage() is called.
+ *
+ * Expected to be called during backend startup (in pgstat_bestart), to point
+ * my_allocated_bytes into shared memory.
+ */
+void
+pgstat_set_allocated_bytes_storage(uint64 *new_allocated_bytes)
+{
+	my_allocated_bytes = new_allocated_bytes;
+	*new_allocated_bytes = local_my_allocated_bytes;
+}
+
+/*
+ * Reset allocated bytes storage location.
+ *
+ * Expected to be called during backend shutdown, before the location set up
+ * by pgstat_set_allocated_bytes_storage() becomes invalid.
+ */
+void
+pgstat_reset_allocated_bytes_storage(void)
+{
+	my_allocated_bytes = &local_my_allocated_bytes;
+}
+
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 6737493402..f4f2c8dce1 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -303,7 +303,7 @@ pg_stat_get_progress_info(PG_FUNCTION_ARGS)
 Datum
 pg_stat_get_activity(PG_FUNCTION_ARGS)
 {
-#define PG_STAT_GET_ACTIVITY_COLS	30
+#define PG_STAT_GET_ACTIVITY_COLS	31
 	int			num_backends = pgstat_fetch_stat_numbackends();
 	int			curr_backend;
 	int			pid = PG_ARGISNULL(0) ? -1 : PG_GETARG_INT32(0);
@@ -359,6 +359,8 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
 		else
 			nulls[16] = true;
 
+		values[30] = UInt64GetDatum(beentry->allocated_bytes);
+
 		/* Values only available to role member or pg_read_all_stats */
 		if (HAS_PGSTAT_PERMISSIONS(beentry->st_userid))
 		{
diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index 740729b5d0..37e82bcd70 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -47,6 +47,7 @@
 #include "postgres.h"
 
 #include "port/pg_bitutils.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -521,6 +522,7 @@ AllocSetContextCreateInternal(MemoryContext parent,
 						name);
 
 	((MemoryContext) set)->mem_allocated = firstBlockSize;
+	pgstat_report_allocated_bytes(firstBlockSize, PG_ALLOC_INCREASE);
 
 	return (MemoryContext) set;
 }
@@ -543,6 +545,7 @@ AllocSetReset(MemoryContext context)
 	AllocSet	set = (AllocSet) context;
 	AllocBlock	block;
 	Size		keepersize PG_USED_FOR_ASSERTS_ONLY;
+	uint64		deallocation = 0;
 
 	Assert(AllocSetIsValid(set));
 
@@ -585,6 +588,7 @@ AllocSetReset(MemoryContext context)
 		{
 			/* Normal case, release the block */
 			context->mem_allocated -= block->endptr - ((char *) block);
+			deallocation += block->endptr - ((char *) block);
 
 #ifdef CLOBBER_FREED_MEMORY
 			wipe_mem(block, block->freeptr - ((char *) block));
@@ -595,6 +599,7 @@ AllocSetReset(MemoryContext context)
 	}
 
 	Assert(context->mem_allocated == keepersize);
+	pgstat_report_allocated_bytes(deallocation, PG_ALLOC_DECREASE);
 
 	/* Reset block size allocation sequence, too */
 	set->nextBlockSize = set->initBlockSize;
@@ -613,6 +618,7 @@ AllocSetDelete(MemoryContext context)
 	AllocSet	set = (AllocSet) context;
 	AllocBlock	block = set->blocks;
 	Size		keepersize PG_USED_FOR_ASSERTS_ONLY;
+	uint64		deallocation = 0;
 
 	Assert(AllocSetIsValid(set));
 
@@ -651,11 +657,13 @@ AllocSetDelete(MemoryContext context)
 
 				freelist->first_free = (AllocSetContext *) oldset->header.nextchild;
 				freelist->num_free--;
+				deallocation += oldset->header.mem_allocated;
 
 				/* All that remains is to free the header/initial block */
 				free(oldset);
 			}
 			Assert(freelist->num_free == 0);
+			pgstat_report_allocated_bytes(deallocation, PG_ALLOC_DECREASE);
 		}
 
 		/* Now add the just-deleted context to the freelist. */
@@ -672,7 +680,10 @@ AllocSetDelete(MemoryContext context)
 		AllocBlock	next = block->next;
 
 		if (block != set->keeper)
+		{
 			context->mem_allocated -= block->endptr - ((char *) block);
+			deallocation += block->endptr - ((char *) block);
+		}
 
 #ifdef CLOBBER_FREED_MEMORY
 		wipe_mem(block, block->freeptr - ((char *) block));
@@ -685,6 +696,7 @@ AllocSetDelete(MemoryContext context)
 	}
 
 	Assert(context->mem_allocated == keepersize);
+	pgstat_report_allocated_bytes(deallocation + context->mem_allocated, PG_ALLOC_DECREASE);
 
 	/* Finally, free the context header, including the keeper block */
 	free(set);
@@ -734,6 +746,7 @@ AllocSetAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_allocated_bytes(blksize, PG_ALLOC_INCREASE);
 
 		block->aset = set;
 		block->freeptr = block->endptr = ((char *) block) + blksize;
@@ -944,6 +957,7 @@ AllocSetAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_allocated_bytes(blksize, PG_ALLOC_INCREASE);
 
 		block->aset = set;
 		block->freeptr = ((char *) block) + ALLOC_BLOCKHDRSZ;
@@ -1041,6 +1055,7 @@ AllocSetFree(void *pointer)
 			block->next->prev = block->prev;
 
 		set->header.mem_allocated -= block->endptr - ((char *) block);
+		pgstat_report_allocated_bytes(block->endptr - ((char *) block), PG_ALLOC_DECREASE);
 
 #ifdef CLOBBER_FREED_MEMORY
 		wipe_mem(block, block->freeptr - ((char *) block));
@@ -1171,7 +1186,9 @@ AllocSetRealloc(void *pointer, Size size)
 
 		/* updated separately, not to underflow when (oldblksize > blksize) */
 		set->header.mem_allocated -= oldblksize;
+		pgstat_report_allocated_bytes(oldblksize, PG_ALLOC_DECREASE);
 		set->header.mem_allocated += blksize;
+		pgstat_report_allocated_bytes(blksize, PG_ALLOC_INCREASE);
 
 		block->freeptr = block->endptr = ((char *) block) + blksize;
 
diff --git a/src/backend/utils/mmgr/generation.c b/src/backend/utils/mmgr/generation.c
index ebcb61e9b6..b06fb0c6a4 100644
--- a/src/backend/utils/mmgr/generation.c
+++ b/src/backend/utils/mmgr/generation.c
@@ -37,6 +37,7 @@
 
 #include "lib/ilist.h"
 #include "port/pg_bitutils.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -267,6 +268,7 @@ GenerationContextCreate(MemoryContext parent,
 						name);
 
 	((MemoryContext) set)->mem_allocated = firstBlockSize;
+	pgstat_report_allocated_bytes(firstBlockSize, PG_ALLOC_INCREASE);
 
 	return (MemoryContext) set;
 }
@@ -283,6 +285,7 @@ GenerationReset(MemoryContext context)
 {
 	GenerationContext *set = (GenerationContext *) context;
 	dlist_mutable_iter miter;
+	uint64		deallocation = 0;
 
 	Assert(GenerationIsValid(set));
 
@@ -305,9 +308,14 @@ GenerationReset(MemoryContext context)
 		if (block == set->keeper)
 			GenerationBlockMarkEmpty(block);
 		else
+		{
+			deallocation += block->blksize;
 			GenerationBlockFree(set, block);
+		}
 	}
 
+	pgstat_report_allocated_bytes(deallocation, PG_ALLOC_DECREASE);
+
 	/* set it so new allocations to make use of the keeper block */
 	set->block = set->keeper;
 
@@ -328,6 +336,9 @@ GenerationDelete(MemoryContext context)
 {
 	/* Reset to release all releasable GenerationBlocks */
 	GenerationReset(context);
+
+	pgstat_report_allocated_bytes(context->mem_allocated, PG_ALLOC_DECREASE);
+
 	/* And free the context header and keeper block */
 	free(context);
 }
@@ -374,6 +385,7 @@ GenerationAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_allocated_bytes(blksize, PG_ALLOC_INCREASE);
 
 		/* block with a single (used) chunk */
 		block->context = set;
@@ -477,6 +489,7 @@ GenerationAlloc(MemoryContext context, Size size)
 				return NULL;
 
 			context->mem_allocated += blksize;
+			pgstat_report_allocated_bytes(blksize, PG_ALLOC_INCREASE);
 
 			/* initialize the new block */
 			GenerationBlockInit(set, block, blksize);
@@ -729,6 +742,8 @@ GenerationFree(void *pointer)
 	dlist_delete(&block->node);
 
 	set->header.mem_allocated -= block->blksize;
+	pgstat_report_allocated_bytes(block->blksize, PG_ALLOC_DECREASE);
+
 	free(block);
 }
 
diff --git a/src/backend/utils/mmgr/slab.c b/src/backend/utils/mmgr/slab.c
index 33dca0f37c..e314f8f343 100644
--- a/src/backend/utils/mmgr/slab.c
+++ b/src/backend/utils/mmgr/slab.c
@@ -69,6 +69,7 @@
 #include "postgres.h"
 
 #include "lib/ilist.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -413,6 +414,13 @@ SlabContextCreate(MemoryContext parent,
 						parent,
 						name);
 
+	/*
+	 * If SlabContextCreate is updated to add context header size to
+	 * context->mem_allocated, then update here and SlabDelete appropriately
+	 */
+	pgstat_report_allocated_bytes(Slab_CONTEXT_HDRSZ(slab->chunksPerBlock),
+								  PG_ALLOC_INCREASE);
+
 	return (MemoryContext) slab;
 }
 
@@ -429,6 +437,7 @@ SlabReset(MemoryContext context)
 	SlabContext *slab = (SlabContext *) context;
 	dlist_mutable_iter miter;
 	int			i;
+	uint64		deallocation = 0;
 
 	Assert(SlabIsValid(slab));
 
@@ -465,9 +474,11 @@ SlabReset(MemoryContext context)
 #endif
 			free(block);
 			context->mem_allocated -= slab->blockSize;
+			deallocation += slab->blockSize;
 		}
 	}
 
+	pgstat_report_allocated_bytes(deallocation, PG_ALLOC_DECREASE);
 	slab->curBlocklistIndex = 0;
 
 	Assert(context->mem_allocated == 0);
@@ -480,8 +491,17 @@ SlabReset(MemoryContext context)
 void
 SlabDelete(MemoryContext context)
 {
+
 	/* Reset to release all the SlabBlocks */
 	SlabReset(context);
+
+	/*
+	 * Until context header allocation is included in context->mem_allocated,
+	 * cast to slab and decrement the header allocation
+	 */
+	pgstat_report_allocated_bytes(Slab_CONTEXT_HDRSZ(((SlabContext *)context)->chunksPerBlock),
+								  PG_ALLOC_DECREASE);
+
 	/* And free the context header */
 	free(context);
 }
@@ -546,6 +566,7 @@ SlabAlloc(MemoryContext context, Size size)
 
 			block->slab = slab;
 			context->mem_allocated += slab->blockSize;
+			pgstat_report_allocated_bytes(slab->blockSize, PG_ALLOC_INCREASE);
 
 			/* use the first chunk in the new block */
 			chunk = SlabBlockGetChunk(slab, block, 0);
@@ -732,6 +753,7 @@ SlabFree(void *pointer)
 #endif
 			free(block);
 			slab->header.mem_allocated -= slab->blockSize;
+			pgstat_report_allocated_bytes(slab->blockSize, PG_ALLOC_DECREASE);
 		}
 
 		/*
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index c0f2a8a77c..3fc9a30c60 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -5404,9 +5404,9 @@
   proname => 'pg_stat_get_activity', prorows => '100', proisstrict => 'f',
   proretset => 't', provolatile => 's', proparallel => 'r',
   prorettype => 'record', proargtypes => 'int4',
-  proallargtypes => '{int4,oid,int4,oid,text,text,text,text,text,timestamptz,timestamptz,timestamptz,timestamptz,inet,text,int4,xid,xid,text,bool,text,text,int4,text,numeric,text,bool,text,bool,int4,int8}',
-  proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
-  proargnames => '{pid,datid,pid,usesysid,application_name,state,query,wait_event_type,wait_event,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,backend_type,ssl,sslversion,sslcipher,sslbits,ssl_client_dn,ssl_client_serial,ssl_issuer_dn,gss_auth,gss_princ,gss_enc,leader_pid,query_id}',
+  proallargtypes => '{int4,oid,int4,oid,text,text,text,text,text,timestamptz,timestamptz,timestamptz,timestamptz,inet,text,int4,xid,xid,text,bool,text,text,int4,text,numeric,text,bool,text,bool,int4,int8,int8}',
+  proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
+  proargnames => '{pid,datid,pid,usesysid,application_name,state,query,wait_event_type,wait_event,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,backend_type,ssl,sslversion,sslcipher,sslbits,ssl_client_dn,ssl_client_serial,ssl_issuer_dn,gss_auth,gss_princ,gss_enc,leader_pid,query_id,allocated_bytes}',
   prosrc => 'pg_stat_get_activity' },
 { oid => '3318',
   descr => 'statistics: information about progress of backends running maintenance command',
diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h
index f7bd83113a..754ff0dc62 100644
--- a/src/include/utils/backend_status.h
+++ b/src/include/utils/backend_status.h
@@ -15,6 +15,7 @@
 #include "miscadmin.h"			/* for BackendType */
 #include "storage/backendid.h"
 #include "utils/backend_progress.h"
+#include "common/int.h"
 
 
 /* ----------
@@ -32,6 +33,13 @@ typedef enum BackendState
 	STATE_DISABLED
 } BackendState;
 
+/* Enum helper for reporting memory allocated bytes */
+enum allocation_direction
+{
+	PG_ALLOC_DECREASE = -1,
+	PG_ALLOC_IGNORE,
+	PG_ALLOC_INCREASE,
+};
 
 /* ----------
  * Shared-memory data structures
@@ -169,6 +177,9 @@ typedef struct PgBackendStatus
 
 	/* query identifier, optionally computed using post_parse_analyze_hook */
 	uint64		st_query_id;
+
+	/* Current memory allocated to this backend */
+	uint64		allocated_bytes;
 } PgBackendStatus;
 
 
@@ -293,6 +304,7 @@ extern PGDLLIMPORT int pgstat_track_activity_query_size;
  * ----------
  */
 extern PGDLLIMPORT PgBackendStatus *MyBEEntry;
+extern PGDLLIMPORT uint64 *my_allocated_bytes;
 
 
 /* ----------
@@ -324,7 +336,8 @@ extern const char *pgstat_get_backend_current_activity(int pid, bool checkUser);
 extern const char *pgstat_get_crashed_backend_activity(int pid, char *buffer,
 													   int buflen);
 extern uint64 pgstat_get_my_query_id(void);
-
+extern void pgstat_set_allocated_bytes_storage(uint64 *allocated_bytes);
+extern void pgstat_reset_allocated_bytes_storage(void);
 
 /* ----------
  * Support functions for the SQL-callable functions to
@@ -336,5 +349,53 @@ extern PgBackendStatus *pgstat_fetch_stat_beentry(BackendId beid);
 extern LocalPgBackendStatus *pgstat_fetch_stat_local_beentry(int beid);
 extern char *pgstat_clip_activity(const char *raw_activity);
 
+/* ----------
+ * pgstat_report_allocated_bytes() -
+ *
+ *  Called to report change in memory allocated for this backend.
+ *
+ * my_allocated_bytes initially points to local memory, making it safe to call
+ * this before pgstats has been initialized. allocation_direction is a
+ * positive/negative multiplier enum defined above.
+ * ----------
+ */
+static inline void
+pgstat_report_allocated_bytes(int64 allocated_bytes, int allocation_direction)
+{
+	uint64		temp;
+
+	/*
+	 * Avoid *my_allocated_bytes unsigned integer overflow on
+	 * PG_ALLOC_DECREASE
+	 */
+	if (allocation_direction == PG_ALLOC_DECREASE &&
+		pg_sub_u64_overflow(*my_allocated_bytes, allocated_bytes, &temp))
+	{
+		*my_allocated_bytes = 0;
+		ereport(LOG,
+				errmsg("Backend %d deallocated %lld bytes, exceeding the %llu bytes it is currently reporting allocated. Setting reported to 0.",
+					   MyProcPid, (long long) allocated_bytes,
+					   (unsigned long long) *my_allocated_bytes));
+	}
+	else
+		*my_allocated_bytes += (allocated_bytes) * allocation_direction;
+
+	return;
+}
+
+/* ---------
+ * pgstat_zero_my_allocated_bytes() -
+ *
+ * Called to zero out local allocated bytes variable after fork to avoid double
+ * counting allocations.
+ * ---------
+ */
+static inline void
+pgstat_zero_my_allocated_bytes(void)
+{
+	*my_allocated_bytes = 0;
+
+	return;
+}
 
 #endif							/* BACKEND_STATUS_H */
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index e7a2f5856a..ca8eeec7de 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1756,10 +1756,11 @@ pg_stat_activity| SELECT s.datid,
     s.state,
     s.backend_xid,
     s.backend_xmin,
+    s.allocated_bytes,
     s.query_id,
     s.query,
     s.backend_type
-   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, allocated_bytes)
      LEFT JOIN pg_database d ON ((s.datid = d.oid)))
      LEFT JOIN pg_authid u ON ((s.usesysid = u.oid)));
 pg_stat_all_indexes| SELECT c.oid AS relid,
@@ -1874,7 +1875,7 @@ pg_stat_gssapi| SELECT pid,
     gss_auth AS gss_authenticated,
     gss_princ AS principal,
     gss_enc AS encrypted
-   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, allocated_bytes)
   WHERE (client_port IS NOT NULL);
 pg_stat_progress_analyze| SELECT s.pid,
     s.datid,
@@ -2055,7 +2056,7 @@ pg_stat_replication| SELECT s.pid,
     w.sync_priority,
     w.sync_state,
     w.reply_time
-   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, allocated_bytes)
      JOIN pg_stat_get_wal_senders() w(pid, state, sent_lsn, write_lsn, flush_lsn, replay_lsn, write_lag, flush_lag, replay_lag, sync_priority, sync_state, reply_time) ON ((s.pid = w.pid)))
      LEFT JOIN pg_authid u ON ((s.usesysid = u.oid)));
 pg_stat_replication_slots| SELECT s.slot_name,
@@ -2089,7 +2090,7 @@ pg_stat_ssl| SELECT pid,
     ssl_client_dn AS client_dn,
     ssl_client_serial AS client_serial,
     ssl_issuer_dn AS issuer_dn
-   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, allocated_bytes)
   WHERE (client_port IS NOT NULL);
 pg_stat_subscription| SELECT su.oid AS subid,
     su.subname,
diff --git a/src/test/regress/expected/stats.out b/src/test/regress/expected/stats.out
index 1d84407a03..ab7e95c367 100644
--- a/src/test/regress/expected/stats.out
+++ b/src/test/regress/expected/stats.out
@@ -1126,4 +1126,15 @@ SELECT pg_stat_get_subscription_stats(NULL);
  
 (1 row)
 
+-- ensure that allocated_bytes exist for backends
+SELECT allocated_bytes > 0 AS result FROM pg_stat_activity WHERE backend_type
+IN ('checkpointer', 'background writer', 'walwriter', 'autovacuum launcher');
+ result 
+--------
+ t
+ t
+ t
+ t
+(4 rows)
+
 -- End of Stats Test
diff --git a/src/test/regress/sql/stats.sql b/src/test/regress/sql/stats.sql
index b4d6753c71..2f0b1cc9d8 100644
--- a/src/test/regress/sql/stats.sql
+++ b/src/test/regress/sql/stats.sql
@@ -535,5 +535,8 @@ SET enable_seqscan TO on;
 SELECT pg_stat_get_replication_slot(NULL);
 SELECT pg_stat_get_subscription_stats(NULL);
 
+-- ensure that allocated_bytes exist for backends
+SELECT allocated_bytes > 0 AS result FROM pg_stat_activity WHERE backend_type
+IN ('checkpointer', 'background writer', 'walwriter', 'autovacuum launcher');
 
 -- End of Stats Test
-- 
2.25.1

#27Andres Freund
andres@anarazel.de
In reply to: Reid Thompson (#26)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

Hi,

On 2023-01-23 10:48:38 -0500, Reid Thompson wrote:

On Thu, 2023-01-19 at 16:50 +0530, vignesh C wrote:

The patch does not apply on top of HEAD as in [1], please post a rebased patch:

Regards,
Vignesh

rebased patch attached

I think it's basically still waiting on author, until the O(N) cost is gone
from the overflow limit check.

Greetings,

Andres Freund

#28Reid Thompson
reid.thompson@crunchydata.com
In reply to: Andres Freund (#27)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On Mon, 2023-01-23 at 12:31 -0800, Andres Freund wrote:

Hi,

I think it's basically still waiting on author, until the O(N) cost is gone
from the overflow limit check.

Greetings,

Andres Freund

Yes, just a rebase. There is still work to be done per earlier in the
thread.

I do want to follow up and note re palloc/pfree vs malloc/free that the
tracking code (0001-Add-tracking-...) is not tracking palloc/pfree but is
explicitely tracking malloc/free. Not every palloc/pfree call executes the
tracking code, only those where the path followed includes malloc() or
free(). Routine palloc() calls fulfilled from the context's
freelist/emptyblocks/freeblock/etc and pfree() calls not invoking free()
avoid the tracking code.

Thanks,
Reid

#29Reid Thompson
reid.thompson@crunchydata.com
In reply to: Andres Freund (#24)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

Regarding the shared counter noted here,

What you could do is to have a single, imprecise, shared counter for the total
memory allocation, and have a backend-local "allowance". When the allowance is
used up, refill it from the shared counter (a single atomic op).

Is there a preferred or suggested location to put variables like this?
Perhaps a current variable to use as a reference?

Thanks,
Reid

#30Andres Freund
andres@anarazel.de
In reply to: Reid Thompson (#28)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

Hi,

On 2023-01-26 15:27:20 -0500, Reid Thompson wrote:

Yes, just a rebase. There is still work to be done per earlier in the
thread.

The tests recently started to fail:

https://cirrus-ci.com/github/postgresql-cfbot/postgresql/commitfest%2F42%2F3867

I do want to follow up and note re palloc/pfree vs malloc/free that the
tracking code (0001-Add-tracking-...) is not tracking palloc/pfree but is
explicitely tracking malloc/free. Not every palloc/pfree call executes the
tracking code, only those where the path followed includes malloc() or
free(). Routine palloc() calls fulfilled from the context's
freelist/emptyblocks/freeblock/etc and pfree() calls not invoking free()
avoid the tracking code.

Sure, but we create a lot of memory contexts, so that's not a whole lot of
comfort.

I marked this as waiting on author.

Greetings,

Andres Freund

#31Noname
reid.thompson@crunchydata.com
In reply to: Andres Freund (#30)
2 attachment(s)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On Mon, 2023-02-13 at 16:26 -0800, Andres Freund wrote:

Hi,

The tests recently started to fail:

https://cirrus-ci.com/github/postgresql-cfbot/postgresql/commitfest%2F42%2F3867

I marked this as waiting on author.

Greetings,

Andres Freund

Patch has been rebased to master.

The memory limiting portion (patch 0002-*) has been refactored to utilize a
shared counter for total memory allocation along with backend-local
allowances that are initialized at process startup and refilled from the
central counter upon being used up. Free'd memory is accumulated and
returned to the shared counter upon meeting a threshold and/or upon process
exit. At this point arbitrarily picked 1MB as the initial allowance and
return threshold.

Thanks,
Reid

Attachments:

0002-Add-the-ability-to-limit-the-amount-of-memory-that-c.patchtext/x-patch; charset=UTF-8; name=0002-Add-the-ability-to-limit-the-amount-of-memory-that-c.patchDownload
From e044bacedab503d1cd732146e1b9947406191bb6 Mon Sep 17 00:00:00 2001
From: Reid Thompson <jreidthompson@nc.rr.com>
Date: Sat, 4 Jun 2022 22:23:59 -0400
Subject: [PATCH 2/2] Add the ability to limit the amount of memory that can be
 allocated to backends.

This builds on the work that adds backend memory allocated to pg_stat_activity.

Add GUC variable max_total_backend_memory.

Specifies a limit to the amount of memory (in MB) that may be allocated to
backends in total (i.e. this is not a per user or per backend limit). If unset,
or set to 0 it is disabled. It is intended as a resource to help avoid the OOM
killer on LINUX and manage resources in general. A backend request that would
push the total over the limit will be denied with an out of memory error causing
that backend's current query/transaction to fail. Due to the dynamic nature of
memory allocations, this limit is not exact. If within 1.5MB of the limit and
two backends request 1MB each at the same time both may be allocated, and exceed
the limit. Further requests will not be allocated until dropping below the
limit. Keep this in mind when setting this value. This limit does not affect
auxiliary backend processes. Backend memory allocations are displayed in the
pg_stat_activity view.
---
 doc/src/sgml/config.sgml                      |  26 ++
 src/backend/postmaster/autovacuum.c           |   8 +-
 src/backend/postmaster/postmaster.c           |  17 +-
 src/backend/postmaster/syslogger.c            |   4 +-
 src/backend/storage/ipc/dsm_impl.c            |  35 ++-
 src/backend/storage/lmgr/proc.c               |   3 +
 src/backend/utils/activity/backend_status.c   | 223 +++++++++++++++++-
 src/backend/utils/misc/guc_tables.c           |  11 +
 src/backend/utils/misc/postgresql.conf.sample |   3 +
 src/backend/utils/mmgr/aset.c                 |  43 +++-
 src/backend/utils/mmgr/generation.c           |  21 +-
 src/backend/utils/mmgr/slab.c                 |  21 +-
 src/include/storage/proc.h                    |   7 +
 src/include/utils/backend_status.h            | 222 +++++++++++++++--
 14 files changed, 560 insertions(+), 84 deletions(-)

diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index e5c41cc6c6..1bff68b1ec 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -2113,6 +2113,32 @@ include_dir 'conf.d'
       </listitem>
      </varlistentry>
 
+     <varlistentry id="guc-max-total-backend-memory" xreflabel="max_total_backend_memory">
+      <term><varname>max_total_backend_memory</varname> (<type>integer</type>)
+      <indexterm>
+       <primary><varname>max_total_backend_memory</varname> configuration parameter</primary>
+      </indexterm>
+      </term>
+      <listitem>
+       <para>
+        Specifies a limit to the amount of memory (MB) that may be allocated to
+        backends in total (i.e. this is not a per user or per backend limit).
+        If unset, or set to 0 it is disabled.  A backend request that would
+        push the total over the limit will be denied with an out of memory
+        error causing that backend's current query/transaction to fail. Due to
+        the dynamic nature of memory allocations, this limit is not exact. If
+        within 1.5MB of the limit and two backends request 1MB each at the same
+        time both may be allocated, and exceed the limit. Further requests will
+        not be allocated until dropping below the limit. Keep this in mind when
+        setting this value. This limit does not affect auxiliary backend
+        processes <xref linkend="glossary-auxiliary-proc"/> . Backend memory
+        allocations (<varname>allocated_bytes</varname>) are displayed in the
+        <link linkend="monitoring-pg-stat-activity-view"><structname>pg_stat_activity</structname></link>
+        view.
+       </para>
+      </listitem>
+     </varlistentry>
+
      </variablelist>
      </sect2>
 
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index 59c9bcf8c4..ee03d08dd9 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -407,8 +407,8 @@ StartAutoVacLauncher(void)
 
 #ifndef EXEC_BACKEND
 		case 0:
-			/* Zero allocated bytes to avoid double counting parent allocation */
-			pgstat_zero_my_allocated_bytes();
+			/* Init allocated bytes to avoid double counting parent allocation */
+			pgstat_init_allocated_bytes();
 
 			/* in postmaster child ... */
 			InitPostmasterChild();
@@ -1488,8 +1488,8 @@ StartAutoVacWorker(void)
 
 #ifndef EXEC_BACKEND
 		case 0:
-			/* Zero allocated bytes to avoid double counting parent allocation */
-			pgstat_zero_my_allocated_bytes();
+			/* Init allocated bytes to avoid double counting parent allocation */
+			pgstat_init_allocated_bytes();
 
 			/* in postmaster child ... */
 			InitPostmasterChild();
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 1f09781be8..358a7fa980 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -4167,8 +4167,8 @@ BackendStartup(Port *port)
 	{
 		free(bn);
 
-		/* Zero allocated bytes to avoid double counting parent allocation */
-		pgstat_zero_my_allocated_bytes();
+		/* Init allocated bytes to avoid double counting parent allocation */
+		pgstat_init_allocated_bytes();
 
 		/* Detangle from postmaster */
 		InitPostmasterChild();
@@ -5377,10 +5377,11 @@ StartChildProcess(AuxProcType type)
 		MemoryContextDelete(PostmasterContext);
 		PostmasterContext = NULL;
 
-		/* Zero allocated bytes to avoid double counting parent allocation.
+		/*
+		 * Init allocated bytes to avoid double counting parent allocation.
 		 * Needs to be after the MemoryContextDelete(PostmasterContext) above.
 		 */
-		pgstat_zero_my_allocated_bytes();
+		pgstat_init_allocated_bytes();
 
 		AuxiliaryProcessMain(type); /* does not return */
 	}
@@ -5775,10 +5776,12 @@ do_start_bgworker(RegisteredBgWorker *rw)
 			MemoryContextDelete(PostmasterContext);
 			PostmasterContext = NULL;
 
-			/* Zero allocated bytes to avoid double counting parent allocation.
-			 * Needs to be after the MemoryContextDelete(PostmasterContext) above.
+			/*
+			 * Init allocated bytes to avoid double counting parent
+			 * allocation. Needs to be after the
+			 * MemoryContextDelete(PostmasterContext) above.
 			 */
-			pgstat_zero_my_allocated_bytes();
+			pgstat_init_allocated_bytes();
 
 			StartBackgroundWorker();
 
diff --git a/src/backend/postmaster/syslogger.c b/src/backend/postmaster/syslogger.c
index 9081ae140f..e8e31ce403 100644
--- a/src/backend/postmaster/syslogger.c
+++ b/src/backend/postmaster/syslogger.c
@@ -679,8 +679,8 @@ SysLogger_Start(void)
 
 #ifndef EXEC_BACKEND
 		case 0:
-			/* Zero allocated bytes to avoid double counting parent allocation */
-			pgstat_zero_my_allocated_bytes();
+			/* Init allocated bytes to avoid double counting parent allocation */
+			pgstat_init_allocated_bytes();
 
 			/* in postmaster child ... */
 			InitPostmasterChild();
diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c
index 22885c7bd2..1131de06c0 100644
--- a/src/backend/storage/ipc/dsm_impl.c
+++ b/src/backend/storage/ipc/dsm_impl.c
@@ -240,7 +240,7 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 		 * allocation.
 		 */
 		if (op == DSM_OP_DESTROY)
-			pgstat_report_allocated_bytes(*mapped_size, PG_ALLOC_DECREASE);
+			pgstat_report_allocated_bytes_decrease(*mapped_size, PG_ALLOC_DSM);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && shm_unlink(name) != 0)
@@ -254,6 +254,10 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 		return true;
 	}
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+		return false;
+
 	/*
 	 * Create new segment or open an existing one for attach.
 	 *
@@ -362,13 +366,10 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 		 * allocation increase.
 		 */
 		if (request_size > *mapped_size)
-		{
-			pgstat_report_allocated_bytes(request_size - *mapped_size,
-										  PG_ALLOC_INCREASE);
-		}
+			pgstat_report_allocated_bytes_increase(request_size - *mapped_size, PG_ALLOC_DSM);
 #else
-		pgstat_report_allocated_bytes(*mapped_size, PG_ALLOC_DECREASE);
-		pgstat_report_allocated_bytes(request_size, PG_ALLOC_INCREASE);
+		pgstat_report_allocated_bytes_decrease(*mapped_size, PG_ALLOC_DSM);
+		pgstat_report_allocated_bytes_increase(request_size, PG_ALLOC_DSM);
 #endif
 	}
 	*mapped_address = address;
@@ -525,6 +526,10 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 		int			flags = IPCProtection;
 		size_t		segsize;
 
+		/* Do not exceed maximum allowed memory allocation */
+		if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+			return false;
+
 		/*
 		 * Allocate the memory BEFORE acquiring the resource, so that we don't
 		 * leak the resource if memory allocation fails.
@@ -583,7 +588,7 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 		 * allocation.
 		 */
 		if (op == DSM_OP_DESTROY)
-			pgstat_report_allocated_bytes(*mapped_size, PG_ALLOC_DECREASE);
+			pgstat_report_allocated_bytes_decrease(*mapped_size, PG_ALLOC_DSM);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && shmctl(ident, IPC_RMID, NULL) < 0)
@@ -637,7 +642,7 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 	 * allocated in pg_stat_activity for the creator process.
 	 */
 	if (op == DSM_OP_CREATE)
-		pgstat_report_allocated_bytes(request_size, PG_ALLOC_INCREASE);
+		pgstat_report_allocated_bytes_increase(request_size, PG_ALLOC_DSM);
 	*mapped_address = address;
 	*mapped_size = request_size;
 
@@ -712,13 +717,17 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 		 * allocation.
 		 */
 		if (op == DSM_OP_DESTROY)
-			pgstat_report_allocated_bytes(*mapped_size, PG_ALLOC_DECREASE);
+			pgstat_report_allocated_bytes_decrease(*mapped_size, PG_ALLOC_DSM);
 		*impl_private = NULL;
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		return true;
 	}
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+		return false;
+
 	/* Create new segment or open an existing one for attach. */
 	if (op == DSM_OP_CREATE)
 	{
@@ -834,7 +843,7 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 	 * allocated in pg_stat_activity for the creator process.
 	 */
 	if (op == DSM_OP_CREATE)
-		pgstat_report_allocated_bytes(info.RegionSize, PG_ALLOC_INCREASE);
+		pgstat_report_allocated_bytes_increase(info.RegionSize, PG_ALLOC_DSM);
 	*mapped_address = address;
 	*mapped_size = info.RegionSize;
 	*impl_private = hmap;
@@ -885,7 +894,7 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size,
 		 * shown allocated in pg_stat_activity when the creator destroys the
 		 * allocation.
 		 */
-		pgstat_report_allocated_bytes(*mapped_size, PG_ALLOC_DECREASE);
+		pgstat_report_allocated_bytes_decrease(*mapped_size, PG_ALLOC_DSM);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && unlink(name) != 0)
@@ -1013,7 +1022,7 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size,
 	 * allocated in pg_stat_activity for the creator process.
 	 */
 	if (op == DSM_OP_CREATE)
-		pgstat_report_allocated_bytes(request_size, PG_ALLOC_INCREASE);
+		pgstat_report_allocated_bytes_increase(request_size, PG_ALLOC_DSM);
 	*mapped_address = address;
 	*mapped_size = request_size;
 
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index 22b4278610..2f43bbb4c4 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -180,6 +180,9 @@ InitProcGlobal(void)
 	ProcGlobal->checkpointerLatch = NULL;
 	pg_atomic_init_u32(&ProcGlobal->procArrayGroupFirst, INVALID_PGPROCNO);
 	pg_atomic_init_u32(&ProcGlobal->clogGroupFirst, INVALID_PGPROCNO);
+	/* Convert max_total_bkend_mem to bytes and store */
+	if (max_total_bkend_mem > 0)
+		pg_atomic_init_u64(&ProcGlobal->max_total_bkend_mem_bytes, max_total_bkend_mem * 1024 * 1024);
 
 	/*
 	 * Create and initialize all the PGPROC structures we'll need.  There are
diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c
index 7baf2db57d..ba5c92b573 100644
--- a/src/backend/utils/activity/backend_status.c
+++ b/src/backend/utils/activity/backend_status.c
@@ -45,13 +45,57 @@
 bool		pgstat_track_activities = false;
 int			pgstat_track_activity_query_size = 1024;
 
+/*
+ * Max backend memory allocation allowed (MB). 0 = disabled.
+ * Centralized bucket ProcGlobal->max_total_bkend_mem is initialized
+ * as a byte representation of this value in InitProcGlobal().
+ */
+int			max_total_bkend_mem = 0;
 
 /* exposed so that backend_progress.c can access it */
 PgBackendStatus *MyBEEntry = NULL;
 
-/* Memory allocated to this backend prior to pgstats initialization */
-uint64	local_my_allocated_bytes = 0;
-uint64	*my_allocated_bytes = &local_my_allocated_bytes;
+/*
+ * Define initial allocation allowance for a backend.
+ *
+ * NOTE: initial_allocation_allowance && allocation_allowance_refill_qty
+ * may be candidates for future GUC variables. Arbitrary 1MB selected initially.
+ */
+uint64		initial_allocation_allowance = 1024 * 1024;
+uint64		allocation_allowance_refill_qty = 1024 * 1024;
+
+/*
+ * Local counter to manage shared memory allocations. At backend startup, set to
+ * initial_allocation_allowance via pgstat_init_allocated_bytes(). Decrease as
+ * memory is malloc'd. When exhausted, atomically refill if available from
+ * ProcGlobal->max_total_bkend_mem via exceeds_max_total_bkend_mem().
+ */
+uint64		allocation_allowance = 0;
+
+/*
+ * Local counter of free'd shared memory. Return to global
+ * max_total_bkend_mem when return threshold is met. Arbitrary 1MB bytes
+ * selected initially.
+ */
+uint64		allocation_return = 0;
+uint64		allocation_return_threshold = 1024 * 1024;
+
+/*
+ * Memory allocated to this backend prior to pgstats initialization. Migrated to
+ * shared memory on pgstats initialization.
+ */
+uint64		local_my_allocated_bytes = 0;
+uint64	   *my_allocated_bytes = &local_my_allocated_bytes;
+
+/* Memory allocated to this backend by type */
+/*
+ * TODO: add code to present these along with the global shared counter via a
+ * new system view
+ */
+uint64		aset_allocated_bytes = 0;
+uint64		dsm_allocated_bytes = 0;
+uint64		generation_allocated_bytes = 0;
+uint64		slab_allocated_bytes = 0;
 
 static PgBackendStatus *BackendStatusArray = NULL;
 static char *BackendAppnameBuffer = NULL;
@@ -403,11 +447,18 @@ pgstat_bestart(void)
 	lbeentry.st_progress_command_target = InvalidOid;
 	lbeentry.st_query_id = UINT64CONST(0);
 
-	/* Alter allocation reporting from local_my_allocated_bytes to shared memory */
+	/*
+	 * Alter allocation reporting from local_my_allocated_bytes to shared
+	 * memory
+	 */
 	pgstat_set_allocated_bytes_storage(&MyBEEntry->allocated_bytes);
 
-	/* Populate sum of memory allocated prior to pgstats initialization to pgstats
-	 * and zero the local variable.
+	/*
+	 * Populate sum of memory allocated prior to pgstats initialization to
+	 * pgstats and zero the local variable. This is a += assignment because
+	 * InitPostgres allocates memory after pgstat_beinit but prior to
+	 * pgstat_bestart so we have allocations to both local and shared memory
+	 * to combine.
 	 */
 	lbeentry.allocated_bytes += local_my_allocated_bytes;
 	local_my_allocated_bytes = 0;
@@ -472,7 +523,8 @@ pgstat_beshutdown_hook(int code, Datum arg)
 	volatile PgBackendStatus *beentry = MyBEEntry;
 
 	/*
-	 * Stop reporting memory allocation changes to &MyBEEntry->allocated_bytes
+	 * Stop reporting memory allocation changes to shared memory
+	 * &MyBEEntry->allocated_bytes
 	 */
 	pgstat_reset_allocated_bytes_storage();
 
@@ -1221,21 +1273,170 @@ pgstat_clip_activity(const char *raw_activity)
  * my_allocated_bytes into shared memory.
  */
 void
-pgstat_set_allocated_bytes_storage(uint64 *new_allocated_bytes)
+pgstat_set_allocated_bytes_storage(uint64 *allocated_bytes)
 {
-	my_allocated_bytes = new_allocated_bytes;
-	*new_allocated_bytes = local_my_allocated_bytes;
+	my_allocated_bytes = allocated_bytes;
+	*allocated_bytes = local_my_allocated_bytes;
+
+	return;
 }
 
 /*
  * Reset allocated bytes storage location.
  *
  * Expected to be called during backend shutdown, before the location set up
- * by pgstat_set_allocated_bytes_storage() becomes invalid.
+ * by pgstat_set_allocated_bytes_storage becomes invalid.
  */
 void
 pgstat_reset_allocated_bytes_storage(void)
 {
+	/*
+	 * When limiting maximum backend memory, return this backend's memory
+	 * allocations to global.
+	 */
+	if (max_total_bkend_mem)
+	{
+		volatile PROC_HDR *procglobal = ProcGlobal;
+
+		pg_atomic_add_fetch_u64(&procglobal->max_total_bkend_mem_bytes,
+								*my_allocated_bytes + allocation_allowance +
+								allocation_return);
+
+		/* Reset memory allocation variables */
+		allocation_allowance = 0;
+		allocation_return = 0;
+		aset_allocated_bytes = 0;
+		dsm_allocated_bytes = 0;
+		generation_allocated_bytes = 0;
+		slab_allocated_bytes = 0;
+	}
+
+	/* Reset memory allocation variables */
+	*my_allocated_bytes = local_my_allocated_bytes = 0;
+
+	/* Point my_allocated_bytes from shared memory back to local */
 	my_allocated_bytes = &local_my_allocated_bytes;
+
+	return;
 }
 
+/*
+ * Determine if allocation request will exceed max backend memory allowed.
+ * Do not apply to auxiliary processes.
+ * Refill allocation request bucket when needed/possible.
+ */
+bool
+exceeds_max_total_bkend_mem(uint64 allocation_request)
+{
+	bool		result = false;
+
+	/*
+	 * When limiting maximum backend memory, attempt to refill allocation
+	 * request bucket if needed.
+	 */
+	if (max_total_bkend_mem && allocation_request > allocation_allowance)
+	{
+		volatile PROC_HDR *procglobal = ProcGlobal;
+		uint64		available_max_total_bkend_mem = 0;
+		bool		sts = false;
+
+		/*
+		 * If allocation request is larger than memory refill quantity then
+		 * attempt to increase allocation allowance with requested amount,
+		 * otherwise fall through. If this refill fails we do not have enough
+		 * memory to meet the request.
+		 */
+		if (allocation_request >= allocation_allowance_refill_qty)
+		{
+			while ((available_max_total_bkend_mem = pg_atomic_read_u64(&procglobal->max_total_bkend_mem_bytes)) >= allocation_request)
+			{
+				if ((result = pg_atomic_compare_exchange_u64(&procglobal->max_total_bkend_mem_bytes,
+															 &available_max_total_bkend_mem,
+															 available_max_total_bkend_mem - allocation_request)))
+				{
+					allocation_allowance = allocation_allowance + allocation_request;
+					break;
+				}
+			}
+
+			/*
+			 * If the atomic exchange fails, we do not have enough reserve
+			 * memory to meet the request. Negate result to return the proper
+			 * value.
+			 */
+			return !result;
+		}
+
+		/*
+		 * Attempt to increase allocation allowance by memory refill quantity.
+		 * If available memory is/becomes less than memory refill quantity,
+		 * fall through to attempt to allocate remaining available memory.
+		 */
+		while ((available_max_total_bkend_mem = pg_atomic_read_u64(&procglobal->max_total_bkend_mem_bytes)) >= allocation_allowance_refill_qty)
+		{
+			if ((sts = pg_atomic_compare_exchange_u64(&procglobal->max_total_bkend_mem_bytes,
+													  &available_max_total_bkend_mem,
+													  available_max_total_bkend_mem - allocation_allowance_refill_qty)))
+			{
+				allocation_allowance = allocation_allowance + allocation_allowance_refill_qty;
+				break;
+			}
+		}
+
+		if (!sts)
+		{
+			/*
+			 * If available_max_total_bkend_mem is 0, no memory is currently
+			 * available to refill with, otherwise attempt to allocate
+			 * remaining memory available if it exceeds the requested amount
+			 * or the requested amount if more than requested amount gets
+			 * returned while looping.
+			 */
+			while ((available_max_total_bkend_mem = (int64) pg_atomic_read_u64(&procglobal->max_total_bkend_mem_bytes)) > 0)
+			{
+				uint64		newval = 0;
+
+				/*
+				 * If available memory is less than requested allocation we
+				 * cannot fulfil request.
+				 */
+				if (available_max_total_bkend_mem < allocation_request)
+					break;
+
+				/*
+				 * If we happen to loop and a large chunk of memory has been
+				 * returned to global, allocate request amount only.
+				 */
+				if (available_max_total_bkend_mem > allocation_request)
+					newval = available_max_total_bkend_mem - allocation_request;
+
+				/* Allocate memory */
+				if ((sts = pg_atomic_compare_exchange_u64(&procglobal->max_total_bkend_mem_bytes,
+														  &available_max_total_bkend_mem,
+														  newval)))
+				{
+					allocation_allowance = allocation_allowance +
+						newval == 0 ? available_max_total_bkend_mem : allocation_request;
+
+					break;
+				}
+			}
+		}
+
+		/*
+		 * If refill is not successful, we return true, memory limit exceeded
+		 */
+		if (!sts)
+			result = true;
+	}
+
+	/*
+	 * Exclude auxiliary processes from the check. Return false. While we want
+	 * to exclude them from the check, we do not want to exclude them from the
+	 * above allocation handling.
+	 */
+	if (MyAuxProcType != NotAnAuxProcess)
+		result = false;
+
+	return result;
+}
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index 1c0583fe26..639b63138b 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -3468,6 +3468,17 @@ struct config_int ConfigureNamesInt[] =
 		NULL, NULL, NULL
 	},
 
+	{
+		{"max_total_backend_memory", PGC_SU_BACKEND, RESOURCES_MEM,
+			gettext_noop("Restrict total backend memory allocations to this max."),
+			gettext_noop("0 turns this feature off."),
+			GUC_UNIT_MB
+		},
+		&max_total_bkend_mem,
+		0, 0, INT_MAX,
+		NULL, NULL, NULL
+	},
+
 	/* End-of-list marker */
 	{
 		{NULL, 0, 0, NULL, NULL}, NULL, 0, 0, 0, NULL, NULL, NULL
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index d06074b86f..bc2d449c87 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -156,6 +156,9 @@
 					#   mmap
 					# (change requires restart)
 #min_dynamic_shared_memory = 0MB	# (change requires restart)
+#max_total_backend_memory = 0MB		# Restrict total backend memory allocations
+									# to this max (in MB). 0 turns this feature
+									# off.
 
 # - Disk -
 
diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index 1a2d86239c..4d2dead51f 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -440,6 +440,10 @@ AllocSetContextCreateInternal(MemoryContext parent,
 	else
 		firstBlockSize = Max(firstBlockSize, initBlockSize);
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (exceeds_max_total_bkend_mem(firstBlockSize))
+		return NULL;
+
 	/*
 	 * Allocate the initial block.  Unlike other aset.c blocks, it starts with
 	 * the context header and its block header follows that.
@@ -522,7 +526,7 @@ AllocSetContextCreateInternal(MemoryContext parent,
 						name);
 
 	((MemoryContext) set)->mem_allocated = firstBlockSize;
-	pgstat_report_allocated_bytes(firstBlockSize, PG_ALLOC_INCREASE);
+	pgstat_report_allocated_bytes_increase(firstBlockSize, PG_ALLOC_ASET);
 
 	return (MemoryContext) set;
 }
@@ -599,7 +603,7 @@ AllocSetReset(MemoryContext context)
 	}
 
 	Assert(context->mem_allocated == keepersize);
-	pgstat_report_allocated_bytes(deallocation, PG_ALLOC_DECREASE);
+	pgstat_report_allocated_bytes_decrease(deallocation, PG_ALLOC_ASET);
 
 	/* Reset block size allocation sequence, too */
 	set->nextBlockSize = set->initBlockSize;
@@ -663,7 +667,7 @@ AllocSetDelete(MemoryContext context)
 				free(oldset);
 			}
 			Assert(freelist->num_free == 0);
-			pgstat_report_allocated_bytes(deallocation, PG_ALLOC_DECREASE);
+			pgstat_report_allocated_bytes_decrease(deallocation, PG_ALLOC_ASET);
 		}
 
 		/* Now add the just-deleted context to the freelist. */
@@ -696,7 +700,7 @@ AllocSetDelete(MemoryContext context)
 	}
 
 	Assert(context->mem_allocated == keepersize);
-	pgstat_report_allocated_bytes(deallocation + context->mem_allocated, PG_ALLOC_DECREASE);
+	pgstat_report_allocated_bytes_decrease(deallocation + context->mem_allocated, PG_ALLOC_ASET);
 
 	/* Finally, free the context header, including the keeper block */
 	free(set);
@@ -741,12 +745,17 @@ AllocSetAlloc(MemoryContext context, Size size)
 #endif
 
 		blksize = chunk_size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
+
+		/* Do not exceed maximum allowed memory allocation */
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		block = (AllocBlock) malloc(blksize);
 		if (block == NULL)
 			return NULL;
 
 		context->mem_allocated += blksize;
-		pgstat_report_allocated_bytes(blksize, PG_ALLOC_INCREASE);
+		pgstat_report_allocated_bytes_increase(blksize, PG_ALLOC_ASET);
 
 		block->aset = set;
 		block->freeptr = block->endptr = ((char *) block) + blksize;
@@ -938,6 +947,10 @@ AllocSetAlloc(MemoryContext context, Size size)
 		while (blksize < required_size)
 			blksize <<= 1;
 
+		/* Do not exceed maximum allowed memory allocation */
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		/* Try to allocate it */
 		block = (AllocBlock) malloc(blksize);
 
@@ -957,7 +970,7 @@ AllocSetAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
-		pgstat_report_allocated_bytes(blksize, PG_ALLOC_INCREASE);
+		pgstat_report_allocated_bytes_increase(blksize, PG_ALLOC_ASET);
 
 		block->aset = set;
 		block->freeptr = ((char *) block) + ALLOC_BLOCKHDRSZ;
@@ -1055,7 +1068,7 @@ AllocSetFree(void *pointer)
 			block->next->prev = block->prev;
 
 		set->header.mem_allocated -= block->endptr - ((char *) block);
-		pgstat_report_allocated_bytes(block->endptr - ((char *) block), PG_ALLOC_DECREASE);
+		pgstat_report_allocated_bytes_decrease(block->endptr - ((char *) block), PG_ALLOC_ASET);
 
 #ifdef CLOBBER_FREED_MEMORY
 		wipe_mem(block, block->freeptr - ((char *) block));
@@ -1176,6 +1189,18 @@ AllocSetRealloc(void *pointer, Size size)
 		blksize = chksize + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
 		oldblksize = block->endptr - ((char *) block);
 
+		/*
+		 * Do not exceed maximum allowed memory allocation. NOTE: checking for
+		 * the full size here rather than just the amount of increased
+		 * allocation to prevent a potential underflow of *my_allocation
+		 * allowance in cases where blksize - oldblksize does not trigger a
+		 * refill but blksize is greater than *my_allocation_allowance.
+		 * Underflow would occur with the call below to
+		 * pgstat_report_allocated_bytes_increase()
+		 */
+		if (blksize > oldblksize && exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		block = (AllocBlock) realloc(block, blksize);
 		if (block == NULL)
 		{
@@ -1186,9 +1211,9 @@ AllocSetRealloc(void *pointer, Size size)
 
 		/* updated separately, not to underflow when (oldblksize > blksize) */
 		set->header.mem_allocated -= oldblksize;
-		pgstat_report_allocated_bytes(oldblksize, PG_ALLOC_DECREASE);
+		pgstat_report_allocated_bytes_decrease(oldblksize, PG_ALLOC_ASET);
 		set->header.mem_allocated += blksize;
-		pgstat_report_allocated_bytes(blksize, PG_ALLOC_INCREASE);
+		pgstat_report_allocated_bytes_increase(blksize, PG_ALLOC_ASET);
 
 		block->freeptr = block->endptr = ((char *) block) + blksize;
 
diff --git a/src/backend/utils/mmgr/generation.c b/src/backend/utils/mmgr/generation.c
index b06fb0c6a4..8f9d56eb0f 100644
--- a/src/backend/utils/mmgr/generation.c
+++ b/src/backend/utils/mmgr/generation.c
@@ -201,6 +201,9 @@ GenerationContextCreate(MemoryContext parent,
 	else
 		allocSize = Max(allocSize, initBlockSize);
 
+	if (exceeds_max_total_bkend_mem(allocSize))
+		return NULL;
+
 	/*
 	 * Allocate the initial block.  Unlike other generation.c blocks, it
 	 * starts with the context header and its block header follows that.
@@ -268,7 +271,7 @@ GenerationContextCreate(MemoryContext parent,
 						name);
 
 	((MemoryContext) set)->mem_allocated = firstBlockSize;
-	pgstat_report_allocated_bytes(firstBlockSize, PG_ALLOC_INCREASE);
+	pgstat_report_allocated_bytes_increase(firstBlockSize, PG_ALLOC_GENERATION);
 
 	return (MemoryContext) set;
 }
@@ -314,7 +317,7 @@ GenerationReset(MemoryContext context)
 		}
 	}
 
-	pgstat_report_allocated_bytes(deallocation, PG_ALLOC_DECREASE);
+	pgstat_report_allocated_bytes_decrease(deallocation, PG_ALLOC_GENERATION);
 
 	/* set it so new allocations to make use of the keeper block */
 	set->block = set->keeper;
@@ -337,7 +340,7 @@ GenerationDelete(MemoryContext context)
 	/* Reset to release all releasable GenerationBlocks */
 	GenerationReset(context);
 
-	pgstat_report_allocated_bytes(context->mem_allocated, PG_ALLOC_DECREASE);
+	pgstat_report_allocated_bytes_decrease(context->mem_allocated, PG_ALLOC_GENERATION);
 
 	/* And free the context header and keeper block */
 	free(context);
@@ -380,12 +383,15 @@ GenerationAlloc(MemoryContext context, Size size)
 	{
 		Size		blksize = required_size + Generation_BLOCKHDRSZ;
 
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		block = (GenerationBlock *) malloc(blksize);
 		if (block == NULL)
 			return NULL;
 
 		context->mem_allocated += blksize;
-		pgstat_report_allocated_bytes(blksize, PG_ALLOC_INCREASE);
+		pgstat_report_allocated_bytes_increase(blksize, PG_ALLOC_GENERATION);
 
 		/* block with a single (used) chunk */
 		block->context = set;
@@ -483,13 +489,16 @@ GenerationAlloc(MemoryContext context, Size size)
 			if (blksize < required_size)
 				blksize = pg_nextpower2_size_t(required_size);
 
+			if (exceeds_max_total_bkend_mem(blksize))
+				return NULL;
+
 			block = (GenerationBlock *) malloc(blksize);
 
 			if (block == NULL)
 				return NULL;
 
 			context->mem_allocated += blksize;
-			pgstat_report_allocated_bytes(blksize, PG_ALLOC_INCREASE);
+			pgstat_report_allocated_bytes_increase(blksize, PG_ALLOC_GENERATION);
 
 			/* initialize the new block */
 			GenerationBlockInit(set, block, blksize);
@@ -742,7 +751,7 @@ GenerationFree(void *pointer)
 	dlist_delete(&block->node);
 
 	set->header.mem_allocated -= block->blksize;
-	pgstat_report_allocated_bytes(block->blksize, PG_ALLOC_DECREASE);
+	pgstat_report_allocated_bytes_decrease(block->blksize, PG_ALLOC_GENERATION);
 
 	free(block);
 }
diff --git a/src/backend/utils/mmgr/slab.c b/src/backend/utils/mmgr/slab.c
index 15d3380640..de85781479 100644
--- a/src/backend/utils/mmgr/slab.c
+++ b/src/backend/utils/mmgr/slab.c
@@ -356,9 +356,12 @@ SlabContextCreate(MemoryContext parent,
 		elog(ERROR, "block size %zu for slab is too small for %zu-byte chunks",
 			 blockSize, chunkSize);
 
-
+	/* Do not exceed maximum allowed memory allocation */
+	if (exceeds_max_total_bkend_mem(Slab_CONTEXT_HDRSZ(chunksPerBlock)))
+		return NULL;
 
 	slab = (SlabContext *) malloc(Slab_CONTEXT_HDRSZ(chunksPerBlock));
+
 	if (slab == NULL)
 	{
 		MemoryContextStats(TopMemoryContext);
@@ -418,8 +421,7 @@ SlabContextCreate(MemoryContext parent,
 	 * If SlabContextCreate is updated to add context header size to
 	 * context->mem_allocated, then update here and SlabDelete appropriately
 	 */
-	pgstat_report_allocated_bytes(Slab_CONTEXT_HDRSZ(slab->chunksPerBlock),
-								  PG_ALLOC_INCREASE);
+	pgstat_report_allocated_bytes_increase(Slab_CONTEXT_HDRSZ(slab->chunksPerBlock), PG_ALLOC_SLAB);
 
 	return (MemoryContext) slab;
 }
@@ -479,7 +481,7 @@ SlabReset(MemoryContext context)
 		}
 	}
 
-	pgstat_report_allocated_bytes(deallocation, PG_ALLOC_DECREASE);
+	pgstat_report_allocated_bytes_decrease(deallocation, PG_ALLOC_SLAB);
 	slab->curBlocklistIndex = 0;
 
 	Assert(context->mem_allocated == 0);
@@ -500,8 +502,7 @@ SlabDelete(MemoryContext context)
 	 * Until context header allocation is included in context->mem_allocated,
 	 * cast to slab and decrement the header allocation
 	 */
-	pgstat_report_allocated_bytes(Slab_CONTEXT_HDRSZ(((SlabContext *)context)->chunksPerBlock),
-								  PG_ALLOC_DECREASE);
+	pgstat_report_allocated_bytes_decrease(Slab_CONTEXT_HDRSZ(((SlabContext *) context)->chunksPerBlock), PG_ALLOC_SLAB);
 
 	/* And free the context header */
 	free(context);
@@ -560,6 +561,10 @@ SlabAlloc(MemoryContext context, Size size)
 		}
 		else
 		{
+			/* Do not exceed maximum allowed memory allocation */
+			if (exceeds_max_total_bkend_mem(slab->blockSize))
+				return NULL;
+
 			block = (SlabBlock *) malloc(slab->blockSize);
 
 			if (unlikely(block == NULL))
@@ -567,7 +572,7 @@ SlabAlloc(MemoryContext context, Size size)
 
 			block->slab = slab;
 			context->mem_allocated += slab->blockSize;
-			pgstat_report_allocated_bytes(slab->blockSize, PG_ALLOC_INCREASE);
+			pgstat_report_allocated_bytes_increase(slab->blockSize, PG_ALLOC_SLAB);
 
 			/* use the first chunk in the new block */
 			chunk = SlabBlockGetChunk(slab, block, 0);
@@ -754,7 +759,7 @@ SlabFree(void *pointer)
 #endif
 			free(block);
 			slab->header.mem_allocated -= slab->blockSize;
-			pgstat_report_allocated_bytes(slab->blockSize, PG_ALLOC_DECREASE);
+			pgstat_report_allocated_bytes_decrease(slab->blockSize, PG_ALLOC_SLAB);
 		}
 
 		/*
diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h
index 4258cd92c9..bacf879294 100644
--- a/src/include/storage/proc.h
+++ b/src/include/storage/proc.h
@@ -404,6 +404,13 @@ typedef struct PROC_HDR
 	int			spins_per_delay;
 	/* Buffer id of the buffer that Startup process waits for pin on, or -1 */
 	int			startupBufferPinWaitBufId;
+
+	/*
+	 * Max backend memory allocation tracker. Used/Initialized when
+	 * max_total_bkend_mem > 0 as max_total_bkend_mem (MB) converted to bytes.
+	 * Decreases/increases with free/malloc of backend memory.
+	 */
+	pg_atomic_uint64 max_total_bkend_mem_bytes;
 } PROC_HDR;
 
 extern PGDLLIMPORT PROC_HDR *ProcGlobal;
diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h
index 754ff0dc62..32a1149007 100644
--- a/src/include/utils/backend_status.h
+++ b/src/include/utils/backend_status.h
@@ -14,6 +14,7 @@
 #include "libpq/pqcomm.h"
 #include "miscadmin.h"			/* for BackendType */
 #include "storage/backendid.h"
+#include "storage/proc.h"
 #include "utils/backend_progress.h"
 #include "common/int.h"
 
@@ -33,12 +34,14 @@ typedef enum BackendState
 	STATE_DISABLED
 } BackendState;
 
-/* Enum helper for reporting memory allocated bytes */
-enum allocation_direction
+/* Enum helper for reporting memory allocator type */
+enum pg_allocator_type
 {
-	PG_ALLOC_DECREASE = -1,
-	PG_ALLOC_IGNORE,
-	PG_ALLOC_INCREASE,
+	PG_ALLOC_ASET = 1,
+	PG_ALLOC_DSM,
+	PG_ALLOC_GENERATION,
+	PG_ALLOC_SLAB,
+	PG_ALLOC_ONSHUTDOWN,
 };
 
 /* ----------
@@ -297,6 +300,7 @@ typedef struct LocalPgBackendStatus
  */
 extern PGDLLIMPORT bool pgstat_track_activities;
 extern PGDLLIMPORT int pgstat_track_activity_query_size;
+extern PGDLLIMPORT int max_total_bkend_mem;
 
 
 /* ----------
@@ -305,7 +309,15 @@ extern PGDLLIMPORT int pgstat_track_activity_query_size;
  */
 extern PGDLLIMPORT PgBackendStatus *MyBEEntry;
 extern PGDLLIMPORT uint64 *my_allocated_bytes;
+extern PGDLLIMPORT uint64 allocation_allowance;
+extern PGDLLIMPORT uint64 initial_allocation_allowance;
+extern PGDLLIMPORT uint64 allocation_return;
+extern PGDLLIMPORT uint64 allocation_return_threshold;
 
+extern PGDLLIMPORT uint64 aset_allocated_bytes;
+extern PGDLLIMPORT uint64 dsm_allocated_bytes;
+extern PGDLLIMPORT uint64 generation_allocated_bytes;
+extern PGDLLIMPORT uint64 slab_allocated_bytes;
 
 /* ----------
  * Functions called from postmaster
@@ -338,6 +350,7 @@ extern const char *pgstat_get_crashed_backend_activity(int pid, char *buffer,
 extern uint64 pgstat_get_my_query_id(void);
 extern void pgstat_set_allocated_bytes_storage(uint64 *allocated_bytes);
 extern void pgstat_reset_allocated_bytes_storage(void);
+extern void decrease_max_total_bkend_mem(int64 decrease);
 
 /* ----------
  * Support functions for the SQL-callable functions to
@@ -348,53 +361,214 @@ extern int	pgstat_fetch_stat_numbackends(void);
 extern PgBackendStatus *pgstat_fetch_stat_beentry(BackendId beid);
 extern LocalPgBackendStatus *pgstat_fetch_stat_local_beentry(int beid);
 extern char *pgstat_clip_activity(const char *raw_activity);
+extern bool exceeds_max_total_bkend_mem(uint64 allocation_request);
 
 /* ----------
- * pgstat_report_allocated_bytes() -
- *
- *  Called to report change in memory allocated for this backend.
+ * pgstat_report_allocated_bytes_decrease() -
+ *  Called to report decrease in memory allocated for this backend.
  *
  * my_allocated_bytes initially points to local memory, making it safe to call
- * this before pgstats has been initialized. allocation_direction is a
- * positive/negative multiplier enum defined above.
+ * this before pgstats has been initialized.
  * ----------
  */
 static inline void
-pgstat_report_allocated_bytes(int64 allocated_bytes, int allocation_direction)
+pgstat_report_allocated_bytes_decrease(int64 proc_allocated_bytes, int pg_allocator_type)
 {
 	uint64		temp;
 
 	/*
-	 * Avoid *my_allocated_bytes unsigned integer overflow on
-	 * PG_ALLOC_DECREASE
+	 * Avoid allocated_bytes unsigned integer overflow on decrease.
 	 */
-	if (allocation_direction == PG_ALLOC_DECREASE &&
-		pg_sub_u64_overflow(*my_allocated_bytes, allocated_bytes, &temp))
+	if (pg_sub_u64_overflow(*my_allocated_bytes, proc_allocated_bytes, &temp))
 	{
+		/* Add free'd memory to allocation return counter. */
+		allocation_return += proc_allocated_bytes;
+
+		/* On overflow, reset pgstat count of allocated bytes to zero */
 		*my_allocated_bytes = 0;
-		ereport(LOG,
-				errmsg("Backend %d deallocated %lld bytes, exceeding the %llu bytes it is currently reporting allocated. Setting reported to 0.",
-					   MyProcPid, (long long) allocated_bytes,
-					   (unsigned long long) *my_allocated_bytes));
+
+		/* Reset allocator type allocated bytes */
+		switch (pg_allocator_type)
+		{
+			case PG_ALLOC_ASET:
+				aset_allocated_bytes = 0;
+				break;
+			case PG_ALLOC_DSM:
+				dsm_allocated_bytes = 0;
+				break;
+			case PG_ALLOC_GENERATION:
+				generation_allocated_bytes = 0;
+				break;
+			case PG_ALLOC_SLAB:
+				slab_allocated_bytes = 0;
+				break;
+			case PG_ALLOC_ONSHUTDOWN:
+				break;
+		}
+
+		/*
+		 * Return free'd memory to the global counter when return threshold is
+		 * met or process end.
+		 */
+		if (max_total_bkend_mem && allocation_return >= allocation_return_threshold)
+		{
+			if (ProcGlobal)
+			{
+				volatile PROC_HDR *procglobal = ProcGlobal;
+
+				/* Add to global */
+				pg_atomic_add_fetch_u64(&procglobal->max_total_bkend_mem_bytes,
+										allocation_return);
+
+				/* Restart count */
+				allocation_return = 0;
+			}
+		}
 	}
 	else
-		*my_allocated_bytes += (allocated_bytes) * allocation_direction;
+	{
+		/* Add free'd memory to allocation return counter. */
+		allocation_return += proc_allocated_bytes;
+
+		/* Decrease pgstat count of allocated bytes */
+		*my_allocated_bytes -= (proc_allocated_bytes);
+
+		/*
+		 * Decrease allocator type allocated bytes. NOTE: per hackers dsm
+		 * memory allocations lifespan may exceed process lifespan, so we may
+		 * implement a long lived tracker for it ala max_total_bkend_mem_bytes
+		 */
+		switch (pg_allocator_type)
+		{
+			case PG_ALLOC_ASET:
+				aset_allocated_bytes -= (proc_allocated_bytes);
+				break;
+			case PG_ALLOC_DSM:
+				dsm_allocated_bytes -= (proc_allocated_bytes);
+				break;
+			case PG_ALLOC_GENERATION:
+				generation_allocated_bytes -= (proc_allocated_bytes);
+				break;
+			case PG_ALLOC_SLAB:
+				slab_allocated_bytes -= (proc_allocated_bytes);
+				break;
+			case PG_ALLOC_ONSHUTDOWN:
+				break;
+		}
+
+		/*
+		 * Return free'd memory to the global counter when return threshold is
+		 * met or process end.
+		 */
+		if (max_total_bkend_mem && allocation_return >= allocation_return_threshold)
+		{
+			if (ProcGlobal)
+			{
+				volatile PROC_HDR *procglobal = ProcGlobal;
+
+				/* Add to global */
+				pg_atomic_add_fetch_u64(&procglobal->max_total_bkend_mem_bytes,
+										allocation_return);
+
+				/* Restart count */
+				allocation_return = 0;
+			}
+		}
+	}
+
+	return;
+}
+
+/* ----------
+ * pgstat_report_allocated_bytes_increase() -
+ *  Called to report increase in memory allocated for this backend.
+ *
+ * my_allocated_bytes initially points to local memory, making it safe to call
+ * this before pgstats has been initialized.
+ * ----------
+ */
+static inline void
+pgstat_report_allocated_bytes_increase(int64 proc_allocated_bytes,
+									   int pg_allocator_type)
+{
+	/* Remove allocated memory from local allocation allowance */
+	allocation_allowance -= proc_allocated_bytes;
+
+	/* Increase pgstat count of allocated bytes */
+	*my_allocated_bytes += (proc_allocated_bytes);
+
+	/*
+	 * Increase allocator type allocated bytes. NOTE: per hackers dsm memory
+	 * allocations lifespan may exceed process lifespan, so we may implement a
+	 * long lived tracker for it ala max_total_bkend_mem_bytes
+	 */
+	switch (pg_allocator_type)
+	{
+		case PG_ALLOC_ASET:
+			aset_allocated_bytes += (proc_allocated_bytes);
+			break;
+		case PG_ALLOC_DSM:
+			dsm_allocated_bytes += (proc_allocated_bytes);
+			break;
+		case PG_ALLOC_GENERATION:
+			generation_allocated_bytes += (proc_allocated_bytes);
+			break;
+		case PG_ALLOC_SLAB:
+			slab_allocated_bytes += (proc_allocated_bytes);
+			break;
+		case PG_ALLOC_ONSHUTDOWN:
+			break;
+	}
 
 	return;
 }
 
 /* ---------
- * pgstat_zero_my_allocated_bytes() -
+ * pgstat_init_allocated_bytes() -
  *
- * Called to zero out local allocated bytes variable after fork to avoid double
- * counting allocations.
+ * Called to initialize allocated bytes variables after fork and to
+ * avoid double counting allocations.
  * ---------
  */
 static inline void
-pgstat_zero_my_allocated_bytes(void)
+pgstat_init_allocated_bytes(void)
 {
 	*my_allocated_bytes = 0;
 
+	/* If we're limiting backend memory */
+	if (max_total_bkend_mem)
+	{
+		volatile PROC_HDR *procglobal = ProcGlobal;
+		uint64		available_max_total_bkend_mem = 0;
+
+		allocation_return = 0;
+		aset_allocated_bytes = 0;
+		dsm_allocated_bytes = 0;
+		generation_allocated_bytes = 0;
+		slab_allocated_bytes = 0;
+		allocation_allowance = 0;
+
+		/* Account for the initial allocation allowance */
+		while ((available_max_total_bkend_mem = pg_atomic_read_u64(&procglobal->max_total_bkend_mem_bytes)) >= allocation_allowance)
+		{
+			if (pg_atomic_compare_exchange_u64(&procglobal->max_total_bkend_mem_bytes,
+											   &available_max_total_bkend_mem,
+											   available_max_total_bkend_mem -
+											   initial_allocation_allowance))
+			{
+				/*
+				 * On success populate allocation_allowance. Failure here will
+				 * result in the backend's first invocation of
+				 * exceeds_max_total_bkend_mem allocating requested,  default,
+				 * or available memory or result in an out of memory error.
+				 */
+				allocation_allowance = initial_allocation_allowance;
+
+				break;
+			}
+		}
+	}
+
 	return;
 }
 
-- 
2.25.1

0001-Add-tracking-of-backend-memory-allocated-to-pg_stat_.patchtext/x-patch; charset=UTF-8; name=0001-Add-tracking-of-backend-memory-allocated-to-pg_stat_.patchDownload
From 7a1d9cd82e72d3cccb356b8930e32b5154e14e00 Mon Sep 17 00:00:00 2001
From: Reid Thompson <jreidthompson@nc.rr.com>
Date: Thu, 11 Aug 2022 12:01:25 -0400
Subject: [PATCH 1/2] Add tracking of backend memory allocated to
 pg_stat_activity

This new field displays the current bytes of memory allocated to the
backend process. It is updated as memory for the process is
palloc'd/pfree'd. Memory allocated to items on the freelist is included in
the displayed value.  Dynamic shared memory allocations are included
only in the value displayed for the backend that created them, they are
not included in the value for backends that are attached to them to
avoid double counting. On occasion, orphaned memory segments may be
cleaned up on postmaster startup. This may result in decreasing the sum
without a prior increment. We limit the floor of backend_mem_allocated
to zero. Updated pg_stat_activity documentation for the new column.
---
 doc/src/sgml/monitoring.sgml                | 15 ++++
 src/backend/catalog/system_views.sql        |  1 +
 src/backend/postmaster/autovacuum.c         |  6 ++
 src/backend/postmaster/postmaster.c         | 13 ++++
 src/backend/postmaster/syslogger.c          |  3 +
 src/backend/storage/ipc/dsm_impl.c          | 81 +++++++++++++++++++++
 src/backend/utils/activity/backend_status.c | 45 ++++++++++++
 src/backend/utils/adt/pgstatfuncs.c         |  4 +-
 src/backend/utils/mmgr/aset.c               | 17 +++++
 src/backend/utils/mmgr/generation.c         | 15 ++++
 src/backend/utils/mmgr/slab.c               | 23 ++++++
 src/include/catalog/pg_proc.dat             |  6 +-
 src/include/utils/backend_status.h          | 63 +++++++++++++++-
 src/test/regress/expected/rules.out         |  9 ++-
 src/test/regress/expected/stats.out         | 11 +++
 src/test/regress/sql/stats.sql              |  5 +-
 16 files changed, 307 insertions(+), 10 deletions(-)

diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 6249bb50d0..c1c2eb3531 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -963,6 +963,21 @@ postgres   27093  0.0  0.0  30096  2752 ?        Ss   11:34   0:00 postgres: ser
      </para></entry>
     </row>
 
+    <row>
+     <entry role="catalog_table_entry"><para role="column_definition">
+      <structfield>allocated_bytes</structfield> <type>bigint</type>
+     </para>
+     <para>
+      Memory currently allocated to this backend in bytes. This is the balance
+      of bytes allocated and freed by this backend. Dynamic shared memory
+      allocations are included only in the value displayed for the backend that
+      created them, they are not included in the value for backends that are
+      attached to them to avoid double counting. Use <function>pg_size_pretty</function>
+      described in <xref linkend="functions-admin-dbsize"/> to make this value
+      more easily readable.
+     </para></entry>
+    </row>
+
      <row>
       <entry role="catalog_table_entry"><para role="column_definition">
        <structfield>query</structfield> <type>text</type>
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 34ca0e739f..9544e50483 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -863,6 +863,7 @@ CREATE VIEW pg_stat_activity AS
             S.state,
             S.backend_xid,
             s.backend_xmin,
+            S.allocated_bytes,
             S.query_id,
             S.query,
             S.backend_type
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index ff6149a179..59c9bcf8c4 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -407,6 +407,9 @@ StartAutoVacLauncher(void)
 
 #ifndef EXEC_BACKEND
 		case 0:
+			/* Zero allocated bytes to avoid double counting parent allocation */
+			pgstat_zero_my_allocated_bytes();
+
 			/* in postmaster child ... */
 			InitPostmasterChild();
 
@@ -1485,6 +1488,9 @@ StartAutoVacWorker(void)
 
 #ifndef EXEC_BACKEND
 		case 0:
+			/* Zero allocated bytes to avoid double counting parent allocation */
+			pgstat_zero_my_allocated_bytes();
+
 			/* in postmaster child ... */
 			InitPostmasterChild();
 
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 2552327d90..1f09781be8 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -4167,6 +4167,9 @@ BackendStartup(Port *port)
 	{
 		free(bn);
 
+		/* Zero allocated bytes to avoid double counting parent allocation */
+		pgstat_zero_my_allocated_bytes();
+
 		/* Detangle from postmaster */
 		InitPostmasterChild();
 
@@ -5374,6 +5377,11 @@ StartChildProcess(AuxProcType type)
 		MemoryContextDelete(PostmasterContext);
 		PostmasterContext = NULL;
 
+		/* Zero allocated bytes to avoid double counting parent allocation.
+		 * Needs to be after the MemoryContextDelete(PostmasterContext) above.
+		 */
+		pgstat_zero_my_allocated_bytes();
+
 		AuxiliaryProcessMain(type); /* does not return */
 	}
 #endif							/* EXEC_BACKEND */
@@ -5767,6 +5775,11 @@ do_start_bgworker(RegisteredBgWorker *rw)
 			MemoryContextDelete(PostmasterContext);
 			PostmasterContext = NULL;
 
+			/* Zero allocated bytes to avoid double counting parent allocation.
+			 * Needs to be after the MemoryContextDelete(PostmasterContext) above.
+			 */
+			pgstat_zero_my_allocated_bytes();
+
 			StartBackgroundWorker();
 
 			exit(1);			/* should not get here */
diff --git a/src/backend/postmaster/syslogger.c b/src/backend/postmaster/syslogger.c
index 858a2f6b2b..9081ae140f 100644
--- a/src/backend/postmaster/syslogger.c
+++ b/src/backend/postmaster/syslogger.c
@@ -679,6 +679,9 @@ SysLogger_Start(void)
 
 #ifndef EXEC_BACKEND
 		case 0:
+			/* Zero allocated bytes to avoid double counting parent allocation */
+			pgstat_zero_my_allocated_bytes();
+
 			/* in postmaster child ... */
 			InitPostmasterChild();
 
diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c
index f0965c3481..22885c7bd2 100644
--- a/src/backend/storage/ipc/dsm_impl.c
+++ b/src/backend/storage/ipc/dsm_impl.c
@@ -66,6 +66,7 @@
 #include "postmaster/postmaster.h"
 #include "storage/dsm_impl.h"
 #include "storage/fd.h"
+#include "utils/backend_status.h"
 #include "utils/guc.h"
 #include "utils/memutils.h"
 
@@ -232,6 +233,14 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_allocated_bytes(*mapped_size, PG_ALLOC_DECREASE);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && shm_unlink(name) != 0)
@@ -332,6 +341,36 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+	{
+		/*
+		 * Posix creation calls dsm_impl_posix_resize implying that resizing
+		 * occurs or may be added in the future. As implemented
+		 * dsm_impl_posix_resize utilizes fallocate or truncate, passing the
+		 * whole new size as input, growing the allocation as needed (only
+		 * truncate supports shrinking). We update by replacing the old
+		 * allocation with the new.
+		 */
+#if defined(HAVE_POSIX_FALLOCATE) && defined(__linux__)
+		/*
+		 * posix_fallocate does not shrink allocations, adjust only on
+		 * allocation increase.
+		 */
+		if (request_size > *mapped_size)
+		{
+			pgstat_report_allocated_bytes(request_size - *mapped_size,
+										  PG_ALLOC_INCREASE);
+		}
+#else
+		pgstat_report_allocated_bytes(*mapped_size, PG_ALLOC_DECREASE);
+		pgstat_report_allocated_bytes(request_size, PG_ALLOC_INCREASE);
+#endif
+	}
 	*mapped_address = address;
 	*mapped_size = request_size;
 	close(fd);
@@ -537,6 +576,14 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_allocated_bytes(*mapped_size, PG_ALLOC_DECREASE);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && shmctl(ident, IPC_RMID, NULL) < 0)
@@ -584,6 +631,13 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_allocated_bytes(request_size, PG_ALLOC_INCREASE);
 	*mapped_address = address;
 	*mapped_size = request_size;
 
@@ -652,6 +706,13 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 			return false;
 		}
 
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_allocated_bytes(*mapped_size, PG_ALLOC_DECREASE);
 		*impl_private = NULL;
 		*mapped_address = NULL;
 		*mapped_size = 0;
@@ -768,6 +829,12 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 		return false;
 	}
 
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_allocated_bytes(info.RegionSize, PG_ALLOC_INCREASE);
 	*mapped_address = address;
 	*mapped_size = info.RegionSize;
 	*impl_private = hmap;
@@ -812,6 +879,13 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		pgstat_report_allocated_bytes(*mapped_size, PG_ALLOC_DECREASE);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && unlink(name) != 0)
@@ -933,6 +1007,13 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_allocated_bytes(request_size, PG_ALLOC_INCREASE);
 	*mapped_address = address;
 	*mapped_size = request_size;
 
diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c
index 608d01ea0d..7baf2db57d 100644
--- a/src/backend/utils/activity/backend_status.c
+++ b/src/backend/utils/activity/backend_status.c
@@ -49,6 +49,9 @@ int			pgstat_track_activity_query_size = 1024;
 /* exposed so that backend_progress.c can access it */
 PgBackendStatus *MyBEEntry = NULL;
 
+/* Memory allocated to this backend prior to pgstats initialization */
+uint64	local_my_allocated_bytes = 0;
+uint64	*my_allocated_bytes = &local_my_allocated_bytes;
 
 static PgBackendStatus *BackendStatusArray = NULL;
 static char *BackendAppnameBuffer = NULL;
@@ -400,6 +403,15 @@ pgstat_bestart(void)
 	lbeentry.st_progress_command_target = InvalidOid;
 	lbeentry.st_query_id = UINT64CONST(0);
 
+	/* Alter allocation reporting from local_my_allocated_bytes to shared memory */
+	pgstat_set_allocated_bytes_storage(&MyBEEntry->allocated_bytes);
+
+	/* Populate sum of memory allocated prior to pgstats initialization to pgstats
+	 * and zero the local variable.
+	 */
+	lbeentry.allocated_bytes += local_my_allocated_bytes;
+	local_my_allocated_bytes = 0;
+
 	/*
 	 * we don't zero st_progress_param here to save cycles; nobody should
 	 * examine it until st_progress_command has been set to something other
@@ -459,6 +471,11 @@ pgstat_beshutdown_hook(int code, Datum arg)
 {
 	volatile PgBackendStatus *beentry = MyBEEntry;
 
+	/*
+	 * Stop reporting memory allocation changes to &MyBEEntry->allocated_bytes
+	 */
+	pgstat_reset_allocated_bytes_storage();
+
 	/*
 	 * Clear my status entry, following the protocol of bumping st_changecount
 	 * before and after.  We use a volatile pointer here to ensure the
@@ -1194,3 +1211,31 @@ pgstat_clip_activity(const char *raw_activity)
 
 	return activity;
 }
+
+/*
+ * Configure bytes allocated reporting to report allocated bytes to
+ * *allocated_bytes.  *allocated_bytes needs to be valid until
+ * pgstat_set_allocated_bytes_storage() is called.
+ *
+ * Expected to be called during backend startup (in pgstat_bestart), to point
+ * my_allocated_bytes into shared memory.
+ */
+void
+pgstat_set_allocated_bytes_storage(uint64 *new_allocated_bytes)
+{
+	my_allocated_bytes = new_allocated_bytes;
+	*new_allocated_bytes = local_my_allocated_bytes;
+}
+
+/*
+ * Reset allocated bytes storage location.
+ *
+ * Expected to be called during backend shutdown, before the location set up
+ * by pgstat_set_allocated_bytes_storage() becomes invalid.
+ */
+void
+pgstat_reset_allocated_bytes_storage(void)
+{
+	my_allocated_bytes = &local_my_allocated_bytes;
+}
+
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index b61a12382b..35fab203d4 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -303,7 +303,7 @@ pg_stat_get_progress_info(PG_FUNCTION_ARGS)
 Datum
 pg_stat_get_activity(PG_FUNCTION_ARGS)
 {
-#define PG_STAT_GET_ACTIVITY_COLS	30
+#define PG_STAT_GET_ACTIVITY_COLS	31
 	int			num_backends = pgstat_fetch_stat_numbackends();
 	int			curr_backend;
 	int			pid = PG_ARGISNULL(0) ? -1 : PG_GETARG_INT32(0);
@@ -359,6 +359,8 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
 		else
 			nulls[16] = true;
 
+		values[30] = UInt64GetDatum(beentry->allocated_bytes);
+
 		/* Values only available to role member or pg_read_all_stats */
 		if (HAS_PGSTAT_PERMISSIONS(beentry->st_userid))
 		{
diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index 2589941ec4..1a2d86239c 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -47,6 +47,7 @@
 #include "postgres.h"
 
 #include "port/pg_bitutils.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -521,6 +522,7 @@ AllocSetContextCreateInternal(MemoryContext parent,
 						name);
 
 	((MemoryContext) set)->mem_allocated = firstBlockSize;
+	pgstat_report_allocated_bytes(firstBlockSize, PG_ALLOC_INCREASE);
 
 	return (MemoryContext) set;
 }
@@ -543,6 +545,7 @@ AllocSetReset(MemoryContext context)
 	AllocSet	set = (AllocSet) context;
 	AllocBlock	block;
 	Size		keepersize PG_USED_FOR_ASSERTS_ONLY;
+	uint64		deallocation = 0;
 
 	Assert(AllocSetIsValid(set));
 
@@ -585,6 +588,7 @@ AllocSetReset(MemoryContext context)
 		{
 			/* Normal case, release the block */
 			context->mem_allocated -= block->endptr - ((char *) block);
+			deallocation += block->endptr - ((char *) block);
 
 #ifdef CLOBBER_FREED_MEMORY
 			wipe_mem(block, block->freeptr - ((char *) block));
@@ -595,6 +599,7 @@ AllocSetReset(MemoryContext context)
 	}
 
 	Assert(context->mem_allocated == keepersize);
+	pgstat_report_allocated_bytes(deallocation, PG_ALLOC_DECREASE);
 
 	/* Reset block size allocation sequence, too */
 	set->nextBlockSize = set->initBlockSize;
@@ -613,6 +618,7 @@ AllocSetDelete(MemoryContext context)
 	AllocSet	set = (AllocSet) context;
 	AllocBlock	block = set->blocks;
 	Size		keepersize PG_USED_FOR_ASSERTS_ONLY;
+	uint64		deallocation = 0;
 
 	Assert(AllocSetIsValid(set));
 
@@ -651,11 +657,13 @@ AllocSetDelete(MemoryContext context)
 
 				freelist->first_free = (AllocSetContext *) oldset->header.nextchild;
 				freelist->num_free--;
+				deallocation += oldset->header.mem_allocated;
 
 				/* All that remains is to free the header/initial block */
 				free(oldset);
 			}
 			Assert(freelist->num_free == 0);
+			pgstat_report_allocated_bytes(deallocation, PG_ALLOC_DECREASE);
 		}
 
 		/* Now add the just-deleted context to the freelist. */
@@ -672,7 +680,10 @@ AllocSetDelete(MemoryContext context)
 		AllocBlock	next = block->next;
 
 		if (block != set->keeper)
+		{
 			context->mem_allocated -= block->endptr - ((char *) block);
+			deallocation += block->endptr - ((char *) block);
+		}
 
 #ifdef CLOBBER_FREED_MEMORY
 		wipe_mem(block, block->freeptr - ((char *) block));
@@ -685,6 +696,7 @@ AllocSetDelete(MemoryContext context)
 	}
 
 	Assert(context->mem_allocated == keepersize);
+	pgstat_report_allocated_bytes(deallocation + context->mem_allocated, PG_ALLOC_DECREASE);
 
 	/* Finally, free the context header, including the keeper block */
 	free(set);
@@ -734,6 +746,7 @@ AllocSetAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_allocated_bytes(blksize, PG_ALLOC_INCREASE);
 
 		block->aset = set;
 		block->freeptr = block->endptr = ((char *) block) + blksize;
@@ -944,6 +957,7 @@ AllocSetAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_allocated_bytes(blksize, PG_ALLOC_INCREASE);
 
 		block->aset = set;
 		block->freeptr = ((char *) block) + ALLOC_BLOCKHDRSZ;
@@ -1041,6 +1055,7 @@ AllocSetFree(void *pointer)
 			block->next->prev = block->prev;
 
 		set->header.mem_allocated -= block->endptr - ((char *) block);
+		pgstat_report_allocated_bytes(block->endptr - ((char *) block), PG_ALLOC_DECREASE);
 
 #ifdef CLOBBER_FREED_MEMORY
 		wipe_mem(block, block->freeptr - ((char *) block));
@@ -1171,7 +1186,9 @@ AllocSetRealloc(void *pointer, Size size)
 
 		/* updated separately, not to underflow when (oldblksize > blksize) */
 		set->header.mem_allocated -= oldblksize;
+		pgstat_report_allocated_bytes(oldblksize, PG_ALLOC_DECREASE);
 		set->header.mem_allocated += blksize;
+		pgstat_report_allocated_bytes(blksize, PG_ALLOC_INCREASE);
 
 		block->freeptr = block->endptr = ((char *) block) + blksize;
 
diff --git a/src/backend/utils/mmgr/generation.c b/src/backend/utils/mmgr/generation.c
index ebcb61e9b6..b06fb0c6a4 100644
--- a/src/backend/utils/mmgr/generation.c
+++ b/src/backend/utils/mmgr/generation.c
@@ -37,6 +37,7 @@
 
 #include "lib/ilist.h"
 #include "port/pg_bitutils.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -267,6 +268,7 @@ GenerationContextCreate(MemoryContext parent,
 						name);
 
 	((MemoryContext) set)->mem_allocated = firstBlockSize;
+	pgstat_report_allocated_bytes(firstBlockSize, PG_ALLOC_INCREASE);
 
 	return (MemoryContext) set;
 }
@@ -283,6 +285,7 @@ GenerationReset(MemoryContext context)
 {
 	GenerationContext *set = (GenerationContext *) context;
 	dlist_mutable_iter miter;
+	uint64		deallocation = 0;
 
 	Assert(GenerationIsValid(set));
 
@@ -305,9 +308,14 @@ GenerationReset(MemoryContext context)
 		if (block == set->keeper)
 			GenerationBlockMarkEmpty(block);
 		else
+		{
+			deallocation += block->blksize;
 			GenerationBlockFree(set, block);
+		}
 	}
 
+	pgstat_report_allocated_bytes(deallocation, PG_ALLOC_DECREASE);
+
 	/* set it so new allocations to make use of the keeper block */
 	set->block = set->keeper;
 
@@ -328,6 +336,9 @@ GenerationDelete(MemoryContext context)
 {
 	/* Reset to release all releasable GenerationBlocks */
 	GenerationReset(context);
+
+	pgstat_report_allocated_bytes(context->mem_allocated, PG_ALLOC_DECREASE);
+
 	/* And free the context header and keeper block */
 	free(context);
 }
@@ -374,6 +385,7 @@ GenerationAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_allocated_bytes(blksize, PG_ALLOC_INCREASE);
 
 		/* block with a single (used) chunk */
 		block->context = set;
@@ -477,6 +489,7 @@ GenerationAlloc(MemoryContext context, Size size)
 				return NULL;
 
 			context->mem_allocated += blksize;
+			pgstat_report_allocated_bytes(blksize, PG_ALLOC_INCREASE);
 
 			/* initialize the new block */
 			GenerationBlockInit(set, block, blksize);
@@ -729,6 +742,8 @@ GenerationFree(void *pointer)
 	dlist_delete(&block->node);
 
 	set->header.mem_allocated -= block->blksize;
+	pgstat_report_allocated_bytes(block->blksize, PG_ALLOC_DECREASE);
+
 	free(block);
 }
 
diff --git a/src/backend/utils/mmgr/slab.c b/src/backend/utils/mmgr/slab.c
index 33dca0f37c..15d3380640 100644
--- a/src/backend/utils/mmgr/slab.c
+++ b/src/backend/utils/mmgr/slab.c
@@ -69,6 +69,7 @@
 #include "postgres.h"
 
 #include "lib/ilist.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -413,6 +414,13 @@ SlabContextCreate(MemoryContext parent,
 						parent,
 						name);
 
+	/*
+	 * If SlabContextCreate is updated to add context header size to
+	 * context->mem_allocated, then update here and SlabDelete appropriately
+	 */
+	pgstat_report_allocated_bytes(Slab_CONTEXT_HDRSZ(slab->chunksPerBlock),
+								  PG_ALLOC_INCREASE);
+
 	return (MemoryContext) slab;
 }
 
@@ -429,6 +437,7 @@ SlabReset(MemoryContext context)
 	SlabContext *slab = (SlabContext *) context;
 	dlist_mutable_iter miter;
 	int			i;
+	uint64		deallocation = 0;
 
 	Assert(SlabIsValid(slab));
 
@@ -449,6 +458,7 @@ SlabReset(MemoryContext context)
 #endif
 		free(block);
 		context->mem_allocated -= slab->blockSize;
+		deallocation += slab->blockSize;
 	}
 
 	/* walk over blocklist and free the blocks */
@@ -465,9 +475,11 @@ SlabReset(MemoryContext context)
 #endif
 			free(block);
 			context->mem_allocated -= slab->blockSize;
+			deallocation += slab->blockSize;
 		}
 	}
 
+	pgstat_report_allocated_bytes(deallocation, PG_ALLOC_DECREASE);
 	slab->curBlocklistIndex = 0;
 
 	Assert(context->mem_allocated == 0);
@@ -480,8 +492,17 @@ SlabReset(MemoryContext context)
 void
 SlabDelete(MemoryContext context)
 {
+
 	/* Reset to release all the SlabBlocks */
 	SlabReset(context);
+
+	/*
+	 * Until context header allocation is included in context->mem_allocated,
+	 * cast to slab and decrement the header allocation
+	 */
+	pgstat_report_allocated_bytes(Slab_CONTEXT_HDRSZ(((SlabContext *)context)->chunksPerBlock),
+								  PG_ALLOC_DECREASE);
+
 	/* And free the context header */
 	free(context);
 }
@@ -546,6 +567,7 @@ SlabAlloc(MemoryContext context, Size size)
 
 			block->slab = slab;
 			context->mem_allocated += slab->blockSize;
+			pgstat_report_allocated_bytes(slab->blockSize, PG_ALLOC_INCREASE);
 
 			/* use the first chunk in the new block */
 			chunk = SlabBlockGetChunk(slab, block, 0);
@@ -732,6 +754,7 @@ SlabFree(void *pointer)
 #endif
 			free(block);
 			slab->header.mem_allocated -= slab->blockSize;
+			pgstat_report_allocated_bytes(slab->blockSize, PG_ALLOC_DECREASE);
 		}
 
 		/*
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 505595620e..cd3896869e 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -5404,9 +5404,9 @@
   proname => 'pg_stat_get_activity', prorows => '100', proisstrict => 'f',
   proretset => 't', provolatile => 's', proparallel => 'r',
   prorettype => 'record', proargtypes => 'int4',
-  proallargtypes => '{int4,oid,int4,oid,text,text,text,text,text,timestamptz,timestamptz,timestamptz,timestamptz,inet,text,int4,xid,xid,text,bool,text,text,int4,text,numeric,text,bool,text,bool,int4,int8}',
-  proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
-  proargnames => '{pid,datid,pid,usesysid,application_name,state,query,wait_event_type,wait_event,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,backend_type,ssl,sslversion,sslcipher,sslbits,ssl_client_dn,ssl_client_serial,ssl_issuer_dn,gss_auth,gss_princ,gss_enc,leader_pid,query_id}',
+  proallargtypes => '{int4,oid,int4,oid,text,text,text,text,text,timestamptz,timestamptz,timestamptz,timestamptz,inet,text,int4,xid,xid,text,bool,text,text,int4,text,numeric,text,bool,text,bool,int4,int8,int8}',
+  proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
+  proargnames => '{pid,datid,pid,usesysid,application_name,state,query,wait_event_type,wait_event,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,backend_type,ssl,sslversion,sslcipher,sslbits,ssl_client_dn,ssl_client_serial,ssl_issuer_dn,gss_auth,gss_princ,gss_enc,leader_pid,query_id,allocated_bytes}',
   prosrc => 'pg_stat_get_activity' },
 { oid => '3318',
   descr => 'statistics: information about progress of backends running maintenance command',
diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h
index f7bd83113a..754ff0dc62 100644
--- a/src/include/utils/backend_status.h
+++ b/src/include/utils/backend_status.h
@@ -15,6 +15,7 @@
 #include "miscadmin.h"			/* for BackendType */
 #include "storage/backendid.h"
 #include "utils/backend_progress.h"
+#include "common/int.h"
 
 
 /* ----------
@@ -32,6 +33,13 @@ typedef enum BackendState
 	STATE_DISABLED
 } BackendState;
 
+/* Enum helper for reporting memory allocated bytes */
+enum allocation_direction
+{
+	PG_ALLOC_DECREASE = -1,
+	PG_ALLOC_IGNORE,
+	PG_ALLOC_INCREASE,
+};
 
 /* ----------
  * Shared-memory data structures
@@ -169,6 +177,9 @@ typedef struct PgBackendStatus
 
 	/* query identifier, optionally computed using post_parse_analyze_hook */
 	uint64		st_query_id;
+
+	/* Current memory allocated to this backend */
+	uint64		allocated_bytes;
 } PgBackendStatus;
 
 
@@ -293,6 +304,7 @@ extern PGDLLIMPORT int pgstat_track_activity_query_size;
  * ----------
  */
 extern PGDLLIMPORT PgBackendStatus *MyBEEntry;
+extern PGDLLIMPORT uint64 *my_allocated_bytes;
 
 
 /* ----------
@@ -324,7 +336,8 @@ extern const char *pgstat_get_backend_current_activity(int pid, bool checkUser);
 extern const char *pgstat_get_crashed_backend_activity(int pid, char *buffer,
 													   int buflen);
 extern uint64 pgstat_get_my_query_id(void);
-
+extern void pgstat_set_allocated_bytes_storage(uint64 *allocated_bytes);
+extern void pgstat_reset_allocated_bytes_storage(void);
 
 /* ----------
  * Support functions for the SQL-callable functions to
@@ -336,5 +349,53 @@ extern PgBackendStatus *pgstat_fetch_stat_beentry(BackendId beid);
 extern LocalPgBackendStatus *pgstat_fetch_stat_local_beentry(int beid);
 extern char *pgstat_clip_activity(const char *raw_activity);
 
+/* ----------
+ * pgstat_report_allocated_bytes() -
+ *
+ *  Called to report change in memory allocated for this backend.
+ *
+ * my_allocated_bytes initially points to local memory, making it safe to call
+ * this before pgstats has been initialized. allocation_direction is a
+ * positive/negative multiplier enum defined above.
+ * ----------
+ */
+static inline void
+pgstat_report_allocated_bytes(int64 allocated_bytes, int allocation_direction)
+{
+	uint64		temp;
+
+	/*
+	 * Avoid *my_allocated_bytes unsigned integer overflow on
+	 * PG_ALLOC_DECREASE
+	 */
+	if (allocation_direction == PG_ALLOC_DECREASE &&
+		pg_sub_u64_overflow(*my_allocated_bytes, allocated_bytes, &temp))
+	{
+		*my_allocated_bytes = 0;
+		ereport(LOG,
+				errmsg("Backend %d deallocated %lld bytes, exceeding the %llu bytes it is currently reporting allocated. Setting reported to 0.",
+					   MyProcPid, (long long) allocated_bytes,
+					   (unsigned long long) *my_allocated_bytes));
+	}
+	else
+		*my_allocated_bytes += (allocated_bytes) * allocation_direction;
+
+	return;
+}
+
+/* ---------
+ * pgstat_zero_my_allocated_bytes() -
+ *
+ * Called to zero out local allocated bytes variable after fork to avoid double
+ * counting allocations.
+ * ---------
+ */
+static inline void
+pgstat_zero_my_allocated_bytes(void)
+{
+	*my_allocated_bytes = 0;
+
+	return;
+}
 
 #endif							/* BACKEND_STATUS_H */
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index e953d1f515..271648619a 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1756,10 +1756,11 @@ pg_stat_activity| SELECT s.datid,
     s.state,
     s.backend_xid,
     s.backend_xmin,
+    s.allocated_bytes,
     s.query_id,
     s.query,
     s.backend_type
-   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, allocated_bytes)
      LEFT JOIN pg_database d ON ((s.datid = d.oid)))
      LEFT JOIN pg_authid u ON ((s.usesysid = u.oid)));
 pg_stat_all_indexes| SELECT c.oid AS relid,
@@ -1874,7 +1875,7 @@ pg_stat_gssapi| SELECT pid,
     gss_auth AS gss_authenticated,
     gss_princ AS principal,
     gss_enc AS encrypted
-   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, allocated_bytes)
   WHERE (client_port IS NOT NULL);
 pg_stat_io| SELECT backend_type,
     io_object,
@@ -2067,7 +2068,7 @@ pg_stat_replication| SELECT s.pid,
     w.sync_priority,
     w.sync_state,
     w.reply_time
-   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, allocated_bytes)
      JOIN pg_stat_get_wal_senders() w(pid, state, sent_lsn, write_lsn, flush_lsn, replay_lsn, write_lag, flush_lag, replay_lag, sync_priority, sync_state, reply_time) ON ((s.pid = w.pid)))
      LEFT JOIN pg_authid u ON ((s.usesysid = u.oid)));
 pg_stat_replication_slots| SELECT s.slot_name,
@@ -2101,7 +2102,7 @@ pg_stat_ssl| SELECT pid,
     ssl_client_dn AS client_dn,
     ssl_client_serial AS client_serial,
     ssl_issuer_dn AS issuer_dn
-   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id)
+   FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, query_id, allocated_bytes)
   WHERE (client_port IS NOT NULL);
 pg_stat_subscription| SELECT su.oid AS subid,
     su.subname,
diff --git a/src/test/regress/expected/stats.out b/src/test/regress/expected/stats.out
index 937b2101b3..2a848c02a1 100644
--- a/src/test/regress/expected/stats.out
+++ b/src/test/regress/expected/stats.out
@@ -1354,4 +1354,15 @@ SELECT :io_stats_post_reset < :io_stats_pre_reset;
  t
 (1 row)
 
+-- ensure that allocated_bytes exist for backends
+SELECT allocated_bytes > 0 AS result FROM pg_stat_activity WHERE backend_type
+IN ('checkpointer', 'background writer', 'walwriter', 'autovacuum launcher');
+ result 
+--------
+ t
+ t
+ t
+ t
+(4 rows)
+
 -- End of Stats Test
diff --git a/src/test/regress/sql/stats.sql b/src/test/regress/sql/stats.sql
index 74e592aa8a..568560c361 100644
--- a/src/test/regress/sql/stats.sql
+++ b/src/test/regress/sql/stats.sql
@@ -535,7 +535,6 @@ SET enable_seqscan TO on;
 SELECT pg_stat_get_replication_slot(NULL);
 SELECT pg_stat_get_subscription_stats(NULL);
 
-
 -- Test that the following operations are tracked in pg_stat_io:
 -- - reads of target blocks into shared buffers
 -- - writes of shared buffers to permanent storage
@@ -678,4 +677,8 @@ SELECT sum(evictions) + sum(reuses) + sum(extends) + sum(fsyncs) + sum(reads) +
   FROM pg_stat_io \gset
 SELECT :io_stats_post_reset < :io_stats_pre_reset;
 
+-- ensure that allocated_bytes exist for backends
+SELECT allocated_bytes > 0 AS result FROM pg_stat_activity WHERE backend_type
+IN ('checkpointer', 'background writer', 'walwriter', 'autovacuum launcher');
+
 -- End of Stats Test
-- 
2.25.1

#32Andres Freund
andres@anarazel.de
In reply to: Noname (#31)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On 2023-03-02 14:41:26 -0500, reid.thompson@crunchydata.com wrote:

Patch has been rebased to master.

Quite a few prior review comments seem to not have been
addressed. There's not much point in posting new versions without that.

I think there's zero chance 0002 can make it into 16. If 0001 is cleaned
up, I can see a path.

#33Noname
reid.thompson@crunchydata.com
In reply to: Andres Freund (#32)
2 attachment(s)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

Updated patches attached.

====================================================================
pg-stat-activity-backend-memory-allocated
====================================================================
DSM allocations created by a process and not destroyed prior to it's exit are
considered long lived and are tracked in global_dsm_allocated_bytes.

created 2 new system views (see below):

pg_stat_global_memory_allocation view displays datid, shared_memory_size,
shared_memory_size_in_huge_pages, global_dsm_allocated_bytes. shared_memory_size
and shared_memory_size_in_huge_pages display the calculated read only values for
these GUCs.

pg_stat_memory_allocation view
Migrated allocated_bytes out of pg_stat_activity view into this view.
pg_stat_memory_allocation also contains a breakdown of allocation by allocator
type (aset, dsm, generation, slab). View displays datid, pid, allocated_bytes,
aset_allocated_bytes, dsm_allocated_bytes, generation_allocated_bytes,
slab_allocated_bytes by process.

Reduced calls to initialize allocation counters by moving
intialization call into InitPostmasterChild.

postgres=# select * from pg_stat_global_memory_allocation;
datid | shared_memory_size | shared_memory_size_in_huge_pages | global_dsm_allocated_bytes
-------+--------------------+----------------------------------+----------------------------
5 | 192MB | 96 | 1048576
(1 row)

postgres=# select * from pg_stat_memory_allocation;
datid | pid | allocated_bytes | aset_allocated_bytes | dsm_allocated_bytes | generation_allocated_bytes | slab_allocated_bytes
-------+--------+-----------------+----------------------+---------------------+----------------------------+----------------------
| 981842 | 771512 | 771512 | 0 | 0 | 0
| 981843 | 736696 | 736696 | 0 | 0 | 0
5 | 981913 | 4274792 | 4274792 | 0 | 0 | 0
| 981838 | 107216 | 107216 | 0 | 0 | 0
| 981837 | 123600 | 123600 | 0 | 0 | 0
| 981841 | 107216 | 107216 | 0 | 0 | 0
(6 rows)

postgres=# select ps.datid, ps.pid, state,application_name,backend_type, pa.* from pg_stat_activity ps join pg_stat_memory_allocation pa on (pa.pid = ps.pid) order by dsm_allocated_bytes, pa.pid;
datid | pid | state | application_name | backend_type | datid | pid | allocated_bytes | aset_allocated_bytes | dsm_allocated_bytes | generation_allocated_bytes | slab_allocated_bytes
-------+--------+--------+------------------+------------------------------+-------+--------+-----------------+----------------------+---------------------+----------------------------+----------------------
| 981837 | | | checkpointer | | 981837 | 123600 | 123600 | 0 | 0 | 0
| 981838 | | | background writer | | 981838 | 107216 | 107216 | 0 | 0 | 0
| 981841 | | | walwriter | | 981841 | 107216 | 107216 | 0 | 0 | 0
| 981842 | | | autovacuum launcher | | 981842 | 771512 | 771512 | 0 | 0 | 0
| 981843 | | | logical replication launcher | | 981843 | 736696 | 736696 | 0 | 0 | 0
5 | 981913 | active | psql | client backend | 5 | 981913 | 5390864 | 5382824 | 0 | 8040 | 0
(6 rows)

====================================================================
dev-max-memory
====================================================================
Include shared_memory_size in max_total_backend_memory calculations.
max_total_backend_memory is reduced by shared_memory_size at startup.
Local allowance is refilled when consumed from global
max_total_bkend_mem_bytes_available.

pg_stat_global_memory_allocation view
add columns max_total_backend_memory_bytes, max_total_bkend_mem_bytes_available.
max_total_backend_memory_bytes displays a byte representation of
max_total_backend_memory. max_total_bkend_mem_bytes_available tracks the balance
of max_total_backend_memory_bytes available to backend processes.

postgres=# select * from pg_stat_global_memory_allocation;
datid | shared_memory_size | shared_memory_size_in_huge_pages | max_total_backend_memory_bytes | max_total_bkend_mem_bytes_available | global_dsm_allocated_bytes
-------+--------------------+----------------------------------+--------------------------------+-------------------------------------+----------------------------
5 | 192MB | 96 | 2147483648 | 1874633712 | 5242880
(1 row)

postgres=# select * from pg_stat_memory_allocation ;
datid | pid | allocated_bytes | aset_allocated_bytes | dsm_allocated_bytes | generation_allocated_bytes | slab_allocated_bytes
-------+--------+-----------------+----------------------+---------------------+----------------------------+----------------------
| 534528 | 812472 | 812472 | 0 | 0 | 0
| 534529 | 736696 | 736696 | 0 | 0 | 0
5 | 556271 | 4458088 | 4458088 | 0 | 0 | 0
5 | 534942 | 1298680 | 1298680 | 0 | 0 | 0
5 | 709283 | 7985464 | 7985464 | 0 | 0 | 0
5 | 718693 | 8809240 | 8612504 | 196736 | 0 | 0
5 | 752113 | 25803192 | 25803192 | 0 | 0 | 0
5 | 659886 | 9042232 | 9042232 | 0 | 0 | 0
| 534525 | 2491088 | 2491088 | 0 | 0 | 0
| 534524 | 4465360 | 4465360 | 0 | 0 | 0
| 534527 | 107216 | 107216 | 0 | 0 | 0
(11 rows)

postgres=# select ps.datid, ps.pid, state,application_name,backend_type, pa.* from pg_stat_activity ps join pg_stat_memory_allocation pa on (pa.pid = ps.pid) order by dsm_allocated_bytes, pa.pid;
datid | pid | state | application_name | backend_type | datid | pid | allocated_bytes | aset_allocated_bytes | dsm_allocated_bytes | generation_allocated_bytes | slab_allocated_bytes
-------+--------+--------+------------------+------------------------------+-------+--------+-----------------+----------------------+---------------------+----------------------------+----------------------
| 534524 | | | checkpointer | | 534524 | 4465360 | 4465360 | 0 | 0 | 0
| 534525 | | | background writer | | 534525 | 2491088 | 2491088 | 0 | 0 | 0
| 534527 | | | walwriter | | 534527 | 107216 | 107216 | 0 | 0 | 0
| 534528 | | | autovacuum launcher | | 534528 | 812472 | 812472 | 0 | 0 | 0
| 534529 | | | logical replication launcher | | 534529 | 736696 | 736696 | 0 | 0 | 0
5 | 534942 | idle | psql | client backend | 5 | 534942 | 1298680 | 1298680 | 0 | 0 | 0
5 | 556271 | active | psql | client backend | 5 | 556271 | 4866576 | 4858536 | 0 | 8040 | 0
5 | 659886 | active | | autovacuum worker | 5 | 659886 | 8993080 | 8993080 | 0 | 0 | 0
5 | 709283 | active | | autovacuum worker | 5 | 709283 | 7928120 | 7928120 | 0 | 0 | 0
5 | 752113 | active | | autovacuum worker | 5 | 752113 | 27935608 | 27935608 | 0 | 0 | 0
5 | 718693 | active | psql | client backend | 5 | 718693 | 8669976 | 8473240 | 196736 | 0 | 0
(11 rows)

Attachments:

0002-Add-the-ability-to-limit-the-amount-of-memory-that-c.patchtext/x-patch; charset=UTF-8; name=0002-Add-the-ability-to-limit-the-amount-of-memory-that-c.patchDownload
From 4dd47f04764b5df9c3962d9fdb4096398bf85dfd Mon Sep 17 00:00:00 2001
From: Reid Thompson <jreidthompson@nc.rr.com>
Date: Sat, 4 Jun 2022 22:23:59 -0400
Subject: [PATCH 2/2] Add the ability to limit the amount of memory that can be
 allocated to backends.

This builds on the work that adds backend memory allocated tracking.

Add GUC variable max_total_backend_memory.

Specifies a limit to the amount of memory (in MB) that may be allocated to
backends in total (i.e. this is not a per user or per backend limit). If unset,
or set to 0 it is disabled. It is intended as a resource to help avoid the OOM
killer on LINUX and manage resources in general. A backend request that would
exhaust max_total_backend_memory memory will be denied with an out of memory
error causing that backend's current query/transaction to fail.  Further
requests will not be allocated until dropping below the limit. Keep this in
mind when setting this value. Due to the dynamic nature of memory allocations,
this limit is not exact. This limit does not affect auxiliary backend
processes. Backend memory allocations are displayed in the
pg_stat_memory_allocation and pg_stat_global_memory_allocation views.
---
 doc/src/sgml/config.sgml                      |  28 +++
 doc/src/sgml/monitoring.sgml                  |  48 ++++-
 src/backend/catalog/system_views.sql          |   6 +-
 src/backend/storage/ipc/dsm_impl.c            |  18 ++
 src/backend/storage/lmgr/proc.c               |  45 +++++
 src/backend/utils/activity/backend_status.c   | 173 ++++++++++++++++++
 src/backend/utils/adt/pgstatfuncs.c           |  16 +-
 src/backend/utils/hash/dynahash.c             |   3 +-
 src/backend/utils/misc/guc_tables.c           |  11 ++
 src/backend/utils/misc/postgresql.conf.sample |   3 +
 src/backend/utils/mmgr/aset.c                 |  33 ++++
 src/backend/utils/mmgr/generation.c           |  16 ++
 src/backend/utils/mmgr/slab.c                 |  16 +-
 src/include/catalog/pg_proc.dat               |   6 +-
 src/include/storage/proc.h                    |   7 +
 src/include/utils/backend_status.h            |  87 ++++++++-
 src/test/regress/expected/rules.out           |   4 +-
 17 files changed, 499 insertions(+), 21 deletions(-)

diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 481f93cea1..9f37f6f070 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -2113,6 +2113,34 @@ include_dir 'conf.d'
       </listitem>
      </varlistentry>
 
+     <varlistentry id="guc-max-total-backend-memory" xreflabel="max_total_backend_memory">
+      <term><varname>max_total_backend_memory</varname> (<type>integer</type>)
+      <indexterm>
+       <primary><varname>max_total_backend_memory</varname> configuration parameter</primary>
+      </indexterm>
+      </term>
+      <listitem>
+       <para>
+        Specifies a limit to the amount of memory (MB) that may be allocated to
+        backends in total (i.e. this is not a per user or per backend limit).
+        If unset, or set to 0 it is disabled.  At databse startup
+        max_total_backend_memory is reduced by shared_memory_size_mb 
+        (shared buffers). Each backend process is intialized with a 1MB local
+        allowance which also reduces max_total_bkend_mem_bytes_available. Keep
+        this in mind when setting this value. A backend request that would
+        exhaust the limit will be denied with an out of memory error causing
+        that backend's current query/transaction to fail. Further requests will
+        not be allocated until dropping below the limit.  This limit does not
+        affect auxiliary backend processes
+        <xref linkend="glossary-auxiliary-proc"/>. Backend memory allocations
+        (<varname>allocated_bytes</varname>) are displayed in the
+        <link linkend="monitoring-pg-stat-memory-allocation-view"><structname>pg_stat_memory_allocation</structname></link>
+        view.  Due to the dynamic nature of memory allocations, this limit is
+        not exact.
+       </para>
+      </listitem>
+     </varlistentry>
+
      </variablelist>
      </sect2>
 
diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index d943821071..a67bd484f2 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -5643,9 +5643,13 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
   <para>
    The <structname>pg_stat_memory_allocation</structname> view will have one
    row per server process, showing information related to the current memory
-   allocation of that process. Use <function>pg_size_pretty</function>
-   described in <xref linkend="functions-admin-dbsize"/> to make these values
-   more easily readable.
+   allocation of that process in total and by allocator type. Dynamic shared
+   memory allocations are included only in the value displayed for the backend
+   that created them, they are not included in the value for backends that are
+   attached to them to avoid double counting.  Use
+   <function>pg_size_pretty</function> described in
+   <xref linkend="functions-admin-dbsize"/> to make these values more easily
+   readable.
   </para>
 
   <table id="pg-stat-memory-allocation-view" xreflabel="pg_stat_memory_allocation">
@@ -5687,10 +5691,7 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
       </para>
      <para>
       Memory currently allocated to this backend in bytes. This is the balance
-      of bytes allocated and freed by this backend. Dynamic shared memory
-      allocations are included only in the value displayed for the backend that
-      created them, they are not included in the value for backends that are
-      attached to them to avoid double counting.
+      of bytes allocated and freed by this backend.
      </para></entry>
      </row>
 
@@ -5803,6 +5804,39 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
      </para></entry>
      </row>
 
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>max_total_backend_memory_bytes</structfield> <type>bigint</type>
+      </para>
+     <para>
+      Reports the user defined backend maximum allowed shared memory in bytes.
+      0 if disabled or not set. See
+      <xref linkend="guc-max-total-backend-memory"/>.
+     </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>max_total_bkend_mem_bytes_available</structfield> <type>bigint</type>
+      </para>
+     <para>
+      Tracks max_total_backend_memory (in bytes) available for allocation. At
+      database startup, max_total_bkend_mem_bytes_available is reduced by the
+      byte equivalent of shared_memory_size_mb. Each backend process is
+      intialized with a 1MB local allowance which also reduces
+      max_total_bkend_mem_bytes_available. A process's allocation requests
+      reduce it's local allowance. If a process's allocation request exceeds
+      it's remaining allowance, an attempt is made to refill the local
+      allowance from max_total_bkend_mem_bytes_available. If the refill request
+      fails, then the requesting process will fail with an out of memory error
+      resulting in the cancellation of that process's active query/transaction.
+      The default refill allocation quantity is 1MB.  If a request is greater
+      than 1MB, an attempt will be made to allocate the full amount. If
+      max_total_backend_memory is disabled, this will be -1.
+      <xref linkend="guc-max-total-backend-memory"/>.
+     </para></entry>
+     </row>
+
      <row>
       <entry role="catalog_table_entry"><para role="column_definition">
        <structfield>global_dsm_allocated_bytes</structfield> <type>bigint</type>
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 4bbd992311..86bde2a44c 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -1346,8 +1346,10 @@ CREATE VIEW pg_stat_memory_allocation AS
 CREATE VIEW pg_stat_global_memory_allocation AS
     SELECT
         S.datid AS datid,
-        current_setting('shared_memory_size'::text, true) AS shared_memory_size,
-        (current_setting('shared_memory_size_in_huge_pages'::text, true))::integer AS shared_memory_size_in_huge_pages,
+        current_setting('shared_memory_size', true) as shared_memory_size,
+        (current_setting('shared_memory_size_in_huge_pages', true))::integer as shared_memory_size_in_huge_pages,
+        pg_size_bytes(current_setting('max_total_backend_memory', true)) as max_total_backend_memory_bytes,
+        S.max_total_bkend_mem_bytes_available,
         S.global_dsm_allocated_bytes
     FROM pg_stat_get_global_memory_allocation() AS S
         LEFT JOIN pg_database AS D ON (S.datid = D.oid);
diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c
index 16e2bded59..68780de717 100644
--- a/src/backend/storage/ipc/dsm_impl.c
+++ b/src/backend/storage/ipc/dsm_impl.c
@@ -254,6 +254,16 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 		return true;
 	}
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+	{
+		ereport(elevel,
+				(errcode_for_dynamic_shared_memory(),
+				 errmsg("out of memory for segment \"%s\" - exceeds max_total_backend_memory: %m",
+						name)));
+		return false;
+	}
+
 	/*
 	 * Create new segment or open an existing one for attach.
 	 *
@@ -522,6 +532,10 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 		int			flags = IPCProtection;
 		size_t		segsize;
 
+		/* Do not exceed maximum allowed memory allocation */
+		if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+			return false;
+
 		/*
 		 * Allocate the memory BEFORE acquiring the resource, so that we don't
 		 * leak the resource if memory allocation fails.
@@ -716,6 +730,10 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 		return true;
 	}
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+		return false;
+
 	/* Create new segment or open an existing one for attach. */
 	if (op == DSM_OP_CREATE)
 	{
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index d86fbdfd9b..80db49d775 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -51,6 +51,7 @@
 #include "storage/procsignal.h"
 #include "storage/spin.h"
 #include "storage/standby.h"
+#include "utils/guc.h"
 #include "utils/timeout.h"
 #include "utils/timestamp.h"
 
@@ -182,6 +183,50 @@ InitProcGlobal(void)
 	pg_atomic_init_u32(&ProcGlobal->clogGroupFirst, INVALID_PGPROCNO);
 	pg_atomic_init_u64(&ProcGlobal->global_dsm_allocation, 0);
 
+	/* Setup backend memory limiting if configured */
+	if (max_total_bkend_mem > 0)
+	{
+		/*
+		 * Convert max_total_bkend_mem to bytes, account for shared_memory_size,
+		 * and initialize max_total_bkend_mem_bytes.
+		 */
+		int result = 0;
+
+		/* Get integer value of shared_memory_size */
+		if (parse_int(GetConfigOption("shared_memory_size", true, false), &result, 0, NULL))
+		{
+			/*
+			 * Error on startup if backend memory limit is less than shared
+			 * memory size. Warn on startup if backend memory available is less
+			 * than arbitrarily picked value of 100MB.
+			 */
+
+			if (max_total_bkend_mem - result <= 0)
+			{
+				ereport(ERROR,
+						errmsg("configured max_total_backend_memory %dMB is <= shared_memory_size %dMB",
+							   max_total_bkend_mem, result),
+						errhint("Disable or increase the configuration parameter \"max_total_backend_memory\"."));
+			}
+			else if (max_total_bkend_mem - result <= 100)
+			{
+				ereport(WARNING,
+						errmsg("max_total_backend_memory %dMB - shared_memory_size %dMB is <= 100MB",
+							   max_total_bkend_mem, result),
+						errhint("Consider increasing the configuration parameter \"max_total_backend_memory\"."));
+			}
+
+			/*
+			 * Account for shared memory size and initialize
+			 * max_total_bkend_mem_bytes.
+			 */
+			pg_atomic_init_u64(&ProcGlobal->max_total_bkend_mem_bytes,
+							   max_total_bkend_mem * 1024 * 1024 - result * 1024 * 1024);
+		}
+		else
+			ereport(ERROR, errmsg("max_total_backend_memory initialization is unable to parse shared_memory_size"));
+	}
+
 	/*
 	 * Create and initialize all the PGPROC structures we'll need.  There are
 	 * five separate consumers: (1) normal backends, (2) autovacuum workers
diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c
index f921c4bbde..a4f9c6eb35 100644
--- a/src/backend/utils/activity/backend_status.c
+++ b/src/backend/utils/activity/backend_status.c
@@ -45,6 +45,12 @@
 bool		pgstat_track_activities = false;
 int			pgstat_track_activity_query_size = 1024;
 
+/*
+ * Max backend memory allocation allowed (MB). 0 = disabled.
+ * Centralized bucket ProcGlobal->max_total_bkend_mem is initialized
+ * as a byte representation of this value in InitProcGlobal().
+ */
+int			max_total_bkend_mem = 0;
 
 /* exposed so that backend_progress.c can access it */
 PgBackendStatus *MyBEEntry = NULL;
@@ -68,6 +74,31 @@ uint64	   *my_generation_allocated_bytes = &local_my_generation_allocated_bytes;
 uint64		local_my_slab_allocated_bytes = 0;
 uint64	   *my_slab_allocated_bytes = &local_my_slab_allocated_bytes;
 
+/*
+ * Define initial allocation allowance for a backend.
+ *
+ * NOTE: initial_allocation_allowance && allocation_allowance_refill_qty
+ * may be candidates for future GUC variables. Arbitrary 1MB selected initially.
+ */
+uint64		initial_allocation_allowance = 1024 * 1024;
+uint64		allocation_allowance_refill_qty = 1024 * 1024;
+
+/*
+ * Local counter to manage shared memory allocations. At backend startup, set to
+ * initial_allocation_allowance via pgstat_init_allocated_bytes(). Decrease as
+ * memory is malloc'd. When exhausted, atomically refill if available from
+ * ProcGlobal->max_total_bkend_mem via exceeds_max_total_bkend_mem().
+ */
+uint64		allocation_allowance = 0;
+
+/*
+ * Local counter of free'd shared memory. Return to global
+ * max_total_bkend_mem when return threshold is met. Arbitrary 1MB bytes
+ * selected initially.
+ */
+uint64		allocation_return = 0;
+uint64		allocation_return_threshold = 1024 * 1024;
+
 static PgBackendStatus *BackendStatusArray = NULL;
 static char *BackendAppnameBuffer = NULL;
 static char *BackendClientHostnameBuffer = NULL;
@@ -1271,6 +1302,8 @@ pgstat_set_allocated_bytes_storage(uint64 *allocated_bytes,
 
 	my_slab_allocated_bytes = slab_allocated_bytes;
 	*slab_allocated_bytes = local_my_slab_allocated_bytes;
+
+	return;
 }
 
 /*
@@ -1294,6 +1327,23 @@ pgstat_reset_allocated_bytes_storage(void)
 								*my_dsm_allocated_bytes);
 	}
 
+	/*
+	 * When limiting maximum backend memory, return this backend's memory
+	 * allocations to global.
+	 */
+	if (max_total_bkend_mem)
+	{
+		volatile PROC_HDR *procglobal = ProcGlobal;
+
+		pg_atomic_add_fetch_u64(&procglobal->max_total_bkend_mem_bytes,
+								*my_allocated_bytes + allocation_allowance +
+								allocation_return);
+
+		/* Reset memory allocation variables */
+		allocation_allowance = 0;
+		allocation_return = 0;
+	}
+
 	/* Reset memory allocation variables */
 	*my_allocated_bytes = local_my_allocated_bytes = 0;
 	*my_aset_allocated_bytes = local_my_aset_allocated_bytes = 0;
@@ -1307,4 +1357,127 @@ pgstat_reset_allocated_bytes_storage(void)
 	my_dsm_allocated_bytes = &local_my_dsm_allocated_bytes;
 	my_generation_allocated_bytes = &local_my_generation_allocated_bytes;
 	my_slab_allocated_bytes = &local_my_slab_allocated_bytes;
+
+	return;
+}
+
+/*
+ * Determine if allocation request will exceed max backend memory allowed.
+ * Do not apply to auxiliary processes.
+ * Refill allocation request bucket when needed/possible.
+ */
+bool
+exceeds_max_total_bkend_mem(uint64 allocation_request)
+{
+	bool		result = false;
+
+	/*
+	 * When limiting maximum backend memory, attempt to refill allocation
+	 * request bucket if needed.
+	 */
+	if (max_total_bkend_mem && allocation_request > allocation_allowance)
+	{
+		volatile PROC_HDR *procglobal = ProcGlobal;
+		uint64		available_max_total_bkend_mem = 0;
+		bool		sts = false;
+
+		/*
+		 * If allocation request is larger than memory refill quantity then
+		 * attempt to increase allocation allowance with requested amount,
+		 * otherwise fall through. If this refill fails we do not have enough
+		 * memory to meet the request.
+		 */
+		if (allocation_request >= allocation_allowance_refill_qty)
+		{
+			while ((available_max_total_bkend_mem = pg_atomic_read_u64(&procglobal->max_total_bkend_mem_bytes)) >= allocation_request)
+			{
+				if ((result = pg_atomic_compare_exchange_u64(&procglobal->max_total_bkend_mem_bytes,
+															 &available_max_total_bkend_mem,
+															 available_max_total_bkend_mem - allocation_request)))
+				{
+					allocation_allowance = allocation_allowance + allocation_request;
+					break;
+				}
+			}
+
+			/*
+			 * If the atomic exchange fails, we do not have enough reserve
+			 * memory to meet the request. Negate result to return the proper
+			 * value.
+			 */
+			return !result;
+		}
+
+		/*
+		 * Attempt to increase allocation allowance by memory refill quantity.
+		 * If available memory is/becomes less than memory refill quantity,
+		 * fall through to attempt to allocate remaining available memory.
+		 */
+		while ((available_max_total_bkend_mem = pg_atomic_read_u64(&procglobal->max_total_bkend_mem_bytes)) >= allocation_allowance_refill_qty)
+		{
+			if ((sts = pg_atomic_compare_exchange_u64(&procglobal->max_total_bkend_mem_bytes,
+													  &available_max_total_bkend_mem,
+													  available_max_total_bkend_mem - allocation_allowance_refill_qty)))
+			{
+				allocation_allowance = allocation_allowance + allocation_allowance_refill_qty;
+				break;
+			}
+		}
+
+		if (!sts)
+		{
+			/*
+			 * If available_max_total_bkend_mem is 0, no memory is currently
+			 * available to refill with, otherwise attempt to allocate
+			 * remaining memory available if it exceeds the requested amount
+			 * or the requested amount if more than requested amount gets
+			 * returned while looping.
+			 */
+			while ((available_max_total_bkend_mem = (int64) pg_atomic_read_u64(&procglobal->max_total_bkend_mem_bytes)) > 0)
+			{
+				uint64		newval = 0;
+
+				/*
+				 * If available memory is less than requested allocation we
+				 * cannot fulfil request.
+				 */
+				if (available_max_total_bkend_mem < allocation_request)
+					break;
+
+				/*
+				 * If we happen to loop and a large chunk of memory has been
+				 * returned to global, allocate request amount only.
+				 */
+				if (available_max_total_bkend_mem > allocation_request)
+					newval = available_max_total_bkend_mem - allocation_request;
+
+				/* Allocate memory */
+				if ((sts = pg_atomic_compare_exchange_u64(&procglobal->max_total_bkend_mem_bytes,
+														  &available_max_total_bkend_mem,
+														  newval)))
+				{
+					allocation_allowance = allocation_allowance +
+						newval == 0 ? available_max_total_bkend_mem : allocation_request;
+
+					break;
+				}
+			}
+		}
+
+		/*
+		 * If refill is not successful, we return true, memory limit exceeded
+		 */
+		if (!sts)
+			result = true;
+	}
+
+	/*
+	 * Exclude auxiliary processes from the check. Return false. While we want
+	 * to exclude them from the check, we do not want to exclude them from the
+	 * above allocation handling.
+	 */
+	if (MyAuxProcType != NotAnAuxProcess)
+		result = false;
+
+	return result;
 }
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index be973b1bdb..73cf3be4e3 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -2128,7 +2128,7 @@ pg_stat_get_memory_allocation(PG_FUNCTION_ARGS)
 Datum
 pg_stat_get_global_memory_allocation(PG_FUNCTION_ARGS)
 {
-#define PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS	2
+#define PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS	3
 	TupleDesc	tupdesc;
 	Datum		values[PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS] = {0};
 	bool		nulls[PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS] = {0};
@@ -2138,15 +2138,23 @@ pg_stat_get_global_memory_allocation(PG_FUNCTION_ARGS)
 	tupdesc = CreateTemplateTupleDesc(PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 1, "datid",
 					   OIDOID, -1, 0);
-	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "global_dsm_allocated_bytes",
+	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "max_total_bkend_mem_bytes_available",
+					   INT8OID, -1, 0);
+	TupleDescInitEntry(tupdesc, (AttrNumber) 3, "global_dsm_allocated_bytes",
 					   INT8OID, -1, 0);
 	BlessTupleDesc(tupdesc);
 
 	/* datid */
 	values[0] = ObjectIdGetDatum(MyDatabaseId);
 
-	/* get global_dsm_allocated_bytes */
-	values[1] = Int64GetDatum(pg_atomic_read_u64(&procglobal->global_dsm_allocation));
+	/* Get max_total_bkend_mem_bytes - return -1 if disabled */
+	if (max_total_bkend_mem == 0)
+		values[1] = Int64GetDatum(-1);
+	else
+		values[1] = Int64GetDatum(pg_atomic_read_u64(&procglobal->max_total_bkend_mem_bytes));
+
+	/* Get global_dsm_allocated_bytes */
+	values[2] = Int64GetDatum(pg_atomic_read_u64(&procglobal->global_dsm_allocation));
 
 	/* Returns the record as Datum */
 	PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls)));
diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c
index 012d4a0b1f..cd68e5265a 100644
--- a/src/backend/utils/hash/dynahash.c
+++ b/src/backend/utils/hash/dynahash.c
@@ -104,7 +104,6 @@
 #include "utils/dynahash.h"
 #include "utils/memutils.h"
 
-
 /*
  * Constants
  *
@@ -359,7 +358,6 @@ hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
 	Assert(flags & HASH_ELEM);
 	Assert(info->keysize > 0);
 	Assert(info->entrysize >= info->keysize);
-
 	/*
 	 * For shared hash tables, we have a local hash header (HTAB struct) that
 	 * we allocate in TopMemoryContext; all else is in shared memory.
@@ -377,6 +375,7 @@ hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
 	}
 	else
 	{
+		/* Set up to allocate the hash header */
 		/* Create the hash table's private memory context */
 		if (flags & HASH_CONTEXT)
 			CurrentDynaHashCxt = info->hcxt;
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index 1c0583fe26..639b63138b 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -3468,6 +3468,17 @@ struct config_int ConfigureNamesInt[] =
 		NULL, NULL, NULL
 	},
 
+	{
+		{"max_total_backend_memory", PGC_SU_BACKEND, RESOURCES_MEM,
+			gettext_noop("Restrict total backend memory allocations to this max."),
+			gettext_noop("0 turns this feature off."),
+			GUC_UNIT_MB
+		},
+		&max_total_bkend_mem,
+		0, 0, INT_MAX,
+		NULL, NULL, NULL
+	},
+
 	/* End-of-list marker */
 	{
 		{NULL, 0, 0, NULL, NULL}, NULL, 0, 0, 0, NULL, NULL, NULL
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index d06074b86f..bc2d449c87 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -156,6 +156,9 @@
 					#   mmap
 					# (change requires restart)
 #min_dynamic_shared_memory = 0MB	# (change requires restart)
+#max_total_backend_memory = 0MB		# Restrict total backend memory allocations
+									# to this max (in MB). 0 turns this feature
+									# off.
 
 # - Disk -
 
diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index f3f5945fdf..4a83a2f60f 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -440,6 +440,18 @@ AllocSetContextCreateInternal(MemoryContext parent,
 	else
 		firstBlockSize = Max(firstBlockSize, initBlockSize);
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (exceeds_max_total_bkend_mem(firstBlockSize))
+	{
+		if (TopMemoryContext)
+			MemoryContextStats(TopMemoryContext);
+		ereport(ERROR,
+				(errcode(ERRCODE_OUT_OF_MEMORY),
+				 errmsg("out of memory - exceeds max_total_backend_memory"),
+				 errdetail("Failed while creating memory context \"%s\".",
+						   name)));
+	}
+
 	/*
 	 * Allocate the initial block.  Unlike other aset.c blocks, it starts with
 	 * the context header and its block header follows that.
@@ -741,6 +753,11 @@ AllocSetAlloc(MemoryContext context, Size size)
 #endif
 
 		blksize = chunk_size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
+
+		/* Do not exceed maximum allowed memory allocation */
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		block = (AllocBlock) malloc(blksize);
 		if (block == NULL)
 			return NULL;
@@ -938,6 +955,10 @@ AllocSetAlloc(MemoryContext context, Size size)
 		while (blksize < required_size)
 			blksize <<= 1;
 
+		/* Do not exceed maximum allowed memory allocation */
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		/* Try to allocate it */
 		block = (AllocBlock) malloc(blksize);
 
@@ -1176,6 +1197,18 @@ AllocSetRealloc(void *pointer, Size size)
 		blksize = chksize + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
 		oldblksize = block->endptr - ((char *) block);
 
+		/*
+		 * Do not exceed maximum allowed memory allocation. NOTE: checking for
+		 * the full size here rather than just the amount of increased
+		 * allocation to prevent a potential underflow of *my_allocation
+		 * allowance in cases where blksize - oldblksize does not trigger a
+		 * refill but blksize is greater than *my_allocation_allowance.
+		 * Underflow would occur with the call below to
+		 * pgstat_report_allocated_bytes_increase()
+		 */
+		if (blksize > oldblksize && exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		block = (AllocBlock) realloc(block, blksize);
 		if (block == NULL)
 		{
diff --git a/src/backend/utils/mmgr/generation.c b/src/backend/utils/mmgr/generation.c
index 5708e8da7a..584b2ec8ef 100644
--- a/src/backend/utils/mmgr/generation.c
+++ b/src/backend/utils/mmgr/generation.c
@@ -201,6 +201,16 @@ GenerationContextCreate(MemoryContext parent,
 	else
 		allocSize = Max(allocSize, initBlockSize);
 
+	if (exceeds_max_total_bkend_mem(allocSize))
+	{
+		MemoryContextStats(TopMemoryContext);
+		ereport(ERROR,
+				(errcode(ERRCODE_OUT_OF_MEMORY),
+				 errmsg("out of memory - exceeds max_total_backend_memory"),
+				 errdetail("Failed while creating memory context \"%s\".",
+						   name)));
+	}
+
 	/*
 	 * Allocate the initial block.  Unlike other generation.c blocks, it
 	 * starts with the context header and its block header follows that.
@@ -380,6 +390,9 @@ GenerationAlloc(MemoryContext context, Size size)
 	{
 		Size		blksize = required_size + Generation_BLOCKHDRSZ;
 
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		block = (GenerationBlock *) malloc(blksize);
 		if (block == NULL)
 			return NULL;
@@ -483,6 +496,9 @@ GenerationAlloc(MemoryContext context, Size size)
 			if (blksize < required_size)
 				blksize = pg_nextpower2_size_t(required_size);
 
+			if (exceeds_max_total_bkend_mem(blksize))
+				return NULL;
+
 			block = (GenerationBlock *) malloc(blksize);
 
 			if (block == NULL)
diff --git a/src/backend/utils/mmgr/slab.c b/src/backend/utils/mmgr/slab.c
index 31814901f3..80e8b95071 100644
--- a/src/backend/utils/mmgr/slab.c
+++ b/src/backend/utils/mmgr/slab.c
@@ -356,9 +356,19 @@ SlabContextCreate(MemoryContext parent,
 		elog(ERROR, "block size %zu for slab is too small for %zu-byte chunks",
 			 blockSize, chunkSize);
 
-
+	/* Do not exceed maximum allowed memory allocation */
+	if (exceeds_max_total_bkend_mem(Slab_CONTEXT_HDRSZ(chunksPerBlock)))
+	{
+		MemoryContextStats(TopMemoryContext);
+		ereport(ERROR,
+				(errcode(ERRCODE_OUT_OF_MEMORY),
+				 errmsg("out of memory - exceeds max_total_backend_memory"),
+				 errdetail("Failed while creating memory context \"%s\".",
+						   name)));
+	}
 
 	slab = (SlabContext *) malloc(Slab_CONTEXT_HDRSZ(chunksPerBlock));
+
 	if (slab == NULL)
 	{
 		MemoryContextStats(TopMemoryContext);
@@ -560,6 +570,10 @@ SlabAlloc(MemoryContext context, Size size)
 		}
 		else
 		{
+			/* Do not exceed maximum allowed memory allocation */
+			if (exceeds_max_total_bkend_mem(slab->blockSize))
+				return NULL;
+
 			block = (SlabBlock *) malloc(slab->blockSize);
 
 			if (unlikely(block == NULL))
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d6fbca4a1e..8937764a46 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -5440,9 +5440,9 @@
   descr => 'statistics: global memory allocation information',
   proname => 'pg_stat_get_global_memory_allocation', proisstrict => 'f',
   provolatile => 's', proparallel => 'r', prorettype => 'record',
-  proargtypes => '', proallargtypes => '{oid,int8}',
-  proargmodes => '{o,o}',
-  proargnames => '{datid,global_dsm_allocated_bytes}',
+  proargtypes => '', proallargtypes => '{oid,int8,int8}',
+  proargmodes => '{o,o,o}',
+  proargnames => '{datid,max_total_bkend_mem_bytes_available,global_dsm_allocated_bytes}',
   prosrc =>'pg_stat_get_global_memory_allocation' },
 { oid => '2022',
   descr => 'statistics: information about currently active backends',
diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h
index c2c878219d..a2a5364a85 100644
--- a/src/include/storage/proc.h
+++ b/src/include/storage/proc.h
@@ -406,6 +406,13 @@ typedef struct PROC_HDR
 	int			startupBufferPinWaitBufId;
 	/* Global dsm allocations */
 	pg_atomic_uint64 global_dsm_allocation;
+
+	/*
+	 * Max backend memory allocation tracker. Used/Initialized when
+	 * max_total_bkend_mem > 0 as max_total_bkend_mem (MB) converted to bytes.
+	 * Decreases/increases with free/malloc of backend memory.
+	 */
+	pg_atomic_uint64 max_total_bkend_mem_bytes;
 } PROC_HDR;
 
 extern PGDLLIMPORT PROC_HDR *ProcGlobal;
diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h
index 6434ece1ef..bca6fe10f3 100644
--- a/src/include/utils/backend_status.h
+++ b/src/include/utils/backend_status.h
@@ -15,6 +15,7 @@
 #include "libpq/pqcomm.h"
 #include "miscadmin.h"			/* for BackendType */
 #include "storage/backendid.h"
+#include "storage/proc.h"
 #include "utils/backend_progress.h"
 
 
@@ -304,6 +305,7 @@ typedef struct LocalPgBackendStatus
  */
 extern PGDLLIMPORT bool pgstat_track_activities;
 extern PGDLLIMPORT int pgstat_track_activity_query_size;
+extern PGDLLIMPORT int max_total_bkend_mem;
 
 
 /* ----------
@@ -316,6 +318,10 @@ extern PGDLLIMPORT uint64 *my_aset_allocated_bytes;
 extern PGDLLIMPORT uint64 *my_dsm_allocated_bytes;
 extern PGDLLIMPORT uint64 *my_generation_allocated_bytes;
 extern PGDLLIMPORT uint64 *my_slab_allocated_bytes;
+extern PGDLLIMPORT uint64 allocation_allowance;
+extern PGDLLIMPORT uint64 initial_allocation_allowance;
+extern PGDLLIMPORT uint64 allocation_return;
+extern PGDLLIMPORT uint64 allocation_return_threshold;
 
 
 /* ----------
@@ -363,6 +369,7 @@ extern int	pgstat_fetch_stat_numbackends(void);
 extern PgBackendStatus *pgstat_fetch_stat_beentry(BackendId beid);
 extern LocalPgBackendStatus *pgstat_fetch_stat_local_beentry(int beid);
 extern char *pgstat_clip_activity(const char *raw_activity);
+extern bool exceeds_max_total_bkend_mem(uint64 allocation_request);
 
 /* ----------
  * pgstat_report_allocated_bytes_decrease() -
@@ -384,6 +391,10 @@ pgstat_report_allocated_bytes_decrease(int64 proc_allocated_bytes,
 		/* On overflow, set pgstat count of allocated bytes to zero */
 		*my_allocated_bytes = 0;
 
+		/* Add freed memory to allocation return counter. */
+		allocation_return += proc_allocated_bytes;
+
+		/* On overflow, set allocator type bytes to zero */
 		switch (pg_allocator_type)
 		{
 			case PG_ALLOC_ASET:
@@ -399,13 +410,35 @@ pgstat_report_allocated_bytes_decrease(int64 proc_allocated_bytes,
 				*my_slab_allocated_bytes = 0;
 				break;
 		}
+
+		/*
+		 * Return freed memory to the global counter if return threshold is
+		 * met.
+		 */
+		if (max_total_bkend_mem && allocation_return >= allocation_return_threshold)
+		{
+			if (ProcGlobal)
+			{
+				volatile PROC_HDR *procglobal = ProcGlobal;
+
+				/* Add to global tracker */
+				pg_atomic_add_fetch_u64(&procglobal->max_total_bkend_mem_bytes,
+										allocation_return);
+
+				/* Restart the count */
+				allocation_return = 0;
+			}
+		}
 	}
 	else
 	{
 		/* decrease allocation */
 		*my_allocated_bytes -= proc_allocated_bytes;
 
-		/* Decrease allocator type allocated bytes. */
+		/* Add freed memory to allocation return counter */
+		allocation_return += proc_allocated_bytes;
+
+		/* Decrease allocator type allocated bytes */
 		switch (pg_allocator_type)
 		{
 			case PG_ALLOC_ASET:
@@ -427,6 +460,25 @@ pgstat_report_allocated_bytes_decrease(int64 proc_allocated_bytes,
 				*my_slab_allocated_bytes -= proc_allocated_bytes;
 				break;
 		}
+
+		/*
+		 * Return freed memory to the global counter if return threshold is
+		 * met.
+		 */
+		if (max_total_bkend_mem && allocation_return >= allocation_return_threshold)
+		{
+			if (ProcGlobal)
+			{
+				volatile PROC_HDR *procglobal = ProcGlobal;
+
+				/* Add to global tracker */
+				pg_atomic_add_fetch_u64(&procglobal->max_total_bkend_mem_bytes,
+										allocation_return);
+
+				/* Restart the count */
+				allocation_return = 0;
+			}
+		}
 	}
 
 	return;
@@ -444,6 +496,9 @@ static inline void
 pgstat_report_allocated_bytes_increase(int64 proc_allocated_bytes,
 									   int pg_allocator_type)
 {
+	/* Remove allocated memory from local allocation allowance */
+	allocation_allowance -= proc_allocated_bytes;
+
 	*my_allocated_bytes += proc_allocated_bytes;
 
 	/* Increase allocator type allocated bytes */
@@ -488,6 +543,36 @@ pgstat_init_allocated_bytes(void)
 	*my_generation_allocated_bytes = 0;
 	*my_slab_allocated_bytes = 0;
 
+	/* If we're limiting backend memory */
+	if (max_total_bkend_mem)
+	{
+		volatile PROC_HDR *procglobal = ProcGlobal;
+		uint64		available_max_total_bkend_mem = 0;
+
+		allocation_return = 0;
+		allocation_allowance = 0;
+
+		/* Account for the initial allocation allowance */
+		while ((available_max_total_bkend_mem = pg_atomic_read_u64(&procglobal->max_total_bkend_mem_bytes)) >= initial_allocation_allowance)
+		{
+			/*
+			 * On success populate allocation_allowance. Failure here will
+			 * result in the backend's first invocation of
+			 * exceeds_max_total_bkend_mem allocating requested, default, or
+			 * available memory or result in an out of memory error.
+			 */
+			if (pg_atomic_compare_exchange_u64(&procglobal->max_total_bkend_mem_bytes,
+											   &available_max_total_bkend_mem,
+											   available_max_total_bkend_mem -
+											   initial_allocation_allowance))
+			{
+				allocation_allowance = initial_allocation_allowance;
+
+				break;
+			}
+		}
+	}
+
 	return;
 }
 
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index 9cf035a74a..0edd7d387c 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1874,8 +1874,10 @@ pg_stat_database_conflicts| SELECT oid AS datid,
 pg_stat_global_memory_allocation| SELECT s.datid,
     current_setting('shared_memory_size'::text, true) AS shared_memory_size,
     (current_setting('shared_memory_size_in_huge_pages'::text, true))::integer AS shared_memory_size_in_huge_pages,
+    pg_size_bytes(current_setting('max_total_backend_memory'::text, true)) AS max_total_backend_memory_bytes,
+    s.max_total_bkend_mem_bytes_available,
     s.global_dsm_allocated_bytes
-   FROM (pg_stat_get_global_memory_allocation() s(datid, global_dsm_allocated_bytes)
+   FROM (pg_stat_get_global_memory_allocation() s(datid, max_total_bkend_mem_bytes_available, global_dsm_allocated_bytes)
      LEFT JOIN pg_database d ON ((s.datid = d.oid)));
 pg_stat_gssapi| SELECT pid,
     gss_auth AS gss_authenticated,
-- 
2.25.1

0001-Add-tracking-of-backend-memory-allocated.patchtext/x-patch; charset=UTF-8; name=0001-Add-tracking-of-backend-memory-allocated.patchDownload
From 752d40bcefa66afc8c73976990d3d5943c35bf0d Mon Sep 17 00:00:00 2001
From: Reid Thompson <jreidthompson@nc.rr.com>
Date: Thu, 11 Aug 2022 12:01:25 -0400
Subject: [PATCH 1/2] Add tracking of backend memory allocated

Add tracking of backend memory allocated in total and by allocation
type (aset, dsm, generation, slab) by process.

allocated_bytes tracks the current bytes of memory allocated to the
backend process. aset_allocated_bytes, dsm_allocated_bytes,
generation_allocated_bytes and slab_allocated_bytes track the
allocation by type for the backend process. They are updated for the
process as memory is malloc'd/freed.  Memory allocated to items on
the freelist is included.  Dynamic shared memory allocations are
included only in the value displayed for the backend that created
them, they are not included in the value for backends that are
attached to them to avoid double counting. DSM allocations that are
not destroyed by the creating process prior to it's exit are
considered long lived and are tracked in a global counter
global_dsm_allocated_bytes. We limit the floor of allocation
counters to zero. Created views pg_stat_global_memory_allocation and
pg_stat_memory_allocation for access to these trackers.
---
 doc/src/sgml/monitoring.sgml                | 188 ++++++++++++++++++++
 src/backend/catalog/system_views.sql        |  21 +++
 src/backend/storage/ipc/dsm.c               |  11 +-
 src/backend/storage/ipc/dsm_impl.c          |  78 ++++++++
 src/backend/storage/lmgr/proc.c             |   1 +
 src/backend/utils/activity/backend_status.c | 114 ++++++++++++
 src/backend/utils/adt/pgstatfuncs.c         |  84 +++++++++
 src/backend/utils/init/miscinit.c           |   3 +
 src/backend/utils/mmgr/aset.c               |  17 ++
 src/backend/utils/mmgr/generation.c         |  15 ++
 src/backend/utils/mmgr/slab.c               |  23 +++
 src/include/catalog/pg_proc.dat             |  17 ++
 src/include/storage/proc.h                  |   2 +
 src/include/utils/backend_status.h          | 156 +++++++++++++++-
 src/test/regress/expected/rules.out         |  15 ++
 src/test/regress/expected/stats.out         |  36 ++++
 src/test/regress/sql/stats.sql              |  20 +++
 17 files changed, 799 insertions(+), 2 deletions(-)

diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 21e6ce2841..d943821071 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -5633,6 +5633,194 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
 
  </sect2>
 
+ <sect2 id="monitoring-pg-stat-memory-allocation-view">
+  <title><structname>pg_stat_memory_allocation</structname></title>
+
+  <indexterm>
+   <primary>pg_stat_memory_allocation</primary>
+  </indexterm>
+
+  <para>
+   The <structname>pg_stat_memory_allocation</structname> view will have one
+   row per server process, showing information related to the current memory
+   allocation of that process. Use <function>pg_size_pretty</function>
+   described in <xref linkend="functions-admin-dbsize"/> to make these values
+   more easily readable.
+  </para>
+
+  <table id="pg-stat-memory-allocation-view" xreflabel="pg_stat_memory_allocation">
+   <title><structname>pg_stat_memory_allocation</structname> View</title>
+   <tgroup cols="1">
+    <thead>
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       Column Type
+      </para>
+      <para>
+       Description
+      </para></entry>
+     </row>
+    </thead>
+
+    <tbody>
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>datid</structfield> <type>oid</type>
+      </para>
+      <para>
+       OID of the database this backend is connected to
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>pid</structfield> <type>integer</type>
+      </para>
+      <para>
+       Process ID of this backend
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>allocated_bytes</structfield> <type>bigint</type>
+      </para>
+     <para>
+      Memory currently allocated to this backend in bytes. This is the balance
+      of bytes allocated and freed by this backend. Dynamic shared memory
+      allocations are included only in the value displayed for the backend that
+      created them, they are not included in the value for backends that are
+      attached to them to avoid double counting.
+     </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>aset_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Memory currently allocated to this backend in bytes via the allocation
+       set allocator.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>dsm_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Memory currently allocated to this backend in bytes via the dynamic
+       shared memory allocator. Upon process exit, dsm allocations that have
+       not been freed are considered long lived and added to
+       <structfield>global_dsm_allocated_bytes</structfield> found in the
+       pg_stat_global_memory_allocation view. See
+       <xref linkend="monitoring-pg-stat-global-memory-allocation-view"/>.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>generation_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Memory currently allocated to this backend in bytes via the generation
+       allocator.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>slab_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Memory currently allocated to this backend in bytes via the slab
+       allocator.
+      </para></entry>
+     </row>
+
+    </tbody>
+   </tgroup>
+  </table>
+
+ </sect2>
+
+ <sect2 id="monitoring-pg-stat-global-memory-allocation-view">
+  <title><structname>pg_stat_global_memory_allocation</structname></title>
+
+  <indexterm>
+   <primary>pg_stat_global-memory_allocation</primary>
+  </indexterm>
+
+  <para>
+   The <structname>pg_stat_global_memory_allocation</structname> view will
+   have one row showing information related to current shared memory
+   allocations.
+  </para>
+
+  <table id="pg-stat-global-memory-allocation-view" xreflabel="pg_stat_global_memory_allocation">
+   <title><structname>pg_stat_global_memory_allocation</structname> View</title>
+   <tgroup cols="1">
+    <thead>
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       Column Type
+      </para>
+      <para>
+       Description
+      </para></entry>
+     </row>
+    </thead>
+
+    <tbody>
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>datid</structfield> <type>oid</type>
+      </para>
+      <para>
+       OID of the database this backend is connected to
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>shared_memory_size_mb</structfield> <type>integer</type>
+      </para>
+      <para>
+       Reports the size of the main shared memory area, rounded up to the
+       nearest megabyte. See <xref linkend="guc-shared-memory-size"/>.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>shared_memory_size_in_huge_pages</structfield> <type>bigint</type>
+      </para>
+     <para>
+      Reports the number of huge pages that are needed for the main shared
+      memory area based on the specified huge_page_size. If huge pages are not
+      supported, this will be -1. See
+      <xref linkend="guc-shared-memory-size-in-huge-pages"/>.
+     </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>global_dsm_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Long lived dynamically allocated memory currently allocated to the
+       database. Use <function>pg_size_pretty</function> described in
+       <xref linkend="functions-admin-dbsize"/> to make this value more easily
+       readable.
+      </para></entry>
+     </row>
+
+    </tbody>
+   </tgroup>
+  </table>
+
+ </sect2>
+
  <sect2 id="monitoring-stats-functions">
   <title>Statistics Functions</title>
 
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 8ea159dbde..4bbd992311 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -1330,3 +1330,24 @@ CREATE VIEW pg_stat_subscription_stats AS
         ss.stats_reset
     FROM pg_subscription as s,
          pg_stat_get_subscription_stats(s.oid) as ss;
+
+CREATE VIEW pg_stat_memory_allocation AS
+    SELECT
+        S.datid AS datid,
+        S.pid,
+        S.allocated_bytes,
+        S.aset_allocated_bytes,
+        S.dsm_allocated_bytes,
+        S.generation_allocated_bytes,
+        S.slab_allocated_bytes
+    FROM pg_stat_get_memory_allocation(NULL) AS S
+        LEFT JOIN pg_database AS D ON (S.datid = D.oid);
+
+CREATE VIEW pg_stat_global_memory_allocation AS
+    SELECT
+        S.datid AS datid,
+        current_setting('shared_memory_size'::text, true) AS shared_memory_size,
+        (current_setting('shared_memory_size_in_huge_pages'::text, true))::integer AS shared_memory_size_in_huge_pages,
+        S.global_dsm_allocated_bytes
+    FROM pg_stat_get_global_memory_allocation() AS S
+        LEFT JOIN pg_database AS D ON (S.datid = D.oid);
diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c
index 10b029bb16..64b1fecd1c 100644
--- a/src/backend/storage/ipc/dsm.c
+++ b/src/backend/storage/ipc/dsm.c
@@ -775,6 +775,15 @@ dsm_detach_all(void)
 void
 dsm_detach(dsm_segment *seg)
 {
+	/*
+	 * Retain mapped_size to pass into destroy call in cases where the detach
+	 * is the last reference. mapped_size is zeroed as part of the detach
+	 * process, but is needed later in these cases for dsm_allocated_bytes
+	 * accounting.
+	 */
+	Size		local_seg_mapped_size = seg->mapped_size;
+	Size	   *ptr_local_seg_mapped_size = &local_seg_mapped_size;
+
 	/*
 	 * Invoke registered callbacks.  Just in case one of those callbacks
 	 * throws a further error that brings us back here, pop the callback
@@ -855,7 +864,7 @@ dsm_detach(dsm_segment *seg)
 			 */
 			if (is_main_region_dsm_handle(seg->handle) ||
 				dsm_impl_op(DSM_OP_DESTROY, seg->handle, 0, &seg->impl_private,
-							&seg->mapped_address, &seg->mapped_size, WARNING))
+							&seg->mapped_address, ptr_local_seg_mapped_size, WARNING))
 			{
 				LWLockAcquire(DynamicSharedMemoryControlLock, LW_EXCLUSIVE);
 				if (is_main_region_dsm_handle(seg->handle))
diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c
index f0965c3481..16e2bded59 100644
--- a/src/backend/storage/ipc/dsm_impl.c
+++ b/src/backend/storage/ipc/dsm_impl.c
@@ -66,6 +66,7 @@
 #include "postmaster/postmaster.h"
 #include "storage/dsm_impl.h"
 #include "storage/fd.h"
+#include "utils/backend_status.h"
 #include "utils/guc.h"
 #include "utils/memutils.h"
 
@@ -232,6 +233,14 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_allocated_bytes_decrease(*mapped_size, PG_ALLOC_DSM);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && shm_unlink(name) != 0)
@@ -332,6 +341,33 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+	{
+		/*
+		 * Posix creation calls dsm_impl_posix_resize implying that resizing
+		 * occurs or may be added in the future. As implemented
+		 * dsm_impl_posix_resize utilizes fallocate or truncate, passing the
+		 * whole new size as input, growing the allocation as needed (only
+		 * truncate supports shrinking). We update by replacing the old
+		 * allocation with the new.
+		 */
+#if defined(HAVE_POSIX_FALLOCATE) && defined(__linux__)
+		/*
+		 * posix_fallocate does not shrink allocations, adjust only on
+		 * allocation increase.
+		 */
+		if (request_size > *mapped_size)
+			pgstat_report_allocated_bytes_increase(request_size - *mapped_size, PG_ALLOC_DSM);
+#else
+		pgstat_report_allocated_bytes_decrease(*mapped_size, PG_ALLOC_DSM);
+		pgstat_report_allocated_bytes_increase(request_size, PG_ALLOC_DSM);
+#endif
+	}
 	*mapped_address = address;
 	*mapped_size = request_size;
 	close(fd);
@@ -537,6 +573,14 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_allocated_bytes_decrease(*mapped_size, PG_ALLOC_DSM);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && shmctl(ident, IPC_RMID, NULL) < 0)
@@ -584,6 +628,13 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_allocated_bytes_increase(request_size, PG_ALLOC_DSM);
 	*mapped_address = address;
 	*mapped_size = request_size;
 
@@ -652,6 +703,13 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 			return false;
 		}
 
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_allocated_bytes_decrease(*mapped_size, PG_ALLOC_DSM);
 		*impl_private = NULL;
 		*mapped_address = NULL;
 		*mapped_size = 0;
@@ -768,6 +826,12 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 		return false;
 	}
 
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_allocated_bytes_increase(info.RegionSize, PG_ALLOC_DSM);
 	*mapped_address = address;
 	*mapped_size = info.RegionSize;
 	*impl_private = hmap;
@@ -812,6 +876,13 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		pgstat_report_allocated_bytes_decrease(*mapped_size, PG_ALLOC_DSM);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && unlink(name) != 0)
@@ -933,6 +1004,13 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_allocated_bytes_increase(request_size, PG_ALLOC_DSM);
 	*mapped_address = address;
 	*mapped_size = request_size;
 
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index 22b4278610..d86fbdfd9b 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -180,6 +180,7 @@ InitProcGlobal(void)
 	ProcGlobal->checkpointerLatch = NULL;
 	pg_atomic_init_u32(&ProcGlobal->procArrayGroupFirst, INVALID_PGPROCNO);
 	pg_atomic_init_u32(&ProcGlobal->clogGroupFirst, INVALID_PGPROCNO);
+	pg_atomic_init_u64(&ProcGlobal->global_dsm_allocation, 0);
 
 	/*
 	 * Create and initialize all the PGPROC structures we'll need.  There are
diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c
index 608d01ea0d..f921c4bbde 100644
--- a/src/backend/utils/activity/backend_status.c
+++ b/src/backend/utils/activity/backend_status.c
@@ -49,6 +49,24 @@ int			pgstat_track_activity_query_size = 1024;
 /* exposed so that backend_progress.c can access it */
 PgBackendStatus *MyBEEntry = NULL;
 
+/*
+ * Memory allocated to this backend prior to pgstats initialization. Migrated to
+ * shared memory on pgstats initialization.
+ */
+uint64		local_my_allocated_bytes = 0;
+uint64	   *my_allocated_bytes = &local_my_allocated_bytes;
+
+/* Memory allocated to this backend by type prior to pgstats initialization.
+ * Migrated to shared memory on pgstats initialization
+ */
+uint64		local_my_aset_allocated_bytes = 0;
+uint64	   *my_aset_allocated_bytes = &local_my_aset_allocated_bytes;
+uint64		local_my_dsm_allocated_bytes = 0;
+uint64	   *my_dsm_allocated_bytes = &local_my_dsm_allocated_bytes;
+uint64		local_my_generation_allocated_bytes = 0;
+uint64	   *my_generation_allocated_bytes = &local_my_generation_allocated_bytes;
+uint64		local_my_slab_allocated_bytes = 0;
+uint64	   *my_slab_allocated_bytes = &local_my_slab_allocated_bytes;
 
 static PgBackendStatus *BackendStatusArray = NULL;
 static char *BackendAppnameBuffer = NULL;
@@ -400,6 +418,32 @@ pgstat_bestart(void)
 	lbeentry.st_progress_command_target = InvalidOid;
 	lbeentry.st_query_id = UINT64CONST(0);
 
+	/* Alter allocation reporting from local storage to shared memory */
+	pgstat_set_allocated_bytes_storage(&MyBEEntry->allocated_bytes,
+									   &MyBEEntry->aset_allocated_bytes,
+									   &MyBEEntry->dsm_allocated_bytes,
+									   &MyBEEntry->generation_allocated_bytes,
+									   &MyBEEntry->slab_allocated_bytes);
+
+	/*
+	 * Populate sum of memory allocated prior to pgstats initialization to
+	 * pgstats and zero the local variable. This is a += assignment because
+	 * InitPostgres allocates memory after pgstat_beinit but prior to
+	 * pgstat_bestart so we have allocations to both local and shared memory
+	 * to combine.
+	 */
+	lbeentry.allocated_bytes += local_my_allocated_bytes;
+	local_my_allocated_bytes = 0;
+	lbeentry.aset_allocated_bytes += local_my_aset_allocated_bytes;
+	local_my_aset_allocated_bytes = 0;
+
+	lbeentry.dsm_allocated_bytes += local_my_dsm_allocated_bytes;
+	local_my_dsm_allocated_bytes = 0;
+	lbeentry.generation_allocated_bytes += local_my_generation_allocated_bytes;
+	local_my_generation_allocated_bytes = 0;
+	lbeentry.slab_allocated_bytes += local_my_slab_allocated_bytes;
+	local_my_slab_allocated_bytes = 0;
+
 	/*
 	 * we don't zero st_progress_param here to save cycles; nobody should
 	 * examine it until st_progress_command has been set to something other
@@ -459,6 +503,9 @@ pgstat_beshutdown_hook(int code, Datum arg)
 {
 	volatile PgBackendStatus *beentry = MyBEEntry;
 
+	/* Stop reporting memory allocation changes to shared memory */
+	pgstat_reset_allocated_bytes_storage();
+
 	/*
 	 * Clear my status entry, following the protocol of bumping st_changecount
 	 * before and after.  We use a volatile pointer here to ensure the
@@ -1194,3 +1241,70 @@ pgstat_clip_activity(const char *raw_activity)
 
 	return activity;
 }
+
+/*
+ * Configure bytes allocated reporting to report allocated bytes to
+ * shared memory.
+ *
+ * Expected to be called during backend startup (in pgstat_bestart), to point
+ * allocated bytes accounting into shared memory.
+ */
+void
+pgstat_set_allocated_bytes_storage(uint64 *allocated_bytes,
+								   uint64 *aset_allocated_bytes,
+								   uint64 *dsm_allocated_bytes,
+								   uint64 *generation_allocated_bytes,
+								   uint64 *slab_allocated_bytes)
+{
+	/* Map allocations to shared memory */
+	my_allocated_bytes = allocated_bytes;
+	*allocated_bytes = local_my_allocated_bytes;
+
+	my_aset_allocated_bytes = aset_allocated_bytes;
+	*aset_allocated_bytes = local_my_aset_allocated_bytes;
+
+	my_dsm_allocated_bytes = dsm_allocated_bytes;
+	*dsm_allocated_bytes = local_my_dsm_allocated_bytes;
+
+	my_generation_allocated_bytes = generation_allocated_bytes;
+	*generation_allocated_bytes = local_my_generation_allocated_bytes;
+
+	my_slab_allocated_bytes = slab_allocated_bytes;
+	*slab_allocated_bytes = local_my_slab_allocated_bytes;
+}
+
+/*
+ * Reset allocated bytes storage location.
+ *
+ * Expected to be called during backend shutdown, before the locations set up
+ * by pgstat_set_allocated_bytes_storage become invalid.
+ */
+void
+pgstat_reset_allocated_bytes_storage(void)
+{
+	if (ProcGlobal)
+	{
+		volatile PROC_HDR *procglobal = ProcGlobal;
+
+		/*
+		 * Add dsm allocations that have not been freed to global dsm
+		 * accounting
+		 */
+		pg_atomic_add_fetch_u64(&procglobal->global_dsm_allocation,
+								*my_dsm_allocated_bytes);
+	}
+
+	/* Reset memory allocation variables */
+	*my_allocated_bytes = local_my_allocated_bytes = 0;
+	*my_aset_allocated_bytes = local_my_aset_allocated_bytes = 0;
+	*my_dsm_allocated_bytes = local_my_dsm_allocated_bytes = 0;
+	*my_generation_allocated_bytes = local_my_generation_allocated_bytes = 0;
+	*my_slab_allocated_bytes = local_my_slab_allocated_bytes = 0;
+
+	/* Point my_{*_}allocated_bytes from shared memory back to local */
+	my_allocated_bytes = &local_my_allocated_bytes;
+	my_aset_allocated_bytes = &local_my_aset_allocated_bytes;
+	my_dsm_allocated_bytes = &local_my_dsm_allocated_bytes;
+	my_generation_allocated_bytes = &local_my_generation_allocated_bytes;
+	my_slab_allocated_bytes = &local_my_slab_allocated_bytes;
+}
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 56119737c8..be973b1bdb 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -2067,3 +2067,87 @@ pg_stat_have_stats(PG_FUNCTION_ARGS)
 
 	PG_RETURN_BOOL(pgstat_have_entry(kind, dboid, objoid));
 }
+
+/*
+ * Get the memory allocation of PG backends.
+ */
+Datum
+pg_stat_get_memory_allocation(PG_FUNCTION_ARGS)
+{
+#define PG_STAT_GET_MEMORY_ALLOCATION_COLS	7
+	int			num_backends = pgstat_fetch_stat_numbackends();
+	int			curr_backend;
+	int			pid = PG_ARGISNULL(0) ? -1 : PG_GETARG_INT32(0);
+	ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
+
+	InitMaterializedSRF(fcinfo, 0);
+
+	/* 1-based index */
+	for (curr_backend = 1; curr_backend <= num_backends; curr_backend++)
+	{
+		/* for each row */
+		Datum		values[PG_STAT_GET_MEMORY_ALLOCATION_COLS] = {0};
+		bool		nulls[PG_STAT_GET_MEMORY_ALLOCATION_COLS] = {0};
+		LocalPgBackendStatus *local_beentry;
+		PgBackendStatus *beentry;
+
+		/* Get the next one in the list */
+		local_beentry = pgstat_fetch_stat_local_beentry(curr_backend);
+		beentry = &local_beentry->backendStatus;
+
+		/* If looking for specific PID, ignore all the others */
+		if (pid != -1 && beentry->st_procpid != pid)
+			continue;
+
+		/* Values available to all callers */
+		if (beentry->st_databaseid != InvalidOid)
+			values[0] = ObjectIdGetDatum(beentry->st_databaseid);
+		else
+			nulls[0] = true;
+
+		values[1] = Int32GetDatum(beentry->st_procpid);
+		values[2] = UInt64GetDatum(beentry->allocated_bytes);
+		values[3] = UInt64GetDatum(beentry->aset_allocated_bytes);
+		values[4] = UInt64GetDatum(beentry->dsm_allocated_bytes);
+		values[5] = UInt64GetDatum(beentry->generation_allocated_bytes);
+		values[6] = UInt64GetDatum(beentry->slab_allocated_bytes);
+
+		tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
+
+		/* If only a single backend was requested, and we found it, break. */
+		if (pid != -1)
+			break;
+	}
+
+	return (Datum) 0;
+}
+
+/*
+ * Get the global memory allocation statistics.
+ */
+Datum
+pg_stat_get_global_memory_allocation(PG_FUNCTION_ARGS)
+{
+#define PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS	2
+	TupleDesc	tupdesc;
+	Datum		values[PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS] = {0};
+	bool		nulls[PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS] = {0};
+	volatile PROC_HDR *procglobal = ProcGlobal;
+
+	/* Initialise attributes information in the tuple descriptor */
+	tupdesc = CreateTemplateTupleDesc(PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS);
+	TupleDescInitEntry(tupdesc, (AttrNumber) 1, "datid",
+					   OIDOID, -1, 0);
+	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "global_dsm_allocated_bytes",
+					   INT8OID, -1, 0);
+	BlessTupleDesc(tupdesc);
+
+	/* datid */
+	values[0] = ObjectIdGetDatum(MyDatabaseId);
+
+	/* get global_dsm_allocated_bytes */
+	values[1] = Int64GetDatum(pg_atomic_read_u64(&procglobal->global_dsm_allocation));
+
+	/* Returns the record as Datum */
+	PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls)));
+}
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index a604432126..7b8eeb7dbb 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -171,6 +171,9 @@ InitPostmasterChild(void)
 				(errcode_for_socket_access(),
 				 errmsg_internal("could not set postmaster death monitoring pipe to FD_CLOEXEC mode: %m")));
 #endif
+
+	/* Init allocated bytes to avoid double counting parent allocation */
+	pgstat_init_allocated_bytes();
 }
 
 /*
diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index 2589941ec4..f3f5945fdf 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -47,6 +47,7 @@
 #include "postgres.h"
 
 #include "port/pg_bitutils.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -521,6 +522,7 @@ AllocSetContextCreateInternal(MemoryContext parent,
 						name);
 
 	((MemoryContext) set)->mem_allocated = firstBlockSize;
+	pgstat_report_allocated_bytes_increase(firstBlockSize, PG_ALLOC_ASET);
 
 	return (MemoryContext) set;
 }
@@ -543,6 +545,7 @@ AllocSetReset(MemoryContext context)
 	AllocSet	set = (AllocSet) context;
 	AllocBlock	block;
 	Size		keepersize PG_USED_FOR_ASSERTS_ONLY;
+	uint64		deallocation = 0;
 
 	Assert(AllocSetIsValid(set));
 
@@ -585,6 +588,7 @@ AllocSetReset(MemoryContext context)
 		{
 			/* Normal case, release the block */
 			context->mem_allocated -= block->endptr - ((char *) block);
+			deallocation += block->endptr - ((char *) block);
 
 #ifdef CLOBBER_FREED_MEMORY
 			wipe_mem(block, block->freeptr - ((char *) block));
@@ -595,6 +599,7 @@ AllocSetReset(MemoryContext context)
 	}
 
 	Assert(context->mem_allocated == keepersize);
+	pgstat_report_allocated_bytes_decrease(deallocation, PG_ALLOC_ASET);
 
 	/* Reset block size allocation sequence, too */
 	set->nextBlockSize = set->initBlockSize;
@@ -613,6 +618,7 @@ AllocSetDelete(MemoryContext context)
 	AllocSet	set = (AllocSet) context;
 	AllocBlock	block = set->blocks;
 	Size		keepersize PG_USED_FOR_ASSERTS_ONLY;
+	uint64		deallocation = 0;
 
 	Assert(AllocSetIsValid(set));
 
@@ -651,11 +657,13 @@ AllocSetDelete(MemoryContext context)
 
 				freelist->first_free = (AllocSetContext *) oldset->header.nextchild;
 				freelist->num_free--;
+				deallocation += oldset->header.mem_allocated;
 
 				/* All that remains is to free the header/initial block */
 				free(oldset);
 			}
 			Assert(freelist->num_free == 0);
+			pgstat_report_allocated_bytes_decrease(deallocation, PG_ALLOC_ASET);
 		}
 
 		/* Now add the just-deleted context to the freelist. */
@@ -672,7 +680,10 @@ AllocSetDelete(MemoryContext context)
 		AllocBlock	next = block->next;
 
 		if (block != set->keeper)
+		{
 			context->mem_allocated -= block->endptr - ((char *) block);
+			deallocation += block->endptr - ((char *) block);
+		}
 
 #ifdef CLOBBER_FREED_MEMORY
 		wipe_mem(block, block->freeptr - ((char *) block));
@@ -685,6 +696,7 @@ AllocSetDelete(MemoryContext context)
 	}
 
 	Assert(context->mem_allocated == keepersize);
+	pgstat_report_allocated_bytes_decrease(deallocation + context->mem_allocated, PG_ALLOC_ASET);
 
 	/* Finally, free the context header, including the keeper block */
 	free(set);
@@ -734,6 +746,7 @@ AllocSetAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_allocated_bytes_increase(blksize, PG_ALLOC_ASET);
 
 		block->aset = set;
 		block->freeptr = block->endptr = ((char *) block) + blksize;
@@ -944,6 +957,7 @@ AllocSetAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_allocated_bytes_increase(blksize, PG_ALLOC_ASET);
 
 		block->aset = set;
 		block->freeptr = ((char *) block) + ALLOC_BLOCKHDRSZ;
@@ -1041,6 +1055,7 @@ AllocSetFree(void *pointer)
 			block->next->prev = block->prev;
 
 		set->header.mem_allocated -= block->endptr - ((char *) block);
+		pgstat_report_allocated_bytes_decrease(block->endptr - ((char *) block), PG_ALLOC_ASET);
 
 #ifdef CLOBBER_FREED_MEMORY
 		wipe_mem(block, block->freeptr - ((char *) block));
@@ -1171,7 +1186,9 @@ AllocSetRealloc(void *pointer, Size size)
 
 		/* updated separately, not to underflow when (oldblksize > blksize) */
 		set->header.mem_allocated -= oldblksize;
+		pgstat_report_allocated_bytes_decrease(oldblksize, PG_ALLOC_ASET);
 		set->header.mem_allocated += blksize;
+		pgstat_report_allocated_bytes_increase(blksize, PG_ALLOC_ASET);
 
 		block->freeptr = block->endptr = ((char *) block) + blksize;
 
diff --git a/src/backend/utils/mmgr/generation.c b/src/backend/utils/mmgr/generation.c
index ebcb61e9b6..5708e8da7a 100644
--- a/src/backend/utils/mmgr/generation.c
+++ b/src/backend/utils/mmgr/generation.c
@@ -37,6 +37,7 @@
 
 #include "lib/ilist.h"
 #include "port/pg_bitutils.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -267,6 +268,7 @@ GenerationContextCreate(MemoryContext parent,
 						name);
 
 	((MemoryContext) set)->mem_allocated = firstBlockSize;
+	pgstat_report_allocated_bytes_increase(firstBlockSize, PG_ALLOC_GENERATION);
 
 	return (MemoryContext) set;
 }
@@ -283,6 +285,7 @@ GenerationReset(MemoryContext context)
 {
 	GenerationContext *set = (GenerationContext *) context;
 	dlist_mutable_iter miter;
+	uint64		deallocation = 0;
 
 	Assert(GenerationIsValid(set));
 
@@ -305,9 +308,14 @@ GenerationReset(MemoryContext context)
 		if (block == set->keeper)
 			GenerationBlockMarkEmpty(block);
 		else
+		{
+			deallocation += block->blksize;
 			GenerationBlockFree(set, block);
+		}
 	}
 
+	pgstat_report_allocated_bytes_decrease(deallocation, PG_ALLOC_GENERATION);
+
 	/* set it so new allocations to make use of the keeper block */
 	set->block = set->keeper;
 
@@ -328,6 +336,9 @@ GenerationDelete(MemoryContext context)
 {
 	/* Reset to release all releasable GenerationBlocks */
 	GenerationReset(context);
+
+	pgstat_report_allocated_bytes_decrease(context->mem_allocated, PG_ALLOC_GENERATION);
+
 	/* And free the context header and keeper block */
 	free(context);
 }
@@ -374,6 +385,7 @@ GenerationAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_allocated_bytes_increase(blksize, PG_ALLOC_GENERATION);
 
 		/* block with a single (used) chunk */
 		block->context = set;
@@ -477,6 +489,7 @@ GenerationAlloc(MemoryContext context, Size size)
 				return NULL;
 
 			context->mem_allocated += blksize;
+			pgstat_report_allocated_bytes_increase(blksize, PG_ALLOC_GENERATION);
 
 			/* initialize the new block */
 			GenerationBlockInit(set, block, blksize);
@@ -729,6 +742,8 @@ GenerationFree(void *pointer)
 	dlist_delete(&block->node);
 
 	set->header.mem_allocated -= block->blksize;
+	pgstat_report_allocated_bytes_decrease(block->blksize, PG_ALLOC_GENERATION);
+
 	free(block);
 }
 
diff --git a/src/backend/utils/mmgr/slab.c b/src/backend/utils/mmgr/slab.c
index 33dca0f37c..31814901f3 100644
--- a/src/backend/utils/mmgr/slab.c
+++ b/src/backend/utils/mmgr/slab.c
@@ -69,6 +69,7 @@
 #include "postgres.h"
 
 #include "lib/ilist.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -413,6 +414,13 @@ SlabContextCreate(MemoryContext parent,
 						parent,
 						name);
 
+	/*
+	 * If SlabContextCreate is updated to add context header size to
+	 * context->mem_allocated, then update here and SlabDelete appropriately
+	 */
+	pgstat_report_allocated_bytes_increase(Slab_CONTEXT_HDRSZ(slab->chunksPerBlock),
+										   PG_ALLOC_SLAB);
+
 	return (MemoryContext) slab;
 }
 
@@ -429,6 +437,7 @@ SlabReset(MemoryContext context)
 	SlabContext *slab = (SlabContext *) context;
 	dlist_mutable_iter miter;
 	int			i;
+	uint64		deallocation = 0;
 
 	Assert(SlabIsValid(slab));
 
@@ -449,6 +458,7 @@ SlabReset(MemoryContext context)
 #endif
 		free(block);
 		context->mem_allocated -= slab->blockSize;
+		deallocation += slab->blockSize;
 	}
 
 	/* walk over blocklist and free the blocks */
@@ -465,9 +475,11 @@ SlabReset(MemoryContext context)
 #endif
 			free(block);
 			context->mem_allocated -= slab->blockSize;
+			deallocation += slab->blockSize;
 		}
 	}
 
+	pgstat_report_allocated_bytes_decrease(deallocation, PG_ALLOC_SLAB);
 	slab->curBlocklistIndex = 0;
 
 	Assert(context->mem_allocated == 0);
@@ -480,8 +492,17 @@ SlabReset(MemoryContext context)
 void
 SlabDelete(MemoryContext context)
 {
+
 	/* Reset to release all the SlabBlocks */
 	SlabReset(context);
+
+	/*
+	 * Until context header allocation is included in context->mem_allocated,
+	 * cast to slab and decrement the header allocation
+	 */
+	pgstat_report_allocated_bytes_decrease(Slab_CONTEXT_HDRSZ(((SlabContext *) context)->chunksPerBlock),
+										   PG_ALLOC_SLAB);
+
 	/* And free the context header */
 	free(context);
 }
@@ -546,6 +567,7 @@ SlabAlloc(MemoryContext context, Size size)
 
 			block->slab = slab;
 			context->mem_allocated += slab->blockSize;
+			pgstat_report_allocated_bytes_increase(slab->blockSize, PG_ALLOC_SLAB);
 
 			/* use the first chunk in the new block */
 			chunk = SlabBlockGetChunk(slab, block, 0);
@@ -732,6 +754,7 @@ SlabFree(void *pointer)
 #endif
 			free(block);
 			slab->header.mem_allocated -= slab->blockSize;
+			pgstat_report_allocated_bytes_decrease(slab->blockSize, PG_ALLOC_SLAB);
 		}
 
 		/*
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 7c358cff16..d6fbca4a1e 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -5427,6 +5427,23 @@
   proname => 'pg_stat_get_backend_idset', prorows => '100', proretset => 't',
   provolatile => 's', proparallel => 'r', prorettype => 'int4',
   proargtypes => '', prosrc => 'pg_stat_get_backend_idset' },
+{ oid => '9890',
+  descr => 'statistics: memory allocation information for backends',
+  proname => 'pg_stat_get_memory_allocation', prorows => '100', proisstrict => 'f',
+  proretset => 't', provolatile => 's', proparallel => 'r',
+  prorettype => 'record', proargtypes => 'int4',
+  proallargtypes => '{int4,oid,int4,int8,int8,int8,int8,int8}',
+  proargmodes => '{i,o,o,o,o,o,o,o}',
+  proargnames => '{pid,datid,pid,allocated_bytes,aset_allocated_bytes,dsm_allocated_bytes,generation_allocated_bytes,slab_allocated_bytes}',
+  prosrc => 'pg_stat_get_memory_allocation' },
+{ oid => '9891',
+  descr => 'statistics: global memory allocation information',
+  proname => 'pg_stat_get_global_memory_allocation', proisstrict => 'f',
+  provolatile => 's', proparallel => 'r', prorettype => 'record',
+  proargtypes => '', proallargtypes => '{oid,int8}',
+  proargmodes => '{o,o}',
+  proargnames => '{datid,global_dsm_allocated_bytes}',
+  prosrc =>'pg_stat_get_global_memory_allocation' },
 { oid => '2022',
   descr => 'statistics: information about currently active backends',
   proname => 'pg_stat_get_activity', prorows => '100', proisstrict => 'f',
diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h
index 4258cd92c9..c2c878219d 100644
--- a/src/include/storage/proc.h
+++ b/src/include/storage/proc.h
@@ -404,6 +404,8 @@ typedef struct PROC_HDR
 	int			spins_per_delay;
 	/* Buffer id of the buffer that Startup process waits for pin on, or -1 */
 	int			startupBufferPinWaitBufId;
+	/* Global dsm allocations */
+	pg_atomic_uint64 global_dsm_allocation;
 } PROC_HDR;
 
 extern PGDLLIMPORT PROC_HDR *ProcGlobal;
diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h
index f7bd83113a..6434ece1ef 100644
--- a/src/include/utils/backend_status.h
+++ b/src/include/utils/backend_status.h
@@ -10,6 +10,7 @@
 #ifndef BACKEND_STATUS_H
 #define BACKEND_STATUS_H
 
+#include "common/int.h"
 #include "datatype/timestamp.h"
 #include "libpq/pqcomm.h"
 #include "miscadmin.h"			/* for BackendType */
@@ -32,6 +33,14 @@ typedef enum BackendState
 	STATE_DISABLED
 } BackendState;
 
+/* Enum helper for reporting memory allocator type */
+enum pg_allocator_type
+{
+	PG_ALLOC_ASET = 1,
+	PG_ALLOC_DSM,
+	PG_ALLOC_GENERATION,
+	PG_ALLOC_SLAB
+};
 
 /* ----------
  * Shared-memory data structures
@@ -169,6 +178,15 @@ typedef struct PgBackendStatus
 
 	/* query identifier, optionally computed using post_parse_analyze_hook */
 	uint64		st_query_id;
+
+	/* Current memory allocated to this backend */
+	uint64		allocated_bytes;
+
+	/* Current memory allocated to this backend by type */
+	uint64		aset_allocated_bytes;
+	uint64		dsm_allocated_bytes;
+	uint64		generation_allocated_bytes;
+	uint64		slab_allocated_bytes;
 } PgBackendStatus;
 
 
@@ -293,6 +311,11 @@ extern PGDLLIMPORT int pgstat_track_activity_query_size;
  * ----------
  */
 extern PGDLLIMPORT PgBackendStatus *MyBEEntry;
+extern PGDLLIMPORT uint64 *my_allocated_bytes;
+extern PGDLLIMPORT uint64 *my_aset_allocated_bytes;
+extern PGDLLIMPORT uint64 *my_dsm_allocated_bytes;
+extern PGDLLIMPORT uint64 *my_generation_allocated_bytes;
+extern PGDLLIMPORT uint64 *my_slab_allocated_bytes;
 
 
 /* ----------
@@ -324,7 +347,12 @@ extern const char *pgstat_get_backend_current_activity(int pid, bool checkUser);
 extern const char *pgstat_get_crashed_backend_activity(int pid, char *buffer,
 													   int buflen);
 extern uint64 pgstat_get_my_query_id(void);
-
+extern void pgstat_set_allocated_bytes_storage(uint64 *allocated_bytes,
+											   uint64 *aset_allocated_bytes,
+											   uint64 *dsm_allocated_bytes,
+											   uint64 *generation_allocated_bytes,
+											   uint64 *slab_allocated_bytes);
+extern void pgstat_reset_allocated_bytes_storage(void);
 
 /* ----------
  * Support functions for the SQL-callable functions to
@@ -336,5 +364,131 @@ extern PgBackendStatus *pgstat_fetch_stat_beentry(BackendId beid);
 extern LocalPgBackendStatus *pgstat_fetch_stat_local_beentry(int beid);
 extern char *pgstat_clip_activity(const char *raw_activity);
 
+/* ----------
+ * pgstat_report_allocated_bytes_decrease() -
+ *  Called to report decrease in memory allocated for this backend.
+ *
+ * my_{*_}allocated_bytes initially points to local memory, making it safe to
+ * call this before pgstats has been initialized.
+ * ----------
+ */
+static inline void
+pgstat_report_allocated_bytes_decrease(int64 proc_allocated_bytes,
+									   int pg_allocator_type)
+{
+	uint64		temp;
+
+	/* Avoid allocated_bytes unsigned integer overflow on decrease */
+	if (pg_sub_u64_overflow(*my_allocated_bytes, proc_allocated_bytes, &temp))
+	{
+		/* On overflow, set pgstat count of allocated bytes to zero */
+		*my_allocated_bytes = 0;
+
+		switch (pg_allocator_type)
+		{
+			case PG_ALLOC_ASET:
+				*my_aset_allocated_bytes = 0;
+				break;
+			case PG_ALLOC_DSM:
+				*my_dsm_allocated_bytes = 0;
+				break;
+			case PG_ALLOC_GENERATION:
+				*my_generation_allocated_bytes = 0;
+				break;
+			case PG_ALLOC_SLAB:
+				*my_slab_allocated_bytes = 0;
+				break;
+		}
+	}
+	else
+	{
+		/* decrease allocation */
+		*my_allocated_bytes -= proc_allocated_bytes;
+
+		/* Decrease allocator type allocated bytes. */
+		switch (pg_allocator_type)
+		{
+			case PG_ALLOC_ASET:
+				*my_aset_allocated_bytes -= proc_allocated_bytes;
+				break;
+			case PG_ALLOC_DSM:
+
+				/*
+				 * Some dsm allocations live beyond process exit. These are
+				 * accounted for in a global counter in
+				 * pgstat_reset_allocated_bytes_storage at process exit.
+				 */
+				*my_dsm_allocated_bytes -= proc_allocated_bytes;
+				break;
+			case PG_ALLOC_GENERATION:
+				*my_generation_allocated_bytes -= proc_allocated_bytes;
+				break;
+			case PG_ALLOC_SLAB:
+				*my_slab_allocated_bytes -= proc_allocated_bytes;
+				break;
+		}
+	}
+
+	return;
+}
+
+/* ----------
+ * pgstat_report_allocated_bytes_increase() -
+ *  Called to report increase in memory allocated for this backend.
+ *
+ * my_allocated_bytes initially points to local memory, making it safe to call
+ * this before pgstats has been initialized.
+ * ----------
+ */
+static inline void
+pgstat_report_allocated_bytes_increase(int64 proc_allocated_bytes,
+									   int pg_allocator_type)
+{
+	*my_allocated_bytes += proc_allocated_bytes;
+
+	/* Increase allocator type allocated bytes */
+	switch (pg_allocator_type)
+	{
+		case PG_ALLOC_ASET:
+			*my_aset_allocated_bytes += proc_allocated_bytes;
+			break;
+		case PG_ALLOC_DSM:
+
+			/*
+			 * Some dsm allocations live beyond process exit. These are
+			 * accounted for in a global counter in
+			 * pgstat_reset_allocated_bytes_storage at process exit.
+			 */
+			*my_dsm_allocated_bytes += proc_allocated_bytes;
+			break;
+		case PG_ALLOC_GENERATION:
+			*my_generation_allocated_bytes += proc_allocated_bytes;
+			break;
+		case PG_ALLOC_SLAB:
+			*my_slab_allocated_bytes += proc_allocated_bytes;
+			break;
+	}
+
+	return;
+}
+
+/* ---------
+ * pgstat_init_allocated_bytes() -
+ *
+ * Called to initialize allocated bytes variables after fork and to
+ * avoid double counting allocations.
+ * ---------
+ */
+static inline void
+pgstat_init_allocated_bytes(void)
+{
+	*my_allocated_bytes = 0;
+	*my_aset_allocated_bytes = 0;
+	*my_dsm_allocated_bytes = 0;
+	*my_generation_allocated_bytes = 0;
+	*my_slab_allocated_bytes = 0;
+
+	return;
+}
 
 #endif							/* BACKEND_STATUS_H */
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index 996d22b7dd..9cf035a74a 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1871,6 +1871,12 @@ pg_stat_database_conflicts| SELECT oid AS datid,
     pg_stat_get_db_conflict_bufferpin(oid) AS confl_bufferpin,
     pg_stat_get_db_conflict_startup_deadlock(oid) AS confl_deadlock
    FROM pg_database d;
+pg_stat_global_memory_allocation| SELECT s.datid,
+    current_setting('shared_memory_size'::text, true) AS shared_memory_size,
+    (current_setting('shared_memory_size_in_huge_pages'::text, true))::integer AS shared_memory_size_in_huge_pages,
+    s.global_dsm_allocated_bytes
+   FROM (pg_stat_get_global_memory_allocation() s(datid, global_dsm_allocated_bytes)
+     LEFT JOIN pg_database d ON ((s.datid = d.oid)));
 pg_stat_gssapi| SELECT pid,
     gss_auth AS gss_authenticated,
     gss_princ AS principal,
@@ -1889,6 +1895,15 @@ pg_stat_io| SELECT backend_type,
     fsyncs,
     stats_reset
    FROM pg_stat_get_io() b(backend_type, io_object, io_context, reads, writes, extends, op_bytes, evictions, reuses, fsyncs, stats_reset);
+pg_stat_memory_allocation| SELECT s.datid,
+    s.pid,
+    s.allocated_bytes,
+    s.aset_allocated_bytes,
+    s.dsm_allocated_bytes,
+    s.generation_allocated_bytes,
+    s.slab_allocated_bytes
+   FROM (pg_stat_get_memory_allocation(NULL::integer) s(datid, pid, allocated_bytes, aset_allocated_bytes, dsm_allocated_bytes, generation_allocated_bytes, slab_allocated_bytes)
+     LEFT JOIN pg_database d ON ((s.datid = d.oid)));
 pg_stat_progress_analyze| SELECT s.pid,
     s.datid,
     d.datname,
diff --git a/src/test/regress/expected/stats.out b/src/test/regress/expected/stats.out
index 55b4c6df01..5fad38d49d 100644
--- a/src/test/regress/expected/stats.out
+++ b/src/test/regress/expected/stats.out
@@ -1469,4 +1469,40 @@ SELECT COUNT(*) FROM brin_hot_3 WHERE a = 2;
 
 DROP TABLE brin_hot_3;
 SET enable_seqscan = on;
+-- ensure that allocated_bytes exist for backends
+SELECT
+    allocated_bytes > 0 AS result
+FROM
+    pg_stat_activity ps
+    JOIN pg_stat_memory_allocation pa ON (pa.pid = ps.pid)
+WHERE
+    backend_type IN ('checkpointer', 'background writer', 'walwriter', 'autovacuum launcher');
+ result 
+--------
+ t
+ t
+ t
+ t
+(4 rows)
+
+-- ensure that pg_stat_global_memory_allocation view exists
+SELECT
+    datid > 0, pg_size_bytes(shared_memory_size) >= 0, shared_memory_size_in_huge_pages >= -1, global_dsm_allocated_bytes >= 0
+FROM
+    pg_stat_global_memory_allocation;
+ ?column? | ?column? | ?column? | ?column? 
+----------+----------+----------+----------
+ t        | t        | t        | t
+(1 row)
+
+-- ensure that pg_stat_memory_allocation view exists
+SELECT
+    pid > 0, allocated_bytes >= 0, aset_allocated_bytes >= 0, dsm_allocated_bytes >= 0, generation_allocated_bytes >= 0, slab_allocated_bytes >= 0
+FROM
+    pg_stat_memory_allocation limit 1;
+ ?column? | ?column? | ?column? | ?column? | ?column? | ?column? 
+----------+----------+----------+----------+----------+----------
+ t        | t        | t        | t        | t        | t
+(1 row)
+
 -- End of Stats Test
diff --git a/src/test/regress/sql/stats.sql b/src/test/regress/sql/stats.sql
index d958e70a86..e768f3df84 100644
--- a/src/test/regress/sql/stats.sql
+++ b/src/test/regress/sql/stats.sql
@@ -763,4 +763,24 @@ DROP TABLE brin_hot_3;
 
 SET enable_seqscan = on;
 
+-- ensure that allocated_bytes exist for backends
+SELECT
+    allocated_bytes > 0 AS result
+FROM
+    pg_stat_activity ps
+    JOIN pg_stat_memory_allocation pa ON (pa.pid = ps.pid)
+WHERE
+    backend_type IN ('checkpointer', 'background writer', 'walwriter', 'autovacuum launcher');
+
+-- ensure that pg_stat_global_memory_allocation view exists
+SELECT
+    datid > 0, pg_size_bytes(shared_memory_size) >= 0, shared_memory_size_in_huge_pages >= -1, global_dsm_allocated_bytes >= 0
+FROM
+    pg_stat_global_memory_allocation;
+
+-- ensure that pg_stat_memory_allocation view exists
+SELECT
+    pid > 0, allocated_bytes >= 0, aset_allocated_bytes >= 0, dsm_allocated_bytes >= 0, generation_allocated_bytes >= 0, slab_allocated_bytes >= 0
+FROM
+    pg_stat_memory_allocation limit 1;
 -- End of Stats Test
-- 
2.25.1

#34Noname
reid.thompson@crunchydata.com
In reply to: Noname (#33)
2 attachment(s)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

Updated patches attached.

Rebased to current master.
Added additional columns to pg_stat_global_memory_allocation to summarize backend allocations by type.
Updated documentation.
Corrected some issues noted in review by John Morris.
Added code re EXEC_BACKEND for dev-max-memory branch.

Attachments:

0002-Add-the-ability-to-limit-the-amount-of-memory-that-c.patchtext/x-patch; charset=UTF-8; name=0002-Add-the-ability-to-limit-the-amount-of-memory-that-c.patchDownload
From 34514ae2bebe5e3ab2a0b5b680d3932b5e7706ee Mon Sep 17 00:00:00 2001
From: Reid Thompson <jreidthompson@nc.rr.com>
Date: Sat, 4 Jun 2022 22:23:59 -0400
Subject: [PATCH 2/2] Add the ability to limit the amount of memory that can be
 allocated to backends.

This builds on the work that adds backend memory allocated tracking.

Add GUC variable max_total_backend_memory.

Specifies a limit to the amount of memory (in MB) that may be allocated to
backends in total (i.e. this is not a per user or per backend limit). If unset,
or set to 0 it is disabled. It is intended as a resource to help avoid the OOM
killer on LINUX and manage resources in general. A backend request that would
exhaust max_total_backend_memory memory will be denied with an out of memory
error causing that backend's current query/transaction to fail.  Further
requests will not be allocated until dropping below the limit. Keep this in
mind when setting this value. Due to the dynamic nature of memory allocations,
this limit is not exact. This limit does not affect auxiliary backend
processes. Backend memory allocations are displayed in the
pg_stat_memory_allocation and pg_stat_global_memory_allocation views.
---
 doc/src/sgml/config.sgml                      |  30 +++
 doc/src/sgml/monitoring.sgml                  |  38 +++-
 src/backend/catalog/system_views.sql          |   2 +
 src/backend/port/sysv_shmem.c                 |   9 +
 src/backend/postmaster/postmaster.c           |   5 +
 src/backend/storage/ipc/dsm_impl.c            |  18 ++
 src/backend/storage/lmgr/proc.c               |  45 +++++
 src/backend/utils/activity/backend_status.c   | 183 ++++++++++++++++++
 src/backend/utils/adt/pgstatfuncs.c           |  16 +-
 src/backend/utils/hash/dynahash.c             |   3 +-
 src/backend/utils/init/miscinit.c             |   8 +
 src/backend/utils/misc/guc_tables.c           |  11 ++
 src/backend/utils/misc/postgresql.conf.sample |   3 +
 src/backend/utils/mmgr/aset.c                 |  33 ++++
 src/backend/utils/mmgr/generation.c           |  16 ++
 src/backend/utils/mmgr/slab.c                 |  15 +-
 src/include/catalog/pg_proc.dat               |   6 +-
 src/include/storage/proc.h                    |   7 +
 src/include/utils/backend_status.h            | 120 ++++++++++--
 src/test/regress/expected/rules.out           |   4 +-
 20 files changed, 537 insertions(+), 35 deletions(-)

diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index bcc49aec45..4c735e180f 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -2133,6 +2133,36 @@ include_dir 'conf.d'
       </listitem>
      </varlistentry>
 
+     <varlistentry id="guc-max-total-backend-memory" xreflabel="max_total_backend_memory">
+      <term><varname>max_total_backend_memory</varname> (<type>integer</type>)
+      <indexterm>
+       <primary><varname>max_total_backend_memory</varname> configuration parameter</primary>
+      </indexterm>
+      </term>
+      <listitem>
+       <para>
+        Specifies a limit to the amount of memory (MB) that may be allocated to
+        backends in total (i.e. this is not a per user or per backend limit).
+        If unset, or set to 0 it is disabled.  At databse startup
+        max_total_backend_memory is reduced by shared_memory_size_mb
+        (includes shared buffers and other memory required for initialization).
+        Each backend process is intialized with a 1MB local allowance which
+        also reduces max_total_bkend_mem_bytes_available. Keep this in mind
+        when setting this value. A backend request that would exhaust the limit
+        will be denied with an out of memory error causing that backend's
+        current query/transaction to fail. Further requests will not be
+        allocated until dropping below the limit.  This limit does not affect
+        auxiliary backend processes
+        <xref linkend="glossary-auxiliary-proc"/> or the postmaster process.
+        Backend memory allocations (<varname>allocated_bytes</varname>) are
+        displayed in the
+        <link linkend="monitoring-pg-stat-memory-allocation-view"><structname>pg_stat_memory_allocation</structname></link>
+        view.  Due to the dynamic nature of memory allocations, this limit is
+        not exact.
+       </para>
+      </listitem>
+     </varlistentry>
+
      </variablelist>
      </sect2>
 
diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 70b3441412..704a75bd6e 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -5704,10 +5704,7 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
       </para>
      <para>
       Memory currently allocated to this backend in bytes. This is the balance
-      of bytes allocated and freed by this backend. Dynamic shared memory
-      allocations are included only in the value displayed for the backend that
-      created them, they are not included in the value for backends that are
-      attached to them to avoid double counting.
+      of bytes allocated and freed by this backend.
      </para></entry>
      </row>
 
@@ -5824,6 +5821,39 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
      </para></entry>
      </row>
 
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>max_total_backend_memory_bytes</structfield> <type>bigint</type>
+      </para>
+     <para>
+      Reports the user defined backend maximum allowed shared memory in bytes.
+      0 if disabled or not set. See
+      <xref linkend="guc-max-total-backend-memory"/>.
+     </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>max_total_bkend_mem_bytes_available</structfield> <type>bigint</type>
+      </para>
+     <para>
+      Tracks max_total_backend_memory (in bytes) available for allocation. At
+      database startup, max_total_bkend_mem_bytes_available is reduced by the
+      byte equivalent of shared_memory_size_mb. Each backend process is
+      intialized with a 1MB local allowance which also reduces
+      max_total_bkend_mem_bytes_available. A process's allocation requests
+      reduce it's local allowance. If a process's allocation request exceeds
+      it's remaining allowance, an attempt is made to refill the local
+      allowance from max_total_bkend_mem_bytes_available. If the refill request
+      fails, then the requesting process will fail with an out of memory error
+      resulting in the cancellation of that process's active query/transaction.
+      The default refill allocation quantity is 1MB.  If a request is greater
+      than 1MB, an attempt will be made to allocate the full amount. If
+      max_total_backend_memory is disabled, this will be -1.
+      <xref linkend="guc-max-total-backend-memory"/>.
+     </para></entry>
+     </row>
+
      <row>
       <entry role="catalog_table_entry"><para role="column_definition">
        <structfield>global_dsm_allocated_bytes</structfield> <type>bigint</type>
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 6876564904..8108d3467f 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -1359,6 +1359,8 @@ SELECT
         S.datid AS datid,
         current_setting('shared_memory_size', true) as shared_memory_size,
         (current_setting('shared_memory_size_in_huge_pages', true))::integer as shared_memory_size_in_huge_pages,
+        pg_size_bytes(current_setting('max_total_backend_memory', true)) as max_total_backend_memory_bytes,
+        S.max_total_bkend_mem_bytes_available,
         S.global_dsm_allocated_bytes,
         sums.total_aset_allocated_bytes,
         sums.total_dsm_allocated_bytes,
diff --git a/src/backend/port/sysv_shmem.c b/src/backend/port/sysv_shmem.c
index eaba244bc9..463bf2e90f 100644
--- a/src/backend/port/sysv_shmem.c
+++ b/src/backend/port/sysv_shmem.c
@@ -34,6 +34,7 @@
 #include "storage/fd.h"
 #include "storage/ipc.h"
 #include "storage/pg_shmem.h"
+#include "utils/backend_status.h"
 #include "utils/guc_hooks.h"
 #include "utils/pidfile.h"
 
@@ -903,6 +904,14 @@ PGSharedMemoryReAttach(void)
 	dsm_set_control_handle(hdr->dsm_control);
 
 	UsedShmemSegAddr = hdr;		/* probably redundant */
+
+	/*
+	 * Init allocated bytes to avoid double counting parent allocation for
+	 * fork/exec processes. Forked processes perform this action in
+	 * InitPostmasterChild. For EXEC_BACKEND processes we have to wait for
+	 * shared memory to be reattached.
+	 */
+	pgstat_init_allocated_bytes();
 }
 
 /*
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 4c49393fc5..06a773c8bb 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -540,6 +540,7 @@ typedef struct
 #endif
 	char		my_exec_path[MAXPGPATH];
 	char		pkglib_path[MAXPGPATH];
+	int			max_total_bkend_mem;
 } BackendParameters;
 
 static void read_backend_variables(char *id, Port *port);
@@ -6122,6 +6123,8 @@ save_backend_variables(BackendParameters *param, Port *port,
 
 	strlcpy(param->pkglib_path, pkglib_path, MAXPGPATH);
 
+	param->max_total_bkend_mem = max_total_bkend_mem;
+
 	return true;
 }
 
@@ -6352,6 +6355,8 @@ restore_backend_variables(BackendParameters *param, Port *port)
 
 	strlcpy(pkglib_path, param->pkglib_path, MAXPGPATH);
 
+	max_total_bkend_mem = param->max_total_bkend_mem;
+
 	/*
 	 * We need to restore fd.c's counts of externally-opened FDs; to avoid
 	 * confusion, be sure to do this after restoring max_safe_fds.  (Note:
diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c
index 16e2bded59..68780de717 100644
--- a/src/backend/storage/ipc/dsm_impl.c
+++ b/src/backend/storage/ipc/dsm_impl.c
@@ -254,6 +254,16 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 		return true;
 	}
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+	{
+		ereport(elevel,
+				(errcode_for_dynamic_shared_memory(),
+				 errmsg("out of memory for segment \"%s\" - exceeds max_total_backend_memory: %m",
+						name)));
+		return false;
+	}
+
 	/*
 	 * Create new segment or open an existing one for attach.
 	 *
@@ -522,6 +532,10 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 		int			flags = IPCProtection;
 		size_t		segsize;
 
+		/* Do not exceed maximum allowed memory allocation */
+		if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+			return false;
+
 		/*
 		 * Allocate the memory BEFORE acquiring the resource, so that we don't
 		 * leak the resource if memory allocation fails.
@@ -716,6 +730,10 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 		return true;
 	}
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+		return false;
+
 	/* Create new segment or open an existing one for attach. */
 	if (op == DSM_OP_CREATE)
 	{
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index d86fbdfd9b..cee66af8f0 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -51,6 +51,7 @@
 #include "storage/procsignal.h"
 #include "storage/spin.h"
 #include "storage/standby.h"
+#include "utils/guc.h"
 #include "utils/timeout.h"
 #include "utils/timestamp.h"
 
@@ -182,6 +183,50 @@ InitProcGlobal(void)
 	pg_atomic_init_u32(&ProcGlobal->clogGroupFirst, INVALID_PGPROCNO);
 	pg_atomic_init_u64(&ProcGlobal->global_dsm_allocation, 0);
 
+	/* Setup backend memory limiting if configured */
+	if (max_total_bkend_mem > 0)
+	{
+		/*
+		 * Convert max_total_bkend_mem to bytes, account for
+		 * shared_memory_size, and initialize max_total_bkend_mem_bytes.
+		 */
+		int			result = 0;
+
+		/* Get integer value of shared_memory_size */
+		if (parse_int(GetConfigOption("shared_memory_size", true, false), &result, 0, NULL))
+		{
+			/*
+			 * Error on startup if backend memory limit is less than shared
+			 * memory size. Warn on startup if backend memory available is
+			 * less than arbitrarily picked value of 100MB.
+			 */
+
+			if (max_total_bkend_mem - result <= 0)
+			{
+				ereport(ERROR,
+						errmsg("configured max_total_backend_memory %dMB is <= shared_memory_size %dMB",
+							   max_total_bkend_mem, result),
+						errhint("Disable or increase the configuration parameter \"max_total_backend_memory\"."));
+			}
+			else if (max_total_bkend_mem - result <= 100)
+			{
+				ereport(WARNING,
+						errmsg("max_total_backend_memory %dMB - shared_memory_size %dMB is <= 100MB",
+							   max_total_bkend_mem, result),
+						errhint("Consider increasing the configuration parameter \"max_total_backend_memory\"."));
+			}
+
+			/*
+			 * Account for shared memory size and initialize
+			 * max_total_bkend_mem_bytes.
+			 */
+			pg_atomic_init_u64(&ProcGlobal->max_total_bkend_mem_bytes,
+							   (uint64) max_total_bkend_mem * 1024 * 1024 - (uint64) result * 1024 * 1024);
+		}
+		else
+			ereport(ERROR, errmsg("max_total_backend_memory initialization is unable to parse shared_memory_size"));
+	}
+
 	/*
 	 * Create and initialize all the PGPROC structures we'll need.  There are
 	 * five separate consumers: (1) normal backends, (2) autovacuum workers
diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c
index f921c4bbde..4103cbedda 100644
--- a/src/backend/utils/activity/backend_status.c
+++ b/src/backend/utils/activity/backend_status.c
@@ -45,6 +45,12 @@
 bool		pgstat_track_activities = false;
 int			pgstat_track_activity_query_size = 1024;
 
+/*
+ * Max backend memory allocation allowed (MB). 0 = disabled.
+ * Centralized bucket ProcGlobal->max_total_bkend_mem is initialized
+ * as a byte representation of this value in InitProcGlobal().
+ */
+int			max_total_bkend_mem = 0;
 
 /* exposed so that backend_progress.c can access it */
 PgBackendStatus *MyBEEntry = NULL;
@@ -68,6 +74,31 @@ uint64	   *my_generation_allocated_bytes = &local_my_generation_allocated_bytes;
 uint64		local_my_slab_allocated_bytes = 0;
 uint64	   *my_slab_allocated_bytes = &local_my_slab_allocated_bytes;
 
+/*
+ * Define initial allocation allowance for a backend.
+ *
+ * NOTE: initial_allocation_allowance && allocation_allowance_refill_qty
+ * may be candidates for future GUC variables. Arbitrary 1MB selected initially.
+ */
+uint64		initial_allocation_allowance = 1024 * 1024;
+uint64		allocation_allowance_refill_qty = 1024 * 1024;
+
+/*
+ * Local counter to manage shared memory allocations. At backend startup, set to
+ * initial_allocation_allowance via pgstat_init_allocated_bytes(). Decrease as
+ * memory is malloc'd. When exhausted, atomically refill if available from
+ * ProcGlobal->max_total_bkend_mem via exceeds_max_total_bkend_mem().
+ */
+uint64		allocation_allowance = 0;
+
+/*
+ * Local counter of free'd shared memory. Return to global
+ * max_total_bkend_mem when return threshold is met. Arbitrary 1MB bytes
+ * selected initially.
+ */
+uint64		allocation_return = 0;
+uint64		allocation_return_threshold = 1024 * 1024;
+
 static PgBackendStatus *BackendStatusArray = NULL;
 static char *BackendAppnameBuffer = NULL;
 static char *BackendClientHostnameBuffer = NULL;
@@ -1271,6 +1302,8 @@ pgstat_set_allocated_bytes_storage(uint64 *allocated_bytes,
 
 	my_slab_allocated_bytes = slab_allocated_bytes;
 	*slab_allocated_bytes = local_my_slab_allocated_bytes;
+
+	return;
 }
 
 /*
@@ -1294,6 +1327,23 @@ pgstat_reset_allocated_bytes_storage(void)
 								*my_dsm_allocated_bytes);
 	}
 
+	/*
+	 * When limiting maximum backend memory, return this backend's memory
+	 * allocations to global.
+	 */
+	if (max_total_bkend_mem)
+	{
+		volatile PROC_HDR *procglobal = ProcGlobal;
+
+		pg_atomic_add_fetch_u64(&procglobal->max_total_bkend_mem_bytes,
+								*my_allocated_bytes + allocation_allowance +
+								allocation_return);
+
+		/* Reset memory allocation variables */
+		allocation_allowance = 0;
+		allocation_return = 0;
+	}
+
 	/* Reset memory allocation variables */
 	*my_allocated_bytes = local_my_allocated_bytes = 0;
 	*my_aset_allocated_bytes = local_my_aset_allocated_bytes = 0;
@@ -1307,4 +1357,137 @@ pgstat_reset_allocated_bytes_storage(void)
 	my_dsm_allocated_bytes = &local_my_dsm_allocated_bytes;
 	my_generation_allocated_bytes = &local_my_generation_allocated_bytes;
 	my_slab_allocated_bytes = &local_my_slab_allocated_bytes;
+
+	return;
+}
+
+/*
+ * Determine if allocation request will exceed max backend memory allowed.
+ * Do not apply to auxiliary processes.
+ * Refill allocation request bucket when needed/possible.
+ */
+bool
+exceeds_max_total_bkend_mem(uint64 allocation_request)
+{
+	bool		result = false;
+
+	/*
+	 * When limiting maximum backend memory, attempt to refill allocation
+	 * request bucket if needed.
+	 */
+	if (max_total_bkend_mem && allocation_request > allocation_allowance &&
+		ProcGlobal != NULL)
+	{
+		volatile PROC_HDR *procglobal = ProcGlobal;
+		uint64		available_max_total_bkend_mem = 0;
+		bool		sts = false;
+
+		/*
+		 * If allocation request is larger than memory refill quantity then
+		 * attempt to increase allocation allowance with requested amount,
+		 * otherwise fall through. If this refill fails we do not have enough
+		 * memory to meet the request.
+		 */
+		if (allocation_request >= allocation_allowance_refill_qty)
+		{
+			while ((available_max_total_bkend_mem = pg_atomic_read_u64(&procglobal->max_total_bkend_mem_bytes)) >= allocation_request)
+			{
+				if ((result = pg_atomic_compare_exchange_u64(&procglobal->max_total_bkend_mem_bytes,
+															 &available_max_total_bkend_mem,
+															 available_max_total_bkend_mem - allocation_request)))
+				{
+					allocation_allowance = allocation_allowance + allocation_request;
+					break;
+				}
+			}
+
+			/*
+			 * Exclude auxiliary and Postmaster processes from the check.
+			 * Return false. While we want to exclude them from the check, we
+			 * do not want to exclude them from the above allocation handling.
+			 */
+			if (MyAuxProcType != NotAnAuxProcess || MyProcPid == PostmasterPid)
+				return false;
+
+			/*
+			 * If the atomic exchange fails (result == false), we do not have
+			 * enough reserve memory to meet the request. Negate result to
+			 * return the proper value.
+			 */
+
+			return !result;
+		}
+
+		/*
+		 * Attempt to increase allocation allowance by memory refill quantity.
+		 * If available memory is/becomes less than memory refill quantity,
+		 * fall through to attempt to allocate remaining available memory.
+		 */
+		while ((available_max_total_bkend_mem = pg_atomic_read_u64(&procglobal->max_total_bkend_mem_bytes)) >= allocation_allowance_refill_qty)
+		{
+			if ((sts = pg_atomic_compare_exchange_u64(&procglobal->max_total_bkend_mem_bytes,
+													  &available_max_total_bkend_mem,
+													  available_max_total_bkend_mem - allocation_allowance_refill_qty)))
+			{
+				allocation_allowance = allocation_allowance + allocation_allowance_refill_qty;
+				break;
+			}
+		}
+
+		if (!sts)
+		{
+			/*
+			 * If available_max_total_bkend_mem is 0, no memory is currently
+			 * available to refill with, otherwise attempt to allocate
+			 * remaining memory available if it exceeds the requested amount
+			 * or the requested amount if more than requested amount gets
+			 * returned while looping.
+			 */
+			while ((available_max_total_bkend_mem = (int64) pg_atomic_read_u64(&procglobal->max_total_bkend_mem_bytes)) > 0)
+			{
+				uint64		newval = 0;
+
+				/*
+				 * If available memory is less than requested allocation we
+				 * cannot fulfil request.
+				 */
+				if (available_max_total_bkend_mem < allocation_request)
+					break;
+
+				/*
+				 * If we happen to loop and a large chunk of memory has been
+				 * returned to global, allocate request amount only.
+				 */
+				if (available_max_total_bkend_mem > allocation_request)
+					newval = available_max_total_bkend_mem - allocation_request;
+
+				/* Allocate memory */
+				if ((sts = pg_atomic_compare_exchange_u64(&procglobal->max_total_bkend_mem_bytes,
+														  &available_max_total_bkend_mem,
+														  newval)))
+				{
+					allocation_allowance = allocation_allowance +
+						newval == 0 ? available_max_total_bkend_mem : allocation_request;
+
+					break;
+				}
+			}
+		}
+
+		/*
+		 * If refill is not successful, we return true, memory limit exceeded
+		 */
+		if (!sts)
+			result = true;
+	}
+
+	/*
+	 * Exclude auxiliary and postmaster processes from the check. Return false.
+	 * While we want to exclude them from the check, we do not want to exclude
+	 * them from the above allocation handling.
+	 */
+	if (MyAuxProcType != NotAnAuxProcess || MyProcPid == PostmasterPid)
+		result = false;
+
+	return result;
 }
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index a5fd5e6964..70c4a0b2bd 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -2056,7 +2056,7 @@ pg_stat_get_memory_allocation(PG_FUNCTION_ARGS)
 Datum
 pg_stat_get_global_memory_allocation(PG_FUNCTION_ARGS)
 {
-#define PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS	2
+#define PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS	3
 	TupleDesc	tupdesc;
 	Datum		values[PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS] = {0};
 	bool		nulls[PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS] = {0};
@@ -2066,15 +2066,23 @@ pg_stat_get_global_memory_allocation(PG_FUNCTION_ARGS)
 	tupdesc = CreateTemplateTupleDesc(PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 1, "datid",
 					   OIDOID, -1, 0);
-	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "global_dsm_allocated_bytes",
+	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "max_total_bkend_mem_bytes_available",
+					   INT8OID, -1, 0);
+	TupleDescInitEntry(tupdesc, (AttrNumber) 3, "global_dsm_allocated_bytes",
 					   INT8OID, -1, 0);
 	BlessTupleDesc(tupdesc);
 
 	/* datid */
 	values[0] = ObjectIdGetDatum(MyDatabaseId);
 
-	/* get global_dsm_allocated_bytes */
-	values[1] = Int64GetDatum(pg_atomic_read_u64(&procglobal->global_dsm_allocation));
+	/* Get max_total_bkend_mem_bytes - return -1 if disabled */
+	if (max_total_bkend_mem == 0)
+		values[1] = Int64GetDatum(-1);
+	else
+		values[1] = Int64GetDatum(pg_atomic_read_u64(&procglobal->max_total_bkend_mem_bytes));
+
+	/* Get global_dsm_allocated_bytes */
+	values[2] = Int64GetDatum(pg_atomic_read_u64(&procglobal->global_dsm_allocation));
 
 	/* Returns the record as Datum */
 	PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls)));
diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c
index 012d4a0b1f..cd68e5265a 100644
--- a/src/backend/utils/hash/dynahash.c
+++ b/src/backend/utils/hash/dynahash.c
@@ -104,7 +104,6 @@
 #include "utils/dynahash.h"
 #include "utils/memutils.h"
 
-
 /*
  * Constants
  *
@@ -359,7 +358,6 @@ hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
 	Assert(flags & HASH_ELEM);
 	Assert(info->keysize > 0);
 	Assert(info->entrysize >= info->keysize);
-
 	/*
 	 * For shared hash tables, we have a local hash header (HTAB struct) that
 	 * we allocate in TopMemoryContext; all else is in shared memory.
@@ -377,6 +375,7 @@ hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
 	}
 	else
 	{
+		/* Set up to allocate the hash header */
 		/* Create the hash table's private memory context */
 		if (flags & HASH_CONTEXT)
 			CurrentDynaHashCxt = info->hcxt;
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index 7b8eeb7dbb..a7df801f77 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -172,8 +172,16 @@ InitPostmasterChild(void)
 				 errmsg_internal("could not set postmaster death monitoring pipe to FD_CLOEXEC mode: %m")));
 #endif
 
+	/*
+	 * Init pgstat allocated bytes counters here for forked backends.
+	 * Fork/exec backends have not yet reattached to shared memory at this
+	 * point. They will init pgstat allocated bytes counters in
+	 * PGSharedMemoryReAttach.
+	 */
+#ifndef EXEC_BACKEND
 	/* Init allocated bytes to avoid double counting parent allocation */
 	pgstat_init_allocated_bytes();
+#endif
 }
 
 /*
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index 8062589efd..bde8e28365 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -3497,6 +3497,17 @@ struct config_int ConfigureNamesInt[] =
 		NULL, NULL, NULL
 	},
 
+	{
+		{"max_total_backend_memory", PGC_SU_BACKEND, RESOURCES_MEM,
+			gettext_noop("Restrict total backend memory allocations to this max."),
+			gettext_noop("0 turns this feature off."),
+			GUC_UNIT_MB
+		},
+		&max_total_bkend_mem,
+		0, 0, INT_MAX,
+		NULL, NULL, NULL
+	},
+
 	/* End-of-list marker */
 	{
 		{NULL, 0, 0, NULL, NULL}, NULL, 0, 0, 0, NULL, NULL, NULL
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index ee49ca3937..697a619266 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -157,6 +157,9 @@
 					#   mmap
 					# (change requires restart)
 #min_dynamic_shared_memory = 0MB	# (change requires restart)
+#max_total_backend_memory = 0MB		# Restrict total backend memory allocations
+									# to this max (in MB). 0 turns this feature
+									# off.
 
 # - Disk -
 
diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index f3f5945fdf..4a83a2f60f 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -440,6 +440,18 @@ AllocSetContextCreateInternal(MemoryContext parent,
 	else
 		firstBlockSize = Max(firstBlockSize, initBlockSize);
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (exceeds_max_total_bkend_mem(firstBlockSize))
+	{
+		if (TopMemoryContext)
+			MemoryContextStats(TopMemoryContext);
+		ereport(ERROR,
+				(errcode(ERRCODE_OUT_OF_MEMORY),
+				 errmsg("out of memory - exceeds max_total_backend_memory"),
+				 errdetail("Failed while creating memory context \"%s\".",
+						   name)));
+	}
+
 	/*
 	 * Allocate the initial block.  Unlike other aset.c blocks, it starts with
 	 * the context header and its block header follows that.
@@ -741,6 +753,11 @@ AllocSetAlloc(MemoryContext context, Size size)
 #endif
 
 		blksize = chunk_size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
+
+		/* Do not exceed maximum allowed memory allocation */
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		block = (AllocBlock) malloc(blksize);
 		if (block == NULL)
 			return NULL;
@@ -938,6 +955,10 @@ AllocSetAlloc(MemoryContext context, Size size)
 		while (blksize < required_size)
 			blksize <<= 1;
 
+		/* Do not exceed maximum allowed memory allocation */
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		/* Try to allocate it */
 		block = (AllocBlock) malloc(blksize);
 
@@ -1176,6 +1197,18 @@ AllocSetRealloc(void *pointer, Size size)
 		blksize = chksize + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
 		oldblksize = block->endptr - ((char *) block);
 
+		/*
+		 * Do not exceed maximum allowed memory allocation. NOTE: checking for
+		 * the full size here rather than just the amount of increased
+		 * allocation to prevent a potential underflow of *my_allocation
+		 * allowance in cases where blksize - oldblksize does not trigger a
+		 * refill but blksize is greater than *my_allocation_allowance.
+		 * Underflow would occur with the call below to
+		 * pgstat_report_allocated_bytes_increase()
+		 */
+		if (blksize > oldblksize && exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		block = (AllocBlock) realloc(block, blksize);
 		if (block == NULL)
 		{
diff --git a/src/backend/utils/mmgr/generation.c b/src/backend/utils/mmgr/generation.c
index 5708e8da7a..584b2ec8ef 100644
--- a/src/backend/utils/mmgr/generation.c
+++ b/src/backend/utils/mmgr/generation.c
@@ -201,6 +201,16 @@ GenerationContextCreate(MemoryContext parent,
 	else
 		allocSize = Max(allocSize, initBlockSize);
 
+	if (exceeds_max_total_bkend_mem(allocSize))
+	{
+		MemoryContextStats(TopMemoryContext);
+		ereport(ERROR,
+				(errcode(ERRCODE_OUT_OF_MEMORY),
+				 errmsg("out of memory - exceeds max_total_backend_memory"),
+				 errdetail("Failed while creating memory context \"%s\".",
+						   name)));
+	}
+
 	/*
 	 * Allocate the initial block.  Unlike other generation.c blocks, it
 	 * starts with the context header and its block header follows that.
@@ -380,6 +390,9 @@ GenerationAlloc(MemoryContext context, Size size)
 	{
 		Size		blksize = required_size + Generation_BLOCKHDRSZ;
 
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		block = (GenerationBlock *) malloc(blksize);
 		if (block == NULL)
 			return NULL;
@@ -483,6 +496,9 @@ GenerationAlloc(MemoryContext context, Size size)
 			if (blksize < required_size)
 				blksize = pg_nextpower2_size_t(required_size);
 
+			if (exceeds_max_total_bkend_mem(blksize))
+				return NULL;
+
 			block = (GenerationBlock *) malloc(blksize);
 
 			if (block == NULL)
diff --git a/src/backend/utils/mmgr/slab.c b/src/backend/utils/mmgr/slab.c
index b436587bdd..9754c6d2f4 100644
--- a/src/backend/utils/mmgr/slab.c
+++ b/src/backend/utils/mmgr/slab.c
@@ -356,7 +356,16 @@ SlabContextCreate(MemoryContext parent,
 		elog(ERROR, "block size %zu for slab is too small for %zu-byte chunks",
 			 blockSize, chunkSize);
 
-
+	/* Do not exceed maximum allowed memory allocation */
+	if (exceeds_max_total_bkend_mem(Slab_CONTEXT_HDRSZ(chunksPerBlock)))
+	{
+		MemoryContextStats(TopMemoryContext);
+		ereport(ERROR,
+				(errcode(ERRCODE_OUT_OF_MEMORY),
+				 errmsg("out of memory - exceeds max_total_backend_memory"),
+				 errdetail("Failed while creating memory context \"%s\".",
+						   name)));
+	}
 
 	slab = (SlabContext *) malloc(Slab_CONTEXT_HDRSZ(chunksPerBlock));
 	if (slab == NULL)
@@ -559,6 +568,10 @@ SlabAlloc(MemoryContext context, Size size)
 		}
 		else
 		{
+			/* Do not exceed maximum allowed memory allocation */
+			if (exceeds_max_total_bkend_mem(slab->blockSize))
+				return NULL;
+
 			block = (SlabBlock *) malloc(slab->blockSize);
 
 			if (unlikely(block == NULL))
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index a6f52a4db4..97196b7eb1 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -5440,9 +5440,9 @@
   descr => 'statistics: global memory allocation information',
   proname => 'pg_stat_get_global_memory_allocation', proisstrict => 'f',
   provolatile => 's', proparallel => 'r', prorettype => 'record',
-  proargtypes => '', proallargtypes => '{oid,int8}',
-  proargmodes => '{o,o}',
-  proargnames => '{datid,global_dsm_allocated_bytes}',
+  proargtypes => '', proallargtypes => '{oid,int8,int8}',
+  proargmodes => '{o,o,o}',
+  proargnames => '{datid,max_total_bkend_mem_bytes_available,global_dsm_allocated_bytes}',
   prosrc =>'pg_stat_get_global_memory_allocation' },
 { oid => '2022',
   descr => 'statistics: information about currently active backends',
diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h
index c2c878219d..a2a5364a85 100644
--- a/src/include/storage/proc.h
+++ b/src/include/storage/proc.h
@@ -406,6 +406,13 @@ typedef struct PROC_HDR
 	int			startupBufferPinWaitBufId;
 	/* Global dsm allocations */
 	pg_atomic_uint64 global_dsm_allocation;
+
+	/*
+	 * Max backend memory allocation tracker. Used/Initialized when
+	 * max_total_bkend_mem > 0 as max_total_bkend_mem (MB) converted to bytes.
+	 * Decreases/increases with free/malloc of backend memory.
+	 */
+	pg_atomic_uint64 max_total_bkend_mem_bytes;
 } PROC_HDR;
 
 extern PGDLLIMPORT PROC_HDR *ProcGlobal;
diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h
index 6434ece1ef..4eef3470a5 100644
--- a/src/include/utils/backend_status.h
+++ b/src/include/utils/backend_status.h
@@ -15,6 +15,7 @@
 #include "libpq/pqcomm.h"
 #include "miscadmin.h"			/* for BackendType */
 #include "storage/backendid.h"
+#include "storage/proc.h"
 #include "utils/backend_progress.h"
 
 
@@ -304,6 +305,7 @@ typedef struct LocalPgBackendStatus
  */
 extern PGDLLIMPORT bool pgstat_track_activities;
 extern PGDLLIMPORT int pgstat_track_activity_query_size;
+extern PGDLLIMPORT int max_total_bkend_mem;
 
 
 /* ----------
@@ -316,6 +318,10 @@ extern PGDLLIMPORT uint64 *my_aset_allocated_bytes;
 extern PGDLLIMPORT uint64 *my_dsm_allocated_bytes;
 extern PGDLLIMPORT uint64 *my_generation_allocated_bytes;
 extern PGDLLIMPORT uint64 *my_slab_allocated_bytes;
+extern PGDLLIMPORT uint64 allocation_allowance;
+extern PGDLLIMPORT uint64 initial_allocation_allowance;
+extern PGDLLIMPORT uint64 allocation_return;
+extern PGDLLIMPORT uint64 allocation_return_threshold;
 
 
 /* ----------
@@ -363,6 +369,7 @@ extern int	pgstat_fetch_stat_numbackends(void);
 extern PgBackendStatus *pgstat_fetch_stat_beentry(BackendId beid);
 extern LocalPgBackendStatus *pgstat_fetch_stat_local_beentry(int beid);
 extern char *pgstat_clip_activity(const char *raw_activity);
+extern bool exceeds_max_total_bkend_mem(uint64 allocation_request);
 
 /* ----------
  * pgstat_report_allocated_bytes_decrease() -
@@ -378,34 +385,44 @@ pgstat_report_allocated_bytes_decrease(int64 proc_allocated_bytes,
 {
 	uint64		temp;
 
-	/* Avoid allocated_bytes unsigned integer overflow on decrease */
+	/* Sanity check: my allocated bytes should never drop below zero */
 	if (pg_sub_u64_overflow(*my_allocated_bytes, proc_allocated_bytes, &temp))
 	{
-		/* On overflow, set pgstat count of allocated bytes to zero */
+		/* On overflow, set allocated bytes and allocator type bytes to zero */
 		*my_allocated_bytes = 0;
-
-		switch (pg_allocator_type)
+		*my_aset_allocated_bytes = 0;
+		*my_dsm_allocated_bytes = 0;
+		*my_generation_allocated_bytes = 0;
+		*my_slab_allocated_bytes = 0;
+
+		/* Add freed memory to allocation return counter. */
+		allocation_return += proc_allocated_bytes;
+
+		/*
+		 * Return freed memory to the global counter if return threshold is
+		 * met.
+		 */
+		if (max_total_bkend_mem && allocation_return >= allocation_return_threshold)
 		{
-			case PG_ALLOC_ASET:
-				*my_aset_allocated_bytes = 0;
-				break;
-			case PG_ALLOC_DSM:
-				*my_dsm_allocated_bytes = 0;
-				break;
-			case PG_ALLOC_GENERATION:
-				*my_generation_allocated_bytes = 0;
-				break;
-			case PG_ALLOC_SLAB:
-				*my_slab_allocated_bytes = 0;
-				break;
+			if (ProcGlobal)
+			{
+				volatile PROC_HDR *procglobal = ProcGlobal;
+
+				/* Add to global tracker */
+				pg_atomic_add_fetch_u64(&procglobal->max_total_bkend_mem_bytes,
+										allocation_return);
+
+				/* Restart the count */
+				allocation_return = 0;
+			}
 		}
 	}
 	else
 	{
-		/* decrease allocation */
-		*my_allocated_bytes -= proc_allocated_bytes;
+		/* Add freed memory to allocation return counter */
+		allocation_return += proc_allocated_bytes;
 
-		/* Decrease allocator type allocated bytes. */
+		/* Decrease allocator type allocated bytes */
 		switch (pg_allocator_type)
 		{
 			case PG_ALLOC_ASET:
@@ -427,6 +444,30 @@ pgstat_report_allocated_bytes_decrease(int64 proc_allocated_bytes,
 				*my_slab_allocated_bytes -= proc_allocated_bytes;
 				break;
 		}
+
+		/* decrease allocation */
+		*my_allocated_bytes = *my_aset_allocated_bytes +
+			*my_dsm_allocated_bytes + *my_generation_allocated_bytes +
+			*my_slab_allocated_bytes;
+
+		/*
+		 * Return freed memory to the global counter if return threshold is
+		 * met.
+		 */
+		if (max_total_bkend_mem && allocation_return >= allocation_return_threshold)
+		{
+			if (ProcGlobal)
+			{
+				volatile PROC_HDR *procglobal = ProcGlobal;
+
+				/* Add to global tracker */
+				pg_atomic_add_fetch_u64(&procglobal->max_total_bkend_mem_bytes,
+										allocation_return);
+
+				/* Restart the count */
+				allocation_return = 0;
+			}
+		}
 	}
 
 	return;
@@ -444,7 +485,13 @@ static inline void
 pgstat_report_allocated_bytes_increase(int64 proc_allocated_bytes,
 									   int pg_allocator_type)
 {
-	*my_allocated_bytes += proc_allocated_bytes;
+	uint64		temp;
+
+	/* Sanity check: my allocated bytes should never drop below zero */
+	if (pg_sub_u64_overflow(allocation_allowance, proc_allocated_bytes, &temp))
+		allocation_allowance = 0;
+	else
+		allocation_allowance -= proc_allocated_bytes;
 
 	/* Increase allocator type allocated bytes */
 	switch (pg_allocator_type)
@@ -469,6 +516,9 @@ pgstat_report_allocated_bytes_increase(int64 proc_allocated_bytes,
 			break;
 	}
 
+	*my_allocated_bytes = *my_aset_allocated_bytes + *my_dsm_allocated_bytes +
+		*my_generation_allocated_bytes + *my_slab_allocated_bytes;
+
 	return;
 }
 
@@ -488,6 +538,36 @@ pgstat_init_allocated_bytes(void)
 	*my_generation_allocated_bytes = 0;
 	*my_slab_allocated_bytes = 0;
 
+	/* If we're limiting backend memory */
+	if (max_total_bkend_mem)
+	{
+		volatile PROC_HDR *procglobal = ProcGlobal;
+		uint64		available_max_total_bkend_mem = 0;
+
+		allocation_return = 0;
+		allocation_allowance = 0;
+
+		/* Account for the initial allocation allowance */
+		while ((available_max_total_bkend_mem = pg_atomic_read_u64(&procglobal->max_total_bkend_mem_bytes)) >= initial_allocation_allowance)
+		{
+			/*
+			 * On success populate allocation_allowance. Failure here will
+			 * result in the backend's first invocation of
+			 * exceeds_max_total_bkend_mem allocating requested, default, or
+			 * available memory or result in an out of memory error.
+			 */
+			if (pg_atomic_compare_exchange_u64(&procglobal->max_total_bkend_mem_bytes,
+											   &available_max_total_bkend_mem,
+											   available_max_total_bkend_mem -
+											   initial_allocation_allowance))
+			{
+				allocation_allowance = initial_allocation_allowance;
+
+				break;
+			}
+		}
+	}
+
 	return;
 }
 
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index 77c4a18e26..403715a3d5 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1881,13 +1881,15 @@ pg_stat_global_memory_allocation| WITH sums AS (
  SELECT s.datid,
     current_setting('shared_memory_size'::text, true) AS shared_memory_size,
     (current_setting('shared_memory_size_in_huge_pages'::text, true))::integer AS shared_memory_size_in_huge_pages,
+    pg_size_bytes(current_setting('max_total_backend_memory'::text, true)) AS max_total_backend_memory_bytes,
+    s.max_total_bkend_mem_bytes_available,
     s.global_dsm_allocated_bytes,
     sums.total_aset_allocated_bytes,
     sums.total_dsm_allocated_bytes,
     sums.total_generation_allocated_bytes,
     sums.total_slab_allocated_bytes
    FROM sums,
-    (pg_stat_get_global_memory_allocation() s(datid, global_dsm_allocated_bytes)
+    (pg_stat_get_global_memory_allocation() s(datid, max_total_bkend_mem_bytes_available, global_dsm_allocated_bytes)
      LEFT JOIN pg_database d ON ((s.datid = d.oid)));
 pg_stat_gssapi| SELECT pid,
     gss_auth AS gss_authenticated,
-- 
2.25.1

0001-Add-tracking-of-backend-memory-allocated.patchtext/x-patch; charset=UTF-8; name=0001-Add-tracking-of-backend-memory-allocated.patchDownload
From 7da189612aab9cf957efa179c52f4b4578ee2944 Mon Sep 17 00:00:00 2001
From: Reid Thompson <jreidthompson@nc.rr.com>
Date: Thu, 11 Aug 2022 12:01:25 -0400
Subject: [PATCH 1/2] Add tracking of backend memory allocated

Add tracking of backend memory allocated in total and by allocation
type (aset, dsm, generation, slab) by process.

allocated_bytes tracks the current bytes of memory allocated to the
backend process. aset_allocated_bytes, dsm_allocated_bytes,
generation_allocated_bytes and slab_allocated_bytes track the
allocation by type for the backend process. They are updated for the
process as memory is malloc'd/freed.  Memory allocated to items on
the freelist is included.  Dynamic shared memory allocations are
included only in the value displayed for the backend that created
them, they are not included in the value for backends that are
attached to them to avoid double counting. DSM allocations that are
not destroyed by the creating process prior to it's exit are
considered long lived and are tracked in a global counter
global_dsm_allocated_bytes. We limit the floor of allocation
counters to zero. Created views pg_stat_global_memory_allocation and
pg_stat_memory_allocation for access to these trackers.
---
 doc/src/sgml/monitoring.sgml                | 246 ++++++++++++++++++++
 src/backend/catalog/system_views.sql        |  34 +++
 src/backend/storage/ipc/dsm.c               |  11 +-
 src/backend/storage/ipc/dsm_impl.c          |  78 +++++++
 src/backend/storage/lmgr/proc.c             |   1 +
 src/backend/utils/activity/backend_status.c | 114 +++++++++
 src/backend/utils/adt/pgstatfuncs.c         |  84 +++++++
 src/backend/utils/init/miscinit.c           |   3 +
 src/backend/utils/mmgr/aset.c               |  17 ++
 src/backend/utils/mmgr/generation.c         |  15 ++
 src/backend/utils/mmgr/slab.c               |  22 ++
 src/include/catalog/pg_proc.dat             |  17 ++
 src/include/storage/proc.h                  |   2 +
 src/include/utils/backend_status.h          | 156 ++++++++++++-
 src/test/regress/expected/rules.out         |  27 +++
 src/test/regress/expected/stats.out         |  36 +++
 src/test/regress/sql/stats.sql              |  20 ++
 17 files changed, 881 insertions(+), 2 deletions(-)

diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index bce9ae4661..70b3441412 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -5644,6 +5644,252 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
 
  </sect2>
 
+ <sect2 id="monitoring-pg-stat-memory-allocation-view">
+  <title><structname>pg_stat_memory_allocation</structname></title>
+
+  <indexterm>
+   <primary>pg_stat_memory_allocation</primary>
+  </indexterm>
+
+  <para>
+   The <structname>pg_stat_memory_allocation</structname> view will have one
+   row per server process, showing information related to the current memory
+   allocation of that process in total and by allocator type. Due to the
+   dynamic nature of memory allocations the allocated bytes values may not be
+   exact but should be sufficient for the intended purposes. Dynamic shared
+   memory allocations are included only in the value displayed for the backend
+   that created them, they are not included in the value for backends that are
+   attached to them to avoid double counting.  Use
+   <function>pg_size_pretty</function> described in
+   <xref linkend="functions-admin-dbsize"/> to make these values more easily
+   readable.
+  </para>
+
+  <table id="pg-stat-memory-allocation-view" xreflabel="pg_stat_memory_allocation">
+   <title><structname>pg_stat_memory_allocation</structname> View</title>
+   <tgroup cols="1">
+    <thead>
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       Column Type
+      </para>
+      <para>
+       Description
+      </para></entry>
+     </row>
+    </thead>
+
+    <tbody>
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>datid</structfield> <type>oid</type>
+      </para>
+      <para>
+       OID of the database this backend is connected to
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>pid</structfield> <type>integer</type>
+      </para>
+      <para>
+       Process ID of this backend
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>allocated_bytes</structfield> <type>bigint</type>
+      </para>
+     <para>
+      Memory currently allocated to this backend in bytes. This is the balance
+      of bytes allocated and freed by this backend. Dynamic shared memory
+      allocations are included only in the value displayed for the backend that
+      created them, they are not included in the value for backends that are
+      attached to them to avoid double counting.
+     </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>aset_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Memory currently allocated to this backend in bytes via the allocation
+       set allocator.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>dsm_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Memory currently allocated to this backend in bytes via the dynamic
+       shared memory allocator. Upon process exit, dsm allocations that have
+       not been freed are considered long lived and added to
+       <structfield>global_dsm_allocated_bytes</structfield> found in the
+       <link linkend="monitoring-pg-stat-global-memory-allocation-view">
+       <structname>pg_stat_global_memory_allocation</structname></link> view.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>generation_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Memory currently allocated to this backend in bytes via the generation
+       allocator.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>slab_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Memory currently allocated to this backend in bytes via the slab
+       allocator.
+      </para></entry>
+     </row>
+
+    </tbody>
+   </tgroup>
+  </table>
+
+ </sect2>
+
+ <sect2 id="monitoring-pg-stat-global-memory-allocation-view">
+  <title><structname>pg_stat_global_memory_allocation</structname></title>
+
+  <indexterm>
+   <primary>pg_stat_global-memory_allocation</primary>
+  </indexterm>
+
+  <para>
+   The <structname>pg_stat_global_memory_allocation</structname> view will
+   have one row showing information related to current shared memory
+   allocations. Due to the dynamic nature of memory allocations the allocated
+   bytes values may not be exact but should be sufficient for the intended
+   purposes. Use <function>pg_size_pretty</function> described in
+   <xref linkend="functions-admin-dbsize"/> to make the byte populated values
+   more easily readable.
+  </para>
+
+  <table id="pg-stat-global-memory-allocation-view" xreflabel="pg_stat_global_memory_allocation">
+   <title><structname>pg_stat_global_memory_allocation</structname> View</title>
+   <tgroup cols="1">
+    <thead>
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       Column Type
+      </para>
+      <para>
+       Description
+      </para></entry>
+     </row>
+    </thead>
+
+    <tbody>
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>datid</structfield> <type>oid</type>
+      </para>
+      <para>
+       OID of the database this backend is connected to
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>shared_memory_size_mb</structfield> <type>integer</type>
+      </para>
+      <para>
+       Reports the size of the main shared memory area, rounded up to the
+       nearest megabyte. See <xref linkend="guc-shared-memory-size"/>.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>shared_memory_size_in_huge_pages</structfield> <type>bigint</type>
+      </para>
+     <para>
+      Reports the number of huge pages that are needed for the main shared
+      memory area based on the specified huge_page_size. If huge pages are not
+      supported, this will be -1. See
+      <xref linkend="guc-shared-memory-size-in-huge-pages"/>.
+     </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>global_dsm_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Long lived dynamically allocated memory currently allocated to the
+       database. Upon process exit, dsm allocations that have not been freed
+       are considered long lived and added to
+       <structfield>global_dsm_allocated_bytes</structfield>.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>total_aset_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Sum total of <structfield>aset_allocated_bytes</structfield> for all
+       backend processes from
+       <link linkend="monitoring-pg-stat-memory-allocation-view">
+       <structname>pg_stat_memory_allocation</structname></link> view.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>total_dsm_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Sum total of <structfield>dsm_allocated_bytes</structfield> for all
+       backend processes from
+       <link linkend="monitoring-pg-stat-memory-allocation-view">
+       <structname>pg_stat_memory_allocation</structname></link> view.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>total_generation_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Sum total of <structfield>generation_allocated_bytes</structfield> for
+       all backend processes from
+       <link linkend="monitoring-pg-stat-memory-allocation-view">
+       <structname>pg_stat_memory_allocation</structname></link> view.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>total_slab_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Sum total of <structfield>slab_allocated_bytes</structfield> for all
+       backend processes from
+       <link linkend="monitoring-pg-stat-memory-allocation-view">
+       <structname>pg_stat_memory_allocation</structname></link> view.
+      </para></entry>
+     </row>
+
+    </tbody>
+   </tgroup>
+  </table>
+
+ </sect2>
+
  <sect2 id="monitoring-stats-functions">
   <title>Statistics Functions</title>
 
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 6b098234f8..6876564904 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -1332,3 +1332,37 @@ CREATE VIEW pg_stat_subscription_stats AS
         ss.stats_reset
     FROM pg_subscription as s,
          pg_stat_get_subscription_stats(s.oid) as ss;
+
+CREATE VIEW pg_stat_memory_allocation AS
+    SELECT
+        S.datid AS datid,
+        S.pid,
+        S.allocated_bytes,
+        S.aset_allocated_bytes,
+        S.dsm_allocated_bytes,
+        S.generation_allocated_bytes,
+        S.slab_allocated_bytes
+    FROM pg_stat_get_memory_allocation(NULL) AS S
+        LEFT JOIN pg_database AS D ON (S.datid = D.oid);
+
+CREATE VIEW pg_stat_global_memory_allocation AS
+WITH sums AS (
+    SELECT
+        SUM(aset_allocated_bytes) AS total_aset_allocated_bytes,
+        SUM(dsm_allocated_bytes) AS total_dsm_allocated_bytes,
+        SUM(generation_allocated_bytes) AS total_generation_allocated_bytes,
+        SUM(slab_allocated_bytes) AS total_slab_allocated_bytes
+    FROM
+        pg_stat_memory_allocation
+)
+SELECT
+        S.datid AS datid,
+        current_setting('shared_memory_size', true) as shared_memory_size,
+        (current_setting('shared_memory_size_in_huge_pages', true))::integer as shared_memory_size_in_huge_pages,
+        S.global_dsm_allocated_bytes,
+        sums.total_aset_allocated_bytes,
+        sums.total_dsm_allocated_bytes,
+        sums.total_generation_allocated_bytes,
+        sums.total_slab_allocated_bytes
+    FROM sums, pg_stat_get_global_memory_allocation() AS S
+        LEFT JOIN pg_database AS D ON (S.datid = D.oid);
diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c
index 10b029bb16..64b1fecd1c 100644
--- a/src/backend/storage/ipc/dsm.c
+++ b/src/backend/storage/ipc/dsm.c
@@ -775,6 +775,15 @@ dsm_detach_all(void)
 void
 dsm_detach(dsm_segment *seg)
 {
+	/*
+	 * Retain mapped_size to pass into destroy call in cases where the detach
+	 * is the last reference. mapped_size is zeroed as part of the detach
+	 * process, but is needed later in these cases for dsm_allocated_bytes
+	 * accounting.
+	 */
+	Size		local_seg_mapped_size = seg->mapped_size;
+	Size	   *ptr_local_seg_mapped_size = &local_seg_mapped_size;
+
 	/*
 	 * Invoke registered callbacks.  Just in case one of those callbacks
 	 * throws a further error that brings us back here, pop the callback
@@ -855,7 +864,7 @@ dsm_detach(dsm_segment *seg)
 			 */
 			if (is_main_region_dsm_handle(seg->handle) ||
 				dsm_impl_op(DSM_OP_DESTROY, seg->handle, 0, &seg->impl_private,
-							&seg->mapped_address, &seg->mapped_size, WARNING))
+							&seg->mapped_address, ptr_local_seg_mapped_size, WARNING))
 			{
 				LWLockAcquire(DynamicSharedMemoryControlLock, LW_EXCLUSIVE);
 				if (is_main_region_dsm_handle(seg->handle))
diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c
index f0965c3481..16e2bded59 100644
--- a/src/backend/storage/ipc/dsm_impl.c
+++ b/src/backend/storage/ipc/dsm_impl.c
@@ -66,6 +66,7 @@
 #include "postmaster/postmaster.h"
 #include "storage/dsm_impl.h"
 #include "storage/fd.h"
+#include "utils/backend_status.h"
 #include "utils/guc.h"
 #include "utils/memutils.h"
 
@@ -232,6 +233,14 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_allocated_bytes_decrease(*mapped_size, PG_ALLOC_DSM);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && shm_unlink(name) != 0)
@@ -332,6 +341,33 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+	{
+		/*
+		 * Posix creation calls dsm_impl_posix_resize implying that resizing
+		 * occurs or may be added in the future. As implemented
+		 * dsm_impl_posix_resize utilizes fallocate or truncate, passing the
+		 * whole new size as input, growing the allocation as needed (only
+		 * truncate supports shrinking). We update by replacing the old
+		 * allocation with the new.
+		 */
+#if defined(HAVE_POSIX_FALLOCATE) && defined(__linux__)
+		/*
+		 * posix_fallocate does not shrink allocations, adjust only on
+		 * allocation increase.
+		 */
+		if (request_size > *mapped_size)
+			pgstat_report_allocated_bytes_increase(request_size - *mapped_size, PG_ALLOC_DSM);
+#else
+		pgstat_report_allocated_bytes_decrease(*mapped_size, PG_ALLOC_DSM);
+		pgstat_report_allocated_bytes_increase(request_size, PG_ALLOC_DSM);
+#endif
+	}
 	*mapped_address = address;
 	*mapped_size = request_size;
 	close(fd);
@@ -537,6 +573,14 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_allocated_bytes_decrease(*mapped_size, PG_ALLOC_DSM);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && shmctl(ident, IPC_RMID, NULL) < 0)
@@ -584,6 +628,13 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_allocated_bytes_increase(request_size, PG_ALLOC_DSM);
 	*mapped_address = address;
 	*mapped_size = request_size;
 
@@ -652,6 +703,13 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 			return false;
 		}
 
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_allocated_bytes_decrease(*mapped_size, PG_ALLOC_DSM);
 		*impl_private = NULL;
 		*mapped_address = NULL;
 		*mapped_size = 0;
@@ -768,6 +826,12 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 		return false;
 	}
 
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_allocated_bytes_increase(info.RegionSize, PG_ALLOC_DSM);
 	*mapped_address = address;
 	*mapped_size = info.RegionSize;
 	*impl_private = hmap;
@@ -812,6 +876,13 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		pgstat_report_allocated_bytes_decrease(*mapped_size, PG_ALLOC_DSM);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && unlink(name) != 0)
@@ -933,6 +1004,13 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_allocated_bytes_increase(request_size, PG_ALLOC_DSM);
 	*mapped_address = address;
 	*mapped_size = request_size;
 
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index 22b4278610..d86fbdfd9b 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -180,6 +180,7 @@ InitProcGlobal(void)
 	ProcGlobal->checkpointerLatch = NULL;
 	pg_atomic_init_u32(&ProcGlobal->procArrayGroupFirst, INVALID_PGPROCNO);
 	pg_atomic_init_u32(&ProcGlobal->clogGroupFirst, INVALID_PGPROCNO);
+	pg_atomic_init_u64(&ProcGlobal->global_dsm_allocation, 0);
 
 	/*
 	 * Create and initialize all the PGPROC structures we'll need.  There are
diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c
index 608d01ea0d..f921c4bbde 100644
--- a/src/backend/utils/activity/backend_status.c
+++ b/src/backend/utils/activity/backend_status.c
@@ -49,6 +49,24 @@ int			pgstat_track_activity_query_size = 1024;
 /* exposed so that backend_progress.c can access it */
 PgBackendStatus *MyBEEntry = NULL;
 
+/*
+ * Memory allocated to this backend prior to pgstats initialization. Migrated to
+ * shared memory on pgstats initialization.
+ */
+uint64		local_my_allocated_bytes = 0;
+uint64	   *my_allocated_bytes = &local_my_allocated_bytes;
+
+/* Memory allocated to this backend by type prior to pgstats initialization.
+ * Migrated to shared memory on pgstats initialization
+ */
+uint64		local_my_aset_allocated_bytes = 0;
+uint64	   *my_aset_allocated_bytes = &local_my_aset_allocated_bytes;
+uint64		local_my_dsm_allocated_bytes = 0;
+uint64	   *my_dsm_allocated_bytes = &local_my_dsm_allocated_bytes;
+uint64		local_my_generation_allocated_bytes = 0;
+uint64	   *my_generation_allocated_bytes = &local_my_generation_allocated_bytes;
+uint64		local_my_slab_allocated_bytes = 0;
+uint64	   *my_slab_allocated_bytes = &local_my_slab_allocated_bytes;
 
 static PgBackendStatus *BackendStatusArray = NULL;
 static char *BackendAppnameBuffer = NULL;
@@ -400,6 +418,32 @@ pgstat_bestart(void)
 	lbeentry.st_progress_command_target = InvalidOid;
 	lbeentry.st_query_id = UINT64CONST(0);
 
+	/* Alter allocation reporting from local storage to shared memory */
+	pgstat_set_allocated_bytes_storage(&MyBEEntry->allocated_bytes,
+									   &MyBEEntry->aset_allocated_bytes,
+									   &MyBEEntry->dsm_allocated_bytes,
+									   &MyBEEntry->generation_allocated_bytes,
+									   &MyBEEntry->slab_allocated_bytes);
+
+	/*
+	 * Populate sum of memory allocated prior to pgstats initialization to
+	 * pgstats and zero the local variable. This is a += assignment because
+	 * InitPostgres allocates memory after pgstat_beinit but prior to
+	 * pgstat_bestart so we have allocations to both local and shared memory
+	 * to combine.
+	 */
+	lbeentry.allocated_bytes += local_my_allocated_bytes;
+	local_my_allocated_bytes = 0;
+	lbeentry.aset_allocated_bytes += local_my_aset_allocated_bytes;
+	local_my_aset_allocated_bytes = 0;
+
+	lbeentry.dsm_allocated_bytes += local_my_dsm_allocated_bytes;
+	local_my_dsm_allocated_bytes = 0;
+	lbeentry.generation_allocated_bytes += local_my_generation_allocated_bytes;
+	local_my_generation_allocated_bytes = 0;
+	lbeentry.slab_allocated_bytes += local_my_slab_allocated_bytes;
+	local_my_slab_allocated_bytes = 0;
+
 	/*
 	 * we don't zero st_progress_param here to save cycles; nobody should
 	 * examine it until st_progress_command has been set to something other
@@ -459,6 +503,9 @@ pgstat_beshutdown_hook(int code, Datum arg)
 {
 	volatile PgBackendStatus *beentry = MyBEEntry;
 
+	/* Stop reporting memory allocation changes to shared memory */
+	pgstat_reset_allocated_bytes_storage();
+
 	/*
 	 * Clear my status entry, following the protocol of bumping st_changecount
 	 * before and after.  We use a volatile pointer here to ensure the
@@ -1194,3 +1241,70 @@ pgstat_clip_activity(const char *raw_activity)
 
 	return activity;
 }
+
+/*
+ * Configure bytes allocated reporting to report allocated bytes to
+ * shared memory.
+ *
+ * Expected to be called during backend startup (in pgstat_bestart), to point
+ * allocated bytes accounting into shared memory.
+ */
+void
+pgstat_set_allocated_bytes_storage(uint64 *allocated_bytes,
+								   uint64 *aset_allocated_bytes,
+								   uint64 *dsm_allocated_bytes,
+								   uint64 *generation_allocated_bytes,
+								   uint64 *slab_allocated_bytes)
+{
+	/* Map allocations to shared memory */
+	my_allocated_bytes = allocated_bytes;
+	*allocated_bytes = local_my_allocated_bytes;
+
+	my_aset_allocated_bytes = aset_allocated_bytes;
+	*aset_allocated_bytes = local_my_aset_allocated_bytes;
+
+	my_dsm_allocated_bytes = dsm_allocated_bytes;
+	*dsm_allocated_bytes = local_my_dsm_allocated_bytes;
+
+	my_generation_allocated_bytes = generation_allocated_bytes;
+	*generation_allocated_bytes = local_my_generation_allocated_bytes;
+
+	my_slab_allocated_bytes = slab_allocated_bytes;
+	*slab_allocated_bytes = local_my_slab_allocated_bytes;
+}
+
+/*
+ * Reset allocated bytes storage location.
+ *
+ * Expected to be called during backend shutdown, before the locations set up
+ * by pgstat_set_allocated_bytes_storage become invalid.
+ */
+void
+pgstat_reset_allocated_bytes_storage(void)
+{
+	if (ProcGlobal)
+	{
+		volatile PROC_HDR *procglobal = ProcGlobal;
+
+		/*
+		 * Add dsm allocations that have not been freed to global dsm
+		 * accounting
+		 */
+		pg_atomic_add_fetch_u64(&procglobal->global_dsm_allocation,
+								*my_dsm_allocated_bytes);
+	}
+
+	/* Reset memory allocation variables */
+	*my_allocated_bytes = local_my_allocated_bytes = 0;
+	*my_aset_allocated_bytes = local_my_aset_allocated_bytes = 0;
+	*my_dsm_allocated_bytes = local_my_dsm_allocated_bytes = 0;
+	*my_generation_allocated_bytes = local_my_generation_allocated_bytes = 0;
+	*my_slab_allocated_bytes = local_my_slab_allocated_bytes = 0;
+
+	/* Point my_{*_}allocated_bytes from shared memory back to local */
+	my_allocated_bytes = &local_my_allocated_bytes;
+	my_aset_allocated_bytes = &local_my_aset_allocated_bytes;
+	my_dsm_allocated_bytes = &local_my_dsm_allocated_bytes;
+	my_generation_allocated_bytes = &local_my_generation_allocated_bytes;
+	my_slab_allocated_bytes = &local_my_slab_allocated_bytes;
+}
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index eec9f3cf9b..a5fd5e6964 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -1995,3 +1995,87 @@ pg_stat_have_stats(PG_FUNCTION_ARGS)
 
 	PG_RETURN_BOOL(pgstat_have_entry(kind, dboid, objoid));
 }
+
+/*
+ * Get the memory allocation of PG backends.
+ */
+Datum
+pg_stat_get_memory_allocation(PG_FUNCTION_ARGS)
+{
+#define PG_STAT_GET_MEMORY_ALLOCATION_COLS	7
+	int			num_backends = pgstat_fetch_stat_numbackends();
+	int			curr_backend;
+	int			pid = PG_ARGISNULL(0) ? -1 : PG_GETARG_INT32(0);
+	ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
+
+	InitMaterializedSRF(fcinfo, 0);
+
+	/* 1-based index */
+	for (curr_backend = 1; curr_backend <= num_backends; curr_backend++)
+	{
+		/* for each row */
+		Datum		values[PG_STAT_GET_MEMORY_ALLOCATION_COLS] = {0};
+		bool		nulls[PG_STAT_GET_MEMORY_ALLOCATION_COLS] = {0};
+		LocalPgBackendStatus *local_beentry;
+		PgBackendStatus *beentry;
+
+		/* Get the next one in the list */
+		local_beentry = pgstat_fetch_stat_local_beentry(curr_backend);
+		beentry = &local_beentry->backendStatus;
+
+		/* If looking for specific PID, ignore all the others */
+		if (pid != -1 && beentry->st_procpid != pid)
+			continue;
+
+		/* Values available to all callers */
+		if (beentry->st_databaseid != InvalidOid)
+			values[0] = ObjectIdGetDatum(beentry->st_databaseid);
+		else
+			nulls[0] = true;
+
+		values[1] = Int32GetDatum(beentry->st_procpid);
+		values[2] = UInt64GetDatum(beentry->allocated_bytes);
+		values[3] = UInt64GetDatum(beentry->aset_allocated_bytes);
+		values[4] = UInt64GetDatum(beentry->dsm_allocated_bytes);
+		values[5] = UInt64GetDatum(beentry->generation_allocated_bytes);
+		values[6] = UInt64GetDatum(beentry->slab_allocated_bytes);
+
+		tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
+
+		/* If only a single backend was requested, and we found it, break. */
+		if (pid != -1)
+			break;
+	}
+
+	return (Datum) 0;
+}
+
+/*
+ * Get the global memory allocation statistics.
+ */
+Datum
+pg_stat_get_global_memory_allocation(PG_FUNCTION_ARGS)
+{
+#define PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS	2
+	TupleDesc	tupdesc;
+	Datum		values[PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS] = {0};
+	bool		nulls[PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS] = {0};
+	volatile PROC_HDR *procglobal = ProcGlobal;
+
+	/* Initialise attributes information in the tuple descriptor */
+	tupdesc = CreateTemplateTupleDesc(PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS);
+	TupleDescInitEntry(tupdesc, (AttrNumber) 1, "datid",
+					   OIDOID, -1, 0);
+	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "global_dsm_allocated_bytes",
+					   INT8OID, -1, 0);
+	BlessTupleDesc(tupdesc);
+
+	/* datid */
+	values[0] = ObjectIdGetDatum(MyDatabaseId);
+
+	/* get global_dsm_allocated_bytes */
+	values[1] = Int64GetDatum(pg_atomic_read_u64(&procglobal->global_dsm_allocation));
+
+	/* Returns the record as Datum */
+	PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls)));
+}
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index a604432126..7b8eeb7dbb 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -171,6 +171,9 @@ InitPostmasterChild(void)
 				(errcode_for_socket_access(),
 				 errmsg_internal("could not set postmaster death monitoring pipe to FD_CLOEXEC mode: %m")));
 #endif
+
+	/* Init allocated bytes to avoid double counting parent allocation */
+	pgstat_init_allocated_bytes();
 }
 
 /*
diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index 2589941ec4..f3f5945fdf 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -47,6 +47,7 @@
 #include "postgres.h"
 
 #include "port/pg_bitutils.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -521,6 +522,7 @@ AllocSetContextCreateInternal(MemoryContext parent,
 						name);
 
 	((MemoryContext) set)->mem_allocated = firstBlockSize;
+	pgstat_report_allocated_bytes_increase(firstBlockSize, PG_ALLOC_ASET);
 
 	return (MemoryContext) set;
 }
@@ -543,6 +545,7 @@ AllocSetReset(MemoryContext context)
 	AllocSet	set = (AllocSet) context;
 	AllocBlock	block;
 	Size		keepersize PG_USED_FOR_ASSERTS_ONLY;
+	uint64		deallocation = 0;
 
 	Assert(AllocSetIsValid(set));
 
@@ -585,6 +588,7 @@ AllocSetReset(MemoryContext context)
 		{
 			/* Normal case, release the block */
 			context->mem_allocated -= block->endptr - ((char *) block);
+			deallocation += block->endptr - ((char *) block);
 
 #ifdef CLOBBER_FREED_MEMORY
 			wipe_mem(block, block->freeptr - ((char *) block));
@@ -595,6 +599,7 @@ AllocSetReset(MemoryContext context)
 	}
 
 	Assert(context->mem_allocated == keepersize);
+	pgstat_report_allocated_bytes_decrease(deallocation, PG_ALLOC_ASET);
 
 	/* Reset block size allocation sequence, too */
 	set->nextBlockSize = set->initBlockSize;
@@ -613,6 +618,7 @@ AllocSetDelete(MemoryContext context)
 	AllocSet	set = (AllocSet) context;
 	AllocBlock	block = set->blocks;
 	Size		keepersize PG_USED_FOR_ASSERTS_ONLY;
+	uint64		deallocation = 0;
 
 	Assert(AllocSetIsValid(set));
 
@@ -651,11 +657,13 @@ AllocSetDelete(MemoryContext context)
 
 				freelist->first_free = (AllocSetContext *) oldset->header.nextchild;
 				freelist->num_free--;
+				deallocation += oldset->header.mem_allocated;
 
 				/* All that remains is to free the header/initial block */
 				free(oldset);
 			}
 			Assert(freelist->num_free == 0);
+			pgstat_report_allocated_bytes_decrease(deallocation, PG_ALLOC_ASET);
 		}
 
 		/* Now add the just-deleted context to the freelist. */
@@ -672,7 +680,10 @@ AllocSetDelete(MemoryContext context)
 		AllocBlock	next = block->next;
 
 		if (block != set->keeper)
+		{
 			context->mem_allocated -= block->endptr - ((char *) block);
+			deallocation += block->endptr - ((char *) block);
+		}
 
 #ifdef CLOBBER_FREED_MEMORY
 		wipe_mem(block, block->freeptr - ((char *) block));
@@ -685,6 +696,7 @@ AllocSetDelete(MemoryContext context)
 	}
 
 	Assert(context->mem_allocated == keepersize);
+	pgstat_report_allocated_bytes_decrease(deallocation + context->mem_allocated, PG_ALLOC_ASET);
 
 	/* Finally, free the context header, including the keeper block */
 	free(set);
@@ -734,6 +746,7 @@ AllocSetAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_allocated_bytes_increase(blksize, PG_ALLOC_ASET);
 
 		block->aset = set;
 		block->freeptr = block->endptr = ((char *) block) + blksize;
@@ -944,6 +957,7 @@ AllocSetAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_allocated_bytes_increase(blksize, PG_ALLOC_ASET);
 
 		block->aset = set;
 		block->freeptr = ((char *) block) + ALLOC_BLOCKHDRSZ;
@@ -1041,6 +1055,7 @@ AllocSetFree(void *pointer)
 			block->next->prev = block->prev;
 
 		set->header.mem_allocated -= block->endptr - ((char *) block);
+		pgstat_report_allocated_bytes_decrease(block->endptr - ((char *) block), PG_ALLOC_ASET);
 
 #ifdef CLOBBER_FREED_MEMORY
 		wipe_mem(block, block->freeptr - ((char *) block));
@@ -1171,7 +1186,9 @@ AllocSetRealloc(void *pointer, Size size)
 
 		/* updated separately, not to underflow when (oldblksize > blksize) */
 		set->header.mem_allocated -= oldblksize;
+		pgstat_report_allocated_bytes_decrease(oldblksize, PG_ALLOC_ASET);
 		set->header.mem_allocated += blksize;
+		pgstat_report_allocated_bytes_increase(blksize, PG_ALLOC_ASET);
 
 		block->freeptr = block->endptr = ((char *) block) + blksize;
 
diff --git a/src/backend/utils/mmgr/generation.c b/src/backend/utils/mmgr/generation.c
index ebcb61e9b6..5708e8da7a 100644
--- a/src/backend/utils/mmgr/generation.c
+++ b/src/backend/utils/mmgr/generation.c
@@ -37,6 +37,7 @@
 
 #include "lib/ilist.h"
 #include "port/pg_bitutils.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -267,6 +268,7 @@ GenerationContextCreate(MemoryContext parent,
 						name);
 
 	((MemoryContext) set)->mem_allocated = firstBlockSize;
+	pgstat_report_allocated_bytes_increase(firstBlockSize, PG_ALLOC_GENERATION);
 
 	return (MemoryContext) set;
 }
@@ -283,6 +285,7 @@ GenerationReset(MemoryContext context)
 {
 	GenerationContext *set = (GenerationContext *) context;
 	dlist_mutable_iter miter;
+	uint64		deallocation = 0;
 
 	Assert(GenerationIsValid(set));
 
@@ -305,9 +308,14 @@ GenerationReset(MemoryContext context)
 		if (block == set->keeper)
 			GenerationBlockMarkEmpty(block);
 		else
+		{
+			deallocation += block->blksize;
 			GenerationBlockFree(set, block);
+		}
 	}
 
+	pgstat_report_allocated_bytes_decrease(deallocation, PG_ALLOC_GENERATION);
+
 	/* set it so new allocations to make use of the keeper block */
 	set->block = set->keeper;
 
@@ -328,6 +336,9 @@ GenerationDelete(MemoryContext context)
 {
 	/* Reset to release all releasable GenerationBlocks */
 	GenerationReset(context);
+
+	pgstat_report_allocated_bytes_decrease(context->mem_allocated, PG_ALLOC_GENERATION);
+
 	/* And free the context header and keeper block */
 	free(context);
 }
@@ -374,6 +385,7 @@ GenerationAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_allocated_bytes_increase(blksize, PG_ALLOC_GENERATION);
 
 		/* block with a single (used) chunk */
 		block->context = set;
@@ -477,6 +489,7 @@ GenerationAlloc(MemoryContext context, Size size)
 				return NULL;
 
 			context->mem_allocated += blksize;
+			pgstat_report_allocated_bytes_increase(blksize, PG_ALLOC_GENERATION);
 
 			/* initialize the new block */
 			GenerationBlockInit(set, block, blksize);
@@ -729,6 +742,8 @@ GenerationFree(void *pointer)
 	dlist_delete(&block->node);
 
 	set->header.mem_allocated -= block->blksize;
+	pgstat_report_allocated_bytes_decrease(block->blksize, PG_ALLOC_GENERATION);
+
 	free(block);
 }
 
diff --git a/src/backend/utils/mmgr/slab.c b/src/backend/utils/mmgr/slab.c
index 33dca0f37c..b436587bdd 100644
--- a/src/backend/utils/mmgr/slab.c
+++ b/src/backend/utils/mmgr/slab.c
@@ -69,6 +69,7 @@
 #include "postgres.h"
 
 #include "lib/ilist.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -413,6 +414,13 @@ SlabContextCreate(MemoryContext parent,
 						parent,
 						name);
 
+	/*
+	 * If SlabContextCreate is updated to add context header size to
+	 * context->mem_allocated, then update here and SlabDelete appropriately
+	 */
+	pgstat_report_allocated_bytes_increase(Slab_CONTEXT_HDRSZ(slab->chunksPerBlock),
+										   PG_ALLOC_SLAB);
+
 	return (MemoryContext) slab;
 }
 
@@ -429,6 +437,7 @@ SlabReset(MemoryContext context)
 	SlabContext *slab = (SlabContext *) context;
 	dlist_mutable_iter miter;
 	int			i;
+	uint64		deallocation = 0;
 
 	Assert(SlabIsValid(slab));
 
@@ -449,6 +458,7 @@ SlabReset(MemoryContext context)
 #endif
 		free(block);
 		context->mem_allocated -= slab->blockSize;
+		deallocation += slab->blockSize;
 	}
 
 	/* walk over blocklist and free the blocks */
@@ -465,9 +475,11 @@ SlabReset(MemoryContext context)
 #endif
 			free(block);
 			context->mem_allocated -= slab->blockSize;
+			deallocation += slab->blockSize;
 		}
 	}
 
+	pgstat_report_allocated_bytes_decrease(deallocation, PG_ALLOC_SLAB);
 	slab->curBlocklistIndex = 0;
 
 	Assert(context->mem_allocated == 0);
@@ -482,6 +494,14 @@ SlabDelete(MemoryContext context)
 {
 	/* Reset to release all the SlabBlocks */
 	SlabReset(context);
+
+	/*
+	 * Until context header allocation is included in context->mem_allocated,
+	 * cast to slab and decrement the header allocation
+	 */
+	pgstat_report_allocated_bytes_decrease(Slab_CONTEXT_HDRSZ(((SlabContext *) context)->chunksPerBlock),
+										   PG_ALLOC_SLAB);
+
 	/* And free the context header */
 	free(context);
 }
@@ -546,6 +566,7 @@ SlabAlloc(MemoryContext context, Size size)
 
 			block->slab = slab;
 			context->mem_allocated += slab->blockSize;
+			pgstat_report_allocated_bytes_increase(slab->blockSize, PG_ALLOC_SLAB);
 
 			/* use the first chunk in the new block */
 			chunk = SlabBlockGetChunk(slab, block, 0);
@@ -732,6 +753,7 @@ SlabFree(void *pointer)
 #endif
 			free(block);
 			slab->header.mem_allocated -= slab->blockSize;
+			pgstat_report_allocated_bytes_decrease(slab->blockSize, PG_ALLOC_SLAB);
 		}
 
 		/*
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index f9f2642201..a6f52a4db4 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -5427,6 +5427,23 @@
   proname => 'pg_stat_get_backend_idset', prorows => '100', proretset => 't',
   provolatile => 's', proparallel => 'r', prorettype => 'int4',
   proargtypes => '', prosrc => 'pg_stat_get_backend_idset' },
+{ oid => '9890',
+  descr => 'statistics: memory allocation information for backends',
+  proname => 'pg_stat_get_memory_allocation', prorows => '100', proisstrict => 'f',
+  proretset => 't', provolatile => 's', proparallel => 'r',
+  prorettype => 'record', proargtypes => 'int4',
+  proallargtypes => '{int4,oid,int4,int8,int8,int8,int8,int8}',
+  proargmodes => '{i,o,o,o,o,o,o,o}',
+  proargnames => '{pid,datid,pid,allocated_bytes,aset_allocated_bytes,dsm_allocated_bytes,generation_allocated_bytes,slab_allocated_bytes}',
+  prosrc => 'pg_stat_get_memory_allocation' },
+{ oid => '9891',
+  descr => 'statistics: global memory allocation information',
+  proname => 'pg_stat_get_global_memory_allocation', proisstrict => 'f',
+  provolatile => 's', proparallel => 'r', prorettype => 'record',
+  proargtypes => '', proallargtypes => '{oid,int8}',
+  proargmodes => '{o,o}',
+  proargnames => '{datid,global_dsm_allocated_bytes}',
+  prosrc =>'pg_stat_get_global_memory_allocation' },
 { oid => '2022',
   descr => 'statistics: information about currently active backends',
   proname => 'pg_stat_get_activity', prorows => '100', proisstrict => 'f',
diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h
index 4258cd92c9..c2c878219d 100644
--- a/src/include/storage/proc.h
+++ b/src/include/storage/proc.h
@@ -404,6 +404,8 @@ typedef struct PROC_HDR
 	int			spins_per_delay;
 	/* Buffer id of the buffer that Startup process waits for pin on, or -1 */
 	int			startupBufferPinWaitBufId;
+	/* Global dsm allocations */
+	pg_atomic_uint64 global_dsm_allocation;
 } PROC_HDR;
 
 extern PGDLLIMPORT PROC_HDR *ProcGlobal;
diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h
index f7bd83113a..6434ece1ef 100644
--- a/src/include/utils/backend_status.h
+++ b/src/include/utils/backend_status.h
@@ -10,6 +10,7 @@
 #ifndef BACKEND_STATUS_H
 #define BACKEND_STATUS_H
 
+#include "common/int.h"
 #include "datatype/timestamp.h"
 #include "libpq/pqcomm.h"
 #include "miscadmin.h"			/* for BackendType */
@@ -32,6 +33,14 @@ typedef enum BackendState
 	STATE_DISABLED
 } BackendState;
 
+/* Enum helper for reporting memory allocator type */
+enum pg_allocator_type
+{
+	PG_ALLOC_ASET = 1,
+	PG_ALLOC_DSM,
+	PG_ALLOC_GENERATION,
+	PG_ALLOC_SLAB
+};
 
 /* ----------
  * Shared-memory data structures
@@ -169,6 +178,15 @@ typedef struct PgBackendStatus
 
 	/* query identifier, optionally computed using post_parse_analyze_hook */
 	uint64		st_query_id;
+
+	/* Current memory allocated to this backend */
+	uint64		allocated_bytes;
+
+	/* Current memory allocated to this backend by type */
+	uint64		aset_allocated_bytes;
+	uint64		dsm_allocated_bytes;
+	uint64		generation_allocated_bytes;
+	uint64		slab_allocated_bytes;
 } PgBackendStatus;
 
 
@@ -293,6 +311,11 @@ extern PGDLLIMPORT int pgstat_track_activity_query_size;
  * ----------
  */
 extern PGDLLIMPORT PgBackendStatus *MyBEEntry;
+extern PGDLLIMPORT uint64 *my_allocated_bytes;
+extern PGDLLIMPORT uint64 *my_aset_allocated_bytes;
+extern PGDLLIMPORT uint64 *my_dsm_allocated_bytes;
+extern PGDLLIMPORT uint64 *my_generation_allocated_bytes;
+extern PGDLLIMPORT uint64 *my_slab_allocated_bytes;
 
 
 /* ----------
@@ -324,7 +347,12 @@ extern const char *pgstat_get_backend_current_activity(int pid, bool checkUser);
 extern const char *pgstat_get_crashed_backend_activity(int pid, char *buffer,
 													   int buflen);
 extern uint64 pgstat_get_my_query_id(void);
-
+extern void pgstat_set_allocated_bytes_storage(uint64 *allocated_bytes,
+											   uint64 *aset_allocated_bytes,
+											   uint64 *dsm_allocated_bytes,
+											   uint64 *generation_allocated_bytes,
+											   uint64 *slab_allocated_bytes);
+extern void pgstat_reset_allocated_bytes_storage(void);
 
 /* ----------
  * Support functions for the SQL-callable functions to
@@ -336,5 +364,131 @@ extern PgBackendStatus *pgstat_fetch_stat_beentry(BackendId beid);
 extern LocalPgBackendStatus *pgstat_fetch_stat_local_beentry(int beid);
 extern char *pgstat_clip_activity(const char *raw_activity);
 
+/* ----------
+ * pgstat_report_allocated_bytes_decrease() -
+ *  Called to report decrease in memory allocated for this backend.
+ *
+ * my_{*_}allocated_bytes initially points to local memory, making it safe to
+ * call this before pgstats has been initialized.
+ * ----------
+ */
+static inline void
+pgstat_report_allocated_bytes_decrease(int64 proc_allocated_bytes,
+									   int pg_allocator_type)
+{
+	uint64		temp;
+
+	/* Avoid allocated_bytes unsigned integer overflow on decrease */
+	if (pg_sub_u64_overflow(*my_allocated_bytes, proc_allocated_bytes, &temp))
+	{
+		/* On overflow, set pgstat count of allocated bytes to zero */
+		*my_allocated_bytes = 0;
+
+		switch (pg_allocator_type)
+		{
+			case PG_ALLOC_ASET:
+				*my_aset_allocated_bytes = 0;
+				break;
+			case PG_ALLOC_DSM:
+				*my_dsm_allocated_bytes = 0;
+				break;
+			case PG_ALLOC_GENERATION:
+				*my_generation_allocated_bytes = 0;
+				break;
+			case PG_ALLOC_SLAB:
+				*my_slab_allocated_bytes = 0;
+				break;
+		}
+	}
+	else
+	{
+		/* decrease allocation */
+		*my_allocated_bytes -= proc_allocated_bytes;
+
+		/* Decrease allocator type allocated bytes. */
+		switch (pg_allocator_type)
+		{
+			case PG_ALLOC_ASET:
+				*my_aset_allocated_bytes -= proc_allocated_bytes;
+				break;
+			case PG_ALLOC_DSM:
+
+				/*
+				 * Some dsm allocations live beyond process exit. These are
+				 * accounted for in a global counter in
+				 * pgstat_reset_allocated_bytes_storage at process exit.
+				 */
+				*my_dsm_allocated_bytes -= proc_allocated_bytes;
+				break;
+			case PG_ALLOC_GENERATION:
+				*my_generation_allocated_bytes -= proc_allocated_bytes;
+				break;
+			case PG_ALLOC_SLAB:
+				*my_slab_allocated_bytes -= proc_allocated_bytes;
+				break;
+		}
+	}
+
+	return;
+}
+
+/* ----------
+ * pgstat_report_allocated_bytes_increase() -
+ *  Called to report increase in memory allocated for this backend.
+ *
+ * my_allocated_bytes initially points to local memory, making it safe to call
+ * this before pgstats has been initialized.
+ * ----------
+ */
+static inline void
+pgstat_report_allocated_bytes_increase(int64 proc_allocated_bytes,
+									   int pg_allocator_type)
+{
+	*my_allocated_bytes += proc_allocated_bytes;
+
+	/* Increase allocator type allocated bytes */
+	switch (pg_allocator_type)
+	{
+		case PG_ALLOC_ASET:
+			*my_aset_allocated_bytes += proc_allocated_bytes;
+			break;
+		case PG_ALLOC_DSM:
+
+			/*
+			 * Some dsm allocations live beyond process exit. These are
+			 * accounted for in a global counter in
+			 * pgstat_reset_allocated_bytes_storage at process exit.
+			 */
+			*my_dsm_allocated_bytes += proc_allocated_bytes;
+			break;
+		case PG_ALLOC_GENERATION:
+			*my_generation_allocated_bytes += proc_allocated_bytes;
+			break;
+		case PG_ALLOC_SLAB:
+			*my_slab_allocated_bytes += proc_allocated_bytes;
+			break;
+	}
+
+	return;
+}
+
+/* ---------
+ * pgstat_init_allocated_bytes() -
+ *
+ * Called to initialize allocated bytes variables after fork and to
+ * avoid double counting allocations.
+ * ---------
+ */
+static inline void
+pgstat_init_allocated_bytes(void)
+{
+	*my_allocated_bytes = 0;
+	*my_aset_allocated_bytes = 0;
+	*my_dsm_allocated_bytes = 0;
+	*my_generation_allocated_bytes = 0;
+	*my_slab_allocated_bytes = 0;
+
+	return;
+}
 
 #endif							/* BACKEND_STATUS_H */
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index ab1aebfde4..77c4a18e26 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1871,6 +1871,24 @@ pg_stat_database_conflicts| SELECT oid AS datid,
     pg_stat_get_db_conflict_bufferpin(oid) AS confl_bufferpin,
     pg_stat_get_db_conflict_startup_deadlock(oid) AS confl_deadlock
    FROM pg_database d;
+pg_stat_global_memory_allocation| WITH sums AS (
+         SELECT sum(pg_stat_memory_allocation.aset_allocated_bytes) AS total_aset_allocated_bytes,
+            sum(pg_stat_memory_allocation.dsm_allocated_bytes) AS total_dsm_allocated_bytes,
+            sum(pg_stat_memory_allocation.generation_allocated_bytes) AS total_generation_allocated_bytes,
+            sum(pg_stat_memory_allocation.slab_allocated_bytes) AS total_slab_allocated_bytes
+           FROM pg_stat_memory_allocation
+        )
+ SELECT s.datid,
+    current_setting('shared_memory_size'::text, true) AS shared_memory_size,
+    (current_setting('shared_memory_size_in_huge_pages'::text, true))::integer AS shared_memory_size_in_huge_pages,
+    s.global_dsm_allocated_bytes,
+    sums.total_aset_allocated_bytes,
+    sums.total_dsm_allocated_bytes,
+    sums.total_generation_allocated_bytes,
+    sums.total_slab_allocated_bytes
+   FROM sums,
+    (pg_stat_get_global_memory_allocation() s(datid, global_dsm_allocated_bytes)
+     LEFT JOIN pg_database d ON ((s.datid = d.oid)));
 pg_stat_gssapi| SELECT pid,
     gss_auth AS gss_authenticated,
     gss_princ AS principal,
@@ -1890,6 +1908,15 @@ pg_stat_io| SELECT backend_type,
     fsyncs,
     stats_reset
    FROM pg_stat_get_io() b(backend_type, io_object, io_context, reads, writes, extends, op_bytes, hits, evictions, reuses, fsyncs, stats_reset);
+pg_stat_memory_allocation| SELECT s.datid,
+    s.pid,
+    s.allocated_bytes,
+    s.aset_allocated_bytes,
+    s.dsm_allocated_bytes,
+    s.generation_allocated_bytes,
+    s.slab_allocated_bytes
+   FROM (pg_stat_get_memory_allocation(NULL::integer) s(datid, pid, allocated_bytes, aset_allocated_bytes, dsm_allocated_bytes, generation_allocated_bytes, slab_allocated_bytes)
+     LEFT JOIN pg_database d ON ((s.datid = d.oid)));
 pg_stat_progress_analyze| SELECT s.pid,
     s.datid,
     d.datname,
diff --git a/src/test/regress/expected/stats.out b/src/test/regress/expected/stats.out
index 5f1821938d..f507a6710c 100644
--- a/src/test/regress/expected/stats.out
+++ b/src/test/regress/expected/stats.out
@@ -1511,4 +1511,40 @@ SELECT COUNT(*) FROM brin_hot_3 WHERE a = 2;
 
 DROP TABLE brin_hot_3;
 SET enable_seqscan = on;
+-- ensure that allocated_bytes exist for backends
+SELECT
+    allocated_bytes > 0 AS result
+FROM
+    pg_stat_activity ps
+    JOIN pg_stat_memory_allocation pa ON (pa.pid = ps.pid)
+WHERE
+    backend_type IN ('checkpointer', 'background writer', 'walwriter', 'autovacuum launcher');
+ result 
+--------
+ t
+ t
+ t
+ t
+(4 rows)
+
+-- ensure that pg_stat_global_memory_allocation view exists
+SELECT
+    datid > 0, pg_size_bytes(shared_memory_size) >= 0, shared_memory_size_in_huge_pages >= -1, global_dsm_allocated_bytes >= 0
+FROM
+    pg_stat_global_memory_allocation;
+ ?column? | ?column? | ?column? | ?column? 
+----------+----------+----------+----------
+ t        | t        | t        | t
+(1 row)
+
+-- ensure that pg_stat_memory_allocation view exists
+SELECT
+    pid > 0, allocated_bytes >= 0, aset_allocated_bytes >= 0, dsm_allocated_bytes >= 0, generation_allocated_bytes >= 0, slab_allocated_bytes >= 0
+FROM
+    pg_stat_memory_allocation limit 1;
+ ?column? | ?column? | ?column? | ?column? | ?column? | ?column? 
+----------+----------+----------+----------+----------+----------
+ t        | t        | t        | t        | t        | t
+(1 row)
+
 -- End of Stats Test
diff --git a/src/test/regress/sql/stats.sql b/src/test/regress/sql/stats.sql
index 58db803ed6..a195776c9d 100644
--- a/src/test/regress/sql/stats.sql
+++ b/src/test/regress/sql/stats.sql
@@ -783,4 +783,24 @@ DROP TABLE brin_hot_3;
 
 SET enable_seqscan = on;
 
+-- ensure that allocated_bytes exist for backends
+SELECT
+    allocated_bytes > 0 AS result
+FROM
+    pg_stat_activity ps
+    JOIN pg_stat_memory_allocation pa ON (pa.pid = ps.pid)
+WHERE
+    backend_type IN ('checkpointer', 'background writer', 'walwriter', 'autovacuum launcher');
+
+-- ensure that pg_stat_global_memory_allocation view exists
+SELECT
+    datid > 0, pg_size_bytes(shared_memory_size) >= 0, shared_memory_size_in_huge_pages >= -1, global_dsm_allocated_bytes >= 0
+FROM
+    pg_stat_global_memory_allocation;
+
+-- ensure that pg_stat_memory_allocation view exists
+SELECT
+    pid > 0, allocated_bytes >= 0, aset_allocated_bytes >= 0, dsm_allocated_bytes >= 0, generation_allocated_bytes >= 0, slab_allocated_bytes >= 0
+FROM
+    pg_stat_memory_allocation limit 1;
 -- End of Stats Test
-- 
2.25.1

#35Arne Roland
A.Roland@index.de
In reply to: Noname (#34)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

Thank you! I just tried our benchmark and got a performance degration of around 28 %, which is way better than the last patch.

The simple query select * from generate_series(0, 10000000) shows roughly 18.9 % degradation on my test server.

By raising initial_allocation_allowance and allocation_allowance_refill_qty I can get it to 16 % degradation. So most of the degradation seems to be independent from raising the allowance.

I think we probably should investigate this further.

Regards
Arne

#36Noname
reid.thompson@crunchydata.com
In reply to: Arne Roland (#35)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On Wed, 2023-04-19 at 23:28 +0000, Arne Roland wrote:

Thank you! I just tried our benchmark and got a performance
degration > of around 28 %, which is way better than the last
patch.

The simple query select * from generate_series(0, 10000000) shows >
roughly 18.9 % degradation on my test server.

By raising initial_allocation_allowance and >
allocation_allowance_refill_qty I can get it to 16 % degradation.
So > most of the degradation seems to be independent from raising
the > allowance.

I think we probably should investigate this further.

Regards
Arne

Hi Arne,

Thanks for the feedback.

I'm plannning to look at this.

Is your benchmark something that I could utilize? I.E. is it a set of
scripts or a standard test from somewhere that I can duplicate?

Thanks,
Reid

#37Noname
reid.thompson@crunchydata.com
In reply to: Noname (#36)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On Wed, 2023-05-17 at 23:07 -0400, reid.thompson@crunchydata.com wrote:

Thanks for the feedback.

I'm plannning to look at this.

Is your benchmark something that I could utilize? I.E. is it a set of
scripts or a standard test from somewhere that I can duplicate?

Thanks,
Reid

Hi Arne,

Followup to the above.

I experimented on my system regarding
"The simple query select * from generate_series(0, 10000000) shows roughly 18.9 % degradation on my test server."

My laptop:
32GB ram
11th Gen Intel(R) Core(TM) i7-11850H 8 cores/16 threads @ 2.50GHz (Max Turbo Frequency. 4.80 GHz ; Cache. 24 MB)
SSD -> Model: KXG60ZNV1T02 NVMe KIOXIA 1024GB (nvme)

I updated to latest master and rebased my patch branches.

I wrote a script to check out, build, install, init, and startup
master, patch 1, patch 1+2, patch 1+2 as master, pg-stats-memory, 
dev-max-memory, and dev-max-memory-unset configured with

../../configure --silent --prefix=/home/rthompso/src/git/postgres/install/${dir} --with-openssl --with-tcl --with-tclconfig=/usr/lib/tcl8.6 --with-perl --with-libxml --with-libxslt --with-python --with-gssapi --with-systemd --with-ldap --enable-nls

where $dir in master, pg-stats-memory, and dev-max-memory,
dev-max-memory-unset.

The only change made to the default postgresql.conf was to have the
script add to the dev-max-memory instance the line
"max_total_backend_memory = 2048" before startup.
I did find one change in patch 2 that I pushed back into patch 1, this
should only impact the pg-stats-memory instance.

my .psqlrc turns timing on

I created a script where I can pass two instances to be compared.
It invokes
psql -At -d postgres $connstr -P pager=off -c 'select * from generate_series(0, 10000000)'
100 times on each of the 2 instances and calculates the AVG time and SD
for the 100 runs. It then uses the AVG from each instance to calculate
the percentage difference.

Depending on the instance, my results differ from master from
negligible to ~5.5%. Comparing master to itself had up to a ~2%
variation. See below.

------------------------
12 runs comparing dev-max-memory 2048 VS master
Shows ~3% to 5.5% variation

Calculate average runtime percentage difference between VER dev-max-memory 2048 and VER master
1307.14 -> VER dev-max-memory 2048
1240.74 -> VER master
5.21218% difference
--
Calculate average runtime percentage difference between VER dev-max-memory 2048 and VER master
1315.99 -> VER dev-max-memory 2048
1245.64 -> VER master
5.4926% difference
--
Calculate average runtime percentage difference between VER dev-max-memory 2048 and VER master
1317.39 -> VER dev-max-memory 2048
1265.33 -> VER master
4.03141% difference
--
Calculate average runtime percentage difference between VER dev-max-memory 2048 and VER master
1313.52 -> VER dev-max-memory 2048
1256.69 -> VER master
4.42221% difference
--
Calculate average runtime percentage difference between VER dev-max-memory 2048 and VER master
1329.98 -> VER dev-max-memory 2048
1253.75 -> VER master
5.90077% difference
--
Calculate average runtime percentage difference between VER dev-max-memory 2048 and VER master
1314.47 -> VER dev-max-memory 2048
1245.6 -> VER master
5.38032% difference
--
Calculate average runtime percentage difference between VER dev-max-memory 2048 and VER master
1309.7 -> VER dev-max-memory 2048
1258.55 -> VER master
3.98326% difference
--
Calculate average runtime percentage difference between VER dev-max-memory 2048 and VER master
1322.16 -> VER dev-max-memory 2048
1248.94 -> VER master
5.69562% difference
--
Calculate average runtime percentage difference between VER dev-max-memory 2048 and VER master
1320.15 -> VER dev-max-memory 2048
1261.41 -> VER master
4.55074% difference
--
Calculate average runtime percentage difference between VER dev-max-memory 2048 and VER master
1345.22 -> VER dev-max-memory 2048
1280.96 -> VER master
4.8938% difference
--
Calculate average runtime percentage difference between VER dev-max-memory 2048 and VER master
1296.03 -> VER dev-max-memory 2048
1257.06 -> VER master
3.05277% difference
--
Calculate average runtime percentage difference between VER dev-max-memory 2048 and VER master
1319.5 -> VER dev-max-memory 2048
1252.34 -> VER master
5.22272% difference

----------------------------
12 showing dev-max-memory-unset VS master
Shows ~2.5% to 5% variation

Calculate average runtime percentage difference between VER dev-max-memory unset and VER master
1300.93 -> VER dev-max-memory unset
1235.12 -> VER master
5.18996% difference
--
Calculate average runtime percentage difference between VER dev-max-memory unset and VER master
1293.57 -> VER dev-max-memory unset
1263.93 -> VER master
2.31789% difference
--
Calculate average runtime percentage difference between VER dev-max-memory unset and VER master
1303.05 -> VER dev-max-memory unset
1258.11 -> VER master
3.50935% difference
--
Calculate average runtime percentage difference between VER dev-max-memory unset and VER master
1302.14 -> VER dev-max-memory unset
1256.51 -> VER master
3.56672% difference
--
Calculate average runtime percentage difference between VER dev-max-memory unset and VER master
1299.22 -> VER dev-max-memory unset
1282.74 -> VER master
1.27655% difference
--
Calculate average runtime percentage difference between VER dev-max-memory unset and VER master
1334.06 -> VER dev-max-memory unset
1263.77 -> VER master
5.41144% difference
--
Calculate average runtime percentage difference between VER dev-max-memory unset and VER master
1319.92 -> VER dev-max-memory unset
1262.35 -> VER master
4.45887% difference
--
Calculate average runtime percentage difference between VER dev-max-memory unset and VER master
1318.01 -> VER dev-max-memory unset
1257.16 -> VER master
4.7259% difference
--
Calculate average runtime percentage difference between VER dev-max-memory unset and VER master
1316.88 -> VER dev-max-memory unset
1257.63 -> VER master
4.60282% difference
--
Calculate average runtime percentage difference between VER dev-max-memory unset and VER master
1320.33 -> VER dev-max-memory unset
1282.12 -> VER master
2.93646% difference
--
Calculate average runtime percentage difference between VER dev-max-memory unset and VER master
1306.91 -> VER dev-max-memory unset
1246.12 -> VER master
4.76218% difference
--
Calculate average runtime percentage difference between VER dev-max-memory unset and VER master
1320.65 -> VER dev-max-memory unset
1258.78 -> VER master
4.79718% difference
-------------------------------

12 showing pg-stat-activity-only VS master
Shows ~<1% to 2.5% variation

Calculate average runtime percentage difference between VER pg-stat-activity-backend-memory-allocated and VER master
1252.65 -> VER pg-stat-activity-backend-memory-allocated
1245.36 -> VER master
0.583665% difference
--
Calculate average runtime percentage difference between VER pg-stat-activity-backend-memory-allocated and VER master
1294.75 -> VER pg-stat-activity-backend-memory-allocated
1277.55 -> VER master
1.33732% difference
--
Calculate average runtime percentage difference between VER pg-stat-activity-backend-memory-allocated and VER master
1264.11 -> VER pg-stat-activity-backend-memory-allocated
1257.57 -> VER master
0.518702% difference
--
Calculate average runtime percentage difference between VER pg-stat-activity-backend-memory-allocated and VER master
1267.44 -> VER pg-stat-activity-backend-memory-allocated
1251.31 -> VER master
1.28079% difference
--
Calculate average runtime percentage difference between VER pg-stat-activity-backend-memory-allocated and VER master
1270.05 -> VER pg-stat-activity-backend-memory-allocated
1250.1 -> VER master
1.58324% difference
--
Calculate average runtime percentage difference between VER pg-stat-activity-backend-memory-allocated and VER master
1298.92 -> VER pg-stat-activity-backend-memory-allocated
1265.04 -> VER master
2.64279% difference
--
Calculate average runtime percentage difference between VER pg-stat-activity-backend-memory-allocated and VER master
1280.99 -> VER pg-stat-activity-backend-memory-allocated
1263.51 -> VER master
1.37394% difference
--
Calculate average runtime percentage difference between VER pg-stat-activity-backend-memory-allocated and VER master
1273.23 -> VER pg-stat-activity-backend-memory-allocated
1275.53 -> VER master
-0.18048% difference
--
Calculate average runtime percentage difference between VER pg-stat-activity-backend-memory-allocated and VER master
1261.2 -> VER pg-stat-activity-backend-memory-allocated
1263.04 -> VER master
-0.145786% difference
--
Calculate average runtime percentage difference between VER pg-stat-activity-backend-memory-allocated and VER master
1289.73 -> VER pg-stat-activity-backend-memory-allocated
1289.02 -> VER master
0.0550654% difference
--
Calculate average runtime percentage difference between VER pg-stat-activity-backend-memory-allocated and VER master
1287.57 -> VER pg-stat-activity-backend-memory-allocated
1279.42 -> VER master
0.634985% difference
--
Calculate average runtime percentage difference between VER pg-stat-activity-backend-memory-allocated and VER master
1272.01 -> VER pg-stat-activity-backend-memory-allocated
1259.22 -> VER master
1.01058% difference
----------------------------------

I also did 12 runs master VS master
Shows, ~1% to 2% variation

Calculate average runtime percentage difference between VER master and VER master
1239.6 -> VER master
1263.73 -> VER master
-1.92783% difference
--
Calculate average runtime percentage difference between VER master and VER master
1253.82 -> VER master
1252.5 -> VER master
0.105334% difference
--
Calculate average runtime percentage difference between VER master and VER master
1256.05 -> VER master
1258.97 -> VER master
-0.232205% difference
--
Calculate average runtime percentage difference between VER master and VER master
1264.8 -> VER master
1248.94 -> VER master
1.26186% difference
--
Calculate average runtime percentage difference between VER master and VER master
1265.08 -> VER master
1275.43 -> VER master
-0.814797% difference
--
Calculate average runtime percentage difference between VER master and VER master
1260.95 -> VER master
1288.81 -> VER master
-2.1853% difference
--
Calculate average runtime percentage difference between VER master and VER master
1260.46 -> VER master
1252.86 -> VER master
0.604778% difference
--
Calculate average runtime percentage difference between VER master and VER master
1253.49 -> VER master
1255.25 -> VER master
-0.140309% difference
--
Calculate average runtime percentage difference between VER master and VER master
1277.5 -> VER master
1267.42 -> VER master
0.792166% difference
--
Calculate average runtime percentage difference between VER master and VER master
1266.2 -> VER master
1283.12 -> VER master
-1.32741% difference
--
Calculate average runtime percentage difference between VER master and VER master
1245.78 -> VER master
1246.78 -> VER master
-0.0802388% difference
--
Calculate average runtime percentage difference between VER master and VER master
1255.15 -> VER master
1276.73 -> VER master
-1.70466% difference

#38Noname
reid.thompson@crunchydata.com
In reply to: Noname (#37)
2 attachment(s)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On Mon, 2023-05-22 at 08:42 -0400, reid.thompson@crunchydata.com wrote:

On Wed, 2023-05-17 at 23:07 -0400, reid.thompson@crunchydata.com wrote:

Thanks for the feedback.

I'm plannning to look at this.

Is your benchmark something that I could utilize? I.E. is it a set of
scripts or a standard test from somewhere that I can duplicate?

Thanks,
Reid

Attach patches updated to master.
Pulled from patch 2 back to patch 1 a change that was also pertinent to patch 1.

Attachments:

0001-Add-tracking-of-backend-memory-allocated.patchtext/x-patch; charset=UTF-8; name=0001-Add-tracking-of-backend-memory-allocated.patchDownload
From e6f8499e0270f2291494260bc341e8ad1411c2ae Mon Sep 17 00:00:00 2001
From: Reid Thompson <jreidthompson@nc.rr.com>
Date: Thu, 11 Aug 2022 12:01:25 -0400
Subject: [PATCH 1/2] Add tracking of backend memory allocated

Add tracking of backend memory allocated in total and by allocation
type (aset, dsm, generation, slab) by process.

allocated_bytes tracks the current bytes of memory allocated to the
backend process. aset_allocated_bytes, dsm_allocated_bytes,
generation_allocated_bytes and slab_allocated_bytes track the
allocation by type for the backend process. They are updated for the
process as memory is malloc'd/freed.  Memory allocated to items on
the freelist is included.  Dynamic shared memory allocations are
included only in the value displayed for the backend that created
them, they are not included in the value for backends that are
attached to them to avoid double counting. DSM allocations that are
not destroyed by the creating process prior to it's exit are
considered long lived and are tracked in a global counter
global_dsm_allocated_bytes. We limit the floor of allocation
counters to zero. Created views pg_stat_global_memory_allocation and
pg_stat_memory_allocation for access to these trackers.
---
 doc/src/sgml/monitoring.sgml                | 246 ++++++++++++++++++++
 src/backend/catalog/system_views.sql        |  34 +++
 src/backend/storage/ipc/dsm.c               |  11 +-
 src/backend/storage/ipc/dsm_impl.c          |  78 +++++++
 src/backend/storage/lmgr/proc.c             |   1 +
 src/backend/utils/activity/backend_status.c | 114 +++++++++
 src/backend/utils/adt/pgstatfuncs.c         |  84 +++++++
 src/backend/utils/init/miscinit.c           |   3 +
 src/backend/utils/mmgr/aset.c               |  17 ++
 src/backend/utils/mmgr/generation.c         |  15 ++
 src/backend/utils/mmgr/slab.c               |  22 ++
 src/include/catalog/pg_proc.dat             |  17 ++
 src/include/storage/proc.h                  |   2 +
 src/include/utils/backend_status.h          | 144 +++++++++++-
 src/test/regress/expected/rules.out         |  27 +++
 src/test/regress/expected/stats.out         |  36 +++
 src/test/regress/sql/stats.sql              |  20 ++
 17 files changed, 869 insertions(+), 2 deletions(-)

diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index df5242fa80..cfc221fb2e 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -5757,6 +5757,252 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
 
  </sect2>
 
+ <sect2 id="monitoring-pg-stat-memory-allocation-view">
+  <title><structname>pg_stat_memory_allocation</structname></title>
+
+  <indexterm>
+   <primary>pg_stat_memory_allocation</primary>
+  </indexterm>
+
+  <para>
+   The <structname>pg_stat_memory_allocation</structname> view will have one
+   row per server process, showing information related to the current memory
+   allocation of that process in total and by allocator type. Due to the
+   dynamic nature of memory allocations the allocated bytes values may not be
+   exact but should be sufficient for the intended purposes. Dynamic shared
+   memory allocations are included only in the value displayed for the backend
+   that created them, they are not included in the value for backends that are
+   attached to them to avoid double counting.  Use
+   <function>pg_size_pretty</function> described in
+   <xref linkend="functions-admin-dbsize"/> to make these values more easily
+   readable.
+  </para>
+
+  <table id="pg-stat-memory-allocation-view" xreflabel="pg_stat_memory_allocation">
+   <title><structname>pg_stat_memory_allocation</structname> View</title>
+   <tgroup cols="1">
+    <thead>
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       Column Type
+      </para>
+      <para>
+       Description
+      </para></entry>
+     </row>
+    </thead>
+
+    <tbody>
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>datid</structfield> <type>oid</type>
+      </para>
+      <para>
+       OID of the database this backend is connected to
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>pid</structfield> <type>integer</type>
+      </para>
+      <para>
+       Process ID of this backend
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>allocated_bytes</structfield> <type>bigint</type>
+      </para>
+     <para>
+      Memory currently allocated to this backend in bytes. This is the balance
+      of bytes allocated and freed by this backend. Dynamic shared memory
+      allocations are included only in the value displayed for the backend that
+      created them, they are not included in the value for backends that are
+      attached to them to avoid double counting.
+     </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>aset_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Memory currently allocated to this backend in bytes via the allocation
+       set allocator.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>dsm_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Memory currently allocated to this backend in bytes via the dynamic
+       shared memory allocator. Upon process exit, dsm allocations that have
+       not been freed are considered long lived and added to
+       <structfield>global_dsm_allocated_bytes</structfield> found in the
+       <link linkend="monitoring-pg-stat-global-memory-allocation-view">
+       <structname>pg_stat_global_memory_allocation</structname></link> view.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>generation_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Memory currently allocated to this backend in bytes via the generation
+       allocator.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>slab_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Memory currently allocated to this backend in bytes via the slab
+       allocator.
+      </para></entry>
+     </row>
+
+    </tbody>
+   </tgroup>
+  </table>
+
+ </sect2>
+
+ <sect2 id="monitoring-pg-stat-global-memory-allocation-view">
+  <title><structname>pg_stat_global_memory_allocation</structname></title>
+
+  <indexterm>
+   <primary>pg_stat_global-memory_allocation</primary>
+  </indexterm>
+
+  <para>
+   The <structname>pg_stat_global_memory_allocation</structname> view will
+   have one row showing information related to current shared memory
+   allocations. Due to the dynamic nature of memory allocations the allocated
+   bytes values may not be exact but should be sufficient for the intended
+   purposes. Use <function>pg_size_pretty</function> described in
+   <xref linkend="functions-admin-dbsize"/> to make the byte populated values
+   more easily readable.
+  </para>
+
+  <table id="pg-stat-global-memory-allocation-view" xreflabel="pg_stat_global_memory_allocation">
+   <title><structname>pg_stat_global_memory_allocation</structname> View</title>
+   <tgroup cols="1">
+    <thead>
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       Column Type
+      </para>
+      <para>
+       Description
+      </para></entry>
+     </row>
+    </thead>
+
+    <tbody>
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>datid</structfield> <type>oid</type>
+      </para>
+      <para>
+       OID of the database this backend is connected to
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>shared_memory_size_mb</structfield> <type>integer</type>
+      </para>
+      <para>
+       Reports the size of the main shared memory area, rounded up to the
+       nearest megabyte. See <xref linkend="guc-shared-memory-size"/>.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>shared_memory_size_in_huge_pages</structfield> <type>bigint</type>
+      </para>
+     <para>
+      Reports the number of huge pages that are needed for the main shared
+      memory area based on the specified huge_page_size. If huge pages are not
+      supported, this will be -1. See
+      <xref linkend="guc-shared-memory-size-in-huge-pages"/>.
+     </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>global_dsm_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Long lived dynamically allocated memory currently allocated to the
+       database. Upon process exit, dsm allocations that have not been freed
+       are considered long lived and added to
+       <structfield>global_dsm_allocated_bytes</structfield>.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>total_aset_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Sum total of <structfield>aset_allocated_bytes</structfield> for all
+       backend processes from
+       <link linkend="monitoring-pg-stat-memory-allocation-view">
+       <structname>pg_stat_memory_allocation</structname></link> view.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>total_dsm_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Sum total of <structfield>dsm_allocated_bytes</structfield> for all
+       backend processes from
+       <link linkend="monitoring-pg-stat-memory-allocation-view">
+       <structname>pg_stat_memory_allocation</structname></link> view.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>total_generation_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Sum total of <structfield>generation_allocated_bytes</structfield> for
+       all backend processes from
+       <link linkend="monitoring-pg-stat-memory-allocation-view">
+       <structname>pg_stat_memory_allocation</structname></link> view.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>total_slab_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Sum total of <structfield>slab_allocated_bytes</structfield> for all
+       backend processes from
+       <link linkend="monitoring-pg-stat-memory-allocation-view">
+       <structname>pg_stat_memory_allocation</structname></link> view.
+      </para></entry>
+     </row>
+
+    </tbody>
+   </tgroup>
+  </table>
+
+ </sect2>
+
  <sect2 id="monitoring-stats-functions">
   <title>Statistics Functions</title>
 
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index c18fea8362..cc8219c665 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -1341,3 +1341,37 @@ CREATE VIEW pg_stat_subscription_stats AS
         ss.stats_reset
     FROM pg_subscription as s,
          pg_stat_get_subscription_stats(s.oid) as ss;
+
+CREATE VIEW pg_stat_memory_allocation AS
+    SELECT
+        S.datid AS datid,
+        S.pid,
+        S.allocated_bytes,
+        S.aset_allocated_bytes,
+        S.dsm_allocated_bytes,
+        S.generation_allocated_bytes,
+        S.slab_allocated_bytes
+    FROM pg_stat_get_memory_allocation(NULL) AS S
+        LEFT JOIN pg_database AS D ON (S.datid = D.oid);
+
+CREATE VIEW pg_stat_global_memory_allocation AS
+WITH sums AS (
+    SELECT
+        SUM(aset_allocated_bytes) AS total_aset_allocated_bytes,
+        SUM(dsm_allocated_bytes) AS total_dsm_allocated_bytes,
+        SUM(generation_allocated_bytes) AS total_generation_allocated_bytes,
+        SUM(slab_allocated_bytes) AS total_slab_allocated_bytes
+    FROM
+        pg_stat_memory_allocation
+)
+SELECT
+        S.datid AS datid,
+        current_setting('shared_memory_size', true) as shared_memory_size,
+        (current_setting('shared_memory_size_in_huge_pages', true))::integer as shared_memory_size_in_huge_pages,
+        S.global_dsm_allocated_bytes,
+        sums.total_aset_allocated_bytes,
+        sums.total_dsm_allocated_bytes,
+        sums.total_generation_allocated_bytes,
+        sums.total_slab_allocated_bytes
+    FROM sums, pg_stat_get_global_memory_allocation() AS S
+        LEFT JOIN pg_database AS D ON (S.datid = D.oid);
diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c
index 10b029bb16..64b1fecd1c 100644
--- a/src/backend/storage/ipc/dsm.c
+++ b/src/backend/storage/ipc/dsm.c
@@ -775,6 +775,15 @@ dsm_detach_all(void)
 void
 dsm_detach(dsm_segment *seg)
 {
+	/*
+	 * Retain mapped_size to pass into destroy call in cases where the detach
+	 * is the last reference. mapped_size is zeroed as part of the detach
+	 * process, but is needed later in these cases for dsm_allocated_bytes
+	 * accounting.
+	 */
+	Size		local_seg_mapped_size = seg->mapped_size;
+	Size	   *ptr_local_seg_mapped_size = &local_seg_mapped_size;
+
 	/*
 	 * Invoke registered callbacks.  Just in case one of those callbacks
 	 * throws a further error that brings us back here, pop the callback
@@ -855,7 +864,7 @@ dsm_detach(dsm_segment *seg)
 			 */
 			if (is_main_region_dsm_handle(seg->handle) ||
 				dsm_impl_op(DSM_OP_DESTROY, seg->handle, 0, &seg->impl_private,
-							&seg->mapped_address, &seg->mapped_size, WARNING))
+							&seg->mapped_address, ptr_local_seg_mapped_size, WARNING))
 			{
 				LWLockAcquire(DynamicSharedMemoryControlLock, LW_EXCLUSIVE);
 				if (is_main_region_dsm_handle(seg->handle))
diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c
index 6399fa2ad5..f43bad4439 100644
--- a/src/backend/storage/ipc/dsm_impl.c
+++ b/src/backend/storage/ipc/dsm_impl.c
@@ -66,6 +66,7 @@
 #include "postmaster/postmaster.h"
 #include "storage/dsm_impl.h"
 #include "storage/fd.h"
+#include "utils/backend_status.h"
 #include "utils/guc.h"
 #include "utils/memutils.h"
 
@@ -232,6 +233,14 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_allocated_bytes_decrease(*mapped_size, PG_ALLOC_DSM);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && shm_unlink(name) != 0)
@@ -332,6 +341,33 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+	{
+		/*
+		 * Posix creation calls dsm_impl_posix_resize implying that resizing
+		 * occurs or may be added in the future. As implemented
+		 * dsm_impl_posix_resize utilizes fallocate or truncate, passing the
+		 * whole new size as input, growing the allocation as needed (only
+		 * truncate supports shrinking). We update by replacing the old
+		 * allocation with the new.
+		 */
+#if defined(HAVE_POSIX_FALLOCATE) && defined(__linux__)
+		/*
+		 * posix_fallocate does not shrink allocations, adjust only on
+		 * allocation increase.
+		 */
+		if (request_size > *mapped_size)
+			pgstat_report_allocated_bytes_increase(request_size - *mapped_size, PG_ALLOC_DSM);
+#else
+		pgstat_report_allocated_bytes_decrease(*mapped_size, PG_ALLOC_DSM);
+		pgstat_report_allocated_bytes_increase(request_size, PG_ALLOC_DSM);
+#endif
+	}
 	*mapped_address = address;
 	*mapped_size = request_size;
 	close(fd);
@@ -538,6 +574,14 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_allocated_bytes_decrease(*mapped_size, PG_ALLOC_DSM);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && shmctl(ident, IPC_RMID, NULL) < 0)
@@ -585,6 +629,13 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_allocated_bytes_increase(request_size, PG_ALLOC_DSM);
 	*mapped_address = address;
 	*mapped_size = request_size;
 
@@ -653,6 +704,13 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 			return false;
 		}
 
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_allocated_bytes_decrease(*mapped_size, PG_ALLOC_DSM);
 		*impl_private = NULL;
 		*mapped_address = NULL;
 		*mapped_size = 0;
@@ -769,6 +827,12 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 		return false;
 	}
 
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_allocated_bytes_increase(info.RegionSize, PG_ALLOC_DSM);
 	*mapped_address = address;
 	*mapped_size = info.RegionSize;
 	*impl_private = hmap;
@@ -813,6 +877,13 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		pgstat_report_allocated_bytes_decrease(*mapped_size, PG_ALLOC_DSM);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && unlink(name) != 0)
@@ -934,6 +1005,13 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_allocated_bytes_increase(request_size, PG_ALLOC_DSM);
 	*mapped_address = address;
 	*mapped_size = request_size;
 
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index dac921219f..d798c05180 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -180,6 +180,7 @@ InitProcGlobal(void)
 	ProcGlobal->checkpointerLatch = NULL;
 	pg_atomic_init_u32(&ProcGlobal->procArrayGroupFirst, INVALID_PGPROCNO);
 	pg_atomic_init_u32(&ProcGlobal->clogGroupFirst, INVALID_PGPROCNO);
+	pg_atomic_init_u64(&ProcGlobal->global_dsm_allocation, 0);
 
 	/*
 	 * Create and initialize all the PGPROC structures we'll need.  There are
diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c
index 38f91a495b..50b36ba5f7 100644
--- a/src/backend/utils/activity/backend_status.c
+++ b/src/backend/utils/activity/backend_status.c
@@ -49,6 +49,24 @@ int			pgstat_track_activity_query_size = 1024;
 /* exposed so that backend_progress.c can access it */
 PgBackendStatus *MyBEEntry = NULL;
 
+/*
+ * Memory allocated to this backend prior to pgstats initialization. Migrated to
+ * shared memory on pgstats initialization.
+ */
+uint64		local_my_allocated_bytes = 0;
+uint64	   *my_allocated_bytes = &local_my_allocated_bytes;
+
+/* Memory allocated to this backend by type prior to pgstats initialization.
+ * Migrated to shared memory on pgstats initialization
+ */
+uint64		local_my_aset_allocated_bytes = 0;
+uint64	   *my_aset_allocated_bytes = &local_my_aset_allocated_bytes;
+uint64		local_my_dsm_allocated_bytes = 0;
+uint64	   *my_dsm_allocated_bytes = &local_my_dsm_allocated_bytes;
+uint64		local_my_generation_allocated_bytes = 0;
+uint64	   *my_generation_allocated_bytes = &local_my_generation_allocated_bytes;
+uint64		local_my_slab_allocated_bytes = 0;
+uint64	   *my_slab_allocated_bytes = &local_my_slab_allocated_bytes;
 
 static PgBackendStatus *BackendStatusArray = NULL;
 static char *BackendAppnameBuffer = NULL;
@@ -401,6 +419,32 @@ pgstat_bestart(void)
 	lbeentry.st_progress_command_target = InvalidOid;
 	lbeentry.st_query_id = UINT64CONST(0);
 
+	/* Alter allocation reporting from local storage to shared memory */
+	pgstat_set_allocated_bytes_storage(&MyBEEntry->allocated_bytes,
+									   &MyBEEntry->aset_allocated_bytes,
+									   &MyBEEntry->dsm_allocated_bytes,
+									   &MyBEEntry->generation_allocated_bytes,
+									   &MyBEEntry->slab_allocated_bytes);
+
+	/*
+	 * Populate sum of memory allocated prior to pgstats initialization to
+	 * pgstats and zero the local variable. This is a += assignment because
+	 * InitPostgres allocates memory after pgstat_beinit but prior to
+	 * pgstat_bestart so we have allocations to both local and shared memory
+	 * to combine.
+	 */
+	lbeentry.allocated_bytes += local_my_allocated_bytes;
+	local_my_allocated_bytes = 0;
+	lbeentry.aset_allocated_bytes += local_my_aset_allocated_bytes;
+	local_my_aset_allocated_bytes = 0;
+
+	lbeentry.dsm_allocated_bytes += local_my_dsm_allocated_bytes;
+	local_my_dsm_allocated_bytes = 0;
+	lbeentry.generation_allocated_bytes += local_my_generation_allocated_bytes;
+	local_my_generation_allocated_bytes = 0;
+	lbeentry.slab_allocated_bytes += local_my_slab_allocated_bytes;
+	local_my_slab_allocated_bytes = 0;
+
 	/*
 	 * we don't zero st_progress_param here to save cycles; nobody should
 	 * examine it until st_progress_command has been set to something other
@@ -460,6 +504,9 @@ pgstat_beshutdown_hook(int code, Datum arg)
 {
 	volatile PgBackendStatus *beentry = MyBEEntry;
 
+	/* Stop reporting memory allocation changes to shared memory */
+	pgstat_reset_allocated_bytes_storage();
+
 	/*
 	 * Clear my status entry, following the protocol of bumping st_changecount
 	 * before and after.  We use a volatile pointer here to ensure the
@@ -1195,3 +1242,70 @@ pgstat_clip_activity(const char *raw_activity)
 
 	return activity;
 }
+
+/*
+ * Configure bytes allocated reporting to report allocated bytes to
+ * shared memory.
+ *
+ * Expected to be called during backend startup (in pgstat_bestart), to point
+ * allocated bytes accounting into shared memory.
+ */
+void
+pgstat_set_allocated_bytes_storage(uint64 *allocated_bytes,
+								   uint64 *aset_allocated_bytes,
+								   uint64 *dsm_allocated_bytes,
+								   uint64 *generation_allocated_bytes,
+								   uint64 *slab_allocated_bytes)
+{
+	/* Map allocations to shared memory */
+	my_allocated_bytes = allocated_bytes;
+	*allocated_bytes = local_my_allocated_bytes;
+
+	my_aset_allocated_bytes = aset_allocated_bytes;
+	*aset_allocated_bytes = local_my_aset_allocated_bytes;
+
+	my_dsm_allocated_bytes = dsm_allocated_bytes;
+	*dsm_allocated_bytes = local_my_dsm_allocated_bytes;
+
+	my_generation_allocated_bytes = generation_allocated_bytes;
+	*generation_allocated_bytes = local_my_generation_allocated_bytes;
+
+	my_slab_allocated_bytes = slab_allocated_bytes;
+	*slab_allocated_bytes = local_my_slab_allocated_bytes;
+}
+
+/*
+ * Reset allocated bytes storage location.
+ *
+ * Expected to be called during backend shutdown, before the locations set up
+ * by pgstat_set_allocated_bytes_storage become invalid.
+ */
+void
+pgstat_reset_allocated_bytes_storage(void)
+{
+	if (ProcGlobal)
+	{
+		volatile PROC_HDR *procglobal = ProcGlobal;
+
+		/*
+		 * Add dsm allocations that have not been freed to global dsm
+		 * accounting
+		 */
+		pg_atomic_add_fetch_u64(&procglobal->global_dsm_allocation,
+								*my_dsm_allocated_bytes);
+	}
+
+	/* Reset memory allocation variables */
+	*my_allocated_bytes = local_my_allocated_bytes = 0;
+	*my_aset_allocated_bytes = local_my_aset_allocated_bytes = 0;
+	*my_dsm_allocated_bytes = local_my_dsm_allocated_bytes = 0;
+	*my_generation_allocated_bytes = local_my_generation_allocated_bytes = 0;
+	*my_slab_allocated_bytes = local_my_slab_allocated_bytes = 0;
+
+	/* Point my_{*_}allocated_bytes from shared memory back to local */
+	my_allocated_bytes = &local_my_allocated_bytes;
+	my_aset_allocated_bytes = &local_my_aset_allocated_bytes;
+	my_dsm_allocated_bytes = &local_my_dsm_allocated_bytes;
+	my_generation_allocated_bytes = &local_my_generation_allocated_bytes;
+	my_slab_allocated_bytes = &local_my_slab_allocated_bytes;
+}
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 49adc319fc..35f2d2bffe 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -2062,3 +2062,87 @@ pg_stat_have_stats(PG_FUNCTION_ARGS)
 
 	PG_RETURN_BOOL(pgstat_have_entry(kind, dboid, objoid));
 }
+
+/*
+ * Get the memory allocation of PG backends.
+ */
+Datum
+pg_stat_get_memory_allocation(PG_FUNCTION_ARGS)
+{
+#define PG_STAT_GET_MEMORY_ALLOCATION_COLS	7
+	int			num_backends = pgstat_fetch_stat_numbackends();
+	int			curr_backend;
+	int			pid = PG_ARGISNULL(0) ? -1 : PG_GETARG_INT32(0);
+	ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
+
+	InitMaterializedSRF(fcinfo, 0);
+
+	/* 1-based index */
+	for (curr_backend = 1; curr_backend <= num_backends; curr_backend++)
+	{
+		/* for each row */
+		Datum		values[PG_STAT_GET_MEMORY_ALLOCATION_COLS] = {0};
+		bool		nulls[PG_STAT_GET_MEMORY_ALLOCATION_COLS] = {0};
+		LocalPgBackendStatus *local_beentry;
+		PgBackendStatus *beentry;
+
+		/* Get the next one in the list */
+		local_beentry = pgstat_fetch_stat_local_beentry(curr_backend);
+		beentry = &local_beentry->backendStatus;
+
+		/* If looking for specific PID, ignore all the others */
+		if (pid != -1 && beentry->st_procpid != pid)
+			continue;
+
+		/* Values available to all callers */
+		if (beentry->st_databaseid != InvalidOid)
+			values[0] = ObjectIdGetDatum(beentry->st_databaseid);
+		else
+			nulls[0] = true;
+
+		values[1] = Int32GetDatum(beentry->st_procpid);
+		values[2] = UInt64GetDatum(beentry->allocated_bytes);
+		values[3] = UInt64GetDatum(beentry->aset_allocated_bytes);
+		values[4] = UInt64GetDatum(beentry->dsm_allocated_bytes);
+		values[5] = UInt64GetDatum(beentry->generation_allocated_bytes);
+		values[6] = UInt64GetDatum(beentry->slab_allocated_bytes);
+
+		tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
+
+		/* If only a single backend was requested, and we found it, break. */
+		if (pid != -1)
+			break;
+	}
+
+	return (Datum) 0;
+}
+
+/*
+ * Get the global memory allocation statistics.
+ */
+Datum
+pg_stat_get_global_memory_allocation(PG_FUNCTION_ARGS)
+{
+#define PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS	2
+	TupleDesc	tupdesc;
+	Datum		values[PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS] = {0};
+	bool		nulls[PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS] = {0};
+	volatile PROC_HDR *procglobal = ProcGlobal;
+
+	/* Initialise attributes information in the tuple descriptor */
+	tupdesc = CreateTemplateTupleDesc(PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS);
+	TupleDescInitEntry(tupdesc, (AttrNumber) 1, "datid",
+					   OIDOID, -1, 0);
+	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "global_dsm_allocated_bytes",
+					   INT8OID, -1, 0);
+	BlessTupleDesc(tupdesc);
+
+	/* datid */
+	values[0] = ObjectIdGetDatum(MyDatabaseId);
+
+	/* get global_dsm_allocated_bytes */
+	values[1] = Int64GetDatum(pg_atomic_read_u64(&procglobal->global_dsm_allocation));
+
+	/* Returns the record as Datum */
+	PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls)));
+}
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index a604432126..7b8eeb7dbb 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -171,6 +171,9 @@ InitPostmasterChild(void)
 				(errcode_for_socket_access(),
 				 errmsg_internal("could not set postmaster death monitoring pipe to FD_CLOEXEC mode: %m")));
 #endif
+
+	/* Init allocated bytes to avoid double counting parent allocation */
+	pgstat_init_allocated_bytes();
 }
 
 /*
diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index 0bbbf93672..4146831d75 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -47,6 +47,7 @@
 #include "postgres.h"
 
 #include "port/pg_bitutils.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -513,6 +514,7 @@ AllocSetContextCreateInternal(MemoryContext parent,
 						name);
 
 	((MemoryContext) set)->mem_allocated = firstBlockSize;
+	pgstat_report_allocated_bytes_increase(firstBlockSize, PG_ALLOC_ASET);
 
 	return (MemoryContext) set;
 }
@@ -535,6 +537,7 @@ AllocSetReset(MemoryContext context)
 	AllocSet	set = (AllocSet) context;
 	AllocBlock	block;
 	Size		keepersize PG_USED_FOR_ASSERTS_ONLY;
+	uint64		deallocation = 0;
 
 	Assert(AllocSetIsValid(set));
 
@@ -577,6 +580,7 @@ AllocSetReset(MemoryContext context)
 		{
 			/* Normal case, release the block */
 			context->mem_allocated -= block->endptr - ((char *) block);
+			deallocation += block->endptr - ((char *) block);
 
 #ifdef CLOBBER_FREED_MEMORY
 			wipe_mem(block, block->freeptr - ((char *) block));
@@ -587,6 +591,7 @@ AllocSetReset(MemoryContext context)
 	}
 
 	Assert(context->mem_allocated == keepersize);
+	pgstat_report_allocated_bytes_decrease(deallocation, PG_ALLOC_ASET);
 
 	/* Reset block size allocation sequence, too */
 	set->nextBlockSize = set->initBlockSize;
@@ -605,6 +610,7 @@ AllocSetDelete(MemoryContext context)
 	AllocSet	set = (AllocSet) context;
 	AllocBlock	block = set->blocks;
 	Size		keepersize PG_USED_FOR_ASSERTS_ONLY;
+	uint64		deallocation = 0;
 
 	Assert(AllocSetIsValid(set));
 
@@ -643,11 +649,13 @@ AllocSetDelete(MemoryContext context)
 
 				freelist->first_free = (AllocSetContext *) oldset->header.nextchild;
 				freelist->num_free--;
+				deallocation += oldset->header.mem_allocated;
 
 				/* All that remains is to free the header/initial block */
 				free(oldset);
 			}
 			Assert(freelist->num_free == 0);
+			pgstat_report_allocated_bytes_decrease(deallocation, PG_ALLOC_ASET);
 		}
 
 		/* Now add the just-deleted context to the freelist. */
@@ -664,7 +672,10 @@ AllocSetDelete(MemoryContext context)
 		AllocBlock	next = block->next;
 
 		if (block != set->keeper)
+		{
 			context->mem_allocated -= block->endptr - ((char *) block);
+			deallocation += block->endptr - ((char *) block);
+		}
 
 #ifdef CLOBBER_FREED_MEMORY
 		wipe_mem(block, block->freeptr - ((char *) block));
@@ -677,6 +688,7 @@ AllocSetDelete(MemoryContext context)
 	}
 
 	Assert(context->mem_allocated == keepersize);
+	pgstat_report_allocated_bytes_decrease(deallocation + context->mem_allocated, PG_ALLOC_ASET);
 
 	/* Finally, free the context header, including the keeper block */
 	free(set);
@@ -726,6 +738,7 @@ AllocSetAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_allocated_bytes_increase(blksize, PG_ALLOC_ASET);
 
 		block->aset = set;
 		block->freeptr = block->endptr = ((char *) block) + blksize;
@@ -939,6 +952,7 @@ AllocSetAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_allocated_bytes_increase(blksize, PG_ALLOC_ASET);
 
 		block->aset = set;
 		block->freeptr = ((char *) block) + ALLOC_BLOCKHDRSZ;
@@ -1036,6 +1050,7 @@ AllocSetFree(void *pointer)
 			block->next->prev = block->prev;
 
 		set->header.mem_allocated -= block->endptr - ((char *) block);
+		pgstat_report_allocated_bytes_decrease(block->endptr - ((char *) block), PG_ALLOC_ASET);
 
 #ifdef CLOBBER_FREED_MEMORY
 		wipe_mem(block, block->freeptr - ((char *) block));
@@ -1166,7 +1181,9 @@ AllocSetRealloc(void *pointer, Size size)
 
 		/* updated separately, not to underflow when (oldblksize > blksize) */
 		set->header.mem_allocated -= oldblksize;
+		pgstat_report_allocated_bytes_decrease(oldblksize, PG_ALLOC_ASET);
 		set->header.mem_allocated += blksize;
+		pgstat_report_allocated_bytes_increase(blksize, PG_ALLOC_ASET);
 
 		block->freeptr = block->endptr = ((char *) block) + blksize;
 
diff --git a/src/backend/utils/mmgr/generation.c b/src/backend/utils/mmgr/generation.c
index 4fb8663cd6..502f877855 100644
--- a/src/backend/utils/mmgr/generation.c
+++ b/src/backend/utils/mmgr/generation.c
@@ -37,6 +37,7 @@
 
 #include "lib/ilist.h"
 #include "port/pg_bitutils.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -259,6 +260,7 @@ GenerationContextCreate(MemoryContext parent,
 						name);
 
 	((MemoryContext) set)->mem_allocated = firstBlockSize;
+	pgstat_report_allocated_bytes_increase(firstBlockSize, PG_ALLOC_GENERATION);
 
 	return (MemoryContext) set;
 }
@@ -275,6 +277,7 @@ GenerationReset(MemoryContext context)
 {
 	GenerationContext *set = (GenerationContext *) context;
 	dlist_mutable_iter miter;
+	uint64		deallocation = 0;
 
 	Assert(GenerationIsValid(set));
 
@@ -297,9 +300,14 @@ GenerationReset(MemoryContext context)
 		if (block == set->keeper)
 			GenerationBlockMarkEmpty(block);
 		else
+		{
+			deallocation += block->blksize;
 			GenerationBlockFree(set, block);
+		}
 	}
 
+	pgstat_report_allocated_bytes_decrease(deallocation, PG_ALLOC_GENERATION);
+
 	/* set it so new allocations to make use of the keeper block */
 	set->block = set->keeper;
 
@@ -320,6 +328,9 @@ GenerationDelete(MemoryContext context)
 {
 	/* Reset to release all releasable GenerationBlocks */
 	GenerationReset(context);
+
+	pgstat_report_allocated_bytes_decrease(context->mem_allocated, PG_ALLOC_GENERATION);
+
 	/* And free the context header and keeper block */
 	free(context);
 }
@@ -366,6 +377,7 @@ GenerationAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_allocated_bytes_increase(blksize, PG_ALLOC_GENERATION);
 
 		/* block with a single (used) chunk */
 		block->context = set;
@@ -469,6 +481,7 @@ GenerationAlloc(MemoryContext context, Size size)
 				return NULL;
 
 			context->mem_allocated += blksize;
+			pgstat_report_allocated_bytes_increase(blksize, PG_ALLOC_GENERATION);
 
 			/* initialize the new block */
 			GenerationBlockInit(set, block, blksize);
@@ -721,6 +734,8 @@ GenerationFree(void *pointer)
 	dlist_delete(&block->node);
 
 	set->header.mem_allocated -= block->blksize;
+	pgstat_report_allocated_bytes_decrease(block->blksize, PG_ALLOC_GENERATION);
+
 	free(block);
 }
 
diff --git a/src/backend/utils/mmgr/slab.c b/src/backend/utils/mmgr/slab.c
index 718dd2ba03..913787dba8 100644
--- a/src/backend/utils/mmgr/slab.c
+++ b/src/backend/utils/mmgr/slab.c
@@ -69,6 +69,7 @@
 #include "postgres.h"
 
 #include "lib/ilist.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -413,6 +414,13 @@ SlabContextCreate(MemoryContext parent,
 						parent,
 						name);
 
+	/*
+	 * If SlabContextCreate is updated to add context header size to
+	 * context->mem_allocated, then update here and SlabDelete appropriately
+	 */
+	pgstat_report_allocated_bytes_increase(Slab_CONTEXT_HDRSZ(slab->chunksPerBlock),
+										   PG_ALLOC_SLAB);
+
 	return (MemoryContext) slab;
 }
 
@@ -429,6 +437,7 @@ SlabReset(MemoryContext context)
 	SlabContext *slab = (SlabContext *) context;
 	dlist_mutable_iter miter;
 	int			i;
+	uint64		deallocation = 0;
 
 	Assert(SlabIsValid(slab));
 
@@ -449,6 +458,7 @@ SlabReset(MemoryContext context)
 #endif
 		free(block);
 		context->mem_allocated -= slab->blockSize;
+		deallocation += slab->blockSize;
 	}
 
 	/* walk over blocklist and free the blocks */
@@ -465,9 +475,11 @@ SlabReset(MemoryContext context)
 #endif
 			free(block);
 			context->mem_allocated -= slab->blockSize;
+			deallocation += slab->blockSize;
 		}
 	}
 
+	pgstat_report_allocated_bytes_decrease(deallocation, PG_ALLOC_SLAB);
 	slab->curBlocklistIndex = 0;
 
 	Assert(context->mem_allocated == 0);
@@ -482,6 +494,14 @@ SlabDelete(MemoryContext context)
 {
 	/* Reset to release all the SlabBlocks */
 	SlabReset(context);
+
+	/*
+	 * Until context header allocation is included in context->mem_allocated,
+	 * cast to slab and decrement the header allocation
+	 */
+	pgstat_report_allocated_bytes_decrease(Slab_CONTEXT_HDRSZ(((SlabContext *) context)->chunksPerBlock),
+										   PG_ALLOC_SLAB);
+
 	/* And free the context header */
 	free(context);
 }
@@ -546,6 +566,7 @@ SlabAlloc(MemoryContext context, Size size)
 
 			block->slab = slab;
 			context->mem_allocated += slab->blockSize;
+			pgstat_report_allocated_bytes_increase(slab->blockSize, PG_ALLOC_SLAB);
 
 			/* use the first chunk in the new block */
 			chunk = SlabBlockGetChunk(slab, block, 0);
@@ -740,6 +761,7 @@ SlabFree(void *pointer)
 #endif
 			free(block);
 			slab->header.mem_allocated -= slab->blockSize;
+			pgstat_report_allocated_bytes_decrease(slab->blockSize, PG_ALLOC_SLAB);
 		}
 
 		/*
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 6996073989..b095740f8a 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -5408,6 +5408,23 @@
   proname => 'pg_stat_get_backend_idset', prorows => '100', proretset => 't',
   provolatile => 's', proparallel => 'r', prorettype => 'int4',
   proargtypes => '', prosrc => 'pg_stat_get_backend_idset' },
+{ oid => '9890',
+  descr => 'statistics: memory allocation information for backends',
+  proname => 'pg_stat_get_memory_allocation', prorows => '100', proisstrict => 'f',
+  proretset => 't', provolatile => 's', proparallel => 'r',
+  prorettype => 'record', proargtypes => 'int4',
+  proallargtypes => '{int4,oid,int4,int8,int8,int8,int8,int8}',
+  proargmodes => '{i,o,o,o,o,o,o,o}',
+  proargnames => '{pid,datid,pid,allocated_bytes,aset_allocated_bytes,dsm_allocated_bytes,generation_allocated_bytes,slab_allocated_bytes}',
+  prosrc => 'pg_stat_get_memory_allocation' },
+{ oid => '9891',
+  descr => 'statistics: global memory allocation information',
+  proname => 'pg_stat_get_global_memory_allocation', proisstrict => 'f',
+  provolatile => 's', proparallel => 'r', prorettype => 'record',
+  proargtypes => '', proallargtypes => '{oid,int8}',
+  proargmodes => '{o,o}',
+  proargnames => '{datid,global_dsm_allocated_bytes}',
+  prosrc =>'pg_stat_get_global_memory_allocation' },
 { oid => '2022',
   descr => 'statistics: information about currently active backends',
   proname => 'pg_stat_get_activity', prorows => '100', proisstrict => 'f',
diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h
index ef74f32693..e6be67de2a 100644
--- a/src/include/storage/proc.h
+++ b/src/include/storage/proc.h
@@ -404,6 +404,8 @@ typedef struct PROC_HDR
 	int			spins_per_delay;
 	/* Buffer id of the buffer that Startup process waits for pin on, or -1 */
 	int			startupBufferPinWaitBufId;
+	/* Global dsm allocations */
+	pg_atomic_uint64 global_dsm_allocation;
 } PROC_HDR;
 
 extern PGDLLIMPORT PROC_HDR *ProcGlobal;
diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h
index 16500d53b2..9b75fc5223 100644
--- a/src/include/utils/backend_status.h
+++ b/src/include/utils/backend_status.h
@@ -10,6 +10,7 @@
 #ifndef BACKEND_STATUS_H
 #define BACKEND_STATUS_H
 
+#include "common/int.h"
 #include "datatype/timestamp.h"
 #include "libpq/pqcomm.h"
 #include "miscadmin.h"			/* for BackendType */
@@ -32,6 +33,14 @@ typedef enum BackendState
 	STATE_DISABLED
 } BackendState;
 
+/* Enum helper for reporting memory allocator type */
+enum pg_allocator_type
+{
+	PG_ALLOC_ASET = 1,
+	PG_ALLOC_DSM,
+	PG_ALLOC_GENERATION,
+	PG_ALLOC_SLAB
+};
 
 /* ----------
  * Shared-memory data structures
@@ -170,6 +179,15 @@ typedef struct PgBackendStatus
 
 	/* query identifier, optionally computed using post_parse_analyze_hook */
 	uint64		st_query_id;
+
+	/* Current memory allocated to this backend */
+	uint64		allocated_bytes;
+
+	/* Current memory allocated to this backend by type */
+	uint64		aset_allocated_bytes;
+	uint64		dsm_allocated_bytes;
+	uint64		generation_allocated_bytes;
+	uint64		slab_allocated_bytes;
 } PgBackendStatus;
 
 
@@ -294,6 +312,11 @@ extern PGDLLIMPORT int pgstat_track_activity_query_size;
  * ----------
  */
 extern PGDLLIMPORT PgBackendStatus *MyBEEntry;
+extern PGDLLIMPORT uint64 *my_allocated_bytes;
+extern PGDLLIMPORT uint64 *my_aset_allocated_bytes;
+extern PGDLLIMPORT uint64 *my_dsm_allocated_bytes;
+extern PGDLLIMPORT uint64 *my_generation_allocated_bytes;
+extern PGDLLIMPORT uint64 *my_slab_allocated_bytes;
 
 
 /* ----------
@@ -325,7 +348,12 @@ extern const char *pgstat_get_backend_current_activity(int pid, bool checkUser);
 extern const char *pgstat_get_crashed_backend_activity(int pid, char *buffer,
 													   int buflen);
 extern uint64 pgstat_get_my_query_id(void);
-
+extern void pgstat_set_allocated_bytes_storage(uint64 *allocated_bytes,
+											   uint64 *aset_allocated_bytes,
+											   uint64 *dsm_allocated_bytes,
+											   uint64 *generation_allocated_bytes,
+											   uint64 *slab_allocated_bytes);
+extern void pgstat_reset_allocated_bytes_storage(void);
 
 /* ----------
  * Support functions for the SQL-callable functions to
@@ -337,5 +365,119 @@ extern PgBackendStatus *pgstat_fetch_stat_beentry(BackendId beid);
 extern LocalPgBackendStatus *pgstat_fetch_stat_local_beentry(int beid);
 extern char *pgstat_clip_activity(const char *raw_activity);
 
+/* ----------
+ * pgstat_report_allocated_bytes_decrease() -
+ *  Called to report decrease in memory allocated for this backend.
+ *
+ * my_{*_}allocated_bytes initially points to local memory, making it safe to
+ * call this before pgstats has been initialized.
+ * ----------
+ */
+static inline void
+pgstat_report_allocated_bytes_decrease(int64 proc_allocated_bytes,
+									   int pg_allocator_type)
+{
+	uint64		temp;
+
+	/* Avoid allocated_bytes unsigned integer overflow on decrease */
+	if (pg_sub_u64_overflow(*my_allocated_bytes, proc_allocated_bytes, &temp))
+	{
+		/* On overflow, set allocated bytes and allocator type bytes to zero */
+		*my_allocated_bytes = 0;
+		*my_aset_allocated_bytes = 0;
+		*my_dsm_allocated_bytes = 0;
+		*my_generation_allocated_bytes = 0;
+		*my_slab_allocated_bytes = 0;
+	}
+	else
+	{
+		/* decrease allocation */
+		*my_allocated_bytes -= proc_allocated_bytes;
+
+		/* Decrease allocator type allocated bytes. */
+		switch (pg_allocator_type)
+		{
+			case PG_ALLOC_ASET:
+				*my_aset_allocated_bytes -= proc_allocated_bytes;
+				break;
+			case PG_ALLOC_DSM:
+
+				/*
+				 * Some dsm allocations live beyond process exit. These are
+				 * accounted for in a global counter in
+				 * pgstat_reset_allocated_bytes_storage at process exit.
+				 */
+				*my_dsm_allocated_bytes -= proc_allocated_bytes;
+				break;
+			case PG_ALLOC_GENERATION:
+				*my_generation_allocated_bytes -= proc_allocated_bytes;
+				break;
+			case PG_ALLOC_SLAB:
+				*my_slab_allocated_bytes -= proc_allocated_bytes;
+				break;
+		}
+	}
+
+	return;
+}
+
+/* ----------
+ * pgstat_report_allocated_bytes_increase() -
+ *  Called to report increase in memory allocated for this backend.
+ *
+ * my_allocated_bytes initially points to local memory, making it safe to call
+ * this before pgstats has been initialized.
+ * ----------
+ */
+static inline void
+pgstat_report_allocated_bytes_increase(int64 proc_allocated_bytes,
+									   int pg_allocator_type)
+{
+	*my_allocated_bytes += proc_allocated_bytes;
+
+	/* Increase allocator type allocated bytes */
+	switch (pg_allocator_type)
+	{
+		case PG_ALLOC_ASET:
+			*my_aset_allocated_bytes += proc_allocated_bytes;
+			break;
+		case PG_ALLOC_DSM:
+
+			/*
+			 * Some dsm allocations live beyond process exit. These are
+			 * accounted for in a global counter in
+			 * pgstat_reset_allocated_bytes_storage at process exit.
+			 */
+			*my_dsm_allocated_bytes += proc_allocated_bytes;
+			break;
+		case PG_ALLOC_GENERATION:
+			*my_generation_allocated_bytes += proc_allocated_bytes;
+			break;
+		case PG_ALLOC_SLAB:
+			*my_slab_allocated_bytes += proc_allocated_bytes;
+			break;
+	}
+
+	return;
+}
+
+/* ---------
+ * pgstat_init_allocated_bytes() -
+ *
+ * Called to initialize allocated bytes variables after fork and to
+ * avoid double counting allocations.
+ * ---------
+ */
+static inline void
+pgstat_init_allocated_bytes(void)
+{
+	*my_allocated_bytes = 0;
+	*my_aset_allocated_bytes = 0;
+	*my_dsm_allocated_bytes = 0;
+	*my_generation_allocated_bytes = 0;
+	*my_slab_allocated_bytes = 0;
+
+	return;
+}
 
 #endif							/* BACKEND_STATUS_H */
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index 7fd81e6a7d..ff76aa99a2 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1873,6 +1873,24 @@ pg_stat_database_conflicts| SELECT oid AS datid,
     pg_stat_get_db_conflict_startup_deadlock(oid) AS confl_deadlock,
     pg_stat_get_db_conflict_logicalslot(oid) AS confl_active_logicalslot
    FROM pg_database d;
+pg_stat_global_memory_allocation| WITH sums AS (
+         SELECT sum(pg_stat_memory_allocation.aset_allocated_bytes) AS total_aset_allocated_bytes,
+            sum(pg_stat_memory_allocation.dsm_allocated_bytes) AS total_dsm_allocated_bytes,
+            sum(pg_stat_memory_allocation.generation_allocated_bytes) AS total_generation_allocated_bytes,
+            sum(pg_stat_memory_allocation.slab_allocated_bytes) AS total_slab_allocated_bytes
+           FROM pg_stat_memory_allocation
+        )
+ SELECT s.datid,
+    current_setting('shared_memory_size'::text, true) AS shared_memory_size,
+    (current_setting('shared_memory_size_in_huge_pages'::text, true))::integer AS shared_memory_size_in_huge_pages,
+    s.global_dsm_allocated_bytes,
+    sums.total_aset_allocated_bytes,
+    sums.total_dsm_allocated_bytes,
+    sums.total_generation_allocated_bytes,
+    sums.total_slab_allocated_bytes
+   FROM sums,
+    (pg_stat_get_global_memory_allocation() s(datid, global_dsm_allocated_bytes)
+     LEFT JOIN pg_database d ON ((s.datid = d.oid)));
 pg_stat_gssapi| SELECT pid,
     gss_auth AS gss_authenticated,
     gss_princ AS principal,
@@ -1899,6 +1917,15 @@ pg_stat_io| SELECT backend_type,
     fsync_time,
     stats_reset
    FROM pg_stat_get_io() b(backend_type, object, context, reads, read_time, writes, write_time, writebacks, writeback_time, extends, extend_time, op_bytes, hits, evictions, reuses, fsyncs, fsync_time, stats_reset);
+pg_stat_memory_allocation| SELECT s.datid,
+    s.pid,
+    s.allocated_bytes,
+    s.aset_allocated_bytes,
+    s.dsm_allocated_bytes,
+    s.generation_allocated_bytes,
+    s.slab_allocated_bytes
+   FROM (pg_stat_get_memory_allocation(NULL::integer) s(datid, pid, allocated_bytes, aset_allocated_bytes, dsm_allocated_bytes, generation_allocated_bytes, slab_allocated_bytes)
+     LEFT JOIN pg_database d ON ((s.datid = d.oid)));
 pg_stat_progress_analyze| SELECT s.pid,
     s.datid,
     d.datname,
diff --git a/src/test/regress/expected/stats.out b/src/test/regress/expected/stats.out
index 8e63340782..748c337ee7 100644
--- a/src/test/regress/expected/stats.out
+++ b/src/test/regress/expected/stats.out
@@ -1572,4 +1572,40 @@ SELECT COUNT(*) FROM brin_hot_3 WHERE a = 2;
 
 DROP TABLE brin_hot_3;
 SET enable_seqscan = on;
+-- ensure that allocated_bytes exist for backends
+SELECT
+    allocated_bytes > 0 AS result
+FROM
+    pg_stat_activity ps
+    JOIN pg_stat_memory_allocation pa ON (pa.pid = ps.pid)
+WHERE
+    backend_type IN ('checkpointer', 'background writer', 'walwriter', 'autovacuum launcher');
+ result 
+--------
+ t
+ t
+ t
+ t
+(4 rows)
+
+-- ensure that pg_stat_global_memory_allocation view exists
+SELECT
+    datid > 0, pg_size_bytes(shared_memory_size) >= 0, shared_memory_size_in_huge_pages >= -1, global_dsm_allocated_bytes >= 0
+FROM
+    pg_stat_global_memory_allocation;
+ ?column? | ?column? | ?column? | ?column? 
+----------+----------+----------+----------
+ t        | t        | t        | t
+(1 row)
+
+-- ensure that pg_stat_memory_allocation view exists
+SELECT
+    pid > 0, allocated_bytes >= 0, aset_allocated_bytes >= 0, dsm_allocated_bytes >= 0, generation_allocated_bytes >= 0, slab_allocated_bytes >= 0
+FROM
+    pg_stat_memory_allocation limit 1;
+ ?column? | ?column? | ?column? | ?column? | ?column? | ?column? 
+----------+----------+----------+----------+----------+----------
+ t        | t        | t        | t        | t        | t
+(1 row)
+
 -- End of Stats Test
diff --git a/src/test/regress/sql/stats.sql b/src/test/regress/sql/stats.sql
index fddf5a8277..a01f2545ba 100644
--- a/src/test/regress/sql/stats.sql
+++ b/src/test/regress/sql/stats.sql
@@ -805,4 +805,24 @@ DROP TABLE brin_hot_3;
 
 SET enable_seqscan = on;
 
+-- ensure that allocated_bytes exist for backends
+SELECT
+    allocated_bytes > 0 AS result
+FROM
+    pg_stat_activity ps
+    JOIN pg_stat_memory_allocation pa ON (pa.pid = ps.pid)
+WHERE
+    backend_type IN ('checkpointer', 'background writer', 'walwriter', 'autovacuum launcher');
+
+-- ensure that pg_stat_global_memory_allocation view exists
+SELECT
+    datid > 0, pg_size_bytes(shared_memory_size) >= 0, shared_memory_size_in_huge_pages >= -1, global_dsm_allocated_bytes >= 0
+FROM
+    pg_stat_global_memory_allocation;
+
+-- ensure that pg_stat_memory_allocation view exists
+SELECT
+    pid > 0, allocated_bytes >= 0, aset_allocated_bytes >= 0, dsm_allocated_bytes >= 0, generation_allocated_bytes >= 0, slab_allocated_bytes >= 0
+FROM
+    pg_stat_memory_allocation limit 1;
 -- End of Stats Test
-- 
2.25.1

0002-Add-the-ability-to-limit-the-amount-of-memory-that-c.patchtext/x-patch; charset=UTF-8; name=0002-Add-the-ability-to-limit-the-amount-of-memory-that-c.patchDownload
From f5a7a2ccfd975cb29b47af4fff563947085e1748 Mon Sep 17 00:00:00 2001
From: Reid Thompson <jreidthompson@nc.rr.com>
Date: Sat, 4 Jun 2022 22:23:59 -0400
Subject: [PATCH 2/2] Add the ability to limit the amount of memory that can be
 allocated to backends.

This builds on the work that adds backend memory allocated tracking.

Add GUC variable max_total_backend_memory.

Specifies a limit to the amount of memory (in MB) that may be allocated to
backends in total (i.e. this is not a per user or per backend limit). If unset,
or set to 0 it is disabled. It is intended as a resource to help avoid the OOM
killer on LINUX and manage resources in general. A backend request that would
exhaust max_total_backend_memory memory will be denied with an out of memory
error causing that backend's current query/transaction to fail.  Further
requests will not be allocated until dropping below the limit. Keep this in
mind when setting this value. Due to the dynamic nature of memory allocations,
this limit is not exact. This limit does not affect auxiliary backend
processes. Backend memory allocations are displayed in the
pg_stat_memory_allocation and pg_stat_global_memory_allocation views.
---
 doc/src/sgml/config.sgml                      |  30 ++++
 doc/src/sgml/monitoring.sgml                  |  38 ++++-
 src/backend/catalog/system_views.sql          |   2 +
 src/backend/port/sysv_shmem.c                 |   9 ++
 src/backend/postmaster/postmaster.c           |   5 +
 src/backend/storage/ipc/dsm_impl.c            |  18 +++
 src/backend/storage/lmgr/proc.c               |  45 ++++++
 src/backend/utils/activity/backend_status.c   | 147 ++++++++++++++++++
 src/backend/utils/adt/pgstatfuncs.c           |  16 +-
 src/backend/utils/hash/dynahash.c             |   3 +-
 src/backend/utils/init/miscinit.c             |   8 +
 src/backend/utils/misc/guc_tables.c           |  11 ++
 src/backend/utils/misc/postgresql.conf.sample |   3 +
 src/backend/utils/mmgr/aset.c                 |  33 ++++
 src/backend/utils/mmgr/generation.c           |  16 ++
 src/backend/utils/mmgr/slab.c                 |  15 +-
 src/include/catalog/pg_proc.dat               |   6 +-
 src/include/storage/proc.h                    |   7 +
 src/include/utils/backend_status.h            | 102 +++++++++++-
 src/test/regress/expected/rules.out           |   4 +-
 20 files changed, 498 insertions(+), 20 deletions(-)

diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 5da74b3c40..397661d4b2 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -2180,6 +2180,36 @@ include_dir 'conf.d'
       </listitem>
      </varlistentry>
 
+     <varlistentry id="guc-max-total-backend-memory" xreflabel="max_total_backend_memory">
+      <term><varname>max_total_backend_memory</varname> (<type>integer</type>)
+      <indexterm>
+       <primary><varname>max_total_backend_memory</varname> configuration parameter</primary>
+      </indexterm>
+      </term>
+      <listitem>
+       <para>
+        Specifies a limit to the amount of memory (MB) that may be allocated to
+        backends in total (i.e. this is not a per user or per backend limit).
+        If unset, or set to 0 it is disabled.  At databse startup
+        max_total_backend_memory is reduced by shared_memory_size_mb
+        (includes shared buffers and other memory required for initialization).
+        Each backend process is intialized with a 1MB local allowance which
+        also reduces total_bkend_mem_bytes_available. Keep this in mind when
+        setting this value. A backend request that would exhaust the limit will
+        be denied with an out of memory error causing that backend's current
+        query/transaction to fail. Further requests will not be allocated until
+        dropping below the limit.  This limit does not affect auxiliary backend
+        processes
+        <xref linkend="glossary-auxiliary-proc"/> or the postmaster process.
+        Backend memory allocations (<varname>allocated_bytes</varname>) are
+        displayed in the
+        <link linkend="monitoring-pg-stat-memory-allocation-view"><structname>pg_stat_memory_allocation</structname></link>
+        view.  Due to the dynamic nature of memory allocations, this limit is
+        not exact.
+       </para>
+      </listitem>
+     </varlistentry>
+
      </variablelist>
      </sect2>
 
diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index cfc221fb2e..aa53e0be3e 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -5817,10 +5817,7 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
       </para>
      <para>
       Memory currently allocated to this backend in bytes. This is the balance
-      of bytes allocated and freed by this backend. Dynamic shared memory
-      allocations are included only in the value displayed for the backend that
-      created them, they are not included in the value for backends that are
-      attached to them to avoid double counting.
+      of bytes allocated and freed by this backend.
      </para></entry>
      </row>
 
@@ -5937,6 +5934,39 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
      </para></entry>
      </row>
 
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>max_total_backend_memory_bytes</structfield> <type>bigint</type>
+      </para>
+     <para>
+      Reports the user defined backend maximum allowed shared memory in bytes.
+      0 if disabled or not set. See
+      <xref linkend="guc-max-total-backend-memory"/>.
+     </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>total_bkend_mem_bytes_available</structfield> <type>bigint</type>
+      </para>
+     <para>
+      Tracks max_total_backend_memory (in bytes) available for allocation. At
+      database startup, total_bkend_mem_bytes_available is reduced by the
+      byte equivalent of shared_memory_size_mb. Each backend process is
+      intialized with a 1MB local allowance which also reduces
+      total_bkend_mem_bytes_available. A process's allocation requests reduce
+      it's local allowance. If a process's allocation request exceeds it's
+      remaining allowance, an attempt is made to refill the local allowance
+      from total_bkend_mem_bytes_available. If the refill request fails, then
+      the requesting process will fail with an out of memory error resulting
+      in the cancellation of that process's active query/transaction.  The
+      default refill allocation quantity is 1MB.  If a request is greater than
+      1MB, an attempt will be made to allocate the full amount. If
+      max_total_backend_memory is disabled, this will be -1.
+      <xref linkend="guc-max-total-backend-memory"/>.
+     </para></entry>
+     </row>
+
      <row>
       <entry role="catalog_table_entry"><para role="column_definition">
        <structfield>global_dsm_allocated_bytes</structfield> <type>bigint</type>
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index cc8219c665..0832027727 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -1368,6 +1368,8 @@ SELECT
         S.datid AS datid,
         current_setting('shared_memory_size', true) as shared_memory_size,
         (current_setting('shared_memory_size_in_huge_pages', true))::integer as shared_memory_size_in_huge_pages,
+        pg_size_bytes(current_setting('max_total_backend_memory', true)) as max_total_backend_memory_bytes,
+        S.total_bkend_mem_bytes_available,
         S.global_dsm_allocated_bytes,
         sums.total_aset_allocated_bytes,
         sums.total_dsm_allocated_bytes,
diff --git a/src/backend/port/sysv_shmem.c b/src/backend/port/sysv_shmem.c
index eaba244bc9..463bf2e90f 100644
--- a/src/backend/port/sysv_shmem.c
+++ b/src/backend/port/sysv_shmem.c
@@ -34,6 +34,7 @@
 #include "storage/fd.h"
 #include "storage/ipc.h"
 #include "storage/pg_shmem.h"
+#include "utils/backend_status.h"
 #include "utils/guc_hooks.h"
 #include "utils/pidfile.h"
 
@@ -903,6 +904,14 @@ PGSharedMemoryReAttach(void)
 	dsm_set_control_handle(hdr->dsm_control);
 
 	UsedShmemSegAddr = hdr;		/* probably redundant */
+
+	/*
+	 * Init allocated bytes to avoid double counting parent allocation for
+	 * fork/exec processes. Forked processes perform this action in
+	 * InitPostmasterChild. For EXEC_BACKEND processes we have to wait for
+	 * shared memory to be reattached.
+	 */
+	pgstat_init_allocated_bytes();
 }
 
 /*
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 4c49393fc5..06a773c8bb 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -540,6 +540,7 @@ typedef struct
 #endif
 	char		my_exec_path[MAXPGPATH];
 	char		pkglib_path[MAXPGPATH];
+	int			max_total_bkend_mem;
 } BackendParameters;
 
 static void read_backend_variables(char *id, Port *port);
@@ -6122,6 +6123,8 @@ save_backend_variables(BackendParameters *param, Port *port,
 
 	strlcpy(param->pkglib_path, pkglib_path, MAXPGPATH);
 
+	param->max_total_bkend_mem = max_total_bkend_mem;
+
 	return true;
 }
 
@@ -6352,6 +6355,8 @@ restore_backend_variables(BackendParameters *param, Port *port)
 
 	strlcpy(pkglib_path, param->pkglib_path, MAXPGPATH);
 
+	max_total_bkend_mem = param->max_total_bkend_mem;
+
 	/*
 	 * We need to restore fd.c's counts of externally-opened FDs; to avoid
 	 * confusion, be sure to do this after restoring max_safe_fds.  (Note:
diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c
index f43bad4439..41ffe48aa3 100644
--- a/src/backend/storage/ipc/dsm_impl.c
+++ b/src/backend/storage/ipc/dsm_impl.c
@@ -254,6 +254,16 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 		return true;
 	}
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+	{
+		ereport(elevel,
+				(errcode_for_dynamic_shared_memory(),
+				 errmsg("out of memory for segment \"%s\" - exceeds max_total_backend_memory: %m",
+						name)));
+		return false;
+	}
+
 	/*
 	 * Create new segment or open an existing one for attach.
 	 *
@@ -523,6 +533,10 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 		int			flags = IPCProtection;
 		size_t		segsize;
 
+		/* Do not exceed maximum allowed memory allocation */
+		if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+			return false;
+
 		/*
 		 * Allocate the memory BEFORE acquiring the resource, so that we don't
 		 * leak the resource if memory allocation fails.
@@ -717,6 +731,10 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 		return true;
 	}
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+		return false;
+
 	/* Create new segment or open an existing one for attach. */
 	if (op == DSM_OP_CREATE)
 	{
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index d798c05180..8493ca1dbf 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -51,6 +51,7 @@
 #include "storage/procsignal.h"
 #include "storage/spin.h"
 #include "storage/standby.h"
+#include "utils/guc.h"
 #include "utils/timeout.h"
 #include "utils/timestamp.h"
 
@@ -182,6 +183,50 @@ InitProcGlobal(void)
 	pg_atomic_init_u32(&ProcGlobal->clogGroupFirst, INVALID_PGPROCNO);
 	pg_atomic_init_u64(&ProcGlobal->global_dsm_allocation, 0);
 
+	/* Setup backend memory limiting if configured */
+	if (max_total_bkend_mem > 0)
+	{
+		/*
+		 * Convert max_total_bkend_mem to bytes, account for
+		 * shared_memory_size, and initialize total_bkend_mem_bytes.
+		 */
+		int			result = 0;
+
+		/* Get integer value of shared_memory_size */
+		if (parse_int(GetConfigOption("shared_memory_size", true, false), &result, 0, NULL))
+		{
+			/*
+			 * Error on startup if backend memory limit is less than shared
+			 * memory size. Warn on startup if backend memory available is
+			 * less than arbitrarily picked value of 100MB.
+			 */
+
+			if (max_total_bkend_mem - result <= 0)
+			{
+				ereport(ERROR,
+						errmsg("configured max_total_backend_memory %dMB is <= shared_memory_size %dMB",
+							   max_total_bkend_mem, result),
+						errhint("Disable or increase the configuration parameter \"max_total_backend_memory\"."));
+			}
+			else if (max_total_bkend_mem - result <= 100)
+			{
+				ereport(WARNING,
+						errmsg("max_total_backend_memory %dMB - shared_memory_size %dMB is <= 100MB",
+							   max_total_bkend_mem, result),
+						errhint("Consider increasing the configuration parameter \"max_total_backend_memory\"."));
+			}
+
+			/*
+			 * Account for shared memory size and initialize
+			 * total_bkend_mem_bytes.
+			 */
+			pg_atomic_init_u64(&ProcGlobal->total_bkend_mem_bytes,
+							   (uint64) max_total_bkend_mem * 1024 * 1024 - (uint64) result * 1024 * 1024);
+		}
+		else
+			ereport(ERROR, errmsg("max_total_backend_memory initialization is unable to parse shared_memory_size"));
+	}
+
 	/*
 	 * Create and initialize all the PGPROC structures we'll need.  There are
 	 * five separate consumers: (1) normal backends, (2) autovacuum workers
diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c
index 50b36ba5f7..cad50b2a06 100644
--- a/src/backend/utils/activity/backend_status.c
+++ b/src/backend/utils/activity/backend_status.c
@@ -45,6 +45,12 @@
 bool		pgstat_track_activities = false;
 int			pgstat_track_activity_query_size = 1024;
 
+/*
+ * Max backend memory allocation allowed (MB). 0 = disabled.
+ * Centralized bucket ProcGlobal->max_total_bkend_mem is initialized
+ * as a byte representation of this value in InitProcGlobal().
+ */
+int			max_total_bkend_mem = 0;
 
 /* exposed so that backend_progress.c can access it */
 PgBackendStatus *MyBEEntry = NULL;
@@ -68,6 +74,31 @@ uint64	   *my_generation_allocated_bytes = &local_my_generation_allocated_bytes;
 uint64		local_my_slab_allocated_bytes = 0;
 uint64	   *my_slab_allocated_bytes = &local_my_slab_allocated_bytes;
 
+/*
+ * Define initial allocation allowance for a backend.
+ *
+ * NOTE: initial_allocation_allowance && allocation_allowance_refill_qty
+ * may be candidates for future GUC variables. Arbitrary 1MB selected initially.
+ */
+uint64		initial_allocation_allowance = 1024 * 1024;
+uint64		allocation_allowance_refill_qty = 1024 * 1024;
+
+/*
+ * Local counter to manage shared memory allocations. At backend startup, set to
+ * initial_allocation_allowance via pgstat_init_allocated_bytes(). Decrease as
+ * memory is malloc'd. When exhausted, atomically refill if available from
+ * ProcGlobal->max_total_bkend_mem via exceeds_max_total_bkend_mem().
+ */
+uint64		allocation_allowance = 0;
+
+/*
+ * Local counter of free'd shared memory. Return to global
+ * max_total_bkend_mem when return threshold is met. Arbitrary 1MB bytes
+ * selected initially.
+ */
+uint64		allocation_return = 0;
+uint64		allocation_return_threshold = 1024 * 1024;
+
 static PgBackendStatus *BackendStatusArray = NULL;
 static char *BackendAppnameBuffer = NULL;
 static char *BackendClientHostnameBuffer = NULL;
@@ -1272,6 +1303,8 @@ pgstat_set_allocated_bytes_storage(uint64 *allocated_bytes,
 
 	my_slab_allocated_bytes = slab_allocated_bytes;
 	*slab_allocated_bytes = local_my_slab_allocated_bytes;
+
+	return;
 }
 
 /*
@@ -1295,6 +1328,23 @@ pgstat_reset_allocated_bytes_storage(void)
 								*my_dsm_allocated_bytes);
 	}
 
+	/*
+	 * When limiting maximum backend memory, return this backend's memory
+	 * allocations to global.
+	 */
+	if (max_total_bkend_mem)
+	{
+		volatile PROC_HDR *procglobal = ProcGlobal;
+
+		pg_atomic_add_fetch_u64(&procglobal->total_bkend_mem_bytes,
+								*my_allocated_bytes + allocation_allowance +
+								allocation_return);
+
+		/* Reset memory allocation variables */
+		allocation_allowance = 0;
+		allocation_return = 0;
+	}
+
 	/* Reset memory allocation variables */
 	*my_allocated_bytes = local_my_allocated_bytes = 0;
 	*my_aset_allocated_bytes = local_my_aset_allocated_bytes = 0;
@@ -1308,4 +1358,101 @@ pgstat_reset_allocated_bytes_storage(void)
 	my_dsm_allocated_bytes = &local_my_dsm_allocated_bytes;
 	my_generation_allocated_bytes = &local_my_generation_allocated_bytes;
 	my_slab_allocated_bytes = &local_my_slab_allocated_bytes;
+
+	return;
+}
+
+/*
+ * Determine if allocation request will exceed max backend memory allowed.
+ * Do not apply to auxiliary processes.
+ * Refill allocation request bucket when needed/possible.
+ */
+bool
+exceeds_max_total_bkend_mem(uint64 allocation_request)
+{
+	bool		result = false;
+
+	/*
+	 * When limiting maximum backend memory, attempt to refill allocation
+	 * request bucket if needed.
+	 */
+	if (max_total_bkend_mem && allocation_request > allocation_allowance &&
+		ProcGlobal != NULL)
+	{
+		volatile PROC_HDR *procglobal = ProcGlobal;
+		uint64		available_max_total_bkend_mem = 0;
+		bool		sts = false;
+
+		/*
+		 * If allocation request is larger than memory refill quantity then
+		 * attempt to increase allocation allowance with requested amount,
+		 * otherwise fall through. If this refill fails we do not have enough
+		 * memory to meet the request.
+		 */
+		if (allocation_request >= allocation_allowance_refill_qty)
+		{
+			while ((available_max_total_bkend_mem = pg_atomic_read_u64(&procglobal->total_bkend_mem_bytes)) >= allocation_request)
+			{
+				if ((result = pg_atomic_compare_exchange_u64(&procglobal->total_bkend_mem_bytes,
+															 &available_max_total_bkend_mem,
+															 available_max_total_bkend_mem - allocation_request)))
+				{
+					allocation_allowance = allocation_allowance + allocation_request;
+					break;
+				}
+			}
+
+			/*
+			 * Exclude auxiliary and Postmaster processes from the check.
+			 * Return false. While we want to exclude them from the check, we
+			 * do not want to exclude them from the above allocation handling.
+			 */
+			if (MyAuxProcType != NotAnAuxProcess || MyProcPid == PostmasterPid)
+				return false;
+
+			/*
+			 * If the atomic exchange fails (result == false), we do not have
+			 * enough reserve memory to meet the request. Negate result to
+			 * return the proper value.
+			 */
+
+			return !result;
+		}
+
+		/*
+		 * Attempt to increase allocation allowance by memory refill quantity.
+		 * If available memory is/becomes less than memory refill quantity,
+		 * fall through to attempt to allocate remaining available memory.
+		 */
+		while ((available_max_total_bkend_mem = pg_atomic_read_u64(&procglobal->total_bkend_mem_bytes)) >= allocation_allowance_refill_qty)
+		{
+			if ((sts = pg_atomic_compare_exchange_u64(&procglobal->total_bkend_mem_bytes,
+													  &available_max_total_bkend_mem,
+													  available_max_total_bkend_mem - allocation_allowance_refill_qty)))
+			{
+				allocation_allowance = allocation_allowance + allocation_allowance_refill_qty;
+				break;
+			}
+		}
+
+		/* Do not attempt to increase allocation if available memory is below
+		 * allocation_allowance_refill_qty .
+		 */
+
+		/*
+		 * If refill is not successful, we return true, memory limit exceeded
+		 */
+		if (!sts)
+			result = true;
+	}
+
+	/*
+	 * Exclude auxiliary and postmaster processes from the check. Return false.
+	 * While we want to exclude them from the check, we do not want to exclude
+	 * them from the above allocation handling.
+	 */
+	if (MyAuxProcType != NotAnAuxProcess || MyProcPid == PostmasterPid)
+		result = false;
+
+	return result;
 }
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 35f2d2bffe..4bcdfc91bf 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -2123,7 +2123,7 @@ pg_stat_get_memory_allocation(PG_FUNCTION_ARGS)
 Datum
 pg_stat_get_global_memory_allocation(PG_FUNCTION_ARGS)
 {
-#define PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS	2
+#define PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS	3
 	TupleDesc	tupdesc;
 	Datum		values[PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS] = {0};
 	bool		nulls[PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS] = {0};
@@ -2133,15 +2133,23 @@ pg_stat_get_global_memory_allocation(PG_FUNCTION_ARGS)
 	tupdesc = CreateTemplateTupleDesc(PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 1, "datid",
 					   OIDOID, -1, 0);
-	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "global_dsm_allocated_bytes",
+	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "total_bkend_mem_bytes_available",
+					   INT8OID, -1, 0);
+	TupleDescInitEntry(tupdesc, (AttrNumber) 3, "global_dsm_allocated_bytes",
 					   INT8OID, -1, 0);
 	BlessTupleDesc(tupdesc);
 
 	/* datid */
 	values[0] = ObjectIdGetDatum(MyDatabaseId);
 
-	/* get global_dsm_allocated_bytes */
-	values[1] = Int64GetDatum(pg_atomic_read_u64(&procglobal->global_dsm_allocation));
+	/* Get total_bkend_mem_bytes - return -1 if disabled */
+	if (max_total_bkend_mem == 0)
+		values[1] = Int64GetDatum(-1);
+	else
+		values[1] = Int64GetDatum(pg_atomic_read_u64(&procglobal->total_bkend_mem_bytes));
+
+	/* Get global_dsm_allocated_bytes */
+	values[2] = Int64GetDatum(pg_atomic_read_u64(&procglobal->global_dsm_allocation));
 
 	/* Returns the record as Datum */
 	PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls)));
diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c
index 012d4a0b1f..cd68e5265a 100644
--- a/src/backend/utils/hash/dynahash.c
+++ b/src/backend/utils/hash/dynahash.c
@@ -104,7 +104,6 @@
 #include "utils/dynahash.h"
 #include "utils/memutils.h"
 
-
 /*
  * Constants
  *
@@ -359,7 +358,6 @@ hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
 	Assert(flags & HASH_ELEM);
 	Assert(info->keysize > 0);
 	Assert(info->entrysize >= info->keysize);
-
 	/*
 	 * For shared hash tables, we have a local hash header (HTAB struct) that
 	 * we allocate in TopMemoryContext; all else is in shared memory.
@@ -377,6 +375,7 @@ hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
 	}
 	else
 	{
+		/* Set up to allocate the hash header */
 		/* Create the hash table's private memory context */
 		if (flags & HASH_CONTEXT)
 			CurrentDynaHashCxt = info->hcxt;
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index 7b8eeb7dbb..a7df801f77 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -172,8 +172,16 @@ InitPostmasterChild(void)
 				 errmsg_internal("could not set postmaster death monitoring pipe to FD_CLOEXEC mode: %m")));
 #endif
 
+	/*
+	 * Init pgstat allocated bytes counters here for forked backends.
+	 * Fork/exec backends have not yet reattached to shared memory at this
+	 * point. They will init pgstat allocated bytes counters in
+	 * PGSharedMemoryReAttach.
+	 */
+#ifndef EXEC_BACKEND
 	/* Init allocated bytes to avoid double counting parent allocation */
 	pgstat_init_allocated_bytes();
+#endif
 }
 
 /*
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index 68aecad66f..eacd1a6043 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -3510,6 +3510,17 @@ struct config_int ConfigureNamesInt[] =
 		NULL, NULL, NULL
 	},
 
+	{
+		{"max_total_backend_memory", PGC_SU_BACKEND, RESOURCES_MEM,
+			gettext_noop("Restrict total backend memory allocations to this max."),
+			gettext_noop("0 turns this feature off."),
+			GUC_UNIT_MB
+		},
+		&max_total_bkend_mem,
+		0, 0, INT_MAX,
+		NULL, NULL, NULL
+	},
+
 	/* End-of-list marker */
 	{
 		{NULL, 0, 0, NULL, NULL}, NULL, 0, 0, 0, NULL, NULL, NULL
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index b090ec5245..5466234d64 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -161,6 +161,9 @@
 #vacuum_buffer_usage_limit = 256kB	# size of vacuum and analyze buffer access strategy ring.
 					# 0 to disable vacuum buffer access strategy
 					# range 128kB to 16GB
+#max_total_backend_memory = 0MB		# Restrict total backend memory allocations
+									# to this max (in MB). 0 turns this feature
+									# off.
 
 # - Disk -
 
diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index 4146831d75..a3891a607b 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -432,6 +432,18 @@ AllocSetContextCreateInternal(MemoryContext parent,
 	else
 		firstBlockSize = Max(firstBlockSize, initBlockSize);
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (exceeds_max_total_bkend_mem(firstBlockSize))
+	{
+		if (TopMemoryContext)
+			MemoryContextStats(TopMemoryContext);
+		ereport(ERROR,
+				(errcode(ERRCODE_OUT_OF_MEMORY),
+				 errmsg("out of memory - exceeds max_total_backend_memory"),
+				 errdetail("Failed while creating memory context \"%s\".",
+						   name)));
+	}
+
 	/*
 	 * Allocate the initial block.  Unlike other aset.c blocks, it starts with
 	 * the context header and its block header follows that.
@@ -733,6 +745,11 @@ AllocSetAlloc(MemoryContext context, Size size)
 #endif
 
 		blksize = chunk_size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
+
+		/* Do not exceed maximum allowed memory allocation */
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		block = (AllocBlock) malloc(blksize);
 		if (block == NULL)
 			return NULL;
@@ -933,6 +950,10 @@ AllocSetAlloc(MemoryContext context, Size size)
 		while (blksize < required_size)
 			blksize <<= 1;
 
+		/* Do not exceed maximum allowed memory allocation */
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		/* Try to allocate it */
 		block = (AllocBlock) malloc(blksize);
 
@@ -1171,6 +1192,18 @@ AllocSetRealloc(void *pointer, Size size)
 		blksize = chksize + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
 		oldblksize = block->endptr - ((char *) block);
 
+		/*
+		 * Do not exceed maximum allowed memory allocation. NOTE: checking for
+		 * the full size here rather than just the amount of increased
+		 * allocation to prevent a potential underflow of *my_allocation
+		 * allowance in cases where blksize - oldblksize does not trigger a
+		 * refill but blksize is greater than *my_allocation_allowance.
+		 * Underflow would occur with the call below to
+		 * pgstat_report_allocated_bytes_increase()
+		 */
+		if (blksize > oldblksize && exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		block = (AllocBlock) realloc(block, blksize);
 		if (block == NULL)
 		{
diff --git a/src/backend/utils/mmgr/generation.c b/src/backend/utils/mmgr/generation.c
index 502f877855..b4c9b40766 100644
--- a/src/backend/utils/mmgr/generation.c
+++ b/src/backend/utils/mmgr/generation.c
@@ -193,6 +193,16 @@ GenerationContextCreate(MemoryContext parent,
 	else
 		allocSize = Max(allocSize, initBlockSize);
 
+	if (exceeds_max_total_bkend_mem(allocSize))
+	{
+		MemoryContextStats(TopMemoryContext);
+		ereport(ERROR,
+				(errcode(ERRCODE_OUT_OF_MEMORY),
+				 errmsg("out of memory - exceeds max_total_backend_memory"),
+				 errdetail("Failed while creating memory context \"%s\".",
+						   name)));
+	}
+
 	/*
 	 * Allocate the initial block.  Unlike other generation.c blocks, it
 	 * starts with the context header and its block header follows that.
@@ -372,6 +382,9 @@ GenerationAlloc(MemoryContext context, Size size)
 	{
 		Size		blksize = required_size + Generation_BLOCKHDRSZ;
 
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		block = (GenerationBlock *) malloc(blksize);
 		if (block == NULL)
 			return NULL;
@@ -475,6 +488,9 @@ GenerationAlloc(MemoryContext context, Size size)
 			if (blksize < required_size)
 				blksize = pg_nextpower2_size_t(required_size);
 
+			if (exceeds_max_total_bkend_mem(blksize))
+				return NULL;
+
 			block = (GenerationBlock *) malloc(blksize);
 
 			if (block == NULL)
diff --git a/src/backend/utils/mmgr/slab.c b/src/backend/utils/mmgr/slab.c
index 913787dba8..00a10f3c11 100644
--- a/src/backend/utils/mmgr/slab.c
+++ b/src/backend/utils/mmgr/slab.c
@@ -356,7 +356,16 @@ SlabContextCreate(MemoryContext parent,
 		elog(ERROR, "block size %zu for slab is too small for %zu-byte chunks",
 			 blockSize, chunkSize);
 
-
+	/* Do not exceed maximum allowed memory allocation */
+	if (exceeds_max_total_bkend_mem(Slab_CONTEXT_HDRSZ(chunksPerBlock)))
+	{
+		MemoryContextStats(TopMemoryContext);
+		ereport(ERROR,
+				(errcode(ERRCODE_OUT_OF_MEMORY),
+				 errmsg("out of memory - exceeds max_total_backend_memory"),
+				 errdetail("Failed while creating memory context \"%s\".",
+						   name)));
+	}
 
 	slab = (SlabContext *) malloc(Slab_CONTEXT_HDRSZ(chunksPerBlock));
 	if (slab == NULL)
@@ -559,6 +568,10 @@ SlabAlloc(MemoryContext context, Size size)
 		}
 		else
 		{
+			/* Do not exceed maximum allowed memory allocation */
+			if (exceeds_max_total_bkend_mem(slab->blockSize))
+				return NULL;
+
 			block = (SlabBlock *) malloc(slab->blockSize);
 
 			if (unlikely(block == NULL))
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index b095740f8a..4bef1ac428 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -5421,9 +5421,9 @@
   descr => 'statistics: global memory allocation information',
   proname => 'pg_stat_get_global_memory_allocation', proisstrict => 'f',
   provolatile => 's', proparallel => 'r', prorettype => 'record',
-  proargtypes => '', proallargtypes => '{oid,int8}',
-  proargmodes => '{o,o}',
-  proargnames => '{datid,global_dsm_allocated_bytes}',
+  proargtypes => '', proallargtypes => '{oid,int8,int8}',
+  proargmodes => '{o,o,o}',
+  proargnames => '{datid,total_bkend_mem_bytes_available,global_dsm_allocated_bytes}',
   prosrc =>'pg_stat_get_global_memory_allocation' },
 { oid => '2022',
   descr => 'statistics: information about currently active backends',
diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h
index e6be67de2a..f62ea132ff 100644
--- a/src/include/storage/proc.h
+++ b/src/include/storage/proc.h
@@ -406,6 +406,13 @@ typedef struct PROC_HDR
 	int			startupBufferPinWaitBufId;
 	/* Global dsm allocations */
 	pg_atomic_uint64 global_dsm_allocation;
+
+	/*
+	 * Max backend memory allocation tracker. Used/Initialized when
+	 * max_total_bkend_mem > 0 as max_total_bkend_mem (MB) converted to bytes.
+	 * Decreases/increases with free/malloc of backend memory.
+	 */
+	pg_atomic_uint64 total_bkend_mem_bytes;
 } PROC_HDR;
 
 extern PGDLLIMPORT PROC_HDR *ProcGlobal;
diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h
index 9b75fc5223..068b96dd09 100644
--- a/src/include/utils/backend_status.h
+++ b/src/include/utils/backend_status.h
@@ -15,6 +15,7 @@
 #include "libpq/pqcomm.h"
 #include "miscadmin.h"			/* for BackendType */
 #include "storage/backendid.h"
+#include "storage/proc.h"
 #include "utils/backend_progress.h"
 
 
@@ -305,6 +306,7 @@ typedef struct LocalPgBackendStatus
  */
 extern PGDLLIMPORT bool pgstat_track_activities;
 extern PGDLLIMPORT int pgstat_track_activity_query_size;
+extern PGDLLIMPORT int max_total_bkend_mem;
 
 
 /* ----------
@@ -317,6 +319,10 @@ extern PGDLLIMPORT uint64 *my_aset_allocated_bytes;
 extern PGDLLIMPORT uint64 *my_dsm_allocated_bytes;
 extern PGDLLIMPORT uint64 *my_generation_allocated_bytes;
 extern PGDLLIMPORT uint64 *my_slab_allocated_bytes;
+extern PGDLLIMPORT uint64 allocation_allowance;
+extern PGDLLIMPORT uint64 initial_allocation_allowance;
+extern PGDLLIMPORT uint64 allocation_return;
+extern PGDLLIMPORT uint64 allocation_return_threshold;
 
 
 /* ----------
@@ -364,6 +370,7 @@ extern int	pgstat_fetch_stat_numbackends(void);
 extern PgBackendStatus *pgstat_fetch_stat_beentry(BackendId beid);
 extern LocalPgBackendStatus *pgstat_fetch_stat_local_beentry(int beid);
 extern char *pgstat_clip_activity(const char *raw_activity);
+extern bool exceeds_max_total_bkend_mem(uint64 allocation_request);
 
 /* ----------
  * pgstat_report_allocated_bytes_decrease() -
@@ -379,7 +386,7 @@ pgstat_report_allocated_bytes_decrease(int64 proc_allocated_bytes,
 {
 	uint64		temp;
 
-	/* Avoid allocated_bytes unsigned integer overflow on decrease */
+	/* Sanity check: my allocated bytes should never drop below zero */
 	if (pg_sub_u64_overflow(*my_allocated_bytes, proc_allocated_bytes, &temp))
 	{
 		/* On overflow, set allocated bytes and allocator type bytes to zero */
@@ -388,13 +395,35 @@ pgstat_report_allocated_bytes_decrease(int64 proc_allocated_bytes,
 		*my_dsm_allocated_bytes = 0;
 		*my_generation_allocated_bytes = 0;
 		*my_slab_allocated_bytes = 0;
+
+		/* Add freed memory to allocation return counter. */
+		allocation_return += proc_allocated_bytes;
+
+		/*
+		 * Return freed memory to the global counter if return threshold is
+		 * met.
+		 */
+		if (max_total_bkend_mem && allocation_return >= allocation_return_threshold)
+		{
+			if (ProcGlobal)
+			{
+				volatile PROC_HDR *procglobal = ProcGlobal;
+
+				/* Add to global tracker */
+				pg_atomic_add_fetch_u64(&procglobal->total_bkend_mem_bytes,
+										allocation_return);
+
+				/* Restart the count */
+				allocation_return = 0;
+			}
+		}
 	}
 	else
 	{
-		/* decrease allocation */
-		*my_allocated_bytes -= proc_allocated_bytes;
+		/* Add freed memory to allocation return counter */
+		allocation_return += proc_allocated_bytes;
 
-		/* Decrease allocator type allocated bytes. */
+		/* Decrease allocator type allocated bytes */
 		switch (pg_allocator_type)
 		{
 			case PG_ALLOC_ASET:
@@ -416,6 +445,30 @@ pgstat_report_allocated_bytes_decrease(int64 proc_allocated_bytes,
 				*my_slab_allocated_bytes -= proc_allocated_bytes;
 				break;
 		}
+
+		/* decrease allocation */
+		*my_allocated_bytes = *my_aset_allocated_bytes +
+			*my_dsm_allocated_bytes + *my_generation_allocated_bytes +
+			*my_slab_allocated_bytes;
+
+		/*
+		 * Return freed memory to the global counter if return threshold is
+		 * met.
+		 */
+		if (max_total_bkend_mem && allocation_return >= allocation_return_threshold)
+		{
+			if (ProcGlobal)
+			{
+				volatile PROC_HDR *procglobal = ProcGlobal;
+
+				/* Add to global tracker */
+				pg_atomic_add_fetch_u64(&procglobal->total_bkend_mem_bytes,
+										allocation_return);
+
+				/* Restart the count */
+				allocation_return = 0;
+			}
+		}
 	}
 
 	return;
@@ -433,7 +486,13 @@ static inline void
 pgstat_report_allocated_bytes_increase(int64 proc_allocated_bytes,
 									   int pg_allocator_type)
 {
-	*my_allocated_bytes += proc_allocated_bytes;
+	uint64		temp;
+
+	/* Sanity check: my allocated bytes should never drop below zero */
+	if (pg_sub_u64_overflow(allocation_allowance, proc_allocated_bytes, &temp))
+		allocation_allowance = 0;
+	else
+		allocation_allowance -= proc_allocated_bytes;
 
 	/* Increase allocator type allocated bytes */
 	switch (pg_allocator_type)
@@ -458,6 +517,9 @@ pgstat_report_allocated_bytes_increase(int64 proc_allocated_bytes,
 			break;
 	}
 
+	*my_allocated_bytes = *my_aset_allocated_bytes + *my_dsm_allocated_bytes +
+		*my_generation_allocated_bytes + *my_slab_allocated_bytes;
+
 	return;
 }
 
@@ -477,6 +539,36 @@ pgstat_init_allocated_bytes(void)
 	*my_generation_allocated_bytes = 0;
 	*my_slab_allocated_bytes = 0;
 
+	/* If we're limiting backend memory */
+	if (max_total_bkend_mem)
+	{
+		volatile PROC_HDR *procglobal = ProcGlobal;
+		uint64		available_max_total_bkend_mem = 0;
+
+		allocation_return = 0;
+		allocation_allowance = 0;
+
+		/* Account for the initial allocation allowance */
+		while ((available_max_total_bkend_mem = pg_atomic_read_u64(&procglobal->total_bkend_mem_bytes)) >= initial_allocation_allowance)
+		{
+			/*
+			 * On success populate allocation_allowance. Failure here will
+			 * result in the backend's first invocation of
+			 * exceeds_max_total_bkend_mem allocating requested, default, or
+			 * available memory or result in an out of memory error.
+			 */
+			if (pg_atomic_compare_exchange_u64(&procglobal->total_bkend_mem_bytes,
+											   &available_max_total_bkend_mem,
+											   available_max_total_bkend_mem -
+											   initial_allocation_allowance))
+			{
+				allocation_allowance = initial_allocation_allowance;
+
+				break;
+			}
+		}
+	}
+
 	return;
 }
 
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index ff76aa99a2..4f96cf4436 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1883,13 +1883,15 @@ pg_stat_global_memory_allocation| WITH sums AS (
  SELECT s.datid,
     current_setting('shared_memory_size'::text, true) AS shared_memory_size,
     (current_setting('shared_memory_size_in_huge_pages'::text, true))::integer AS shared_memory_size_in_huge_pages,
+    pg_size_bytes(current_setting('max_total_backend_memory'::text, true)) AS max_total_backend_memory_bytes,
+    s.total_bkend_mem_bytes_available,
     s.global_dsm_allocated_bytes,
     sums.total_aset_allocated_bytes,
     sums.total_dsm_allocated_bytes,
     sums.total_generation_allocated_bytes,
     sums.total_slab_allocated_bytes
    FROM sums,
-    (pg_stat_get_global_memory_allocation() s(datid, global_dsm_allocated_bytes)
+    (pg_stat_get_global_memory_allocation() s(datid, total_bkend_mem_bytes_available, global_dsm_allocated_bytes)
      LEFT JOIN pg_database d ON ((s.datid = d.oid)));
 pg_stat_gssapi| SELECT pid,
     gss_auth AS gss_authenticated,
-- 
2.25.1

#39Noname
reid.thompson@crunchydata.com
In reply to: Noname (#37)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On Mon, 2023-05-22 at 08:42 -0400, reid.thompson@crunchydata.com wrote:

More followup to the above.

I experimented on my system regarding
"The simple query select * from generate_series(0, 10000000) shows roughly 18.9 % degradation on my test server."

My laptop:
32GB ram
11th Gen Intel(R) Core(TM) i7-11850H 8 cores/16 threads @ 2.50GHz (Max Turbo Frequency. 4.80 GHz ; Cache. 24 MB)
SSD -> Model: KXG60ZNV1T02 NVMe KIOXIA 1024GB (nvme)

Hi

Ran through a few more tests on my system varying the
initial_allocation_allowance and allocation_allowance_refill_qty from the
current 1MB to 2, 4, 6, 8, 10 mb. Also realized that in my last tests/email I
had posted percent difference rather than percent change. Turns out for the
numbers that were being compared they're essentially the same, but I'm
providing both for this set of tests. Ten runs for each comparison. Compared
dev-max-memory set, dev-max-memory unset, master, and pg-stat-activity-backend-memory-allocated
against master at each allocation value;

Again, the test invokes
psql -At -d postgres $connstr -P pager=off -c 'select * from generate_series(0, 10000000)'
100 times on each of the 2 instances and calculates the AVG time and SD
for the 100 runs. It then uses the AVG from each instance to calculate
the percentage difference/change.

These tests contain one code change not yet pushed to pgsql-hackers. In
AllocSetReset() do not enter pgstat_report_allocated_bytes_decrease if no
memory has been freed.

Will format and post some pgbench test result in a separate email.

Percent difference:

───────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
│ Results: difference-dev-max-memory-set VS master
───────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ 1MB allocation 2MB allocation 4MB allocation 6MB allocation 8MB allocation 10MB allocation
2 │ 4.2263% difference 3.03961% difference 0.0585808% difference 2.92451% difference 3.34694% difference 2.67771% difference
3 │ 3.55709% difference 3.92339% difference 2.29144% difference 3.2156% difference 2.06153% difference 2.86217% difference
4 │ 2.04389% difference 2.91866% difference 3.73463% difference 2.86161% difference 3.60992% difference 3.07293% difference
5 │ 3.1306% difference 3.64773% difference 2.38063% difference 1.84845% difference 4.87375% difference 4.16953% difference
6 │ 3.12556% difference 3.34537% difference 2.99052% difference 2.60538% difference 2.14825% difference 1.95454% difference
7 │ 2.20615% difference 2.12861% difference 2.85282% difference 2.43336% difference 2.31389% difference 3.21563% difference
8 │ 1.9954% difference 3.61371% difference 3.35543% difference 3.49821% difference 3.41526% difference 8.25753% difference
9 │ 2.46845% difference 2.57784% difference 3.13067% difference 3.67681% difference 2.89139% difference 3.6067% difference
10 │ 3.60092% difference 2.16164% difference 3.9976% difference 2.6144% difference 4.27892% difference 2.68998% difference
11 │ 2.55454% difference 2.39073% difference 3.09631% difference 3.24292% difference 1.9107% difference 1.76182% difference
12 │
13 │ 28.9089/10 29.74729/10 27.888631/10 28.92125/10 30.85055/10 34.26854/10
14 │ 2.89089 2.974729 2.7888631 2.892125 3.085055 3.426854
───────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
───────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
│ Results: difference-dev-max-memory-unset VS master
───────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ 1MB allocation 2MB allocation 4MB allocation 6MB allocation 8MB allocation 10MB allocation
2 │ 3.96616% difference 3.05528% difference 0.563267% difference 1.12075% difference 3.52398% difference 3.25641% difference
3 │ 3.11387% difference 3.12499% difference 1.1133% difference 4.86997% difference 2.11481% difference 1.11668% difference
4 │ 3.14506% difference 2.06193% difference 3.36034% difference 2.80644% difference 2.37822% difference 3.07669% difference
5 │ 2.81052% difference 3.18499% difference 2.70705% difference 2.27847% difference 2.78506% difference 3.02919% difference
6 │ 2.9765% difference 3.44165% difference 2.62039% difference 4.61596% difference 2.27937% difference 3.89676% difference
7 │ 3.201% difference 1.35838% difference 2.40578% difference 3.95695% difference 2.25983% difference 4.17585% difference
8 │ 5.35191% difference 3.96434% difference 4.32891% difference 3.62715% difference 2.17503% difference 0.620856% difference
9 │ 3.44241% difference 2.9754% difference 3.03765% difference 1.48104% difference 1.53958% difference 3.14598% difference
10 │ 10.1155% difference 4.21062% difference 1.64416% difference 1.51458% difference 2.92131% difference 2.95603% difference
11 │ 3.11011% difference 4.31318% difference 2.01991% difference 4.71192% difference 2.37039% difference 4.25241% difference
12 │
13 │ 41.23304/10 31.69076/10 23.800757/10 30.98323/10 24.34758/10 29.526856/10
14 │ 4.123304 3.169076 2.3800757 3.098323 2.434758 2.9526856
───────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
───────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
│ Results: difference-master VS master
───────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ 1MB allocation 2MB allocation 4MB allocation 6MB allocation 8MB allocation 10MB allocation
2 │ 0.0734782% difference 0.0955457% difference 0.0521627% difference 2.32643% difference 0.286493% difference 1.26977% difference
3 │ 0.547862% difference 1.19087% difference 0.276915% difference 0.334332% difference 0.260545% difference 0.108956% difference
4 │ 0.0714666% difference 0.931605% difference 0.753996% difference 0.457174% difference 0.215904% difference 1.43979% difference
5 │ 0.269737% difference 0.848613% difference 0.222909% difference 0.315927% difference 0.290408% difference 0.248591% difference
6 │ 1.04231% difference 0.367444% difference 0.699571% difference 0.29266% difference 0.844548% difference 0.273776% difference
7 │ 0.0584984% difference 0.15094% difference 0.0721539% difference 0.594991% difference 1.80223% difference 0.500557% difference
8 │ 0.355129% difference 1.19517% difference 0.201835% difference 1.2351% difference 0.266004% difference 0.80893% difference
9 │ 0.0811794% difference 1.16184% difference 1.01913% difference 0.149087% difference 0.402931% difference 0.125788% difference
10 │ 0.950973% difference 0.154471% difference 0.42623% difference 0.874816% difference 0.157934% difference 0.225433% difference
11 │ 0.501783% difference 0.308357% difference 0.279147% difference 0.122458% difference 0.538141% difference 0.865846% difference
12 │
13 │ 3.952417/10 6.404856/10 4.00405/10 6.702975/10 5.065138/10 5.867437/10
14 │ 0.3952417 0.6404856 0.400405 0.6702975 0.5065138 0.5867437
───────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
───────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
│ Results: difference-pg-stat-activity-backend-memory-allocated VS master
───────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ 1MB allocation 2MB allocation 4MB allocation 6MB allocation 8MB allocation 10MB allocation
2 │ 2.04788% difference 0.50705% difference 0.504772% difference 0.136316% difference 0.590087% difference 1.33931% difference
3 │ 1.21173% difference 0.3309% difference 0.482685% difference 1.67956% difference 0.175478% difference 0.969286% difference
4 │ 0.0680972% difference 0.295211% difference 0.867547% difference 1.12959% difference 0.193756% difference 0.714178% difference
5 │ 0.91525% difference 1.42408% difference 1.49059% difference 0.641652% difference 1.34265% difference 0.378394% difference
6 │ 2.46448% difference 2.67081% difference 0.63824% difference 0.650301% difference 0.481858% difference 1.65711% difference
7 │ 1.31021% difference 0.0548831% difference 1.23217% difference 2.11691% difference 0.31629% difference 3.85858% difference
8 │ 1.61458% difference 0.46042% difference 0.724742% difference 0.172952% difference 1.33157% difference 0.556898% difference
9 │ 1.65063% difference 0.59815% difference 1.42473% difference 0.725576% difference 0.229639% difference 0.875489% difference
10 │ 1.78567% difference 1.45652% difference 0.6317% difference 1.99146% difference 0.999521% difference 1.85291% difference
11 │ 0.391318% difference 1.13216% difference 0.138291% difference 0.531084% difference 0.680197% difference 1.63162% difference
12 │
13 │ 13.459845/10 8.930184/10 8.135467/10 9.775401/10 6.341046/10 13.83377/10
14 │ 1.3459845 0.8930184 0.8135467 0.9775401 0.6341046 1.3833775
───────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Percent change:

───────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
│ Results: change-dev-max-memory-set VS master
───────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ 1MB allocation 2MB allocation 4MB allocation 6MB allocation 8MB allocation 10MB allocation
2 │ 4.13884% change 2.99411% change 0.0585636% change 2.88237% change 3.29185% change 2.64233% change
3 │ 3.49493% change 3.84791% change 2.26549% change 3.16472% change 2.0405% change 2.82179% change
4 │ 2.02322% change 2.87668% change 3.66617% change 2.82124% change 3.54592% change 3.02643% change
5 │ 3.08235% change 3.5824% change 2.35263% change 1.83153% change 4.75781% change 4.08438% change
6 │ 3.07746% change 3.29033% change 2.94646% change 2.57188% change 2.12542% change 1.93562% change
7 │ 2.18208% change 2.10619% change 2.8127% change 2.40411% change 2.28743% change 3.16474% change
8 │ 1.97569% change 3.54957% change 3.30007% change 3.43808% change 3.35792% change 7.93011% change
9 │ 2.43836% change 2.54504% change 3.08242% change 3.61044% change 2.85019% change 3.54281% change
10 │ 3.53724% change 2.13852% change 3.91926% change 2.58067% change 4.18929% change 2.65428% change
11 │ 2.52233% change 2.36249% change 3.0491% change 3.19118% change 1.89262% change 1.74644% change
12 │
13 │ 28.4725/10 29.29324/10 27.452864/10 28.49622/10 30.33895/10 33.54893/10
14 │ 2.84725 2.929324 2.7452864 2.849622 3.033895 3.354893
───────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
───────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
│ Results: change-dev-max-memory-unset VS master
───────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ 1MB allocation 2MB allocation 4MB allocation 6MB allocation 8MB allocation 10MB allocation
2 │ 3.88903% change 3.00931% change 0.564858% change 1.11451% change 3.46296% change 3.20424% change
3 │ 3.06613% change 3.07691% change 1.10714% change 4.75421% change 2.09268% change 1.11048% change
4 │ 3.09637% change 2.04089% change 3.30482% change 2.7676% change 2.35028% change 3.03008% change
5 │ 2.77157% change 3.13506% change 2.6709% change 2.2528% change 2.74681% change 2.984% change
6 │ 2.93285% change 3.38343% change 2.5865% change 4.51183% change 2.25368% change 3.82229% change
7 │ 3.15057% change 1.34921% change 2.37719% change 3.88018% change 2.23458% change 4.09044% change
8 │ 5.21243% change 3.88728% change 4.23719% change 3.56254% change 2.15163% change 0.62279% change
9 │ 3.38416% change 2.93178% change 2.99221% change 1.47015% change 1.52782% change 3.09726% change
10 │ 10.6543% change 4.1238% change 1.63075% change 1.5032% change 2.87926% change 2.91298% change
11 │ 3.06248% change 4.22213% change 1.99972% change 4.60347% change 2.34263% change 4.16388% change
12 │
13 │ 41.21989/10 31.1598/10 23.471278/10 30.42049/10 24.04233/10 29.03844/10
14 │ 4.121989 3.11598 2.3471278 3.042049 2.404233 2.903844
───────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
───────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
│ Results: change-master VS master
───────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ 1MB allocation 2MB allocation 4MB allocation 6MB allocation 8MB allocation 10MB allocation
2 │ 0.0734512% change 0.0955% change 0.0521763% change 2.35381% change 0.286904% change 1.27789% change
3 │ 0.549367% change 1.18382% change 0.276532% change 0.333774% change 0.260206% change 0.108897% change
4 │ 0.0714411% change 0.927286% change 0.751164% change 0.456132% change 0.216137% change 1.4295% change
5 │ 0.269374% change 0.845028% change 0.222661% change 0.315429% change 0.29083% change 0.2489% change
6 │ 1.0369% change 0.368121% change 0.702026% change 0.292232% change 0.840997% change 0.273402% change
7 │ 0.0584813% change 0.151054% change 0.07218% change 0.596766% change 1.78613% change 0.499307% change
8 │ 0.355761% change 1.18807% change 0.201631% change 1.22752% change 0.265651% change 0.805671% change
9 │ 0.0812124% change 1.16863% change 1.02435% change 0.149198% change 0.402121% change 0.125709% change
10 │ 0.955516% change 0.154351% change 0.425324% change 0.871006% change 0.158059% change 0.225179% change
11 │ 0.500527% change 0.307882% change 0.278758% change 0.122533% change 0.539593% change 0.862113% change
12 │
13 │ 3.952031/10 6.389742/10 4.006802/10 6.7184/10 5.046628/10 5.856568/10
14 │ 0.3952031 0.6389742 0.4006802 0.67184 0.5046628 0.5856568
───────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
───────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
│ Results: change-pg-stat-activity-backend-memory-allocated VS master
───────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │ 1MB allocation 2MB allocation 4MB allocation 6MB allocation 8MB allocation 10MB allocation
2 │ 2.02713% change 0.505768% change 0.506049% change 0.136223% change 0.591833% change 1.3304% change
3 │ 1.20444% change 0.331448% change 0.481523% change 1.66557% change 0.175325% change 0.974006% change
4 │ 0.068074% change 0.294776% change 0.8638% change 1.12325% change 0.193568% change 0.711637% change
5 │ 0.91108% change 1.41401% change 1.47956% change 0.6396% change 1.33369% change 0.377679% change
6 │ 2.43448% change 2.63562% change 0.636209% change 0.648194% change 0.4807% change 1.64349% change
7 │ 1.30168% change 0.054868% change 1.22463% change 2.09474% change 0.316791% change 3.93449% change
8 │ 1.60165% change 0.461483% change 0.722126% change 0.173102% change 1.32277% change 0.555352% change
9 │ 1.63712% change 0.599944% change 1.41466% change 0.722953% change 0.229375% change 0.871673% change
10 │ 1.76986% change 1.44599% change 0.629711% change 1.97183% change 0.99455% change 1.8359% change
11 │ 0.392085% change 1.12579% change 0.138195% change 0.532498% change 0.677892% change 1.61841% change
12 │
13 │ 13.347599/10 8.869697/10 8.096463/10 9.70796/10 6.316494/10 13.853037/10
14 │ 1.3347599 0.8869697 0.8096463 0.970796 0.6316494 1.385303
───────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

#40Andrei Lepikhov
a.lepikhov@postgrespro.ru
In reply to: Noname (#38)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On 22/5/2023 22:59, reid.thompson@crunchydata.com wrote:

Attach patches updated to master.
Pulled from patch 2 back to patch 1 a change that was also pertinent to patch 1.

+1 to the idea, have doubts on the implementation.

I have a question. I see the feature triggers ERROR on the exceeding of
the memory limit. The superior PG_CATCH() section will handle the error.
As I see, many such sections use memory allocations. What if some
routine, like the CopyErrorData(), exceeds the limit, too? In this case,
we could repeat the error until the top PG_CATCH(). Is this correct
behaviour? Maybe to check in the exceeds_max_total_bkend_mem() for
recursion and allow error handlers to slightly exceed this hard limit?

Also, the patch needs to be rebased.

--
regards,
Andrey Lepikhov
Postgres Professional

#41Andrei Lepikhov
a.lepikhov@postgrespro.ru
In reply to: Andrei Lepikhov (#40)
1 attachment(s)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On 29/9/2023 09:52, Andrei Lepikhov wrote:

On 22/5/2023 22:59, reid.thompson@crunchydata.com wrote:

Attach patches updated to master.
Pulled from patch 2 back to patch 1 a change that was also pertinent
to patch 1.

+1 to the idea, have doubts on the implementation.

I have a question. I see the feature triggers ERROR on the exceeding of
the memory limit. The superior PG_CATCH() section will handle the error.
As I see, many such sections use memory allocations. What if some
routine, like the CopyErrorData(), exceeds the limit, too? In this case,
we could repeat the error until the top PG_CATCH(). Is this correct
behaviour? Maybe to check in the exceeds_max_total_bkend_mem() for
recursion and allow error handlers to slightly exceed this hard limit?

By the patch in attachment I try to show which sort of problems I'm
worrying about. In some PП_CATCH() sections we do CopyErrorData
(allocate some memory) before aborting the transaction. So, the
allocation error can move us out of this section before aborting. We
await for soft ERROR message but will face more hard consequences.

--
regards,
Andrey Lepikhov
Postgres Professional

Attachments:

reorder_operators.difftext/plain; charset=UTF-8; name=reorder_operators.diffDownload
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index 33975687b3..3f992b8d92 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -291,10 +291,7 @@ _SPI_commit(bool chain)
 	{
 		ErrorData  *edata;
 
-		/* Save error info in caller's context */
 		MemoryContextSwitchTo(oldcontext);
-		edata = CopyErrorData();
-		FlushErrorState();
 
 		/*
 		 * Abort the failed transaction.  If this fails too, we'll just
@@ -302,6 +299,10 @@ _SPI_commit(bool chain)
 		 */
 		AbortCurrentTransaction();
 
+		/* Save error info in caller's context */
+		edata = CopyErrorData();
+		FlushErrorState();
+
 		/* ... and start a new one */
 		StartTransactionCommand();
 		if (chain)
@@ -383,10 +384,7 @@ _SPI_rollback(bool chain)
 	{
 		ErrorData  *edata;
 
-		/* Save error info in caller's context */
 		MemoryContextSwitchTo(oldcontext);
-		edata = CopyErrorData();
-		FlushErrorState();
 
 		/*
 		 * Try again to abort the failed transaction.  If this fails too,
@@ -395,6 +393,10 @@ _SPI_rollback(bool chain)
 		 */
 		AbortCurrentTransaction();
 
+		/* Save error info in caller's context */
+		edata = CopyErrorData();
+		FlushErrorState();
+
 		/* ... and start a new one */
 		StartTransactionCommand();
 		if (chain)
diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c
index 12edc5772a..f9cf599026 100644
--- a/src/backend/replication/logical/reorderbuffer.c
+++ b/src/backend/replication/logical/reorderbuffer.c
@@ -2565,7 +2565,7 @@ ReorderBufferProcessTXN(ReorderBuffer *rb, ReorderBufferTXN *txn,
 	PG_CATCH();
 	{
 		MemoryContext ecxt = MemoryContextSwitchTo(ccxt);
-		ErrorData  *errdata = CopyErrorData();
+		ErrorData  *errdata;
 
 		/* TODO: Encapsulate cleanup from the PG_TRY and PG_CATCH blocks */
 		if (iterstate)
@@ -2579,6 +2579,8 @@ ReorderBufferProcessTXN(ReorderBuffer *rb, ReorderBufferTXN *txn,
 		 */
 		AbortCurrentTransaction();
 
+		errdata = CopyErrorData();
+
 		/* make sure there's no cache pollution */
 		ReorderBufferExecuteInvalidations(txn->ninvalidations,
 										  txn->invalidations);
#42Stephen Frost
sfrost@snowman.net
In reply to: Andrei Lepikhov (#41)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

Greetings,

* Andrei Lepikhov (a.lepikhov@postgrespro.ru) wrote:

On 29/9/2023 09:52, Andrei Lepikhov wrote:

On 22/5/2023 22:59, reid.thompson@crunchydata.com wrote:

Attach patches updated to master.
Pulled from patch 2 back to patch 1 a change that was also pertinent
to patch 1.

+1 to the idea, have doubts on the implementation.

I have a question. I see the feature triggers ERROR on the exceeding of
the memory limit. The superior PG_CATCH() section will handle the error.
As I see, many such sections use memory allocations. What if some
routine, like the CopyErrorData(), exceeds the limit, too? In this case,
we could repeat the error until the top PG_CATCH(). Is this correct
behaviour? Maybe to check in the exceeds_max_total_bkend_mem() for
recursion and allow error handlers to slightly exceed this hard limit?

By the patch in attachment I try to show which sort of problems I'm worrying
about. In some PП_CATCH() sections we do CopyErrorData (allocate some
memory) before aborting the transaction. So, the allocation error can move
us out of this section before aborting. We await for soft ERROR message but
will face more hard consequences.

While it's an interesting idea to consider making exceptions to the
limit, and perhaps we'll do that (or have some kind of 'reserve' for
such cases), this isn't really any different than today, is it? We
might have a malloc() failure in the main path, end up in PG_CATCH() and
then try to do a CopyErrorData() and have another malloc() failure.

If we can rearrange the code to make this less likely to happen, by
doing a bit more work to free() resources used in the main path before
trying to do new allocations, then, sure, let's go ahead and do that,
but that's independent from this effort.

Thanks!

Stephen

#43Andrei Lepikhov
a.lepikhov@postgrespro.ru
In reply to: Stephen Frost (#42)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On 19/10/2023 02:00, Stephen Frost wrote:

Greetings,

* Andrei Lepikhov (a.lepikhov@postgrespro.ru) wrote:

On 29/9/2023 09:52, Andrei Lepikhov wrote:

On 22/5/2023 22:59, reid.thompson@crunchydata.com wrote:

Attach patches updated to master.
Pulled from patch 2 back to patch 1 a change that was also pertinent
to patch 1.

+1 to the idea, have doubts on the implementation.

I have a question. I see the feature triggers ERROR on the exceeding of
the memory limit. The superior PG_CATCH() section will handle the error.
As I see, many such sections use memory allocations. What if some
routine, like the CopyErrorData(), exceeds the limit, too? In this case,
we could repeat the error until the top PG_CATCH(). Is this correct
behaviour? Maybe to check in the exceeds_max_total_bkend_mem() for
recursion and allow error handlers to slightly exceed this hard limit?

By the patch in attachment I try to show which sort of problems I'm worrying
about. In some PП_CATCH() sections we do CopyErrorData (allocate some
memory) before aborting the transaction. So, the allocation error can move
us out of this section before aborting. We await for soft ERROR message but
will face more hard consequences.

While it's an interesting idea to consider making exceptions to the
limit, and perhaps we'll do that (or have some kind of 'reserve' for
such cases), this isn't really any different than today, is it? We
might have a malloc() failure in the main path, end up in PG_CATCH() and
then try to do a CopyErrorData() and have another malloc() failure.

If we can rearrange the code to make this less likely to happen, by
doing a bit more work to free() resources used in the main path before
trying to do new allocations, then, sure, let's go ahead and do that,
but that's independent from this effort.

I agree that rearranging efforts can be made independently. The code in
the letter above was shown just as a demo of the case I'm worried about.
IMO, the thing that should be implemented here is a recursion level for
the memory limit. If processing the error, we fall into recursion with
this limit - we should ignore it.
I imagine custom extensions that use PG_CATCH() and allocate some data
there. At least we can raise the level of error to FATAL.

--
regards,
Andrey Lepikhov
Postgres Professional

#44Stephen Frost
sfrost@snowman.net
In reply to: Andrei Lepikhov (#43)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

Greetings,

* Andrei Lepikhov (a.lepikhov@postgrespro.ru) wrote:

On 19/10/2023 02:00, Stephen Frost wrote:

* Andrei Lepikhov (a.lepikhov@postgrespro.ru) wrote:

On 29/9/2023 09:52, Andrei Lepikhov wrote:

On 22/5/2023 22:59, reid.thompson@crunchydata.com wrote:

Attach patches updated to master.
Pulled from patch 2 back to patch 1 a change that was also pertinent
to patch 1.

+1 to the idea, have doubts on the implementation.

I have a question. I see the feature triggers ERROR on the exceeding of
the memory limit. The superior PG_CATCH() section will handle the error.
As I see, many such sections use memory allocations. What if some
routine, like the CopyErrorData(), exceeds the limit, too? In this case,
we could repeat the error until the top PG_CATCH(). Is this correct
behaviour? Maybe to check in the exceeds_max_total_bkend_mem() for
recursion and allow error handlers to slightly exceed this hard limit?

By the patch in attachment I try to show which sort of problems I'm worrying
about. In some PП_CATCH() sections we do CopyErrorData (allocate some
memory) before aborting the transaction. So, the allocation error can move
us out of this section before aborting. We await for soft ERROR message but
will face more hard consequences.

While it's an interesting idea to consider making exceptions to the
limit, and perhaps we'll do that (or have some kind of 'reserve' for
such cases), this isn't really any different than today, is it? We
might have a malloc() failure in the main path, end up in PG_CATCH() and
then try to do a CopyErrorData() and have another malloc() failure.

If we can rearrange the code to make this less likely to happen, by
doing a bit more work to free() resources used in the main path before
trying to do new allocations, then, sure, let's go ahead and do that,
but that's independent from this effort.

I agree that rearranging efforts can be made independently. The code in the
letter above was shown just as a demo of the case I'm worried about.
IMO, the thing that should be implemented here is a recursion level for the
memory limit. If processing the error, we fall into recursion with this
limit - we should ignore it.
I imagine custom extensions that use PG_CATCH() and allocate some data
there. At least we can raise the level of error to FATAL.

Ignoring such would defeat much of the point of this effort- which is to
get to a position where we can say with some confidence that we're not
going to go over some limit that the user has set and therefore not
allow ourselves to end up getting OOM killed. These are all the same
issues that already exist today on systems which don't allow overcommit
too, there isn't anything new here in regards to these risks, so I'm not
really keen to complicate this to deal with issues that are already
there.

Perhaps once we've got the basics in place then we could consider
reserving some space for handling such cases.. but I don't think it'll
actually be very clean and what if we have an allocation that goes
beyond what that reserved space is anyway? Then we're in the same spot
again where we have the choice of either failing the allocation in a
less elegant way than we might like to handle that error, or risk
getting outright kill'd by the kernel. Of those choices, sure seems
like failing the allocation is the better way to go.

Thanks,

Stephen

#45Andres Freund
andres@anarazel.de
In reply to: Stephen Frost (#44)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

Hi,

On 2023-10-19 18:06:10 -0400, Stephen Frost wrote:

Ignoring such would defeat much of the point of this effort- which is to
get to a position where we can say with some confidence that we're not
going to go over some limit that the user has set and therefore not
allow ourselves to end up getting OOM killed.

I think that is a good medium to long term goal. I do however think that we'd
be better off merging the visibility of memory allocations soon-ish and
implement the limiting later. There's a lot of hairy details to get right for
the latter, and even just having visibility will be a huge improvement.

I think even patch 1 is doing too much at once. I doubt the DSM stuff is
quite right.

I'm unconvinced it's a good idea to split the different types of memory
contexts out. That just exposes too much implementation detail stuff without a
good reason.

I think the overhead even just the tracking implies right now is likely too
high and needs to be optimized. It should be a single math operation, not
tracking things in multiple fields. I don't think pg_sub_u64_overflow() should
be in the path either, that suddenly adds conditional branches. You really
ought to look at the difference in assembly for the hot functions.

Greetings,

Andres Freund

#46Stephen Frost
sfrost@snowman.net
In reply to: Andres Freund (#45)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

Greetings,

* Andres Freund (andres@anarazel.de) wrote:

On 2023-10-19 18:06:10 -0400, Stephen Frost wrote:

Ignoring such would defeat much of the point of this effort- which is to
get to a position where we can say with some confidence that we're not
going to go over some limit that the user has set and therefore not
allow ourselves to end up getting OOM killed.

I think that is a good medium to long term goal. I do however think that we'd
be better off merging the visibility of memory allocations soon-ish and
implement the limiting later. There's a lot of hairy details to get right for
the latter, and even just having visibility will be a huge improvement.

I agree that having the visibility will be a great improvement and
perhaps could go in separately, but I don't know that I agree that the
limits are going to be that much of an issue. In any case, there's been
work ongoing on this and that'll be posted soon. I was just trying to
address the general comment raised in this sub-thread here.

I think even patch 1 is doing too much at once. I doubt the DSM stuff is
quite right.

Getting DSM right has certainly been tricky, along with other things,
but we've been working towards, and continue to work towards, getting
everything to line up nicely between memory context allocations of
various types and the amounts which are being seen as malloc'd/free'd.
There's been parts of this also reworked to allow us to see per-backend
reservations as well as total reserved and to get those numbers able to
be matched up inside of a given transaction using the statistics system.

I'm unconvinced it's a good idea to split the different types of memory
contexts out. That just exposes too much implementation detail stuff without a
good reason.

DSM needs to be independent anyway ... as for the others, perhaps we
could combine them, though that's pretty easily done later and for now
it's been useful to see them split out as we've been working on the
patch.

I think the overhead even just the tracking implies right now is likely too
high and needs to be optimized. It should be a single math operation, not
tracking things in multiple fields. I don't think pg_sub_u64_overflow() should
be in the path either, that suddenly adds conditional branches. You really
ought to look at the difference in assembly for the hot functions.

This has been improved in the most recent work and we'll have that
posted soon, probably best to hold off from larger review of this right
now- as mentioned, I was just trying to address the specific question in
this sub-thread since a new patch is coming soon.

Thanks,

Stephen

#47Andrei Lepikhov
a.lepikhov@postgrespro.ru
In reply to: Stephen Frost (#44)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On 20/10/2023 05:06, Stephen Frost wrote:

Greetings,

* Andrei Lepikhov (a.lepikhov@postgrespro.ru) wrote:

On 19/10/2023 02:00, Stephen Frost wrote:

* Andrei Lepikhov (a.lepikhov@postgrespro.ru) wrote:

On 29/9/2023 09:52, Andrei Lepikhov wrote:

On 22/5/2023 22:59, reid.thompson@crunchydata.com wrote:

Attach patches updated to master.
Pulled from patch 2 back to patch 1 a change that was also pertinent
to patch 1.

+1 to the idea, have doubts on the implementation.

I have a question. I see the feature triggers ERROR on the exceeding of
the memory limit. The superior PG_CATCH() section will handle the error.
As I see, many such sections use memory allocations. What if some
routine, like the CopyErrorData(), exceeds the limit, too? In this case,
we could repeat the error until the top PG_CATCH(). Is this correct
behaviour? Maybe to check in the exceeds_max_total_bkend_mem() for
recursion and allow error handlers to slightly exceed this hard limit?

By the patch in attachment I try to show which sort of problems I'm worrying
about. In some PП_CATCH() sections we do CopyErrorData (allocate some
memory) before aborting the transaction. So, the allocation error can move
us out of this section before aborting. We await for soft ERROR message but
will face more hard consequences.

While it's an interesting idea to consider making exceptions to the
limit, and perhaps we'll do that (or have some kind of 'reserve' for
such cases), this isn't really any different than today, is it? We
might have a malloc() failure in the main path, end up in PG_CATCH() and
then try to do a CopyErrorData() and have another malloc() failure.

If we can rearrange the code to make this less likely to happen, by
doing a bit more work to free() resources used in the main path before
trying to do new allocations, then, sure, let's go ahead and do that,
but that's independent from this effort.

I agree that rearranging efforts can be made independently. The code in the
letter above was shown just as a demo of the case I'm worried about.
IMO, the thing that should be implemented here is a recursion level for the
memory limit. If processing the error, we fall into recursion with this
limit - we should ignore it.
I imagine custom extensions that use PG_CATCH() and allocate some data
there. At least we can raise the level of error to FATAL.

Ignoring such would defeat much of the point of this effort- which is to
get to a position where we can say with some confidence that we're not
going to go over some limit that the user has set and therefore not
allow ourselves to end up getting OOM killed. These are all the same
issues that already exist today on systems which don't allow overcommit
too, there isn't anything new here in regards to these risks, so I'm not
really keen to complicate this to deal with issues that are already
there.

Perhaps once we've got the basics in place then we could consider
reserving some space for handling such cases.. but I don't think it'll
actually be very clean and what if we have an allocation that goes
beyond what that reserved space is anyway? Then we're in the same spot
again where we have the choice of either failing the allocation in a
less elegant way than we might like to handle that error, or risk
getting outright kill'd by the kernel. Of those choices, sure seems
like failing the allocation is the better way to go.

I've got your point.
The only issue I worry about is the uncertainty and clutter that can be
created by this feature. In the worst case, when we have a complex error
stack (including the extension's CATCH sections, exceptions in stored
procedures, etc.), the backend will throw the memory limit error
repeatedly. Of course, one failed backend looks better than a
surprisingly killed postmaster, but the mix of different error reports
and details looks terrible and challenging to debug in the case of
trouble. So, may we throw a FATAL error if we reach this limit while
handling an exception?

--
regards,
Andrey Lepikhov
Postgres Professional

#48Stephen Frost
sfrost@snowman.net
In reply to: Andrei Lepikhov (#47)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

Greetings,

* Andrei Lepikhov (a.lepikhov@postgrespro.ru) wrote:

The only issue I worry about is the uncertainty and clutter that can be
created by this feature. In the worst case, when we have a complex error
stack (including the extension's CATCH sections, exceptions in stored
procedures, etc.), the backend will throw the memory limit error repeatedly.

I'm not seeing what additional uncertainty or clutter there is- this is,
again, exactly the same as what happens today on a system with
overcommit disabled and I don't feel like we get a lot of complaints
about this today.

Of course, one failed backend looks better than a surprisingly killed
postmaster, but the mix of different error reports and details looks
terrible and challenging to debug in the case of trouble. So, may we throw a
FATAL error if we reach this limit while handling an exception?

I don't see why we'd do that when we can do better- we just fail
whatever the ongoing query or transaction is and allow further requests
on the same connection. We already support exactly that and it works
really rather well and I don't see why we'd throw that away because
there's a different way to get an OOM error.

If you want to make the argument that we should throw FATAL on OOM when
handling an exception, that's something you could argue independently of
this effort already today, but I don't think you'll get agreement that
it's an improvement.

Thanks,

Stephen

#49Andrei Lepikhov
a.lepikhov@postgrespro.ru
In reply to: Stephen Frost (#48)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On 20/10/2023 19:39, Stephen Frost wrote:
Greetings,

* Andrei Lepikhov (a.lepikhov@postgrespro.ru) wrote:

The only issue I worry about is the uncertainty and clutter that can be
created by this feature. In the worst case, when we have a complex error
stack (including the extension's CATCH sections, exceptions in stored
procedures, etc.), the backend will throw the memory limit error repeatedly.

I'm not seeing what additional uncertainty or clutter there is- this is,
again, exactly the same as what happens today on a system with
overcommit disabled and I don't feel like we get a lot of complaints
about this today.

Maybe I missed something or see this feature from an alternate point of
view (as an extension developer), but overcommit is more useful so far:
it kills a process.
It means that after restart, the backend/background worker will have an
initial internal state. With this limit enabled, we need to remember
that each function call can cause an error, and we have to remember it
using static PG_CATCH sections where we must rearrange local variables
to the initial (?) state. So, it complicates development.
Of course, this limit is a good feature, but from my point of view, it
would be better to kill a memory-consuming backend instead of throwing
an error. At least for now, we don't have a technique to repeat query
planning with chances to build a more effective plan.

--
regards,
Andrei Lepikhov
Postgres Professional

#50Andres Freund
andres@anarazel.de
In reply to: Andrei Lepikhov (#49)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

Hi,

On 2023-10-24 09:39:42 +0700, Andrei Lepikhov wrote:

On 20/10/2023 19:39, Stephen Frost wrote:
Greetings,

* Andrei Lepikhov (a.lepikhov@postgrespro.ru) wrote:

The only issue I worry about is the uncertainty and clutter that can be
created by this feature. In the worst case, when we have a complex error
stack (including the extension's CATCH sections, exceptions in stored
procedures, etc.), the backend will throw the memory limit error repeatedly.

I'm not seeing what additional uncertainty or clutter there is- this is,
again, exactly the same as what happens today on a system with
overcommit disabled and I don't feel like we get a lot of complaints
about this today.

Maybe I missed something or see this feature from an alternate point of view
(as an extension developer), but overcommit is more useful so far: it kills
a process.

In case of postgres it doesn't just kill one postgres, it leads to *all*
connections being terminated.

It means that after restart, the backend/background worker will have an
initial internal state. With this limit enabled, we need to remember that
each function call can cause an error, and we have to remember it using
static PG_CATCH sections where we must rearrange local variables to the
initial (?) state. So, it complicates development.

You need to be aware of errors being thrown regardless this feature, as
out-of-memory errors can be encountered today already. There also are many
other kinds of errors that can be thrown.

Greetings,

Andres Freund

#51Anton A. Melnikov
a.melnikov@postgrespro.ru
In reply to: Andres Freund (#50)
2 attachment(s)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

Hello!

Earlier in this thread, the pgbench results were published, where with a strong memory limit of 100MB
a significant, about 10%, decrease in TPS was observed [1]/messages/by-id/3178e9a1b7acbcf023fafed68ca48d76afc07907.camel@crunchydata.com.

Using dedicated server with 12GB RAM and methodology described in [3]/messages/by-id/1d3a7d8f-cb7c-4468-a578-d8a1194ea2de@postgrespro.ru, i performed five series
of measurements for the patches from the [2]/messages/by-id/4edafedc0f8acb12a2979088ac1317bd7dd42145.camel@crunchydata.com.
The series were like this:
1) unpatched 16th version at the REL_16_BETA1 (e0b82fc8e83) as close to [2]/messages/by-id/4edafedc0f8acb12a2979088ac1317bd7dd42145.camel@crunchydata.com in time.
2) patched REL_16_BETA1 at e0b82fc8e83 with undefined max_total_backend_memory GUC (with default value = 0).
3) patched REL_16_BETA1 with max_total_backend_memory = 16GB
4) the same with max_total_backend_memory = 8GB
5) and again with max_total_backend_memory = 200MB

Measurements with max_total_backend_memory = 100MB were not be carried out,
with limit 100MB the server gave an error on startup:
FATAL: configured max_total_backend_memory 100MB is <= shared_memory_size 143MB
So i used 200MB to retain all other GUCs the same.

Pgbench gave the following results:
1) and 2) almost the same: ~6350 TPS. See orange and green
distributions on the attached graph.png respectively.
3) and 4) identical to each other (~6315 TPS) and a bit slower than 1) and 2) by ~0,6%.
See blue and yellow distributions respectively.
5) is slightly slower (~6285 TPS) than 3) and 4) by another 0,5%. (grey distribution)
The standard error in all series was ~0.2%. There is a raw data in the raw_data.txt.

With the best wishes,

--
Anton A. Melnikov
Postgres Professional: http://www.postgrespro.com
The Russian Postgres Company

[1]: /messages/by-id/3178e9a1b7acbcf023fafed68ca48d76afc07907.camel@crunchydata.com
[2]: /messages/by-id/4edafedc0f8acb12a2979088ac1317bd7dd42145.camel@crunchydata.com
[3]: /messages/by-id/1d3a7d8f-cb7c-4468-a578-d8a1194ea2de@postgrespro.ru

Attachments:

graph.pngimage/png; name=graph.pngDownload
�PNG


IHDR����Z	pHYsg��R IDATx^��y\Te�?��0 �.BJ��+���+���i���i�}��o��ugi��eee���i��w�������� �� 
�	���������330,���x�xp������s����R����@!�B!�B!�B1�m��
�!�B!�B!�B�����6m�H�B!�B!�B!�B�qqqa=!�B!�B!�B!�
�B!�B!�B!�b!
�B!�B!�B!�b!
�B!�B!�B!�b!
�B!�B!�B!�b!
�B!�B!�B!�b!
�B!�B!�B!�b!
�B!�B!�B!�b!
�B!�B!�B!�b!
�B!�B!�B!�b!
�B!�B!�B!�b!
�B!�B!�B!�b!
�B!�B!�B!�b!
�B!�B!�B!�b!
�B!�B!�B!�b!
�B!�B!�B!�b!
�B!�B!�B!�b!
�B!�B!�B!�b!
�B!�B!�B!�b!
�B!�B!�B!�b![q!�B!��6�N����lkk�B!��B!�B�\#�������<A�VC�VC�����666ptt���+|}}���%��I���(++W[����B���������Q#������G||<����M�����'O�k��h�����Z#%%��#j�Z�Z����������#7n___��Zv����RZZ�������O\�\�v
<x����n��	www4n�X����6��Qe�5�j�*&))	�~�)[~��w��{w����q>D�N�`oo/n��Z-��������� qs�*--�����@�����
6D��-�R)��E���p��Edee���nnn���A�.]���"�n�V�����������l���������h��������"��zZ����pqq���������GFFk�4
k�������'''4i��7��}[*!!999�6m����U�C.;;�/_Frr2
akkwww�j�
AAA����B�����7o"''���(..���3<==��m[4o�����(Wc����R���ukqS�Y���V�q��u���#//>D�z�����f���]�v�����CNN�������jQRR�N�������~~~h�����Uv��%���@�P 88��� ??���CFF������///t���������TRR���/�k�Z����+�����U+�m����(*�
�.]BRRrssNNNh��1��i�-Z�A!���7���[�j�����F���#44#F�0���}�4���bs��A���������i�����mu�Z����K���������-��h�e�>|eee8v�,XP��w���g�}&�6�����u���c�}�������]�V�Te�6mW1[�lAjj*BCC� KUEDD`��x���������8�FU/j�������Fm��	{�������/�D�z���jWii)���K�������7�xC��v�>}��'����M���+�y��966��2����U�V�����&���
���'Z=|�0�n�
�J%n�_����c�����7��>}k��E�>}���K�l����|�r�������73aaaf��R������/�}�Y8::��+�����-Cnn.�������G���R��a�������T�@��O�07��R��g������2h��F��A���<J�����4��?-[����s�����������kbbbL��T*��G<���f�����;�����F���b��!8p��m�9w�����K-[�D�.]�=x�����aN�8a�o��a:t���_�B�!UW\\������7z�7pttD���1n�88;;��9%%%��c���o����/����G!U�c!�<qrss�o�>��=aaa�f"P�T�������(n����,|��g8x� ���h4�����;4
���1w����\INNFBB���q��Yqs��9s�������M��FU�Q�FUT]n��9�~NMM���_rr2���S��v�������j���u+V�Xa6���:6m��%K�@����e���������`��C��`���jq3����b�
�[��l�ZFF.\����[�$s��m���v��r��E�r�)������wc���HJJ7W���W�(�N�:�
,������>���'����|�^����?~���.v��Un`
�g;�]�_}�W��j���r��|��W(,,7U�������X�t)���+\�v��9�	�>}�|�	��?/n����T�]����GAA����������{��l�+((��y�p��Q����W���#55U�DH�KMM�J�Y����`�����w��k?��9|�0�}�]���%%%�����c��r�������7�`����&B��5B�i
�666&0�j5V�Z;;;���S�L�����o���"n����,,X���������9s���	
6D�&M����R	�V���,$''��|�V�U�V���������c����������6V�����q��:�i]�PUu�FQUQu��j��!��������Wk���;�J%k�\\\Lf�eee���S8u�����x�bq��q�v����k�����������"���r��k��a���x���%������w�}������C899!99�.]b����o���~��9s��R��m��������-������OC�R!::������U�V�Q�FfK���*�
��]C���=����X6Nvv6������&�e���/<==Q�^=(�J��j��{w��e����b���X�t)���%�]1��by��U�V�����
���


p��u��w�m��w/���:�6l���M���A�����!33�},-�[W��1��_�?�`���5�����������]\\���WWW"55��k4�
�S������+-ZXX���d����}����������?7��X�N���H�,;s�����X�|90svvFHH4h������S�0(i����
�bMEEE������'������W[�n>
222�h�"���s�6looo���#//w����&�J��~�	�}��������;e�~�����uk��� 77W�^EVV��s�N4i��z���!�I�����������������B������ 55��������He�N�����c���>\4o�o�������<���K�.a������R�TX�x���y��y�*�bm}����	�����������s��?��7�|#�)W�s���:t7q~��g$$$�w�Y�~��h4\���7q��}<��S��,WTT�5k���EL�6�:���6�"�6�_��~��W�����g������K������3�u�V888`��i&;�W�^�+W����Q]���X�������

$����������Y`���x��gM�W���c>XQ��{��m,Z��e�DGG����� Wrr2v���������Gq�������o����������������N���;w����ge��1qqq\fMRR:u�$�����'#00P\���d�Z��e�`����6m���4
�(rrr2[�*%%�+���SO���?���*))��M�p��A�n��}f�kk�����������!!!��]YYY8z�(>�Z�q��q�����U����w�^l����� KY��{��],X���Q(���
�V�Zq����\�r�w�F\\��m[��<�|���]��t�x�"V�Z��Wqqq8s�����9111�S�C�f��;z�(����K���[\����||��7������]�va��IlBj��#G�y�fq�cA��`��%��J��M1u�T�k�N��?s�m��iii�aV�Z���~�Z����nh��f��)�G/++��M���~�n��-\#�p(�F1J�bkk///xyy!88�������O~~>�����_?�;����U�a�Q��j�e�8p�*#���n����#>���:,���0k�,dff���[�%������#�����R��B���BQ��'""EEE����p����:K�����������M�j�*��(=j�,�(�Q-[���%K��uN��}����-={����~����9����.�������+8q��:��.��/�������1c�H��k���|�M67��,�\[�nem���f��-�)�J���k�s���3>>IIIh��9�/���s��.\�����r�{2��4HLL�8�f���������{�}w��;W� PTT���w�n6���5�0aX�����'#::�e�����<^��Z���1e����yzzb���:t(N�:�6m���TXmW���\���/�v����R�q��j���������>������-��'O�I�&�.�P(��K��5_�5[���J�,�.�h4\�����~�m�Yg������{s��e��'N���	d�BB�ul�������9sd�O@�6u���:u����� C��E����2e
����{�n|��h��!�f`cc��_~��������DJJ
�6m*�MyR���	!�M�6�����u�zP|�]�p~�!���o�N��G�r8J����^��u�B�@hh(�NZr�Qf/V������X�z5>���G���QAm�i�F���2���'K@@���{��51SIZ*P���C�g�Ri4���S�N\�����(..f����\f����������J�,�gjN(�$���q��
n�1��k�����������t�@K���|�����
���_RRbtn,��lR�
��3L��<<<��s���+���+�����o>�����X����_qs9:;;c��y&k������A��c��\�Ii��"�Z-��;ppp@�.]�=�q���$��	�v���R:P���7o���A����L.c����h�[�T*���os����4�s��9��-3X3P(��hS�=��'�!�"v�X29��.&&��-�n�z��mt��%���e%^z�%�o��[W��s��7a�� 99���qpp`#�333+����������������G��z4#%%qqqub2mj����2��(��6�R���HHH����e�V����wq��-��{���(����8?�4fPZZ�.���;�[FW��j��������

�J�:�
�������wO��Vp
�N�����9^^^���3o��W)i� �]8x� 7�M��M1e���OkBmW@?G����1�����	�f�Y�Z����B9r�[��k�Y%�*��	*�����<��������mqvv.wp�8 �q���j���#..iiif���TPP���d������;���"��������%


������8��w�B���T*RSSq��-���sm`U��j��� >>YYY�~�X�X��������>�����)�Lk)1���Z�=��'�e5!D �������Dz���qcL�6
���X�h�d/������CF�n�0b���qr���~�[~Io��u����,6�=,,LV�CJ�P`��!�8q"����g�a�������9s�y��U+��;W�K������>;;v�������~��u���111�w@�T�u��		Ahh��S��Q%Gm�q�F�V�mTU8pW�u��\{e�b�
������s����u��'bcc�N%OOO����=������?��?��-������7^x�.�����~b%H�F��}w����������fp���s����[g�X�8X����[��S�>H�'�
��������#������5c��(�J�h���;�f�H[��^{�d H44���ENN���beH�$GG�r���DDD�`o�^�L�--Z�������w�y�[��#�������cR����6��M��|bu���
����� ���kh�����/�^��������\�```�K0Z�N��#��[�]XZZ�����m[��b)???�����_�~����W�|�r�<n�8��u�.\�������o��u����=�_��-/]�T�N�t:DDD���������(
�h��{���A�����������q��n�K@��6n�=z����C�}vP����k���d�a<<<��cG������N���'p��!���r�������@t��
]�v5{�u:���q��q��u��������z����������r��N�6
�:uBRR�m����h�u
����c���HHH�%?��#��;l�0�5�[g�cPt:���������������7��MLL���wMf��c�}!��e��$!��"�37I������G����c�-Y`NFFwC���Z��!j�tD���_��d�
�F�=�������������3f�5k������c��\]]�>�+W����{���q��y6!<������c����c�R����y�&n������w�V�FGm��Q��TU*��k�����U����,dee���+������k�f�eeea��=����g�}����c��
FGu�T*>|����7o<==�����F���1�����WZZjt}M��������e���-[����?/i)R���h�B�qh�t>���B�A��kyyy���5�KB$%%U9�VPP�u�����RN�O�f?�.t��nnn,�{��Yl��/��"�_xx8�������Lcbb�����5�NkZmW777���+�������W,�:l�0n�6\�z�;w �j����www��s�JOO�V�e��\�
6l��W+S.  666��jDDD�����#++���F�wR�������ukY  ??�}���R���������:ts���T@B�e����������w����;p��Q���;&fdeea���&KVggg���8q�f���e;k�Z|�����
���"DEE!**
}�����3�]��������$q�@���$$%%����Z����k4DEEa��F����/�k��@�k����Au�s�0
d�*�k����{7[����������U;;�G�Y�b]��$���/j��5��$�����%K0~��*uZ�yJ�w���{��eee���?�����=f��iQ�X]v��i6�������GHH���j5�����b�s�=��Z�0o
b�������'O��7n��;�w���5ggg�m�-[������I�F�Q��6�|5�F����Wc��5(++���=Z�j��M����<��_~�k
�>>>����������[W
�nnnpss�2�J%[/�g����h4\�|�-;::
B����@�1�������i������e�k�2�b�j^^�(�x�P�T*����w�Z���?��#������������4����ys��������i����k�.,[��
V�����M��v�Sb��W�^�rM���
��\�lY�k����j��+�������;��C-HKK���BCC"��2���,[���B1s�2m���XB�T�[�nl9!!�����w���>|X��+,,d�����������s�5[[[�W�^���?~����R�����R������:���C|��w&�g?��3�M�P������P(d��w��!*yzz"  M�4��S�0iii���O���R������o��M�r���\,\�P�|bLzz:�����U�Vh���J%��k��sqq����,����*�O+zX�T'i�4���RbL|]K���q�6��o/;���'[�=�B�Q�J����/���t2zc����N��2�,��hp��)������-[b��U�~�:rrr`ccwww����w��fGeV���dDFF�r*�
iii8{�,�����w�}��X���|�?~����G������-[�D||<}����5����];����N���0�7�d���p��U�<t�P����G�z3f��y��h48y�$�m�fv"��@m�q�FQU����5j
X�lY�:O��������>E� IDAT��&�Z�}��a����3��o�V�0c�����_@tt4V�X�����p��5�����PRR���2���[l�������K�,a�M�4��������'Np�v�u���aK2�
�|?���4X�Z��<�8r_�Z5j+��W_}Uv}�t����_�>�����<�v�����:�>Dbb"��=����-[��>�T���j��]�b������?��. &&�F���������-�}�]�1�%A�j�����ZY{���&&&r�*[�jU�L������J%�Z-rrr��������L�>]�M�XZ��Sb��)����g�J�\TD�^���Z�����s&���;��CIII���7l8{�,+�lcc�=zp�W�Z������K��1����jl����>|�_~����/�l�9c����������#F 88���P((++C\\6n����*�
��o�eM�x6�����9s�krRR���/���s%`u:W:���o��&�w���eggc��}8v�������B,[��e�*�J<���5jwn`��=��w/t:JKK���?b��eFKG���Z�!!!x����g�������>�������y���;�}��q����n�`�8�������}���!C�p��""�233���ws%aF�i�H���4���1����7o����r��Mn�B��?��=(��P������DXX:w��Y�f����.���&;�
�I�&U����s����\���s�[�n�����������!�&
:k����]�v
:t��;u�{�wpp�j�KG�����JG���c��a������OW�Q5����{�<mTe888����t������NM���(,,�����-Z��O?��?��sgL�6��X�t���mh�����F��{��e�R);n�������������������l,!f���#
�988`����{7���������xY`HZ�K�.\�KS��D�c(rpp��	0t�P����N�c�mlldY+�=z4|||�b�
v�T*������Y�f����Z���|\����^q~��M�r����������������e�F��w������Y�f��M3�M�((++Cqq���k�����f*�VRR"�4q��������s`` �e�e+�����}'0u�T����`BB��=[�s���o��:w�,;'mll��];|����;w.�����s���q8v�X.��3�������Ln}^^����+T�A���'c�����	��[�4J�������OgggL�4	�5�����p{��������j��sg�����g���i��Ly�q�����LtK�ALq�My����yV}||��S'��Be!	!Fh4����x��71{�l�����6m�y�l�����

�Tib�tN@__��lLtt4���K6�v]a��W_!22R������k����&-����'���z���=$IGAK�t:n[�~�Lvh���re��4h ���*j�j�Qu���F�4��b��3�<#�����k_������;wr���.+�i ��W� 
�����`����V1�)-��������s�fbi���R�c�{��\�}^^���n�P����a���;���7o����@.c����8u��,� ���/:JIKx*�J��R:����&�I���Q����y��~F�������gc�g��.33?��~��7��F��"Yk�N��-b����XB�PpYe����,]@�����3gd���#-�*�8�~V*��>}�,�&5q�D.hx�����	

5�������#��V���j@��������<E����,�d���#�����'
�cgg�3f��l�����&�A0K�#���'�q[��~��{�}���d�!�P�!��������F�(
<�'O�u^�bggW�(���?	�@����;�A�x��!N�>��������dl�����WV�����sg��W����h4���Grr2�]����b$%%���~Bxx8�y��rGw��sE�Vs��%��z�)���!9Y?>,,c����������o_���J%{��~�:��P(0t�Pn{�-��>���Gk�L�Q�����y�<.mTM3(3��SU���M�4a�����GYzz:+��ty���${X�8OU��%v���?�;={���s��3I^y��Oll,��spp@PPlmmaoo�:����8M�4a}j�<@BB���PVV��/"::c��������0���}�p����h��97OcTT�����{�����l ce#��h4�������������&UW���X��+O-�����/+�f�����s��4i����Y*�
�y�&����V�q������x��7e�1\
E�~Nb�RY�z�b��N�CTT��#4�P(�����jq��I<����=�A��ngg��]��m�|�AAA�N�������n��F��]��m�����{����8��C���O���1���\�`tt4���-��=s�j+�r�%���P��q�����>�z�)a/��]�Vk����&����g��$H�:u�+?Tn ��d2�tH!&�j�
�f����=��7������D �Z�����y�d�?��k�v��a��l��'0f��#��C�����R*�
7n��'�Kd-_�~���'�.�+��yc���uc�uw��5;'Bm2d:��###�|E����;���[�1b��n�:ddd`��1��
�����EmT�<W�z�m�6�s]�������TS��{b�PM����J�������������t�����n����vdJ;�*��%�?�b@��({)q?i�pqq1w>�k�;w����j5�������:r�����@�&M�A���		a���G�sa��{�V�B\\t:v���=Z�UF���l;{{{�c�<���X�lX���f��{{{�������/�����7.\�O>�������!)~��.Wk���W��(..������#e�W�^���+������"����7o�E�������t��m-*�'�K�*�xU6���Ex{{��j�����kiii�y�&}p���^��
��>=z47h@���sg.hj8�
L}WD�Z�b����2$&&���_��r�������#))	����j�pww���%f5j�]�ta��222��g���W^��d���#�q,))��_~�	&`���]7���k���
B�R���1�����k2�f��^UU9UZZ��+W��'''L�:�['��,SK�����[�rss���e;;;�{$�
�Bd�����_���j��k��a%Dn��m���8����#d����8�<{�/--���gMv$�4GGG��1*����K�.�����v>�5�����7��}��t^���0��]m���F�p���@�4��R���}6l���E��2e
��_�N�N����c���F�i�Y�Q��������Q�/_6[�����{,�kbvTm�}�6��(j������C�q����O�r��{�V�Ng���c�!v\������{JII��O#�����.]��cw��Y\���"-����������s���G}�]�����[��3�����7$$D@1g�����q}����������M�6X�x1��Y��***����o�����������h4�j��v�*
n���2��k��Z�5��NNN��ee"MQ*���TRR�l��C������������/^,�*S�����m��_������'��W/l��
���6?�����K>�������/����w�r�aq��8�����l��j�[@��y3��*��6����>+G�����K��i��9r$BCCM~.#F�@bb"F�T*�[�;w����C1x�`��EK�{�������%[-'}�,-�ZU9UVVf�~���M��`b�g)1�)�}��]�����c��q���=!����%�<�|}}��];t��	��w�&�-))������0E�!���v�#�����+���-�����JJJ�X�9|||���O������]�����HKKc��O�f��������C���o��=���c�={6V�\itNk�6��PU�<�m�233�e��lgg����K�0Nz]��tu�1��=��M��1E�?��j)))�g�B___�,m�M���q��=���4����~+����+5��j���7����nNII	�����===1m�4Y0���3g��^;;;�+
�;J��n����c�����G}$�Re5}\����^�3���3q�D�s27�^e���!88�-�t3���g���?O�;6bG�����`��%�^�����������@6�������+�.�Mz.;::�2������"fU����m������k�������<Mquu���.+������+W�������i�P(0k�,�3�+7�����[���w����;����Je��A���@����� V���:b�!+���q78s���{gK��	!O.�\#�X�_�~c�)bccq��	8P��T�8"��������L^����X�%@�y������S����kW��������������W�����z��)��N�=t�PY�T�����}{����b��N�CXX�\����g��G�6j�j�Qu���Fu��EV�I���>b�V�Z����j���������es<������srr�-,��i��4�Z����T*������<==���;���*�
���Crr2�����\{��!���,*Ig�8�PymRAA._�@����Ca��]��u:��\�/��2���X6Ixx8��y��E�������3s���q�6k^{�{�[�nq���m��\���[���CW�\a��N�:Y|=;�+����ooo4o�����;����#22�e�4m���b0`�m����b\�zh��1\����E��5m�����s'[vtt������W/6��N�Cbb"�����3���s�����W�m�6.�:33��/���1}�t���P(���/�O�>��};��9�������u�V\�x~�!�QVV�
�����|����jJe�Ae�����1�}m���,�fW�!��@|]QAA��[��
f��!�@!R�BB,�P(0}�t��;��`��i���e��j�7�b�c���aoo�:���u���3�������DTmS������+WzF$�������R(<x0���O�r:'NDjj*{��_�>���'�5�������/b�����o��������\,Y�K�.�������CmT����Qc��W�j��k�*�
u��	n~___<��3�=L36��\�8 /[f(������-�.}=///�D�4�0�����-�v��2X��;�eY�Y1M�6�B�`�����U����u��9s��������rh���,��O������c�{��A�R��6m�����l����Jw@[[MWk���������+??��_��Tlu?'1�.�LIH@X���m�j����jp
z������]��J��G�����g?;;;#44'N��N���#G�e���3���%������T||<����'�|"�V(
Y)��t��:t��7�e�.X|��q�����_���?�~�i���[?~<���/n>���x,[��}�
lll��@3DE9��T*��o������|�2���*��w��%n�y����h���\���kd<B���b-!������u��T*�����=�5HG������1F��8���(**���s��e�O��@����y�f���Y_�~4���]WH'������������_�
�O���?~<�.]���.((�JNUj�j�Qu���F�������7�e��mK�����e�
��H3o�����Qn�pYY@�v��t:n4�\��������V,	iX'��U�!�G���u��#�y��������@n����7+�u`m5y\����^��������$~N��|��j6������2����Xr���}��?����W/�>JJJ�}�v�:;;�J=K�m�N���'����;������,f0E8��c�������g����*  ,��I������+��g�F�0k�,|��G\&sll,.^���4h�~K>�,=5�����p�����ELL[vpp0[�6::�����]v.B�1\#�T�s�=�=P�9sF6"�T���c������,�z]������:o\\\,���m��WUHii��I�k���3��x��Q�^
7�CExyy��>�>cCY��FmT��6�ny��(�������Y�L,+3g�Xv��v��������s�'��l:���kJ||<W�R:����4h��=+c����:������<k��N~s�fff&+����]��~1�R^� ���f�������V�^]ks�H��q�6�<���w��!\`���\)��$~N��������Di���+T�����e����xn����/#[Uh��[>p��y���2����,��R����=z���oK�)C�u@_�Ol�-%}��� �d��2z�h����-���pAs���0e�n�4�#������h�HM���By�����S������};�����9�����f�n��)S���$����K!f��W��M���]���� U#>�]�z�[�L�Fd������CuEbb"���O>���~�!�1�~�k����h6�y�����j��1�i`Ig�5PU����;�6Jp������4����m6��Z"""d#�'N�(��|nnn\��;w�v�fffr��!!!���`�TXX�,�fr���q�VJJ
��-����[7q������5:[����.�lI<1���Z�}V...\��1��$&&b��u5r��S�����}�m���t������_es����DEEq���s��-:��������k{Z�l)��T�4;��=���19�M��&�^�Yn\�|���r�333���m��1�(�t^G��j�I<��++�-K�a�m5Q��<b@��J��YS�qR��������XV��<111\{�P(0h� ���7";;�-w������BD\#�TXPP����������=HUxyyq����g���F������ub�Tm�p������G��Ub���A�X��N�:q����\y���E������n��q#���;���Q������qo���t��_Oi��Z���N���b������S�V�
��6m�d���N����kY�R��]�:u��eXEGGs��I���r������%iV������$��wpp�8�����B��_��r:��7oFll,[���`�������m�->|iii�:�
6��@��7o��#Gr��;�+V��PS^���j��Z[u\{�N��ef<|�_~��E�����������j5~��G�,d��-���R���,����);�-!~�w��m����={�����G�%�Z5��w�
(			1Y:�K�.� U�F����H����5[
T���������������~./�R|_�2�RSS�`�HI����B���K����E���c��h��[���������5�wX���i��(U�cPS���0~�xn��u�d����7ob��e\���Lf]��q����k�I� ��,��'����'����������

5;I���)�6+$$�h��r���[7��K]4n�8,Y��~���E�����+�����+Vp��;w���/[�	*�
prr�B�@ii)���������O�J����p�����gk�\��Z�������X������WB#<<��|�K��=`y{{�C��=��������m���/��u��t:Y��8b��QU�����gk�\��'��j��!���Y'YLL~��wL�8QV&�q��}{=z�-�_�s���Fs�T*������U��u�d%%%���R��>�+
��q+V��k����]��������
�0`�,�������?��Y�f�9�JKK��~�|�� IDAT���������G����d�&M�pVR���h���x0U�g�%&&��%3����Z�f�Wqq1������8;vL��6a����q���?m��1����I�h��ej4,\����:������������e���#�e�	&����\03""W�\��a�___V����o�>������q����zxx`��������w���K�.E����o_q�Mzz:N�>����F�Dvv6���agg�N�Z���t\�rG��2��J%�N���/"""��

5�]6'  �;�

�x�b���[,�K�Ra��=\��I�&f�������� DGG�u� )�B�!C�`��Ml���5����C,@�y�f8::b����~���X�~=7��e��F�y-�JP_�|7n���
��h�a�;v�[o,��}�v\�|�F���a�������2i�����X�~=z����c�r����bl���-��*
L�2.d����W#==c����+�>0��[�b���;v,�����acc��{��E�N���Rii)


X�W�cP����V�W��`��%6l���G���!>>�N����'�l��
���^b�R������_�����q��-6��9�����'�!�����_|����
�������_���'�������f���/�9*�zk��}$:�����B��������
6�J�BBB7"�����Og�5����8|�0�C��950k�,q�Le>[s�Je��������]���T3&$$k��e:��7&M�T'��=z`���,6l��r;(Y���X�h�����uk�t:$''s�+
������EmT�?[s�Je<)mT�~��y6<�c��a���x���%{>�BBB��Q#6�?!!������� ..o����VE]�xQ8�����\���O��RwwwL�:+W�d�"##q��y4n�j�YYY\���������^��+WX�:�J�o��
4���233e������,�C\�bR
���wgY�:�===������e1+V��}�Ba4��`���f��U-�g��K/a��E�����a��epvv���T*��l�a����t�������o|�������l��
��m�B����t:


�sAJ�5�.Wk��ko��=QRR�U�Vq�����,�mooGGG�T*�e���I����;�%u:������o�������%��9���X�`k?�����������R�Dff&�udoo���~��{����������-�	��m��gR^p�^�zx��7��W_A���{��{�"00NNN�����K��r����5kV���y�DFF���eee������kW���������8w�+Oo8�}	��_~��
q��Eh�Zl��
�v�B�v�������\���p�W���R�aaa���%@�����ys4i�EEE�����v777�qm��-�O���2:����������U+xyyA�����HHH`���]���o_����rwwGhh(�>����7���������<��u}���+����������`���X�`��.--������~���������F�|���&�N��u��������!��!�
���p�������������9s&�j57j055��\�������~�^Q�:����1f��=�Jf5I,�V��
WWW�k���������+W��������]�P�~}npS��=�-gffY�P(0y���\���n�F��'��;v,�_��u�k�Z���'J�o��.\�:�T*�,����;U
��T*�]�V\]e}���J������O��m'|||0{�l�s�888���?�������������P(0n�8Y���r��������-	i�����O���30X�����)S��kWqSZZ���J��d0�x��7�f��S����uv�����'��9NNN���O�q�F�8qB���t&K���['M�d�8���q��q���������o��:�}�����R�D�>}0i�$q�Y�� ��U+��1�h����on��97�XE5m�s���w�}��w�Ng�X8::����2Y��*BBB`oo�F�a����e��O=z~~~�V�Za���X�l�[322�r�R
6�G}d�|�����0u�T�Y���p��9�;w��O�P���_���������_|@_"Z�N����,������3g����LY����$�l�����{�h`����_�>V�\��Z�111��������0Y���^}�U��������R�11|_�uj���3���c���\��|���}{����6���8p����B*��k��JS(�>}:>��S�a������u�����7�(�R�>������s'�Y����'&N�X��sMQ(�_�>\\\��Y3�o��z������JHH�����r�Y�{���D��N��s����={��_?�J���?�Bdd���Z@@��W�90�����EmT�y��({{{��7;w���c��v�?�Z�l��?�������/�BQ��Vm�������[�n���WQRR�mwvvF��������{�qww��E��w�^?~�������=����������n��ef����iS�}�}�6t:�E�-666pttD�
��eKt��������^��>�N�:��(���}��y����{7���P\\,��R���@<��3�9�>}:��}��!::�d��g����g������E����r\�����AAA���op��Q�>}���&��vvvh��9�����wo��c���������z
�[�F�=LfCJI���1'^�v�����b���8{��ln@;;;���`��	������#88��]��o6l�=Z�6m���w�}��;w����6z�h��!����g�y�����<x04h���]�v���"00���g%�����;v����`��O8::�����v��������1c�p����_}�:������8);;;������7����{w�i�;w�DDD�����i�v���={���T��������k����sF���v��������c�����#GL��T*����A���6�s(;N�RQ���X��%N!��JOOGJJ
����P(��A�j�RY.\@��-+\�.++iii(,,�B���������|�PE�[YY���p��}8;;�Z��6��� ==:�������+|||���Y����������\����a�����-7peJZZ���PXXWWWx{{�a���nUr��M���re�w���HIIAvv6�j5������U=�������� ??Z����l�CE�A�t�u����e����C��W...������_�	����R$''#''���h��!|||�|L-q��]������_�dRTT��mkQ�T�N�c�u�J'''xyyY�WY:������>lmm��-*�
�o�F^^��|Z����F�����Q�F���)70_VV���t��EEE���������*|M*++����������b8;;���M�4��������|������J!:RT�"E��"�Uu��b]�u�}����zWAT��uYuY�KDDZ���B�������l��������z>����3�L�n��|���w��4T�+\��h���bbb����|~�Rzz��=���,+$$D���JHHhT���U�I��AE�V���z���V��������j<�>5��
4��u���+hZ�4+IIIJOO������#������MEsz�6��
��5�J�n����c-����.o(��s�����mN�4-���A��kvK@5��"\<D�x�p
���!�5�C�k���y[@sWZZj|m������6�3q:�r8�����m���p
������t:%I�]w�&N�hY��|��7���/���~(�M_ff��l����+??_���
S����W�f8:%%%)..N��������T�����Yttt�����dm��]'N�PQQ���������G�j���i��RRR�i�&������P���j���������`��zw��im��M�������u�����(##C�z��Nu�p
������3G�����=w!!!����5|�p�T�����]��-�����a��Y�/�S�N�O���|���������$��������t����_���h������~�q�������_;v��NI*������u�������:]/�������*;;[�t��wj��Q�U�������^~~~��_�j��g��y������'k��U�kR����gk�����&o���Z�l���$$%%�����1X��;�V�X�g�yF�N��NW��~��O�6X���b]�t�^x�Y����
�`M�y������:u�����S@�"\������7m;��������������ZZ�h��n�j�5e�w���~h-7	yyy�9s���������.��r�7Nc��Q�^�L�7fdd���_�1�����o�a
���i�k��F7�p�.��2��������C�1c�1�O5�k��r����RRR�S@�c[H8GG������q�V���s�)<<�����i���Z�d�Q�������Q���z��7k�.���hM�>�Z6Y�d��.]j�}�Q�o���UWzz�)8>|x��>;vL����������5k4d���
������[n���_/��f�:�W^yEyyy����7k��-������>\z������������[k��I�%���g��^c@}"\�sd�@����M��$y{{���o�������&I��k��N�����)..��i����k��S^^^������L����3�F�bbb4e�M�6M={���	�K$I����0a�f��i�6n�Xe�v��A�_��:T���s[Q�}��z����k������{�&I'N�����Z[�f�-Zd-��p
����0u�g���B\\�i\�f��c��F�VVV���<���XV6
.�K����>l�jr"##���������={��'N�0�+�w�yyy���ov�5���K���dI��m�TRR"___����������f-��p

JZZ�rss������0[�x��r)==]999��l
W��-�����^?����z�)���z���:y���������s�8���VVV��N����!o�s�5��t*33S������QTT����*������Vnn��v�"""�:r:����Pvv���U+���X�����<�:uJ���


U�V�L[�YY���B��]AA�il�m};��{������_��&����Z��x�����Ry��q�Fc��wo������l���F�VZZ��[�n�U�K��s����)�^������0s�L���G�t�E��G�����|�reff��������3f�GQnn����[�Y��tV�T~6��!C����O>�D�CS�L�3�<Scxp��!}���JJJ2����E]r�%;v�.��"�[����H�/��5k���j����S�N�4b������@g��eZ�h�l6�&O����i���JLLTNN���f��K�.��o������K����������={*����m[���W��WTT�i�*���Z�`�~��'���~~~����n��fEFF�����\.�\�RK�.���GMs��������~��U
HL����N�>���&�_8`����*��U��������k����x��Z�v����)##�4���0�%i��}����m���M����y�����j������������n-W���To�������������{�k�s999JOO�$��v=���F�������`�-_�\�<��z��e]b��{��|��j�v����7�|c����V`I��-[�d�9������f��]�V�G���~���K�v���3fT�����}�vm��];v���GS�]���|�{�|�r]s�5z�������\.���[/������
6���d���z������JJJ�RRR�p�B�5Jw�q�u�a����9s�����S*..��?����$=�������uI�(--�������d��T���~�z�_�^C��<`�����BCC�Ps��u�7o�n������D�������f�����Ry���;���rI������������=w�PL��9b{�����'O�4��B^^^�?G�t���5k�D��������e�,���qn{������F�����+>>^����u���z����y�fS�Brr����������H
8P�2�:t��z����<v����v�:t����;+<<����tj��Ez��wLu��k������L����_;vT�����Z���&O�\��j��z��7�`-<<\��uS||�i�A����>�H��7jV�W�����jz��f�)&&F��wWBB����\.��������[F���eKu��M���3�yyy�>}z�\]��LtW��kz��{�v[U���G�&M2����o4m�4�����k����|��-�������q�sss5m�4K*�N}���<7�m2���cK��9�IWgHH��{l�nL���[�������{�Q�N��V���5��v�����nS��=������]���_h���F�����_����N�S�����f�$�|�������3��>��3-^��XS�5eMl6�F��q����o;z��������OFm��5��������Z������3:����u�m���+�4`����3g�"fff���������5Vyyy���.��"M�8��}�����Y��������x�b�s�=��
{����Y���h��4r�H�7�NV\������@c��5��R\\���8�v�m�������'4s�L�;%33S�/�����5u��r��~0�>>>z��u������L}��w�����$�_�~���[��g���7j��]�������?*//O�����?���
0���q���|�M#�		�O<!�V�������}�vc_eW�5P��U��l���7����Y�K7�p�)0�����b�
�g�����?���;V�v[�?:�P������K/�!I���R�=4y�d]v�eF=77W�����V��{��1c<|�p�����I��w�m���K/5j�����c�1���#4i��J�"�k�N?�����nS}��y��w�\z����s����4e�
<��IR�6m��Oh��AFm����v�U�����L�R���GyDaaaFm���n+�9���;��/���^�u�]���*��SO=�g�y��}�J�~���K/��5Ij��u�����W���999:}��1����)X����n��v����5��7v�X=�������@_~��q�^PP��qu���XS�.�������{�nI��c�=�Q�Us�~�$�3�4�P�I�aoM�sw>>>��EEEn3u���_aaa���	�$%%E3f�0����Ku���ZV������$00��7`��������[�r��N�1��e���$�7�4vw����������tN��#4j�(c\ZZZ)�����M�����_�|$w6�Mw�u�)�q����}��'o��7�����W\a�O�>]i���~��tF���C5t��_T��}gUjzl����s�222*=��V�V���&�������M��U�n��}��q��.]j�R�����<O����m�)�NHH0�.��w��fg��WuNdC�����S�����X=��#l'
��p

^PP�`�O�>m:������������8##�4>7�x�) ��a���Lg�m���m����*���c������3����L���D�k���o��m�����Y�&��Y���L�Z�7o�����Vx&33S���MJdd��������s��g�1����z���Cs��1��G���� IDAT6���]ii�>��cS��;�8����������~�87288XO>�d�a.P����(��t��U+W�4�4#��39����GwGpp��u�ft����*''G����yUbccu��qc\��5�V���~F�d�v���L���3�:t����������Q<G����~k-:u��k���T=z�������^��7��a��y�9�p84m�4�:u��]y�����{�����{��o��q����5e�=���U��U�}���z�������2^K�\r�&L�`Yua����������T*����������2����w]����&�C�����lh���~���[�gm��9��m������?���I��p
�BLL�i��y��������t��;kW�5t:[			��)322���t��G�����u����������^�L�[o����N�2mCg������;�-����,�Y��Z68��J��o~�<x��~���@��,X�k��F#G�TPP��6�/^l�D2d����~��u��Y����>���\���BM�>]S�N=���>��y����4u�T���I*��|��G*��Jm�{}HNN�w�}g�CBB�>��<�����rUz�T�=\;��)��Y��544���k�V���%K��]w��n��������9P����$swS�N��m�\.�~��g
6��w��e�TyK��e���N�>m������������W����l6=��C������~kl�����/��B�~������c�V��,++��E��qdd�&M�T)����< ��a���Z�x�9o�X��z�\.��1C)))�����F���,+�Y�"MII����%�����)p8����f�����o�1�����\.�>}Z!!!n+*+..6�kg�3��{���?4�]�tQ�V����������Rc]XX�bcc�9�B�0�:�3k7�����_~�����8���S�=*m+v��I}��7�8$$�t����>�����CH������={�j�8�����
y�<j�"""4t�Pk���cGkIRy8t�-�h����?�~��g�����P_|��6m����z�\l���X]s�55E'N����URR"����s	�j�|���^�|�6o�l�].�)(9���k��������+::����j������M�����Kt[Q���0�8++��X��m���i\v�������g��r��7�0m{�g����+n��w��ic�����CYV����|��E����������4w�\IRnn����?����W��]e���g�-X��t?&L�1�
�3��_��{$66V#G�4����1���g�-66V��w������=���?~����+���OFx��~M�6M�'O6:�<�~�3ni��]�j������,+((8������|]ok�Sj���RJJ����kc����I�&���^DD�i|��q�������'I�[�6�k�����_�N�rss�e�Q \@�P��\����]w�233��{rss5g��w�����!C���v��	�k��nt����u��M����%c�^7W���z���4x�`���[F��g�m��I}���T9���WUi���i|.�Zm�����C�1�Z�Vaa�q��TBV��X����������o������*]��X��LNN��L5+�v����w&v��V??��c���Z???
4HR��hz��(X�����f��t�w�[�n������������u�WX����}���/��"���K*��1&&��v������v~��

Utt����$I�v�Rii�Yo�����Kw�y��{�=��u�V#\������������Q���B;_��O�>���iii�pm��A�������_������q\\�F����f			�qRR�&L�`�Y������u��g��o6�Mw�}��\��3g�Z�-j}{�|�[@C�����������J���a���?_������QLL�z�����k���z��g��[o��`m��=FP!���.��2����Ok��U�N6�g����i���n�p���yK��-[��H�6m2�����LAHppp�wnq�/���4}�����f���{������������m������c��uw��)��T��}�f�o�kh�JKK��;������]}���yW/^�7�xCiii������gk���z��g��?�A7�p�z��!��v�;k����H}��1����������Mg���;W�v[Q5�J�o~�������?<z���i���M�FV�N3�0�K�.n3��e�j�jq��9�s�z���6[7����P\.�f�����b�v�5��C�n�<c����s�t:M5�������s���t���ZV8�j��p�9rD�/6�MTa���z���s�N������mU�o��FRy�GBB�JKK�����;w��~���s5k�,�������qp�b�
-\�PEEE�)m��M�=���9b�n���JgZ������n2�EEEz���b��*����\��7O�=�����c�� ���4f�c\��-[f
6+�8qB�����}�Y=z�:���Y�F�=���}�]�����JJJ�����j�g<������+..��)S�q�F#�����3fh��FM*��Zs����+L_yyy�]�vZ�v���~_G�a�rt����9s�����ZZZ��N��-[��a��U��p~5���,9��3G_���v����`���+99Y�����~~~z�����g�K�[�I�o6?������l6����*�y��U�_��`e�������|}}u��i<x���n�{���q�L�
c����c����(�<��={�>��3u��Y���*..VZZ�:dt�|��'z���+u�]����������$��1~���������cG�����t���c������2�������r�������D���+66V�����w��Z�����+�t��4a����+�u�����i����(���0j�(SPW�����2335w�\S��ph����Zun��&�k��������������k�j��
j���������n
p��m��'c����f���R~~�6n�h�6���S�N��S���C�j����r�\.�V�Z���,=����iI�������u��)h��u�%�A������q��x@�����������7��2Sqq����B���z��������~0�EEE��}��J�C���p��L�����S���JNNVrr��&��L�����M���������|`�����3u�����u���[�u��^���>Paa��|N�������0�\KKK+u�I���O<Q����k�W�����W^��K�V�T����p
8P���S�-���[n�EaaaJLLTjj��N�BCC��m[���*22R���:v��~���L�-[�h���������;��C}�����j�*�9YR��o��u��q�t�����b��t�������?��n�Z�v�!!!�����
����[�/(///�}��<x�,X����W������[7
4HW^ye�Z������/k�����aC��,I>>>���+4~�xEFFZ�%�!���Z�p���_����yyy�G�3f�G?3Zs����#Gj�����^�n����/���m�*]��� 
:T7�xc���g�.�o��b��g�K�:w�l�.�W^y��������/�,�|K�c�����HAAA���T��m�oz^>|X�'O6:���{����OLL����`��<�����v������.R@@��������������\.�e��j��u�y#���X�RNN�JKK��-[�m����nz��s:�:~��N�<���B����e���������uy���9���L���W������k��E��z76���:r�����e���v����g�.��5K+W��T����;�XV����{%���$::Z�����y���x�����,�����Mc����S�N�nKy6�����kWk�A���S�.]��&�n�+66V�����Z���R||�����S
Zs���M@@@��>��������n3@������7j������Q�V�4b��Z�c��ph���JJJRII����t�u�U��K���R-X�@����N��:z����kg-W�r����c�����f�*--M���3����	@}����`����6m�v�����b�]�V/�����]k]Z%����^{M�~��RSS�����K��O���tU�={��/_n-��:z�����W/���v��i�6���h��YJKK3j
��+h*���4}�t9����@��`;�������S��w��O>)???:tH/���>���������/[�L��m���cu����f�i���={�������zI��E�����'�	�����{Oeee��g��L���m���K/ULL����������k��
���5n��];��j��Y�v���������j����`�g�������-�����kK�.����m��f���}{]u�UZ�l�v����={Zne�d�k�����������K�e�W:L<))I�}��������#:y���������S��M�6z������-@�>��S�V�������#�X�@��`����u�BBB��}{S��������V���:u���w�.oos���K������c�zjj�����*!!A����94\����6m������0�t%~~~3f��L��V�ZY��(((H7�p�^|�Ev�@�� ;�


������;[�.I������?~\���uk���7\233��CI�����.=���z��W�o���M�6����$���Zf�NHH�n��������}��k�.=zT999r8
T�����cG]v�e������,$$$���LAAAj�����G�Jt����nAA�$)  �2#c����b��Y��5�������W�TTT$Ir:�z���������'{�i�3��w����8p�h����Nv�]_|�.��b����m$���q��%<x�Z��R����o
v[���\.��V�����8�N�x��9��m�x���������U���9g�|���Av�Ut�U��VQ;�6>��4w���j�*-Y�D��
SBB�N�:%Ir8r�\:u��BCC���
>Y4=�����&^�@���h�x}M���j��Zpp�����<W-++K�e�1s?W���>f��!IZ�r�V�\��L�������'����^j�@3� �5�����h?~\���
		1�*�m����Q�J�6m$I��H������Wll������:-I���O����|P			�i4C
2\���={*%%E+W�4G.((���ki
�����{�n�=��BBBt�E���#��w��=��}�t��a
4H�������q?����U;�����k�^{�V�\����J���
���+�����zHv�]�TRR�7�xCeee����=��c���q�4c�M�>]�G�VII��.]*???�x���:�
6\k����y���=[�-�$��;�����u>>>j����=���8�.IPaa������>�LR�����j���i-p&
6\��.]����_WFF�JJJ)����)S�(''G����9I>|����'O���K�����l�e����k����U�����L|||��*��v:�p��.pF�k����"\<D�x�p
���!�5�C�k����"\<D�x�p
���!�5�C�k����"\<D�x�p
���!�5�C�k����"\<D�x�p
���!�5�C�k����"\<D�x�p
���!�5�C�k����"\<D�x�p
���!�5�C�k����"\<D�x�p
���!�5�C�k����"\<D�x�p
���!�5�C�k����"\<D�x�p
���!�5�C�k����"\<D�x��Z�+����Ku��q���4h�l6�ui�6n����W+''G�Z���#��Kc���XK�,��;�p8��uk�1B			n�"��_����GM�
w�}�����e4C��m��MS�N�$���j�����q�����I�&YVWm�����������]�Vk����?�H����k��y���T@@�V�^�U�Vi��	��������e��n�*???�V����"\��z�JJJ����*00P/�����������^zI��������[of������������|�I������Cz����'��o�����������eK���W�t��!=��s����5x�`�������w������T��3�~��geggk�������$��o�$�[��}y��.]*����n���6k������*���j����$ooo#X�X��K9���u�u�m��U���woS�k�����b;��[�*$$�R�[�yk5�GII�l6��Y�<�#G���tZ�������)))����hS=$$D6�M��UAA������sg�����%���(**��?��}����+�T��-�K��c����@��x@�z���@sU��ZAA�|||��m��m6�|}}U\\l�[U�_����G�*�Gff�~�aIR���u�}���m6�bbb4j�(���i�����q�f���7�|S-Z�0�����{�%M�o�i�54]������7�J��k5q:�r�\���*nk�����9R[�l��M��t�R�3������j��6d����kJJJ��?��Q�Fk�|�y�������29yyyu�����2���������WR��4���>4i�$������_���s��}{���C���U+�z���-))I����)�U�u%������������8�t���.^�@�EG*���[Zxx�\.����L���l�\�*�.w��������\����������������%Ik�����I*?�
��!\k���$�������%I;v4��l6����������\��'�Q��f��Uff�$),,�2��������W�\i������l���������5w�\%''���z��)��e�����]�V���F�v��i���k$i��������������2c�p8���(I����Q@�V�g����G������[��[o�[�nJJJ���[5|�p�n��X;k�,���G6l�o�a����Z�\�R_}�����v�� IDAT���+W*''G=��������O?����5p�@���j���Z�n�4r�H��f�����L
2D������_t��u��A�{�6��y��p�n�������Y���/�h��u�������u��w�����i��=���3�[�j�g�yF�g���E�$I������;5p�@c]�^��w�^-\�PR���]�v�w�a:��g��������_H����t�Wh��I��l�:4o�={��$�s����.//O999j�����r�\:y������n4������(22R>>>�iIRzz�������@���_�,��������Y�xl��U���C�����{�J���3\x������7�t���.^������7�y����� Y������hk�$""�Z�$22�Z���?�[��`*!\<D�x�p
���!�5�C�k����"\<D�x��Z@���W��%����]���|�J�.Vf~����������6���%�5�f��}9���*,u5�]���UT�4j��^��w�.m����TT�T�`u�i!6B��@3�tI�}sP��E�)9�R���`M�
J�r�I}������m���[id������	>j����mr��Zm�9��O'4m��\�Y���p
��t����,���I��<-��i-4Il	��|��	k����!M;�*���:4��c*��Fe�����.9r$�C��d�����0Q�������4�K����yQR���c��!�:4z��.[E���N�s���NU���U�i��o~U^��XW���h&N9���*=��Z=g~�rf��<X�Yg+s���O��0�:h"���x�F?o~�D�t�(�ceO%g��Su��T�����%oX��&�w@�	/�"�.�YP	Q��(����;�.,[r�Y�=R�e�\9�2�	 \hF&^��Z:/�������S�/��n@]*X����m��k��T����*�	���t�k�����d�u���f����uX��>�_����
�RY���J��y�d5\%��	�s
�q�$��Z5����
j{V���"=�0Y�m��N
^�������k�dok-�:����wf*9��������_�R�Sa-�5�kK����R���d�$����h{J��l�����*.u�)���>|pI���4u�P��@�4�`9�YKg�-����e@@����:u$�HE�N�x��
'���C���Uw����78����z�m!I�����o:e��r�'w���������h��|���c���8_6�`���#\h�
K���K���7[���f��vM�<�Z����9�R��g�pz��G�[����MW����9�����G|�;����M	g�41�����W����*�5I������������k�F)����`��}�a�o�|;
4�eG��7�i�y���
�@�p����e��Z�L���i���������9���7��=����ok�F~}oP��S���
��m�����+����eo��4v���2�e;2u8��Z�����yk�|�<���6����h���hq~����v�JK�IN�u���&�U��IR���l�n1�Y�
�T�k�$���9*;�I��'�*��=,F>]�(`��9�
!:�����ZK��),�����
�n-U�c��	#\C�R��{F�f������g��.��~
����}��v�Z�����;���;�<�.WI�'�(�#����J���vC@c@�@r�����f��g[k�fW_�R?���S��)o�M����.�@�r�����o�q����w��r���"yy�O(�o���v�#m�u��<}J����B�0W^�:X�
�kM�W-���k}�m���������)���M�_��t���)X>���+*^~�����eo���`M���lQ������t�*���%��:h�j���������?��+:�W/�W���m����� 
�j-
Z��$�6�#��^n+<W��s��*���Rv���6k�@U~'��U]��+��Z�RL��:EZ����4��H]I�r�t,�X�.>,IJ�)QJv1�kh<\.|?�z��%��C����c�����&��z[����5�&d`�P��
��+�������Y�
Y�MRh��.�i��n�s?��u���\��C�q���}�-kRR���V��|k	�@�4!6I��Q��1k<��m�=�c�!*�2s��p�
���9:��x@=s:�?{�'Uy���s�n���,DT$k,�%������<������D�&1E��TC�&{T@Q@����e�]��:;;����c�3gnfwg`����z��������N^3s�u������Z3�/��t�nS��bhT��B1DDDDDDD1�c!����N3��&gX�����e2H�S���s��b�� �������<�!���P��9pD�&���������
��
).	�������wu�O�y�����	�I��	""""""�Q,��fn��yw,����	HK0�l��B+;��I9�8����YM�k;T�
O���o����u�5CV)Lfj��w��p�|rW���HXv��t1ADDDDDD1�c!����NN�����x�����cp�@����e)�N6���6l���z��>����a���u�)����Z8*��A��qH����,	b����L�-��&"""""����8w�e��V�?�o��]8�:���F���nw�-(���{�h����$�&��I[�!��\�[(�b8h���H���0O:GLi����&"""""����8���+��Ek�SL:\��GasD����dFY�w���>]�(:��i��5=u��=����bH�G������������K��y��Z���
@e'�x���85����M�c�]������V1V���mG�u�(PUX�n��r7�C'O�`�)���/#n���p��ZJn?
w��f""""""�u,��S���B��-�O �P������g�_��]����(��jH.���@�N�
cFL%gjkg�j]�������b�kDDDD�����b�������6�x8�YQ�f������F�#wCc2��������\�v�_��.KDDDDDD���5"""�q�oHF[p�`�����
�����k;Y\�h��bdL�i��PHYf,��cJ;���;������(V����O��@��5Ar|d���U��7vu*[�gw#%���~dE����`w�F��}0�d'���0��$X�����[.�F%Ya._ �CJJL���l��?8���d���������b�� """������1V�Yq�H4�������p��4q��UAC{
6�����5��k����C[���6d����
�9���1���)0�W�n5��snCaa�y���v�#$\�@��]DDDDDDk8����hr��;�)%����x1V�y%�.�
IART��<�o?v)�Yy3VU=yBam��jD��t9���'o�k����XtT���-4�NF������0O=_�Vz� �V��DDDDDD�X\#"""�2��bhTs���~��J����k���,K���
���O����<�����%�h��K��$$�����^��]�9����dn�e�*E�
���=�N�!9��Y��yx�.KDDDDDD�j�W�DDDDs�{�V�X\�*�"bz~"��D�n�m�"��^�7���JKH�(�g4�����������6?EU�([S�B������������c�D1V�iK�k�kDDDDDD��kDDDD����$�)��\���d���(�#�d�0���}��hH
������b����S����v���u�G��N��n�r	W�����B���!����d�h�H�L=O�v7��2���Q,bq����h�|kI>���!5<2=���Z�������u����C�X6�}�g�8H=����{
���9�	��`�w
i�����9��9�`H�����7lo>��w���t;������(V�����������D3�J9�RO��Q�?%
�~�|�\��.J��{�67�:X0��5v���9�����l?�:����v`h�?U���@�kt����;^������O7�]�C��������bAt�i!"""��&+*�N�oq`���*H���D���Xt���8#&������y��Y�3���1|?����{*���#t�!�aIwCU���'=��-��� e���	�`��(]
�{�;H���`���$"""""��b��8�gw��
M����q��U�r��n^�����Lam�~4���]��DE�}��AC6���X�5Ul�1����}��t7���SU���kz���j��DDDDDD%,��#����jl�����w��
���p�+��.�-N��k����/���t���|�h*���'�{����v�b����?���c�b8��M�<�^���w`���0E	�kDDDD�D���?~���!��h�u����s�T4e�!#���+��F��<a.;�F���R�v�.���E��l����`�g������s�lC�r�����������5"""�q��O[`���i�u����b8�$s���k�X\�1,_�]d��\v�5��j������.�as������^�z�>����2���Guz��$��C�J�CDDDDDD%,���v7v���u�����=`�^D��
��an%��A�)n����N1�����-�
Zkz�^��3����)b�8Cz�
;)1]�JJHCDDDDDD%&1@DDDD��������H�b\�CFJ�Q�F���D��\��!����A�(H����
� 1.����p�n�%e")��L��/����������	I����d��L���l���3�-CDDDDDD%,��J0mh��*1�f10� Q;omW��k�������/h�K\���"�_q�|�������U���CC��*�1x�u4H�P$����I��2�B�X$��f�<���lS'�fXf_&�������(J8����h(H���Q%XH����Q��]�}�_�!���bzm�������Q��_qN9�]�
�v�}��7V������+L�d2�%�s Cj.��) :p5�$	�W��u��������p�PLQ��FDDD4d%�19'^�h��T�P/���d������>�.K����6�[[/;�j�$w>H�D���,��L��p�NH�@2*`]��~�Rs}nI��\���o�
����n'^�j_��""""""�cq����h����|�����p��1��������}|D$��-?Dkw#� p����A0Y�g0�Y�B�Y� ��2��`@]c�f�*�d��G���{��(E�kDDDD�DqF�~N����w,-@�u�W'��Y�
��n.9�����Q���O���Kf]���|����C�p7�������!�n'^����3zT�\�������J(��b�������"��5"""�q�������b�,(K������	��U,�]����7
���<���x��h���B�������m���W��5]6x���UA"T\a�h�u;_Gs�1���Q�k��p�p� �������(�X\#"""gn�:�b�W���7O��~��	&��������[Z�0���x}W;x�G;�b�>'^���v}��%(���M�W�g����s������
���/Z.�{��Q{�""""""�bq����h�����������b3'$bF~��bw�0�[�����X������:���z:�gd��Cu�A������Y�u]���k������h�u�z��P�|P[G��`����'�������(�X\#"""�qN��������T�O�p�yP�u�\�����v4�:��	�mn�����6:����9�zJ��V4W�
�����V[��fav�"��M�b��g�:Z��d�����\{�CDDDDDDA,���A���Q�U{;?�2U��q��G�9�S1EQ�u��m����=>��t��{����:m��E7��A�]��y���v���&-lH����I2`���j���-�W���^8�-i	�>$�F�<����.?""""""���>������s���Z���y��Om
���k��f���bHb2Ft�0�����\���n&f��):
����SL�M����-��w�!�^�rG���2�����a?���3e�����
�#��7���Y�=�.������!Z&/�!}��F15"���`*=KQD�#����
�=b�����Y�/�c�[�482��mh��
�c��7������daK�mA������PU$�}�/A��9����pa
��k�����g��.����x$3������&1DDDDDDD��V""""���A����?�2M0����K��!:
���:.; 1.��R�1:I���>T����%�������S>������9��ECO���)Y�E�kDDDD1���b�^�@p�#�b2`nQ�����%p���NV�X��Em}���`5Wd*�
����K�T�y�/���:�P���[�~��b"lL�g��Q��f�!""""""������b���9�*PVSl?��eQ^@��� ��s��0��6����/��f\��a���1>�	@�P ���\��u!>��WB�O�~�2a9�1LDDDDDD2��DDDDq.YEM�C�jbvp?���l�7���:R���sQ�'��4�B��-�k�%�.AZR�nG`r��X/����Omk%T5�"��2$e"���a���@��8""""""
�����c�l�����������L�:U�6"Y��v�Z���N�%%%���+������������Q[[�����b\v�eHOO��Q�|r���c���2$�?%M��%�RQ���ohBu���-=U>=����1F�����}8�t@[_q�Wu��s.��W\������N�����`��}��Au
�iH�8$\v,�/SDDDDDDA1����k��w��<�����7���������~���_����������f��������������fm�s�=�5k����---x��w����vvQ��kC�*�I@V�Y���t+������)@u��y����Y	�pB���kmf�Y(�����N
�%M���S^�
F1>����7"���`�w
����[r+�����EC�v�=z���*f�������Z�������s<��3�?>����@Z�f
����/}�K��W�
I����b�����������n�	W]u�������SO=�g�y���/�wIDDD}vY�*9.����`6W��a�`CerS,�z�w��:z[�����O�k
�I��#(WT�'&�;�s��sg^,�"��Q��k~
|�1}�,@n��o#"""""�(	�c�����CUU�r�-�Z����R\p����������Crr2���zH��WX�l���PQQ��s�INN�VX�c2����������")�bYJ|p������[��������w�����������/C9~�Yn��5�<aG�*
,3� ��R3&���&���M��k�*�#�Tr�v������JDDDDDDQ���={� %%���>�������|����f���c��0�|��N�
��=b�L�e(��s.Q$M/HC����h�\���SX�[Q��H��q��v��]oj����� F;��x���'�aJ��� IDAT\*��������+.�>�,���U?��/�"�T<G�V����4��DDDDDD
��*6L������<1���t@gg������y���>���]]]B�����O?
EQp�UW�i"""��8or*rS,b����8�/I�1�X��U]�g��6�}�>����s�vOJLG�]/"n��b
`�w5��zJB��/����9i�N�!�?��]����aw�gb:��0f�hk����,EC�� >��O���6<�q$6�
��� d���F����;�|�	���N�_���/��^��'"""������_�`��
n;�F�X;c�[	n���~�]*T�����^:�
$X�t;N�dI�e������k���F�5A���.�[���kx�����Y�@m���P�n��������p��7��T2W�v���e������(|�%���3��;��3��Q�c�
q�y�a��mx���PVV��3g��VYY)���4��7��-V���1���2z�4{e'�L3��y��7���P�>�d���F��B�=Pt��F]�m==������G���.�93���8
h���O�;l_�vl��>0b)[�G�@q����Ofx��x��f��c�7u�j+������p?�������d��pg�����X\\���5Rw0�}�����;����>
EQ��c�a``�gQ$�JX\h��#pF����p�Y&����'��gI���K���3�c�)+��-G�i��rg!;��X��e����,g�z#r
��O_���=O|��Uh�:*�"��3M�6�6���k"""""�h������d�L&���uww��������U�>����d��Y�X�x��% S�LCD4�
��o��S�>�7�5�<Y29��$�wC�l8 ���)�]�X����zz*�e���l~�~^
���N�o����|��!�����Z�>��������^��m���������
��E�h��W��9F�NF��t�6���Xm0O�'l"�����&��;R��(V����%IBnn.:::����b���0i�$��(?��&Luu���=���8�)��j��>Q�U����������2/3
���I9��ia��qj��7 +��WVj��r����n�������SuI�jZ��Q�:�	�;��H�`.��-�����DDDDDDi1Y\�3�8��b���Zlpp�7oFVV�Oqm���x��|
a)))(..FCC���\���PWW�����d�4��������(
����`.�E������;��<��(�YL����X��$�w�������_*C�9f��RdE���i���]��[���]���c�D��?���r��p�9��\���u���
]�������"-&�B���^������W^��fCZZ��_���^�u�]0</��N'{�1��n�����vW_}5�x�	<��������t:�����j���_�2��r�W�����0�|l��uuu(--������#"""���N;���2V�i�����$MO��S�p�kOmj��O!13��X������j���F�	_8�a��s�����e�L�3�GS�Y,��T�^����3�"��������1f_���b��XNN���>�\���� !!��z��hf�������GII��s�9v�/��"��y����������3�r��EX�v-^|�E��d�������}M+�ECu��kmbv�iYp2$�e�c^I�V\;���I�����h����R�u���ue���GB����_k�O�*ZAc�O1MvCu
��ZS�tqE@��`�����o~���N8�Ndee�l6���$	+V�@oo/���|r�l�2,]�mmm0�����$y_�L&�x���������UU�~"""�h�9o�4	9��W�n���2(tZ�PQ�E[_|�g�D������[���B�&f���%�FT�S.�"B2Y`*�w�^���n��������d\�eeff"??����l�[Xf0������l�����hD^^��_����(�j>G������oHFGp�aQlZ��
�� ������!��p7{�Y6��W.�I��8��yS�p��t�;W�f�C�,E��(�}
8d��9����t:J����='K_X���-����mm}��k ��Q�k�j���� 
`_:�f�P��$�����|����q���j�q>��z3\��t�������(�X\#"""�QG;����x2�N��z}w�~$&�O�+7���
0�X:�
aGh�-��5Cj.��T]vtF�	�{�#��(S>TU�o<��v���S��Z�G��K��� ����^{���y""""""
�����bTM��v=1+.��2�#��F������M_���4]6t�����BM�*�oo��>�k�3��!��U��=s^��i1VC���c�kbP��W����6����g������(LX\#"""�Q����>r���<�1e�x@�N{o3*��h���]������-����/���d�o��hS���+�����P�a�������$�?zr�Q1KDDDDDD!��Q���E����3�`8^Dp�4�8|7�������o���(���3������yk�g�=���1�C�gD���%�����=�n��KmD* ���X-&������(�X\#"""�A�67z��'}^�k����8m������*�P7�g^i����@�j����	�"c������j[*�����<�@�mG���kDDDD1���[T�J2#%n�Qu��������{���������0�X:�
aG�*�k��Cz�7�^[����Z�T��U����IQ��o�aKM�4xG���Yu;N�)�zcU:\�[���S�a6F��A�l�����������]6�
u��y���>?h6��_I`#����d������Y%b�������B��^yQH�
�x���ru><�������8��{;���=��S�?���wy:���VQQ?�g>m�O���Q]G����l;�A[/�{�.zE���q�#! )!�)��X&� P����b9�O�p�.��i����������(�X\#"""�2��b�;��R�'��
�gK+���*�N+��?65���_�h�v��w����SC6�_Y���������;B�H�����5	�x����Td���Y�
cN9�
���qo�i�L1CDDDDDD!��Q����M=1�C���NnS�����:v���V����1�9�"��=����~����x���h�f_�!|�������W��5L��&��j�i�o�F�"P`����'�-�}�J�!����DDDDDD,�E�������b�����G&�N�����K�~n�����8�k���O��������58���C6-���5�1�''WUa�{���r�|�����_�$g����Q�=�3��!��H���H�����4�oD�7��dISDDDDDD�%HDDDD#�j�;���5��][��N������	<�_�n>(�4���=>�X%�C�g$d�DH&�.{rr�' 35W��=�v���6���!��k����a*����Y�s�������("�
����(���d14*��b�X��x2����n?��
y{.��:��kGwx:.uc����P��v���P}�����0O^�����
DDDDDDn,�EQZ�I��b�g>���e$�{HKn?����
���.���
�c����pH�;�L�x��0���kH��{�C���p�v�n���Q��~���#Sr�a1��lVA$1x�S�$�F5�0��Z�kw��Q�,`��B��Tc~h�k�Vs�UmK�
;�������e`��������(4'�����B���H�7�a��	�������gd +�,��:J
��b�"�o�[����+�N�2��d��������� aV�|1<�����m�_��!)�s��qr�!]����������5"""�(z��V�����_�������:j��8��9�F��}y��f��(WS��'W�MK�C�Ln>�]Rr %������n�D�����]G>�ag�.������r[�n��kDDDDQr���
�=b�/�Q��i�+�������e#�����LD�%�N?
�9��Q���H�2w���f�yk�&�O��� �G��U/��GQ0���p��m��G`�������\��n��DDDDDDJ,�E����G��d�k#;v.J3���5e���b\<#�'w���H����������a�2��q�����)��+�kS~hFB�%����Q�L16�U���{�AU1�
�6>����tg�Q���FDDD%
�14�� ��WF���EI���yH����:�t�(��u�=HM�-��$H�����,�N���5��7M��$g�
W�V8���Y�R;sU����0��kDDDD�$����u],�����t���g���#����x����I���)S���uc���/�]4�Z14���"�*�/������bhD�u?�mDDDDDDtJLb�����"�0���v���t�:��d�a_�
p��k1'-1.��^����8{�������b
����zDy�`L���!��/��/��{V�)�
�u�O`6�,������O�H�uAn;c^��f}���FDDD%�MN���1�W�������|:�X\�9u�G�?���$���������������|)<9�y�`w�����b
`V��d������P:�����N��B"""""��
��P""""���D�?%M��|a.R�?��*���zp��2E��v�v]�?="�5p��[k�+���d�s��q��W`R�1������]4$���1I'q""""""]_��XnY�����b��E��q��������@Q��n����i�N�zV�Y�Lx�-��u=<�"A���_�/��4���&,�z��k����ER\2��������T�r'�a"""""":E,�EQ���./��s���3�p�e%����0�b�� �Pw���.���*T��������e�H�#Z\�3-�3q��>�WS	���\P��_�����DDDDDD����-DDDDc$	�M6k��4+���i	|�x�]�=~�Z�k1�����^m=�h�.>r�1�n'@����L�4�d�v��J� pf���C�@��<�|X�\G�*@0��TS�\�-��&"""""���g-����Ht��;�pJ^k:E����N�����j���e;oM����	����|��:a�</�T	x�d�=O.��+����#���H������v@���f=�$�	���IDDDDDD��W[DDDD1@?��8#N�����X��H�:aU����)�g�2��n��"���������EU������_�������3���H��%���-u���J�x�}�����HDDDDDD'��5"""�(S;>�J2��Z�I�Gw���"]qm�!����e)Zj�j��
f�2��{�Z�T6����m�������W?���f1��2�_t�������"""""�pbq����(�:�]����0�bRL��T��ZlJ>6['�d��C_���kL�3"]7&���E�[v���J[��G��f��Z�Q�P���r���� ����S����]�;j}�DDDDDDZ,�E�~$dn�q��x�g��9�;�~�}
�6�M�h�7�9������L���]�����]�����raGx(�P:�uC�jk����m�F�[��^�.�)��F2Y`�.���$�^l�sCDDD�9V�	�/"E�*��	�������`��.fBB]=�kQw��{�YI�$��f]6|d�yk��l�X�:U�=�����[�p����k�ae���]�u�>DDDDDDz,�E���V�����~��)��;���09n��ct�.��1���K]g�FPR`j�i����2�%��F�|o1)�,���Vsd���;����������5"""�(��9�whET�:`�,��������B������vu�g�������k�u�%�AD�Q�+r��O�e����\�wj�[qN9���c�L�AjR�+c�����R	�|���kDDDDQdw)h���]E�(�����p3�S@�������Y���������_w,/���3PU��v�E����m���e,r�;��,�%X�p������.����f��T[���tDDDDDDZ,�E�1�H�x�Y��9�J3t8�_b��������\�P�/�

����x�Z�8��{�~��W���� !/�P�����N[#X���_��HK��'(������E����CJ�����$"""""��bq����(�|FBf�E���s�}6 ���i	�{X�D��w�+���k�x�7x�������3���������c�t���Zu(Y�a��LQoXR|
������,S��f�_�eP#$C�g4d�A]�������B��5"""�(��"z�Z���}WF��6��Q��W���8��k������{�_����F��?w���IL���;o��7�"�RfR�L����p���A~F�O1<;-+��yE�hd�t�2�#4������(�"�������������y�O��y�Gae�������@�������y�j�c������t�����+���Yn���H�����������w��{eY�w��C�������\cq������(|X\#"""��!���?m�}�V��mm���9�jo'���u��@���7J���X��4��(��;���n���[��<X��y��+������j12�3��Z�T��)+n��9g>���z��(?�������NS,�E����go���b
������>�m��n��R����@�1sj�%@�bttrP���"��(f�J�7!%�{�U=�����q�UeC��>�(�[���176�k&���������^�|��SU!���@DDDDDD!��Q����

���T���f�y;�B��a�w�
�5���]����,�Rzc���8�5���K��v�����P��Ov��
	��T��o�c�$�
QT���k��-��`�1o���[�I""""""
�����"�{���{;�<�
��d���C�{5P�k18S0o0�E`�s�x���o$oWYPz����~��]c�Z�e����Q�������Z�*�vg����������Lt�GC�y�QX��FDDD{����]�b��t��9o�d�,�m,�b�+a*P��
\�_��_���zv�������Y�q�]v�	�yk����L�����-�������)��FDDDDD'��b"""�����[oa��-����$I����y���K/�V��PA��es��Q�����������\�Y|��>�U�`�:�3c���$�����\k�v@VT
�����v�����]t����,_v���b8$�����)?��k�P������v�s��)J���sMn�0���""""""���.	�G�}����n�Z�
p8BSS^z�%��G?��C���Q�$Z�{s;���1��������C���SF��|
��`��cPu���4+�kinEEK��w�T�5	����0�,b����E�l��b8d|;����X1e�,�:��!%k�v�:l����������EDDDDDD�"�wJ���h<��k���?�n��)���hoo�o~�����i
�iy���@{���y� �������Ex���T���$ g90�-11:��0�9Zf���To���N��n����oo{�)�b
f��^|7���������Pl]P��g�bqm�Oqm�.Y��/���[}b�s������|�1@qW,��Px^Q��l6<���b����!�\�n7�l
��+�%t��� s��� IDAT��3���C����H�����6�]�D����d}E���8���EZAf	Jr���eg��}�{�\��0�@���4$e����FL�0S��n:EUt��pUn���_Au�����Y�7=#�������(H�{LDDDQ�q�F����a�TUE}}=�����p�|kI,c?����,e��<<�p���(f�+yH�#F�#����Y��������];��ZD�PQ�tP[i�r,�u	��Su��Cn������t��Q^0]���;��Q��!�T�
�7W�a_�
@����An��DDDDDD� ""����ao�G dYFUU\.>��3455�`0���K�,��9�Xd!Mz�	?��OnhBm��E!�Q���sp��u�t��=��8���	�J~,FON�@��@��������t1:��d��_��lxrC�%aAi�v�VGozm��zR�]6����Z���9%9��m��
Y�=Q�>�CC�o�~����c��H��1IDDDDDDbq���h�������BOO���1y�d$%%i������l��k�������c��]�2e
���N$'{��S���_U��>[	�S�Y0�(���#/�[8:i�8�-��91��4Xc��	@�y@�}@�R��P(H���p��Y�������_;�����-��%��P��
�=������/@~(~������v��^���4]6��c!M�Su��2i�,]qm?���J�>���bhTn]"��5""�q��v��w��{���sF��`�E]��.��V�Buup��$IBoo/TU�$���SYY��z?��O�N���j�5���d&�u;NQ��~
k�	Lz��: ��\&�WG��m�P5 �����x��O���0z7���><�a��T���o��W_)���P��-���7�������k����n���#M��N�h����v�""""""
B�����(��v;V�X�w�yn�����vC�e(��5k���{�����(�|T���k.�CCCp8p:����>����������5v{��3��B�m/P���������p��IF e�s3����^ ~�P�G��.������b�v��lj�RCK��V�?]�	/��P=��9��baG��<a�v}����N�13�����/�������(,��/��2��*���044��	�����!(����F#�V�p�����*�v;\.E�,�p�����PUmmm'��������)J�������z��F%����������_y�o���k��]�
����0���A1L'IU�4{�N��������	i��b�����R�Y���h�!aG���/� ~7r`�%""""""�/�W`DDD
�����ah�4=EQ�p8���\�Gy���N��pN��og���p8<����W���)x������
���#��U�����H9��>z?0B���&���������:����+%H(�Vq-��[�d���;��n�����\��u�c���a""""�Q����}�Mn��7o�����>B$�<���7c���b*���5""��s�N�'E#=�UUn�f���������o��?����=a41}�t���h1y�N������������'��`��k��q�L�������HI@�/����e�&��} �R�]�k��
�����	9!�����"��\�]��b���&��������f*�|���OU1��sH���b�������y�f�]�V���p8�v�a�X������"��=���q���������?�XTT��o�Y[��oCww7L&��������oV�^���GbjT��Q����X�p!�/��]=v�O<�`���(//v��7�|{����j��g�-�c�kDDD1������5��|GG ++?��Op��a�X�0y�d�������G||<|�A���XE��`�����S�[\��"���Oz>�#K���Y~�]��^�Y}���9pi�&��z�D��B����6�`�.f���J[�Cq�`�v]���0��*��O��i������M�����Zl��������;1c���u����g�1<��!�sw:���V��!<g�$UVV���CBBp�����c�=��J��6m���/�����N:���p�\HMMS�X\#""�q#}�n$�'��$a��iZ�����r��";;������O�2?��O�N��C���
iq�� �N4�d]'F#���y�k���7��k}�����CA��V��-`���w��������q��/I�3�b��	��Z{O3zm�HML����-�F�:�����Lc�&"""������������A455a``����_���x���Q\\,��+''g��rss�PL��y3������rU\�����+���())�������4a'������
�m��;��.�P�cq���(������O?��h��=�h<����d7�$��[n���?0�L#����y�������L!K��w�%Y�HM����7��;g��Y��@|��H��9��
����@���|�����.y�.K���G��i���~N��G[���#�������Q��������%e�g�p�i?���D��9����|��3�0�i������%��e�����CX�r%����t:���/��?���V�����a����������s�=�5k��1�,����
k���x�����$���QUU�O>�D�8�y9DDD1n��HHH��h�
h"�������s�=WL�h���8��3�����F���o���F������n�������WX��(y@�FO����@���5�D���c�j
�����o�����i4Q�;E�>r������{*$H>�!�4F��5c�<14&�>��C�������p�_�����__���������?��3������H�X�JWTX]�Ew]WW]�������}���}�UT+`�" E:�JBz�L��?��3s�!	)��z�r�|�L�!e�=�sN���)�f�?���6EQ���?��{�v��s�N��&ti��o��<pJ�5�?��}����ccc���{%�&D��+�B�qQQQ$''s��a�f3.�K{��(JP���k�!!!!��
����y����{7f������FQ��p;���8P*N��R�fi	������G��OC������Q��!�(X���	H���s�x�FW��T9��	|{8o-=�,BZ������b���>�k�m
���5@��]I�n�h
�]�B!�h��"�K��co��gW�6\���o�����cL��~�%''���Bnn.N�����1K����<����w#��i����Ok�����c��������������RZZ��nGQ������w�{AA���DEEikEEE�\.��������9z�(v����233�l��{��h$!!����={())!,,������[7��j�x<>|X����� ==�������"������2-VVVF^^�v?22��������$++���b�N'���dff6j���������'Ob2����iii��je����o�������O�F�t:�������"�F#��u�W�^���
I�	!�m��m�8|��v�d2im}�'Of��	A��P�{���o���%K��p8j�`���BUU�\;M'�B6Kr��C��G���(�����
=�'�*��e?�A!6�D�������������`n����k		�hiJ�Xi����<�����%%4�Q�_��b���]!���T��������jn�s�I��$���\�o�|���7w}��A�|��$%%�l�2�Qu{������>}:����q�����������o��_�	�{���K/�����7��3�<�������{������*{����������[:thP��ONN��+������j
�|�����Y���?�������OY�z5�e���������?xnuqq��5����[A����:�M�C��.Y���k����		a��aL�>�����5�
6�����������!C������L���,Y��+V�px;����f&N��u�]WgrOUU�/_����k��=z���v���� �B�!��p��Al6qqq|���zzz:			�������b�_�~\y�������DM�(
'Nd��al��M���j�*������[9����~�3��6Gr��{}�~�k���h�9�;k��S����A�|�kC�G���R������L����:��G��4ji��O���1��$���U�*�+>NJ\��#Z���P���Us�aJ>�B!�8�
��X��k>��T��_�/�{�Yk�����Io{}���af�[,���NF��_j���������.55��S����K�R^^NNN���DFFRRR���������/��O�Y!����o���($$$�p8(// 77�����n��I�&=n���,]�4((;;�����<��CA�I_� UUQU����(A�kK�8p���^��E!66EQ())��t�n�:bcc����{4�������UU���DQ-)�m�6�y�}�������y�������7>>��MII	v��/���;v��#��H�y<^{�5�����b�Eii)G�
8�}���B�F�8q�7�|�#G�����������$��U���tEEE1z���XAA��o�=�������E���#�[l3$���;��*�G�����k�`}W@������t~:|1���'z3�&jj�j����rp4��v?�1�-!��."��MK��D����"�I������\�������1�/�C�a!�BtB��<����_M��T�yC��}�"L����b�qCB�����)QU�w�yG��=zt�I
�
6p��!}�	&4�������;�����+��C����_g��]TVVE��}�4i}��	x���w�^�������5j&����j�|�M��]�����O>�Q-���*�G�f��Zr���������g���*.�o��A	��#G��G��kW.��Rz����l����|��'�[������_�|�I�q			,\���k�����p�]w1|�p����"�{�9-v�e�1u�Tbcc���d��
l���3f>TSPP@����={6x79r�y��������Y�nc����v�y��������������������w�}���c����k�1w�\��}���XKLL�7��
��`0`��X�xq��������!�����;�7on�UU���<���
�C�Zo�g����]�����V����.�&�x��j-�b$:��
�M�h���[[x_0w�/����_�����y��@�:�(G�u�%9�k����Ee�g��x/4��B��X�N���H��R�B;kG�5>]K�����l�Z��~��B����u���`��K{���DN��x$�B���Sv��y�4����P�.*?8��5�@�-�7y����;Q����f#''��7r��	�������t�
��AV��.�����[��?����������6������[Wg���f6�y��G�Z!��������]�vQRR��;�s��������X\\�_=���������v������?�I;FQz�!�t��H���+w�qyyy8p������_�\��x��w��Zm�{dd$'Nd���A�@=z����j���gOn��vy���@L�}���Z���3gr�UWik�M�u�]��v�n��������&=�������O>���c�=�%�[�6k�,�����������M	!�g��j������v�r���l8�N'v�����������W_������7n�v���>����	�����%`�4�_���/�������'�j���c�n�O�J�fM�/�z��\L�t(�?��gr_����X8o������=n>�a[�~�b�������?������2o���>������G��B��g���*�B���.8�j��f�zp�B���5kx��Wx��x��W������ZZZ>�`�vvz����:�����y\��^�z1m�4~��_1h� mm��EA�������Zg��Fm���f����..���]z��Z2h��-�\�3����@�F��n�N����26l�x���\����Q�L���{k{�#B�/_x�hS�L	Zt��Wk���_~��������k�������j�3d!�B�j�������v�k���Y����ba��e�;��7��m��)�_�����f��O>���n�&8o�[s�[��]&B�w6^�bF{g��UE� �}���������_g�������������}`[8o�wj���p���k���+m���������	��~h��}+���{��[f&�N��G	8	�qeoEu�0�E���(u_B!D��1��q�_oU�]P{������O�-�1���M�0�(�6�*��3�2eJ�9S�y��G�L+���X����������S�N���?f��E|���5*������T��3g��Z�;-).�������Id�������p�\=z����a����e�������",,,(iWYYsshc���[{=G�Qo2�T���STT����kI���m_ml6��x�O�l��
������;
I�	!�g�o�~T �������s'#F����"##�:u*���>�m
0a��u��;R�'0�����k(��u�<\e�E?cd�A�n\p��H��0����M�Zr-���J]i
�Ts�'O�u��lvn'������Ra�ub'�~|�w`�7>�e'Y�j���~�R�
�3��>#q�l��x�U(����!�B�6�`$b���h�T,����U0zs��Vo���?���C�b�����X�`;v�8�J��(0�b�X�����5u�T���[


(..���df����Y��������������1�9���s�����[o�a��Z��>�]�iH^^�v��n����������'��i������S[����*++),,�W�^-�<�$�&�B�A�|���f��7z�75��d�e����^����<TU��>���s�=�����a��b�fWp���b65�KKO�x��N��7	���=�+m������+�������v7����e��9\v���w �Nk��5w�!p�r�i
���3h���h�[�j�����z�z���{+1-?���&�k�q�.�����w\!��u�_v��6��u�1�e�Q����zb��l6c6��4i?��#���g��=|��wA�:����^�z�Zif49��sY�b�my�\KKK�6j������v`�VQQ�?��V�������#INN��t�m��fi�i�Z����>1�������k�����}��@p�^DD�t�8����Bq�����x�b�~]m*�Z��T ����3�7o{��a���<Xw���{�����!��f�����������	
�prY���v�@�!�;bF����<v�M�� *�D��H��{�v��!��fp$/�/��P���	�tG�����I���p���`w�}�V���*{�neD���7�	c|:�����IrM!���������R�����]S�2���d���:EQ���[x��q�����;�{�������tGP��	��
L�<���A����j���1�����X������+�5����fI�Y,�y�v{��OC��<x0�g�XmX`�����[S�L!��'�|����*����[?�=�
����~��i�7��rJ�<�ev��5�Ge����\�_j���P������>���G �B�|b
����h���Qn�y��c�iom�r�-!{�����	.�I�������z���6G��Z��c�.�/�&�B�����#���1�u�/���9��/��_:c�w����������Dvv)))����*-���Zm�m�����P�3���c���d�9kNN��&q���5k�)!�?W<�sii��q�����'N�V;I�	!�g������w`�����jK�)�Bhh(��0`��3:�LQf����A���c������G������c�f��o� IDAT����bk���p�A�u
������������I�}�n�X����X��\�$�����������k		��Zj�H���]��z�E%�C-���[�-�5!�B�S���������~�\�/���^$v���}���3��k��������;3��D��=o���_������������%��n7����U��
�|�3�������cbb��50Yt�y�i��"p����/P�����7��QsHHH���}��i#M�l6���w4EAA����IrM!�8������v����l��l�����l�d2�o~��3>��[�n��O�,[������#��<+���#��������9z�J��#l>�>�A���������������%�90x�T���jaI�5�C�{���[3����m!S�,�m�{��j�&c�O�$�T��t�IrM!�-�h"��,�~��������o/����f������?~�m_�#F����u���V����l��m�n�X���5��
`���+^N��w�yGn5��7�|S�^3~�xm-p[]��m��i�k�A�������P/!!�!C������"zyyy��i�4i���������u8�Z�^x�v��7������vD��B!D++,,���>�;�E	�^|�����"..N>#�M������lX�V>��sf���?��������>�{�����@���������������A�������wH%�����P�&m!O��i�X�WaFj�����);�j��N5&������;6�Y��U���
\3�f���y--�-d�1T���OJ!�BtV��{.C�e��M�d�n���a,_��
6��A������57]�f�5d��1t�^��fk�8q"_|�%%%�������3l�0�������������&O�4��)�?�|�-[����Khh(C��`0�o�>-Z�*�Nyyy,X��K.���������?K�.e�^oG�������}���l6c�����/0`�zy�T����?h����j�}�:�,,6���k���woF���d���t�����Xn��F���Guu5�1'N����.�W�^�L&rrr�����������{�d���0a���#++�;v����2}�t�����l��������l�2����o����_|��|���p������2}�t@dd$'O�d���Zu`{#�5!���-]������(���d��t�t:q���L&����*����Ey[��QQQ\~��Z�p��U�?����ks��U;�I���Q�����Xb�����0
�G�W���Y�����5��h���8G.0�VR����!,D4��#y�QU���9�B����� �I���KWK�%�NWJ\wf]|'��z^�$#��.l�0��e���p;A��)<��U
!�B����g�c�l6_|��F��Z#���Ko��q�&�<���>\C�>}�xr�b�p��w���O�p8x��wjM0���������o_F���?�HUU���J���(L�6��?�8(����+���+}���H���Kxx���k���w������z���hL&%%%����!C8~�8����Y���������=��ba��i���{��n������������K�"LMMe�������TUU�q�F6n�����?o����db���<��s<x����s������_��WDF���,��s���������c�������]�jo���B��|Co}�j�dx�p;l66�M{s1v���7(m��_L�.�Cn��%K������"j�>�KBd#*H<6�~\��
�����p�v�2��j- q�������"C0��oksNe�������������,��8o��N���<t��|�.u�S�b��<>�5��V��h0bH���5!�B���8�������_�s�Xg��_?{�1Pc4EHHW^y%��w_�s�����o���/'44���w��<���L�81(����7n\�.Bf����G��SOiUi����
n��&���o{���bbcc�����;w.��v����l6V�\�{�2e
3g�������
4`��z�)�������_\�z�tEGG������3gj�t�bbb?~<O>�d���z����O>����1����bcc�5k��F��'��}�T�f�[Svv6��/'''���(�
�E]T���>�7of��5����������z��|�r:��($''3q��;���K�;����[���������
B������g�����p����������L&m�����`�d2�(
���<��3��yj,_[�w�}W�rz��_�o��������w��Ks��o=Z�+���u�14�������T�=l���M1�h(�~�����������lc[iw��9p�-����0����G>9��B��IcL��o�E�������v��{�����4WwD��|o.�=��pa���/�r��X�H��65��w���z���=��9�Sm�b��o�v`=�v������!��c�\� ����acn!��;tG�~�����m��o!����R�;FUU����u�Y�u}�6N���G�b��IJJ"!����fp���r��q���y��q:�;v���j���HMM�5���p88r�����RSS��='N� 444h�\���j����x<�������%�j�r�8q�����*�������RZZJHH���M�`d�������pCJJJ��Am��o��_m9
;v������R�u�������y3YYY�|����k��G�x�b"##���g����[��?����9���Rz�!���HLL$,,�={���7�0{�l.��R��~��g�o�^�/�9s�49�&�B��`0Fuu5�������L&�?��S���7�-1b+W�$;;�>��x�]�9j.����)6����1K�qR���W1�$�W������������P��I�X��\���k�LU=�����H����\�k���W��f�`��+=�26�����G���_Sc���T�	!�B�M�������(J�$�ccck�XjN!!!g|�nHH�Y��Z��n0l�F�~��um2��ZL�EQHKK#--M��(���^������p8����Exx8�?�8���TVV��O�r�J&L�P��L����,Y����������#Gx���x����������b�p��72j�(�[-��#�����3~������_�<�Q!�h�>}��c��F#�������d2i:TU�h4�(
�����EQ�����M3�b���\p��#;��<+G��I��H�niX��DR���m��!��s7�<P���Q[N��O@��:���qv�����`��m�=.-n�8�e��J<%'����-���`$=�,-ay8w��K�%�/V���!�B��b�����7On������a!Di����?�Hii)�f��J###�>}:/��26lh0��|�rTUe��Y�N��={2v�XV�X���{8p �=�\P@zz:]�v%;;����:�0�B����*�|�
YYY�w���������*N�S�����v���=G[��_?��?���%K2dH�Ux����j}�^E��DF����1�U���������g���w��J�u��'�NH�Z��=.�Z�"_��H���`��[����(�lE�;���@�Da����3R3�����}���X��)9�������B!�B���7��T�f�!ZG�_���};����}m���}�v���k$�233Y�b���8���z(�Btt�~	��ANN&��n���/$!���n�����}��VE�b��t:���` $$EQ���3g�x����k�e��x<


����N����s��6���n��l�z<����B������_����Z�`;��@pr-�����bl�dPG���u&��7�~�*��]u�%��f�
H<�R3����������3�\���b
Eu9@Uq�����3B!���eddt��yBtd��=:q���E_5��(���V+������������������������:���3?�0��?���D�Bq�>��c�������l6�V�V���l�b���(dffr�������-JMMe��1��e��QQQAqq1V�UmZ��=K�	���������Q�h��.����Q�AX@/�������Lo2FU!�L��r������V�yv_��9*��tk���x2��=�����\�����q��"�C��B��]B!��YXX�������h{j�v�0��JHHH��2EQ

�n��B��j���z�ju=����0S�L	���M�4	����M���y3������^""��fM����.��X��[4E~~>�V��f�i�&������V1=v�X�
FII	%%%��4����=���Y�nN����J�������������������Ci�(��:�� ��F^?�ao��3��F��Y�]{�K�J(�Q��}4�9R���K}��������1m�������Z\���5s��ll�m�{�L����������Z��o�ch�	��f���v�S'�@�������|6���$�������VQ����r���o� ��6sH�s��iI���`�&�ag������(�B������h�VO�����T�[�s�_��;v0d�
�6g�bbb��6c����g�e��m�]��I�&/�B4��={PU��U�o���8��I$$$���.Pz���s����w�����U�V�w�^���*"##����b�K2|��p���p��i�<�H���9L8L�M���]���#�����rq�����N�;�1
����Z�U���,q���>T�������*���Pv\������~��V�mY����<����6�j��
�g�xD���v�n�J���B!�B��i��Zhh(.�����������r��X���m�T[u�/����
�~�m�f3s��	ZHJJ��6l��m#77W��h}�v�v6B/�nX��M�b�
 8�T_��n����XK=/��#G8x��f��r�t:���h4��'X�f
w�}w�L 6���Y}��}�
���K�h���'��3���>5Tn�\�#�����{	���jkvu���E�u�E����,zEm�n���(`wa6c$}�v�=H����i�aa-����?@���*���������1�y5��w��_�_�s��������->�_��Z�[�=��W=��A���[�SA����T�$���[���%~��m�T�
!�h���U�t��UUk��*--EU�Z]����0�L��U�=gbbbP��������k����Z]|;�m6�nE!�h�f}�Z]7���������*N�������n�%���;��aC��;���n�6�+�Z��#{G���}��X(X��=��R�&���
x=�b�]rJkn����������zjn�\��3cbF�km�������Z�7�z��
oR����3�<�9�o�}!�B!�M������Tmg���C��4}��	��)�Brr2��������9�l��?�@zz:�'O��
).��C�����!�M������~���o������������h�/k�K�|������G.�CT�?Y:��D����;�w#�r*IT58��8��3	���7���a�t2=o�x�j�����%�;���/��V�p0E10,s�~���N��n�R2V����|���A��,��^�Gk���[�!6%���wXB!�B�X��\;��sX�zuP|���(������XNN���.���
8UU���j��~�z����je���(���~��:+����.��n��_�~���Bq*.���F#F�QK��L&!!!A��'N5��*���h������k���#�:<�Z��1�f��%��$k�*�j�L;����L�G@	x+�@���������s�e.�JA�/mE��=k�4��T�r��tK��_h6���k)�������PQ|e}�j�j^�T�����(�B!��qN����9������;��o���_���l������3a�RRR�c�����o�>~��'���h��.����W�x�b������e������q�wh..\Hqq1���,]�T{<x/b�u�]���3f�L&7n����������=N!�h�;v�`��n7���p8p�����%�|3E����F�0nK|__`b��u�6[�����&�5��d >�4[�,�����W�x�
?�]W�����#<��&9�!9��I���l��n��~N��}af�A�j�m�p�QU\���5cj�O��T6��cie���-����	�<Ew����B!�B��i����`�����?��7nd��
�F&L�������MOOg��}�����������y�������g���\x��8p�o�����J6n��{8�o��J��?��?��^1b7�|s��B��X�l�~�)�O:)��%�|�5��c�r�%�h�����d����W��j6��x��*����`���L�4��LQ���������pc�����o	0w��pCV�I�������Y:����"@���^�4��,{���f	c��[�b�����n�����Z��7u�����.�P�"�c��\�P	+�B!���Z=��}��Gee%eee����?���g3y��Zw�gff��s�QTT��� !!A����k���n�#�v�UW1u�T���q�����c6���	!��v���j��ph�Z���AK�u����3g�����Mff&������%��v�V��c2�

e��%0�]������7{Kxoc6�7���_���/����4�N���j'T�[��p��vg��8N���J7�eo�����%����\���'�~X�	M10���L=��?�����4�����^�����~��lLs�����-C��n�p�����JH�hBL�L�
!�B!DGrF��"##���k��5���ONN�s>
@||<���A��S��Xiii�XBq��{�=TU��t���i���Z�Z<,,�]'��[�6k�,�6�����XoKH����������/�k�m/��u�5k>;OT����T�k�.ur�C�wp�y,j(X�+�;�����zE���C�;o����U���G��d�������:]��-!;@�@J\w.:gR�_�����j��7�������eO�c.�m�Q��}��y+�z��
!�B!���;k%�B�SR^^���o��.����,*++u���y�����co���|�����j��V���R;mix�RY��w6���5��a���C
�<���b��ow&�b}�^gA#S���^�+K����/Y������>������5Sjf�J�v����["��Z�����K��fe�������*�K��l��������7!�B!�h�$�&�B4���B�;k�>��j��JJJt����#����������������`��R
+�N>R�1l��_Cm���/A�;�h��������DIU=�s'���7)*���k���p��p�rU�u��ZTx,�	�p�>��?xZ�z�S��u�K�p
ju�e���B!�BQ'I�	!���b��(��Tk���P}�]�}�uQ��4s���c��S������a�L����P���f��VHv].�G���:���z^�Nj��o��:UV����V}���kP+��T�Va-%�([�S���c����fa[�_TG���>�=�q����B!�B���B�����	GQ�zl�Sdd$�����v)55��������h�b���l��p��.]�h��g��&�Q*�:~�4o��!��n�G;���@x��/;�#�e��R�~�S���JN���j��M��;�UI)����#��rk�>�����?�1��7�C�r��	!�B!� �5!����F���]��(�V�6a����'�d2}����l6k_�����F�l6�y��1s�K�I�Wlm�;��'}�n%����9d��!2����.��H^�{�I�Q�PS�*e�!�W��w��� IDATn`K��@��b#���EG��f��I;��c��B!�B���q�^�B�6d��)���a0�d2i�l&�	����`�{��\~�����kS�L!55����b�d�&BV���Nuu56�
����C�x���??l`�}�N
pNm�,�G��u�>��E���~��s�+^!�l�_G�+
�%�\���'�l}�^����f�
��f�@��",QM~����L;F%�i�>%�cTS!�B!DK���B�L&w�y'���Z�VXXaaa����(
��������|�(BBB��������ZC��v\.W�q������l��������7S�$`	i�[����'&��wg�>����J�`8o��1t�b'��\�$tI��J�ZM�
�N������-��>�l�'��ac�����������������mN!}F�C����oH���q!�B���������������~�z
��m��
X�~={���/u
��j�B�:IHH���L&"""���d��9��;����U����\t�E��
��]�|1UU����?��[m_�#B�5"E��&����r�uT��{�#
����tJ$\
}^�A_�)�W����E�)�r��J{������������>�&3�������<�yY�]cr����!-��>T����������2jJx�>\�
��QI�!�B�c��������p��l�2-Z�7�j��`�n��6�l��_mTVV���c��ym:q����2o�<�-[�_�j�2-�B��PQQ��={������?���pD����x+���v�			��o��e�f���s(�N�������zx2��:�7�\������(}��QLu>�|
������
]i,+�-'J�BfJ��A����o/����"���b�KT"�Oy��.��K��]|��Ke���1�w�@�)�.+�*!>�_}���D\q?���/���(�z�<�/�W�$�B��������)..������Z���1_}����^������K/Q\����l�2��h�)N��j��t��Ml�C����B!N�O?��%��������]8nN�����=�����y_f���!	<vU/n�F�����>�>Z���k�e�P��=Zb-P�)�9I��t�rp5=��Qe�����Pkb-",�+G��������#��������fL��bX�b#�^��Kf33����
�~|��]�!�B�vo��]����t:Y�~�~�MQU���`��R��������w-�6z�h~�aI�5���<^y�n���6]U&Z^#���Bq*�6��$��[7o���P��
�zZ�?!��U:��g%�3��$z'�Q����1Z�)�
H�V�|N�
�_�G�tq|���;�5;���7���#�%����)�&����~��yk)�%$@bl*�]���uJ��A\tmcO�c�
P��$�e��c���q!�B�`��U��5k���-���<���|������/`���������$��L���X�n�C�$:���v	!���q��A����CV;�!C���h��M��` 44����(rJiu��6�GuC���0���K���@�|�Ep�O�h�������3)*���/�Cm ��%k��|�7;�I����&���}�����pG���s����.8�	!�B4���(������5���A�e��V^^�O?���?p��O��*j-����a���w�}���[�� UU��?�IEE�������}���+Dk��kB!D��i�v;99�=z�v��W�b�����f.�K[7�A�����kk�]nY@r-���5�n�w3�o��
�S!f��1�������L�������N������^��j��2v����?�-!�-djf�J�2��KX�{��FA+�Q���I�7^��|�2PS�B!D��.:J����:�%(nL� �����}`P��}�����n"##���8�N��Y���3��;y�$v���.--������@���ZSzzz����dggs��1TU%..������y��w�Z���w�J|}������[�w���	X�x�����+W���CD\\w�}7&S�����QU��Lll�~��FY��\-66��^\TT���"))I���?���G���$$$����]/��*������MII	����j�MFFqq
�Z���deeQXX@LLu�Ps��j_@YYyyy�����z��UVVr�����P���4222����w��=���Afff���^YY���������0RSSIOOot�����}��QVVFXX�{�&))IX���?YB!�`��������7�
KG3r�H�;��_Mhh(�����<�k����UW]��v/���"-��	A
�����T�W~��#��	�����W�}�~�����H6g����Tm�b��m�5L��,�%�x*����-$x���4�o|��->Z;���nP��{�ucP��������5�$�*�B��s�YM��Q����>��C��>��I�2j�~�U�������9zii)�7o����g��A���}��~�)��z+�����UVVr����t:9��sx������,�x�
�=��X,4H�f��gO.��Rm���`0���K�1cyyy�N�Y�V-Zx�������1r�������t:4h���~�����W����>|����3�p��q���^�u�����ZcvYtt4��rK�.@����s����E]Dxx8+W������s�9��=��]k�h���7n����t��6d�n��f����'k���������6mZP����|�������F�bTT�������"<<<h
��K�,���>������<y�d����:�9�p�B~���7..������/�8(����w�}WKL:th����i8%*�B�&9y�d�h����DQf���_��z������:t�{�����z���,-�^U���U�+�Rj���ku&�~��a�����Tj��[�}��r;)��3o���fn�����|J�+3({�
<�N�<���da�������g��[���K[�1����hh�}��'��B}(�������+B!���TP����&��<XW��+78��Zv���U]x����DV\\��]�e���Z%Q}s���]�%g&M���w���O<�]������b�����5�\�Xo��O<�M7���b	Zk�������v�;vl���t�R�~�i���Khh(qqq�����r^~�e��U��u�X�bF����D����v���_��W��/��e�X�n]��x��[�n���(//ZS��t=��Oo��U<������UU1�L$$$h����
�-[��}����,Y��%K���t��E�t��|��g,\�P����,z�!6m����������Hd�w�vqq1�����W^��x����c��j�*-�EBB���i��	���e���B�N(�j�{������vN���<�����oho��<���>��_\c�`{�[��
���
o��V�P�^�]�~8��5f�S'~�>R���}r���F!�P����.���']�A��R��!�~�^W��F�v��w�W�������tHi��\;��tK��� ������a�M#l���xj9�@��k;t5�B!����Qm�_uR��u����u�~��}��7������I�=0���n��Y�9����������������w/yyy$''k�>�~�-III�w�y���+������`0p�-�0~�x��0z����*��*$��C��r�J�v�>}x��g9t�.����8�W\�����a���DEEq�m�1j�(L&��������]����'�|R�Z��h4r���r���b�XPU��G��h�"�l�Buu5�������JT^}���[��K.���#G��[7<���,X��C�Q\\���K�5�_i������Y�v�V�w�]wU��m��������*��n����Gk	���|V�^Muu5��{���^:�������TUe������k�l6���+&M�������^x���J�f3�f�b��1Z����o�����u����`�����UU���_����o�Z���k��HLw6
\�B!DC<���g������ST�ou��
'��/_��}�PU����h��h�__�5iii�=Z���!����5��`�%��F)]%�5�����=�n`���7��|�~��PP��6��G6�����}�>tjT����'��F����R����zc����i;���O\�,>��Y�9�����XF����0��K�KA�?���B���/	!����;����?���e��		���	��"
EEJ�Vmq��m��Z��j[[k�Z���?*n`]h��*�* ���$!$��������0w��,dBr�����s���������sDo��4l\��`�q�mT/��m<,��R���`i_V��9y�}�������?���.P���F�������};���A���g�c���y��
,\�P[_���+���k�o�����������J.Y���������
������())�2�E���GP6R}}=���|��'�s�=�7N[;[�����/t 9<<�;���}��QQQ�e{5w����/f����<EQ�������c��e|����:u�
6e&%%��SO��>��K�������F�m�\k/����+�?�����$�0%%�I�?�3f�x�b�ZQ.��JKKY�j���}�v��:P���^������<���#�5�_�����P^^�[o��W\��l|�Qsr|m����������=��O~��������$�&�Bt��'x���9r��q	��r��]�@�\t����]����f�5{������c�vK}����\KkK�5�	�L������&��'�����`
T�1<!p�/��E�nspm���$D'�;���	��I�V�^���Kb��4SN�7I��O�������J����8-�mL&��v'�/���nzR�Ou�S��_`��ML]�s �B����������8��\G����up#��L�&6�k�����k��/�X��2e
�w���p�m�6�O���egg���Fqq16l����z~�g���vf�z����k��ZD$$$0d�rrr�������K�{�%������3l�0<��m������F�~�i{�1���u_!�������c6�9������Oill�����l��>OP_{
@u��mM�ok~111�=����s��)�������;v�����K.��I`��Z�f�2e
�V����P����e����/�l��EFF2k�,^{�5jjj����:t(������������0�L\B!D������?����j�^/.�K��5�LX�V>���f3�����/�s>��S����/E��x�x<����d�b��(��p3k�,��8'�3����o
����H���Aw��;�f;/7�h���j�������Lz1���a��5AU�b#��m�}��slo[v���������|I������H���{�/�Mp
�_��Vk~jc
��}������B��(Q���M�s�?�)&P��LTU�JB���_+k0i�$�����z��aCPpMQf���K/���S���o�V:��tj���\rIP���{[����
�\�������^�d	]t�v}�5���Oh����Ws��wk�'N���������d���>����������'..����V��<x��{�R\\LCC���Z�:��:\���w��A�������������}��������?����_ZZ���C9y�$���J��;��������B�A���*���x<�NgP���n��v�Z&N���a�t��{�;��d��B�O8y<�n�v��_�\\�mCp-n&�8������>N���������>�Az�'�G���b�����M��n�+���v[�������~����$:"���a���s��]����2S���C����6��<��8�"g�'��Fk�	!���gNH�/�.����6�J����6�W�RL���������X7�k���{9y�W�c���Ak����9������Oii)�������O���_�������k��m��Q__��(��=[��ry~��c��!�U���b���5�dee���
�h�"���~�^/;v����hIUUUl���>133��������HII�������&e?���+�/_�j�
��O�u�D�J�>��U��d��H��]�f
k����[c:]=D�}9x�`m,����B�l��U�k~�l6�������>\��Gn�������p8���RSSCtt�q[������	�<LoKY���=��}u&���z�qV$������;`�����I�s�u%���e�ba�pn�j)**|������l.8&�']�����^�z���U{��_�����	�yN��T�����8���
	!�����������sm�6T���s���T�����i7W���54�=4e�rrrPU��7�`�m-<<�i����G�}�v�D����=zt���'Nd�����������_�Un_O6o���G�u�>p�R����4�����c�p:��8q����`���-��6�kl�����s�\�x�	�N'��0q�D��K||<555|���:���s}�S��������a���9����@MM�6��ES]��,�B��v�|��k~�������K}Nzz������_��j�5:��	�[z��j'�����@JL�k�F��@m-����`���V�3}�DdA�����
|Xu#�+}>����<�]5�z�s�=����-/O�J����z�����8�$�w���(�egj�_A!�B/���p���S�g\
�D�9�'��nSUU�����QQQ|��g�P]]����5�Y�f��G�t:��u+������p��W�HMMe����]����"~���0w�\bcc9t��W�>�f�r���^�q� Hk���d���>3h� �|�I��7h.�UWW�3�<����n����X�H�+**����>��p8�,�z&����s����}���q�r�}���B���Kh-������^��f�M�<�M�6m������U��XJ�
K[KFf��m��jpW!|�/;��"Z�8G������*[^�-�L)}UWs�j�j�b�:��l�����w�RVu��������)1�bCmcv�b��wv�!��`���?R��Oq�.�nh�k�K'����ta��3Y�n�V1����U�Vv+))����1B�0`#G�d����_����RTU�_�~�;V���[n�������9t���-Z���,Y��KK�3���e��SK=�����C���j}�����,�-[�h�Y7�pC��ZW2�m)�����
�;���Z\\�w����IpM!�h���Z��L�2E�W�����������j��r�0�L��������/�)����7C*jD���� �B����S��(�Y	s��dE|����������G�����+Y��)3N�J��;��\i�&96���b������5��m��8v�m\j�m���!W!�}�91���/��e%�o�9���d�I����q�-t�4����'���T���������/�|i��5���g��~:�}p�Wh��Ff��i��q��a��ZDD����5���g���`xU�4����������e�WY�����i6�III1�h���0\.�%��>(��_hYW���>X4~|��<����`�Qvv�v0{���!�egg�(
������2��V�3d���_|����D4%�5!���N�8�eV�L�VE�t��C�/3�\2z�hv����ln�=���f����e�������v~ �m�J]�+ nz�Z�O�40G���� �����������S�x����f������o�j�)�������Cu��CL~�aG���}/���������bR���=�B�B�K�-����}���Ly�;�5�/����'O��������#��tr��w�p8��u+7�|sP��I�&OEE������k� IDATvf����������={6w�}7���A_�;DDD0f�v���_|��'���_��O>�D+�9b��g�������<���)**j�w����w�y'h.�jkky������}�k�X�}���	�._D�O�$����<����L����+���f��uL�2�1c�������T�t�$$$0y�d>��3�����������z�UTT����q���k�������,Z�(h���3U%����z!���'~�7aaa�f�Y,-�v�e�V��`�X�Z�Au��E�nv���CD��y����Nd�Um����(��(x]��b��+��q�)�t����_��_��AX��w
�:h��Q�NJZ���
����R��I��%�����r ��L���G�G��B!�D���Z`
���?���e��/�2n�8�WR���?Z7����9S��>}z��)UUY�f
����a�^~�e�|�I�q�����y��f7�q����(
.������l�����J*++���y��W���\s����3q�D�Wz�O������tRUU���#�<�jV[W��u+������BUU*++��a=�%%%L�0!����������+��������x��G��</�3���
�}�7m��G}D]]��}��i_3,,LJy�^���?����RXX�����t�����e�x���4����n"::���W��3�p��a�n�������������7^
.�l��^�����O>INN���x<<���{�n�������ZB!�hUZZ������f���x<Z6��l�nV�����B���_?,X������f��V�/c�l6�(
\}���W�l*P�������q_�{O6�		s���0|l�F^,�p��ERT���A��R�7���2[��8�}d\jB��	�v�q�W���=Z���e�Db�~�������TWp_o�)����<%<6hM!������b���/���f��)l��
����:uj��e�]�[o����e���+b(�Bzz:��������e�������O��.;T:x�`n��V�ZEYY����[�?~�z���=�u��QRRBaa!�>�h���n�������u��������^z��^z���Je3G���	��s'999,Y����8\.������.���?FUU�z�-�����
:�����?�W_}�����?���?���s�=\x��L�:���JV�\�����w�i1���?d�����INN������'�����-[��e��6�<3��w��s�=������C���kO�����1{!�B�*""B;���zq�\�/�f�Z�Z�A�l]tQ�YZ}��Y����;����l6c����lX,Ea���,]���{����;�.��[���q���������a���T[��]#8s-3�����E\�@�4��/�h�����'N��j��v/%,
\�Mk>^_�K�3��9q��(�B���[�N;�9a�����&L��UQ���/)/.���)S;vl�r�F��s&L &&���0�����I��3g��O'..������o^�9s����{�%-�i/���8/^����K�b��y��G�8qbP��l63y�d~���3h� �+�Gvv��_L/..���#������f����.//���������^����r��7b�Z�����/�4~	������o~��^d�N�
��3g���/5jT�U��������Z
�v���Cy����9s&aaM�����`�x���^z)?�0��5}f���`���Z%��������*p��4����[�j�]!����A�L�w�(//�����p�v�q��Z����������v�I�����X�j�a�����e��=z�C�q��	�w�|���v�Fg~�s��x�=_���p������,�-�:��s "4��[���9�r{�aX�fz���c������r��\5*���oY�����)���f���/A�9U@�[�������b�&����uh�������fXi�3��-)d	��4���W����M���}��Mo���8�x��=b�n��:���VB7������[�3����I����z�M�t�W}}=��?$''���O�t���bN�8���$11���wy�������k{���RMM
w�y'���}�����AUUbcc���_��[sjjj8v������&��)..&111���^CC���x�^"""HMM%<<��MS__Oqq1


��v���������������:���ILL$6�� �*++)--EUU���HHH0n�S��o:���!�=@nn./��"���Po56�M\\\w�y�Y��TQQQL�>����s�����?��~Z�!���*��8=��Yk��ya�A��������ZpmL�&vV����o����k���_����A�m���e��V���Fb����	����(�U&�DF���|����C!	������8�,OI�[Va�c%;�B!��*�������>W�iii�f�u���(F�a���������j���n��1/<<��#�����!C����b�t�]I\\��q)�6T-�B�ro��6O>�$eee�����	
�)���b��K/��Gm6}^45l�0�����a����=_QU��(-�i��VU|���|�N�Q���0;|%��:�}U����8:<�����@���k!|�w�l`�/CW2T}�\G��6T�[���yB!��g���<��c|��W�%rrr���|����&�\B!��������8�N�n���(
6�M�!6o�<�Xk�����c��y3�v�b����]=[qP�Z{�kjp�Z���Xt^��xM���u�L��7lAex�
_�o2S������V�@u�������>l`j��U��@?���-���m+O�1��B!�hFCC���)++���b��!deeMuu5�J��L&,X`�
B�s�d�	!�m��*/��2�4��_��_���g���A������������=���*A�v��������y`,:O�����]f�?`��2����}M~I x����ZO�Qml�KC����|_�/��_r��1����(@�~kB!�m�r�2d��.�������;�Z��w�}W�EGGs��������g��5!��
������%.������;���[��Ypo�����f��t��������6n���n/e�.��]�k���Q��������������U���r��h�c~��a5�.{�l������#O�Qml��5M�.�V�XCyu)�1)�]��v�q�U�����B!���bbb��HII	[�l!77�'N���Hxx8���g��1\r�%R��E�����v<w�
$�&�B�AYY���UU�,���ji��6����,����W�\	�WJB�,
�����h�oMt����>�
W�?��NAeH��8na�G�b������	l�������@����Pg��������%Q�1$��p��$�'upm���C��2��*a��3.!�B�V���r�5�p�5��D'DEE�|�r��g��B!��j�K��Z��c������q��i���w��!(���t���b�h�������
���+c�i�����#~�U	|�������?2N�J'���r��E1q^Rh\��k��w�t���gxu������V��}�5����F�0.
!�B!D�����B!N0`��`2�Z
���@���nXg2v�X����� ??���g*�
�[K�mGP�jx�|cS8�^�.:���r&;�5N7��heG��2{�����i	q�3O�W�X2��e�Jt��Ap
���O��GQ�"�K��XG\J���B!�B��IpM!�h���(�L�����(�V��k_�Z�A8����h�]�KD�tE���Z���U~�]
��;z��#��d)2N7u���{����^�l�[S��P�*�kS���� S�wM�}�n�1s�]�&��s����v�7.C	�
�B!�B!�5!���n�����1�����iYj��`6����(����������m5v�Xm������������������X������.�E��v�Z��k��u
tQ�2���)d�)���"�u�B���x�Q\��K�v5Sl*Q�����m��/��0����5n�B!��o���B�FQQQ�s�=$''k�������	CQ�
�]w���D��m�6����PVV���;y���x����������S�����q�g66��������Y���4��2N���J_��"_��+��kA���J�� =1������z9^z4xC((
&]�U�=B!�BL>�B!�a��A\y��As&��p�M7�t�R��E������SOq��q�^/����Fq:}��O?��+V�����gOY��'��is���O�olM���A��s,Q��S�rZ�H{�zG-�U��u�3�t�"s�@m,|�&�����������W�#O!�B!D0�qB!���������O������W�o�����x<�NgP�����xg��]l��]��w��������,m<�T���9r��ke����X���y���S�J����8�AR\?�j���5���L��8Zr���1��~f]/<��L!�B!D0�G!�h����}���1c�H`�����i�&�&�5?UU��>���z�tI��x����bb�s,��t�N�/$*�6�t������2�������fN��Zs�}�
t%<CI��T��m�i!�B!��k$�&�B�C^^


X,F�i�!:����BUU�^o��5?�����G�����~k�G�A����[���=H�5���Q�;��
���=��_W;���T�oE�v-�k��L	|_�O����9a�{�z�x��oB!�BHpM!�h�/��R�1���vd*����� x���������6�<���"FB�y�k�e����o��|�O�q���!<�������uE�4���mw�����qB�{�����VLq����VUWAU]�n5D�V���K)
)�B!�����B�����1ct+�3���0�3&Z�_#<<��zvUv sMJB����%����%_��W�+��*�[���h�FP�����%�Zo��6)JA%!3�Q"Hld��� p~�Y�^�e��wIiH!�B!�h�<�
!�mT^^��������G�VEg8���E�l6�5���c���^w�NU
n��m=��P�6p)%!�ME����:<��C
�x����z���K ���p5o�����SU%�;j����!�����~�����L���C%�?���R<e���c��T�n&u����F�S!�B!�6	�	!�m�w�^m���JJJ�nUt��d�[��e�l�flV���BXX,0.�����v���_��y*�������t�7�q3�v��S\��th�;�RW����������.,�-�uYk�1�D��u���SzT��jc��q�t~f�����s������48��'�s�:���.(�@u����&U��w���5!�B!���$�&�B���={���Q�t+�+L�<�)S��(
aaa��v�V+6����p�V+����o}K+#y�U�KB��b.���`��|4�������Z@Nt������������@p
�Xyc�uo�/	����� �kmQX�,��������-���+��o74Y�J��b���y��i������ ���
*�B!�}���B�6p�����j��o��)��w�����m���0�LZ���(�L&�.]�%�\b|�YS��\K�m���
��{�Bcp6�"�|,46��.��|������g�(��}���K�^�5T/�SG�Ks�@m,|\n'O��@P�����'�x���J�R��{�q�6d�y�JhX���B!�B�9\B!����C8�,%�������8��(���3����w���9s�5�����\��)�d��5�)y��j�
��n���I1v3Vs�����)�8�Z@���v���h��"(s-��5oU	����)1S�*�����eG��MT�U���2Nw����C���-r�^^��J!�B��IpM!�h���TUU��g���#F`�Zu�DW�����.`��2D������:��uYNM2��U�ww�\K�6�����4��v��F���v=2�sm���~�]'E����Pg��KB���Pl��U�U�����t�6���zG�q�S�eGAU��-R������B!D��*j;�[SVV��-[��e������Vy<���Wm�\%M>�B�fx<>��>��c***��t-�Wvv6���&������������xUJ�7�M2�*������U��V����I��?������I$[���k[j��(0f@�a���xY>�/�l��?)��c]F���l������������us��#������p�#�B!��-[�����p8hll��p�v���lDEE1`�����I�kz(����g�����
0��n�I�~�������b�����D�����w/k��a�����Vy�^>����}.��n��F��v��?������C.��������z�j��m�����|!������7N�<��E�1b�qK�r8����l����'O��*����7������_?�KD�HpM!�0(--�o����lUUQ_y������.��bm]t���l�~�m���p8->��Ri������@j�!s��@����z���s��D���T�+h>�a2���2�F�o����$F���5}I���b6����SzD���V����S�.w��rg������1E'��B!z���R���o�|YSG�e���$&&���}���,�6�;��={��-jl>���~JJJzD�����SOa\jUuu5O=�`��M��5������������SPP��I�7n�qK���e��m��W^�����a�������S����:��������}C�jjj��q#��m�G?�Q����0�B��y�^�/_N~~>^���A}}=


444�v�q:�����;v��r�

Dx���������v�����ZJ��io/��A��?l�Fv��;.I�b
���o����m_��X����!���/	�B]��k���	1)X-��%���a��ST"���[ds���i!�B�-99�1c�0n�8�NTT�b��S����@AA��M���p�y���Ojj��e=��-[x�������������7Z`-33�����!����`6�C����g�5�%�t:Y�jK�,a��5���x<,[�L��3��o��[o��Q�F���O?�����v~�#�B�n������������SUU�N'��b�ZY�b?����&���d"++�;v�2c�t]I��*��[K3�[�l��1j�qFt�Q�#yl�`�����'(u����J����}��<E��^A����2L���k�����fSF�`���K�9`	��5���Q�Q]��b�N&����B!z��2m�4�ZUU�������)..��t��k�q����^l��%�k��r�X�r%|���M=p������;��z((0
��{/[�ne�������*#G���G���L�:��Lmm-����q����]������+Y�h��6k�,^x�>��o��67�|��.BC2��B��7��?-q����JAA�d��Hvv�6��o�n���g������2������������������:4���@���f�nw���e���t?��
�.p���<0�(4�f����3}@�`6Y�cN�zc��)�?�~�bk�D�)2����E�G��B!4�%y����x����������9�|6
EQ8���Y�t�v`v����\][��l��g?��O;Xx�����1qqq,]�4��5���f�������K!3r�Hf��������n���������n0��o�Q+��/[)BK2��B��TU�Ndy�^�j���x�^�f3��##�kKt�����KJJ(++#))I�#��[��|G<���oB�\���b&F�� �n���*�7N����'��o�j�)�)��C]R_R	����� IDATX���d�?�a�y�8Z�3)
����[����YX�gS���q�j����c��iJD��B!�.��77���6��Ww����v��c�r����������_?���q�\TVV����]�����w��f�1�|����4����c����{��r���sO�������x<���dj�����������������9r��������a��z�y<���Oii)V��!C�4[�������������m����N������))�UG�{������<����:uj�=�l6'Nd���TVVr��������IpM!�8������Zs��_tLRR����Mjnn.�\r�aW����,��%@6�I0������D�P�m�����2�����g�E��I�	���2CIH)���F~���Cy��������_tD?���N4�Lq�D��4jC5�����&,��$�&�B�V���_�i��������~��������1����&S�+����b��1�v�m�����;�v���_����9���E�{���@Ull,��_u;`���|��\{����=���{Nk)��7��Mf�����?��Ojkk��L�4����K�������_�����v�_~�v����jA0�M�6�i��`��Q��g?���*77W���gffj����$�b��o!����7�g�������VDw�g�����VB���M�#p�.M���(�����3qW��n���jVH��Q�����8U����**��]g�Ei�����)=���I��h^����;��������j��%
I`MO	���1N����B!�0�l�:6�����M����+��{�V�����N�8��n'11����d������y��III1.������������7o�aG����������;v`�������}����b�
�x�	�/_Nmm-qqq������?��?����u[������E�d2���$�}���y--
T-�!�kB!�i��MV�5�����jEQ���4h�qYt���l>���\�z��Q��b]�ZT��h���e����-T74�Cd����~i�6J���6L���5������ x�9��j�������*k�I]�8\��YC��d���we[���s���|�c5'���<8���yu%>�B���=.*j�7���'����������3e����},�e�����r�J����K.i�s��m9r�8
���3�X:���������m��Gi���'�|�r���Gmm-���>���g3th��,x����x<<��S���������������mf����l����+V�}������;IOO�������m���<�������g�����e�M�<���~���\����i�.�e��Q^^��%K�5k��rK��(//��������4f����s~��B����ri���A���0�N'�x@�Z�Z��/���o��F���d���RWWGAA4n�"]����������2mf}S��.=.�/����aR �v�g�:��?�����,2.q�8���~?Z�X�����B&Ip�=$��u�5�W��������y*
��Kh�!�"tj�x��-������-�u��l K��"��<v�?����{��EQ�v;�����g�q��q���p�B����{�5g��i=*���w������nP;���FJKK��y3.d����ZWKHH|�����w���i�����8�,Y����q8�l6~���i_`���,X���^z	�����kaaa$''ST������{��l-�������!`��7^!��$����(������f�a6�	�����*fsp]x�Z���pL^���TNNN��k�+l8X��#��\��`�8L���o���gE7�������V��W��r����k���o<@EM��@�������]�n�@�T�oE�!��<0�(�(�MbL*��}=&
N��>����������s����B!z�C���,���k�}dk��k6l`�������s�}������p����,(k���2h� ��GXX999����7�x������]O�J��j����JAA111A�5���Gkc����v�����(=����5"4$�&�B��!��� ??EQhhh�f�a�X�nVTU��vgffj�"4�������}��3g�aG�p{U�����|Q��\�d��Z���8���Qaf0�C�p���}-J��7��O��+r��O��P�j3$^������k5��WZU��������7.u)��PO�p5[1�Ic���L��f������l��0�������\B!z�����8o
}����@.�5����]��|��_o5����_���K!�m�����_�m���]��7����������kL�:5���������w�����W"��pZ���\.�J�;q�o���q�I��>#��v���������&����B��f����+�~kN�����lFUUTU�j�b�X=z4III�/!�Yvv6o��6yyy8��������u*����yUV8x��0����
��[�E�����"��k*
���u��@��s.��t;���ti�6X��=]�C���{�
*	��	}��oW�H��C�_���`N����B!��=��~s�r�t��|��m��E%���������{���'O��p����je���K���ov�]


��n�s�M7�V}�����u�(--������<F���o�������E��S=���o]�������������s���bpM_
2���`��[L!����N�JVV�V��_*������f����w�cx��A�i
{=4��z{
kYw�2��Z3�O5����M���0����I/�b��(��$��n!2�w�r��4d����Qt��;��L�����l��R]pM��K�]fJ�T�Y�%2��9��:�����B!��M�-A9���M3��<��FLL�g�f�������~����]��A�5�1���?^�.((����l���5��/��<����}IKK#999h_tt�6�������NLL���P��5!��4EQ��w���+��wo�7�			�v�m�����d21r�Hv��������w��v�fM�4���S\=&	�Y��^�	lN�������-�v(g.="���/{-�d�u�����s��z����K������)=����o�C2R�h����x�n���=���l�qg�d��(����`�N&r������5�Bq���1��/��w��2.�{o�8l�����k���?����x<�\�����k������EFF�V����������t-
��O>i�nB(+))a��������>��/�)BK��B!�Nll,?����[�����+��W��#G�Z��oR�o�>�J�syT�?(����r�4PF��/t���V
����I`����]+p����&U7To����������d&%.�8��$s���31����=.��.�
��_���;Q�������R���4|�W��B!��E�~�]s"���4�g2������d��������UW]@]]�V&�������?�������5w0��j��_G���Y}�p��&�kV����@�	�;�(�B�#>�������l,[�Ln{}p������J���t;�N�����5�����4��M�q���t_�+�~��k^�z'1H���P��/����"���r;�|���d���	k�j��^���j�����X���l%-1C��<L��Tdw������g�1o^���X�N��1��$�B�>HA����`��il�]K~�!<^7��q��3I�?������k�e�������e�.��R�����6���r��a


�z���s�����ii;���u��v���w��:j��a����>����o�������������U�5��B!����\m<|�p�A�aRRR�J$����V�V�����������KU�X)����3�r��!+�6���n��cl�3�]e�Ep����������g�����/
Yp���]����������J�{�7�
!�����J����s������_p��E=2����[o�U�~���q8�����������f����
��s'v��#Fv�MDD�6������ ����${-##C+�Y\\������^����5��*BA2��B}�A}���E!++��}�����N�j��5�&���"�{������03����U�c���G�g�|^9�9�d��m�m����9�_�_�S�{���<����Y�����H���������4���4SH�MF�P����Xi��TG�#��)iM�)����Sl�qI!���0~�x&O�����)--e����x���m���c��m�� C���.0Nk�����K/m��V�\v�e�Y����
�/_Nuu5S�L!<<�C���/h����
��c�M�
�d2��z��a			L�:5�$���j�2b�rss)))����g������RXX���e������7o��/`������2z�hjjj�����e�;>~�x�KE�HpM!�����
*o ���);;[������j�	]e���}E[�-���t��<���b���=JJ�
�^7d�*(j=xP����6�>fC����+K8Us2hm��I,����%t���G�LJBvNFr s-�d�n�{x��A��[��,���B!�i7�|3_~�%����Y���S�2p�@��f���f���lp�����{���:t�Y���v���n~����t:Y�re�����,,X`�n���8.��2>��CTU����7�~�)��-3n�����o��_������kY��w@���/�Ppm�������n�:�Ng�}������"D�,�B�>����7�|������{���	����s��T_1r�H-�VUUEqq�aG����1I��&��#�������$d�0G�E�`1)�����<��Z��!�r}`|��4��R�3���o?|�_|�/!	�xJ�hcsr�"E��,die1
��������^|��c'��B!z������z�[�|9^o��6#G��W��YYYM�Z�V����<��lZk�E��`�"#���>�������///7N��w�����Nrrr���l���.���j�!BK2��B�i�����^�����DCC�����w�T\�}QQQdddhY�999���vu��'��c��O�qz�S���Ib��d��9�6�R��J�
�D���b1�'���s���_�.����g������5	�uFj|l�0�n_����#�?�����bS1E'��)3.5K�E`Jl�B!�������y�������+���+��,^�������'ea�K�Uff&?���������c�����a���7��l����c���5����G5Nin��n���t���8�n��j�*��f�������?�g�y��G����@xx8������JQf�����3)))�����FZZ�|N�HpM!D�UZZ���>�������r��z�(���l�f��}�vE�����YYYA���/�����(��q�:<���b�f��Nd��h���jp��9V^�/I��A�o|�a���������9'�5�P^S�]g��������66'���������.�����n
����_x�>c\iV���P,���B!��sjjj(**2N���(�=�t����N���l6��r�]�l63dH��DWJMM%55�'E�$�&��ORU�^x��������e����n7����g�}��)S7n��+�������������x<�N��8��z�6��5�[(�p��R����c���{j��c�	�:���St�{�����q�=�����!�Mm��[({b�����U�X,�G���	6�Y���s�1�j�����/^�s�G��|����>�{�i!�B�	{����g�v���d2��+����D�kB!����b8������;���>?�93�L���H��	��j�j).�V{��U{��m���zm��/�[�Z�u�
����
AeK�,d�&�d���c��3';$���y�^�����;r&8�<�y���������n,�|���������������t:9v�X�=!���D�@��l5�F]I�������)����zF��:l�4�k���9�P�������5%6	S�������R���o9P�[�s{��+��}�_�y�Zn����}�O�����e�}��|a\ *w&���%���B!D�eeeq��{�d��������B�!������YqW�^/��^�b�0a����gW������k
��Zvr���%!%k-��3���^\����l��s��>��k������o���Vs�SB�kn��?��_���3�}t;+W���?�fS�^����H��o8�~�W��.�<��]��$\�8��!�B�>7v�X�����B}{�v��I~~>6����L.��&M�d��)������]�p�\���q�%���(�t����[GEE�������t��~�%+�b��e���jX	���t:QUEn���S���-[f��w�^��&]p���k�o-�%��I��iv��U���j[�m�J���K�UG�q^V����3��������7���2���Hy�lY�e��3.�:E�:s���h��)Z7>�������B!�b�������<��#�������-[���~��-[�[;��zY�r%/��"���466���r�=�P^�����7�p�}��i�&ZZZ(++��w���;���0��B!Dd����/����+33Skah��)�������[�[��.�B�f�Bfbt���]��c	��=}�����@0�c��@I�p��|�Z�!sM����f��7���������]ga�*s�hm��A�O!�B!"]�w���Gy����:u*��_���������b��^����%��G}����Y�l�?�8?�07�p---���+��n���y��y���x������~������_7|E!��b������c2��ZG���I�g�y�aE����\������v����@�.31���`�M��f1��",����,�EA����-?0su�U����qN���e!�%�v2Jk���l1Nw��RG���8���Y���"����B!�BD��
�}��������`���&=z4��w���^����kILL��+���
-ZDNN_�5N��Y�f��?����<�u��seee��B���~��������j�l6�����_l\a�d2e����O����m=,	��%/:	����?��6��XD��"]�ZZR&�1�����z\����M�l'�sW�km�V�T�2���T���_D!�B!���
�}��7$%%1z�����~kEEEA�F���TWW3u�T-����I��x<������6���$''�!��,s��e���(���j%&&����j%66��LLL?����=D��������2[ s-[����ms`�"%!}�ZY���6�V4������f����������1��� z$�$�o�I��>�Xb1%���5]_�	!�B!D�����n������pm�
@mm�a%X[�YG_#%%���:����m��={�aE!D$Q����,_��gA��f�f3��p�i�����N{�C���S�j���Rl6�n���7�2��;	�z�����q���X�-}�Zu�o�.�����C��06����%!�������c�����l�����>3N�9}=��&�B!���S����n 66���/��t��HK���J[=���t���0���>����/^l\�����"�X��Y�[6���������a�������F�{p������$%%i��6l
����I��{�coS%V6����Q��)���-������0����
6>L��W�Oe��:fG�����*��-�J��������������+�A�'o{L:�!��{�w��������/�&��qK9R�}�6k�_d���	Q)�����9MD����B!����{�TU�ey�~�x4 IDAT�L[�����h���k�������_Nbbh�T!��R�S�Ne���Z�����N��t��hq�8�5�b;������[���}/?~L
���im+�Z��y
W>�KUc��YVr�n54�����M�[�����QY�Q|m%9��7)pN��Z!�B!����\k�,�(;�m.&�����u�������?���'77�o��Ak'c���g�����iX���.�K+%�`�&L���Y"��[__����i�	&t��Mg:��_n��`53��N��_z���X���N�
��������t�6��PS��?�K#9{�
�$uIa��<^s��6)&��}�f���P������	��fa	���'���~�OE[�s_~M�
g�q�K>����yX��W��+�hM_<�������B�����B��HB��2s-11������������u�����u�5\.�<�7�pf�<i.�C��#G�x�7�-c�z���c��@����>/�Yn<����DuC���q��[LF��k�����c�,	����@0&;-7��5T>}�5].�{�)���KIH����9=pN}����f��B!�B-a\S���,jjj��)m�9����������(,l�����G���a��Q����������/��k!����2�&L�@TTX&u�n$''3bD�f�������6��I���+����b�B�Y��"�e��ky��93:���90C���������{�#>[%�;�6�J����0r)	i��N��t�q����P������X`Q!�B!����L�>UU��a�6g����e���A�]�vi���$%%���KiiiP
��C�(**b����
���������~�m�B��WPP���L��[�����yp�'�k��K��M��Zfs�$�������]�ZnF��k��@��)y8����"��d��K�:q�u����a|����}OQ0���%�&�B!�������K��a��|�MZZZHIIa��
�l6n��L&\��r������xhnn��n��������_��c�=��_�����?�j�r�����xx���QU���SO=�� 77W�+�"28���CQQ��
����3e���_������T�����$sM\�����>s������%)y!T���D�k9����HI��1w�"�y)����qIm�p�w����a��~aN���^ 8�*�B!�CM��233���~���>�{��@\\�^{-�����EGG���MII	yy��g���Gkk+���:���*���7�t����>�������S^^����rB!"���;Y�jMMMA���PQQA^^^�dDhM�4	EQPU���&�?T�d��*����Z��k*�>
��u�A!�j&)�L���KC&��2����]����0��8��+��&s-�����������1g�����Z�}���H��������l��f���}��&�B!���6���d�������r���Nttt�EQx����l������h�"�?�|���0������4]�l��-��B!D�Z�f
������|x�^EAQ�f3�>�,�����Tll,�G���Q6��O?��q�8����5k����-N/��PU�������Y{�kO(�tN���S�4V��*���4|Dg������)�_�{Ex(�>���&SV���{+(s-]�k}EAa��8k���+��U������;�����c����B!�Bea\k���u3����kmL&���&�bh*,,�����%�=O���l�j��n�:f��)%"���*++�����O?��q��q������������|����Dd
��*������i�M�G}�Z���8�Fv��'�ke
N@��s��M�[~X�JtYc�2�`RzH>U����������3�9����k�>{��s���0�KJ!�B!��S���B!����QU�����������{����"������~�������r�t:q����Jaa!��?555������{�y������T^�^���;������Z����,��(�/��}��uA������m��������o�K~����bNmY�>/��@9R!�B!�J$�&�"�577SXX���x��~Ji����RWWgX�����_|����������zq�������xp:�<����m5;��>����X�lgaU+o��L����`5"�����k@���Z���
��J�����V�ZSb�1�
�������V���t��VC��yX�v(�!�B!�C���BD��@���]V���
��>��!���������iq�\��JAA�K�u�`�������(�vO-��Np���X`M2����@�Zu��W����2�>�}��	��k��X��o-c4�����9l$�(��TE�t�[f]f����6B!����{!�QXX��-[��eK���D{.�������$��BD���8����;���������


i��x�^������=�
�������vkb�H]����`8�JFb4f�����S�����+$��:�Fl�!uI����Lmc����d�����K���dRL����r��{%U����b���Lc�` �kB!���y��=�w�a\
[���.��+�����%����o��g�}�M7���g�i��k���g���<���$&&o8��7�`��,^��/������?����wbbb����III1n�W�������������FE!##��s��|�r�����(�Briii�/S�U��d2�(
			>��,�TS��L_[�ag��m6�a%������*lN)	A�&��I��L������a�D�w+�OZr�n54���%}V������qQ�a�Jh��Gkc��}B!�8���a����KZZZ��ai�������TUU��t��a���n��]KSS���n������J��YCII	�?�<���������<x�o�����?��d�v{��	N���{���{���Ohll�����*�y�~��_��'�o��aB!"��(\t�EX�V-;MOQ,�M�/��� �/mO�uw������J�����h�e����	)	9�e��k�6����i����agJt%!s3����������3$s������������G�K	!�B���{�RYY���f��-�����*�V��z�����y���6.���0�����#))���xRSS��-������;z�����'�x������*�����j�q�v;f��E�q��7s�5�h���{��>-�)BO�B
!�.��v��Aaa!111x<��-��Dtt4��������K
��l���������e�����)S:/�6<������T;T�LH���7"�
��!�����`���|Nh�6�:��Z�KB���2�X�B�?}������>;Qu��k����� �B�!��sS�R�W��7KT�q��Y�~�6���g������QWW��O>��}��������G��������7������%66������{�r�gt�0l���K>|8��Y�f�9t��}��q�����+ZV�m����9s��%K�������G�r��Qv���Yg�����E�kB!��������K/���_~Itt4���A{f����+B�$����>�|�	���DGG�v�����Ea���L�4)h]��l3��{������3�S�@�������G>f�)H��R�m��ZI�.sm�k���@�R�S���o�c�q}s
M�6c;���kJL"��4|���?{M�kB!�p�[xo����x=NO+fS���q���I�M3�"���c�v|��a����2�B�-c����|�[��7�x���V������g�}��)S������>�0|��3�BEQ���g��W���|����5+(����^�o~��n�*��AL�kB!����D���Z���Kmn��a���p�9�0k����)NMll,+V��O����Z���(��e%Z�V����.�qZ,�?����>���u�����#0���$��[��5��'*'�j����Z>�����T\(�����ZP���\�'R����tb�hn��n(�*dj��7��
s����Z����B!�z��
x~�4�����<�:����/�z�1c����P��q#^�����N'n����|�����������W�1bD�s����q���������JQQ%%%��Jjj*c��%..��_~���O~���k��7�����r��-��7�����n�:<�_�w��������	T����v�jkk�z�dff������� ::�#F0z������ng����l6�4iIII�z���FZ[���6������^������>k6����J�8!!A+k�[�n����~��	'N$==������k\�H�~��B�0p��!m������+����a��������^����]=�#Fp�-����4��y�LX������k�f����d��$�js`A��E}�������CrlTp���3P=��Gi[K=��@���@FS�H���SP������(�}pM�&h�����Ws��eD����%�B����������9�-�����Z<���,�r�SU�
6p��g������;��y3W]uU�}�M�6���op��7v$inn�W��n��i�����x���C<��s�^�4��1C�n=z��#��)���E]�UW]Eeee��kv��7�x�gm�r�-��SCCw�yg���y�������z�!JKK���{������+���A{������7n������j��e�����t�^{�56n��<�������QWW�����ls��Wr�e��������qWUs��������������
���'��
!�R8��'M�$��2y�d~���p�u�1o������������8������/4k13wl��l,�LO_+4J��K�@qj�,f0�����!���i�fh�Z�3P�%!����7L���c�X������^I����&Z��W�����X�c��4>����}����!�B����}/Po�2N���8xs�_��!�g�-3i���Z�����v�C\p��#,???hM��O?��,Y�D���g���X6lc���b��p8���W\X�����?+V� &�w��6l�@ss3��w^������/��<@ii)III$$����������f���x�^����L<����5kx��w�����(�L���Ams��NFII	@���Qjj�6����gG���}�V!�1cpMD����X�`������^������{��@�=����L�l�c���z���)f�����l���"���dJv��!�Lh�_c����M�C�XT����/	�F2�B'7s�6�����G��������.�W�������H��� �!���6QP��8�#**{���;UP���>ZI�(���2�����PzY���O> --�I�&�����l��������i�������q�������*++;|X�-;*33�3��Wp8<��x<L&?���������>�����i[�I��SO���u������Y�r%G��������������K�;}-%%�?��Ox<~�����)**"%%������3���G���'������\.�����Y�����IMM�������j�*�y��.]���O]s�5\v�e����A��6����Z��O?��'�|��o����>���wTU����T���O���\B1d��v�)"��Z��<y�6...�n�}��N�-p�3<�X��KB���:�bp�b���@y[�@�����f\J$���k�\]&S��>|������X�/}	���BT�^�`�-�����5� ��6�������L~
[!���Hy\}�q���Q&�'��;���q��p����VLt,��v�q�S6��;�UG�����(���1m�4���k�o�����[�d	;w���kW^y��p��-3���.����o����Z�x�X6�������s�N'���\s�5�������2�E�����z��~Hii)6l���o�Y}�d2����e�u�b�p���������3�n�����������w��e���f.��b8����imm���PL&$$���@ll��5C��tj�sc�
#}����bp8��F!�b:x���A'111����<#G���0���5u��r[ ������}'I��H��8�� +�����ta}9�����[�5��zN��(
�������3��f������Gk�s��N�n��qJ!�a��z�S�s�����h��w�M�6���_3�|m��4���d��m�<�i����3���
TA k-&&&�'[QQ�6>����q���T����kll������������Y�8����*���
F��3����?QVV��H��
���L�������4��
kkku+C��lT����$��ubp��5!�C��$��[�l��0i�$�i��������@PeD��d������d	�E������z�$.�q���������(�>��������)9%�w=!����I$-)��A���B����*�+��#�-���Ny�
Q�
(q=�]!�c�������9P��q��T�9���=,�|1Q'Yrd�h�"C^UU�$���#��<6{�l�{�9|>����w�y���(\x����������w�^-��r���s������*��|>m�Y�4}FUO3��S_�Y��[oe��y����^��?��_����������n��+**������IKKk��
=�_�/o���/��R���7}�t-`��F����?��e���%�5!�C�1�&"�>��?�=�e�Z���x�P1C���u1��3���]��*�f�R!~:���/��,�Vc���������\�~k+'c�\+�.����v������6��z�\B!����`��t���+����g�����Y�4����f��=TU�?3�sN�����D&O���}�(((������m����c���86m����m���nGQ�,	�����k���-KM����c����'�n\L�:5(��L�+Vp�]w�����s'^�W����l�����Yc\������KQQQ�����8-�f�ZQUU�-���u��/t�@!�bI���i����������V�j�T��\��[K8����"2d$Z�:�cOU��Q���00nhq*E�~k���Z�u����>����Z����t%B��))�8���7��B�.9�:�c����X�V�7�V�t�Z�~�6���l�VRUU6o�]���0[��_�d���Zk��M�?ki���~�Y�fiYW���^������k���O�Ntt����h�L�����lF�	���***�5��Bvvv��������������dm��(��������F�����vDx��5!�C��C������w���UU9t�3f�0nk�f��p�y��\��[�������d���ky��Q�NXS���'�c[>�Pl�%K�ZIu �����i�P���RJ�Z������^0��bJ����9T����#!�CElt+�������&g�AKT?8�N��Cw-n���J&			����<��y3�_~�n.��B��[���b����v�i�����K�����b��E�_����2x����������C�x����������2����u�c��������m~��1<��#���x�b/^l�n'--���f���iii��\������0/	�	!��%'N�����b�S��'���_��k=	���Yk��Q�Y������5}&���)V-�V�+t����(�����)�Sr*���\K��Z���k��G����M]7N?i�B�Ew������`
�B���W�B���O��>������%���=�Ear�l�8����^��6n��������W^y��#Xee%�t�������)((`��MTWW��*�����O��:��������i�&:�c�=��������T�e�]Vl����r�}o��PXX�������7n���S\3l IDAT�$�&�bH�~kC�>����ke
�~k��[�?���eo$�/-"����/�e�����-��������jo@�7h���z#�G�(&T��������i}w���r�b,�.���c�(��
1s�&j�,��B!��xK���9W����4��U���ggI4n�w���a���o����m��k�����,Y����:��������:
���f,X@aa��_-..���,�M���%KHMM5����3��������c�e��)+�_���f23{Q�[G��v:�$&������Ct<&L`��-|���v�������p�gV�`"�5!�������b���AYD6��.**��pt���>smDJ��b'�%+p,"F�����3�������!����3�����c�qNF�3��YkJ\2J\J`Q��%����Q�����V\U���5���=�#{2�O�op�%�B����:;���B!�kT,#SB�Uo���TUU��f7�|�aG������n��t�u�V���Z,���v�g�f��a���c���������|��_���~�%K�p�m�������C\\3f�����b��]TTT0|xp���
�2��&M����3qqq�x���,\88��$%%i����o}K�zrf���K/����[�lYY�{n��7�x���;����51���B!D$QU�={�h���5�m��Q��������
;��S����d�\��I>70�[C���X+�c6�����NH�����Z�g3�������r�?�[�3L���%��K��ut��B!D(}��'����5�9f��	����cG���lf��E��y���i`JUU��}���)++#??��^z�Gy�?����o���>�JV��+��EQp��<���l���������Y�j����K/���w��|}�����q#uuu����	�������n�:ZZZp:�������@���JOO��s����|�/�����2v���o�[���o��A>1�H��B��T]]��5k���op8�|VVV��Ddj���V�����L�6��+��`v�1sM�kC�>s���a�{H�;��Y�w�~\�!�`,�Q��r�2G�VCC������ql���qTR���	�a#������u��*��B!��fc���X�Vf���d��9s��m�/
� is��������%K���E��n�^������y3k����{�	�;c��������W^����?����-\v�e�^we������QTTDss3�<���>7�x�qkX������.��W_�����������������su����������s��1���y����[8�������g���d�	!��87n������/���phYk�o(��3��t�z(��7q�Dm�]�5�j����z��k��/p����m
��2]�Pb��%;p\�8��B��*�}�;����G��d�
���@�%��"T�c���:��(�B1�6n��e��y���f���y��Z����w���JIIa��9�~����-�~���y��$%%a�Z>|8�g����/����#%�_R����7�|���S���|�;����l���	)))�x��\y����^1���s�=��?��l\T�-[����}���?�X[[k�����8���>������������~5��wB2��BD�}��i��n7�UUQ����b��/� >>�����W�H��;v���i��zZ	�(�BF�n_�g��%�d+;�J��_~������F>'D����|����g��?CR�S�}�D���~k^]�7s�hm,BK\��+��qb�2d��#sf ���?��v�D���B!������Y�|�q�KV�����8��?�!>��8�Nvv6���/�����]w�E}}=;w�d���-���<^y��t��:�,�:�,��������r������c1��&�&))�[n��n�����v����.��+W�4N������g�qF�{���j���j�t;��/���.�����G\\YYY�������j��k�����>eee455���@vvv��<18IpM!D�p�\���������s�����$&&�
60g�&L����+77���^��#G�0y�d�6jZK��-��UD������lD����-�.s�qv��u;Oh�	_-��{`����}�8(s-��5����P�K����6�h������(�>�����m��a��
^7�*��c��O2nB!��������GNN����ZU';;����d�Z7.��$}-66��{��l6���c��oB�B!D��w/����|��������������i�aUD*���t�������q����$d���������;�iT(~j�1.�	�����@	����j��D�]%��)�/�E��&3�t�M}VcH������C}�P!�B��j��=��������?������������U!�`!�kB!"FII	��u�m�����""��I���g4���=�����Z�iG�8iA`,"�����/�9��y��6t���p�E`���Co��'��2SF�VCC@1���>*-#NNN�8�V��g5��9c,�J����
qpO!�"������3�PSS���k�����SILL�����j��&���/��������BD���4�DFEg������A�w������a����5]p��/@=��1'@���5���k5Mn��{^�U��!���))�*��9cQ�����5��6��t����G����yC�9'�Bf�n7������UU),,����g���Dn���~)E(�
	�	!����������(�������
+"����a�X�~|��k�sOj[��k�������I�@��Q�.-!�h�����������������Znf��i(���������&s��d�	!�b�KJJ��;�����-[���~***p8���2r�Hf��������3�\1��]!!����O�2�L&S��!E�b���={�aUD���(�����?p�@��Z�K��k�T2������t.���;�p��V�,f����CVY�>sM�1J�����3�}�����G�1���+(s���n0��
B!�J������K���K�KB���W�B!�IJJ���.�j�b6�W����(L�0�s�9'h]D>}i�����KB&�Fo=�R�`�<���00�����5GX��.h����V�T��)+�e&��2�B���[[�J���KM� �����4�95L'������J?S!�B!D����B���x�bf����bbb�_ccc1�L���r�u�i�!����>|���[�Z��$�.k�e7x�c%
��D�yyk%�6�q�������YGA����������%���������$��9-7x�9%��PR�������>�Q!�B!"���BD���-����%K�c����dBQ�=�\~������ex�
��CT��*������c��5���P��\��$d��`���r�����
tz�������3Nwl��`����E�����d�Ru��Tr�H��U:�Or3Y�E��w�Z��	!�B!"��\BqE�z��5��/���c���(�%�����M��z�PPP���������1M����St���~kR2��,j ��������3�6F��3.�)&��R���T�/	�9��`�����&)	6����g�q�����x�$�&�B!��|��&�"":tH��3�3fH`m�{��Wy�����kmTU���?�l�[��UFh�k*�6k{I^��S����^�g8�������a���A�A�Cp���R�}$8�6��0d�Ip-l��BW�v�?��&�B!�j$sM!D�������>�����j��&M��C����aC�����|>�d(���������Iv���5�1p�^�<?0'&��g��j��������'PC ��������0�]H8=x�$��BD�5�Hp-|���-�&��jHM����_�L]p��|^0����B!�"IpM!�����X�nk����v�Y�nYYY��6��Y�F������`3��X,E!�8F�$#��_B���>�&Ct�nX���������v��m�{i5Ns�@���Y;@9��d���e
@pMU�3��%�.�cIM�����g9�2�fJ���DU}�u��/���g�&�B!���Gs�B�0��[o�z�j�n7^��������v��*��og���x<�K��r�8|�_NOUUG���m�UU��a��]�_�������Uxl�cq��Dj|�gcG������8����P��q����q�[��]�P�5��:[�c�\/��5} 6�(��Q��>+�B!��H�kB!���B>��#-���z�z���n-�RVV�{��gx�
���������:����������YGF�a�4h�k\"&��
���A&�|Ez��Thw*_6�����Zf�b-q����LL��(1�
N����/��w�J��	!�B!"���Bj������r��z��e� ���kq8�"����k���#zm�-���:�,���*���j��V�3�8���3Nu�^gK�Vx�[����������\+������k��!�B!D(IpM!����*����������PX�RYb�Y�VbbbP������@��5����gE9V�y ����#�bz����>I_�/�$�������#��S���>s�'�kB!�B���;B!D�p8Z���J��i[oll4���`��)��f�J�����:�J�^1������������5�8����jp�H\���5��,dz�{��������/����������\�9��Q)�B!�J�kB!�������]FR�zrr�aE���wQ���(L��?���f�f3��.f������&E�)�u��"^�y%�^��d���78P2pe!�H��~,QV�������DC��>N��Vu;�5�oB!�B����%!�b��?������t+��f3&�	�����sSZ����.]
��DFEEi��������v�Y[I��,$��b����:�FUM<]� ��|�N>�b�������Q�h��r;���h��\�Kp-<����DCA����2B;��kB!�B�H��;B!D�QU����ZGEEuX��-��p�Bm,�����3w�\E�b�������d���{���N$�4��������Sy��~�j�q) qL~�S�����L��l��a�������$`JH���p1��5�����kB!�B�vjW�B!�ill��t��xP���e%��f,111Z������_B1QQQ�p�
�z������r���9{j][U��e�l�b�0+YI���/�WE��P�6(�wU@���Yb\��"]y��+	��3�h��Dx��?���P1�����3B!�"2���}O����e��l�B]]���>�������x��CN�{B!�@LL�6v������b��f�����(��v�a"���3g2s�L�N'/��2����m������Q?DQ�.H�� �R���
p�9�Y�����uG���z*�� h��8�?U���?���k=PP�5��o`����\FJ�nG�xk�ics���W����qe})��K�nG������B!�h[�l���?��t�p8p:�x<,			���0c�f����	0�����9=�����C�����������(~��_�v�={�����s��w������������8������k�[z����'�|�;�����>���o������[�?���G��Q�/N����z���*V�X��I��[B����'�x�[n����T�r�N����������7�P^^��n !!�����p�B�>������{��?�����~�^/&����Drrr�3g��~z������BJV���#Gr��q�f��?���(��>�����j�d2���k�*b(�Z�L�>]��K)t,ew��P��+NH]�f�f���=-��������l�jW�����Mp�G3R�e\m�����}���y������J���;�Bw���H����5l$���n%�G�0r�aW�iWRU%�Q!��������4���:v��7o&--�����L�:���������t����6TVV4?<���>J\\��jll��G����|���\x��dddv��^x���:����={63g��E��-[��m�V�����7���z�������i\�3


��������n�r�N�:V�Z������?������]���kk������e��W}}=����kSUUEaa!7nd������			�maK�kB!�����/`�Xp8�����E��g���o�?x!&N���g#��G��;�6A�g��������3�H���YL����>+��\�"=!��-�atL|����N�1��L�g���.���)��������w~G]S5�/�]&��.����(&r2�q�l/�U�!�������
Sr�n�B!����� ;;����n������fjkkY�r%�����|(733��>�YY���g��-<��S���^�ill��������<~��_���b���������l6w����p���r���o�y�f�>�l���:��>QRR���+��������9lhh������H�KMMe��i6��Caa!@UU�v{���L���i������pPUU����q�\����r����6	�	!��,X������o111�\.�I��Dtt4&��a��q�UW^-$''���I]M���$[S���H�x��5�z~""���DN�I����+_TP\���x��a�N��CO��5����P��_n\����\����������C��M�����i�����Evr���������X�1%g��U��G	�	!�"\y��,X�@;VU����}�Y���q�\�����u�]�W���[?��?�%����/��G}d\���������2�F�����u�3����N�n�����9r�q��M�<���������s�9��Lss3����q�O}��'���K8�����:�s��xx�����ZJJ
+V�`���������V�b����N?�t��������q���R__OAA���=���B1H(��O~��8�E�j�Kll�V
2''�;�����g���12�ik?��`��5�!y����(�������I���l'.j�vjs=���8�iq4���/�;���yX�����~��-�D	�(���_�����\�*C\�JC
!�bHivz�PP��[*x��r>�SGms������(L�2����[����]5����o���{�9������9p����}���e�C\\�-b�����1y�d�?��n3�Zyy9=��>�l�kp����7����g���T����k��,�����7o�q�GRSSY�t�v|�p��aN�d�	!����O��~�3����ba��Q�u�Y,Z���lx���<�_?]����

�%u�R=#SM��N\������Xg����������Ove���u})�$dZ.t��Z�}6cq�aT����3g��}x�n�0�B)T���6^�RA��g������������������EQ��Eq��VkE�{����J��W[�z/��\k[�R�^�nT[j�"����$�}_g2�9�?��9s��@2������g>��!s�����~�+;��#�[.O`��>�����U���/�����n���:��`{���c��������������'\s���Y�nf�����g���Vu���"<��d2��7���������;{�,'O�DUU���6lX@�;��CFF���X�V��d�G��Iyyy�Xddd�������2�555����8��{�=n����7���p�W��G��B����*6l������{o��;����Nn	�	!�����������>���8B����p��J	��/P��DN��^-Y\+w���8C��_�T5����m��k\U�{�X��=���?�StM�;z+k�y}����u IDATp��i�:���7�d�J��B�[��U����p{T��=�����wu� n�iS�<��2c���,Y������]kX��7�|S{�0b������3�����x��Wt+`��5l����o��9s���k��kW`u���Pn��6f������/�}�]��^�	&p�=�����s'��u�`��%��5K{��SOQT�?�7o��������G���G�����%))��K�2j�(��y��f]�{���_kYr�����K.1�h����qZZ�n�k���B�n�!� 99Yk�M
��ngy�61`��_P�B��"�z��h	��z��*7�q������CM�6����5�(����5��'��)�,��u�0��������1$i$?��������0D;�����j���B��N���=M�����`��
��4Nu���Z���p8������{r8���T����S:t���3����>��S���;N�<��� $$���2TU����U�V�w�^v��
�2��N����s�N~�����#��_���f3&�Ib)��w�b��������~@�]k\�{x�����W^����N����>���/g��Q�]��%B��;vL;�N;\D���p������	_)��}�8H�mq�?�|��t�=�"��}��Z���2����:�����p��������1��x�^���3h�q�]y
�Sw�+�'|eSL����+)�,������6�tM���y�����bhr��>�g7��*�UE�"�i%!�B4����Q����w��395�K��QU���Wk������!��m��P��9����j����������O�8��+Wr��A������ --�9s�0t��yGx����x<���dff���������w���9s0������j�*v������{7�����'?�������?��TUU�o�>222���'��K/q��a^}�U���{��)))����`����}����.�5�\cj��y�������x��b�`2���� ;;[x��1��K����u��x!��=zT;n��E�VR���c�����Zp�H^�Z�yo@���AO���({@pm��p0��
�U�eJ�9"�~��c���(��d����8�.��j?��m�����;L��X�I���DE�O�����Z�z�����I~��oc�tL3v��)"oe!���\B!���z//~v���m�%����e��FI�������Zr��_^3������>p����p8p:�����}�v��=@�>}X�p��Y��W5e���]*�v1����I���O��,��!+,,d��-,\�����ks�-6�W���Y[?����>}��8::�����e���r���l<����������x����y�\������������..�=�x<TW�������Bk���c����&L����^������?�B!z���������
��
�2K�cX7i��2 9�1T���
��O<�w���>����cc�����e�:�x��p�[k��v�2v������)�
,����������b�R<y�r�z��b*��~��=�}����$������f|������-:��{�r��7���9a�?�Vx����B!��*����l`���V�i}0��TQ-�NU0����TOOO'==�8��K����<o�����z���"JJJ��^����T.��R�v;���#|�qqq\q�����T9A��Jbb"YYYDFF��3F;������ykaaa�qS�����a�q�{�������?����j�RWWGii)�O�f���������'�l�2BBB�O��$�&��[�g�%$$�����y����JH�� *���Z_�����\6�Pv��*�C�d��f������2_�>l	������������b��E��
���@��[w��W_v�q�]�~�����^�?��:d2��~�)�	�����Q���{N|������Z9Q}�>!�Bt=�qbB-�����$������o�7EQ�&jW�z���x����f�T#O<�D�e�zcpi��Y,Y�D{<o�<>��#>���{�=�N��������)�`��������`��@k�>��v�q�d�������[�9�Z���/��[��PVV��S����\�6�6a������9�N��Y��u���m<��c�}��	�	!����$��`�b�������q�Ww�XAR��@]�+!�W�.��S�B��;�r������8 "4����#�{),�eU�7�I#�b����vP�=����M�Z���ZWK�W�6�	����m(K
���*�(�x��R���B!D�b��[�RPy�A�?�&�������[L���A�Mv�<6�B����0�{����'�r����o�2�������:f�ZwT[����p8������7o_}�������p�����1���M����.�P�� Nyyy��)))�\���0$$��������
���l�����������-���5�}�v>���;�8q�qi�#�5!���>�&%!E�X�PQP�E���k[O�l�04>���g���]X$3�����]*j����s�~���E�e��!�Gq��QTQ�=���_�/n�Ap����w'���o5�N���M�!���veN0�T���A!�]��b���g�ry<��\����q\R�8��Aa�������3�o����G�r��a���k-H���3�RSS��43���?��7���\KNN���h�4��Ml6III�a���o���������Hnn.���dgg���bx����^���^
������5�:u*��o�������B����������NKK��
�2'��2���n������\�yp,�Q�,���Aqe1I[#z�H��p��*��b1��ETH��'��h�C�O�Q��b3N4�]xU����l�ol�5���W�k
oU�M��Q)��d�;��f�8�8����kjm9��RLa��CB!D�6eH�OU��tE�U�qp��8�p�)����Ky��G�x<�^�����e\�������s+!!A;��������>�X��������������iii����s��f�k�-&&F;.**��t].B�m;vL;����O�>�Y!ZVR���%���m��u7�+���������������S�3�od�������~�]�Z���q0�08���0G�e�B�u��&e������b6���M[�������DH`���l�4R���4rTX�/�onWJhT@0MJC
!�=��sU2sF��4X���C���r��m����;���j�Ldo��o_����k��}0��������~�v���>c��/�(3���������@�
$�&������LKKj�l���-s�]���~�B
*#�z����RWW��\.����(������<�;��iB�`�i�����U���wQ�23��R��4��r�����.���8$:��d�'�~�� ��_��m�^�F�!�B���-&~4�/O�Ke���&���`��(�3��]�����UD���o&.��I�u�V���kX��X,
�J6�;
 3�����2�����SW���}]�����\�{8~�x-�����U�V%h��~��B��`���B�n�\�-���P��d�
AUU\.W����RWW��������?�<`^�N������������0�7���o�����\;����)2�e�F�u|�L&3�GE'�8�'�FR���)"C�y`��0y���S" �V(�5!�������I<1/���m0�^��q�e����������o��.W��{�)S�PQQ��-[�p��v��
������������C�t3�Kxx��O������+t��yE�����o���W_}��,8��}���:p�e�������kmB!Z�����g�
�%�&�*������S�������������7o�qZ�2�t�kg�
�5���?���*0���Bf�?����@���q����k�zh�\�K�H���d�����e���������>�
^��?�Oo�5�
���L�w�+�5!�BtQ���g���������B��Y�w�a\��
��m�q8���C�<y�qX��v>3f�`��������������SZZ���+���`��I���p��1����h��s����p^�uRSS1�Lx�^������e���������X�V����������7�`���DEEq���^/�����u��}/��Rn��F��]��M���o��Og��DGGSWW��'���/���x~sN�<��;������STT����k�����5��C�w
|1$�&����z�l������������Jbb�a��s�{9]�DqW�s�%
�%%%����B�V�S��bm� D�%`�O���1WW5R^]By��\KI���X�#�����?���v�4��F���pLi����|6��k',��	y�/����@a��)y��t�5))�B��l��E����������:u�VVO�� ����������e��u��F����5��������+���c���MG��������W_�g�}���|��G|��7������]�m����O?�����/���/���f����Z{����~;6�����o��Jyy9���k�<�0a����a��������u&�2����zn��v�T���]!������c�����[ddd4:������s��m-���+>����� ���j�IJ84�a><�uYG�g�f�f��39��d�)f����������CT��w[����X�
f]��9n �������8��	���]��__���h0��Bz�KPk�t�B!�]Gll,��z+���\���0{�#F���O2j��F���V+7�p?�0f��{������b����������4�/_Ntt�����I�=���o������f������M�z���\u�U<��,_�<��gKE!44�A�q�u�����r�w4�Z�2���#*H9����W_��
B�����������Z~��_SRR��������W��b�`�Z;v,�����8X�Z���;���c��b��Q���/�h���v����Jmm�nu ����ba��������\��{���e��>�sve��4{��>>��"_��e3�����"
������}�1���
��M�d�;����:�_�����({v6��b"��uH���m�������w?�u���%�����|�
���v��?�[@Z�1<����HU)����5�D.�3����EB�����Bt
��-D�+++#;;���j���6lX�����x�����ru���M�x<�>}���ZBBB���O��`k��������l������'<<���D����K{����,�B�.��?�k��n����z���c��mZ�V!8[�;������5Sy6����:��f3������������m��k9-�]�������+�4�33�R�WROuVj�5s|p����1P�}�UpU��(A�:T������O�		�	!�B�Gee%999��VQ�C���� 2���^�=��f�b�t���l�.�w�L\B������i�&\��o`������f��q�F	��n������8Q����n�	���d�������(X,�D�����|��������r�e5��}�4��J�9ac��d��BL���O�)�X��a��s�;�?�u5������]p�P��	!�B���x������b2�x�����B�"�5!�]�����z�x�^T���s����l6�������f���^�`N5�Un��fd�!�^�	���AVI�F���l���o��+��[��yr���5s8����se���\�x=d��)�������������B�a$D'SP��`�Yp<���x�5O�	��B!�hJbb"W_}�q�U��K\��$�&��Kk(�R`�����Q�D�^Y%��D�F��d@d	�9��q�vvd_BD}���>A��>���~������:����T�4p���3��@��y%���}�p�b�'�c�u�� �GJ�0-��Up�I���Q�����H��B!��<������]����Bti�����w`)��*l6�Y��y���@#Bv`6y�O����X�l�6���Iiii����K��a6�~��*�����fr��K����a�(x<��t�=I��Y��d����k��A�	��������"�A����*F��mZB!�B����;�B!D'8p ���(����j���K�3f�yq�w���3����`=�=���@�P���$�<�����d���|����������7�n5�wM���A�o�3P{�o�?�2���v������?�d�uo��(3�~�)�JH��X���B!�=��}B���L&n��v�v{�6����j�f�q�-��E/7�_8����
���]�q����}�OO?�4^C�[ee%6l��'� 333`N�N�1�������e?��i(^��~B{��\;��8
&���{�� Hp��KI����)�����s��(������B!�=���Bty�_~9����_���ph�����V+.$>>^�T!pXM,���8�KBq^��P'���Nii)���IMM
5558�N�^/������+��&���5��'!���c���-T�|=������8�W��l�; p��Vc�c��J���7��h0�
��g!�B!DG���B�na��%��G?|�lV�����(����������,!|��b�%��}z��ZS���DMM
�������zq:�x<��������9�;�����4�
�o�"������uUS��KI�g�����O
������I11 ~��8��!�	��&�B!��y|
j:Aff&6l ''���&M�����Q_c����k�����������W_������4�������������dgg�5X�ti�%��B��($''k��f3���c����9R��&DS�G�����<�1��K���~6��������|}���v�1��l���[n�E>'�b�te!s���xU��s�e��ks�Rs�,]V��J|T��- �&%!{�A}�q<� ���5�\B!�B��r'r���<��s����C��k�.�;��%K�������?����p������[��e��w�V:L���#<�����;�Qpm�����������������BtG����������u�B����P�s������
+��x<����i���EUUjjj())�R��X�H;
��^��J7}����?���
(	90a��9E&�k������%F�\�g�y��Qk�QB�t+�B!���	zp����W^y���P�z�)�������������?g���4����N�b��5�5�|������y��'y��7�0a��GUU6l��_��W�n������+8�~B!��#G�h�-e*����:�������]����x<��-�����(x<���El��H��L��2�?�z�ne+��$��>��9���\���� %1M;>���W���8G8��
O�),)�V	!�B!D�����~�-eee�x���N���p,X��m�����a�TU��;����
��W^IEE������O��[o%�#��;�x<�8�/'5lX��"�[v��/�����QW�����(�L��T7��Z���6��&z��h�����k	?�����H�3 s-%���k^��L���z�����WE�y���(��B��&�B!����\��o���1b���v>���#22�Q�[CC�kTUUQTT�������[�K�TWW���'�������^B�5dff�r�n\[,�Re���K}���TC����3�>[4d�7�an����l
%Eo�/��B�B�c��-��s�������:g���,x�U{PL���.�R�#���$�qg����kB!�B�� �e!��=@bbb�xdd$��P\\0nTSSCYYii��&
bbb�����������p����_�����SSS@tt4��sc��5�B����RSS[~��3�N�:��p�]at IDAT��9�|�~f����U�_�G}IiEQ�Z�X,BCC���[�9�{d����Cj>U{����q��k �����q���A`�Q0�KB�b�Q��{��)%q(���d�gB����#�kB!�B��&����������(�l6-+�9
������'y�k�v7��($''3g��v;;v�`��]��������/aaa�����F��g������;	���xy.Po�����`D�Nm��2���|�111\s�5l���}�h�fWE�]s�5PPP��NO��y��������S���w���#G�PU���DDO'����&3=O�.*w���������>���|��`
=���s����n�����l����;���|��a���?��1��u����y���s��n���Sw�YB!�=C��k-�z����E[5<����x�b�����m3f���g�e��=l���9s��!�"��^/g������_7+D��=*�����!���Z��`���$''�a����1��U��f3�/&::Z������#in/T�AT@��Be�
�l��\r?���r|fo1��o1C����I�/��o���5�d.�=Q���'�5P;�+;)��T�O;6��a���k��
�B!�B�=�f��������`6��q��K}}=�C����l��2����F			�!&M���={�����M��Bto
�a��;����L&W^y��!B�Mo>wO9Q9�Eq3���7d>qQ��K����)S�2e
����<y�W^y�����������-���ys�#R�s�L���(����F'�6 <p�Z�oC`M/�T�����v�ad��N��V|Y�/���.�_'}m���WG�^r�����%����~�;J�
HI����H�PUJ������`���g�����o!D� �B!�*�V� ���AUUJKK����PU��@�^DD����l
�o�i��p�M����E!D��_P
4Hk��d���MO�������� b�nU���.����l�#G��V�ct}��o#�9��km$�����d��0�8��K�'Kt����[}�UT2|�p�BQ0'���H�5!�B!D���ZRR'N^��<���:���	�����HQQs�}��()��C��OB���������f�h�3�����$$��t��w�y'�5a�/Z\;w�����'�X�&����9�?��y�u�j���T����L�����mf~p3��Z}W!�B!����F�
��_~0�����(
�'O��rrrx��w8u��n%�3UU^�����[����Z~~>��
p|%�6m���#�q!����j@pM����]�Dp-�
�q�����G���U�l�k��Z}98[��J��������2�LQ}Q����II���k�LiG�3kN!�B!:@�{�]~��0�}����K/1r�H�����}��9sf@��_�#G��s�N^x�m��k���/���?������h���K�����O���������NII	3f��b��}�vN�8��!C7n�q�B� ��������EQ�6o��Av�E�����?x����2
�[�Z���5/�l^c&���J�A��p��<�	Ct3����e�9��;��,�B!���zp�d2��������}�v�m���lf���,Z�(`mJJ
G�!%%%`<!!�Gy��+W��'���E��6mZ���3f��������l63e��,Y��(��B!�I��6p�@BBBt�B�N��CYM=��	37��V �u�"""HNN&''������h��z�cg���������|Y<�c��do[���m	
O��Z��z&}�Zf�qT����mc����\�V�:+Q�B!���k��������8v���k������V#����l�j���������.�eo��@ll,?�0UUU�������E�1w�\����S>�����SWWG\\\�'��3�1c�q��n��y��QPP����O�>����B!:��������������|iiiZp����\qE���D������>�W0^����T�3+���x��S��-�����`������s��k��
�rH���[�qL��(�P�����f(UB�B�q�n��g�}�����t�r�����f���;v,&Lh�^���~���{���0`?����������X,x����q����_�C=d�j���e���|���L�<�;������222��������vQz;v�`��5:�%K���j��r�\����p�]w�d�S�N�������SS��,��q��?>����g4���Cl������SRR���BQbcc5j�f�b�0���������c.����:�n7^���FTTC�a������z�N	�5'<<�8�Q��'G�>}�C�5�B�����e��]�:u*�Cl�?����L�����[k0|�p���+��UUUvx�r�*�{�h�4�xU��Y���nd���g���P�O2�z�[(�1��/=���cA��(�S���\B!D�*,,$##�8���N�>��M������{/�F�2.#;;�}�����t��=ddd����bRH�=z�^x���P�T�***x����B�7of���M&�t�7�|�������0a�^z�qI���u+��m��������6���x<�k����t^�u<O�xyy9���l����z��#G������j�*�}�SU���b6m���M��5kK�4nQp������z���ddd�~�zf����E�z���N
�	!�F{�������(//7N�g�F����0N	���
j`�Z�k��������������IQ��ww����q�J~����Z�<�H�������7�����S�$�M�}���c������B!�(>>���$L&555���PUU@qq1�>�,O=�4<�/!!��f�U�7�n��������nSp�������7�9s��qz������6��8III���`6�������o��
��������i�'O����6.� yyyZ`�l6s��W2l�0\.�6m����\.���?���/6�=z�(�=��v���=6lTUUq��!���]4��l�W\Arr2&����J�����?���q�F���X�p��i=���Bt_}�o��6�+9��x�� ������9}�4�=���&Z/��E��,1_0�����V���"11���|���&���k��2��[W��X��w3���Tc�S �N�h������4��C�5.�.z�A����������/7*�5!�������k\�/\���������������+���������{�|P��@��wC�5win����W�q�F��yy<^|�E-�����?���Jt����~�-�
�_�~��7b�~��_������S��TUU��'��/��_�e���?������f���SO=���G)))����?^�_����>���<x0K�.%555`����^���n��8������8p�+V��zY�~=��o��d���	n�R!�����������������vS__�����t��*g����-��R�3%������`K�?n%}i����w:YX��|>�}B���sz�0�
P����oMJB�d)��,�����=�������!��g�B�+��rHw@�v���������MQF��C=���;p�n�������o���qA�5���_+�C=��@hh(3g�d�����1b������f.������]v�nL&����������Y�����Z`��K.���o2�0z�h������7�=�1c��{z
��N�kB!���k�jMQ��������v�������6��i%Unj�^F�����$d}p��z��whm�Z�jO\��/����	����|������:,��k7�h�A��&��e����%b:�>p��,DuV�f�B��9O��+��O�j7�n�5p���k<T�4>��%&&j���n7eee��S^^+V� ''���m��������[�����~���\���"�����
�K���$??? (z��Y6m�Dzz:�j0�x<<x�����-[����0���t���������)**
��jjj�����V����j����;3����w/����TDDDp���c���]l�������=���F^�B�^����@��#UU�z}7��9�h��M�.u\T����kEEE����[!z���6�m}�?!�
��<���~��������w���'Q`�Z��/>:�{�.�����������bE��������?[!�Hu��[�Rw�eT�����`����
L����p�d���,Y������]kX��7�|S{�0b������3�hm�����W^���5k��q�Fn��f����k����]��ahh(��v�g��_�����n@2�	&p�=��v�����G�*X�d	�f��?��Si�7o��������G���G���%�\��M�x��wx���2�v��m V%`#0��x�
7���������{�$=�7�B�nGUU***���4�_����d�8�4��d=����ZLLL@e)
�{M�������Ru�������'/��FFU���I�=n<����.�I�<

)	��83��!��]B!z���Z�5���G;Umm����p8����aE��p8����y��GHHH0N����S:t���$���gX��|����X��]�v�p8����2�jjjX�j�=�+W������������;w����N{�Zf�9 8�(
&�)��5m�4����'x���((�����m��M�4��$���������s��Wjs���?��	_5�[o��MY���d�	!��t��FUU&���[�������M;S�"M_��B.<�1|�p����#G�2e�a��
F%�1ep$���mh�
�����g��H������e���(����Mf�q��E�3(q�{8��+,�����9H�5!����>p%U���q�yyoA�_U�:"��LUUV�^�U����+Z�l����'��4s�L,��s�=666�'W[|�������Y�r%����������3gC�vl9�����/�@ff�q:@MM
����y����3��LYY�V�b���/�+99����'Z���{���?����*���GFF���7q�D^z�%>������Yz/��"%%%�w�}��=����;p�2��<�����7������'O���2c�-�-..��K�<���3Z[��}��{�Zzz:�����RVV����9q�V��;���9s���cu��x!��������kf������(��f ���-�.qqE���^K|���Z������55���N����S���n��h�da.T�2(�T3Un����U���\2������=Q�.;13��5]�5	�	!�]@�1�u��i�P���v1�~1��|�q��E��p�t:���a����={�>}��p�B��5� k�����Tp�b���W;���O��8�N
��e.d����\{kh�`������?�1��O�GGGs�}��l�2\.6��G}4����q�X�`o���;O�kv����xrrr�������/~��|�I���p��|���/����#<<<�9����qrr�n�}���
L&�^{-�&M2N�h=�'^!D�w�u���w�a�Z�z��z�)��5_�1cQQQ�B4��U9[�bDcp�������4��G������]|z��8���x�]���t073�u��Zp����|o�� ����[�+%!{�A��9��^��Ii~�v{���B����1��N�'������IOO7��/��FA
����z����
�^/���\z����v:��}���������+.����5�8��j%11���,"##���>f��X�w�
v����/�L]�oCgbb���.//��k�r��� ������=�����o6jwa�Zy��'��F�ETT���IAAYYY�]��O?���n��h��z2	�	!��RRR����Y�v-v������AUUE�j��(
�����M&D���:�T�b��F�w�]���X������G�e����U���Yn������q�l5/���67}XT��5���+����d_�|�}�=�����\�$vli�5����PU/u�.r����r��������%D6�!��&�J�(Tl1�����=Wm�M�"'��{2����G�KQT��_�o�Q����'�x��K!v6cpi��Y,Y�D{<o�<>��#>���{�=�N��������dE���k����|A}�����@s^^��q������,^z�%�n7V��e��1m�4v���o�Aii)���?)((`���Z�Wh3n\7�����)]z��)������AQQ���:���g��5x��F��H�kB!��y��������K��3���������.z��'C{0q��9�.����������#G$�&���<8�wwX)��]��)u�a3��QQ��?F�W�?��
�Lp�������\��=��� )v9�������\3E&���P]�����XR�V	!�"xL���q�m-����M��5�v�{����'�r����o�2�������n2���jkk�c����C����y�����(,,�������TxIOOo2�v�]w������Syyy��)))��Q�V���}?��O����_~9��
����-'N�`����]�V;��������h�G��q�����������>�qqq����d����������k����W�����B!�
EQ�9sf@���}�2m�4���>~���I�=�&�%.F�[�
��w$�OZZ�v,}��^���3�.�L���<�����Y�w�vo){�[z��u+(�����"JD�n������t}�:��HiH!�����[.��c�a4��n'22�9s�h�t�����6�����e���Mf���f���o��������l&%%5��7��<��������D||�uXvv�v�a��Q�z�EFF��_�B�2[�~�����o_m��S����l0w�\�-[��e�.:f���0a������aE�#�kB!����"�����<�����B�^v����k�S^�+/??������ *z��1v����l��Sy�`������� �Nm���*���S��%T��8K���v�`�d�qJ� *����&�2��{#�f��E8l-�f�X��!�g�zuHpM!��)��d��r���� r�q4�Ea���<���x<V�^���������3���cc����>�X���������9v�_���q����X����]����������$������������j2229r���B�!���OO&�b!�]���jbb���E�)�d��wh��Z\\\@]v�^
���wvf��\��3��K��������u��d`
@�)����q��a�=Dyu)+�]�7�>��T �8��m^���n�P�w�'t������!�Bt[	w��������q_���4�t�0w�\����2��]��}�Ng��Pk*���j)K�-����Z���Y��'N����]�w��j_�wh���'���B�.E��g	�V5u^"�{�*��
"�0/��#�c}PX�n��ZN������������o�apw�?oe!5���$@��O��]X�}�u������f��-�)MaY.���/)�,4N�s�`�X2��B�$��&���o��U��j��B�U������o&..��[��w�^����b�0h� �W����i�����III�����:�����t/���1��B�3�e7������������k��=|����\G:p��v�/O�SIpM!D�����B���R'��%!#'����b���edd�fDo�m�������_��E�>s-��`��U�|����v���+Yy>��\���8,�����g��o������x}�
�p��g�y�KPk����B��)6~}�>���5oA��v/^�=~��7p���>�[L��+�YQQ��-�7e����� IDAT9s���w�p8.xcth����C�t3�Kxx��O������������������d7��s�V>2::: �������_�=^�r%���?���������2����k9}�4����;6pA$=��Bt���5���!�*��\k���
�yyyTTT������7�Fn�/�v��Ert`����r�+�G����
(\�(�q������������������������C��yt����G]�N�����PZ��Sp���
��B!:�����8q";v�����5k�p�w��a��m�f0t�P&On\�������1�������f�������r�J***�4i!!!;v����/Z�f���8��555�����%==���X�N�J�~��K�4������9|�0��������?���(��9���
����<x0'O���v���O�p�B���p:�l���O>�D[�u�d��z��;v�#G���*o��_~�%��Mc��A���QUU�����������������r�V+.����\v���������x��^Q.T�kB!�}���[�Li
S��A�\���#&&���R��u��k.z���-��]�b��:J��Mld�����:��l�ND����+�=x�N����8�{�C�k(
��!�g�$�&�B���h�"������d���L�:U+���T��UW]�dp����n�:�p#C�����������g������z��&��F�b����V����������>CUU>��#���^|�E��.���n���������_��_hs�f�jsp
��?�1O>�$555�����k��0i�$���:�0��Gy��_~Y�4�����w�5��3��oM�����C���P/^����=�T��5sr�B�J�oM�'g���

}��0�E	8O���h0@�w�Li��2�u���4���o�n��-���d�P�LQ��!���{�P��{f4���5�s��4d}�I��B!Dp���r���� ���+��5�[�1�'�|�Q�F5���Z��p�
<�������������X�`aaa��n%--����7�I����8�*��g�a���X,�s�Y�d	?������Fv��x����������l����M7��s�=��,���d"""��#G����^x�i����X��!���g������������JV �d�����UQq���Zm-���v�mo�n���]����J--�V�
j��lZD@eMB!��}������3gN��d%��~�|y���N������<�s���5�_T ��o8����>�%6hO���������>��S&M����IKK��M�����k'j�t���@"vb��m�0���T/4|��i���m����c\����r.0�0f�F�@}s��k+�K��<6�\�����B!��O�\s
�\s�q�S��-c��e�eV�Z��U���aJUX/���q)���L~���RWW��'hnn&::�)S��[�?����7���+(--�t���?l\��v�m�v�m�� ���/�KA/���qY3g����v�����g����c���Abbb�	�p���p�}��v�)--���	��BRR�����]Z�p!.�����'O�����(������Att��!A��s0RIrM!��PUUEuu�v.��D_�4��d���[�?I��*����y}}=�W�`���|��_%))I���C�\��w����,�d���@��)S��b�5������r����L�������m�R,�b�;{��l�}��h��{���p�q�_��%�&�Ba���Hii�q9,��������>%��a6��x;��`6������/V����L�r��������H�kB!�}���[}u�����=��%��k��������'���!>�EQ0�L���������������-F��16,&�OEN�9������j�����7+M��&����ZSLD��
�w+j[�1
���)6�����#�%���Qr������j����+6\��,�Xm���\�)*A�C!�b�9p��<��q9,&�����/�e!����B�3�����G�
��hD_UUa��"���g�>��c-��t:�z�Aq��������#=�Aq1��M
�qv���[B���i��c�Sn`�:HK��=.�u��1�nP���~`N�$��u4������AU��`�K����DO5���p�6U
Hr�����R���L�$�&�B��-%%�K/������n	!�$��B�.��7�x�>��Cb���������W��?6
h2M"������+��t�Xk_��������;�p�
7��n|B �v������d���)8yP������k�����@u��?�1gk���)f,��7j�5%"��K��%���d�q�D��*<v���sr6�c��=u��E�MB!��KVVYY�
!��%�l!������|���_x�^|>��P������~���1<R���q���[#����]~~>������+���={�)���������<���q���n�
����������:�_09`�.�0�!O�V���b_�Rk�@j�8b����D|������]������
!�B!��%�5!��JUU��Y��S���|�����������������������o.D��^��&�FkB��[����s�BiO�UUUi�c1z�O���hvE�"�����|��tRA�r�k����Ksj�=C������w��T�T��S���~�:��U��]�7R���h���5���
!�B!�$�5!�����>c�����J[[[�������t���ok�!�UQ}�4[�v�rQ �l6@�mK��v����b���%�0'�87��=�_7��2��@��C t������5sZ�."F���-gRjx��O��������:���R�������^7�����&\�>�	!�B!�"�5!��j����nUW|>����g�}fRc�V��IM�5E��I�&�a���ff����LCD��Qf-��8]��M�������%hC�<5����?��
����s�T��*

Q��r����QX��C��F���_]�1�Q��h~���jOCB!�B1$HrM!������z���^{E��S�!BS��N)g�%*�IZZ999(���j5��Z{��K.1D�hP�T��u\;W���kNw�OKD�
�5�GW��8�1����b4(�(0.�t�,���k�[��WSb\�@u����Q��B!�B	�\B1�,�}K�v]%/��J�k�v��D���p�m�a���X,��vL&�[*EQ�X,8Ea��E��?���h��jE��n�k�����]j	�:���X�no����q�����LUq}����%w�N��&�B!��$�&�bPM�0���J{�b�����!x�H6�Nm����g����}�����c6�q8DFF��f�k_��W��DB�X��������R�3�q��\����Sj�k-L�����Vm���Tm\�{��qI!�B!�8I�	!�T\p&�	���%���f3f�������k����1��������g��<���,[������j���8���N"##u����� +9V;7Y��Eif�d����'��5�	h+����kb�9w�e��.E9b8kb��]���[Bw�t�h!�B!�J:��)�B�����l�2�v;�EKJ�L&�V+v���|�+��=�\�U;.r�#6��Z(�x��<��c���?�������������.�R���bN����N�}m���tpd���z���S�2����b�X~���H�h\6hm~��a���)*%2���y�D��B!�B�q�\B1��=�\&O���(�l6"""�����p`�Z�X,�x��2�J���1��8e:Gx���$%%i��������R'msi���c+>�Knc��y������.��?�b����A�
V��{�{�-��YU��f^����7����}����.Y2�bj��B!�B�!D�kB!���d������9r$(�(
���s���h�mB�Mu����������#''P�������jjj�ZM��]��N����$�\���up��k���9)�b�E�h��6�_��7��~)�y����>���/�����^�����bS��YlD]s�qU!�B!�I�	!�mmm<��#l��������������b2����+IO���E/4��B�Jd���
o��i��T�	��	���&�8O���|�7<w��,�z��{�����d��P�!����&tb��Y��F,f�1�����m��������b�"��_`�>�x��hN��������N2��B!�bH���B�A�n�:�����|����t:q���\.����z��\.V�^��h�&D�|u�yk�m��H��\���O�UTTP[[����h|B`V�b�W�]}���7�X��k�ro^sUB��p���2x���a�V*�,�\��\-�n���&�
N��_2.��%s.�w��>�0��b�2���>���u!�B!�J$�&�b�����e�����R����8�N�^o�^!z�U�M;�o[HF\�bh������hw&�!��rM��V&�Jj�+a�2h>h��z��NW��B�J������Z*�����z����5U�{M��%j�����"t�Q��X�	�-T�B!�b����B��o�>��
��X��z�@`�aS�X�>�N�L�b5w�kl���$�&R��0+���HN�K�-2hO����	��T�����!�-��Ni��\��?�����y��r�)�Hl��Q��E��
v!�B!��&�5!��������3D����������}
��	o���
�G�\���
�P#���im��������P�w�j�J~c\	�S�ZS"�0E'��b4�n�0.�t*�*��2��f�����[U�A!�B!�I�	!�p���*
E	]I����0D��F}�%�1�tRu������������~���z�����h�L�R�����E?1����T�o8���yk���,F>�-��R��g��f�bN���zt�K�B!�b(���B�7e��fs���l`��������6�kYHf�C<�������Ak�������z�j�z�)�����b�kn.����������:�n�i�&�Jh��������5a�3n�q)�i�����E����V�B!D������������;v��x�a1@��9t�\��u����B!���6m���c�Zq�:�R1��X,l6_|�1,D*j�6���y�9'a��k>��g�}���bTU�������d�f������O?�<��"o�F���������>�&����u�e��iA26���#S{\�*�
iwW;�\��� F�+�����O
��`���d�M7.�s�T��6 �5!�B����STT�}��g
Y6l�����n��
����u����Gq��w2�|��{�����e���GLLL���^}�Uv���e�]���_n��'O�����p8�������3nT��w���?��1R_��C���'���~jjjp:�(�BBB3f����.�n�7z��w��kN���������a�����%;;���;���^|�!�rM!��3�L�~���L&,v�����d�l6c������X�����W"��#(������"�"?q��{�i����V�^/>�UU�z������*������[���h��:��R�b��aS����G�>��w���1��%6h_���W:����<���������6���|�����b�[������G}5���0��B!����y�f>��S����q&����������S�PHG���?�!���.���l���7���}QQQ�o���'x���hkk3npo��&�f��}���;��������z�r�:|�0����8~��1Ro����2{�1}�Q6n�HYYN��{���TWW�}�v~����z�j���JJJ������c���RYYIuu5eee������o������^zi�V�
��'!����q�����/^x����,+V����.Z�[u[���d�R�*����*�6m�m��t:q8|��,_�����9�����Qn\��he+o�����I�X!�Z�3a�r���)ou1xN�6M���Vbt���;P�7>|��
������~��C���6M;V[��5Vb���!�B�w���s��;��5UUY�vm��PW>���?�%��?�|V�Z5h�A��CTT���$$$`���[\ZZ�v������UTT�n�:v���7��M�>�l��~�c�~����v����4���������<���45�dff2e�bbbhjj���C�<y������Ozz:&����F�?����QU��7�����@�kB!��3�������Bjj*S�L��K/����������.$3y�[BVUUiw�������������r222�[�������;&*������g�i3C���%���-/���c'�e�?����b�r�Ewq�������s��*�J����=O\t��C������������KrM!���������m�6d�k555<��s:��tz555<��SZRf��%�u�](�����#�<����7o&��u@��u�]Gjj*6�����G�����f���l����Vo����J�x�	ZZZ�����_�:�&u������]��k�������/g���Ak��������;�p�u�a�Z���t�\B1�
��+���k��F�t�ky����o1:�����|�'STUEQ�3�C�}%��CQU��*�J[X81�f��9���)O��5i	):����������mO\J���.�>>(�5KZ���5OY>���v!�b�SU8R����6|�Jz����H,��I�����������#G�PVVT�4X���������M�x��W{��RUU�~�i�>}:w�yg���`HMM=�7Q+�����k\���c��5��nZW_��g�}VK��u�Y|��������9��{,�����3g2k�,�����������$�H&�5!����vs���|�������v����y��:q�+�P����(!�*������`���B�Z=���j�������1���G����Nyu�5KJ���PP�J����=-�cFf�C�����y�&�e���B!������a[)%���N��#-|��t���Zl[�l��������v�m�6���/�+//��S������)++�Fdff�TU����'N��*			dee���kiii���FPrc��-���K��3�%�\��u��xw6m�������			�w�}X,����|TVV�9bc�gKWWW��zIN�w*PU���|����Z����3q����MKK������CNNc�����hmm
ZKJJ��)z����3���Z�P���h������(//����f��b�
�|���o���s�w�^

�Kbbb���{�L���mb�]||�v�v��L;�t��!�������/[��6��h�>P�V����;����oBTT�'O����������e���AoB���Q63M��[�E;N��W�0��F{��� ���Ny+tm!�rMt#+m��\+,�5D�9-G;��KrM!�N�������tv�am��'�;�5s�X����}VU���7p��gSWW��={��};+W�J2l���7�|�U�Vq�Ei1���&~���v��9s&?��O�XAA/��"��n�i���|��'L�8�+��B��|>L&W\q+W���������W_}�'M���ow�|Huuu|�;�	Z;��s���{��~��_RRR����OTT�>�,%%%A{RRRX�j������+l��	�'p��ba����x��A��+����-[�s�'�|���t��r��glOh�����X�bE�Z��;���=��}�k$''�a������9��������~\_�8q����	��o���
!���������'�u��!ZB������v�Uo�|���L&�Vk��m����jEQn��fcX�09������)d=J�A�Q3!�%�y;����k8��KrM�%� IDATt'+m�v|�,��{�Yt�M_M	������B1�*\��Q�ib����[En��e�`;p��V��d�/^�-�o��K/�:�l���m���j7V.]�T[?p��<���X���'++��F[[��X����k���{��G���[q8z��e���45�[{_x����[��5kx��G)))a��1DG�+**��/��O>�������%11Q����xx��7X�~���p������������{��G?��V���>�>���\�Mq��p��v��M�6i�_V�\����H����B1@���p� �>�����c������L�/_��o���f�b����PU����9_�t)S�H[��n��$�7����ySbI�2�����/�7|�wL�{@��w�Sh	�D�c����"�����������Z���,a���t{��Ts��6�"PzqC!�����<��O������2~qCv����|@bb"999L�0�����e��m��9S������y���gyyyTTT�������WG%''3���v[[�����x<�L&����s���v����o�k#��'�f�o�rg6m��O�<�'�x��G���xHHH`��Y\u�U:� ..�����x<�������C���@QQ�=�'O���rq��,X����NBB^����{����/�_��e��i-o��V�X��
��'������_���~�s�=������g�m��;			���������Dk;�����Uk��m���#�|>������������-���\M$�&�bP�\.�=��O��+^�^q�@[�5����K�%��������d��5������(
w�u,�=B�T��#������c(H\���������y0w+����M8�u���T_8y;�������)����b�K�� �E�����|fL�g���|M�`����Z�+����}��8.�:�%���B!��S���������L����%PR�������HF���������M}}=�w��-
E!22��3g�w�^v��E[[[P����K����&{��m�t�MZ�c/�+����
�
j��]�,��.�LK��3������}�{8�N�m��-��������B��S�_|1hxKK%%%l���{��WKd�7�����c��`d������IKK��&M��w��C=�od��w��}�6��\y������k�.Z[[),,�����DGG�}���/��~~\{����Y��d2�l�2�
t4���B�Aq���^�������~��1]5O�;�*O:�\�Z���g��c����Gqq1���GUUTU�qK1|�<N�N�F�:�%��N[<NK���e�bM����#���|Nh�	q�����*���R5)��(&�R�q��A�hY��'�\��i~�A��F�������-��:�������,]\!�}u���w��TIm���pU�19%����?�z������%K�h��/f���8�Nv���J����"--���2�m��a�W{������V\\�/Z�H;n���@vv6��������~�2����UUEQ�7oS�L����s�N������-?���$	�S���A��v�����333;m�8s�Lv��@uu�!:���9ln�S���q�O��>#�>��>��7c�bcc�X,���q��)�?��
��?����^���_�32HrM!��h��0u��N�	�#A-!������={6�g�f��}������v�����#�T4�����+/x��'�9y�BB����\51�"2��K��_���-�K��HrM�'+-�\+,
�������m���S�[YD��D���`B!�M�+V���b`����^���ZK�����}.\��/����c��mA�5EQ����Y�f
���<xPk�r�����
���������1��A���
���;���A�w�}wPk�����'�|RK&���k�s�=Z�������y����U{�!�$��5����E����~�����5kVP��/��Z��1�������i�(�����o����'�UUU������~^{�5|>�y��I�\B1(�w�HKH�/��h���������zomf����q��k���ddd
j#OQy��������T�����+��Mm^Z\������.
$���@�������x*�S-�SuA!����]}�,03u 4o�y'����Gh��%".Ze	!����cl<~C6����v�S��>*��-��vf����{�25����*8��S����[����0m�4:D^^����;V�_x����������[�j���;w�����(fM%%%i�'N� ;;[�+))�b��K��[��1cF��_f��[o�����|>�������l����g�6��g�UcC5a2�7mw��������Z_����(m_CC��Q��3GKL~��'A���HJJ�{�����w���a���\q������XC�
�B�����c��i��\}�*��@5Nn�"&$9�A5����J�������_Ea���r�-��aJ-Ee�����	��h+�63-.����5N���n�$.0����kS���b���'&&i�'�����YPV}�Vg3�������/�]����%��HrM!��g)cl���}exM���;����sqNK&�����_;�,	�x�b:���l������^�EDDp�y��i�&v��EKK���l����2k���,X���kQU���z�%K�U���K��5k��n+������>}�.���FFF'N���rQ^^NFF����Y{F}�q4�����������<����9�EEEZ[������v�������_7.d���x�^����y��g�6bIrM!��+((�Z#DGG���Wt-!k=)�r�g^b��A���Y�n�v��s`2���{7yyy|�[�b�T�&i��k�Rs�		v�N�?^����Z�B2���������
�7C����wn��L��"��D�R�3��G��lBE��<������L����O���f�H�	!��w��L��c�T��H�m���)��S__��=�6��������W��k�_~9�6m��r���s�Ygic/�-[� %%�K.�������R}�Q���jbcc)((���^�m�V�\ixt��+���Fc�����@���I�&��SOi�"�e�]�e�]f\�W}y���;v,���477����e����o(����EF>I�	!�p�yk]�=#D��ZB.DE�Qk��p��Q^}�UTU��v��W��FSS/��=�PP�}1�y}^�O��?L��b���$�z�z�����'��9K�����������������*��D��DVZ����V�; �5�^) 0��'�B!��3)p�%���m'9p2����Lt���2pX;�6P�l����jjj���_6�VQQA~~>99�������i����c���TVV��*�����3G����n�
�����[)((����uP��pp��w����
4���V]$��J���p����s�h�"�y�6l�0h�5}�����h!�5!�N�\�_�b��T���.R�5UUY�f
���r�:WVU���������
6��]���:Yu��V�f����@RK�:-�	7��B�W��
c �n3��~�@5��*H�����J��%�j��y�$�Rh�	,C�RY!����,��d��p���(�i��Bz��s�cY:3�i�n�UU���7�����l��������m���kK�.%//���N�<	�W\����f����;���Bm�Zdd$)))��9��K�j3����I�0��x����z^����R��gLNN6������t�������F�/}}/��r�����*��9�7o���u����c}{��@�kB!Tcc�V��\��U-������0)�?t.����QRR�������q�\8v���M7����31��[B���M���H���8����/2��[��Z��(z������B�nO)D��������E��9i"���x�7����h�h
}�B!��L����q�����?�N�������.������w�������?��_�*6[��������������]tQ���o��7�d����s�=���}��������������)//�����y��3''���k�����rss9���u��C?��������
���aJJ
W]uo��/��N���K�vz�������&�r�l��AKFGG3{���
#�$��B���@$66������.F��m�a�g,�	�����;�Y<S�����5Um�c�Q{��������)b�:�KLJ������f���������u�������W�V�,L|������+��9M�k�g�������4V�����?��W�y�!�r�\��)�5!�B���h����l6s��e�������{�n���/hq���%�\��K����LL��������������|���8u�.����8f���9����m�n��>��s�n7�=���r���?������k�j{���:���&O��������2{��~��hS�L��p�����~Hvv6��{.��#G����A\��&����\���������:�7of��%L�8���(���8x� |�A�{�}����X�V�N'eee������B�_x���c�����$��B(cK�����G�����E�yk�C�
����#���]UUTUEQ�~�P%���e���,C����0>���������B'��������5��@��xtUk��DL����Bt/���b�������7W��4�+���E7aR�kf������8�>�H!�B���z��������,X��������s�N��R�\���K��?����c���A1=EQHOO����������f����������?���,���������/�LUUO?��q+V�`������-\����L���ijj��]t�V�2n�+V����+^����W�z�j-~���r�9��1���Z,~����3�����p��	^y������UW]e\��]wR������o��s�5�F<I�	!�P��H��1C��t����
�yk����I6EQ��^3��(����cG�^#�����B+�&$:�����6.0��x��+������9�2oM���������Z��U���{O����������~��`���&��SB!�m��Ek�?��.��������f��r��~jjj�*����X�x1���Z��{���]��#G��t:���g��q$''������{�������u��q����D�]}�������+�PVV���c���![Z��l6����?���|���!G!u��/��������v�����:,}}�v;������{7o���^�HKKc���\t�E=�2e2����b��q��3��.�(���h"�5!�������*�\�k������{���\?��kIIIL�6���<�V+.����������1������n@QLLL�b���_~v��i���H�"��I��:����:��T�&�5��%����t�����/����x��n�=J+�,=lYjI��n*��B1z]{��\{������v;/���q9����e|��+��������o\����������Z���2������/�l\i��E,Z����2���q�\$&&����uY��1c���o�;������	L������O��DFF�|<��y�B���������%�r�^{-W\q����|>"##III!""����^x��RH��.\���������'illDQbbb��� ::��� �V�v���M�kB!��%dzz����#P������)��B,s�%�n��V|�A����vk�L&v�EQ?~<W\q���b8;Z�3������������c��ye����/�lRX1/��s�0�tI�
	�C����Pl�=oY �f������������v��?g���Y��Fc�G�)S��O�Sx��}�
��B!�����b����?���Z�N�1�o���HKK3.�+��Nvv�qy�����f�
%��������� �4�B����O����Ku���C�g��m75��JNN��;� 22����� ""�����0n�8���N��6��[Bf��)�u��u���5��T�u{*yh�1\C���'��k���+���q��:�-K��WY�	��(	��>}���s�B�u?�=�e���7.!�B��?�9EEE����~3��	��B��g�]�B1"�|���5i	)��.������[������Ovv6���{���pW�����m�~1��+�&�Z�y}*����&g���[��l��OOq�b]�����8~7����_��+�V���5����}B�P\�x���B�>fS�>Z�S���!�����c�2n&�7<}lC)�B1PZ[[���@UU��?�Cvv63f� &&���>�����[&�����������	H!��BQQ---������>s�AK qq�u1����P����5n��6������~Gqq1���133��1\��/8��H�m/����?��;o����i����U���DN���gI`�]��0�;p:��-T�Y������	��������m��X&������������`�Z��[��0gL!�B�	n����l���QU���B
�����a��Ur�D�a�����B����;��������'c�����}�T�3��9o�3&��������%�����UW]e�)������8��s}[�������*|v��e3
3���|�y�>��O����N��7C�
�r+��@����=��8��R��l���o�M%z���������n[
�NKbM!�C��1c�������`�����R^^N[[ddd0{�l�?�|"##�B#�\B�/���X�n��m��������XTUEQ�j�>1,�ZBl^�z�Bg�0I���3g���?8z�(������v������v���I�=J;?���j����I3#S$$\������������?���'���
:!���6���tN��C�Zr�����a�`�>N'�<����gy/!�B�a %%���������B�r��B�>�����`��-�|>|>^����O>��^xA;�W���������_��`7n		���}����b8+,���N���������!��!�9����
�����"�k���]W�������I���x��������9R����v�U!�B!�����B���|>V�^MMM
>����V���p:�����t:QU��;w�uk���=�<��������X;Vs���C��(��3G;��w�.*�������.)099"��;�c��_�N>m\�@�����'"��SQ!B�5i7]�
���@�#�{�}0�B��)�h���������P!�B!�8�$�&��O>��#
QUUK��y�^\.{�W_}����<"!���ZkR2�����8������;W;>t���3"�/����,O;7V�]:=�)�Dpj�������~'����%[J-��8G�1$D�V^�
������q���4~}�+���o�;s�Y����A]D!�B!�I�	!���]�v�r�:$��y�^|>N������BtO�\;�9W;n������`���.����@RFO'���t�`RLL2�9o���IAk�Q�o���uEf�v�JH��.*���Y���������r��������c��vK�����k(�B!�g�$��B�Iyy9�oJ{�����;*�~��}����0a�&�,g�������_��%���l���I�k�&q��D�.�fQv3��8���Hc�O������9>��$D�((LL����7jk�+�h���fI$���y���
!�B!��\B�'����
G�~!��z�����u��		��-$4wm��}]V~���PWQ��K��M
_Z���'�h�b���U���"���>���?��$D��O����>�GQy�a��0��������Z�Vv!�B!�����B�>�0af��	f2����qv�!������<�VdQ�D IDATv3�QV-6���=[KJ���r�x �(��#��YP��H�����}������JlD �V�����B��������LV#B��I1��i��b��<6K;��kB!�B��`�'�������k|�A�{�9��{v������w��������O�UUU�mA�o�.m��"L^x!V����5����d"))�3B_t����
�y��������������5�����(*?��ON��E&%Z�U��]�|,!���)�V��).�����TB.����k^��&�B!��tr���_����"77����;x�����c�qk��^/O<�k���������{�=~��SVVf�������O]]��Y!�h5}�t�,Y���j�h2���l�l6n��6���[i$�5�r-��l�x8��l�o
)������0^����f�3>9������l���a���g�����x����.��oB����3�\3�*�<'%�&�B!�8��lr�����^{�3f��3���_��Gy������'�n��!l�������|�r~������Or�w�����/����t��?���^zIf�!D}��_d���(���f#22���H-�f��������i��"����
T�����OHT�W��Zqq1�����.��<�g�M�l
�&W/KW�v,��5��[a�V��<��,M���)���CB��]r���������T�V�>�.*�B!��o�&��{�=TU�?��?���w�O�8�/�����������w�%&&��n�IkUv�%�0~�x���������c��?`���������B�0DFF�j��Ui6�����r����K���a�}6y����H�\KOO'))I;����I?{j�.	�I����f7
�a�]����oB�O�m���l�S��KrM����D���i��K���dN�
�������T�a�B!�B�!�\��oc��a���A�999����P������d��A-���5<%%%?~���x{�1f���W!Dx


��b���O<��~�;���o���l�-Dx��M�����x}�����DS�|�REZC��%����={/e!6"�^5��k�LH�&>iwj���F��\@�������9e�v���kB!�B�3lH&�ZZZ���#55��*����
�`����~���8jjj�7o>� ����oB���..��1����jX��hlu�����l='T��=�<��mn_`}�'�������������,����u��)�$]k�%���/�-c�1E:0�����/S��������E��	!�B!��!�\����i��r��O�����U���f����"&&F.!D��Tq3{v�..���;�����{U��;�he+�u��<�L�:U{���x���5�C�a����1)$���E��o
YT����@�BPN��5��&�eH����~����<�^�.:p���I��B!����8����S���*Y��
���6.	!F��VUUEUU�v-��!j�</Eu*j����??�6�6_�f�u��I�zR�����S��}�0a���l����������SO����h���-�qZlf��6W��iAyS�����4��YT�1u��:�QO�_{��;���ku���d���������&&$N6n�wO��#�.�� � �9x����gQ!�B�YC�v����������@��������B!�SPP������
�s�*U���X;j	�����7�u�'.Lv{�:J���,�	I��P=�xK��Ti����1wU�vl�����YLV2&i�%�Gt������%��s�q�!�B!�<C�r-&&����\���Z��
�r�8WM/���WS����-�)������`������>�l��a����p4�)��������9M�L�:���cg�g<==�w�yUUiii�j����e�6���[�u��8=f���(���)y��v�d�%L���G�����xP��3u|�nRP]�4���	�s�r��c���q�
�u8?���4��k��q��cM��|���R��9y�s�A����o ~��C�T�
�?TU
���'
9u�?�a��EX,C2�0d��J[[6�
��l�����n���0$_������Bii)


�3F�=�������3ii�	�������p87����b�khh���H;�3g�.*D�L0�����w�|�:gv�Z��C�������*��{������<����lcRZ�aG�&%EP{����������0�+�6&���D�&H�J�F!�A��Y�u�8�dPl �3���k���s�a�B!D���_OQQ��w�14dm�����6n��g�ZZZX�n}�w�y'���7n�������w��U����_����#@!@�A��PF���Z�"V\_�����Z�*���QE\h�� 2��	H	�!�������s�=$�& ����~���9��M8�������o�`������zn8���>b��]��1��3gj��]qq1����?X�h����Sv���W_}�����Z��7?~<�g�V{���n��m�6���C~~>����l6���dddp�W��D����RZZ��b�b�`��PbccIMM���.��?��yY`��(���
�9�����[�����eee����SWW�������o_���<�r9t�����3F��B�{��UK�EEE���+F��P�yM��+����?�������Lu�����������8%i(�gY����*W~��eY�3��<
X��nlO}��E�{�����2��+�V��O�4ul;���B!������{�����Q�|^���/Y�b��-�Q���G��/�����U�Va�����EYY�~�)'N�����j�uSw�������g����Y�F��2����j��LQ�-[����7<��JKK������?NMM��Y-egg������/�u�V�������N�v;EEE�������b����������xHII	TVVR\\��Tx�6m��=Ut@�O���+���
6������HDD6l����������X,�����l6���~���_=���?X�d	W_}5�����
�����B�u����8==�ke��-�g�N��1^����g`�W���Uff&}��|��������.q>�;�
�
��
6t�{�8����E
�$��ceC���@��:�����O�@~.��
�%:,���2���1~�4�.���5L����X�����_�B!D���?ee�k��[�2c������(,_����P[���y��g������Y�p�W�vDXX���466��_�_D����v���*++���?f����u�]�7N��K6o��7�|8����9������Y�v-�N�������z����_s����ky������
C��w��RUU���{����j��1�H��s�u��|������RXX��lf���DEE1|�p���=����Cqqq<���,[�����EG����������}���$&&r��	����y�	&����|��+��{��w��
%��s�V+��;�3���^b�����z�cl����&�x�^�tX||<�����^vv6��O��������3y:KQ��-[�hv����1�u\��
cb��i��Ds�3sM(`)���,7H�����=\3��G��bi���$�dW��B!���_�^o����
�UWW��+�p�@������y�������Y�hQ����O>����9r��(�����CBB~~~�=Z���C�������g�9�����z�|����x��Ghlld��]�F����u��;w��[o���^z)��zk���v���7�i�&�����e0������\���+W�(
����:��~5d�����RUU��b!&&___�=:����z����V���6mS�N�����@LLL�?H-Z��E���B!Z������L/���#55U�C�.�Y�3��t�[Z��j���>3�I�.������|��W��4���_e�E�4��R���f�+<�e!K��%��/r��s��������_�+#��c���%p���Yu��JpMt���G�����T~O�]��1$�b+t��a+�/�5!��|S�J�A�>Pl4�@�O8������k�z|��aJJJ<2�zJsF��9���`��u|��G]*[�(
�����w�s:t(w�yg��NOHHH8�	.:��	�Y�;���zdd$iii�����AYY���W�kjjX�t�z|�u�����T=vg0�6m�_~y��~�������1��>|X�,���;��Ltt�v����o���fz���~#!����$dZZZ� ���>Q��SI�LN�+��k�1,)�����_��O���=����GSSS��������+�aA�n��������YX�����*��������7@��.v2w�����Bx�{����\lv+>�����5�\��kB!���^:k����?u5~�{y���o����NHHf�����M�����<����b6�HJJj�YGII��������(r��	E!**�����1�������|���j�RTT��M���?V��d��u���������3��&��AE�g?������=�����������?���<JKK���%))�~��y���F<Hmm-���2����-"���hjj�����QKb��v*++=������Ud�Y�188X=����@ill�j����8u��Z���/0���C�m��lMWk�<7<<���r��p�cz�;K!�EQ������#G��
�U
T�U�>=6��zW�A���.�g��(�����������w8���p�%�h��������C�v��_Y�������V�7��Xc���y������J��+��_�5��a����^����|���X����30������JS�v���B!�%�U��>��^�����A����Ea��
�7���v���������=7n���>`���L�:U]s������>��je���<������C�����������p������c�����+�P�z��+���o�Q��F�Q���������[
>u���x���	&p�=�x�=����������`���RTT��'>>�����������u���l�����g��'?�����������~�<���$%%�������#�
7����s=�:*--�M�6a�ZY�|9��~��f2���*QQQjp�A?���,8��YG�L&*+�������3��b�B!.��������6��&����]7�~k��n+e�Fg���^�'=��
�����'��k]+K����3��C��u��tg+�Q�>��!l<B��&��~!|
~Ht���9��tI��d��
�������%��Bq���~`�Yc>���999jf���;v,������>}��#l��Mk��l��f���5K������'�Tk���0???L&�X�?�G`
��rO>�$��v�{An��
4440e����q������SO=EQQaaa��������x��gy������/���DGG��x6��O?���?�\=�#t:z��#p�<�������z���X�v-������n����������;�f�������u�;��v�|�M>>>�|���-�$sM!D��?�8p���]Uz��4r>aL��e�g��p-c��1�_�v�G/33��[��o�>�v�Z�B�N5TRR�
w5�V|�Yj���U9o��lE������oG\U������H��'�KA!$��&���/�r���4�[��MlD��.1D�F��T���A|8�	!���l�������3m;�D^	�.f�$�o�v�������~h��!�������ng��M��S���#��{7��������7k�����c��Q�3���_�f������/���_8���o#77@-=�.-����Y���S��������#�l6���1b�\s
QQQngyWDD/��6��|P��Baa!<��#df:���=�+��Bqq1����F��/~�������|��W����|���\y��j@k����;�U�Vy��4�����w�e��-���+�{���7N��kY�x1���?�X,l�����l233��q#�F�b����:��2d����s8�Z�
___l6���������J"""���{8��~��m\B�%RRt���_�p��D����9/���e���j����4�&�h4r��a�_X��s�t�'���b��D0Z\��;�fWh0�	�w[��8jN��>�N?���\�xF�#��2�x��'�s�3+�d1�����>��;f=����=��B��')
k�6�YR�kB!�Y�����z���6#dM��v�>Fn�g0�#jkk��k�,Q���

b���dgg�s�NL&�G���Y���{7��^����5�#G���iW\q����s�N����3��@XX�/���l6�i�&,X������253O������t_fp��,**b��
�{��j ���z=���������o�[]�T����W����g/�x@�&3\}������s�N���(((P�!!!��������G���[o��7��������q���o~����{8�?o����X�B;Mpp0�������%�]�oBq�������-%!�74�L����4�\kV^o����8�BHj������<��/�����;~S������y��s�9��Cz:�3��-��l�C!����K����Y�������"�h�v�+�����B!D4d�\`�MP�E;���7b��gI�f��!�f3��oW��
�86m���W�Z@@�GO���Bu�Z����(��_]]uu�l�����������#Gr��72�|z��
83�^z�%N�t��w.EFF�Hj�z�\k�L�{�aUU�%����>�H
�bb\Uy����������qpp��JK��x��'<~�����m*�N���c�8q"'Nd����������o��}����E�u��^!�E/;;['$$�ZA��2Vl%N����)�ljy#�u�h#>���D�cj�����
���a�6QRu��WxX���.��W�����:et5����>n�����|�E���!h��O���'��W�N�{d;�NgE�CA������������]>+�}����B��C����]� �����'t],}�q�
�(�Z�W�^$''�kc���_����M�61e�uM��1s�L���SUU�����`��b������'O&((H=��pU�h�g�{FUG3�����S��/f���s������';;�����+���{����R����������[d�����������<���m��=j�<w#F��������~
@ll,��w����Y���?�������NCC�^{�z������9���G��������6�������_;M^^���*���,Y������e���m�
\B�iRRt�0�zu�g������;��x����{�=***(--m�m>�3M����l����3[2&<���3����U��C��L[�>u�����M��	�Ru
[5�mw�*]��A���u!:��=�QR}��c��L�]:+��dG]��JW��B!:G��:��{���C�3�uF�0�(�n��/''���r.��R����PRSS9p����TTT���6e�>��CL&7nT�k��o�h4����5k�������8qB�Rs�\	�����0W��a4�qZZ�G`
��S��v?�0����w{�����e��M��3k�\�:��l��RXX���OPP�Gp���A��

���W_H�={6��
��g�����+V0x�`xf����l��)S��lX��V��:j��!�����=��������3�R��z�(���`4=�
tW�nq����^[�	8��:��t��mh���g��Mtt4}��Q���EE�:|����OY��?-k�|�P��xZ�����pR��]� IDAT�[����V����<'���{Ai��Ms1�\�R�Ct���\�T����k����������B!���u<-�Ez*��~��%Nm��JC*������{���L�4	p�Rk`5��1bIII�~p��j��Z�zu����;w���F����t6����������H�^�g�]i��e<???[�r6^�BCC[��$&&������W?'W_}u�JO��;����U�\���/�9rD���;�`����r�-��N����Z�����TWw2�"&�kB!:%''G-s*MOE����=P��v�+����i8{�j�T�e����{������'g���WJ�QO3[M��������V�����)IC�7P�|F��G�����C�aXR�zl�:�b:��M�sf�������=mR����t^iU�}����.:V�z!��|z
���-p��`����B!zX�hH�=��v�S��3O;�mjkk�>R!!!���s�y�y�f�����f����u��X,l���a��q��A�V������6m�������<��S\{�����s��!V�\	8K�x������=���~]����}�{�������/�����3�1c�v���|��e���n+.c��%((��HAA�:?h� u��~L&S��E�-22R�\TVVz��m���B�N����qFFF����H��m��
���xO��"�������� f
�V�/D����^����������.�o��7(;u�gY;����3�����3�:$�-�j�/s�q�j���1)?WD�vb�:6�����#��&�]���z-D���q&IQ}9�N�Y+�`v����o�w���08\��5!��<��[���33Kevf�%-���f�~������\_[������c��!�\�>}HMM%77��7RQQ��($$$����v�������fc���:t�%K�x��x�b��og�9#
����m��{���
�\LL&�:v���N����h��������=��d����f���ngv�@�<��8	�	!��0����}��>RRtI�7P��v�����	O����(��;�<(�[��_�Yk��mNmm-���o��=D���o�v�M�O����8��}�K�����)I�������,;����F'{W=���9�t���X��j�HpMt��a��_������z
N`po�6F7��J�X�R��U�����������Q!�='f.D������V
��������BQ6l�8���V�Y]]��[~��M�5�Y�f�����C�(..��+�P�?j&M�DAA��_-((���x���Y�����v��c��i�����<yp~�qq]�;q��m6��/����p:���W������(
�\E��e5m��Y�f��k��r�J222���s���UWW�~ft:]�R��m\B�ayyy�[8~~~���iv���������~���2��QL����K\\Ht:j����,	�� �����r\ycgv��h��k�a~<=7�O�����)LVg��f��,��Gx����2�������c��j�3B�k��,[��v�]�%^
��w~���]
8j�0g�������wp����/!�Bt#C(����]�Q������p�6[����9����w���lf��m���?���U:}��1DFFr��)�F#L�:��h|��|��g��5�{�����x���;����?�@VV���$$$x���a��)5d��.g��gd<x���'���x����������V�f���=�'�|��1c����|���j/>m�I�&�~�z:��b������{�e�����j�:�j��l�25�3==�G,=$�&����KB���u����@�����klL.W]�@;}Q���T/������j�Z�k�>��d�c�5�Y<���������G�)3/[LI���3����������>}������pGx���8��C����
�@�T�Yn�q���i��WK���?�:��B!.�|��:n/k
�/gff�}�v�����k������i������L��f`JQ��qV��������QRRByy9�������?~<��Jg��?���,�V+O?�4, 55��;w�|�ru��9s�qg
��5��;�`��IOO�z6^w4h�L&�l�BJJ
&L��������W/""Z��������b�
�f3EEE<�����;������Y�n��m�/�^u�U���z���n���?PSSCCCO?�4����;���������b��]|�}�*�8�l�BHHz����F�;���[����A��n�Ms�h���Bt��(j���#G��
�	���[�n�N]4RSS����b�`6����k��5�]�����'PY[�]jS�����N�5����>!jp-����4�U����8�n:�`1���@u��Y}�vF�v�>�O���\�R�t�HI�|#����:���@����������V�H!�?^������,c�������5;Z;v,��o��!�UC�O�����f��Xs���HJJ����?�P����y3_~�%�=�X���:k���|�����{TVV����]���s���}��1cHNN������^�u�N�����[�k��;�+V`��y��7x��7��{��������qfaaa���`���(���C�x���Ut:��r�G��Y\\����y���())`�������K�!!!L�6M;�������+�iUbb"��s����%��N'��C
��q���t���kv�A�@D�8���i����E����������$D��Nw���
v^��E����[I�^����t�/!������`�Y.:��q/�t���D��h�����5��*�t�s#��U�i!�B\���[����Q���2s7j�(�:��}�����X���`���ddd�(��u���2j�(������'!!�1c�p��W3e�5�����?�Xs�����ky��Z
�DDD�p�Bn���R�{�1&N�����sa����t�M�V�����u��e�]�c�=����[����t2��{�����c�]||<�>�,��rK����{8p ?���Y�d	c���ni���/QQQ�5�E���3���_?�6q��&��C�KB8Pj0��������V�����j�/*jP-++�[n������&�����dU�u�}
~�5����g�=�Vc�Q^g!>�U��v<[���T���!�-�����y�����vV��<�J��Y����i�<�Er��j���V�O;�.{Q�vJ!���������^;�.�z�-���[n���e�v���Dz�!���h4���s��)v���n)���d�{�=�t�.��.��JJJ(--�b����7��w�����������~EQQQ����o�_wk�\�����=����s��7s��g~)������+������APP���v������>|8������`2� 11�����������k���k�������r������',,��}��t�d����"	�	!�������g���P�4��������\u��-##�N��(���p��q���OVO�����y��=By�I�2~A�y�c����]:+!�zG�St�Y2���
�)�������Q0f��
j\�&Ta� }-\
���:���w,��_����v�^1��g�	��.u�bn'`�
����B!��2o�

�O�>�:u
��y����z�RRR��?:���j:o
n��cg�������wB�B!.h����<�z�����%!Dg����5gx��e��9�7���NXX����g�[t�~	�y����c�|#���a��)�x�
&
o����Hu�^�-u�*�W�4�:t:|z�R2�?d����`����3Bt��?!�$,(��nx�����%8��3��[_&%�;�����zk�������IB!��������3G��.p��<@��}5�B��\BqF�}�������s[��.�K�������� ��|�o�n���R~��������3g�f��NE�G�����}�����'v~�i<��!	A�;x
��Wp�v��3���. D=��sf�����I��D�t�w`oC[�	�1:t�:��C�����������=R�KT�w���K��i�������D������SB!�������_���J�x�	RRRHKK#44���:������@��3o�<�� ������B�3����[(��Z��)h������`�o��O_233Y�r%'N�������h�.�]����S�f0��p�����w�����F��>m�[kO�X��[��{��[����
���cH��Ld��,�����,����/�*,{��.��;x�^��!�B���j%%%���*E���@}Q�]hh(.��R�B��!�5!��������������T�=
J�~������j�����\[.f			���SVV8�I�O���%���#;�q��qn+�+*���P_*��Ys��F&��i�k�~km��@�P�����	�	��7S
�t�������V�Gu�vI��'���sf�	!�B����0���>�����u+�����D`` �z�"==���'���0��K�kB!�����r��Rdd$����Bt�{p-�j��2��%����N�#33����
p����Z�h27�_�O=���@jB0�5��52.����P]�����@����5@��{���R�'b47�������p��M���i��-�C��@����S.U!������3g�)�/�L��B!�������D'o�op4��o\�QWQc�Q\cV�$��)3�U�/77���&�U�]����8	������^2����oM�>��z|FQW�������J��������a���N�����b���������$����x�KB�?�O\����4TkB!�B�n'�5!�m2��8p@=����kj68l�`��������_����c)))��8;��seS����omx�K��z��9�-�VTm��h�z��<�se��!�-��z�k,�Y��������jw�$�(J�O���7yp������q�����e\�_�������Q
!�B!���}: ��G%''��@`` C��l����U�=���	z�����`)V������pF���rO�:�Mg���3���tVrW��"gOB�dW	��t�^���k,�YP��	���]R��*����������#�������SW�{i��.!�B!��	�	!�h�{I������]�@��C��kP��[�%%![�^r��}��v�U�m5%�TW�3�w[�:<KC�]��|���M}�k\����c!���]s�c�M��������b/;D�����(���1�\I�k�����[���B!���IpM!D��v;{���7IIH�5��`:�:����ZU�����o�uiii������D^^�f����#[�qbt_b#�V{Nj�+�V��� ��c���wX���t��Z��.D|��#�T��XOm�)�t�8�+�{���K��Y��i������+B!�BqV$�&��U����F|||6l�f�]T��k2��<JB���'�t<������C���R�{e�JBf����f��k'�`����7�]����@�,�q�*�X�.0Y���*�N�IA�hi�v�K���Fi��N�(��1}�.���R!�B�=]�#Bq1p/	���F@@���g�z�k}-@�~k�m�Y�YYY(��������G����	n�=�O�B����v���OWJB6���5�Z��]g�Y�Sgd���S�f�<�%�[��S�@q`����B!�Bt���B��(�GpMJB
��VB�����Q8 �����@�s>L�����qWO0�=��sh2;?�>_�����������{�r�7��n����t��IQW93��P��=)D'�������	�}�S�fS{�u�[���F!�B!����B�p��qN�r�C��tdddhv�E�k�s����)�2�`vf��t���������0�����d���S�d��{��.�W����0m{�f!��*�W�?���b���3:�'"����~n����t�5/D�tz��^��nSbT���h�;M15h���0�k��B!���$�&�����)))�����
q����E_�=JB�
$�O.O�D[Rx_�������=\�a�����8U�N
0��������
��_���zu������ �C�Gp���s� �"E��2�n�B���������H)�3���k��eO�N	!�B!D���+!�-HIH�-&���u=��[������T�EEETVV����Ug<E����qO�[3�Z��(�c�����U�G�O?����b5��<�\5�j�&(x��]�M!�,��	|
~�%�M�#�_������`��P�5����SB!�B�e\B������bW���C|!�J�g��>"g`s(���-�zIp�#HHpeaHiH��.��r��Sdh,}����]g����O�Q����J6H��X�������5��-�|��=+D�:��.|���Gh�Xp�o���{��]�'p��j��� ��_j��B!���$�&���{����$��;WvI�6U~�G�}�MXl�l����\{D��4d��*���G�L�J	���W�N��V���:nk���^;�������]�b���/�����q��?�7P]k0�����������t_���Mu:&�]p�vE!�B!�L�kB!<HIH�=�^�:���,	9(>?����
-�����|�VEW)����m�qO����}�S�g��#�CP�/����BC6����m����6��t��7��#�d��9��n}�Fo ���N�%����U���D�gO�����B!��;��Bq1��������������ss�Q}�����$dg������pEa�����+
Jr�3�@���>`�fG�3$�N0���Nq��3��)�����k�v��.�#�������G��+s[�?���,���O�[��E�$�B!��&�5!���{���~pIrr�f�]T��k>	|�0�.oR�%��9:������������������^�	u[�����}<39F��'��������M�������3�����a���I����p�Ur���E�6���n�^^@�7�j��B!D)��>7:[���l����[�R]��
!EQhjj��p���
EQ0�L��3�L^���Pt���B���{I���t:)�'��=�����;�f�z�����9r$�6m ''������f������Mt[�9~i3�K��%w�v��<���P0�k�,�A��
!����J����A�����x)%;>����=JEzK��e(��=(0}��>8J�$�B����[����1���L&�f36�
???BBB�������3��|��dggk����On���x����:u
z�!���FNNk����G�.���p�v�Z��������[:-77�W^y�����q��iv8�����+W2p�@�������2�����k���s�m�1d���uw2��|���l�����l6:����F��UW]Ett���6m���_Maa!6�
��UW]��#��=����z�j�����l�`0������S�>}z��
W�ZEEEw�q�v�����>��S�j�������^�l6c�X�X,��vt:AAA$&&�����	��>�.\B��b�������^c����E���gI�����m_����������^d8p���L�6�Au�S.���xn�k�t]�8L�����Xd>��������7�c�]:_H�-<�]i]�?jg����/e�����#;����|5�����O�)lGw�7��}$�B�WEE����i��5u��16o�Ltt4w�uiii�m�8q�S%���A������������������_$((H�����:^|�E�����e3g�$6��1������������3f������u+��o��w���V�+� IDAT'���p���TUUw��?jjjx��g),,��W���JJJ��a���2������wv���1o6����"++����3�|��f�W�f���jv��#G�p��v���C=��O�!��������3g����~������������V�kV���y�Vaa!��m��O>����g���-��g��B!�[�bq�!	��7q�E���8x8/t��kiI���N������������p�4nH�	�4;z�>$��_��.���,����Yk�������z�a�>XmJ�D^������G�����m��+����Q����v9:�_!�?~�������������			Q����x���8~���-�����w�v���kO;/l���?���-�gRWW�SO=�����y���{,������`���n����V��,����/f��5��.y��w��Zll,����7��
,���455�d�jjZ�L�|�r5���W/n��V���N�N��f��\����w��8��{�=E!$$��s�r�]wq�������{��b�
��Nv����bEi������B���G5+-5�Y���?��n`���DDD���3�<C]]�����zXQ!�E��������|�D�N�\�����l���uQ/���n��Q������lG����P�q��6r���4=�z���J}�zz��D�I�Np��@n����N�� �K8�(�t�`i!�g0H�R	����gX�h�
�%W8�=��Gkv��}p$��*�J��A�p!�B\<n��&M��+�Bnn.��-������|��?�v����3p�@��y�j��|�r��]�]:#����%K(**�w��<��������m�6���G�^����.55����w���r��-_Tlhh`������2y�d���HOO������|���k��_�BNN&���7r���
A�N�8�W_}���y��'���S�L!##��^z	�?����]��V��������Oz��N��O<��hd��u��=[
p5+**�f��c�f������9�WWWGee%111�.���-2�n��6^x����KCC���g���{��<yB����(s %!���
���-�X�E������A`�O��[��#F`08{n544p��!���A�[i��)-o�z���Yz@�o���|�HMpez���q�Ba��0j�y�����u�:y�Bx�����'�������v�]>���B!D���:t���<jkk����N���Cy��G�,����V�f�����{y����Xg�%//���y���1m��-��������S{��yFFO=��-jQRT��y�O<v��:n�j�*���/�������V�9q�%%%��w�}GU����y��������g����3�Z��{hnnn�?���=�a9r�m�c|}}��O~�>�������Y!����4���5�i������ x8N�iI���W�A`` C�%''pf�JY��;T�C}�����7�1��f�=����x)��(C��&�������z��@���s�m����^��	�#^��_�����T�����I�������������1����}!�B�T[[��������q8�|jj*��zk�%�����x())�j�RSSsNJz[ii)�<�~~~��;��>���e!O�8���_�����{�m7��;TVVb���c�^��������HTT��*..���#(�BLL�
�P��vrss����������V?�&��EP(,,���@����R
D�F����c???"##���h�kj��l�k��JNN&99�c���	��o�,7��������N�c����~w&L���}�srr�>}���{�8EQ��kW�=�|~��������;�mG����d�\�kB!<JB2��BA���^2�'p���{�5)	y�F�������M7���}):f�!WI��}3	�?��KE���I�;p�:NMte�U�[�j�|�
����H���	*?��[�������>$D�����,
9c��J��8��4}�~9S}xA��N!��8�k����hDQ���^�'77�?����g?c����3����~sp3==�;�����8V�Z������~[�=���Gjj�fG�������
��W=��V�\���k�?>�f�b���-2���������9s&�|�
���>


{����E��~b�v���W<K��q���1C=����De�����-[��e�z<|�p�q��[JKK��6�������&�����_�~��9sMQ5[�O�>mf*���HSS�G�[3m6����[
�5�[k���5p�������O!���(
YYY����^c9	���Es��S�6�_Hp�233�`Zuu�q���������p����zH���p���Kl�+��W����Z:?�l+����Bx�(��������8���~�����;�A	[�6�s8B!.@


,[�����n�d2���F#6�
���;���8455�_S@@����?N�s�=<�����u.k����8pp������4;�?_|��<��w�&  ���H��h4���o�����l�2���  ���b��]���W�;�`0xgu:z���WwpJedd��x�dl�FkMTT�:./w��.++�lv>�i�\p��|����������[4m6����y���G��tHCC��/ 66�+��R���H��B\�8z���?�������OP�s��Pg�����P?��z�f��,,,������?��f��Ru}�J���Q�����������pt�an���LE}
���viJ��z��-��e����`��Iq~5hkv8K��;�������?�uz�/�	��'a�a��}�oEq8K	LX�>T>�B!DwX�r%uuu��v���;���f����;<�������(,_�\-=8y��v�!��oo3�f��i���?������0�U��3��[��/���-[����ihh 44���3k�,�v�������n����/z�l��h����[o��Y�fa0�����7�d����3 ����o~��[vv6/��2


������\5K��K.���^�������k����%K���f�����9��o��s���<yR-�������N�r��r�Z�Yz�����ju��s�u��d�n�����J������Y�~=v��]�vy��;p��Z����/g��u444P^^�f@������W��������c&����x���{�e���;^!D�h�u�j�*N�<������g��c���$dN��m���z���B7j�(����9s4;D[�KB�E$�s���|���;�e�ohb���y#s
 �2�KK	(v�������K�����7����j�`��wCoC}x�S
@�;�����l���B!�pR���7��]�}�v��^GV�___���x��W����n����Df���n�5999�t:0�L�<y�;vP\\@tt47�p��,O�=�Z3i���*�v6��������=���L&***��������;�{�����O��Kk��w���I�*$,^���b6��������x������y�����
8?'��5bcc[<;;�>��5X}�u��h	�\�=����y�X,�������G��7��q����s��I8��;<�k��w�����5K
�9r����{������wo�������]��B!:���w��U����_����$d��;����) ���,Zmqm����z����o+����Z�[���^�j-`�hUD��D��%�BB $�,��l��c8s�LN�x?���3!�9���?���n��j�*�����������w�y�{����g!Z�~*2��1�M���[�,iii�Y�P87��K��������<��@pwQj*q��1����L���2,�����Ixp;/�M���^V���M�k��X3h2���2swtJpM/��.���/+�B���|-�����a�q�����=�Z+""�i��%�["##���=�Nbb"O=�T���<Z������d/��n
Djj*6��#G�h����]Ktt43f���w��#Ga�Z�����������]P>f�m[���D��2��������db���bcL&���t:�s�{���z���Z����:u*G�!;;���-��\�<y2����l6������g������g��X�V\.����:u���"^|�E���?NRR���N��;p!�W���������(8\.���%  ���@6o�Lbb"���7g�
�k�-	9	���\��^t���Z�����o��j�����
����Y��|u�-������������`��+����
�c���+�����S��&
�-�&����*�A�i����#D�O����>�����0�cY��Y��,��,r,�B�5���]�@���<A�e���p��f����/:�bw3�����C=���~��|���]�P���M����{����Z|��6�������>��T�eG8w�~���p�2'���X�j�~M<�����g�z��	z~��\�����������a��)����8�N233�1c�O�����)S�`2����'N�h��*���y��'|��\.v����U�(((`���������g^g�;!��N�a����\�8�NE�f��n�:RSS�<�Z\C������OIH}�Z�� �����-7~�x-���W_Ip��O���T�B�0��aF���x3���7���
�	�����J@-
�!����<j��:�w��3zb��_��
�����-/$!��nF��$�R�i.'����c���I!�B\������O>I^^�q�EEa��
��v�fs�g
&�I,X���A�����o<���}�{L�4���zv���e�eee�h�"������`PP��w�nTu����e�JKK)//�����xfdd�},_��x�Gh.���*++�fP0����{��Gii)��(���4


����@�����9-=���L&������c2�c��Q:t��{�2c�-{5""�#F������:u
EQZ�s�X,��1���ZV�^MUU����������:�s�N-���E��=<+O�����y�3�h���P��� v���}�\�~ko����_����<***�d���,��6m{��t,-���i�n'�������<�����:�I�^+X���W�k��DG��?v(��_�yb'	��6��8&����Q8O�}C��2%�&�B�1j�(F�e<�bv��
6`�Z���~3�<}����X�d�a�k�l6l6���g���?~��G��u�V����G���A���4�X,�������p��i��Zbb�OyAYV����@�����1�������������k���mWT�}����EEE-?�����Z ���V����������C�8t�uuuZI�I�&i���>������s~�OM�6m�W��J>\B�a
����xo=�a����W�~<B�L �[���[�TIII���h�_���xm�����ZwsB��rc�`�x/�	��k�/�Qcw�������PsB���B��������W�����k������T&A��7�B!D{�~��|����?����n��-x�Z,���M���d�����g���r��;����FDD�q�uG�w�W�������kj|�����>��k��A���K��Mr8���kZ�z���Z�2<�2P�P6�����P�=���D�6���TV�=�A�������&M���U�p8l��E+�����	���������Pp:�Z���&�b!��N�[9������hV�:�v�2<%!O��Q�P_W�����/E��L&�)��`���s�\�:�	��du{��D�u�LA�7UO�m#�JiU��Z�������n�Ni��l��_Q�����&j������kB!��P6���{���X�f3AAAk�Y,BCC��w��c�O�����o����/ke"�w���Z����:���>��/��z��go-�n�:��=@jj�O@����$m��r���f��
 $$D�~STT�hiHO�F������\		a����Y�EQ|JB���$���'��-U__�U���,���W�Bt;������x����
#B�@mT����~S���e�
�
&���kQ��>������K�t�Bo��$dr����t�����Vm��2S7��������\���(>�.j�N��K�;��4v�d��o�����S��J�e��G3�B�����/~�,X@hh(&�	��DPP��Og���3�xZ�Z�x1���������l��Y@@�r��-��QZ�a�������u���,������_���1z�!��������'NP^^n����w/���>e=�������7���\PK�zx^&��'�jiH�m�%!A�������_Keggk�m}M��<�B����)S��ycMA-��f&L�`�y��y�{��^�����~kR��<X+g�v���	�uYb��5��
��B\��z��o����/
y�C�k�R}�yP��q���-�����*w�n����	�������&��
�/���B!DGd��%��������-/��+W�������S�l6|�Am�/�K��:�OfTUU;v4�V+**����fZC_�����wThh��P������r�x��W����K�`pSL&'��Ea�:]u�+v����S��={���h�|���8m�R��6m��C���<���������&L 00P�����)
���k���r�~�mm���]�����B\'����>}:��o'((�����b�h�.\����(y����|�;�/�>���Z�1�L����e�@-
9e���O������G��	�f�F��#��Ig������Gc���k�.�R�p�Y���1*�|N����I�s�h�����y��:����NQ0�zB8�n�qt3�a3�u������G!��Hf����lNZZ�&Mb��}�������7�n��
���������C���z��n��9s&���3�Rs����O>�������TUU1y�d������e���Z����onDi�A�a6�q��ddd��i�|�^
�V+)))=z�������p��wAQQn��A�Ok��~Haa!�>��p�B��!���=�����z��l��
����-[�Z���=EQ��o�����������j�k��u���RTT�o~��,YBXX��g��5���c2�X�l�v�������-	�Djj*{��%<<�����0`����C]]���
^���������E������\v���e�
8����Y�)�B\G�-[���g����f��(
n����e����r�-���.gA�n�Y���.���[����������<x��{���H&L�����l~|��������H�����t4���-���D����z����0�_�}�Z%�^]p��0�w`��h��R��%a.T�Px>�����FQ���/�gn�q|�ZB�}+	�-�+�B������OVVuuu|��'L�6M+���/��h��Y~�kn�[+����C�v{p-((���������v�y��A��#Gr�]w�X����3g7nDQ>��v����/�l����}���X�����M���.��s��:�VXX��~���\.>��S�_V��'�����w��^}�UEa���l��Qw�z����}�����SO=���?OMM
G�������p�wh}�����,7�5PKC������'�m[��\�4�1�VTT����'�cz���|����j��:E��@!�5+$$�g�y����[��n�X0�L����Gy���>��B�X�7�����x�*������s'e(���\4���k���<��sdee��;�uYb������Rj*qx�����m��)��`��sX2f	�������Jo�O��������#�}}��#�}J������P�/s����b����B!�*���Z�����7�h���oWM IDAT��b�������d���
Z�X�Vn��6�y��v??Z�|9w�u�z]��m�
�����*P��[������6�3g��?��?:t�q�a���������T����������'7������=�.]�s\�����ZZZAAA~��0����F||<3f���g��'?���o�+�rrrP���cxV���5�����w��q�����v�9s�����������L���)k������Iq��P��M��@���g����r5E��i��42R�I�����(���$++EQp8���d�j�j%`��_k���������#�����W~_���:�=E���w��4����3cuo���s�?�M��L-[�Yv9o�>���`~y{�VE6)�V(�D��R���fKWL`�s�������w���l��������f�����0��8V<�nw�QO�����V��
���g�xX\%:��-����-D����������/Jrr26��8�]\.�������
]-\.�N�������`������ZEE���GQbbb��l�3O����:���C|||���8q�����\�Zx�6IYH!��N���n/5 �!�����1�����N-�0:��V]o��������|+�B}}��[��7��������'��h��`[/F���Z�+yz@XG|���5���v���:�������Mop���
��M��h������ZNQ����Gf��������7IpM!��������b��1�L�����w��,�5���b�0dH'�;o������<x��p�]��S#	�	!����%!#�5F�=\�-	��J|�<��,�7����X����������gIHH0N���;�-o8~�
X��{cG���������-�?2��@35v7n���0�o���9���,��� �v�,!Zmp|
�C���tEqs0o7�G�7Nk3��+>Z�U~E��*�B�M�����)�����o�����J�kB!�hw
����������x�k��z5��F���(Z�����\.,�O����k.�������I)3u���qb�C��4�b4�0�if���W���<U������^��A�p�o�~��\�d23>���z=���;4�f���T��$�5!�Bt���8���c<�"Ws�=!�F\B!D���\�C}�A�"mH�7�6&��nR����n��ZcYk�q�]-�x=�)<Hum%�����3����&m�:l&�!�.&�{��c�t�"��X�������m{�7�v�#pVB@�����	�3�����]��.,f�aV�$7jR@����B!�]l���Z�O�y$�-�B��)��w;f	�����+�)����G%Jp��X,�����W,z�cb��;��r2��Q&b����m�������9[7�<X��<�.7q�B+�(�O_aw6�����y`�V��uP��q!�h��IZY�K�U���2�h;K|
��7�6�n�!!�B!�hT�O^�B!�b?���q��nYE����QA�K�|g�8Q-'�x_;����l&<<���d��5MAa�6m�G�����R��OLV����M�q����h*YqO~�g����
1�����������}}��v3��u������C��Qs	�
�a!�B!�h���B�v%�d���A�}���\������������J�>}0��b2�
�o��wK��_�Z���\y��?ex�?L��R����)0X7���:o�<g<��	�$�����nm�-�v�f�?����'O������`�H�=���f���|���xX!�B!�$�5!�B��������K�K��Y�������y�����l��f�f���f����	�l����c[��������e1�.���������NVQcW��5E��0�\�reG�����Vt������\����u�"_G��{0��]9�]x`�
L!�CP!�B�:\B!D�T��������������N�V]`���8o/6�yF����?��Q����b���F�������\7��l��'�����S�(5W^�[Y���b�2�N��n�/������Z�b{'�/f������k��Bn�	���S"��^��,�������B!�B�B\B!D����"f��ZTYE���#B�Z|K����O>���k}�Q�O�f��v_)�y)�<G��c����Y��nb?�Q��I��m���?F����l-�/
y9.����������%���7k����qW��&!�B!D�$�&�B��s�A�����x��8T�/	)���Cll,�&Mb��eZ���j������gh�	Q�I���n�O����su�-���k���6���	N��t��d��2a�7�v��+j��?:C@�1�{'�;��=K���B!��#�5!�B�^�������1K|�/�8}J���+���SHHc����w����>���Mv#&]����(�D�|Q��8|��xKL�����c��p������=�(N��m4��XB�������@�n��f28f��k?��nP!�B!�'�5!�B���U��������^_2*�JB{3fD���{3�233�����^��k+9R���?e�7t�����/	9��%!b��3-�x��)����2Hc����n�����}��h�����7h��;����m�-����(��S�A!�B!�h���B�:u'��������Wd�����
��!0v�XBBB�������0���y|nEmP�'4�����]���~d��8��%!=��b���s�#����x�	Q���V{��h}���swh���b��%.Y���L7*�B!�M���B!Z���y�CR|{0n�t���JI�!  �'{-#����Z���fm{��Y�L�{	�8������'o��c7&`&���w"<H���!���n�����}!�h���X�WzC�Vr���aF����f���E7*�B!����'B!���(.�L������v���K�.�&����D��9s��]PP��S�����Z{
��h�����(�lo)E��tLWzM��	�������9�;�{KE�_rx'v����z��P�P����m�+(�������;�4d��`R�����p�9l�!�B!��IpM!�-wq�����[�;��[K�!$P.7z���$���e��|�M���������l�����j��k���p�����~����]�Xr�<�`��M00*��c��Z��A��MNI�af;���m��>�U�v���]��5sD��	�C��F�B!��q��K!�-w�5�v�B���_q��\�W��z�Y�fi���������[����o�������w�\C���%!'�����tbWr��E��Tw�U�1�3#��X�*���i�C��K_����}!�hB�m�L�)J.�F;�m����=k���k!�B!�hJ�=](((`��
�����>}:�+e9Z"33���*++���e��9�����q�\l���`��0`��z+�����O?����+��
~�a,��Q!�B\MeP�V}x�(������G��WT���/�������FEwS�m��� N�S���fjjjx��7(++���n��]�N;������������
�v��i�l���0�(��d�fTs��xC�v�5
��@������CW������$�/f0������v��ofu���s���o���}�G�n��7�	!�B!��n	�eee������}�r��233������t�`�����u��JTT�v�b��<������j`��_$++����V+6l`���<���$$$p��A:��f��<���\BqR�t
����`	�����d]�����W}#�m�g��-;vEQ���k��@`` ���g���>cW�������%m� �
�b����v�G��v���
v����xs�9J���QL|D �z14&��f�}������_���E�L6�K�k��p�M�~T�r�?�/	�	!�B!����5����������?OLL�.]b��|����=��O�q��I��}F���O?��f���S������7�d���X�V>��s���X�p!��s&��/���7�x�w�}���z�������/AAA>��B��R�K�������d����j��+�JB����L�.N��>�P����5P��L&�V+���? ����u}I��!����{�g?��N}���AXu��:Z/��� �uj����+��	����b��cms�x��j������8K�V�4l&�x�����r]5��:7:0�6-��8���r�e�
!�B!�
]�sm���TTT�p�Bbbb

����`��+�_��a�E�[����m6p�@n��F���8v��}�aaa,]�T+79{�l����������>�B!��9
�~f<�P�(zI�u+j��Gj?����PSS��(�\��r:�=z���x�q�]�;���O�	%!�?���)31�F;N����>��kFG�^����s��[��M"|�ig��n�FC�F�������2��x��7`
@q�c?��0C!�B!|uyp���C�7��������Os:Dxxx�7O������=Kii)#G�$ �7A/%%��IQ�o�l��N~~>�O���v��	!���S���x��S��e�Jk�T�>���M�J�U�=�������d��\.p�F�GO��F����-���2o����-�~g��|w�9J��~��n^�Z����������Pw��/D�Mf&$����m�k����������82 ��=i?�/��B!���_������c��]���K[�)�s�\~[2�����no���1���styY�3g��s<<<����~������PQQ��a��C����p�p�����������wo���2d�v��?�155j_���{��c�]�F�B�V����i��*�C�|�>]�N�!���kxDBC�LBO6c<�&�	������h�����A�;��\s�����L1��W��t:]^��o	��]�gkNsG���m1��A�q@�����_g	�b
������|�^���c����!S���bw�{��8�we	��{V!�B\��_���'y��'�C=�G}D]]K���{MM
���c��<����?�8��6m���-[x��W	���v�Z������s����������3������c�i1��VVV�g�}���{�p���^�0��S�r�M7���v}}=�1��o����(�BXX����y��~czl������N'6��#Fp��73f��t���IIIa����!������k,]��'��Q]]���+����n�c��q�\�L&BBBHHH`������k�	�6]\����j�6�&3�L6[���
nXF�j�����eu}HH�~
����DmM&�����?����}�����O������m+��?n<$��F��[\��{���:��-{0�q��WT�
bO��]RPm��VOv5��q�\�t:1���f�Y,�3�����eN���������Q�5��?��]���}�K�@n�)�p��^��������?��x�U�,"���,z����P��6�5?���mN���w��������������\�*�W���[����a7��G	�OX<��s�(�5�g�N��B!��(
�7o������/���oW���������
7�n���'���@yy9�������u����������1cAA]������vm��'�p���f�jjjp8DDD�Z-''��^z�K��-3@m����G^^_~�%���At��n�Wyy9�����%)yTWW�m�6������������3�}���G����s����p��/^����}�=jjj��c�����2339t��F��\s89r�xXSPP������?������1x�`���G-)w���J����(J�����|�A~��_q�M71s�L�z�)RSS�|�2�����B!�E�����pKS\�H*�J.{���D��K��i��I��������b�!����'9}��uj��l23"i�aF�29j	<���_?p�n�cU���Z���um-Rr�Lp���V�U��9\�������
�Ni�Z����L�������A;�M�B�3>|����vu~o��P���~���z�8�������_�Z���1���������U�<�����f3�:CBB���/�����?���|������c��Vs8���+Z`-99�o��|�{�c���Z���g��r�J�q����/������#�<��>���������+��z����XKJJ�[���>�(�f�������dff�O�xZv�={���B������
��|��DSbbbX�x1��sK�.e��9Z&aYY/��UUU��z��]R��0��t�r�|��n����l��F����9� ;MO? 66V?����9p�g��5�����B���g�������E�]�l���~3��F.�X.��73>"�����L�Z\�����SPP@qq1���8�,��l�*��1�y�����*3���+�H~����S�h��N$ut�K�����'\r90G0p�]`�����+�Cq��p�z�3l�@���s/����hZ�~h���Z�:�������c?��JQ��������r;�������q�]�1����,�Es�8�0K�D���B���*:��M��`�f�t���r^y��&3S^^�K/��=���x����.��,����X�����������p������	d���.sss��c��p�Y�Vf����5k�������[|������O?Mee%yyy�8q���d�9�6m"//��|�rm���nb���|�������~�z���~m����
60t�P~���i�o��F�����+X�f����'��w�^���������^�-	�%$$4��[�|9/������Kl���;���gNO����>}��(J��jEE���
t������7��c�����U3��k��/����BqM��3���I?��>>�������.�_@@O?�4'N����� l6V�U��JKK��vUQP�}��om������Q�������i�5����e���7,��&��z�/~q��-w�|>e����u o7.��x�]�}����g?��nT!�-QVV�?��O�����k����*UUU���_�?q�D�+�CQ��Kn���?��g�y�M�5EQ���Hu�z�>b�}��.
�y���3g�"##�C]�d2����7��Y-Z�����5P�
�������Q�g����7��M�q�{��Wk��g����>�H{M=���
��M�2E��VXX�����?�^VV�������A���Z�,Y�D�?q��n���yw��HHH ;;���<�������M�t7�L���Q\\LUU������cxR==�^��'OD��}�COP��
!�=Fx:��15���V`w�9\��:H�.P=SXX�=��f����;w������������7�����+>�=�7ab��Y���RS���Nm?p�|�h��7�~�6
�Vy0���=\-M�n�gA��9���0��>S�hJie����8]*.��������-�Y��q�?�)!�����[!��s��|��g�Y����3���r����d��n)��e�\.�������p8���������w��9��Ybb"Vk��g�������)�BAA���(�Bdd$�&$$�w�y����������l�����������Y�n�6��/��B�������'��*�t��Mi�oO������.\�����mE!''G�?MLLd���>�����=Jee%aaa�����<�������9�U�s�\���QYY��WVVRRR���������u��]��t�.;q�eej�i���}�y���m�FEEg��!))	����z0`@��Czz:YYYdgg�����ZQQg��m0�~kz����;��XKxJe�ZV�j�u��+F������y6^�} IDAT3S�L�����L&�c���l�����t
�3fg��a���,Z�6����a��]DGG3t�P�f3�������?~\+���KAA��O�~�������\.�m�����B!�;�5���3��*�NH~�!.���RWG[���uP&��T�F�b��Q�~~~>����8u������v��y�?��^��J��~t�]�C����U�f��L������p!��{&�����mL��}8q����0���,�D���>��WP�/�9���_@q�Qj*��N��o�	!��`���|������?��S�N�����E�(
�7o����
233��m��-����n��?��O����2k�,mL���K���?��p0z�h�}�Ym,77�U�Vq��i�j�i��������2o�<m��vc6��7o��-�����������]�	*?����:SEEO>������t~�C������o(**�����W�^����EEE>s�����w���!Cx������/|R,\��%K�����{�=�l�����w�#11P�j���'���t��N)Q����������W*�tLb��Z�������$


������58p��m�\s�\Z�7�={�p�w�S��;y�d��k�����������k&L�_�~:t��+W2b�8��C��={�Os��_���������]��`�6o���u��|�2�{�f���TVV���@���h�"���?���/s�-�`����a6�����K�x���:�����9������K^^C�a��q�<!���rYW�"$��<bC�<�#3�%!��
�b��%�~�f��qW�j��@�e��Dh�����z�0u��h�����=������ �}~��v����W�-���x��6�?�p^��������kP|
��@N�Ld�LP`�oMA�XG����..��X�kB!D3�����	�=�������/�3����������n����R233)//�����=Z�;g�>��#�n7���o��e�����P�����/������C�>}(**���N�-^��'�j���+|MZj���Zy�o��� KO��[oq��.]�Dxx8n�[�JJJ��o~��a�����d2Eee%N����|@``����������&��'@�=�����ZQ��|M�@�?QQQ��'KP���i��/�y��y��9sF{=[,\.���Znn.UUU>�Z�w����K���;���k���=_���f3�<����:{��e��=X,f������(lNNN�4���X~�����ohuHCBB��������y��������������o���>��Oo��1��_�b��+��-�N��C=�-+)�B�nw���\��a�f�%�LP���������<=��w���C�P�3g�`9�;��Y=VPr������S�w�qwu�S���c:�$�������x_�`�%.�8��q������f��/s" �[p�5u����WS�Vt�5����n��9���x���Ro���oC���"��B\�E�� ����������5kHOOos��f���y��_�}����HII���Z` ##�'�MZZ���;v����YF��p�y����������3N�����?�7����TUU��?��c������9�x�����C���_$??��Idd$c����[o��h�{�f���8�N�z�)�p�������'���j�+����3g���dgg3a�|�A"##q�\l�����~P�,X�@�1v���r��w��G����������f������+��G?�����m�FMM
��-���|�=m��\�Qp����'y��E�XS�z����\}I���g�q�F


8��V�������������m[�����>��c�V+555����w�^���2dO>�d��pv�.��!}��g�t����DFF��(<���~n��fbbb�C��������.`������[�t�����5����c�X���n�x��E�~���?��ETTT��B!�u�����[���Jk��UW��M0�_���]�o��L�8�}��`-�E}d�aV��/	9,i4�a
�!��=�s5
�{'��k�����3-�;����������d�����pS��}op�:�v�}�h�{����gp���j����f0����!S0�E��.���C�4��4!���P[[���?��`�3UWW��#��Xtt4�=���������d�~u�[zz:&����F������ouuu>�����k}�222X�t�6jY}O���y��������zy��;W����������SOQ__OFF��{�6�%%%Zf��db��U>���������y3?����@VG3�������V`` �=��O���A�x��G��/	�	8O>����X,�r�-����o�>jkk�������������7t���z�:��h����j`������z�~�s�=�C�;`��EdddP__��={|>_Op-55�a���m�6.\�@UUU�eHKJJx��w�����/�/n2 ���m�@	

%))����d"..���QQQ$$$�
�y��f������iX���[���XBq}s��2��<�����KB��E�Mm,�^��~�v�d�-�rAm�}5�}T]�
=�$��������uhW�1��ys������+e�-t����p.l�=���w��k���S`�����F7��p��)<���:3#�l!p�-����G�A!�������e���PVV��Zj����\jd}����'j�c��=�qP{T{>
��<YkAAA>e#���I�&i����2P3�<���+''G��|�iii,[������o_@
��\����bm~w�����2���������>���uaO���j����sIJj��Y�O�bi����{�9������5�����A��DFFj���2��������:u�O���������2e
��O'==���GJQQ/��"�>�l�~oW�n�\B!Dv�-P��2�W3���.�&%!�
			L�<Y��(���}�������4�3e���n/	y��"��>�mL��������� N��+"��Vp����m�G[��[-{B�)8�:������[L�~��?�����8�9g�OSy�"uv��TVy��6�$*<����$'y�t$[�m��xg�Q\�������B�kIrr2���=&������Ve])����LJJ�	L�8�U�Vi��n���H�d2q�M7i=��}��v;;w�`��>���n��m,���O4ii�Ws�e�q���$���~���q��A���y��������;w�?�P�����j���K�����4�:�W_}�d�3f�O�������Uxx8K�,1�P����Ng��D���'KMPk�{�r����1�������z?�����]����������h-�m��������Z���o��9p�@�x�	�c.���;w�j�*


X�b/���{_=��%�&�B��$d��`�AWRe�L�7�e�)	y�X�p!{��EQLu��{7��M3N�Qv����0����7��
�Y�mK�@,q=����a�9Yv��'*�{R,s�7�-vv���x��u�� �a)!L&3�����q��������@���/�+��f�N��9<��'D���R2���X�Sp�SW�����y��B�kA�^���o���Rk��W���7���5�]�����V�������������1|�p�9��c�(--�)7y��7�f������u�\��g555�L&���-U�mjYjz������F�������}���5P�/��/������v������������ddd��j�Xw�Z�+�������4\s�\����Zf����	
���D_M�����������} �_/?���s.\�������Gpp0��������o���$����������Mf��c�X�1c����^����*��_�����S{��{
!�����5�r�?��6���Z���FlX�u���%>>����G}�Sf�'�u���:}�\�H��)	9vA�����6$�E�\�j�(l�C���@���G�;�]p�����#_��+���0���&�~�>�k*���fK���>w��=(�B���d",,����sO�{�.Y����{7�-��5�5�M�����A<�!Ea��m>c���L�>P{�yX[�n����D�E}&L���>����i����z��3��Jk�%#F���x%$$h��v;�����@�bJHHh�_kz�]����|o���0N���Gi���� ����d�D����^�FEE���������L=�5�����5�\[[���G|�x�A[\��O���k�H�'�kB!��:��w��\��7��\� %!�9.d�����)--e��]��eOSTz�����~�������:������8�w5kw�e�0i`8;��&�[r*:��[�\��M�������]���zG-�|�W�A-����Ke�e�K<q�
�x����L������}����X�>�B!�w�����5K�Cf�)7|�p���g�4���Z���P�e��=��m��]w����n��/��������5j�`X��a����8f����M�(..������������ 77���P��-3��v�z���mCaa!�/_��4��^zI���������[�y��>��@�0{���/�o�����~���F�����mOpW�>hjTZZ�m�{���k������l�����\�l�����f�����3���TTTp��E��i]E���Pp:�>_��@�kB!�P9����	�z�
*k��(����8�cJY��#..W�p,�Gu����S}������A�)���6����������X��7'=����Zp�@a5k��	���k�n���U����h���(�������7p{���bj3S�>���~t3�_����B���~���8��[�����(��7�{���E��:�'p��%�}�]�_%%%����������������cl�����RE!>>�q�����z��p:�l�����\^~�e���� �q� F{y2�jkku#���#�	'�OQ^{�5-sq����f��yyyZ��Q^^�h=�!����g�
6L��d�Y�V�����c��!44�K�.�v���H_|�q���L�0A�o���z�O\W���p-�B�kB�_�}�6�5�o���,���/Q�VF�E����7s�QL(����s�Nf��i���vU��������=�\�p5kw����0+����Vp�8oo�6ki�����RV��2j���]\L[���G���Va
�%B!���ba��EL�<������p�\$&&������XgR��������oIH���*8@FF�Op
`���;v���\��Q���7��@��ba������i��BBB���c�����?���H�Y�3h� ,.�K��\.����s���5�h��]__�S��j��:�A�������������o��0���do���{��l������j�;����}�WY���g�d'��{#�����V�V��mm��V[���j����:���V\�**�@� ����IBvN���p�MHB���q9��s�D0'���������S�=;X��i����~���LKKK�>?����G����n���O��������#!���k�W���O���T\��=�$��7���j�#!�����_)������v��h�^�8qb��^��Q����}�Q��2o��c[\���@�@b��kD�	y�a��A���,v�����`t��{���'���rW����@U�{��T6/�)\'c��b��A$Dp���O���&"""u�v��UW]e
��U�VQT{m0r�H����[2�� _������������J�><~�xrss)++�����x8��3��b��9����e��Y|����K�.)��5x�^F���+������o_J�����9x��#�\�z���k��e��)I�GVV���
60m����#WTT��2���g7���^�z��sg�����w/�-:�h�9s����f��������Y�`�i���/r�-�SB-Z/�N�>=��T[[Y_7��	��j���2 77���,*++��uk��������3�������c������{���o}���n
���
E�bO��d|o]�<w?g�D�QJKK�y�Z$a�'����g��I=��0��y���o+�U�����`�����~L��K��0���A���1�0�K��t1�{�mX�����i�o���������{�9���HV������H��{���{���r1f�>��jkk���O�8qb|�n�3}���yiS�Nm�0e�&o�������������w�^�������0j�(N;��&]����.���>#
���r�5�0d��.]�����x���k�g�����$�0j��z;������x���|��G����	&�p8��i��w''�y�/��bS����Y�x1��?��[�n)E�/��'�x�'�x���jF�IUU�����A�R�:���X�p!�H��t:�>}:�i�t�R^}�U v��y������1��l�^�z��
6���l***	yP�^�X�zu���d���,^����i�TTT�q�F>���xG\�>}�=��=SqMDDD`������@��g;��Dc/��<v������l&M�������5K^[��)�����=_X��W������f��q�}X�g	9��ko��t'#{d�rW5��}q-�����c��\Y�Q��z�c�������{�5�"�c/����V)���S��$i7***X�ln��Ic�N9�>�� 62��0c�^y���(�f5<��0�u�����y�����q.��������N�;���������g�����?���.��F�a
7�������7��o�����{�3�8��N�����p�%�����H$��O>��O>�����8����qx���k���-())a���I�F��R\�>}:�6mb���A�~�������<���o[�t�����g����b�&���g���)9N��[o�5�hxp$$�_\��l�z���������<�w���^����JJJJ��)���]�v��?&��d1f�n��V�N�u�]�X'����H��o���Lt�V�~��P��~n,������vj���;�������R>��#KF�31yl�C
�zc�s,\��5�&��� Z;���kDbLG{t���/TK�V��<�|z\�����`���Q�C�9�����1��h��Rq�^8{a�������vEDD��Y�`�H����q��2K6n�����U�VQZZ������)�������hu�m�1n�8���p��2~�x�=�\�N�/ll���_|����s���s����{vUNN��rW\q�u�Y�v;w�}7�&Mj���c��.�������s��k�Q�i��������������)((H���v&L��<@~~~��A��~:?���S�4h��wc��I���p�i��r�7������$�2���b��)�s�=�y��dddX��=c���&��r�e,X�����"�1m����L�x�����_�m�v�:v?m�����o�W���}��UM]�Z�w����>��XH=�S]�D���gn��O?��~�f�?t��p�"0��M�J��[��_�0���f�'�?��&�)�R|o�&����w2�7<j�h_�Q�o?��*���&v��a���#.���kxDd��02�
�#u��N��{cs7�5�����~����r����W����k8�����ny������������o�e�s���t��[�����A�oiOJKK�F��t�4����?�eee������g{��e��}�A������_������k�����[�;���Z�o�N4�����K����imn�������r����k�����)**�4M


�jl�i�l����������M�b�������j��xb���$��/���{	��/f<����l7=r��-����;�E��;�� IDAT�D(++c��AL����j>Xyp�F����j�U���1�G4<����Q��#W[~�#��L���bWd�����r�~��#?	����,�Pq��_�T|����>�8��:�����~M����M���|����ja
�5�l|�~���bB[>�9@�MEDDN$GS�H��z���'eee���ZC��]��`kIn�����[�NZZZ�|���K�.t�rd�x���4�������Z=Z�T-"""���b]&�L(�1�����'?��`a
��2����E���&����|&O�_��j�p���U��j�����P�
o��hUqla��6=5��J
����m%�I�G���\=�~	YI�l�!M)��Ly6����8}6#���_�!�4p27�s'���O�wj}X�����4%��hHi����y����f����]���>i���&""r�2���w�u�[����X���1���Y��U�p�������`�Z8�����
C9k�5�uF����������w�?��2W��n9nzY�������;�5����A����X�8v�c��R�D����+������k��- ��=L5����
!"""������{���~�����
Fff&���l��!>R�f�q���Z>��t�\9Q���t�z���U`[�?�>�����������r���G���d=:�����s�&�F~�4rd�	�,�{����C����3
���n���Pb-���M���p��������@(������6o��k�����>����/�effr�����Q�"�4*����������������G���y��AB�&��I�w�9��r��xx��w,�����[C
���0n�$k����~�YS[����LKMh�N���������dk�%���<���.��G�����=���R�!EDD�*++��|�;������+�d������I���;v,�_=����8�����Dc!EDDND%�B�uz�0e�T�L�����3x��7�7o��M���Z2[��AS�8�L>^�p1�������@�;���j��]k�:��8�������&V |]�j�����bg;�{2��v��_7�V��s����g��������{[�DDD�D��K.��b.��b���'��&""r������N��whb
t��u&5Ua���m���cg��Yx��q~>����z���:n>�N�m
��x�W�0�Lk��D���_�G����q�187~cQ-������,}��bl���,u_����e`|����]9Q��&""r�)~jV%���
muz�y�����4y��NN$���z��w���H�h��f���������G���oa;�B[�b������SS:�>��vJ<��__7��5��A�������Z��s�� ~?���`��9�"""""�n��&""r"1��]kW@���@p���������9n���������������Z��=db����������W������/n�Cz�I�n�#!]&b��8������hcE���������7C��6���Hr�:l�_���	m���!"""""�;�DDDN${�H��A��$���W����bk��V����i�5��q�8�g���~�����2Z���_�e�����I_�o�`��E���������??!���x�5�
�Q��	��q9b���@�e��,-���N�����Wk�v����s���:���/.��E�5����m�'�7�wXb]��r������8m���C���w~��G��e��u�Fy���,-�������s4}��=j����W����w�B`�����y)���e��������������A��h*�t!��J�7}���Z�s��0~?��]�@M��������T\9A\<n
��b���45����Wy�x����C����ks��B<N��8�9l.����z���l��))���/��'����/8��I�����|���k��cR��7	�y�����18'~�>��w+w<������{��Zxp��F]?��?��"�N�M�H���;�s_DDDDD�G������
��8wdb�=�W�����-���-�S�f�3��1�7~�x���_?����������Oc�Q���d���-����������S�&5�=�Y�x�t$�	l(��(�	��G{������b�Z�w0��=���k��M�E�+�������FC������PT\9���0y{��������zT���dke|=cH��k%�a\~�����-[X�dIR��+�����%���h�W�m�26�c��R��2j=m
wo�)���k��]������z����\0C��Vh�9���{A�~x�2��{�vEDDDD�x�v�J�����Q��z�M������u�][F${�;����>����!C�0z�����_$$e��>I$� �+SG�k�h]5si
5*�i�5��������nl�a������Z�l4{�cb]��?�X��S�n�������M�����k"""��P1l�Nb�{$������4�>sX�FAJ����J�v;eee���[��#��d�%u�]:�F��3��B8Hd�*k�Q������%�*	��>�q��
k��t��]@l��s���@����m���c�UEDDDD����DDD�xa��o�
l@0l�5���E��6�S��u
��5R�K�.�y����7���z�)S����g�lX$a���������d���y�������9����)��	Y������P����y������xF�{��]��b?���
��jMiW\������4������c����c��/�����9�sMDD�xU��_>�d4x�%%�/5���@|}��2=��$�����df����B!���c�h���-������w2���d�����e6�]����o`����af��������4��7��?���T~�X��Cf����-�Ix���?���
��B��]�"""""�1��&""r<�o����/�����������J�W�p��|K�H����������e����_$e�oG�f�z�+l��(�Y@����p������nT��7ZC�^�\�5���9��o��C����	�f8%E���V�P��W1��-�H���Q��)�������tp*����td�*��WX�eXu.�������!\w&�=�G�?
�<�8��	�Y#	0�6�3�WX���I���/�!����P�����h����SB�XA�!&��k??l^K3�\C���d/����k��;�O.G�5�4 �j�&����v�)�i/L�k`�VZwL���)�d�����A���H�R6���u�=�o�����/A��D��G(�J��j������/.���!�8�0������b/3����;w�%+a��l��������,Z��5��������s����k�`
w���:�3p�Sg�ep���>�X�d(�)��v/v'�"�@�x3�uX��0!����������t`*����tD^��gA`�u'U����k�^����I]k�g���F��q�g���y�����o���={�2VnYj
5j�����[zFF�5SW�2\�/�������Y���:('�l�V�FtO��S�X�-��/�������K�9���VXC�
m[f
�����H�����HG.�
_�F�*�n.�a-X_�r��%c,"Mw�E��+HE"����F-YPV]b
5����ju�O�-���/�
��&���p
���xf������;�-�GG~����t��sz�q�����X���������E�72������a
���H;��Q��t�����Ck��P4�km��
�u��9�����^����y�f�}�]f�L-@e��u'5Q�7�jU���������5�\���>���`���b4������������������8�������uu�	�=	�������.��>p�@�d<�(�H�D,l�����]h
�����H��DEDD:��w����>��U��
��\:�yo��g��Q�z�����/������2`D��)����$k���&�����`�e�~������3��+�%��:�W�F��(�`����>B���=�@�`�S��&~;~5���R%���O�u�M{v8N��DDDDD�SqMDD��	�'�0�jB��21�����g8�2D���W_Mff&�P�'�|2e<�iC�������1]�z2e���p�	�}����k�9�;��i���l
w���d�:(y��%��lY��L����^6�9�M���L�5�����i���QTs����Jsp��N��#����u�]_o�����z+�v��\?���uCn��^�N�u�U��j|s_;���{��I��L�x+D���C��Tn��������~����:����Qa^DDDD�8�����HG�;�i\#�����xsE|}�I�9��@Z��q�R�C���+l���7�<��O������G�s�u������Uu��~�����:���F@6��/.�E$�R���[�������`���&����~�uKDDDDD:8�5 """�\���� ��s�r���)�_�;D�&O�/���������^Z����e6n�Hii)�h��{�����V��������<�(Q��J�N�cD��Lyv�u���������u��7a����!m�l�5�8�(~
��������{�]�O��������p���9
��I���������H������H�b���4��f��A��w���E);J�����[��"G���r�M7�����4��?���,*��;`"���~��g�D4������g��M���-I�&�����QqM�	{A_�}�a9Ni����H�a���a�������S�������9<���F9P������iCr�9-�+�
�9��_/_�Tx���p�����_���k�k���:O�
Wgk��|�����5�!
�n��H��G��W��=(�B�����Nr�����1���������	���?��������#x[�\t�E�[��-[��9�����7/����|Kv��V����?�������wrR����i�������������H�SqMDD��3���&��t"�>F���PxS�f������|��#�+`rpD�/��]}j2���Z�5��vN�1���6bD����U#�s�5�����5f����w���iSY c4Tn�iX�XkDDDDDDD����&""��E}��J807�<	F�g�]>�}~�7�'E��W�[C"���|�|�0�N�^;���*�SO=�5�\��U�(..��r��wo�����/YC�?$�����;�;��q'�0t,�:mg@����������H�k�w*DDD����a��P��D,�t����z�����3�������7�.Y:WJZW(��/�M��
� �W��4�e���b�
���"Jaa!_��W���_J�%�A5��"�v��{��Ir�x��Ga}�f�o����Q�;�EDDD���M�bBja-���akm� 5��z�"&�7WX�"-������k���^7�a�����h�H$B8&c�&������b��%���V��_�V��-��/��Ln7
o�~����;_
}�FEDDDDDDZ��5io�?���B��D��l�2���X#v����Fm/
XC"-��/����/��g�tSF���#0M��O  ����B!L���g�����������/~6�N�r#����JiGz��?������7U���5`��`OOz�������H�QqMDD�=��$��	��D���a���wmX4�i-.���4���-����������Y�
�x�������4M�P(D8����������p��W����k�����o�$I��#��k`bL�s��a,)��i+M�NDDDZ��-?�]'b67�;t�R"�D]��w~Z��D'�HK�����? � ����������k������lH8��p�r�J��Q�]�8��-��a�~�}�h�sG���kTDDDDDD���sMDD�X���Y��5gg���
k�ecX�
08����qi.����W~������m����9�8p�;k�1����-�5Gx�j?z*���z�^c�2DDDDDDDD��������T��������10n	d���5S�Nfm���sF��+�c
���,��n�0������0)�NKK�fk�%�a�J�n����Ma�����c�+���z�v��-Y""""""""�;�w'DDD����qX1�������E������
[���=��O�l
���>����_�0�+,���������c��0`@�yM���0��m��a�q���p�
}""""""""������H[��`�������6�����)�Gb��,�V�DB��@v���N��]����8�b�H���;y��cbP����.�)����377�SN9�����l6[|o��D���
mXH`����g�Wp���!"""""""�8�5 """����\5+1gg��LK����]��Y�?��=�����y�s�d�9������������_=�}|�j��4����d����5�\���k���"--�`0�i��rv����}�����+={����#ZUL������.�N�FR�����������sMDD���:v�Zra-{
�_�b��=������~!(�t���= ��"FtO�g�
k�:L3��^��]�[��o]t?=�%e������;��w�����������xR
k���<��C,Z�(%�$��/���+�pz������cNDDDDDDD�!�\im�*���Xq-Y�;��C`��TEm�_����P����3{����W%��^\�7��� ��d�
�6tzRF�z���=����~��e�(**��r��O�N���;x���0M�`0�SO=������������~�z����m��k�ywb/���!"""""""�4*��������������9�`��!��D�(�CQ~3o'%�����9�;��<IY"-c��,�����n����O�`r�;����s������}=�Q����L�6�i���8p ]�v��G�����?����7s��7��o�E���������5�l�c/J�i:�DDDZEv����p"�5�����������]l-����>�'��L�9z���<��o�p�@�X�l!�nX���5�'��������@>l�0���~�����e������>��g��\�����`����`D�o���{���^����~�f����������QqMDD��v��������
z�z�F������e�nV��������#���D�^8�'��:��'ua��asp�U�G�����yyy�u�]����������i�����|�h����0Vx3<���Np�2��/s��q��a����VDDDDDDD�YZ�rb����Q��5wO�>��i���&����,�Z���/��N+D=9��^����-���a*|e�p����\r�%�u�]�����<�-����Pub��|>�|_,�0���A����#"""""""r$T\i	�
Xw�����x�e0�s�>=k���#v�xs��6�g�8����I����������OX��B��k�e�����{9�0���/���������a3�dH�x�AS�k�#�r����������@v$b��G(�Z��,���L�X�=��f��ak��%'�@�O���Dj�f~I�x�kw� jF[�����+������)�+z�;�4��Q��O|�� kC=����<ZDDDDDDD����;"""���6��OO-�eM�u������a��A��0���P����3��6�[:�������������s/��y���T�h�?q`k	,{���Z�]��K�w������n�^���d���D�v��DDDDDDDD��:�DDD�D�g��Z��"3��'���#>[��*������wV���9^g�e���8� IDAT����%�x���|g�
k��>�b>K�`
7���$��a
��p�H��X���]16!��Qie�]����:a��72�C��?�$�������DDDDDDDD�����9Q���+�v?��D�;�<�'%b����r���>��hJ����e�����hboB�,�6��FAJ�{q����f��$��	i�>OJ�E�$g'�Kx��;Y��O�og�����S9�����J���������4��k"""M�����R��o�~�[Zj���������V�Oram��<��P��j��*}e�*�j
7�a�����[�-�pz�e�*�nP��ev�&6��[��=u��E"�{�=-Z���3�5kiiG���O�^R,""r\0a��������;��~T�5x|��Fk�����+UX��Q��������_a@�a�p�p
�j
b���������������@��_��������
%u���������4B�k"""�	��
���k���_��Gnj��,��-���)�
��$%��r2���&Isy�����>�B�V�mYJp�����0L�������G�`����Kuu5�����3����s�E1a�l6]&"""""""
SqMDD�!%���[ �4v����Z����5���eLU�����Hs�S��n����p����>�lr3��-��R����/~��������g3g�d�����7���������<��S��7�K/����Gc�I&"""""""�PqMDD�*R	�n�}O��s���O��A��h�AdQ���7����,\�O��Kj�>�v��~���<b�5�*BQ��CD��$�v'iSo!�w�!�l����_x/��cR�iii\|����1��_��D��g���8p �_~9���Oy,�FJa�;w��rYSDDDDDDD�8������X;c��U.��<}!�B�|`���a�����x�-
����
�0��S��jTa��\�FT���z��T�����aX�q�5�UV�+��7~����k�j������I#��n�%Z}�AlY����s R�
���	��0%n/�G��?��u��"�7b���zb/��h�gff&W_}53g���W_e����f���q�Fz�!N>�d.��2:u�DEEs��a�����a�N'�����+�$333����������qJ�59A���1��}���Z��(z��2���G�hb?�d�O�N�ZH�/��kJygM�u�Q�d[C"����#���9L3��8��K����Hsy�1���y����k*jJ�q�;�����G��B��9L3�L@���U��p~�}�)8GB�.|�����V���N7�!g���]lY]R���{���oV���?��F���L���t'����evJ�5Q�N���W����3y�����/�{K�.e���3�/�����Z��(�a
�X�x1�V���[na��a�����������I�59������������P��53�bQ�v�a���B�{�h��&5�\TK�/L��N��i�9m��8�����5�,�VE��#!{��9oT��r���W���nbw��C
^����Y�y1��$9�l�������>M��{���~
�������t���q;�Q��h4B�N}�0l�uKy��Dl������.�~3C��������k�YD����?�x��q�9z�%��b�20%�z��������5kx�����};�p�O?��=��aB�P���0\.���<�����g?####�9EDDDDDD�������GL���rDj������HC���S�;q�	��-��O��&:j6��G�q�I�q��J�E�Y������x��4���i��[C��`�!E~��[�uO��"������d�HKvpU\����t��l��[�������������0b���9'OH�<�5/��TX�7��������eB[���dIly=���\C�7:��%6��C��x�b����PV�.
�����\�4	��n���x�����SrDDDDDDD�������?��6~�m��s s�5���������4^�N�4y}������s{�����u�|���.��t'3��2ch.^���%�<�h[�c���v�)s���.�v���k���,��u�C
kVkv����7�s']r�[�Z��������	��$%d�.$���p���m���0&N����������i�����A���X�t)�^{-Ng��"""""""����;"""�)�6�=2UK-�������$�m������#�:�wKg��<����nKt�����O/����E�!\��9n<*�I#>Y�>ph�����2�/O�cL�n����W������3�:�����+T���a�f|dCL�$�)))�k���9N��&""�'T^�:�� c,��
6�5���}����	[#q�+���Y������\����0up�3]){V��N���]AA���@
*�(��OI�>J��)��Gq��+�QT����Fe�3���?�,������)�j�6*m���M�F��9*�����d���l��	������9���q���T�c+R���p���y��@v������-w�x���RBEp�Uk�����t[U�L�&2�q�39cp�z�v�ud�h��������gjk�������R*jJ��*�l�zJ+���(�RZUBiU1���yt��V2����x�a�]�=�{8�7|�`��&�����-'�e�u���]���Z�.]��lD����c6�
��E�N���"""""""rQq
(--���������={RUU����Y�d	��?.W��""m"�6}7�	f�b1{:t�2��%8rR���\
��[7b�`�9��w��9cM��u�����5��j��P�5�(�;���W���+���3{Z�������f��UD�(i./cN��i��Knk�	#jF��WQS[I�����Jj��T����UP�+���VFeMQ���Mk��t?�#U���S��{�]�/j�&��}D�o"�w-��k��YC����������c+--��c��l�2�n7�@�?�^<���u���������qN�5�����������;�H$�c�=���y��w8��s�i[�/���B�r�W��>+�
�Z���&)z���Z��?�u�y���#��������P�q]��L�m
��
���aN{��>;^�J�jyt�C,\�VJ�6���/��l�B�2�;�u�e)���iF�����>��K����d?��j�>j5���~�W��WS������_�/P�|-�n�����N�]���B��B
���]H�'�_<wU�����c��fm�4������
�=����:f��h�."v-�Edm/"5"�����1{��;���������k����p�\�B��l�a�r����dffr�WX-"""""""����V\\��e�8���;v,v��k���E��d��D���o�u�C�����k�'�{�u���a��=k�~���r��u��n�V�Y3���u�������Ak4E��������v6�����!��d������%]�z1������F�j�kc���������
��B����P#��6�2M�2M��l��LrL�1�����<�kF�������o_��>�Q����P\��7��'Q_����X���p1e�,���>7��>6\X������$�=G��I"���
g�H����w�����f�����?�����p�F1���5##���g���ay��������oN����U�5jTJ<;;���B�o��isom��vP`'l���u�D!3�
��H-D�I7_���p�����T5�b��pv�������>G.��U�?�	��b�*����'��b��"���!lL�^�u���V���&t#���s��y\�X2��u{U�t�Y���A�@M]!��6����}��A�Wk�F�'���,�=Ydz�������Sw?����%;���s��Z�Ja�G��<�R��.���	�fpc����?:��\�2��Q�f���~_�.;��(8[v!���8���m(��#0�s���.��~�v��b�4����=��8z��l�#G��g?��=���/���������"333�"""""""r�:��k�w�������Jy��=TWW�*d96���t�5��=��o=��X��������=�X�y m@��,mx�whl��#���0�)X1"U��wO�u����yzC����n���&u�O���n��������;��Y�k�A�{��_� 	�T��)��a�p9�x�id�g��J'��N��K�;�;�'�tw^O^w��L��2<Yd�e�u�7�]����W4ZT;��p���n���f4v�F1��	11d��d�bM4B%�F9'j��I_�v'����{a�}���}�{��ax���1��o�����#�����3����^p�nC���dgg���}
��Oqq1�aPPP�����V��N��ZMMl�QZZ�e'q0} 8�����!9N����h��k�`�5�3e���vm/��7���~�QKW��<�6 �� �29P/����
y����<���[	o���z�V,H����{Y^������g��W���X���c�=f
q�5���o����u}VmJt�4Eq�>k����vN������J��.���}������i�����R��������&l�	�c���P�O�k�[W��-�M�4vQPc:���7
0�mH��FmfB�\>����Q��>��<B�L�+�a<������4�S4.o:��������	��������[�i�&kH�����n����h�������oi?�u�f
���s'|q��9��Fcc�X/"r���&����$��iDL�K|�A�c��U1��������7;��_��r�'��J����eM?"0&�G/o�OK���s1cs�
��������	s�:�p4d
���.�������l������Uw��0�t����>���a�];��Fsk{]JY�I����w���}k��"�4j��Z�"���)����������DDDDDD�p��������������:��3�!��6l���A�,;�$8�m���~
6��`8b7��Fo.0���a�R>�08l9`�w`���ze�g�a
��i�@��0M�
DHw����O�������WY��#k�A��r%�����������A�;[��V[>�k*>"�l�5� ��q�;;6��b
����v��N��Mx�*���	��fm������o����09����[D����"����o����/����PZz�8���2����h$��H�pB����������Vk�m�}��-��T�.������0 �c��������������_%;�������^���ex2���]����}�GU��O�B)�P��^���t��Uv��v����k��_�]�umX`E]�*~��")�PbDHBi�$d2�?�7�;7���A]2�����q��s�����9�~Ni��4FD�6�0UUi_Z�~��o���Cb
���S�b�}�333}�O�<���|u����~v=^�Bj�YKd'������_hsi�
)v�����������m�������O�!�b�.�x�5����9�rk�_�.��G%���O�Wa]��7����-��+��O5j��Z����M�6����7�SRR�v�5j�(Sk�8���x�Vu�h/�Y$��Xk~����+��w��iRT�y_�����UR�����h����g<�����%>�^g���_f-F=���U}&Z��p�9�JE�n�iGTK�\���]p�BZ$�P����%+�����;<+�P���2&&F'NTJJ��x�	�;V���Z�r����4f��-��K�)�.e��
���.OyH��z���)���=�����8��i�Q���H��xI+��_����j�l�9�n��A3��#��Q���3��������\y��������l�<�%
����r��9�29G�RMQ���r�HTHt��%���5I�3g�BBB�z�j-X�@���O�t�M
��"�!���~�J�����aRT7)���%����h������'��o�w���L�1m��C_���[��.�C�&)��$��/QMy�BZ$����#D!�:XK`�#Iaaa����t�������j���bc��&��
k)E��?�Q-5��hk1NGT�B��2�?�5���H�o��ZH�B��#��Dr
���`�5�&�k�M$��H�6�\l"��Dr
���`�5�&�k�M$��H�6}r��v[��UQQ���jkq�TTT4��zUUU��rY���v�kUUU�����l\.����������v��*//o�=V��h �?l+�c����}�����h��?L~�����VEE��[������\}��6l��n�AC��61l��I+W����N�U�V�����L��n��Y��m��}Z�d�������J����s��?~��;�<9�-���}�����m�JJJ�p8�����#G���.RTT�� ����h������/5b���=�������/��R�w�Vii�$)**J=z�����5r�H�?X�h�v��m-�e��A�9s��X�TYY�%K�h���������V�-4h� ]|��j���� ������O>Qhh����~���[�H�N�:�e��i��u:r���n��:u��Q�Fi���������#�
���QNN�/^���L��OR����M_���.]���L�:uJ�������k���JHH����?���:y�����K.�DC��Kb�4Vc��
)**�K/��+��R�;w�VK
,F���`s:����F�����o_�?��n�������}��i������^k�a���Z�b����T]]���H���[S�NU������+(�kz��TXX(I����5p�@�����s����_���7��K��'�a�m��Q�f��E]dmbX�d�-Z�3{��r���:p���m�����[aa��s���G�?������2�����|}��g��q�~��z_����D���Wzz�$i����4i�--������w�QMM�O������4���i��
������g^^�<h-��}���"IRaa�����[���>����Z�n��l���o�]�
���UMM��z�-�\�R�����:_|������i�O���VVV�����z�j���u��4F���`�z�j����F�l��U����,�<RRR���oZ�UPP����k����;w�lm"I:t�����������X�$1F�1c���:uJ���WFFF�+N��@� ��������{O6l��]RRb�<..�Z$�3����u�V����J���*55U�^z�.��R�z�	��9���z����A���������VbM�<�{kQQQ;v��v����
���G��m����|�N�:�}x��u�.\(I�����I���m[���h��*//WZZ�-Z�+����������*//Whh�����={���D�V����Gu��1=���z��'����WRR�'�xBG��$u��Y��ki)egg��w�UMM�BBBt��g�_�~


��C��f�UUUi���Z�xq�3��3��z��i-������?o<�0@��������[�{�nUUU��_������U+�O�KMM������������{�U�=,-0|�pm��I���C�t:u��Q�\�R%%%�����O?���z�V�+�
����������oK�����*M�4����������;Vqqq*,,���������
���z�����];����-[��{�{��h�����x������a-6����@�9���f�-]��Z���A���=�@�;� IDAT���"I����o$�:t��	&�y��������+��n}������K���
��Zaa��{�9#�6z�h�x��u>����W:t������G���u������'���?�$-[������S���;�H��|�����M�~���z��U^^�����1�g`�p�Bc���s�j���F������#�����:x���m����>�����A�;�����|��:�			2d�v���{��W���>�#G����?.�������5���w�k���o��.+W�Tff�$i��)�3g�Q7i�$����Z�|�*++��g���+�4��`���5������_g�u����#F��P�~�|��N�����[%%%�����-[4z�h�6��h��?lRSS�`����W_���?������D���T�=|������������S�N��/��u�]g��W�6mt���[������c��,Y�D�����$F���`s��;==�����\p�����9|���-[&I����|�Ac��q��i���z��%I�/&�hP����r��z����3�z���n������y�~���u�=��$��&L�`\�[��a�?~\�����5���g��!��"n���F]^^����kI���C}$�VX������M�@�Y�x����/I�������[��>22R��~�}��Z�5IJNN6�R������G--~<���%K�H�������--���g�Y�f��-[�Xj�����j�LHH�����`b���wtt�&N�h|��D�
4F���`SXX�W^y��>���.j0�����\kb�����������ct�q;F�Ojj�-Zd-�H�����t���c�4�|UWW[�N��?��o\{����^1b�q���������S�U�$�RRR�������<C���t��O�y��o��;�{���Z�Q�F��w�6�7o�lt�um7��gOc��={�Xj��q��a}������P��7���	V�CIII�bCC1�cedd���c��s�9G����RDD�1S������@������o�i���f�:-g���Y�N�9r�H@1H��w�}�8�l��A�5k��E��u���������������/�,��]��6$F���������s�=����z�;�	m�;wV���--<�#(�k�������C��r�bbb,��<��:+��v3x��������ukEEEI��y������^�z�V�AII���l,X���I�U"�V�5���V^^�$����un�[����K��������<����1��c��%���~��+�u��	��C��)++��nl����d��}������t�M���Zaa�qm���TWW�������ua��w���'O����>����^����:u���!�e��w����v��W_UVV�BBB�������A%%%*..6��������K��dU�.]����
ix�V�z�j�e��q���H��o�1�h��t�����T�!��g%]vv��������K��h�������+??_]�v5�M����w�^I�X���--~���L���H�z��al�R�7�|S�����S�$y��=z�~��_�y��>m��-I���7��2oG[PP`����S��|�rI���]w�iy�^YY��k�J���f��*y���jl����������?7�����E���/%%��nh����b=��S��k����C��4i��?�|����Ed��s���555z���t��Q��������I�Y���{NW|K�'�|bL����+��GK���Z�J��_��v���A��7��M��������������5�v������O������V\\�����i���t�
q�\��u8>��I��u^�Z�2���}i_QQ!�����I����;�`a����>[����������2�h�B={�������{w�]
[�t�qm>��.�W���\TT�/��B;v���?��-[u�����wU��W�M��_m<,4Hk�����[u��qEEE�S�N;v�F��`����F���SNN��.]���<9]s�5>�&�8�Uj|���o�v�o=;
h��?���TI�Y�N���?���\����M�6>|�&M�T�L:���l�[�Niii��_��W
������I�KRvv��~�m���G��~����v��6��1�{���]�vI�n��u�����Z�1j������t����[���K�<sO�<Y�����\���
m��Y������{}��]+��o�w�
hH�O�����x�
cV���2���#Z�z����g����c��Q�F��2��zER�/�g�UUU��pcDD�Q���^�Ly ������^�d��V*((��
4s�L]|��F]}�����zbb��9�K_			:���������
���S���WMM�rss��o��;�4�����/���
@���x�<����$H�8:q��v���
6h��y��SEE��x�	�sbb����J
2��������3���9���[�|@S���f�w������������*##C�V��}��Wk�m�������522R�\r��O�niU[���5n�8������H6l0�`��u��-[�)S�H�|70F�9c�5k��.�����UUU�(ct�����}��^y���n���[W_}��I�"##u�y�)99Y�CZ�b����UQQ����/z������wKH���>M>��=�D��ds8<x�z��!���-[����#�����/��'�|���q���b����]v�e���^��d�������}>74��z/L�;�3����F]�v��A���{���?��C%$$��s�5���v���[o1<{�l�����c�k����%��Q�4h� ���K�����+//�8����������F0JOO7�kjj�#F(66V999Z�~�\.�v�����~[�_�������h������w����ol��\.����?L�c���EFFj���j�������~�z�������z��g���O*<<���VUU���=z����&O����P]t�E>�8~�x���[Z�b�$��/������p8l�����v:�����z��7%I��
��Y�|����K�c�n�����`q:����T�=��*++��uk�q����Y���5t�P]q�>o��q�����Ryy�
�i�&�?^��������N|���qb^�-I��z���*��������j����������s��������Ryy�$��			��p��#""|V�5t�y�\}�o���<��<��\s�5��/�P�|������t�9��;�^�b��B�_�~1b�����w��$�9R��/��}��v��{�n#�fN�UWW�����F�3����u��>(��i��;VO<���n����+M�6M:t0�������K/)''G+V��������������>���}xcb����Pn���`b��f��������6}�t=��C*,,��#G��W_�{~�������|m��Y��-���[�o�>=��������.��Rk����/���kUYY����I:k�]�@�t�~��1��?_�������n�����j������oL��@���r����WAA��N�����z�G�j������.k�$�m���2e����I�v��e$����].����?��	�&�$�O�>>�5�����3��o���gF����[���_K�:v��3fXZx��
m�]j�p8���H����{�{�G ��vp:����~g��������(�� ���ai��c�������$�@��k���h�������\�����q�6
m/45�N��y��={v�~�w��=z�$��So�����PBB�����K��M�$eff��w��ik~�nl�������j��@01��S�N��sDll�~������oI���Q�������^w�q��JKK��/�;����t�G��go��'�1zee���������������C�(ct�a�������o�>9��;W;v4�N�3x~~�qmw�n�o��=����W��;���{�j~��];u��A�VUU��=�w�{YY��5����u�]W�
����\o}\\��0��ys����Zyge����7�M��a�k��~nCCC5x�`-_�\�go�^�zYZy�����Y�\r�����2�l>��E����'���g�� �l����������g���&�<[E�_�^�'���5k����+���i����3g��z�|�ycc��?�������k�>l�0���k��C���A���7�(//Oiii<x��Y��}��E���`������_��C��v�=��q�URRb\����r:�7n��:���b�1:��@�{��UZ�j�$�X���Z�x��V����+���_�G�3f��U������1:�
h�&�r�������;�F�N�<i���������bI�y��W��>I>q�����*�g����v�eeeu�=�g������7��g���y/v�jV�5k�{�'%%�Za�����a������oI�f�������uNf1�}u��?�������$��/YYYF]��-�������������><::���V�x�s�����{�g7�'�1Ff'�%�ct�y�%%%����������SVV�1�-��������`H|��S�����YYY���5�)++�'��;��G�5��


�k����4��k�h�Y+V�r��~���j��u�<��\v�e��"""���"9rD���~g�:t���������/�2335`�����2�[�n�zG�i���BCC�r�|V�Y���_����������?�����a������������a����233%y���4u:t��}�TUU%������nM�����Y���T���5������t]}���2b���m�
��v���3F�}��9��#y��7n�(I������];��@b�1:��@�����S�~��r


���F���C��l������������5��b�����&�r�k���K�C��%�\.�rrr$y���g�H�wo����������2�.��\.��o�n��0�a���|�C]gL���/��
�����K�.�<[M�_��y�%����x�
c�?i�$c5K�v��m\�u�Y��5�����JKK�o�>IR��}����:o�TWW���#�Zs|�m��TS?�����l��y���$����h �?,�}a]c�#G�}����>����5;***��kaaa>�	�>���v����
�1c������%i��3f��$F��6���A ������4���������������������q��m[c�]FF��$3��FTTT��I����k��53f�����]��z�jc�y�^�j��]�p�1�e��!>|�O}]�3������l��G�j����</��u�f�
6��A�n��Z�R�:u����q�����b����<��l���R�y��c�I�Y����M����qqq
�J5���Ujj��X��c�c[��-[���N�:I���\��|���jI�����-I_~�������S>���������}�����+�o����yy��M��b4�����7^r�����I������A��j���Jm�����+;;[[�l1>����T�Q�s�$}��G������^	7���:F���Q���=�T|K��k)))~������e����ww�����n}��GF���
�	?'N<-������s�>"5��:��k���W3�[�j���hUTTh��uz�����c���?��\��w��y��s�.]����]�v����}{���K��9�m��A���*))Qzz�Z�n���Jm��]����N�<)���n�Am��1~O�f�t��Q>|X555��c�����p8����W_}����O���C����S�NZ�v�***�s�NEDD�U�Vr����g�g�4c���p���z��g�hIII������aaa
	��I����?��O�������RDD������r�J�����,�Y�f��R"""�x���s��N��������E������S�_~��V h�j�JTnn�:�'N(11Qaaa:r�������b���u������n=��s���OUQQ���UUU�������/��G��\r����%���L�v�~t��o��G��@�		Qhh������ �[�VTT�N�8��?�Xk����9����o�Y!�x�b���;:z���N�jjj����M�6��W_5��h����~����8=�������TRR"�����jeee��?��U�$y��o�Qqqq�_*���]�������]�vI������#�����Q��@�~��>q������W�{�6�;>>^�6m�k���;v(,,L���*..���[��������S�?W��^[�j��n�:���������H+V�����/�����h�r�-�&��������wKM/�%K�h����b_|�f��i|����}��Wk�[}{�1c���������c�=�������z�����'�0�����W��w3j�������z��3U��������'V^~�em�����~�]v���k�������=(]�F���o���y+����������8=���Mz�����"=������qqqz��G|�J����#�<R�V5^�F�����j������={����@�p�\z����>U�l?u��w��\����������bS��:v���zH111�~����P��O27���p������2�1:`���7��l�_��_����O�h������������$��9S_|�O|?���u����S'=��F�o�v�Z������M���x�w�Z1���l+�$O'��S'eee�����.66Vs����i�|��.]���7��5d��	�L�.]��e��5j�
�������u���3gN��4^���3f�\.����}��i���.��]����MQBB����\;v��.<<�����0�����Z�`��e����g��o����>�l�����m�s`���_��3g�M�I�mf���t��a�����9r����N�s��`�t:u�9����T999>������;��5��������UZZ����Z�u��U�g��������h �?,BBB4b�EDD(++�����;���nS��}}����4z�h�\.�����/!!A��M��7��sN�7�{���=z���cF�WHH�z����n�I#F����b���c��v��r->>>�
����O�
�\<x�jjj���S��o����N��n�A��7��������������Z�����S������4fA�r�,77WG�UUU����u�Yg[���Yn����)���PNN�***��U+�m�����V.�K999*--Utt���k�s����">|X'O�Ttt�z��qZ7���:u�����UVV&���������v������Pj�����@���:x�������]������J����������R��m�|���R`1H����<xP���r8j���:t�`mV���Vvv��������Z�v/�}��I������B��7W��me�7�1:`�/1F���@� X���v�������"����U�V��j���H���r��JLL����x���L����J�8���h:�q��"������.�����7���Z@Gr
���`�5�&�k�M$��H�6�\l"��Dr
���`�5�&�k�M$��H�6�\l"��Dr
���`�5�&�k�M$��H�6�\l"��Dr
���`�5�&�k�M$��H�6�\l"��Dr
���`�5�&�k�M$����?���,HL�:�IDAT-[�L999j�����1c���pX��i���Z�v������uk�w�y����O���+V(55UUUU�����M�������_~���������^���Pk1��/�\��k��}�YIR���w�^m��]�~�����Kk�������>Rtt�����i�&m��A��z�F�%��X{����k�.%&&*<<\��-������c��]�v���;w*--M����_!I����I�@�/�\�������75k�L�=��UVV��\)))�8q��t�b���������O�>���{�C���G��4l�0���k�����k�f����.�L�C�V������������������t:}��������7���H3f�Pbb�$)::Z�\r�$i��-��~-[�Ln�[������f]�t��q�TRR�}��I��.]�-Zh����v�'NTRR�v�����J�g
���kiii�����'''K�������4����Z��=o-++K���*((P�>}��@�W�^�����#G|����t��}��w�����~�m!���%Im���)����������}�����UTT��={Z���U+I�������#Ij�����$)66V�TXX�n���w�y�����67�x�`� �������r����ZM�p8��V���WTT��F
�$UVV������f����H�"""$I�<��}���<y�"##�u�Vm��]/���^x�5o��|�m����"M�
4m�8�t�@�E|����$��n�RSS��!!!�������Fn��Zl��^��m����u�����Z-[�4�o;v��~�i���j����<y�O���?�A= �W�K�I�k555z��g�����z���$yV�UWW��r)44�hSSS���j9�N����3+��eN����43s;Ij����Z�4|�p���*77�Ze?@���$�BBBt��w��I�V�Z);;['N�PBB�Q^TT$���7�e��E����=��������D�s�����-�r��'I�9
6�Z,Ij���v�����L����$I��w7��q8j���rrrTRR������3��m+I���4��<(����;Z����7I�X~j����$�^���<%%E�C#F�0�rrr�p�B<x��R�����n���(//��M��������+&&F�:u��#G|�?���o����a��),��[���Suu����ri��u����d���'Y�V��C�*))Iiiiz����wo���*--M'N4V�I�?�����_��m������)S�h�������t��I���j���*..�-����O����.��/����^\p�����l�2EFF��K.1~�?��j���
��_���Lu��M4� ����;�I����T�4�����l���C���*((��	t��W���v��!eff�o��9r�Q��ys���[�����}�����r�4{�lM�0�h����V�Zi�����}����+66V��v��v�j�;q������o��F�v�Rqq�F���s�*22�h��t��qI�c���nI����O��CYY�������(k��n�������h�F�:~�����������pk�$���F���


UBB������\.����I���=��M�gor��r0��\l
�?���2�@���s������*}��w���Tee����t��)���)22RQQQJLLT||���y�v����[���Saa�������h�o�^���JLL���P$�����y��|�Mkq�.\(I:r��~�aKmm�����������G�e���&�|��7z������k����O��P�6m�U�Cr
�TYY��{�j������5e���7�Qhh���$i��%Z�h��n�����{������M�5���P�\.k�$O���O?UFF����nEFF��o���X���cG���GN�SEEE���o�m			����O{pf"��_������k�����/����$�����g����o����={����USS���2���h��]����TXXh���g��{�=]{��F�������k|��+��BS�N�)�������(**�Z�P$������j0�a\;���W���Rxx�$)$$D111���Qrr�~��_��w�UJJ��~����1c�Z�n-I���oUPP`��5�obM���o�9s�X��,�Z���p]}������O��-[��C��P!Or
�k������)S|��������rS���4m$���;�|.))1��N��F������6�k������lN�Yo�W����6�k�Enn�������W�^j����9==].���M�5�b���>�{��a\���k��i�Zi��%z����o�>�r���\L�l���\

U�~�L-�/��VYff�{�1�������}�@�f-�Q^^��.]�+V�l�8a��l�����p���{�`��Z���n�����{��u���3gj��>���Fr
Ae��5���P�-�p8T^^���lX��M�6�9s��X�g{����Nc������km	������zJ#G��u�]�sN8s�\@P)**RQQ������$�u�]j�����Grr�~�a������>��;|�7o���G����"�@��k�IBB�~�����'�T�����u�������n=���JNN��;t���|�M�2pfb��J�����cG�����r)**J��7W�t�Yg�[�nr8��l�������?��/������M�6���/V�L������J�~�4k�,k�i�p84}�t���+%%E��v��u�V�k�����L�6����C�|>�3�5�'��M9�N�sqq����H�?�@�r�H�?���UTT�M��LDr
h���m���Z����R,�)2d��gp�	�����+��g��[�n�0a����IRuu�v���E������=III6l����H���r��v�ZIRff�233%IN�SQQQ*--Uuu��5o�\��r�BCC}���������WQQ��X>��y�i�F���S�N��U�Dr
h�>}����_|�]�v�����D����?_S�L����V�3�c���nI�����@=���u�����\���j����t��v��Y��3Xzz�$V�?Z�f���_?k1h�B��#��Dr
���`�5�&�k�M$��H�6�\l"��Dr
���`�5�&�k�M$��H�6�\l"��Dr
���`�5�&�k�M$��H�6�\l"��Dr
���`�5�&�k�M$��H�6�\l"��Dr
���`�5�&�k�M$��H�6�\l"��Dr
���`�5�&�k�M$��H�6�\l"��Dr
�)�{���n.`��5��^�z9�e���2�7�[a�IEND�B`�
raw_data.txttext/plain; charset=UTF-8; name=raw_data.txtDownload
#52Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Anton A. Melnikov (#51)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On 12/26/23 11:49, Anton A. Melnikov wrote:

Hello!

Earlier in this thread, the pgbench results were published, where with a
strong memory limit of 100MB
a significant, about 10%, decrease in TPS was observed [1].

Using dedicated server with 12GB RAM and methodology described in [3], i
performed five series
of measurements for the patches from the [2].

Can you share some info about the hardware? For example the CPU model,
number of cores, and so on. 12GB RAM is not quite huge, so presumably it
was a small machine.

The series were like this:
1) unpatched 16th version at the REL_16_BETA1 (e0b82fc8e83) as close to
[2] in time.
2) patched REL_16_BETA1 at e0b82fc8e83 with undefined
max_total_backend_memory GUC (with default value = 0).
3) patched REL_16_BETA1 with max_total_backend_memory = 16GB
4) the same with max_total_backend_memory = 8GB
5) and again with max_total_backend_memory = 200MB

OK

Measurements with max_total_backend_memory = 100MB were not be carried out,
with limit 100MB the server gave an error on startup:
FATAL:  configured max_total_backend_memory 100MB is <=
shared_memory_size 143MB
So i used 200MB to retain all other GUCs the same.

I'm not very familiar with the patch yet, but this seems a bit strange.
Why should shared_buffers be included this limit?

Pgbench gave the following results:
1) and 2) almost the same: ~6350 TPS. See orange and green
distributions on the attached graph.png respectively.
3) and 4) identical to each other (~6315 TPS) and a bit slower than 1)
and 2) by ~0,6%.
See blue and yellow distributions respectively.
5) is slightly slower (~6285 TPS) than 3) and 4) by another 0,5%. (grey
distribution)
The standard error in all series was ~0.2%. There is a raw data in the
raw_data.txt.

I think 6350 is a pretty terrible number, especially for scale 8, which
is maybe 150MB of data. I think that's a pretty clear sign the system
was hitting some other bottleneck, which can easily mask regressions in
the memory allocation code. AFAICS the pgbench runs were regular r/w
benchmarks, so I'd bet it was hitting I/O, and possibly even subject to
some random effects at that level.

I think what would be interesting are runs with

pgbench -M prepared -S -c $N -j $N

i.e. read-only tests (to not hit I/O), and $N being sufficiently large
to maybe also show some concurrency/locking bottlenecks, etc.

I may do some benchmarks if I happen to find a bit of time, but maybe
you could collect such numbers too?

The other benchmark that might be interesting is more OLAP, with low
concurrency but backends allocating a lot of memory.

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#53Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Noname (#38)
3 attachment(s)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

Hi,

I wanted to take a look at the patch, and I noticed it's broken since
3d51cb5197 renamed a couple pgstat functions in August. I plan to maybe
do some benchmarks etc. preferably on current master, so here's a
version fixing that minor bitrot.

As for the patch, I only skimmed through the thread so far, to get some
idea of what the approach and goals are, etc. I didn't look at the code
yet, so can't comment on that.

However, at pgconf.eu a couple week ago I had quite a few discussions
about such "backend memory limit" could/should work in principle, and
I've been thinking about ways to implement this. So let me share some
thoughts about how this patch aligns with that ...

(FWIW it's not my intent to hijack or derail this patch in any way, but
there's a couple things I think we should do differently.)

I'm 100% on board with having a memory limit "above" work_mem. It's
really annoying that we have no way to restrict the amount of memory a
backend can allocate for complex queries, etc.

But I find it a bit strange that we aim to introduce a "global" memory
limit for all backends combined first. I'm not against having that too,
but it's not the feature I usually wish to have. I need some protection
against runaway backends, that happen to allocate a lot memory.

Similarly, I'd like to be able to have different limits depending on
what the backend does - a backend doing OLAP may naturally need more
memory, while a backend doing OLTP may have a much tighter limit.

But with a single global limit none of this is possible. It may help
reducing the risk of unexpected OOM issues (not 100%, but useful), but
it can't limit the impact to the one backend - if memory starts runnning
out, it will affect all other backends a bit randomly (depending on the
order in which the backends happen to allocate memory). And it does not
consider what workloads the backends execute.

Let me propose a slightly different architecture that I imagined while
thinking about this. It's not radically differrent from what the patch
does, but it focuses on the local accounting first. I believe it's
possible to extend this to enforce the global limit too.

FWIW I haven't tried implementing this - I don't want to "hijack" this
thread and do my own thing. I can take a stab at a PoC if needed.

Firstly, I'm not quite happy with how all the memory contexts have to
do their own version of the accounting and memory checking. I think we
should move that into a new abstraction which I call "memory pool".
It's very close to "memory context" but it only deals with allocating
blocks, not the chunks requested by palloc() etc. So when someone does
palloc(), that may be AllocSetAlloc(). And instead of doing malloc()
that would do MemoryPoolAlloc(blksize), and then that would do all the
accounting and checks, and then do malloc().

This may sound like an unnecessary indirection, but the idea is that a
single memory pool would back many memory contexts (perhaps all for
a given backend). In principle we might even establish separate memory
pools for different parts of the memory context hierarchy, but I'm not
sure we need that.

I can imagine the pool could also cache blocks for cases when we create
and destroy contexts very often, but glibc should already does that for
us, I believe.

For me, the accounting and memory context is the primary goal. I wonder
if we considered this context/pool split while working on the accounting
for hash aggregate, but I think we were too attached to doing all of it
in the memory context hierarchy.

Of course, this memory pool is per backend, and so would be the memory
accounting and limit enforced by it. But I can imagine extending to do
a global limit similar to what the current patch does - using a counter
in shared memory, or something. I haven't reviewed what's the overhead
or how it handles cases when a backend terminates in some unexpected
way. But whatever the current patch does, memory pool could do too.

Secondly, I think there's an annoying issue with the accounting at the
block level - it makes it problematic to use low limit values. We double
the block size, so we may quickly end up with a block size a couple MBs,
which means the accounting granularity gets very coarse.

I think it'd be useful to introduce a "backpressure" between the memory
pool and the memory context, depending on how close we are to the limit.
For example if the limit is 128MB and the backend allocated 16MB so far,
we're pretty far away from the limit. So if the backend requests 8MB
block, that's fine and the memory pool should malloc() that. But if we
already allocated 100MB, maybe we should be careful and not allow 8MB
blocks - the memory pool should be allowed to override this and return
just 1MB block. Sure, this would have to be optional, and not all places
can accept a smaller block than requested (when the chunk would not fit
into the smaller block). It would require a suitable memory pool API
and more work in the memory contexts, but it seems pretty useful.
Certainly not something for v1.

regards

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

Attachments:

v20231226-0001-Add-tracking-of-backend-memory-allocated.patchtext/x-patch; charset=UTF-8; name=v20231226-0001-Add-tracking-of-backend-memory-allocated.patchDownload
From ad74704ef5a62f9d2b8d98f40d6fbc5b52bc742b Mon Sep 17 00:00:00 2001
From: Tomas Vondra <tomas@2ndquadrant.com>
Date: Tue, 26 Dec 2023 17:54:40 +0100
Subject: [PATCH v20231226 1/3] Add tracking of backend memory allocated

Add tracking of backend memory allocated in total and by allocation
type (aset, dsm, generation, slab) by process.

allocated_bytes tracks the current bytes of memory allocated to the
backend process. aset_allocated_bytes, dsm_allocated_bytes,
generation_allocated_bytes and slab_allocated_bytes track the
allocation by type for the backend process. They are updated for the
process as memory is malloc'd/freed.  Memory allocated to items on
the freelist is included.  Dynamic shared memory allocations are
included only in the value displayed for the backend that created
them, they are not included in the value for backends that are
attached to them to avoid double counting. DSM allocations that are
not destroyed by the creating process prior to it's exit are
considered long lived and are tracked in a global counter
global_dsm_allocated_bytes. We limit the floor of allocation
counters to zero. Created views pg_stat_global_memory_allocation and
pg_stat_memory_allocation for access to these trackers.
---
 doc/src/sgml/monitoring.sgml                | 246 ++++++++++++++++++++
 src/backend/catalog/system_views.sql        |  34 +++
 src/backend/storage/ipc/dsm.c               |  11 +-
 src/backend/storage/ipc/dsm_impl.c          |  78 +++++++
 src/backend/storage/lmgr/proc.c             |   1 +
 src/backend/utils/activity/backend_status.c | 114 +++++++++
 src/backend/utils/adt/pgstatfuncs.c         |  84 +++++++
 src/backend/utils/init/miscinit.c           |   3 +
 src/backend/utils/mmgr/aset.c               |  17 ++
 src/backend/utils/mmgr/generation.c         |  15 ++
 src/backend/utils/mmgr/slab.c               |  22 ++
 src/include/catalog/pg_proc.dat             |  17 ++
 src/include/storage/proc.h                  |   2 +
 src/include/utils/backend_status.h          | 144 +++++++++++-
 src/test/regress/expected/rules.out         |  27 +++
 src/test/regress/expected/stats.out         |  36 +++
 src/test/regress/sql/stats.sql              |  20 ++
 17 files changed, 869 insertions(+), 2 deletions(-)

diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 4f8058d8b1b..99f5acf07f4 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -4563,6 +4563,252 @@ description | Waiting for a newly initialized WAL file to reach durable storage
 
  </sect2>
 
+ <sect2 id="monitoring-pg-stat-memory-allocation-view">
+  <title><structname>pg_stat_memory_allocation</structname></title>
+
+  <indexterm>
+   <primary>pg_stat_memory_allocation</primary>
+  </indexterm>
+
+  <para>
+   The <structname>pg_stat_memory_allocation</structname> view will have one
+   row per server process, showing information related to the current memory
+   allocation of that process in total and by allocator type. Due to the
+   dynamic nature of memory allocations the allocated bytes values may not be
+   exact but should be sufficient for the intended purposes. Dynamic shared
+   memory allocations are included only in the value displayed for the backend
+   that created them, they are not included in the value for backends that are
+   attached to them to avoid double counting.  Use
+   <function>pg_size_pretty</function> described in
+   <xref linkend="functions-admin-dbsize"/> to make these values more easily
+   readable.
+  </para>
+
+  <table id="pg-stat-memory-allocation-view" xreflabel="pg_stat_memory_allocation">
+   <title><structname>pg_stat_memory_allocation</structname> View</title>
+   <tgroup cols="1">
+    <thead>
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       Column Type
+      </para>
+      <para>
+       Description
+      </para></entry>
+     </row>
+    </thead>
+
+    <tbody>
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>datid</structfield> <type>oid</type>
+      </para>
+      <para>
+       OID of the database this backend is connected to
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>pid</structfield> <type>integer</type>
+      </para>
+      <para>
+       Process ID of this backend
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>allocated_bytes</structfield> <type>bigint</type>
+      </para>
+     <para>
+      Memory currently allocated to this backend in bytes. This is the balance
+      of bytes allocated and freed by this backend. Dynamic shared memory
+      allocations are included only in the value displayed for the backend that
+      created them, they are not included in the value for backends that are
+      attached to them to avoid double counting.
+     </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>aset_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Memory currently allocated to this backend in bytes via the allocation
+       set allocator.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>dsm_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Memory currently allocated to this backend in bytes via the dynamic
+       shared memory allocator. Upon process exit, dsm allocations that have
+       not been freed are considered long lived and added to
+       <structfield>global_dsm_allocated_bytes</structfield> found in the
+       <link linkend="monitoring-pg-stat-global-memory-allocation-view">
+       <structname>pg_stat_global_memory_allocation</structname></link> view.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>generation_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Memory currently allocated to this backend in bytes via the generation
+       allocator.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>slab_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Memory currently allocated to this backend in bytes via the slab
+       allocator.
+      </para></entry>
+     </row>
+
+    </tbody>
+   </tgroup>
+  </table>
+
+ </sect2>
+
+ <sect2 id="monitoring-pg-stat-global-memory-allocation-view">
+  <title><structname>pg_stat_global_memory_allocation</structname></title>
+
+  <indexterm>
+   <primary>pg_stat_global-memory_allocation</primary>
+  </indexterm>
+
+  <para>
+   The <structname>pg_stat_global_memory_allocation</structname> view will
+   have one row showing information related to current shared memory
+   allocations. Due to the dynamic nature of memory allocations the allocated
+   bytes values may not be exact but should be sufficient for the intended
+   purposes. Use <function>pg_size_pretty</function> described in
+   <xref linkend="functions-admin-dbsize"/> to make the byte populated values
+   more easily readable.
+  </para>
+
+  <table id="pg-stat-global-memory-allocation-view" xreflabel="pg_stat_global_memory_allocation">
+   <title><structname>pg_stat_global_memory_allocation</structname> View</title>
+   <tgroup cols="1">
+    <thead>
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       Column Type
+      </para>
+      <para>
+       Description
+      </para></entry>
+     </row>
+    </thead>
+
+    <tbody>
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>datid</structfield> <type>oid</type>
+      </para>
+      <para>
+       OID of the database this backend is connected to
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>shared_memory_size_mb</structfield> <type>integer</type>
+      </para>
+      <para>
+       Reports the size of the main shared memory area, rounded up to the
+       nearest megabyte. See <xref linkend="guc-shared-memory-size"/>.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>shared_memory_size_in_huge_pages</structfield> <type>bigint</type>
+      </para>
+     <para>
+      Reports the number of huge pages that are needed for the main shared
+      memory area based on the specified huge_page_size. If huge pages are not
+      supported, this will be -1. See
+      <xref linkend="guc-shared-memory-size-in-huge-pages"/>.
+     </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>global_dsm_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Long lived dynamically allocated memory currently allocated to the
+       database. Upon process exit, dsm allocations that have not been freed
+       are considered long lived and added to
+       <structfield>global_dsm_allocated_bytes</structfield>.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>total_aset_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Sum total of <structfield>aset_allocated_bytes</structfield> for all
+       backend processes from
+       <link linkend="monitoring-pg-stat-memory-allocation-view">
+       <structname>pg_stat_memory_allocation</structname></link> view.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>total_dsm_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Sum total of <structfield>dsm_allocated_bytes</structfield> for all
+       backend processes from
+       <link linkend="monitoring-pg-stat-memory-allocation-view">
+       <structname>pg_stat_memory_allocation</structname></link> view.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>total_generation_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Sum total of <structfield>generation_allocated_bytes</structfield> for
+       all backend processes from
+       <link linkend="monitoring-pg-stat-memory-allocation-view">
+       <structname>pg_stat_memory_allocation</structname></link> view.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>total_slab_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Sum total of <structfield>slab_allocated_bytes</structfield> for all
+       backend processes from
+       <link linkend="monitoring-pg-stat-memory-allocation-view">
+       <structname>pg_stat_memory_allocation</structname></link> view.
+      </para></entry>
+     </row>
+
+    </tbody>
+   </tgroup>
+  </table>
+
+ </sect2>
+
  <sect2 id="monitoring-stats-functions">
   <title>Statistics Functions</title>
 
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 11d18ed9dd6..fd7fcaf59e3 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -1369,3 +1369,37 @@ CREATE VIEW pg_stat_subscription_stats AS
 
 CREATE VIEW pg_wait_events AS
     SELECT * FROM pg_get_wait_events();
+
+CREATE VIEW pg_stat_memory_allocation AS
+    SELECT
+        S.datid AS datid,
+        S.pid,
+        S.allocated_bytes,
+        S.aset_allocated_bytes,
+        S.dsm_allocated_bytes,
+        S.generation_allocated_bytes,
+        S.slab_allocated_bytes
+    FROM pg_stat_get_memory_allocation(NULL) AS S
+        LEFT JOIN pg_database AS D ON (S.datid = D.oid);
+
+CREATE VIEW pg_stat_global_memory_allocation AS
+WITH sums AS (
+    SELECT
+        SUM(aset_allocated_bytes) AS total_aset_allocated_bytes,
+        SUM(dsm_allocated_bytes) AS total_dsm_allocated_bytes,
+        SUM(generation_allocated_bytes) AS total_generation_allocated_bytes,
+        SUM(slab_allocated_bytes) AS total_slab_allocated_bytes
+    FROM
+        pg_stat_memory_allocation
+)
+SELECT
+        S.datid AS datid,
+        current_setting('shared_memory_size', true) as shared_memory_size,
+        (current_setting('shared_memory_size_in_huge_pages', true))::integer as shared_memory_size_in_huge_pages,
+        S.global_dsm_allocated_bytes,
+        sums.total_aset_allocated_bytes,
+        sums.total_dsm_allocated_bytes,
+        sums.total_generation_allocated_bytes,
+        sums.total_slab_allocated_bytes
+    FROM sums, pg_stat_get_global_memory_allocation() AS S
+        LEFT JOIN pg_database AS D ON (S.datid = D.oid);
diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c
index 628f3ecd3fb..6725780fc77 100644
--- a/src/backend/storage/ipc/dsm.c
+++ b/src/backend/storage/ipc/dsm.c
@@ -803,6 +803,15 @@ dsm_detach_all(void)
 void
 dsm_detach(dsm_segment *seg)
 {
+	/*
+	 * Retain mapped_size to pass into destroy call in cases where the detach
+	 * is the last reference. mapped_size is zeroed as part of the detach
+	 * process, but is needed later in these cases for dsm_allocated_bytes
+	 * accounting.
+	 */
+	Size		local_seg_mapped_size = seg->mapped_size;
+	Size	   *ptr_local_seg_mapped_size = &local_seg_mapped_size;
+
 	/*
 	 * Invoke registered callbacks.  Just in case one of those callbacks
 	 * throws a further error that brings us back here, pop the callback
@@ -883,7 +892,7 @@ dsm_detach(dsm_segment *seg)
 			 */
 			if (is_main_region_dsm_handle(seg->handle) ||
 				dsm_impl_op(DSM_OP_DESTROY, seg->handle, 0, &seg->impl_private,
-							&seg->mapped_address, &seg->mapped_size, WARNING))
+							&seg->mapped_address, ptr_local_seg_mapped_size, WARNING))
 			{
 				LWLockAcquire(DynamicSharedMemoryControlLock, LW_EXCLUSIVE);
 				if (is_main_region_dsm_handle(seg->handle))
diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c
index 35fa910d6f2..a9e0987747b 100644
--- a/src/backend/storage/ipc/dsm_impl.c
+++ b/src/backend/storage/ipc/dsm_impl.c
@@ -66,6 +66,7 @@
 #include "postmaster/postmaster.h"
 #include "storage/dsm_impl.h"
 #include "storage/fd.h"
+#include "utils/backend_status.h"
 #include "utils/guc.h"
 #include "utils/memutils.h"
 
@@ -232,6 +233,14 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_allocated_bytes_decrease(*mapped_size, PG_ALLOC_DSM);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && shm_unlink(name) != 0)
@@ -332,6 +341,33 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+	{
+		/*
+		 * Posix creation calls dsm_impl_posix_resize implying that resizing
+		 * occurs or may be added in the future. As implemented
+		 * dsm_impl_posix_resize utilizes fallocate or truncate, passing the
+		 * whole new size as input, growing the allocation as needed (only
+		 * truncate supports shrinking). We update by replacing the old
+		 * allocation with the new.
+		 */
+#if defined(HAVE_POSIX_FALLOCATE) && defined(__linux__)
+		/*
+		 * posix_fallocate does not shrink allocations, adjust only on
+		 * allocation increase.
+		 */
+		if (request_size > *mapped_size)
+			pgstat_report_allocated_bytes_increase(request_size - *mapped_size, PG_ALLOC_DSM);
+#else
+		pgstat_report_allocated_bytes_decrease(*mapped_size, PG_ALLOC_DSM);
+		pgstat_report_allocated_bytes_increase(request_size, PG_ALLOC_DSM);
+#endif
+	}
 	*mapped_address = address;
 	*mapped_size = request_size;
 	close(fd);
@@ -538,6 +574,14 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_allocated_bytes_decrease(*mapped_size, PG_ALLOC_DSM);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && shmctl(ident, IPC_RMID, NULL) < 0)
@@ -585,6 +629,13 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_allocated_bytes_increase(request_size, PG_ALLOC_DSM);
 	*mapped_address = address;
 	*mapped_size = request_size;
 
@@ -653,6 +704,13 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 			return false;
 		}
 
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_allocated_bytes_decrease(*mapped_size, PG_ALLOC_DSM);
 		*impl_private = NULL;
 		*mapped_address = NULL;
 		*mapped_size = 0;
@@ -769,6 +827,12 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 		return false;
 	}
 
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_allocated_bytes_increase(info.RegionSize, PG_ALLOC_DSM);
 	*mapped_address = address;
 	*mapped_size = info.RegionSize;
 	*impl_private = hmap;
@@ -813,6 +877,13 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		pgstat_report_allocated_bytes_decrease(*mapped_size, PG_ALLOC_DSM);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && unlink(name) != 0)
@@ -934,6 +1005,13 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_allocated_bytes_increase(request_size, PG_ALLOC_DSM);
 	*mapped_address = address;
 	*mapped_size = request_size;
 
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index b6451d9d083..81304a569c0 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -180,6 +180,7 @@ InitProcGlobal(void)
 	ProcGlobal->checkpointerLatch = NULL;
 	pg_atomic_init_u32(&ProcGlobal->procArrayGroupFirst, INVALID_PGPROCNO);
 	pg_atomic_init_u32(&ProcGlobal->clogGroupFirst, INVALID_PGPROCNO);
+	pg_atomic_init_u64(&ProcGlobal->global_dsm_allocation, 0);
 
 	/*
 	 * Create and initialize all the PGPROC structures we'll need.  There are
diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c
index 6e734c6caff..838a7337933 100644
--- a/src/backend/utils/activity/backend_status.c
+++ b/src/backend/utils/activity/backend_status.c
@@ -49,6 +49,24 @@ int			pgstat_track_activity_query_size = 1024;
 /* exposed so that backend_progress.c can access it */
 PgBackendStatus *MyBEEntry = NULL;
 
+/*
+ * Memory allocated to this backend prior to pgstats initialization. Migrated to
+ * shared memory on pgstats initialization.
+ */
+uint64		local_my_allocated_bytes = 0;
+uint64	   *my_allocated_bytes = &local_my_allocated_bytes;
+
+/* Memory allocated to this backend by type prior to pgstats initialization.
+ * Migrated to shared memory on pgstats initialization
+ */
+uint64		local_my_aset_allocated_bytes = 0;
+uint64	   *my_aset_allocated_bytes = &local_my_aset_allocated_bytes;
+uint64		local_my_dsm_allocated_bytes = 0;
+uint64	   *my_dsm_allocated_bytes = &local_my_dsm_allocated_bytes;
+uint64		local_my_generation_allocated_bytes = 0;
+uint64	   *my_generation_allocated_bytes = &local_my_generation_allocated_bytes;
+uint64		local_my_slab_allocated_bytes = 0;
+uint64	   *my_slab_allocated_bytes = &local_my_slab_allocated_bytes;
 
 static PgBackendStatus *BackendStatusArray = NULL;
 static char *BackendAppnameBuffer = NULL;
@@ -401,6 +419,32 @@ pgstat_bestart(void)
 	lbeentry.st_progress_command_target = InvalidOid;
 	lbeentry.st_query_id = UINT64CONST(0);
 
+	/* Alter allocation reporting from local storage to shared memory */
+	pgstat_set_allocated_bytes_storage(&MyBEEntry->allocated_bytes,
+									   &MyBEEntry->aset_allocated_bytes,
+									   &MyBEEntry->dsm_allocated_bytes,
+									   &MyBEEntry->generation_allocated_bytes,
+									   &MyBEEntry->slab_allocated_bytes);
+
+	/*
+	 * Populate sum of memory allocated prior to pgstats initialization to
+	 * pgstats and zero the local variable. This is a += assignment because
+	 * InitPostgres allocates memory after pgstat_beinit but prior to
+	 * pgstat_bestart so we have allocations to both local and shared memory
+	 * to combine.
+	 */
+	lbeentry.allocated_bytes += local_my_allocated_bytes;
+	local_my_allocated_bytes = 0;
+	lbeentry.aset_allocated_bytes += local_my_aset_allocated_bytes;
+	local_my_aset_allocated_bytes = 0;
+
+	lbeentry.dsm_allocated_bytes += local_my_dsm_allocated_bytes;
+	local_my_dsm_allocated_bytes = 0;
+	lbeentry.generation_allocated_bytes += local_my_generation_allocated_bytes;
+	local_my_generation_allocated_bytes = 0;
+	lbeentry.slab_allocated_bytes += local_my_slab_allocated_bytes;
+	local_my_slab_allocated_bytes = 0;
+
 	/*
 	 * we don't zero st_progress_param here to save cycles; nobody should
 	 * examine it until st_progress_command has been set to something other
@@ -460,6 +504,9 @@ pgstat_beshutdown_hook(int code, Datum arg)
 {
 	volatile PgBackendStatus *beentry = MyBEEntry;
 
+	/* Stop reporting memory allocation changes to shared memory */
+	pgstat_reset_allocated_bytes_storage();
+
 	/*
 	 * Clear my status entry, following the protocol of bumping st_changecount
 	 * before and after.  We use a volatile pointer here to ensure the
@@ -1214,3 +1261,70 @@ pgstat_clip_activity(const char *raw_activity)
 
 	return activity;
 }
+
+/*
+ * Configure bytes allocated reporting to report allocated bytes to
+ * shared memory.
+ *
+ * Expected to be called during backend startup (in pgstat_bestart), to point
+ * allocated bytes accounting into shared memory.
+ */
+void
+pgstat_set_allocated_bytes_storage(uint64 *allocated_bytes,
+								   uint64 *aset_allocated_bytes,
+								   uint64 *dsm_allocated_bytes,
+								   uint64 *generation_allocated_bytes,
+								   uint64 *slab_allocated_bytes)
+{
+	/* Map allocations to shared memory */
+	my_allocated_bytes = allocated_bytes;
+	*allocated_bytes = local_my_allocated_bytes;
+
+	my_aset_allocated_bytes = aset_allocated_bytes;
+	*aset_allocated_bytes = local_my_aset_allocated_bytes;
+
+	my_dsm_allocated_bytes = dsm_allocated_bytes;
+	*dsm_allocated_bytes = local_my_dsm_allocated_bytes;
+
+	my_generation_allocated_bytes = generation_allocated_bytes;
+	*generation_allocated_bytes = local_my_generation_allocated_bytes;
+
+	my_slab_allocated_bytes = slab_allocated_bytes;
+	*slab_allocated_bytes = local_my_slab_allocated_bytes;
+}
+
+/*
+ * Reset allocated bytes storage location.
+ *
+ * Expected to be called during backend shutdown, before the locations set up
+ * by pgstat_set_allocated_bytes_storage become invalid.
+ */
+void
+pgstat_reset_allocated_bytes_storage(void)
+{
+	if (ProcGlobal)
+	{
+		volatile PROC_HDR *procglobal = ProcGlobal;
+
+		/*
+		 * Add dsm allocations that have not been freed to global dsm
+		 * accounting
+		 */
+		pg_atomic_add_fetch_u64(&procglobal->global_dsm_allocation,
+								*my_dsm_allocated_bytes);
+	}
+
+	/* Reset memory allocation variables */
+	*my_allocated_bytes = local_my_allocated_bytes = 0;
+	*my_aset_allocated_bytes = local_my_aset_allocated_bytes = 0;
+	*my_dsm_allocated_bytes = local_my_dsm_allocated_bytes = 0;
+	*my_generation_allocated_bytes = local_my_generation_allocated_bytes = 0;
+	*my_slab_allocated_bytes = local_my_slab_allocated_bytes = 0;
+
+	/* Point my_{*_}allocated_bytes from shared memory back to local */
+	my_allocated_bytes = &local_my_allocated_bytes;
+	my_aset_allocated_bytes = &local_my_aset_allocated_bytes;
+	my_dsm_allocated_bytes = &local_my_dsm_allocated_bytes;
+	my_generation_allocated_bytes = &local_my_generation_allocated_bytes;
+	my_slab_allocated_bytes = &local_my_slab_allocated_bytes;
+}
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 0cea320c00e..b372ee691ba 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -2016,3 +2016,87 @@ pg_stat_have_stats(PG_FUNCTION_ARGS)
 
 	PG_RETURN_BOOL(pgstat_have_entry(kind, dboid, objoid));
 }
+
+/*
+ * Get the memory allocation of PG backends.
+ */
+Datum
+pg_stat_get_memory_allocation(PG_FUNCTION_ARGS)
+{
+#define PG_STAT_GET_MEMORY_ALLOCATION_COLS	7
+	int			num_backends = pgstat_fetch_stat_numbackends();
+	int			curr_backend;
+	int			pid = PG_ARGISNULL(0) ? -1 : PG_GETARG_INT32(0);
+	ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
+
+	InitMaterializedSRF(fcinfo, 0);
+
+	/* 1-based index */
+	for (curr_backend = 1; curr_backend <= num_backends; curr_backend++)
+	{
+		/* for each row */
+		Datum		values[PG_STAT_GET_MEMORY_ALLOCATION_COLS] = {0};
+		bool		nulls[PG_STAT_GET_MEMORY_ALLOCATION_COLS] = {0};
+		LocalPgBackendStatus *local_beentry;
+		PgBackendStatus *beentry;
+
+		/* Get the next one in the list */
+		local_beentry = pgstat_fetch_stat_local_beentry(curr_backend);
+		beentry = &local_beentry->backendStatus;
+
+		/* If looking for specific PID, ignore all the others */
+		if (pid != -1 && beentry->st_procpid != pid)
+			continue;
+
+		/* Values available to all callers */
+		if (beentry->st_databaseid != InvalidOid)
+			values[0] = ObjectIdGetDatum(beentry->st_databaseid);
+		else
+			nulls[0] = true;
+
+		values[1] = Int32GetDatum(beentry->st_procpid);
+		values[2] = UInt64GetDatum(beentry->allocated_bytes);
+		values[3] = UInt64GetDatum(beentry->aset_allocated_bytes);
+		values[4] = UInt64GetDatum(beentry->dsm_allocated_bytes);
+		values[5] = UInt64GetDatum(beentry->generation_allocated_bytes);
+		values[6] = UInt64GetDatum(beentry->slab_allocated_bytes);
+
+		tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
+
+		/* If only a single backend was requested, and we found it, break. */
+		if (pid != -1)
+			break;
+	}
+
+	return (Datum) 0;
+}
+
+/*
+ * Get the global memory allocation statistics.
+ */
+Datum
+pg_stat_get_global_memory_allocation(PG_FUNCTION_ARGS)
+{
+#define PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS	2
+	TupleDesc	tupdesc;
+	Datum		values[PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS] = {0};
+	bool		nulls[PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS] = {0};
+	volatile PROC_HDR *procglobal = ProcGlobal;
+
+	/* Initialise attributes information in the tuple descriptor */
+	tupdesc = CreateTemplateTupleDesc(PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS);
+	TupleDescInitEntry(tupdesc, (AttrNumber) 1, "datid",
+					   OIDOID, -1, 0);
+	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "global_dsm_allocated_bytes",
+					   INT8OID, -1, 0);
+	BlessTupleDesc(tupdesc);
+
+	/* datid */
+	values[0] = ObjectIdGetDatum(MyDatabaseId);
+
+	/* get global_dsm_allocated_bytes */
+	values[1] = Int64GetDatum(pg_atomic_read_u64(&procglobal->global_dsm_allocation));
+
+	/* Returns the record as Datum */
+	PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls)));
+}
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index 5c9b6f991e0..2b082c68df6 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -170,6 +170,9 @@ InitPostmasterChild(void)
 				(errcode_for_socket_access(),
 				 errmsg_internal("could not set postmaster death monitoring pipe to FD_CLOEXEC mode: %m")));
 #endif
+
+	/* Init allocated bytes to avoid double counting parent allocation */
+	pgstat_init_allocated_bytes();
 }
 
 /*
diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index c3affaf5a8a..7af0d141da2 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -47,6 +47,7 @@
 #include "postgres.h"
 
 #include "port/pg_bitutils.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -517,6 +518,7 @@ AllocSetContextCreateInternal(MemoryContext parent,
 						name);
 
 	((MemoryContext) set)->mem_allocated = firstBlockSize;
+	pgstat_report_allocated_bytes_increase(firstBlockSize, PG_ALLOC_ASET);
 
 	return (MemoryContext) set;
 }
@@ -539,6 +541,7 @@ AllocSetReset(MemoryContext context)
 	AllocSet	set = (AllocSet) context;
 	AllocBlock	block;
 	Size		keepersize PG_USED_FOR_ASSERTS_ONLY;
+	uint64		deallocation = 0;
 
 	Assert(AllocSetIsValid(set));
 
@@ -581,6 +584,7 @@ AllocSetReset(MemoryContext context)
 		{
 			/* Normal case, release the block */
 			context->mem_allocated -= block->endptr - ((char *) block);
+			deallocation += block->endptr - ((char *) block);
 
 #ifdef CLOBBER_FREED_MEMORY
 			wipe_mem(block, block->freeptr - ((char *) block));
@@ -591,6 +595,7 @@ AllocSetReset(MemoryContext context)
 	}
 
 	Assert(context->mem_allocated == keepersize);
+	pgstat_report_allocated_bytes_decrease(deallocation, PG_ALLOC_ASET);
 
 	/* Reset block size allocation sequence, too */
 	set->nextBlockSize = set->initBlockSize;
@@ -609,6 +614,7 @@ AllocSetDelete(MemoryContext context)
 	AllocSet	set = (AllocSet) context;
 	AllocBlock	block = set->blocks;
 	Size		keepersize PG_USED_FOR_ASSERTS_ONLY;
+	uint64		deallocation = 0;
 
 	Assert(AllocSetIsValid(set));
 
@@ -647,11 +653,13 @@ AllocSetDelete(MemoryContext context)
 
 				freelist->first_free = (AllocSetContext *) oldset->header.nextchild;
 				freelist->num_free--;
+				deallocation += oldset->header.mem_allocated;
 
 				/* All that remains is to free the header/initial block */
 				free(oldset);
 			}
 			Assert(freelist->num_free == 0);
+			pgstat_report_allocated_bytes_decrease(deallocation, PG_ALLOC_ASET);
 		}
 
 		/* Now add the just-deleted context to the freelist. */
@@ -668,7 +676,10 @@ AllocSetDelete(MemoryContext context)
 		AllocBlock	next = block->next;
 
 		if (!IsKeeperBlock(set, block))
+		{
 			context->mem_allocated -= block->endptr - ((char *) block);
+			deallocation += block->endptr - ((char *) block);
+		}
 
 #ifdef CLOBBER_FREED_MEMORY
 		wipe_mem(block, block->freeptr - ((char *) block));
@@ -681,6 +692,7 @@ AllocSetDelete(MemoryContext context)
 	}
 
 	Assert(context->mem_allocated == keepersize);
+	pgstat_report_allocated_bytes_decrease(deallocation + context->mem_allocated, PG_ALLOC_ASET);
 
 	/* Finally, free the context header, including the keeper block */
 	free(set);
@@ -730,6 +742,7 @@ AllocSetAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_allocated_bytes_increase(blksize, PG_ALLOC_ASET);
 
 		block->aset = set;
 		block->freeptr = block->endptr = ((char *) block) + blksize;
@@ -943,6 +956,7 @@ AllocSetAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_allocated_bytes_increase(blksize, PG_ALLOC_ASET);
 
 		block->aset = set;
 		block->freeptr = ((char *) block) + ALLOC_BLOCKHDRSZ;
@@ -1040,6 +1054,7 @@ AllocSetFree(void *pointer)
 			block->next->prev = block->prev;
 
 		set->header.mem_allocated -= block->endptr - ((char *) block);
+		pgstat_report_allocated_bytes_decrease(block->endptr - ((char *) block), PG_ALLOC_ASET);
 
 #ifdef CLOBBER_FREED_MEMORY
 		wipe_mem(block, block->freeptr - ((char *) block));
@@ -1170,7 +1185,9 @@ AllocSetRealloc(void *pointer, Size size)
 
 		/* updated separately, not to underflow when (oldblksize > blksize) */
 		set->header.mem_allocated -= oldblksize;
+		pgstat_report_allocated_bytes_decrease(oldblksize, PG_ALLOC_ASET);
 		set->header.mem_allocated += blksize;
+		pgstat_report_allocated_bytes_increase(blksize, PG_ALLOC_ASET);
 
 		block->freeptr = block->endptr = ((char *) block) + blksize;
 
diff --git a/src/backend/utils/mmgr/generation.c b/src/backend/utils/mmgr/generation.c
index 92401ccf738..0ed54571497 100644
--- a/src/backend/utils/mmgr/generation.c
+++ b/src/backend/utils/mmgr/generation.c
@@ -37,6 +37,7 @@
 
 #include "lib/ilist.h"
 #include "port/pg_bitutils.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -263,6 +264,7 @@ GenerationContextCreate(MemoryContext parent,
 						name);
 
 	((MemoryContext) set)->mem_allocated = firstBlockSize;
+	pgstat_report_allocated_bytes_increase(firstBlockSize, PG_ALLOC_GENERATION);
 
 	return (MemoryContext) set;
 }
@@ -279,6 +281,7 @@ GenerationReset(MemoryContext context)
 {
 	GenerationContext *set = (GenerationContext *) context;
 	dlist_mutable_iter miter;
+	uint64		deallocation = 0;
 
 	Assert(GenerationIsValid(set));
 
@@ -301,9 +304,14 @@ GenerationReset(MemoryContext context)
 		if (IsKeeperBlock(set, block))
 			GenerationBlockMarkEmpty(block);
 		else
+		{
+			deallocation += block->blksize;
 			GenerationBlockFree(set, block);
+		}
 	}
 
+	pgstat_report_allocated_bytes_decrease(deallocation, PG_ALLOC_GENERATION);
+
 	/* set it so new allocations to make use of the keeper block */
 	set->block = KeeperBlock(set);
 
@@ -324,6 +332,9 @@ GenerationDelete(MemoryContext context)
 {
 	/* Reset to release all releasable GenerationBlocks */
 	GenerationReset(context);
+
+	pgstat_report_allocated_bytes_decrease(context->mem_allocated, PG_ALLOC_GENERATION);
+
 	/* And free the context header and keeper block */
 	free(context);
 }
@@ -370,6 +381,7 @@ GenerationAlloc(MemoryContext context, Size size)
 			return NULL;
 
 		context->mem_allocated += blksize;
+		pgstat_report_allocated_bytes_increase(blksize, PG_ALLOC_GENERATION);
 
 		/* block with a single (used) chunk */
 		block->context = set;
@@ -473,6 +485,7 @@ GenerationAlloc(MemoryContext context, Size size)
 				return NULL;
 
 			context->mem_allocated += blksize;
+			pgstat_report_allocated_bytes_increase(blksize, PG_ALLOC_GENERATION);
 
 			/* initialize the new block */
 			GenerationBlockInit(set, block, blksize);
@@ -725,6 +738,8 @@ GenerationFree(void *pointer)
 	dlist_delete(&block->node);
 
 	set->header.mem_allocated -= block->blksize;
+	pgstat_report_allocated_bytes_decrease(block->blksize, PG_ALLOC_GENERATION);
+
 	free(block);
 }
 
diff --git a/src/backend/utils/mmgr/slab.c b/src/backend/utils/mmgr/slab.c
index 40c1d401c4c..c99ff532af2 100644
--- a/src/backend/utils/mmgr/slab.c
+++ b/src/backend/utils/mmgr/slab.c
@@ -69,6 +69,7 @@
 #include "postgres.h"
 
 #include "lib/ilist.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -417,6 +418,13 @@ SlabContextCreate(MemoryContext parent,
 						parent,
 						name);
 
+	/*
+	 * If SlabContextCreate is updated to add context header size to
+	 * context->mem_allocated, then update here and SlabDelete appropriately
+	 */
+	pgstat_report_allocated_bytes_increase(Slab_CONTEXT_HDRSZ(slab->chunksPerBlock),
+										   PG_ALLOC_SLAB);
+
 	return (MemoryContext) slab;
 }
 
@@ -433,6 +441,7 @@ SlabReset(MemoryContext context)
 	SlabContext *slab = (SlabContext *) context;
 	dlist_mutable_iter miter;
 	int			i;
+	uint64		deallocation = 0;
 
 	Assert(SlabIsValid(slab));
 
@@ -453,6 +462,7 @@ SlabReset(MemoryContext context)
 #endif
 		free(block);
 		context->mem_allocated -= slab->blockSize;
+		deallocation += slab->blockSize;
 	}
 
 	/* walk over blocklist and free the blocks */
@@ -469,9 +479,11 @@ SlabReset(MemoryContext context)
 #endif
 			free(block);
 			context->mem_allocated -= slab->blockSize;
+			deallocation += slab->blockSize;
 		}
 	}
 
+	pgstat_report_allocated_bytes_decrease(deallocation, PG_ALLOC_SLAB);
 	slab->curBlocklistIndex = 0;
 
 	Assert(context->mem_allocated == 0);
@@ -486,6 +498,14 @@ SlabDelete(MemoryContext context)
 {
 	/* Reset to release all the SlabBlocks */
 	SlabReset(context);
+
+	/*
+	 * Until context header allocation is included in context->mem_allocated,
+	 * cast to slab and decrement the header allocation
+	 */
+	pgstat_report_allocated_bytes_decrease(Slab_CONTEXT_HDRSZ(((SlabContext *) context)->chunksPerBlock),
+										   PG_ALLOC_SLAB);
+
 	/* And free the context header */
 	free(context);
 }
@@ -550,6 +570,7 @@ SlabAlloc(MemoryContext context, Size size)
 
 			block->slab = slab;
 			context->mem_allocated += slab->blockSize;
+			pgstat_report_allocated_bytes_increase(slab->blockSize, PG_ALLOC_SLAB);
 
 			/* use the first chunk in the new block */
 			chunk = SlabBlockGetChunk(slab, block, 0);
@@ -744,6 +765,7 @@ SlabFree(void *pointer)
 #endif
 			free(block);
 			slab->header.mem_allocated -= slab->blockSize;
+			pgstat_report_allocated_bytes_decrease(slab->blockSize, PG_ALLOC_SLAB);
 		}
 
 		/*
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index b8b26c263db..fe0549c43d9 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -5435,6 +5435,23 @@
   proname => 'pg_stat_get_backend_idset', prorows => '100', proretset => 't',
   provolatile => 's', proparallel => 'r', prorettype => 'int4',
   proargtypes => '', prosrc => 'pg_stat_get_backend_idset' },
+{ oid => '9890',
+  descr => 'statistics: memory allocation information for backends',
+  proname => 'pg_stat_get_memory_allocation', prorows => '100', proisstrict => 'f',
+  proretset => 't', provolatile => 's', proparallel => 'r',
+  prorettype => 'record', proargtypes => 'int4',
+  proallargtypes => '{int4,oid,int4,int8,int8,int8,int8,int8}',
+  proargmodes => '{i,o,o,o,o,o,o,o}',
+  proargnames => '{pid,datid,pid,allocated_bytes,aset_allocated_bytes,dsm_allocated_bytes,generation_allocated_bytes,slab_allocated_bytes}',
+  prosrc => 'pg_stat_get_memory_allocation' },
+{ oid => '9891',
+  descr => 'statistics: global memory allocation information',
+  proname => 'pg_stat_get_global_memory_allocation', proisstrict => 'f',
+  provolatile => 's', proparallel => 'r', prorettype => 'record',
+  proargtypes => '', proallargtypes => '{oid,int8}',
+  proargmodes => '{o,o}',
+  proargnames => '{datid,global_dsm_allocated_bytes}',
+  prosrc =>'pg_stat_get_global_memory_allocation' },
 { oid => '2022',
   descr => 'statistics: information about currently active backends',
   proname => 'pg_stat_get_activity', prorows => '100', proisstrict => 'f',
diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h
index e87fd25d643..26b17d66477 100644
--- a/src/include/storage/proc.h
+++ b/src/include/storage/proc.h
@@ -404,6 +404,8 @@ typedef struct PROC_HDR
 	int			spins_per_delay;
 	/* Buffer id of the buffer that Startup process waits for pin on, or -1 */
 	int			startupBufferPinWaitBufId;
+	/* Global dsm allocations */
+	pg_atomic_uint64 global_dsm_allocation;
 } PROC_HDR;
 
 extern PGDLLIMPORT PROC_HDR *ProcGlobal;
diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h
index 75fc18c4327..c2c8ba7214d 100644
--- a/src/include/utils/backend_status.h
+++ b/src/include/utils/backend_status.h
@@ -10,6 +10,7 @@
 #ifndef BACKEND_STATUS_H
 #define BACKEND_STATUS_H
 
+#include "common/int.h"
 #include "datatype/timestamp.h"
 #include "libpq/pqcomm.h"
 #include "miscadmin.h"			/* for BackendType */
@@ -32,6 +33,14 @@ typedef enum BackendState
 	STATE_DISABLED,
 } BackendState;
 
+/* Enum helper for reporting memory allocator type */
+enum pg_allocator_type
+{
+	PG_ALLOC_ASET = 1,
+	PG_ALLOC_DSM,
+	PG_ALLOC_GENERATION,
+	PG_ALLOC_SLAB
+};
 
 /* ----------
  * Shared-memory data structures
@@ -170,6 +179,15 @@ typedef struct PgBackendStatus
 
 	/* query identifier, optionally computed using post_parse_analyze_hook */
 	uint64		st_query_id;
+
+	/* Current memory allocated to this backend */
+	uint64		allocated_bytes;
+
+	/* Current memory allocated to this backend by type */
+	uint64		aset_allocated_bytes;
+	uint64		dsm_allocated_bytes;
+	uint64		generation_allocated_bytes;
+	uint64		slab_allocated_bytes;
 } PgBackendStatus;
 
 
@@ -294,6 +312,11 @@ extern PGDLLIMPORT int pgstat_track_activity_query_size;
  * ----------
  */
 extern PGDLLIMPORT PgBackendStatus *MyBEEntry;
+extern PGDLLIMPORT uint64 *my_allocated_bytes;
+extern PGDLLIMPORT uint64 *my_aset_allocated_bytes;
+extern PGDLLIMPORT uint64 *my_dsm_allocated_bytes;
+extern PGDLLIMPORT uint64 *my_generation_allocated_bytes;
+extern PGDLLIMPORT uint64 *my_slab_allocated_bytes;
 
 
 /* ----------
@@ -325,7 +348,12 @@ extern const char *pgstat_get_backend_current_activity(int pid, bool checkUser);
 extern const char *pgstat_get_crashed_backend_activity(int pid, char *buffer,
 													   int buflen);
 extern uint64 pgstat_get_my_query_id(void);
-
+extern void pgstat_set_allocated_bytes_storage(uint64 *allocated_bytes,
+											   uint64 *aset_allocated_bytes,
+											   uint64 *dsm_allocated_bytes,
+											   uint64 *generation_allocated_bytes,
+											   uint64 *slab_allocated_bytes);
+extern void pgstat_reset_allocated_bytes_storage(void);
 
 /* ----------
  * Support functions for the SQL-callable functions to
@@ -338,5 +366,119 @@ extern LocalPgBackendStatus *pgstat_get_local_beentry_by_backend_id(BackendId be
 extern LocalPgBackendStatus *pgstat_get_local_beentry_by_index(int idx);
 extern char *pgstat_clip_activity(const char *raw_activity);
 
+/* ----------
+ * pgstat_report_allocated_bytes_decrease() -
+ *  Called to report decrease in memory allocated for this backend.
+ *
+ * my_{*_}allocated_bytes initially points to local memory, making it safe to
+ * call this before pgstats has been initialized.
+ * ----------
+ */
+static inline void
+pgstat_report_allocated_bytes_decrease(int64 proc_allocated_bytes,
+									   int pg_allocator_type)
+{
+	uint64		temp;
+
+	/* Avoid allocated_bytes unsigned integer overflow on decrease */
+	if (pg_sub_u64_overflow(*my_allocated_bytes, proc_allocated_bytes, &temp))
+	{
+		/* On overflow, set allocated bytes and allocator type bytes to zero */
+		*my_allocated_bytes = 0;
+		*my_aset_allocated_bytes = 0;
+		*my_dsm_allocated_bytes = 0;
+		*my_generation_allocated_bytes = 0;
+		*my_slab_allocated_bytes = 0;
+	}
+	else
+	{
+		/* decrease allocation */
+		*my_allocated_bytes -= proc_allocated_bytes;
+
+		/* Decrease allocator type allocated bytes. */
+		switch (pg_allocator_type)
+		{
+			case PG_ALLOC_ASET:
+				*my_aset_allocated_bytes -= proc_allocated_bytes;
+				break;
+			case PG_ALLOC_DSM:
+
+				/*
+				 * Some dsm allocations live beyond process exit. These are
+				 * accounted for in a global counter in
+				 * pgstat_reset_allocated_bytes_storage at process exit.
+				 */
+				*my_dsm_allocated_bytes -= proc_allocated_bytes;
+				break;
+			case PG_ALLOC_GENERATION:
+				*my_generation_allocated_bytes -= proc_allocated_bytes;
+				break;
+			case PG_ALLOC_SLAB:
+				*my_slab_allocated_bytes -= proc_allocated_bytes;
+				break;
+		}
+	}
+
+	return;
+}
+
+/* ----------
+ * pgstat_report_allocated_bytes_increase() -
+ *  Called to report increase in memory allocated for this backend.
+ *
+ * my_allocated_bytes initially points to local memory, making it safe to call
+ * this before pgstats has been initialized.
+ * ----------
+ */
+static inline void
+pgstat_report_allocated_bytes_increase(int64 proc_allocated_bytes,
+									   int pg_allocator_type)
+{
+	*my_allocated_bytes += proc_allocated_bytes;
+
+	/* Increase allocator type allocated bytes */
+	switch (pg_allocator_type)
+	{
+		case PG_ALLOC_ASET:
+			*my_aset_allocated_bytes += proc_allocated_bytes;
+			break;
+		case PG_ALLOC_DSM:
+
+			/*
+			 * Some dsm allocations live beyond process exit. These are
+			 * accounted for in a global counter in
+			 * pgstat_reset_allocated_bytes_storage at process exit.
+			 */
+			*my_dsm_allocated_bytes += proc_allocated_bytes;
+			break;
+		case PG_ALLOC_GENERATION:
+			*my_generation_allocated_bytes += proc_allocated_bytes;
+			break;
+		case PG_ALLOC_SLAB:
+			*my_slab_allocated_bytes += proc_allocated_bytes;
+			break;
+	}
+
+	return;
+}
+
+/* ---------
+ * pgstat_init_allocated_bytes() -
+ *
+ * Called to initialize allocated bytes variables after fork and to
+ * avoid double counting allocations.
+ * ---------
+ */
+static inline void
+pgstat_init_allocated_bytes(void)
+{
+	*my_allocated_bytes = 0;
+	*my_aset_allocated_bytes = 0;
+	*my_dsm_allocated_bytes = 0;
+	*my_generation_allocated_bytes = 0;
+	*my_slab_allocated_bytes = 0;
+
+	return;
+}
 
 #endif							/* BACKEND_STATUS_H */
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index 05070393b99..7d412b26801 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1872,6 +1872,24 @@ pg_stat_database_conflicts| SELECT oid AS datid,
     pg_stat_get_db_conflict_startup_deadlock(oid) AS confl_deadlock,
     pg_stat_get_db_conflict_logicalslot(oid) AS confl_active_logicalslot
    FROM pg_database d;
+pg_stat_global_memory_allocation| WITH sums AS (
+         SELECT sum(pg_stat_memory_allocation.aset_allocated_bytes) AS total_aset_allocated_bytes,
+            sum(pg_stat_memory_allocation.dsm_allocated_bytes) AS total_dsm_allocated_bytes,
+            sum(pg_stat_memory_allocation.generation_allocated_bytes) AS total_generation_allocated_bytes,
+            sum(pg_stat_memory_allocation.slab_allocated_bytes) AS total_slab_allocated_bytes
+           FROM pg_stat_memory_allocation
+        )
+ SELECT s.datid,
+    current_setting('shared_memory_size'::text, true) AS shared_memory_size,
+    (current_setting('shared_memory_size_in_huge_pages'::text, true))::integer AS shared_memory_size_in_huge_pages,
+    s.global_dsm_allocated_bytes,
+    sums.total_aset_allocated_bytes,
+    sums.total_dsm_allocated_bytes,
+    sums.total_generation_allocated_bytes,
+    sums.total_slab_allocated_bytes
+   FROM sums,
+    (pg_stat_get_global_memory_allocation() s(datid, global_dsm_allocated_bytes)
+     LEFT JOIN pg_database d ON ((s.datid = d.oid)));
 pg_stat_gssapi| SELECT pid,
     gss_auth AS gss_authenticated,
     gss_princ AS principal,
@@ -1898,6 +1916,15 @@ pg_stat_io| SELECT backend_type,
     fsync_time,
     stats_reset
    FROM pg_stat_get_io() b(backend_type, object, context, reads, read_time, writes, write_time, writebacks, writeback_time, extends, extend_time, op_bytes, hits, evictions, reuses, fsyncs, fsync_time, stats_reset);
+pg_stat_memory_allocation| SELECT s.datid,
+    s.pid,
+    s.allocated_bytes,
+    s.aset_allocated_bytes,
+    s.dsm_allocated_bytes,
+    s.generation_allocated_bytes,
+    s.slab_allocated_bytes
+   FROM (pg_stat_get_memory_allocation(NULL::integer) s(datid, pid, allocated_bytes, aset_allocated_bytes, dsm_allocated_bytes, generation_allocated_bytes, slab_allocated_bytes)
+     LEFT JOIN pg_database d ON ((s.datid = d.oid)));
 pg_stat_progress_analyze| SELECT s.pid,
     s.datid,
     d.datname,
diff --git a/src/test/regress/expected/stats.out b/src/test/regress/expected/stats.out
index 346e10a3d2b..92326a3e697 100644
--- a/src/test/regress/expected/stats.out
+++ b/src/test/regress/expected/stats.out
@@ -1646,4 +1646,40 @@ SELECT COUNT(*) FROM brin_hot_3 WHERE a = 2;
 
 DROP TABLE brin_hot_3;
 SET enable_seqscan = on;
+-- ensure that allocated_bytes exist for backends
+SELECT
+    allocated_bytes > 0 AS result
+FROM
+    pg_stat_activity ps
+    JOIN pg_stat_memory_allocation pa ON (pa.pid = ps.pid)
+WHERE
+    backend_type IN ('checkpointer', 'background writer', 'walwriter', 'autovacuum launcher');
+ result 
+--------
+ t
+ t
+ t
+ t
+(4 rows)
+
+-- ensure that pg_stat_global_memory_allocation view exists
+SELECT
+    datid > 0, pg_size_bytes(shared_memory_size) >= 0, shared_memory_size_in_huge_pages >= -1, global_dsm_allocated_bytes >= 0
+FROM
+    pg_stat_global_memory_allocation;
+ ?column? | ?column? | ?column? | ?column? 
+----------+----------+----------+----------
+ t        | t        | t        | t
+(1 row)
+
+-- ensure that pg_stat_memory_allocation view exists
+SELECT
+    pid > 0, allocated_bytes >= 0, aset_allocated_bytes >= 0, dsm_allocated_bytes >= 0, generation_allocated_bytes >= 0, slab_allocated_bytes >= 0
+FROM
+    pg_stat_memory_allocation limit 1;
+ ?column? | ?column? | ?column? | ?column? | ?column? | ?column? 
+----------+----------+----------+----------+----------+----------
+ t        | t        | t        | t        | t        | t
+(1 row)
+
 -- End of Stats Test
diff --git a/src/test/regress/sql/stats.sql b/src/test/regress/sql/stats.sql
index e3b4ca96e89..01134187bb8 100644
--- a/src/test/regress/sql/stats.sql
+++ b/src/test/regress/sql/stats.sql
@@ -849,4 +849,24 @@ DROP TABLE brin_hot_3;
 
 SET enable_seqscan = on;
 
+-- ensure that allocated_bytes exist for backends
+SELECT
+    allocated_bytes > 0 AS result
+FROM
+    pg_stat_activity ps
+    JOIN pg_stat_memory_allocation pa ON (pa.pid = ps.pid)
+WHERE
+    backend_type IN ('checkpointer', 'background writer', 'walwriter', 'autovacuum launcher');
+
+-- ensure that pg_stat_global_memory_allocation view exists
+SELECT
+    datid > 0, pg_size_bytes(shared_memory_size) >= 0, shared_memory_size_in_huge_pages >= -1, global_dsm_allocated_bytes >= 0
+FROM
+    pg_stat_global_memory_allocation;
+
+-- ensure that pg_stat_memory_allocation view exists
+SELECT
+    pid > 0, allocated_bytes >= 0, aset_allocated_bytes >= 0, dsm_allocated_bytes >= 0, generation_allocated_bytes >= 0, slab_allocated_bytes >= 0
+FROM
+    pg_stat_memory_allocation limit 1;
 -- End of Stats Test
-- 
2.41.0

v20231226-0002-fixup-pgstat_get_local_beentry_by_index.patchtext/x-patch; charset=UTF-8; name=v20231226-0002-fixup-pgstat_get_local_beentry_by_index.patchDownload
From 468288c2dd154ebcb90cb3a93bee36622169be18 Mon Sep 17 00:00:00 2001
From: Tomas Vondra <tomas@2ndquadrant.com>
Date: Tue, 26 Dec 2023 18:05:02 +0100
Subject: [PATCH v20231226 2/3] fixup: pgstat_get_local_beentry_by_index

---
 src/backend/utils/adt/pgstatfuncs.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index b372ee691ba..9b52cc5091f 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -2041,7 +2041,7 @@ pg_stat_get_memory_allocation(PG_FUNCTION_ARGS)
 		PgBackendStatus *beentry;
 
 		/* Get the next one in the list */
-		local_beentry = pgstat_fetch_stat_local_beentry(curr_backend);
+		local_beentry = pgstat_get_local_beentry_by_index(curr_backend);
 		beentry = &local_beentry->backendStatus;
 
 		/* If looking for specific PID, ignore all the others */
-- 
2.41.0

v20231226-0003-Add-the-ability-to-limit-the-amount-of-mem.patchtext/x-patch; charset=UTF-8; name=v20231226-0003-Add-the-ability-to-limit-the-amount-of-mem.patchDownload
From d45b026dfcaa5d891f83af43645fd92519d9841a Mon Sep 17 00:00:00 2001
From: Tomas Vondra <tomas@2ndquadrant.com>
Date: Tue, 26 Dec 2023 17:55:23 +0100
Subject: [PATCH v20231226 3/3] Add the ability to limit the amount of memory
 that can be  allocated to backends.

This builds on the work that adds backend memory allocated tracking.

Add GUC variable max_total_backend_memory.

Specifies a limit to the amount of memory (in MB) that may be allocated to
backends in total (i.e. this is not a per user or per backend limit). If unset,
or set to 0 it is disabled. It is intended as a resource to help avoid the OOM
killer on LINUX and manage resources in general. A backend request that would
exhaust max_total_backend_memory memory will be denied with an out of memory
error causing that backend's current query/transaction to fail.  Further
requests will not be allocated until dropping below the limit. Keep this in
mind when setting this value. Due to the dynamic nature of memory allocations,
this limit is not exact. This limit does not affect auxiliary backend
processes. Backend memory allocations are displayed in the
pg_stat_memory_allocation and pg_stat_global_memory_allocation views.
---
 doc/src/sgml/config.sgml                      |  30 ++++
 doc/src/sgml/monitoring.sgml                  |  38 ++++-
 src/backend/catalog/system_views.sql          |   2 +
 src/backend/port/sysv_shmem.c                 |   9 ++
 src/backend/postmaster/postmaster.c           |   5 +
 src/backend/storage/ipc/dsm_impl.c            |  18 +++
 src/backend/storage/lmgr/proc.c               |  45 ++++++
 src/backend/utils/activity/backend_status.c   | 147 ++++++++++++++++++
 src/backend/utils/adt/pgstatfuncs.c           |  16 +-
 src/backend/utils/hash/dynahash.c             |   3 +-
 src/backend/utils/init/miscinit.c             |   8 +
 src/backend/utils/misc/guc_tables.c           |  11 ++
 src/backend/utils/misc/postgresql.conf.sample |   3 +
 src/backend/utils/mmgr/aset.c                 |  33 ++++
 src/backend/utils/mmgr/generation.c           |  16 ++
 src/backend/utils/mmgr/slab.c                 |  15 +-
 src/include/catalog/pg_proc.dat               |   6 +-
 src/include/storage/proc.h                    |   7 +
 src/include/utils/backend_status.h            | 102 +++++++++++-
 src/test/regress/expected/rules.out           |   4 +-
 20 files changed, 498 insertions(+), 20 deletions(-)

diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index b5624ca8847..6b0e7b753d8 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -2167,6 +2167,36 @@ include_dir 'conf.d'
       </listitem>
      </varlistentry>
 
+     <varlistentry id="guc-max-total-backend-memory" xreflabel="max_total_backend_memory">
+      <term><varname>max_total_backend_memory</varname> (<type>integer</type>)
+      <indexterm>
+       <primary><varname>max_total_backend_memory</varname> configuration parameter</primary>
+      </indexterm>
+      </term>
+      <listitem>
+       <para>
+        Specifies a limit to the amount of memory (MB) that may be allocated to
+        backends in total (i.e. this is not a per user or per backend limit).
+        If unset, or set to 0 it is disabled.  At databse startup
+        max_total_backend_memory is reduced by shared_memory_size_mb
+        (includes shared buffers and other memory required for initialization).
+        Each backend process is intialized with a 1MB local allowance which
+        also reduces total_bkend_mem_bytes_available. Keep this in mind when
+        setting this value. A backend request that would exhaust the limit will
+        be denied with an out of memory error causing that backend's current
+        query/transaction to fail. Further requests will not be allocated until
+        dropping below the limit.  This limit does not affect auxiliary backend
+        processes
+        <xref linkend="glossary-auxiliary-proc"/> or the postmaster process.
+        Backend memory allocations (<varname>allocated_bytes</varname>) are
+        displayed in the
+        <link linkend="monitoring-pg-stat-memory-allocation-view"><structname>pg_stat_memory_allocation</structname></link>
+        view.  Due to the dynamic nature of memory allocations, this limit is
+        not exact.
+       </para>
+      </listitem>
+     </varlistentry>
+
      </variablelist>
      </sect2>
 
diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 99f5acf07f4..01e5d5ef85b 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -4623,10 +4623,7 @@ description | Waiting for a newly initialized WAL file to reach durable storage
       </para>
      <para>
       Memory currently allocated to this backend in bytes. This is the balance
-      of bytes allocated and freed by this backend. Dynamic shared memory
-      allocations are included only in the value displayed for the backend that
-      created them, they are not included in the value for backends that are
-      attached to them to avoid double counting.
+      of bytes allocated and freed by this backend.
      </para></entry>
      </row>
 
@@ -4743,6 +4740,39 @@ description | Waiting for a newly initialized WAL file to reach durable storage
      </para></entry>
      </row>
 
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>max_total_backend_memory_bytes</structfield> <type>bigint</type>
+      </para>
+     <para>
+      Reports the user defined backend maximum allowed shared memory in bytes.
+      0 if disabled or not set. See
+      <xref linkend="guc-max-total-backend-memory"/>.
+     </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>total_bkend_mem_bytes_available</structfield> <type>bigint</type>
+      </para>
+     <para>
+      Tracks max_total_backend_memory (in bytes) available for allocation. At
+      database startup, total_bkend_mem_bytes_available is reduced by the
+      byte equivalent of shared_memory_size_mb. Each backend process is
+      intialized with a 1MB local allowance which also reduces
+      total_bkend_mem_bytes_available. A process's allocation requests reduce
+      it's local allowance. If a process's allocation request exceeds it's
+      remaining allowance, an attempt is made to refill the local allowance
+      from total_bkend_mem_bytes_available. If the refill request fails, then
+      the requesting process will fail with an out of memory error resulting
+      in the cancellation of that process's active query/transaction.  The
+      default refill allocation quantity is 1MB.  If a request is greater than
+      1MB, an attempt will be made to allocate the full amount. If
+      max_total_backend_memory is disabled, this will be -1.
+      <xref linkend="guc-max-total-backend-memory"/>.
+     </para></entry>
+     </row>
+
      <row>
       <entry role="catalog_table_entry"><para role="column_definition">
        <structfield>global_dsm_allocated_bytes</structfield> <type>bigint</type>
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index fd7fcaf59e3..c665985aca8 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -1396,6 +1396,8 @@ SELECT
         S.datid AS datid,
         current_setting('shared_memory_size', true) as shared_memory_size,
         (current_setting('shared_memory_size_in_huge_pages', true))::integer as shared_memory_size_in_huge_pages,
+        pg_size_bytes(current_setting('max_total_backend_memory', true)) as max_total_backend_memory_bytes,
+        S.total_bkend_mem_bytes_available,
         S.global_dsm_allocated_bytes,
         sums.total_aset_allocated_bytes,
         sums.total_dsm_allocated_bytes,
diff --git a/src/backend/port/sysv_shmem.c b/src/backend/port/sysv_shmem.c
index 2de280ecb6f..af87c1dd3b3 100644
--- a/src/backend/port/sysv_shmem.c
+++ b/src/backend/port/sysv_shmem.c
@@ -34,6 +34,7 @@
 #include "storage/fd.h"
 #include "storage/ipc.h"
 #include "storage/pg_shmem.h"
+#include "utils/backend_status.h"
 #include "utils/guc_hooks.h"
 #include "utils/pidfile.h"
 
@@ -917,6 +918,14 @@ PGSharedMemoryReAttach(void)
 	dsm_set_control_handle(hdr->dsm_control);
 
 	UsedShmemSegAddr = hdr;		/* probably redundant */
+
+	/*
+	 * Init allocated bytes to avoid double counting parent allocation for
+	 * fork/exec processes. Forked processes perform this action in
+	 * InitPostmasterChild. For EXEC_BACKEND processes we have to wait for
+	 * shared memory to be reattached.
+	 */
+	pgstat_init_allocated_bytes();
 }
 
 /*
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index b163e89cbb5..a658bc0d131 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -545,6 +545,7 @@ typedef struct
 #endif
 	char		my_exec_path[MAXPGPATH];
 	char		pkglib_path[MAXPGPATH];
+	int			max_total_bkend_mem;
 } BackendParameters;
 
 static void read_backend_variables(char *id, Port **port, BackgroundWorker **worker);
@@ -6130,6 +6131,8 @@ save_backend_variables(BackendParameters *param, Port *port, BackgroundWorker *w
 
 	strlcpy(param->pkglib_path, pkglib_path, MAXPGPATH);
 
+	param->max_total_bkend_mem = max_total_bkend_mem;
+
 	return true;
 }
 
@@ -6372,6 +6375,8 @@ restore_backend_variables(BackendParameters *param, Port **port, BackgroundWorke
 
 	strlcpy(pkglib_path, param->pkglib_path, MAXPGPATH);
 
+	max_total_bkend_mem = param->max_total_bkend_mem;
+
 	/*
 	 * We need to restore fd.c's counts of externally-opened FDs; to avoid
 	 * confusion, be sure to do this after restoring max_safe_fds.  (Note:
diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c
index a9e0987747b..2c74580cec0 100644
--- a/src/backend/storage/ipc/dsm_impl.c
+++ b/src/backend/storage/ipc/dsm_impl.c
@@ -254,6 +254,16 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 		return true;
 	}
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+	{
+		ereport(elevel,
+				(errcode_for_dynamic_shared_memory(),
+				 errmsg("out of memory for segment \"%s\" - exceeds max_total_backend_memory: %m",
+						name)));
+		return false;
+	}
+
 	/*
 	 * Create new segment or open an existing one for attach.
 	 *
@@ -523,6 +533,10 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 		int			flags = IPCProtection;
 		size_t		segsize;
 
+		/* Do not exceed maximum allowed memory allocation */
+		if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+			return false;
+
 		/*
 		 * Allocate the memory BEFORE acquiring the resource, so that we don't
 		 * leak the resource if memory allocation fails.
@@ -717,6 +731,10 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 		return true;
 	}
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+		return false;
+
 	/* Create new segment or open an existing one for attach. */
 	if (op == DSM_OP_CREATE)
 	{
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index 81304a569c0..51a6c312284 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -51,6 +51,7 @@
 #include "storage/procsignal.h"
 #include "storage/spin.h"
 #include "storage/standby.h"
+#include "utils/guc.h"
 #include "utils/timeout.h"
 #include "utils/timestamp.h"
 
@@ -182,6 +183,50 @@ InitProcGlobal(void)
 	pg_atomic_init_u32(&ProcGlobal->clogGroupFirst, INVALID_PGPROCNO);
 	pg_atomic_init_u64(&ProcGlobal->global_dsm_allocation, 0);
 
+	/* Setup backend memory limiting if configured */
+	if (max_total_bkend_mem > 0)
+	{
+		/*
+		 * Convert max_total_bkend_mem to bytes, account for
+		 * shared_memory_size, and initialize total_bkend_mem_bytes.
+		 */
+		int			result = 0;
+
+		/* Get integer value of shared_memory_size */
+		if (parse_int(GetConfigOption("shared_memory_size", true, false), &result, 0, NULL))
+		{
+			/*
+			 * Error on startup if backend memory limit is less than shared
+			 * memory size. Warn on startup if backend memory available is
+			 * less than arbitrarily picked value of 100MB.
+			 */
+
+			if (max_total_bkend_mem - result <= 0)
+			{
+				ereport(ERROR,
+						errmsg("configured max_total_backend_memory %dMB is <= shared_memory_size %dMB",
+							   max_total_bkend_mem, result),
+						errhint("Disable or increase the configuration parameter \"max_total_backend_memory\"."));
+			}
+			else if (max_total_bkend_mem - result <= 100)
+			{
+				ereport(WARNING,
+						errmsg("max_total_backend_memory %dMB - shared_memory_size %dMB is <= 100MB",
+							   max_total_bkend_mem, result),
+						errhint("Consider increasing the configuration parameter \"max_total_backend_memory\"."));
+			}
+
+			/*
+			 * Account for shared memory size and initialize
+			 * total_bkend_mem_bytes.
+			 */
+			pg_atomic_init_u64(&ProcGlobal->total_bkend_mem_bytes,
+							   (uint64) max_total_bkend_mem * 1024 * 1024 - (uint64) result * 1024 * 1024);
+		}
+		else
+			ereport(ERROR, errmsg("max_total_backend_memory initialization is unable to parse shared_memory_size"));
+	}
+
 	/*
 	 * Create and initialize all the PGPROC structures we'll need.  There are
 	 * five separate consumers: (1) normal backends, (2) autovacuum workers
diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c
index 838a7337933..a3d610a2461 100644
--- a/src/backend/utils/activity/backend_status.c
+++ b/src/backend/utils/activity/backend_status.c
@@ -45,6 +45,12 @@
 bool		pgstat_track_activities = false;
 int			pgstat_track_activity_query_size = 1024;
 
+/*
+ * Max backend memory allocation allowed (MB). 0 = disabled.
+ * Centralized bucket ProcGlobal->max_total_bkend_mem is initialized
+ * as a byte representation of this value in InitProcGlobal().
+ */
+int			max_total_bkend_mem = 0;
 
 /* exposed so that backend_progress.c can access it */
 PgBackendStatus *MyBEEntry = NULL;
@@ -68,6 +74,31 @@ uint64	   *my_generation_allocated_bytes = &local_my_generation_allocated_bytes;
 uint64		local_my_slab_allocated_bytes = 0;
 uint64	   *my_slab_allocated_bytes = &local_my_slab_allocated_bytes;
 
+/*
+ * Define initial allocation allowance for a backend.
+ *
+ * NOTE: initial_allocation_allowance && allocation_allowance_refill_qty
+ * may be candidates for future GUC variables. Arbitrary 1MB selected initially.
+ */
+uint64		initial_allocation_allowance = 1024 * 1024;
+uint64		allocation_allowance_refill_qty = 1024 * 1024;
+
+/*
+ * Local counter to manage shared memory allocations. At backend startup, set to
+ * initial_allocation_allowance via pgstat_init_allocated_bytes(). Decrease as
+ * memory is malloc'd. When exhausted, atomically refill if available from
+ * ProcGlobal->max_total_bkend_mem via exceeds_max_total_bkend_mem().
+ */
+uint64		allocation_allowance = 0;
+
+/*
+ * Local counter of free'd shared memory. Return to global
+ * max_total_bkend_mem when return threshold is met. Arbitrary 1MB bytes
+ * selected initially.
+ */
+uint64		allocation_return = 0;
+uint64		allocation_return_threshold = 1024 * 1024;
+
 static PgBackendStatus *BackendStatusArray = NULL;
 static char *BackendAppnameBuffer = NULL;
 static char *BackendClientHostnameBuffer = NULL;
@@ -1291,6 +1322,8 @@ pgstat_set_allocated_bytes_storage(uint64 *allocated_bytes,
 
 	my_slab_allocated_bytes = slab_allocated_bytes;
 	*slab_allocated_bytes = local_my_slab_allocated_bytes;
+
+	return;
 }
 
 /*
@@ -1314,6 +1347,23 @@ pgstat_reset_allocated_bytes_storage(void)
 								*my_dsm_allocated_bytes);
 	}
 
+	/*
+	 * When limiting maximum backend memory, return this backend's memory
+	 * allocations to global.
+	 */
+	if (max_total_bkend_mem)
+	{
+		volatile PROC_HDR *procglobal = ProcGlobal;
+
+		pg_atomic_add_fetch_u64(&procglobal->total_bkend_mem_bytes,
+								*my_allocated_bytes + allocation_allowance +
+								allocation_return);
+
+		/* Reset memory allocation variables */
+		allocation_allowance = 0;
+		allocation_return = 0;
+	}
+
 	/* Reset memory allocation variables */
 	*my_allocated_bytes = local_my_allocated_bytes = 0;
 	*my_aset_allocated_bytes = local_my_aset_allocated_bytes = 0;
@@ -1327,4 +1377,101 @@ pgstat_reset_allocated_bytes_storage(void)
 	my_dsm_allocated_bytes = &local_my_dsm_allocated_bytes;
 	my_generation_allocated_bytes = &local_my_generation_allocated_bytes;
 	my_slab_allocated_bytes = &local_my_slab_allocated_bytes;
+
+	return;
+}
+
+/*
+ * Determine if allocation request will exceed max backend memory allowed.
+ * Do not apply to auxiliary processes.
+ * Refill allocation request bucket when needed/possible.
+ */
+bool
+exceeds_max_total_bkend_mem(uint64 allocation_request)
+{
+	bool		result = false;
+
+	/*
+	 * When limiting maximum backend memory, attempt to refill allocation
+	 * request bucket if needed.
+	 */
+	if (max_total_bkend_mem && allocation_request > allocation_allowance &&
+		ProcGlobal != NULL)
+	{
+		volatile PROC_HDR *procglobal = ProcGlobal;
+		uint64		available_max_total_bkend_mem = 0;
+		bool		sts = false;
+
+		/*
+		 * If allocation request is larger than memory refill quantity then
+		 * attempt to increase allocation allowance with requested amount,
+		 * otherwise fall through. If this refill fails we do not have enough
+		 * memory to meet the request.
+		 */
+		if (allocation_request >= allocation_allowance_refill_qty)
+		{
+			while ((available_max_total_bkend_mem = pg_atomic_read_u64(&procglobal->total_bkend_mem_bytes)) >= allocation_request)
+			{
+				if ((result = pg_atomic_compare_exchange_u64(&procglobal->total_bkend_mem_bytes,
+															 &available_max_total_bkend_mem,
+															 available_max_total_bkend_mem - allocation_request)))
+				{
+					allocation_allowance = allocation_allowance + allocation_request;
+					break;
+				}
+			}
+
+			/*
+			 * Exclude auxiliary and Postmaster processes from the check.
+			 * Return false. While we want to exclude them from the check, we
+			 * do not want to exclude them from the above allocation handling.
+			 */
+			if (MyAuxProcType != NotAnAuxProcess || MyProcPid == PostmasterPid)
+				return false;
+
+			/*
+			 * If the atomic exchange fails (result == false), we do not have
+			 * enough reserve memory to meet the request. Negate result to
+			 * return the proper value.
+			 */
+
+			return !result;
+		}
+
+		/*
+		 * Attempt to increase allocation allowance by memory refill quantity.
+		 * If available memory is/becomes less than memory refill quantity,
+		 * fall through to attempt to allocate remaining available memory.
+		 */
+		while ((available_max_total_bkend_mem = pg_atomic_read_u64(&procglobal->total_bkend_mem_bytes)) >= allocation_allowance_refill_qty)
+		{
+			if ((sts = pg_atomic_compare_exchange_u64(&procglobal->total_bkend_mem_bytes,
+													  &available_max_total_bkend_mem,
+													  available_max_total_bkend_mem - allocation_allowance_refill_qty)))
+			{
+				allocation_allowance = allocation_allowance + allocation_allowance_refill_qty;
+				break;
+			}
+		}
+
+		/* Do not attempt to increase allocation if available memory is below
+		 * allocation_allowance_refill_qty .
+		 */
+
+		/*
+		 * If refill is not successful, we return true, memory limit exceeded
+		 */
+		if (!sts)
+			result = true;
+	}
+
+	/*
+	 * Exclude auxiliary and postmaster processes from the check. Return false.
+	 * While we want to exclude them from the check, we do not want to exclude
+	 * them from the above allocation handling.
+	 */
+	if (MyAuxProcType != NotAnAuxProcess || MyProcPid == PostmasterPid)
+		result = false;
+
+	return result;
 }
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 9b52cc5091f..09451bc4298 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -2077,7 +2077,7 @@ pg_stat_get_memory_allocation(PG_FUNCTION_ARGS)
 Datum
 pg_stat_get_global_memory_allocation(PG_FUNCTION_ARGS)
 {
-#define PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS	2
+#define PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS	3
 	TupleDesc	tupdesc;
 	Datum		values[PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS] = {0};
 	bool		nulls[PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS] = {0};
@@ -2087,15 +2087,23 @@ pg_stat_get_global_memory_allocation(PG_FUNCTION_ARGS)
 	tupdesc = CreateTemplateTupleDesc(PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 1, "datid",
 					   OIDOID, -1, 0);
-	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "global_dsm_allocated_bytes",
+	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "total_bkend_mem_bytes_available",
+					   INT8OID, -1, 0);
+	TupleDescInitEntry(tupdesc, (AttrNumber) 3, "global_dsm_allocated_bytes",
 					   INT8OID, -1, 0);
 	BlessTupleDesc(tupdesc);
 
 	/* datid */
 	values[0] = ObjectIdGetDatum(MyDatabaseId);
 
-	/* get global_dsm_allocated_bytes */
-	values[1] = Int64GetDatum(pg_atomic_read_u64(&procglobal->global_dsm_allocation));
+	/* Get total_bkend_mem_bytes - return -1 if disabled */
+	if (max_total_bkend_mem == 0)
+		values[1] = Int64GetDatum(-1);
+	else
+		values[1] = Int64GetDatum(pg_atomic_read_u64(&procglobal->total_bkend_mem_bytes));
+
+	/* Get global_dsm_allocated_bytes */
+	values[2] = Int64GetDatum(pg_atomic_read_u64(&procglobal->global_dsm_allocation));
 
 	/* Returns the record as Datum */
 	PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls)));
diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c
index 012d4a0b1fd..cd68e5265af 100644
--- a/src/backend/utils/hash/dynahash.c
+++ b/src/backend/utils/hash/dynahash.c
@@ -104,7 +104,6 @@
 #include "utils/dynahash.h"
 #include "utils/memutils.h"
 
-
 /*
  * Constants
  *
@@ -359,7 +358,6 @@ hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
 	Assert(flags & HASH_ELEM);
 	Assert(info->keysize > 0);
 	Assert(info->entrysize >= info->keysize);
-
 	/*
 	 * For shared hash tables, we have a local hash header (HTAB struct) that
 	 * we allocate in TopMemoryContext; all else is in shared memory.
@@ -377,6 +375,7 @@ hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
 	}
 	else
 	{
+		/* Set up to allocate the hash header */
 		/* Create the hash table's private memory context */
 		if (flags & HASH_CONTEXT)
 			CurrentDynaHashCxt = info->hcxt;
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index 2b082c68df6..02a060a3da8 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -171,8 +171,16 @@ InitPostmasterChild(void)
 				 errmsg_internal("could not set postmaster death monitoring pipe to FD_CLOEXEC mode: %m")));
 #endif
 
+	/*
+	 * Init pgstat allocated bytes counters here for forked backends.
+	 * Fork/exec backends have not yet reattached to shared memory at this
+	 * point. They will init pgstat allocated bytes counters in
+	 * PGSharedMemoryReAttach.
+	 */
+#ifndef EXEC_BACKEND
 	/* Init allocated bytes to avoid double counting parent allocation */
 	pgstat_init_allocated_bytes();
+#endif
 }
 
 /*
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index 9f59440526f..bcad500bde7 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -3553,6 +3553,17 @@ struct config_int ConfigureNamesInt[] =
 		NULL, NULL, NULL
 	},
 
+	{
+		{"max_total_backend_memory", PGC_SU_BACKEND, RESOURCES_MEM,
+			gettext_noop("Restrict total backend memory allocations to this max."),
+			gettext_noop("0 turns this feature off."),
+			GUC_UNIT_MB
+		},
+		&max_total_bkend_mem,
+		0, 0, INT_MAX,
+		NULL, NULL, NULL
+	},
+
 	/* End-of-list marker */
 	{
 		{NULL, 0, 0, NULL, NULL}, NULL, 0, 0, 0, NULL, NULL, NULL
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index b2809c711a1..59cb9886d73 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -160,6 +160,9 @@
 #vacuum_buffer_usage_limit = 256kB	# size of vacuum and analyze buffer access strategy ring;
 					# 0 to disable vacuum buffer access strategy;
 					# range 128kB to 16GB
+#max_total_backend_memory = 0MB		# Restrict total backend memory allocations
+									# to this max (in MB). 0 turns this feature
+									# off.
 
 # - Disk -
 
diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index 7af0d141da2..656ec384851 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -438,6 +438,18 @@ AllocSetContextCreateInternal(MemoryContext parent,
 	else
 		firstBlockSize = Max(firstBlockSize, initBlockSize);
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (exceeds_max_total_bkend_mem(firstBlockSize))
+	{
+		if (TopMemoryContext)
+			MemoryContextStats(TopMemoryContext);
+		ereport(ERROR,
+				(errcode(ERRCODE_OUT_OF_MEMORY),
+				 errmsg("out of memory - exceeds max_total_backend_memory"),
+				 errdetail("Failed while creating memory context \"%s\".",
+						   name)));
+	}
+
 	/*
 	 * Allocate the initial block.  Unlike other aset.c blocks, it starts with
 	 * the context header and its block header follows that.
@@ -737,6 +749,11 @@ AllocSetAlloc(MemoryContext context, Size size)
 #endif
 
 		blksize = chunk_size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
+
+		/* Do not exceed maximum allowed memory allocation */
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		block = (AllocBlock) malloc(blksize);
 		if (block == NULL)
 			return NULL;
@@ -937,6 +954,10 @@ AllocSetAlloc(MemoryContext context, Size size)
 		while (blksize < required_size)
 			blksize <<= 1;
 
+		/* Do not exceed maximum allowed memory allocation */
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		/* Try to allocate it */
 		block = (AllocBlock) malloc(blksize);
 
@@ -1175,6 +1196,18 @@ AllocSetRealloc(void *pointer, Size size)
 		blksize = chksize + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
 		oldblksize = block->endptr - ((char *) block);
 
+		/*
+		 * Do not exceed maximum allowed memory allocation. NOTE: checking for
+		 * the full size here rather than just the amount of increased
+		 * allocation to prevent a potential underflow of *my_allocation
+		 * allowance in cases where blksize - oldblksize does not trigger a
+		 * refill but blksize is greater than *my_allocation_allowance.
+		 * Underflow would occur with the call below to
+		 * pgstat_report_allocated_bytes_increase()
+		 */
+		if (blksize > oldblksize && exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		block = (AllocBlock) realloc(block, blksize);
 		if (block == NULL)
 		{
diff --git a/src/backend/utils/mmgr/generation.c b/src/backend/utils/mmgr/generation.c
index 0ed54571497..a1667c34371 100644
--- a/src/backend/utils/mmgr/generation.c
+++ b/src/backend/utils/mmgr/generation.c
@@ -200,6 +200,16 @@ GenerationContextCreate(MemoryContext parent,
 	else
 		allocSize = Max(allocSize, initBlockSize);
 
+	if (exceeds_max_total_bkend_mem(allocSize))
+	{
+		MemoryContextStats(TopMemoryContext);
+		ereport(ERROR,
+				(errcode(ERRCODE_OUT_OF_MEMORY),
+				 errmsg("out of memory - exceeds max_total_backend_memory"),
+				 errdetail("Failed while creating memory context \"%s\".",
+						   name)));
+	}
+
 	/*
 	 * Allocate the initial block.  Unlike other generation.c blocks, it
 	 * starts with the context header and its block header follows that.
@@ -376,6 +386,9 @@ GenerationAlloc(MemoryContext context, Size size)
 	{
 		Size		blksize = required_size + Generation_BLOCKHDRSZ;
 
+		if (exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		block = (GenerationBlock *) malloc(blksize);
 		if (block == NULL)
 			return NULL;
@@ -479,6 +492,9 @@ GenerationAlloc(MemoryContext context, Size size)
 			if (blksize < required_size)
 				blksize = pg_nextpower2_size_t(required_size);
 
+			if (exceeds_max_total_bkend_mem(blksize))
+				return NULL;
+
 			block = (GenerationBlock *) malloc(blksize);
 
 			if (block == NULL)
diff --git a/src/backend/utils/mmgr/slab.c b/src/backend/utils/mmgr/slab.c
index c99ff532af2..34fe5d713e0 100644
--- a/src/backend/utils/mmgr/slab.c
+++ b/src/backend/utils/mmgr/slab.c
@@ -360,7 +360,16 @@ SlabContextCreate(MemoryContext parent,
 		elog(ERROR, "block size %zu for slab is too small for %zu-byte chunks",
 			 blockSize, chunkSize);
 
-
+	/* Do not exceed maximum allowed memory allocation */
+	if (exceeds_max_total_bkend_mem(Slab_CONTEXT_HDRSZ(chunksPerBlock)))
+	{
+		MemoryContextStats(TopMemoryContext);
+		ereport(ERROR,
+				(errcode(ERRCODE_OUT_OF_MEMORY),
+				 errmsg("out of memory - exceeds max_total_backend_memory"),
+				 errdetail("Failed while creating memory context \"%s\".",
+						   name)));
+	}
 
 	slab = (SlabContext *) malloc(Slab_CONTEXT_HDRSZ(chunksPerBlock));
 	if (slab == NULL)
@@ -563,6 +572,10 @@ SlabAlloc(MemoryContext context, Size size)
 		}
 		else
 		{
+			/* Do not exceed maximum allowed memory allocation */
+			if (exceeds_max_total_bkend_mem(slab->blockSize))
+				return NULL;
+
 			block = (SlabBlock *) malloc(slab->blockSize);
 
 			if (unlikely(block == NULL))
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index fe0549c43d9..19839fc0459 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -5448,9 +5448,9 @@
   descr => 'statistics: global memory allocation information',
   proname => 'pg_stat_get_global_memory_allocation', proisstrict => 'f',
   provolatile => 's', proparallel => 'r', prorettype => 'record',
-  proargtypes => '', proallargtypes => '{oid,int8}',
-  proargmodes => '{o,o}',
-  proargnames => '{datid,global_dsm_allocated_bytes}',
+  proargtypes => '', proallargtypes => '{oid,int8,int8}',
+  proargmodes => '{o,o,o}',
+  proargnames => '{datid,total_bkend_mem_bytes_available,global_dsm_allocated_bytes}',
   prosrc =>'pg_stat_get_global_memory_allocation' },
 { oid => '2022',
   descr => 'statistics: information about currently active backends',
diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h
index 26b17d66477..e53ed1cba05 100644
--- a/src/include/storage/proc.h
+++ b/src/include/storage/proc.h
@@ -406,6 +406,13 @@ typedef struct PROC_HDR
 	int			startupBufferPinWaitBufId;
 	/* Global dsm allocations */
 	pg_atomic_uint64 global_dsm_allocation;
+
+	/*
+	 * Max backend memory allocation tracker. Used/Initialized when
+	 * max_total_bkend_mem > 0 as max_total_bkend_mem (MB) converted to bytes.
+	 * Decreases/increases with free/malloc of backend memory.
+	 */
+	pg_atomic_uint64 total_bkend_mem_bytes;
 } PROC_HDR;
 
 extern PGDLLIMPORT PROC_HDR *ProcGlobal;
diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h
index c2c8ba7214d..f07db4e57ff 100644
--- a/src/include/utils/backend_status.h
+++ b/src/include/utils/backend_status.h
@@ -15,6 +15,7 @@
 #include "libpq/pqcomm.h"
 #include "miscadmin.h"			/* for BackendType */
 #include "storage/backendid.h"
+#include "storage/proc.h"
 #include "utils/backend_progress.h"
 
 
@@ -305,6 +306,7 @@ typedef struct LocalPgBackendStatus
  */
 extern PGDLLIMPORT bool pgstat_track_activities;
 extern PGDLLIMPORT int pgstat_track_activity_query_size;
+extern PGDLLIMPORT int max_total_bkend_mem;
 
 
 /* ----------
@@ -317,6 +319,10 @@ extern PGDLLIMPORT uint64 *my_aset_allocated_bytes;
 extern PGDLLIMPORT uint64 *my_dsm_allocated_bytes;
 extern PGDLLIMPORT uint64 *my_generation_allocated_bytes;
 extern PGDLLIMPORT uint64 *my_slab_allocated_bytes;
+extern PGDLLIMPORT uint64 allocation_allowance;
+extern PGDLLIMPORT uint64 initial_allocation_allowance;
+extern PGDLLIMPORT uint64 allocation_return;
+extern PGDLLIMPORT uint64 allocation_return_threshold;
 
 
 /* ----------
@@ -365,6 +371,7 @@ extern PgBackendStatus *pgstat_get_beentry_by_backend_id(BackendId beid);
 extern LocalPgBackendStatus *pgstat_get_local_beentry_by_backend_id(BackendId beid);
 extern LocalPgBackendStatus *pgstat_get_local_beentry_by_index(int idx);
 extern char *pgstat_clip_activity(const char *raw_activity);
+extern bool exceeds_max_total_bkend_mem(uint64 allocation_request);
 
 /* ----------
  * pgstat_report_allocated_bytes_decrease() -
@@ -380,7 +387,7 @@ pgstat_report_allocated_bytes_decrease(int64 proc_allocated_bytes,
 {
 	uint64		temp;
 
-	/* Avoid allocated_bytes unsigned integer overflow on decrease */
+	/* Sanity check: my allocated bytes should never drop below zero */
 	if (pg_sub_u64_overflow(*my_allocated_bytes, proc_allocated_bytes, &temp))
 	{
 		/* On overflow, set allocated bytes and allocator type bytes to zero */
@@ -389,13 +396,35 @@ pgstat_report_allocated_bytes_decrease(int64 proc_allocated_bytes,
 		*my_dsm_allocated_bytes = 0;
 		*my_generation_allocated_bytes = 0;
 		*my_slab_allocated_bytes = 0;
+
+		/* Add freed memory to allocation return counter. */
+		allocation_return += proc_allocated_bytes;
+
+		/*
+		 * Return freed memory to the global counter if return threshold is
+		 * met.
+		 */
+		if (max_total_bkend_mem && allocation_return >= allocation_return_threshold)
+		{
+			if (ProcGlobal)
+			{
+				volatile PROC_HDR *procglobal = ProcGlobal;
+
+				/* Add to global tracker */
+				pg_atomic_add_fetch_u64(&procglobal->total_bkend_mem_bytes,
+										allocation_return);
+
+				/* Restart the count */
+				allocation_return = 0;
+			}
+		}
 	}
 	else
 	{
-		/* decrease allocation */
-		*my_allocated_bytes -= proc_allocated_bytes;
+		/* Add freed memory to allocation return counter */
+		allocation_return += proc_allocated_bytes;
 
-		/* Decrease allocator type allocated bytes. */
+		/* Decrease allocator type allocated bytes */
 		switch (pg_allocator_type)
 		{
 			case PG_ALLOC_ASET:
@@ -417,6 +446,30 @@ pgstat_report_allocated_bytes_decrease(int64 proc_allocated_bytes,
 				*my_slab_allocated_bytes -= proc_allocated_bytes;
 				break;
 		}
+
+		/* decrease allocation */
+		*my_allocated_bytes = *my_aset_allocated_bytes +
+			*my_dsm_allocated_bytes + *my_generation_allocated_bytes +
+			*my_slab_allocated_bytes;
+
+		/*
+		 * Return freed memory to the global counter if return threshold is
+		 * met.
+		 */
+		if (max_total_bkend_mem && allocation_return >= allocation_return_threshold)
+		{
+			if (ProcGlobal)
+			{
+				volatile PROC_HDR *procglobal = ProcGlobal;
+
+				/* Add to global tracker */
+				pg_atomic_add_fetch_u64(&procglobal->total_bkend_mem_bytes,
+										allocation_return);
+
+				/* Restart the count */
+				allocation_return = 0;
+			}
+		}
 	}
 
 	return;
@@ -434,7 +487,13 @@ static inline void
 pgstat_report_allocated_bytes_increase(int64 proc_allocated_bytes,
 									   int pg_allocator_type)
 {
-	*my_allocated_bytes += proc_allocated_bytes;
+	uint64		temp;
+
+	/* Sanity check: my allocated bytes should never drop below zero */
+	if (pg_sub_u64_overflow(allocation_allowance, proc_allocated_bytes, &temp))
+		allocation_allowance = 0;
+	else
+		allocation_allowance -= proc_allocated_bytes;
 
 	/* Increase allocator type allocated bytes */
 	switch (pg_allocator_type)
@@ -459,6 +518,9 @@ pgstat_report_allocated_bytes_increase(int64 proc_allocated_bytes,
 			break;
 	}
 
+	*my_allocated_bytes = *my_aset_allocated_bytes + *my_dsm_allocated_bytes +
+		*my_generation_allocated_bytes + *my_slab_allocated_bytes;
+
 	return;
 }
 
@@ -478,6 +540,36 @@ pgstat_init_allocated_bytes(void)
 	*my_generation_allocated_bytes = 0;
 	*my_slab_allocated_bytes = 0;
 
+	/* If we're limiting backend memory */
+	if (max_total_bkend_mem)
+	{
+		volatile PROC_HDR *procglobal = ProcGlobal;
+		uint64		available_max_total_bkend_mem = 0;
+
+		allocation_return = 0;
+		allocation_allowance = 0;
+
+		/* Account for the initial allocation allowance */
+		while ((available_max_total_bkend_mem = pg_atomic_read_u64(&procglobal->total_bkend_mem_bytes)) >= initial_allocation_allowance)
+		{
+			/*
+			 * On success populate allocation_allowance. Failure here will
+			 * result in the backend's first invocation of
+			 * exceeds_max_total_bkend_mem allocating requested, default, or
+			 * available memory or result in an out of memory error.
+			 */
+			if (pg_atomic_compare_exchange_u64(&procglobal->total_bkend_mem_bytes,
+											   &available_max_total_bkend_mem,
+											   available_max_total_bkend_mem -
+											   initial_allocation_allowance))
+			{
+				allocation_allowance = initial_allocation_allowance;
+
+				break;
+			}
+		}
+	}
+
 	return;
 }
 
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index 7d412b26801..cf7a2b52359 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1882,13 +1882,15 @@ pg_stat_global_memory_allocation| WITH sums AS (
  SELECT s.datid,
     current_setting('shared_memory_size'::text, true) AS shared_memory_size,
     (current_setting('shared_memory_size_in_huge_pages'::text, true))::integer AS shared_memory_size_in_huge_pages,
+    pg_size_bytes(current_setting('max_total_backend_memory'::text, true)) AS max_total_backend_memory_bytes,
+    s.total_bkend_mem_bytes_available,
     s.global_dsm_allocated_bytes,
     sums.total_aset_allocated_bytes,
     sums.total_dsm_allocated_bytes,
     sums.total_generation_allocated_bytes,
     sums.total_slab_allocated_bytes
    FROM sums,
-    (pg_stat_get_global_memory_allocation() s(datid, global_dsm_allocated_bytes)
+    (pg_stat_get_global_memory_allocation() s(datid, total_bkend_mem_bytes_available, global_dsm_allocated_bytes)
      LEFT JOIN pg_database d ON ((s.datid = d.oid)));
 pg_stat_gssapi| SELECT pid,
     gss_auth AS gss_authenticated,
-- 
2.41.0

#54Anton A. Melnikov
a.melnikov@postgrespro.ru
In reply to: Tomas Vondra (#52)
4 attachment(s)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

Hi!

Thanks for your interest and reply!

On 26.12.2023 20:28, Tomas Vondra wrote:

Can you share some info about the hardware? For example the CPU model,
number of cores, and so on. 12GB RAM is not quite huge, so presumably it
was a small machine.

It is HP ProLanit 2x socket server. 2x6 cores Intel(R) Xeon(R) CPU X5675 @ 3.07GHz,
2x12GB RAM, RAID from SSD drives.
Linux 5.10.0-21-amd64 #1 SMP Debian 5.10.162-1 (2023-01-21) x86_64 GNU/Linux

One cpu was disabled and some tweaks was made as Andres advised to avoid
NUMA and other side effects.

Full set of the configuration commands for server was like that:
numactl --cpunodebind=0 --membind=0 --physcpubind=1,3,5,7,9,11 bash
sudo cpupower frequency-set -g performance
sudo cpupower idle-set -D0
echo 3059000 | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_min_freq
(Turbo Boost and hyperthreading was disabled in BIOS.)

I think what would be interesting are runs with

pgbench -M prepared -S -c $N -j $N

i.e. read-only tests (to not hit I/O), and $N being sufficiently large
to maybe also show some concurrency/locking bottlenecks, etc.

I may do some benchmarks if I happen to find a bit of time, but maybe
you could collect such numbers too?

Firstly, i repeated the same -c and -j values in read-only mode as you advised.
As one can see in the read-only.png, the absolute TPS value has increased
significantly, by about 13 times.
Patched version with limit 200Mb was slightly slower than with limit 0 by ~2%.
The standard error in all series was ~0.5%.
Since the deviation has increased in comparison with rw test
the difference between unpatched version and patched ones with
limits 0, 8Gb and 16Gb is not sensible.
There is a raw data in the raw_data-read-only.txt.

I think 6350 is a pretty terrible number, especially for scale 8, which
is maybe 150MB of data. I think that's a pretty clear sign the system
was hitting some other bottleneck, which can easily mask regressions in
the memory allocation code. AFAICS the pgbench runs were regular r/w
benchmarks, so I'd bet it was hitting I/O, and possibly even subject to
some random effects at that level.

To avoid possible I/O bottleneck i followed these steps:
- gave all 24G mem to cpu 0 rather than 12G as in [1]/messages/by-id/1d3a7d8f-cb7c-4468-a578-d8a1194ea2de@postgrespro.ru;
- created a ramdisk of 12G size;
- disable swap like that:
numactl --cpunodebind=0 --physcpubind=1,3,5,7,9,11 bash
sudo swapoff -a
sudo mkdir /mnt/ramdisk
sudo mount -t tmpfs -o rw,size=12G tmpfs /mnt/ramdisk

The inst dir, data dir and log file were all on ramdisk.

Pgbench in rw mode gave the following results:
- the difference between unpatched version and patched ones with
limits 0 and 16Gb almost the same: ~7470+-0.2% TPS.
(orange, green and blue distributions on the RW-ramdisk.png respectively)
- patched version with limit 8GB is slightly slower than three above;
(yellow distribution)
- patched version with limit 200MB slower than the first three
by a measurable value ~0,4% (~7440 TPS);
(black distribution)
The standard error in all series was ~0.2%. There is a raw data in the
raw_data-rw-ramdisk.txt

For the sake of completeness i'm going to repeat read-only measurements
with ramdisk. Аnd perform some tests with increased -c and -j values
as you advised to find the possible point where concurrency/blocking
bottlenecks start to play a role. And do this, of cause, for the last
version of the patch. Thanks for rebased it!

In general, i don't observe any considerable degradation in performance
from this patch of several or even 10%, which were mentioned in [2]/messages/by-id/3178e9a1b7acbcf023fafed68ca48d76afc07907.camel@crunchydata.com.

With the best regards,

--
Anton A. Melnikov
Postgres Professional: http://www.postgrespro.com
The Russian Postgres Company

[1]: /messages/by-id/1d3a7d8f-cb7c-4468-a578-d8a1194ea2de@postgrespro.ru
[2]: /messages/by-id/3178e9a1b7acbcf023fafed68ca48d76afc07907.camel@crunchydata.com

Attachments:

read-only.pngimage/png; name=read-only.pngDownload
�PNG


IHDRq 9Vy�	pHYsg��R IDATx^��wTT����0e���Q{����$�$��$�4cS��}�hL��D�����5��1��KTPTD��i�P�a~���{�t���Z��-3��;����9�H� �B!�B!�B!V��_A!�B!�B!�B=[�:t�'�B!�B!�B!����7�HB!�B!�B!��DIB!�B!�B!�+DIB!�B!�B!�+DIB!�B!�B!�+DIB!�B!�B!�+DIB!�B!�B!�+DIB!�B!�B!�+DIB!�B!�B!�+DIB!�B!�B!�+DIB!�B!�B!�+DIB!�B!�B!�+DIB!�B!�B!�+DIB!�B!�B!�+DIB!�B!�B!�+DIB!�B!�B!�+DIB!�B!�B!�+DIB!�B!�B!�+DIB!�B!�B!�+DIB!�B!�B!�+DIB!�B!�B!�+d�� �B!�b�Z�����e[[[H$��B!�R;(�C�z����w����QVV���rTTT�������������F�V� �J�����������W��Y�fptt�sss�P(�e???�gkW\\���d�����d���2DFF��������:����s�(�J�T*H$��rxzz���r���^�gk)WWW8;;#++��Tc��7����p��U���`��Q������B�@@@���CmT�k,mTee%222�s���J�Rh�d2�r9Z�h___���w�^����-�QHKK�g�}&,��7�������;w������@xxx������������������G*--M8w���aoo777�i�]�v�����dff���K���CYY�������>}�������(�Z���$$$�������B�&M����=z@&��/�K�V###r�^^^�f�����T��-[��u�&����{����l���������q��e������j�...h��
z��WWW�%)((���W������b(
8::���
��������1�q��6�����8u�����6m���-�R�������T�������V�Z!00��7�^�����(((�yfx��!�j5���
???4i��y���������H$����Y�J%.\�������C&����]�vE@@�Y�A�;III�q����QRR'''��������uc����R�p��5$&&����P*�B<����;w6���4|�{�@!u ,,�W�eoo��}�b���h��=����������_m��W�^����[+,����
��Z^^��+W������m��"�����{7
lll���>��?�1�s�H$���&N��n�����gk��'b�������M5��g��s���j��={p��m[|�hLff&/^�����7?v���[����s�>��s~�^���

���S�a��9W�7oNmT�x�"V�^���*888`��������;w"44�����K��Z����Tl��)))�&�L&��!C0c���9yyy��q#�]��o���`���x����Jh]�~�6m���w�M�\���{!!!&�YYY������iS�]���lPQQ>��#��rl����,��6�\�v���s�.4�}P��8z�(<h�c�L&CHHf��av����p��i���!==������		��)SvjH������VTT`��=CUU"""�d���,��w�b����x���s@�S�Nx��'���o�����{___�=#G���M�g%�s�V�\	���G�>}�=t���a���z��}���E�x����o&���S�N�������7	�R)�w��3f������#::�v�B~~>�I����'�x&L����X7��	!�JEE�����_`���P���.DD�P����Fjj*��"J�k����������*\�r���z��j\�r��/������������TVV
�����;X�lJKK�M��FY�qn�***��������77x�cu��	a�Tyy��~�������o������V�n������mqqqX�x������8q�����R�������L�������X�d	��������p,[��`��k�7o��?��o��M(���Y����B�V������b��n�
.]�@�2lW��X�v-v���7���T*��������R��7�u��
|��G��i������9��?�999�f�=��jHm]{���������?�����
��1�R����c������2zh��q��/��={�M�r��ml���/FII	��bQQQ���m��V��n�:l���������/�������G����B�+V���~2y��R�����&���{�b��uF8�f����;�b�
��{����8��K*�B�R��hnv���O�T*��5��L�y����o�r��T*��7������:[[[����^���������C.�C*����
EEE�u��	����}�Y���������H>����t��5|���V�F�F����Fyzz����J�P*����Czz��R*���q#�����{w��������4�l-<==��z��`����2������SHII��?�\�e�������c�?������'Z�h�J���\�vMhs����o����/78�����}�s��l���u������'|o���~�,��z�*�n��$�����D���$''�N�<�V�Za����:�8�p��9�k�N����/
?����=��>��s��	�A�����?�`�����w���7����������D�����}��3g�a�����M�������(,,��;w�k�B�������Y�q�����yyyX�d	���/������,*��P(�j�*��{{{4o����P*����Faa!��%����$��*--Ezz:����}���������/�09���Z�3g���+8�������#::ZX���E�����U+(
���
�c�Z��7�y��uVN�s��}��RQQ��+W�����z�\___���������a����*:t<����u������Tyh��	�w����!11iii���W�b��mx��WE�"�M���B}��v�*�<x���,������B]d@��488:t����m���w��W�����j0����a��XU��
���T*��y��*P�Z�n�O>��_���J?~�w��-���=z��`���U�,����GGG�^�������?q��qay��y&��������u��
��w��5�e>�Z���P����`R������{\��!C���g��W������+bbbh�����+���nO]�=Wlmm���c��MC^^RRR��wo�����X�9s�`��M(..���������@�~����_]�����@���#��K�s��/_���a9::C�e����u+Ty��g1y�d&�r��-|��WB����X\�|=z��4�
6y��7Og���Hl��Q����o�
gggf?-q�����1c�h�~J��i����L����M2D<Z�XB���
G���R)>��St��I�������_�38~�8�z�)�e�����~�z&�foo�'�x��I|)
������#�������.i��U����*
,_�\'��h�"��jLee%�.]�3B�c���<y2�v����������c���������l7��O>�Iz��j\�t	7n���7o����f�x			���t����<N���8p�����eK|��G��r�����eN�8@����_���aB���OxT~��'&������3gb��L��V�������qqq��'N�y���4i���\��mmm��/ $$D�}:w�~��G�������<yr������$!��qqq.`666pss���1a��\����a2@*��,z�h��J%����c��1��u��Q�'���o�i�Qc���0i�$�����J��/b�������5k�seS�����4�}bbbPVV�������O?��3Gaa!��_���q�FU�Qnnn�;w.rss���@3�Kff���
jr��z�Q5�����������?V�X��~dZ�j�/���V�B�n�������|||����c��u���/�M�����������)S����h��
�z�-a�
@���3aaaL��Y�f��C���;w�9�***�	&p{j���w��Ezz��Q��]c���iI,�fm�>yyy�q�MP�������n�b�
��
�I���E||�P����������#�����/���\g���������#��1j�(:��(9`��<�b�}�]�~=����e�\��?�������������
^~�e�5J��]�v�;w.F�����m�H$���s����_-�?�|��8�D��Rj{��>�L�����h�R)f���;w����d����m��������<c����?���6m*�KC"����.Dhh(v��)l��o������6p�@���������o����{������+W������I:����X'��BH����7�x�Yg��������X�p!����Zy@������:}�t�{�=J������!��������sW�T8z�(>���m(��2��(�D"��]�%�:j����6m����� ���ah���2�Tj�}{���B���QYY)��}?___2D��5y�d����D[�QXX��q4�cS���h��u����!��&EGG�/�����2���6�k���_�������'�|b0�#fgg���������T-���j���7<<�9�R)��}��R�/_f��o�����X��&p��G�pqq�����T*�������N%�������G��z��R�N"�P�B��Z����3��{�=�	�O<��cJ��������sg�^��`G�/�Y[���DIBH�����<��W			X�jsQ<xp�zgm����O��o_L�:U����k�����!�Nh�e�rss���(����b��Boy�L�g�y��2r����
����y�&����N
[���Em�~|%�]�PQU}������@JJ
rss���S�����Crr2n���(�{{{�����/�d���[�=z�,?)�+�J�����4�)b���33J'%%E��,|	)�zI�Ba0�e��j�������������k��������x���k<b�&�qj��[\\�S:����G�.]�u�����4�YW��e���]�tI8O���{{{n����4#�����;3b��k��z��!������dddd�$��JEE233q��M������d�����������{��E����Jddd�����}�6s_k	�B���o#))	YYY������*))	���F�K����Am���g�����3YUA��g��\.���?/�k����c�}i<��BH%~S�������s
����E�x��W��kW|��W����<xyya��9:��Y;��f�V����H<YxPP���p��u����J��#>g�w��Y�f�y����o�h���x�b��s��f����3�;�f�������������w��~�?�y��H$���A�^�0d��{��j�X�F�'.�P%V�mTu%''c����j��>,,�����dX�d	���QPP��;w����L�_.��W�^�6m�P����������a�N�������y��s�;v���W#  ����n��5HII�	���G:���c�b������$������%%%1�{���E[���3����1 f���$m�u���>��8�Jm���������������:m��[���}�tJC���i�D">#""0f���Lm)1-}�m);�)S�X\���=��
���w��]�w+((����a���df�	'''�e��Z�f���|F�e���sg��r�i����zH�R�k�W�\��
1E�P��>���u��y���XEEEX�`>��#�%�


�p�B��<{�l�e�����+W��$�7o�~��a��I����R(�����3g������pwwG��=1~�x��Q1�Z��'O�����}�6����]�vEPP�����4��:������J�@��}��S�������'����$�lll����A�a��QF��,����i��������CTT����U+|����r�P����>}�Y6�����3 �6���9r$��i�}�9#JI�EIBH�$��cgg��A�qckk�I�&a���:��Z���
�����,�H��o<���u��Y�g;;;�z-Z���
�	m�������g��K/�Qsss�/�P/�%88[�l�y�:{�,����),,���-�b			��+W�`���z{J��j��}�o������f�xyy���)j�tQ�K����Oo@�!i�mTuUVV2�4L)--�

E�����W_�����S�VFGG����x�������U�V�������x�"�^����{Og��B�����6���$���>%$$0�|���Z3tt���{�����gkk�������w����P���sx�����tG�h�������6�$K���&p��wo!�������W��>`����l&���sg��6���L�E[[�j�j��8�Z�u�����#4�V^y����WhF�=�����x�=1b�h�yJJJ�s���]�v��`���v�����'�JKKQZZjVo~-�\�����QVVf����S())AXX����of�9sF8�2�={�d��T*l��
G���{��������o��~����X������i��kVaa!N�:���(<����J��W�f�#���2��������1t�P������0��b*�
7n���7�����h��Z�z5����M4��iiiHKK���G1o�<�r�Zyyy��TII	����b�
��!!!j~�P��.��#r�\��a��� �ddRRR��G�}����4���!������Gm���h�����+V�����k��hn��7e0����9�<�=*,���Kh���h��'::Z������.]��o���C_yy����!={���U�j%�c�!C�0�|'}"##���������k��e82�������#Sj�e��:���Fm�.j�XUUU��k�����o���Yk����G����X�bJKKacc���[�}��LhFk�����/C<==��sg���0�MEE~�����qqq����NP���nnn�?c������7��+�������G��	��yxx�U���9��4#+����/�$&N��_���*�\��&UUU!&&��7���=�{����>>>�}���T*���a��[[*�b����Z���L���]�2%����>��y�=~�8t�6mZ��-��7R�>effb��M�rpp0���+��<g����A����{Es�)@�m�Gy�C\���������c�6}��Y<x�����=O�u���f����3�R��m1p�@����������f��m��$�N2A"�@.��t,Q�T���_u�7Z�I�4m�T�5��P���pvvF������|O��jeff2�#�i�����K�n���N��/�4k~���J�^�Z�����E������hM�j����w�2�y��m���4�O�W�:]QQ�����f�h'
��!�4*J�;v�`���S�����8Rggg����,�,6{����K�������*����]�v

Bppp�nljCQQ���/a����
��wqqqB�%[[[����f�'Zqqq&�4�z��W�9qo���������GFF��CS_�������!C��Wbb"rrr��En��:uJ��O�>�nLL3|�G��3g�L���Bll,v��mr���Fm�~�k����3g��4
233q��9a�www���{F'���s�!�Q���C�_�p���%�����.f IDAT�@EE�v��Y�f	�����p��l��U:i�uww�k���\�233��?��KKK�����L�8Q�A�j�*f���~8|�03��w�}��x�o���L�m��zG��s���C"����A��E\'��-c�'�~ee%So��	���0�T������I�L�0���;MBH�V
u�&�]�zU8�={��IH��ys����X�r��A#33�-��a����$%%	�?���z?{�>���]}���Z***��7...������q��5����������
�By��!|��dh���?;����(899A*�B�T�������p���|>|8f�����<�������S����r0�o������k���7�a����������=u�&M�����������

���eooo�����wB�V���S��u+�J%����i�&�o�^o�Ls���~~~�����#0h� &8����0�N������c�U�Z�����dx�����a]~~>�=����$Dxx8�<e�<��SB�����N��������Bii)V�Z���b������1q�D��SRR�#G� 44j�*�
k����U��������R���l***���$�5�O��1�k�h^C�MMqqq�����Yeggs{�v��I��w��&�$
}���F����/_��#G�k@@�Y�`fff��o��W3�h�"~�c�����7ncc�
6�D
q��%\�t	��|P����{��<�'00�������V��W���s'��N��u���QPP� �v�����4��1c�0���O��g����7n0��c�
?kk�k����LoP�����w�	��j��GCk�bcc
&\$	F��3f�|���s�1�Q�akkwww�^�����?�~�m&�hcc���`���a����z,^�Xg.ooo��?��� 66�I�888=fUR������,?�����6hl�:eh�d2���9�?�����9222����z�B||�0b���s�2e���|���xzz"$$DH����#++�d;Wm��8j*����e��z�jdff�$4O�<)�ccc����,s�_��0�k>������9,�H��_0��T*���"77�����������7?x������������~��_%���������{w~�Y���+$���M&����i����-�������{���3gh5z�7>��'�xBo�X|�:::2�
�9�<<<��g���,�H$1b������?�$E8�W_}����3g������v�U�V�;w.�j�0����{HHH`F{1�4����$p��6s�L�7N��?�����<���c���

�����g��|$�J����X����3f�y���������16��R�D��M�h�"������`b�R5=u�v��QK���I�����R�I�TTT0s�I�R�7N�i���c%�+������7���~������:^�u�[��	�zzzb��yzo"I��VUU�<������_��$!!K�.����QYY�onP����7o��@

~�Nri�Z�j�<DEE��-�����<@��yqAL&������F=:������\�l�Hi�C�(��5�`�w��L�1x�`��V��M��#_R�����gJ��k��`I)������������d�s��~�g�_�����������I��+���3�$�����"�)�Y5m�***��H.�[<V�R!**������eK�=�����
fgg#==]�?�(��z���6\�v�Y...�9�y���X�t)�}t��~Feee:���_M��sss����c��-z��0��Q8�nb��m���������:����~}nn������Z�~���)<<J�RX�1c�����A��r�����JX�u��YoG��'�d���}<���3U�Y�R|j����9����<M�0AoGl����3��32���^�v�DKYz�?����>�k��jL9x� S.q��q5�F�Cip�������1�.]�����2;@+��L��5��qpKT�C,((�F����T*���7�
�k���������Z�6m��c�B&����J�������D||<���������w���SX�`�P��KG�����r�w_��Y�f����B���:=x���1c�r8���������X^^����{�k��	8p���N�%K��ztZ��K���vvv���EEE������)UYY���4��������y������s�1�Q��X�L�T
[[[!Hd��F�����
T*����
�R����[�u/��b����dMM�������������C����}�vTUi&������L ]���u��B";55�d��.�$�.���� ��o>�w�}������s��	���L|����={6�"���y��S������`}��Jb��������d2�5
�z�B�&M���DGG���BP6==;v��+��"������7��B]�|���W3f�����p
rrrp��
dee���������_���������(�Ht����T�b�=z���YH��?^gDIDD���I$�s
�I&���1���c .����l0	/,��������7u���6ooo899	�|m9D-wwwxxx����X����<����k'� <<\�����g�
�S�DbpD"/88��_�y��w���!:�mm��1�|b�O�Z�����VVV���a���U'�H'�w������r,X�;v�7��m[,^��_M8|}f@(�D���/^,�(�}�6��;W���zxx`����j�����p����P�T�����e��b�
������[���G)&&����?�{mP(;;���L6k��wo4m�T�0����:I�����������;h� ���O�(����(//���?f��FmT�jhmT@@&L����	���C(�5k�`�����,k<W�������������_�����/��"�KFF�9��`��1�j������nt�$�����	������{s�������A���[��l	�5���J�i���G�������+W�7ir]�IZ��D��c����������f��a�����e���������QQQ�Q�F	�t{=�tt��������+���h�"�6�S�N�����['�;y�$�L�"� �������wZ+>>6l@AA�������c��EF����d���cGaGc��<�f���OsI�R	s����B�T
	.�J����1c����J���x�y��9�����KaY�P0�C;v�h�s���JNN��$Nqq1���������(
8;;���vvvBG���	&�����h�	K�.�3�<�#F�L��?111BBl��������)SL�~�	���	�B����������`�}���N��&��:,�����9K������Q������������/�^K>J�B�w�}���(++CEE�=*�W(����8@J���,h���NpT����>�,�l�"�������1666B�H��7??�����/�(����G��m�V�h��� ���o�rdd����5���AHH���@�3O�P07����#F��T�����y��r�J��%..�/_F�=0q�D����Q��4�6J.����^�B�F����������/��u��6����Bo^}�|��F���L@�WUUev'--
G��]]]����@�R��Z�6+(%�������7|i(C�@��wR��L@S��{���B����BG;�
�����=�����������
k�&	Fr{����������E�	�M�6��&t��m���m��L����I��-�c�L&c����W����&��;~�x��wpp0.\� ��*�
����\�g��W3D"�0��J���R��u����������
*�
[�l�����]uT'��'_�Mf��d>qi�A�	I���r\�rE}t��%�����;���[�n	����p���4m���g5o
`��L;t��}�d���fZ|e��S�

�Q-b|�C}m�������*�&S(��u+<�1c�`��Q;�k�/���m��Z
�Z�c��!""C���	��C�\2yyy�?�h�����X]$Qx59�a�= �,1���G�d�H$:	"}�?.<W@��]��<%�S���!�j����{w������:�[i���q�v���L
u:t(�@���(�jF�a��<,�(--�)�!��/����V�Z	�g�����a
�=��J%S�933S�����18��C����/��|�Z���8,[�K�,a���&j����FM�:�Y>}�4�l�cE��J��O?��jg��i08�%���j��>��(�?��gn��}������$��#qM�S�k:%%���P����vO�����������&�������`��fZ�����lll���o��M9�Y�f	�*�
�v���;���c�����m�m����7��kE}��d���!%�����2Gvv�Y��={�>�m��a����.5���������c�J�2�������q~��!|{�'�,��_��%��[[[����S��v,!!�����������|�����!�.]����_1	;;;xzz��{I$��;S�La�U�����w/�����
;f������9PYY�����?6l�{��?����I��v�Tu�A}�K�{�UVV2�k�m�>���BGG@����=[�i�h$!��k��&M�����m��o��6�'�)�w���T������Jx���Z]
~�o�^����";;�	&Z3�C�D"1:��_�~8t���y��%�������&7?}�����-7h��+I�����+W����8t�3�pbb">��3����6l��U�������(???888=#���F
�������s�������������C=�y�f���w�	����*((0��X;���������L2�'8����'q�����[7���A�V����~?q)5@�{�d2!���___a{uT�M��H@3?�����������G����!q|��u���A�v���w���7��7����q�m|0��H
�;.d������G�VZZ���,��Y_:v�������dt��+W��C��=����k��!�O*�,�e�D�so\�x>��4	<�=z���������(
���`��Lg�f���|�|��T [�������W��D��#Gb���h����`��%�w����:$	�}�Y2������g�eee��w/.]�����x��t��G������vA�V#22W�\�����6�����h���k���)���������,�������f�+33�9���i��F6m��t�x���tF�����8��Fa������&������Cu�� 5��d�m����BaUR@��*,,lI���r������y�����"##�%@Z�G��8)))�s�Z�l��}��d�I�R�9��
Ctt4���'�������I�:o+����w�1�Q�����b����z�J5e�~�C>>>x����������&�+����ZYYYF�������8������������P'���O���r�Ng��
���;w��}-.�h:������:t����,i������J����&ax�pZ���I$��������&$q��K._����2��J}��&��J�R��~������^F��v0%cbb0}�t����'xy�M�9991I���,n��m�����|'�4h���Q(�z�*����������<
��!C�<�F��#\����eC���s������~8�?>:w���	4i�D���1�Z���o�����c��}�\/���X�j>��s��sggg<����4i�=�?��C��b��X�r%���acc�\.�\�3��!��T����r�-Z������Gzz����x�7@��������G���BIU�����p�R�d2����/��bvmrb��9���'lNP�����a�*::�������{�n���s����|��Zh{�iEFF���KBoF???��1�T��C���o�APP��^�Vc����=��Q����Q|@�6������F�GG�Vc����w����6��9�IC�7$%%�Y�$���[�n1��h�*�f�L�&M�eqG<
G�o��B�����L�X_�S����&,i��2����ny$>������,����3��������Z}��&���R�t���������z�b�O�8a��0u����=3�������4	��2E�V����<�������C|]]���c��111L���c�
?���6������~��)��/�����v�2�Ol��QK���0��Y�f�M��D���1w�\|��GL�811���L�\����c����������������&s�A}�U4�������u��,�`����D"�k��V�$-ix(�Ci4�u����������Aj�&hG#�����jz;�������O��F�K�R�\�Q����b�2��������o��<���u�^�*SU�c����2]\\�C[co����0:v�Sj���O��|oW�7�>��]~n��S��m����������DRR����gO�V���o�M��=z���=�=<< �[�%##��<���MR���wX"��
���M�ztG���p���,����f��R}��������yyy�y��w����I�i;X���X����sB����:s�"n[�j5SZP���d��
��T���������W����x�8���uk�e�\\\�6��d��7�e}��9�����lVY�����;^z�%f��+W�eC������2����wn+..6��B}��}��cP_������t:s��Y��sGXn��:u�$����/�0F��S��<(�CiTf���<�;v��uJ�.ooo����Mgvv63��o6�^�������:�t�Qjj*ss��{w|��'&�-\�������6������|������N3sC�������(>b��G���Q|pU<����H��1�{�.~��7aY"���W_��<�qsscz���s�h�077�I����W�U����9{���Q����cz����������q-}sK�-�#~���J&pT��I���B��sg��������h���Gh3I���2�Y�F�4S}���Z��IE-�|)��AW>�.�Ht�*:~��#O��������f��V���V�.]����Hf�'U&��t>��'q�#�u�5j�p}�o��]<
!33�)��OUUs`oo�S.�\����������0)?���g�-Z0�������(F����>��1�/����h���rl��]��a�����@��1$&&���5i��=��h�8����B����sQS�T�����u'�0`����K������w/��>���ll���Y7t�P�Ak�?�����k��&�����y(LOO��$�L&�;����#M�[OHH0Zz�������F����F]�xG�a�
6�Y�V�����:�����]\��.��j�I}������vv����t�Z������6Z*��������r���q��a��())aFx{{3�V�\7��������]���������kM��M�i�e����e)))F����L����]g��L��^{�Y�����K���g��T��:����6///����G
�������~����3�yO�Z�������#&G����3��jCyy9��]�$`�����,4�d\�~��iSt�������={2��bcc
������wc��a:���j�����Cwww�m����N�Y"��������w�7���?��aC���g.m�1�w����7..999����%����hQ?Z����<�������3����3f��,,,��w����'T���_|�I�EEE��m���<|���L2���[g�����m�6f��/����f��Y6��B���DFF
7O)))8~���C���t���"�I����g-����S'��'1� IDATk4q�DDDD@�P���
+W���9s��
J��v���s��u���z�uI�T�������J�P��x��222p���<y��im��)�z�)�;�g�g�31qM�����r�J&1#���,�����=�������������
?��d2�z�)3=�p��a����V?S���[
��R(())���$	T*���������h�<4����z]�+�z�(OOO���	���l���=��E�7d�������������'�xP�T())a&���'NAQ@�P���5�|���a��!!!L�����X�nf��%>�������3��#F����O !!AX>x� 0a�a���7�i�&�=���L�E���H$:	-{{{���[��
�R4��M�
#7RSS
�u��&=|�Phce23�%���G�
��6mBqq1��#|����p��1���_���h�^�za��Q�������>��a�0`�t��QhU*RSS�$P�e����M�6
+V���m��W_a��9L�����[����W/�����
����E�	���j5v�����(�5
�{�f��
q��E>|��?����www�d2��j���#++W�\Axx8���J�x����y1G<�}ppp�:�988m������s�
���T*���`��-��ggg�I�&	��
d��F�2:r��q�H�:�����������Wll,~����9S'a��;w
�r������:w�,��*++������O2���j��������������'�K#::��m����1u�T�;PYY�SP���s����kt��O?�4�v�*lS��8|�0SZ��K$���K���/�D��?����,L�:NNN����^8**
{����q�0u�Tf{m��}BM�A}j��5&N��$�w�����$L�<����D"�Z�FNN��9��G�2�`[[[���:#���n����������������	�4��Bi���5>��S�f������<==��5�����?���Z�~�N
g�u�����Z�`A�����������?�@�f��������7����������H$x��7un��ZZZ���@��e�����>���zqY�����;F\,��_1=���gQ�o����y�pC��_a��F���M��w��B/wc�c���/���7��_E`` �r9�����7o2��?�Z��EmT�jHmTXX����n�:w���s���u���b����6l:$,���������1c���K�g�������`!PWRR�O?����h��)��������C���^�^m���|&h�3��O?�4(vww��/����=s�.\��-Z���yyyL�looo��k�^�0t�P�'�6�|��!xyy���P����!Ctz���8��53�&
8P�*�����'������6)66V�#�O�>��9<i�$DGG�u�J��;wb��}h��%T*���u~W��#f���Z����R�p��	a$�\.���<x���Z����������#88X�'''��?���/<==�P(����������={���k��%-Z����3A�;w�`�����u+lmm������J�%�d2�Y�i��y4	$�ZmpD���-�}�]���	����z���q�����B��7�|�&M�������LP�������a��A��k�j5lmm���h��-:t� �s�3o��/����$aN�'N����F�=�s������=���gsc�������~�
qqqB<??����{��r�\�w�n���������Z�FTT�����m[������7o�d�e777��h�!���������������j���3�%�N��cG��=�6m���G�",,�������j5������ad��C�0t�P��j�:�	5=�����������K/^���!�J������&��ekk���{�`)�K�.�$krss���������o�q�$!�Qj��5��/��-//���[���r{��9r$JJJ�g������z��J�R��=�`���b��Y"� 88/��b���k|�"s��\]]��S'�Gsqq1�\�"���6�G��8��o��GW�^C��`�����������({{{L�2�&M��$�!�K5u�T\�v�)��T*���/��q{�����,�T*�N�Ss���_~�	T����C�P(�c����T*�������?����k���R�]
�N�4@��|��W������J�i������(++�I������P�T&����I�U����,��U���Vee��chF����{F����g�F�V��o�>���B�0�����<y2&N��o2�Z�k]x��7Q^^��s��}[�w���.44�����%K���?3���>|�S"W�K�.�9s���H��+����}{���kzGi����m�2spY����1�/_����fd�9��M�f�_uyxx�S�NHHH����]9v�X��yR��dh�S_|����k��������d2���c�{cgg���{��-:�$%%�-���<���X�p��_�v-�,Y///����������7y��������+������;�L"�`���zG�>�����a���Q*�HHH`F��yxx,�XS��'��1�/�s�����;�;�$~U*����y��x��Wu���R(��y3��J�B���~g��E^^M�����[M���n�����]�������Z�0s�L�=�����=��������;b�����[�.���0AWWW�7������)Ks��i��ju��
-[������	d�^y��m�QQQ:RZ����8q"�
f��r]�6�n5�6J"����...h��
�t��A�1���qj�����h�"<xL������/^���7����z�g%%%�*�ddd 66�_]+�����@������:�e���1|�p<��S&G�J�R���;���?�9���~�l����GHH���G�T2=�M%qd2����k���b��*�Jddd��q�Ou�$�B���8�cX�	���m����#44�O�6�]������c1t�P����?���

ez�����������4��3�Z�km�J������2��x������3���j��9>��S\�x�v���9<$	|||��[7<m���w1�L&�\.G�f���5/&�,�R=��������'N�
h��'�dJO��A�!!!��U�f����Z�n��;c���;���K���#,,L�9����~��a��i�V����K�.�/���7n0�$	��i�I�&		�>����GII	
���///xyya��e8~�8.\��7	,��0`�L�>]��_�x1�?�3g����%	:w��i���g������<���a�����=:u����`8�h��&,�O��cP_�R)^x����#�|�����������1v�X��"##�A�|���D5�y�%�B����III(,,DEE�����C��!�-%%R�������ddd���*�JH��M�q�6�����*dff���{pvv���B}���QQQGGG899�U�Vf����2ddd���666��������@�1������Fqq1���U������ ??��+������w�B�P���...�����BNN����P(����j�
-Z��I�����������"H$4i��;w����RHIIAQQ���`ccggg4i�m��5�pm�233������R����e��5*'f.�B���/c����&�n��	GGG�#�������;>�*���{2		�$�@��jAX���������.�ZV]��m?��bEAYpXiJG,T��PB(!�$�03�?����;i�$�z>>9e���{g�y�s�Qedd(??_������T��-�,p��>W���+�����05o����G'O�TZZ��;���d���N�<�#G����
PTT����������t�f�)""B����|�8�N���)++K%%%


Uxx��7o^�^,u�T�N����>j��=���2�B���0��j��4%!�q�8��*�p�B��1��g���t�T}:��8W����p	���n4�K���
B�{����u���5���������
6�����/��gC>���|DBB��v�j�����8k��8��8W$''+77�Z]c�����
���!�=q�,���8>���� BD���q|!�"��A�8>��Z�UZZj����'������8�N9���
���\.�<y�(��v��q�!`E�p>|��N�$��k��m��f�����=[_|��Q������� ����ri��}
V������:p���v�����M@�����#�<b����.]~��=�_QQ�6o��]�v)77W.�KAAA���T�����S'[vV***����{�n�X�����eKu��M������W�m����@%%%Y��Tff�


���%((HM�65�effj��
:p�����������P%$$�c������VZZ��~�I���SVV����;�m����l���Q�C��������u�Vk�///O;v�P�.]hm���g����g�QLL���gm�Pnn��z�)k��I�f���r�4o�<��3G����f��nW�>}t��w����c�5k�
����f(8P��
;/g+�[�No���RRR���Z�������f�k�iINN�s�='�����?�?� ��e�Y�f��K�.�����f��Y�+�p�B}�����W_~��bcc����U�����3��r��W_����*I�������Xz����R�=Z�w����c�4j����Yb���������g���b������RAA�>lm�[�Cc����i�*
p������;k�}s�\7n��M�V�@�[ii����[�����%<�{������+8�fG��?��O�Y����s�\��i��}�Y�_������r��w��|P�yu��!�5J���������0�,������Q3'N�������f�g	w�#Ik��U�V�<Z+���??����;�����i�L���fSrr�qm=zT��mSnn�$�{��g������k���F�f��k��j����N�v���]�v���o��34t�P��\����7�|S�����s��	���e�m6�:w����5h�@���
t��	Iea�[o����G�I�&������+�Z��(������.R||�
�~�z=zTRY�����WM�6U��m���	������7��


RHH��������M���8Kx�8�����a�<Z�WZZ�-[����T�����p~:t��,X`�������O�C�����n��o��F��Lmg�������(��v�����:�U�Vi�����k,��7�x�W�u��I�;V�����zu�w��[n�V�<�����:t�}�����-  @���*))1���k�x�+�/((���c��o�I*���1c����~S?��{�j���F9..NO=��)������)S�h�����f�}��G����m�9BCCu�����O?��n�w�qZ���������Z���8�Y�3�9|��������D��~��W�����p.�����B�n��6�PC*����cGu����t�HKKS^^�Q���_����wom��Y+V��$i��=j������e��)��}����EDD(""�Z]�
x19r�&N��#G�������n�vQHH�x����7�\���_�r�d��,���?����'�x�k���n����u�����C��k�.���*))�������(%%�Z}������;�T�L���\���p8�U8����K:��[��T.�/��b*���1���J:kg�TGvv��\Y�k
l��=�|���Z�l�����|PO=�T��[tt�����r~~�


<z�9z��i��(..�����v�l�����L��UAA��x�
c:�3q��������SPP�"##f�R-.�K��������fS�F�e�/^�X����|�I{<�b���:r�����������|;''G���r:�


Utt���O��G�����,���(  @�7��1����T999����������n�V-N�S��SNN������I��ZZ��Y���g��!�jk�SXX�C�U8�VN�8�#G����T������:�sG*{�333������P5i����H��x�;���"���(**JAAA�n��6�/++K���r�\
		QLLL��wyyy:z��)]�}�)33S���


U��M�|�������f;����VRR�C����H
6T\\\����5�l���9���g���Rvv��?���REFF*::���"U��e�>��k�9�:�y�
Le����<�W���}���V]�vUhh����%���t�s:�z���u��ak������C����1���E=��#�?�-Zd�X������G]w�u����36����1�5j�H}��U�V�4u�T9�5JO?�t��iii�9s�6l����R�>$$D\p����z�h����+**�����j�*edd����m[
8P=z��p�l����;w�l6�F����hi��Z�r�i6��fS���u��7W{�"������N?����o�n:nIj����w���q��������i��YZ�z�i����@]r�%���[���3��'==]���j����IR��7��V*[R�tC�={�����2���w�6l�/��B[�l1�&T��u�5��s��F}yF�a,���o_�|�������_~��+W�������o�a��\.�V�\��K�j�����G~~~JLLTJJ�.��rz<�wuu|��s�N-[�L�6m�z�v�Z�l�����o���:K�.��Y���+������]�Vs��Qjj�Go���.w?�����6n��o��F[�l1-Y�������.��}f4l�����W�3�L���_5{�lm���t��v�m�V��wW������j���l6�q-,Y�DW^ye����m�L�3�����M��l�2����F��.�@�]v���mkj�����5n�8�uLNN����f<���;f�������H��26l0~V��-o,��nW�V��i�&I�����[�j����j��#���`���G}d�9�������Wk�,���Cnn����������y
��<xP�f���E�����k���.�m������2�����5{�lS]DDD��7n���~[��kZ�j���Y�A�i��a��.�lp�?��O�����X[�l��-[��M���0� r+((0^�E���+���/�X���.�K��m�K/��{�������~�M&L�t�iw�1g�]u�U���;�]��m����[�R1��������a�=��Sj����K��h�k����������g������w����S����p�B���/������Z�~���_�=z�o�����n���FP�������W_-�=8p��J���;vl�����Tjj�RSS5o�<=��#^�GIus|EEE7n�i����ph�����{��,Y��\����n��fLx>G�������6�wW������v�����j���Z�r��IR��[�j��]�gB������?��K�j���=|���3��_X�%��7��m��m�����j��q����H]t�E����%�-�5v�X=��c� 3##�t~v����������,��������k�������y����X�N�8�7�x���4i�G}TO?������������6m��;�w��}���Z���o��uv+((PAAA��Sm+)))����zSHe�-[��[o�U
6$��	�obH��9b����c��JJJ��s���@�G�6�
�)55U����iP$&&F�{�V���������|��J�l;p��������uk�k�N�52�q:��;w��{�=S���� IDAT�5k������cPP���i��;zm��k�.�9�kF����K��[oN�F�������$�=.�KS�L����:�+V��W^1
��l6����c��j�����q�\^w�[����F����d%$$�����5v��r������f��9����p���1{��1~�-?������m[�k��������{��W�
C�JJJ4v�X�=OHHP�v���aC�_�~���������?S�c������N�:�E�������5����2�q|�����/���P�A���4�3F'O�4�Wd��F��:3��5�������R�3�+�i���Z�n�:3�{Lu��/4����k
u|��������P�o�^�[�6����u�����o�]���Fy��������T&L0�]���a�������4=��s^NTT�:t��v��y�����tv����;�����tIe��O<azm�g����/��T��>;=gCU7��~'[g"�-�o��)S�����k��A=�]���DBB�n��vu����s8��u�>��s����������^{�4H�t:5~�x�P��r�n��c0��ph����?���:`U����j����;�������gk���F��U����T� ��={Lwaaa�������b
Z222���aUVV�����#G}�����k�.�h�B��v��u�����I��;�O�<������{�1�����C�&M2���f���_����B0�{3�|����7��S\\���D�~������Q��!������{���c�?~������n�
��3�r���~:tH����(����4H_}�����Q�������A�����7
����h��%�3g�q���m�4c��*_�U�V���T��5�C=dl�^\\��;w�j

���o���n�
7��k����/??__�����+��%���q����7��44�����l���5v�X%%%����������?���>2�tJMM������oB�>��s��������]�vy
���u���k���F922R��v�z��a<���+Vh������3�M�6����~��WIe�c��UJJ���SK�-^��T<x�n��F�u-..������W_�;�.IM�6���>��_�x������s��_�~:~��v��i����[�����|�3���Y�N�t���z-��o�>-^�X����}��W�g���~j��6�M?���7on�u~*--��E��r@@�WX.��Z�d���"�7H�}��C�N�L7�l��I&L��Q5�lOw��}{�u�]�^�.f�T�i��z��M��T6���sg�9R]t�Q����o����g���0������4�n����o7����a,Vd���������ZJHH�C=�����T��g�y�A�r�4a�c�922R�F�R�>}�6�����O<�K/�����m[�3��.���5��u��?l��������{�=�������>|��,&�{���O����.w	O�\r�^|�ES�#I���^3�V�X���~��������^h���z��$�_��xLtt�i�����Jg=�����5l�0���###u�M7��g�1�S����r���T111z����G*��b�{���>3�.����{LC���#?44T��
3]�`�2�u|��w��w��Q�F��K/5�����JII���>k������3~�Lii����?���n2��h��������~��-���&M���_T���M����O�������k��I�����������c�i���^{�)��#���:t��u
�UW]��^{����Srr�^z�%�>ZN�S��-�O?�$��=:t���������G�f^���W�>��W�#��aw�]w�����4PX�j��Z6l�������%KL'�����}�N�8a*[g(W�:��{�����"##����U)..6�,�G}��y
@]���j�c�����k���������4x�l�2�&��w�KewOW��n0��n�j*[U�!����u�UW���R����~0
�w�}��}n��4|�p��������{��p4h�@���������WY�z��9b������������T��������@>v���s�/�������y��JII1��[��=�I�z��iZ�U�gLMU6p*I:t�u�]g�KJJ���*��w�Y� ����L-_��(4�����c��F�������=����			��{��)wy6��-[��CE���w����B�Gy�+`���Mk��^xA���3�;-_�\O<���~�m�	s�����zj����@�'����+W�>S������Gku�:r��V�Ze��5k�������F��s����8q�Q���O����E^^����K�T�~kEEE�re��'kH\��5_�����AAA1bD��O�B���^�z����k���F��.����JJ[�je*;v�T��o��D���v�������5kV�^
�6lh ��m�G�7������l0O�����jKU��s��d~?��g���iS5h�@={�4f�������F���b�L��={J*�[��.����W\a�����<Z�EEE�f�U��~0����l��A��wo�����J���T��2���7~...�Z��<�_~y���R�_����3-���R�l	_���^���i�u�l�v���z��'5s��
������p��q��������z��75{�lcV``����c��HOO�3�<SnY_V�^m�!b����
�����1c����m�r��<�}��'*,,4����o�ty��R����b����W���|P			�^���o;@�u��A��-3�{��1�	��L�
�K���aaaJNN6fedd(77W��1n��7��[�w�[�h;U���=�W9y��i����[{��Q��{�xp���}�*]��m�����+����m�ALDD������f����]�[�lQII��� �=�!11Q�6m�tfB���(5n��K�zm���� ��-[�����UXXX���zM���x
���S=>����;wj���:p������r���iS������e����cy���w�Sn�����9�J��		�_��k��f��o�����K��?����6���C_|���9���������&���k��������>��C�4x��j����O�a������G}TM�4��!C4e�c����c?��/��xLM��x=P???]r�%�����Tc��1n����c�=vZ�������L{�Y�v�m�����7�B���x]{��=��3X��XU����Q\��|]��G��1�(�r�-�=@] �8M������L��"77W'N������:��n�T�V�L��;vL���4-��v��r�V�������'�u���d�gxu��Q�����Ju� ��]�����%���N�W��r�L��<g.����q��[g�8������g���qx>v���r:�^�a]���7B����\.��������K�eff��'��h�>�A5Q��[�r�f��U�e��������U���]��z��vF�Js:��^[^AAy�������^�zi��u�6m�i��w�}��m�j���:55y��Z���w���S���r��r��o���%K��O
4Hqqq��x��{�.\h���s��\LL�F������>2>��N����$�n��x�����z^���5;�����'�h``��x��Z�~���7���?����6�DQQ���}�l��t�=�T��n}?�7
T�=c������R_���}���{����{��ti\�B��������3��mk���r���?���.3�=�����ru����l���|IeK������J{N��9�����8t��)��\�G��2e��v�����,5j�������C�!Nqq�����}9����t�����`����<���8��:���b�7��Ie�aaa���Wnnn�f�U������������5�{6��l����.��M�0�t}��W�����
����W^���M�4���)))��%K�t�R���G��zk�a��3�Ah???=��C^�]R��������'K*��O���������[��)��������4��_�~:~��i��'��477����Y�*��:[M�6�tI�����C����Nu�{��?BBBLe_����7�x��WJJJ��Ozz���c�=zT�%28Uu������e�z���O>��������sg��q�9���g����*7f�.��s�|�$��K.Q�.]Lu�Q��am��>���o�Jtt����o�6�7��sI'������K�.��a�\.���[��m����K�Ie��kjjj��8���Z>UN��t�$$$��+���Q}��7�V�2��x��N�^�u�rfqqq<x�.��"���J*�[}��E�����~��.�{�%��5���W��et����@=��C�����}�$�����s���kg�]=��\{���N�:i��yZ�`�1���ri����i��x�	���'N�fcv��������.��%K���*�li����*��������4����M������~j�[�p�iFRe�l�b��������\|���~�X��>m��MK�,1����[=z��:����]E<�����Z��>^�)S�����<�=��G���/�����w���P}5�k���S������0�t�M�6m������{N7�p�:t� ������k��Y��s���z-3VS������=`���y������Y�cu�9�e��7����k���g���'P�^��}.��]k���s)5�l05!!���e��=����yn��*��S]~~~
6�����3zWv|���38=z���>�|����x��*�k�6�{��7����b��O���.������Z'N4����j���s


���Cu���k��y�?�������W_����n���NtKNN6~.�{�;��������z��k�������^�����Ko���h�������;�������!bu���\��q��^�����x]�NP�qN�u����hS��k�UVV����[IeA��l��i����:��������1��4Lua���n_�k}>�q<g��u����]�c�eeem={���Y�E����y�uU+KR5j�����3u���s�\Z�`��_n�S�����\����H999^����s)B���G����`
2D�������n|>���k�������%y�h`
��c�-Z� ��<�����QQQ8p���R��������S�N���S;�|�����.�������G�������C������=n�N����t�Y�/��w�t�����MA}JJ�6lX�`����&�����ll6����%''����W^^���-::Z��v�i���s�N��-Z�,������7�~��7c�r_��M��������[�����������4���B��
�[�n�����r��;������EIj������}��p8N�n�S���a
��[>�&�������<���*))����Uv|�6�
8����uq��l�����o������g?����kK�������k���^J7n4B����F��T��4��h���)���5�����Z]����!N���O��g���wk���F900P����Q���$#�q�\��qc�7��������\�������:kU��-[f
q���M�z��f��������?�h�7n���x�e~��'��1Cyyy
P||�:w��>}�h��!z��g���o�z��}�v#�����t�E??~\��/���Gx�
����+Vx������L���8R��jV=z�(w���w����f��5��(���=���$��;�T�/��uCo�L��T��}��M��z�g;kX&��������{<?7������/�ry~��gS�t�.�	������E�C'N4-�w��7��9����V�w��e�����[7�VPB�*--�{��g�T��+��8�?��������������o��g��<�?���������N�O3��)**��)S�������2�
2��3m�4�r'�\���]s�5��"�|�I��cu��:�1T�\t�E�}I$U&&&��Q�}/�����h�"�Zn�T��u3�0Z�f�i��"999���tTu|�K�I�e�JKKM����jKm_�;vTll�Q��cG������I[�l������&�������f;#�7n�V�x�����)..N���Fy������Z�J����Q���<�%�jC���g���YS��1##C%%%�jx�5k���o��������s��fy�_��+�t��}������_���eNm��<�o�>��?����]�v�����~��7��i�����+<z��={�����Z�j���Reff���~��%K4m�4M�4I}��/^\�@����K5g�ccaO�7o���?�}��u���������M7�d������/h�����Dyyy������c�i�����:��qc��&���p��r�:������g��rp��y��l�
RM�+*ZJM*����1���/���3���STT���g��7�0��:th�-'f��t��w�����'��O>��D*D�.]���~Z����6��t�/66�4#��o�)wY��G����_�=r���|:j����l����Mu��O����_�1�����w��V�����y��3F?����|),,���K��������YZ�8��^{M/������r�4{�l�R����O�>���I�4w�\S�q��	��1C�����Y��7�2�����������$iAA����+=��3�
{�W���7�&q������]�5k�T��g�'�-�g�1����2-��p8�r�J���k��c�
t���}@�j��1�9��p���?���3��C������@������4�
����7����{'>|X#F���z��l��������r�[II�>��S��3G]�tQ�
t��q����k��[�n<x����������r�JIe��'O������];EDD���X�VZZ�����S��K/y�<�C����{�a�Ie���>���~�6m��Q�Fr:�:p��)��3g�|�A�|��<�&M�Tz>���Kk���T�Rjn���FXX[3qv���'�|RIIIj����N��;���w{�m�\r�����j������nM�4I.�K.�K��������M5n�X.��xN��f����}�z-9eU�w�
7��>�$egg���SJJ�bcc�t:�g����/:y��u��I#TY�r��@�����>%%E�����U���%K�h���j���bcc������9w�����]�vI*[����~�T6��n�+//�kY��-[j��a�������}�v����j�����m+����{�{Ie�!W_}�Q����U�V������i����_*..N�C^!^����~W}����n��}��gF���~�E�)))IM�4�����=�;v�}��y8p`���u�p:��8q���)U��sKNN�ZB���n��M��&
5z�h5j�Haaa:z��N�8az����Oy�6�w�8��lr�\*((���Shh�{�1�;������9s�X�+�r��|�regg�����6K*��=@RXX��k�Z�.��R�{���.�v����Q�F��YPP`���*22R���^�f�???=������L�Ly���)--M����KKK3~�h)5�n���a��:q�D�K��%&&��������}����V:H��wo�����Z��5l�P&L0B���Rm����������rg�Y���]q���c�V�^-���]�t��W��=b��Z��h��e��O�^�Bm_����r*z�������a��o}n���[�$��Xx���MK���s=z�h��6m6����?{}���k��z��7���e����T��^������f��������S�a�����]������@j������6�|����Z}Z�����3���W^1�|���Vvv�G��g�����T�F�P��-[*%%E,��y#I�5R���5x�`���X�
C�Udd�V�\���9�NEDD�Y�fj���bbbT\\�h��u��������?���/��F��;�P���5t(-� IDATk�,-_�\����v�����d
<������l6��OR�=4c�m����n]�l �K�.�����63�kv�]w�}�����Y�fi��-�>G%''��K/UJJ�i�gJii�i���'  @��w�����5�k���h�\ZZ�}��)))����6l��m���7z��o����}{�p�
����������S�����Y��z��r�ST���wo����Z�Hm��f��>�-Zh��Y^�QHH�z����o�Y���j�������n�:Ie��jSm_�v�]>��z����3gz7RYt��W�g��������u��oTTT�/^l
L����t��W��K/���T_���i��Z�fM��M��u��7�}���fIe���+�h��������fl�%&&����R��}���b5`�u��U3g���u����m6�Z�h���
0������u����_~Ys�����K�=?������|������m���.Ij����
����ERR�^z�%IeK�8p@EEE


ULL��5k���Z�w�^�9���x�����{���+W�����a�����={t��1���)""B-Z�8������������\�\.���)**J���>3�Q\\���4������T������R�f���~��t��!eeeU:�^[�o��^x�(�1B^x�q�dgg���_aaaj������=]?�N�������������*<<\��7�����+))��;������`EFF*11��A���,���O�
ek������,<xP���
T�&M_��U���������H
6Tdd�Z�n]���T%33S���*((��fSDD�O9��������UXX(???�\�v�N�S{��UVV�������p�h����a�������TAA�������hk7��j�*����F��7�T\\�G��;vHb&@�4m�TM�6�V����D%%%�Y�#)oO����m�V9��T�g*�����
�8?_���*66�Z]�|�����S�V���U+kS����5h���w�GEEU�gOm��cs���]������k�)���;��������t�3Qw�5kV'7������2���6/�:���+�r����k�CCC=Zp���?�$������J��i�������y��k�.��vu��IW_}��]+�w�^-X�@TXX�z��Q�Z�?���V�X���\5i�D����]�v��������M^JKK5k�,
2��p��������j����R�RW%%%���t��a��.�N8��8qB����:d���������!NVV�F����,%$$������e���[���^
4�>�������oH��7o��~�M?���v��������7c�}���


Utt���Y�U�V���2���}�v�������k��L�<Y���'����ph��	:y���o��Q�F�Y�f������@���k�������LM'$$����g��mJOOWNN�������7���F{xx����:�G�[j�L�2E������C'N���+�x�b
4������?^����������+??_/���/^��e��JMM�W_}��;j��
TZZ�^x�M�:U��wW@@����G,X�����We���Z�r%K��:�o�>9r�T������tS�U\\��q����E�i��5�jIRpp��z�)�R����s��Q����������.v�]��z�����n�:�#����������_���K*[���o�$�]�V��`��\.�~���2m-[�T�~�����m��I*���/��?��ft6l�������&))Io������Hk����@]w�u5j��4ibm�i���W���5z�h%%%Y��)5���y�fIR��]M�������{M����i�$�[�n��:H*�+G*���-[z����o��j���������������{L����0a���UFF��y��j�J���*((�v����8������[Zk&<<\C���7���;wj������rss�p8���X�i�F]t�������9AAA���s�.�s���|�N�:o%&&�[�n
		�v�'�(�q/�ki�"##u��A���W�D��w4m��T.���c�����P999j�����$5j�H�t��1Ie�o���� �X�������B�=ZAAAz������/[��������U��n��C��M+��,11Q/������q��/��p��Q���;�a����A������JC���B����l6�4h���bJ*��q�_\\,���*N�S���Svv�F�Y�eM��c�k`R���T�F{��l6k���tJ�\.�����Ng��w�W�����?����u���������/������	7NU�f�x���*))�T��te4h��'O��p�n��N�S'O�TPPP������������������.S�V�t��QI���������GQ�Y=�������������{z��==����{xO�=�����s�������B����8�%����,-Rvv�6lX�RjR��6������VLL�Q���#���&M�(,,L�����7����%I�7��T����$i��eZ�l��Uz��G4b�]x���&�zU�'>>^��{�n�����/((��#G��sg��"qqq��e�v��m
q���#Ij���l6��6m��*//O������������*I��~���|��oS�V�����F{�$''���Ok����'������r�W�^F]aa�����]����d=�1�/��fS��=%I]�t���2�+,,��5ksJ!N�����/((H�������"""��w5���h���5j�������t-Y�D			���K��������3e������GQQQ���/�X			��i��~�m%''k��
��i����XI��W_�e����/�TAA�"##�l�2�������_�r(�V�G�������i��e�:u�$�c��z�������MHH��fSLL�BBB�z???=��S�4i���[��k��n�k�����;�~M�4��O?���'k�������`�y��������\R����_��_4l�0;vL�������v����k�N!!!
4�EEE����R~~�rss��
��HR���5z�h;vL%%%���Q@@����o��������B�����
���q�����xk��{	�����*44�Z�%::�ZpNbCD���q|!�"��A�8>���� BD���q|!�"��A�8>���� BD���q|!�"��A�8>���� BD���q|!�"��A�8>���� BD���q|!�"��A�8>���� BD���q|!�"��A�8>���� BD���q|!�"��A�8>���� BD���q|!�"��A�8>���� BD���q|!�"��A�8>���� BD���q|���@���v\��gkV�.��"��Va��U�������!�M��������1�_@�q�8^���UZ��g��)<���:I:VP����h��=;(Q���.���H�,���9:�U,�����@�j�92�%�;�����=7{�����l�F<��(u����}�#Gr�^��P��m�����N8���
�gm��g��w�K#g��w��NmZ�#��~5�A�X�����g[�kU���c���j�8���cEZ�z�Z]'�NZ�0�����V�����*�8�����Uu",���@��!��D��ZU'��4�Z�	!���w��qU����g�z�$�wclcL3:	-�H�	!�i7.��R���Z���������P�
�nlY�-��eui���y!k���4*��h�������Hc��g����,
3]����7>S�O����C�XP�e%���H4�����L�np�#�1C`�dA�^���6��:Li�G?�l���k����#I��Y4B��:�zzC��6v�e8���q�����6���9������]#`����gN*��]mO��Mw���*����b�;�O��V�����so:�}���j�)2�������E��1N
��o�C1�t��<��c�������4�CW,]���I��;-;�G'���oW���)��k�4���f�����aEZ�$�[����.�\��'�>d�;Bz|���z��,����#Qq�[�&f�4�cyD��63O�mjPu�_�������')�	:��E��`����&E�����u��C
U
lyI��)����H��o��y��:�IR���/�>^Y^�m��8�>qb�~�����M���X�7�
�n�����j����/�$b��J����d���������o��/;n��p�-(����������*2�@��������_7I�g��*���R`�J[r`LI�-m��SM�_�������zt�����C����K���F�^�+��qj1�=���d�[����s��~YS��������=%I��	%r:��i5S��t��\���Y�����tj��.>c��.#&�g�=4 ��MR��"Lo�S��T�[_������qj�����#��%�r;��D������`�8�Q���1�m�����=��3��fW�=���5����*�r��y��S��3l�8�Q���q�����p��H���{U��?����=zi[���X�h�.Y8FY^�$�3�����s(�`��g�"���3�']�k���_������r��jk+[��p��(�:��H��8t��1���[U����]\�0\��"9Kf(��=�/�����y\�Y8I���@������nw�=�PM��r��������k
*1��������G!:q0""��j��s�.��&\�[-�|^�
����7��v`��
�Ch �NCW.)����j���N����"�]h�{j���
Uo�������j}��8�����W���3~c�"���&I����������� ��y��%8Z1N
�*�q����})����_�����H{��;_W��?�$e��2���#��rNR�c��I}d��Vu��S��|O-!m�n����I���G�h�t��b�������{��}�O�J3l;G��?��T�k������p�ne^�Ce^�]���#�D���E���T�(}���~��%�Kf(��JLp�������L��a��e3r5uL�=|�,����������|��"�N$�������)�o��[^��o���|+~-����n52����;�]t��$i�o%i��LSN�������B{��2$]y|�l���}�R��8�0N
C"��=���&�V*�P�m��2���,������{���}��,(������c%d�eK���y^9���<'������9�j��L�������7��z�N��'����y5o\�������*�����������;�t:5o�<�w�y�z���{�n�X�B555����	'��e���0�oN�y����+jnnVqq��:�,��5+n����;����E���w����+Wj���JOOWYY��;�<�����@���������d^$1;��
8��Y�����x��k���v�<��=i�$)�����9z}g�mG�N��;����p��1��S]E���~����h.7����2VK&gGc��5�qj


������O���MUUUz���t��7+���h���������_]�`P[�l��������/n�?����W����[����z�j�|��Z�zu��n��o���sUVV��7l����z���������=����7���������Hc�|�������d�r>��Ap$��7V����]�1�0����h�SKK����l�YQ�[W,��5n{�;������~�r�X+�R��;q���>566�;���-Z�p8����K����V�\�.����8�@@��~�222t��7k��1jkk��~�#�\�R��/����UQQ��{Ls���w��y�^UVV���n�����%K���vK�L���+��(<tX�E0TQQ����oh��I���+W��{��C=�o��������e{/<X���t{x@2/�^�]ke�7�S1�)#=G�O�T�����aeO?I_;�L�{q��:��GH���=����Js��NHu�__��@cHzzC��ei����u�T4�����:���;:�������N����*9�]���������jjj��_�1c�H����t�e�I���Y#IZ�b�L���>�������'���OWKK��m�&I����M7�����/���UO/^�_����$�|�������h�dF���=��H���m�����S���$��c��8fG��v*��y���:�=�]��
��	��"�Is���������:���>���Y�P��tg�c\�z���q�FI������Uii�v�����
$I,����=[R�Y9R����M�<��K�5k���y���[���W[[�<�o}�[��|���;��ws����---���;��5���[��Z7���)�����_��[_R��EZj{.������z����������I��Ns�v$����"�T�f������g{�)@�T'Nuu�$������������������k�����srrd�����������������$���K�*�������%K������3��@�'���(�iY���8]c�>�;y^�{G���l�
�#�$y]�2=W9�#_�������h�9L]��#��cP�8��������GMx<]�������������v�c�<��~�|>����O�98~�_R��������>���4�}����������F9^���k�zxMS���cDB��(�������C����*��k]t����;aD�*x��~����X��Q ������y�=i�0�������n���|������k�zxMS�)G�Au�	>��t}��4�y���H$�����}�K��TKK�.��2eg>�s6T(���W��$����x2����R-#��!�D��G����s��c����v$dz��4���C*�H�?`h
���mct}�0--������ IDAT��x
���t:��H$�P(�������;�������[���/j���:������9s�=�Q��N�����4����^��'\W�� ���G���)�����_����?'B�m�:�0���px%I�.��f���"�+[$��9���@���f�=����j�����G���^���k�zxMSU��T'N^^�$�����:���Q���	G�I]g��������xSS�L�Tqq�����r����Xu?n��1�L������.I�����"����_?P�5n��?��~p��Sl�h�e����C[�"��+���C�%P������>0���3n�8IRyyy\���]������=;v������]�$I��O�a*))�������J���z���U[[�s�9gP�8���Th�F{�W�������,�fO
	G�x9'����
�=�w��Rx�6�/��O�^h��<���gM�����]y.}������V0���o��9r8Z�z�:::���+W�4M�t�I�����#�<�5k�Dc�t�1�H�V�Z_�r����'�(I�?�L�������z�j
��s�N=���*((��?�q{}V�m%	J�AM���P����^H�Z�9���k�M��"�#z;����������#�|>����}�D}����;.S9�.y-����������6�����-_�\+W����c�v�i�����/����2-[�,������?��O��[o�U�������L6l��~�;��3G�����
�|�r���J��;�<�Z�J�>���������U�V���Y�]w�����B�����N��)���;��#.?q�D]v�eq1�3�����%�k����{�2y��\��S�3K?/����]�;�LI?z�B7�?Is�e��I��t��\�<-W����k����5��&���u��H]�*�H�g>�9�Z�J���$i������k�r��lYY��PQQ�23c7��C�_����n�]�Vk���������u��WG���n����'=��S����]}��:��S�����g�Uuu�$i��}��o_\�����p8G���bqd
�����n�k�<��Fs��nS����r�4����������Rq�GZ��!���re��pb�.]4F���~[Hb���s�\���k��O|B������P^^�}��.]��3g*33S^o��

t������M���*((Pzzz�I�5k�~��_���^�@@EEEr���mQ��v�N;�4{X_|�.��b{���T/����{Z���#�0�o�yzg�.���I��5��6��c���4X�PD��fm��#I2��mA����7�[��ecu���X�>���^����c�[AA�a���,�?���Uaa�������#�5i��3����/���W���MR��n�Uu�Of�}@/m�}�]�?��^�R��N{
0�}�"�2���K�'#-���g8�����d�3GL�/d%��������>=���>L���~�F�H�W���"��[��/�'=��������=e�=uDey��PB�i��.<,^������=
����3 �$�]+�V�j�dF�.�<���#3O�I���9N�s�G��(I<��nN��u	
F��{(�����iF)�8��OF���}D��]����.���~���U���s���I�:T$����$���_	D��|'��.����U;���O--U~fr��8�c%T�3����F�_�T��Y4Y���,��WY���[��^]�[�Sg���Ig��l{�Wn����a�(FcF��8�E�H�a�0���h��j;P-��<�$v��M����=�|q�r����00q0 �=i��Zy\�a����J���Qh�{�p�q;
}�����:��8������$��>������ox&z��v�9����k������N�m���lrQ�~v�4-���h�3g����&���n(��������Bt�9�|Krd���Ma�Mlb�B��+�p��JJ��.}��2��c�u��5�0-�Ks;Fz�����~�Z+���k���3���
#��%`%d���m���5+�k�=����=:ez�����m��n�H%q��P@�������h�3��L����v�
%S��$I��+l��a����}O}���aK�*\����5����
l~Af�#.���,n=R&YF���������:�m�2������MI�$����}!����k���s����8�Q�|��n�\�w�8��#I/��`�[����;.Scs=�p��^2U��+I2;�,��#���sw�R��%)�"ioP�#7�lo���"�
j�d����a�r����e�c����4ob��3O���^��=��8����"�{��2}���a"�
����=<����K���������Ss�����$�1�D�����P �-f�fD����j�Y��T��].�Jf������p��V����a�lz�.�_3iFq����	���	Jww��u�X&��u���oWp���F����3cG\n��H5H5q'�P5��3�W�q�=<"v��^�?�P�n�~p��0%��K2<�r�\]6�h�����cc#���c���8�gF���E��!�q���eYr$8'�3���u`���x�V��>�H�>���6�Z���RMl� �QP&9�R$lO�����`�=:���:��$�������1=qN���f�2C��x�����P�)�V��_����?(��{��89����TA'��Lyf�a��3w�O���p�R���]�)���6����j��j��*��1#�|�~��}uR�����@j����d\�_2��Q]�1�s�q������R��;���n:���������������{8�p.�6�88�#�D���(a!�H�R�e?�#���6�:t�����G�����2�4��+^��(�Pe�����&�9����"z��}�����=,9��9S�_}T�Y����"6���Z���
���Y��������~�i���u���=�;3����������8������Ux������LYW�D��2���]���kj����v����N�����������7��?n��pS�=�T�s<*�t��=(��\����vF#:q��`����g�r�&3��m�}zaK�$������a������e%�H�������n����A=�|;�tO[jI��g6��C�Z[������n��c��}qM\h%��8[8RE�(�w��@�$�py�����cd��`E��k�����q��RWKb���r�-��������uM�_-�aK0ZQ�@��;��^�&/���X�#����@a��,���3�$�L\�qy���J���<6����?��3R
RA���`D�cE�d�fH*�r��	��?��k�~�u����$y����3��JJ�����sq�
�[	��(��0��Y��-��{�I���Z41������\�y1Q��O��r�����_.g�4�X�=q��S�X���E���(�@*����+��LS���*��x�m�����"ey��p��\2Fi����:��)���*���(���D���w��������ccE�����"�,`4���G�`����k������������g����)���s����rM:.z�����Pu�i4(�OS����)��Z�q`������,E��-��p���t�����)��>��X��?Q�>
=V�7S�	�F����-��g�,��8��-Y�hDq"M5
7����SO�d���1��Q+Z�(��N��~|�.YX$�@*8�X�����U��������N�(� Np�����h�9%�lr�8���hA���������s��5eq�:��]��m��}�dg-�T��?��80�Q�@�y8�i���#IM���������tKvp�e�q�\�`��o�J��{����"m����gRa���]o��S;jGO
p8�8�1M�v�]��&�y8�v��
�.�g�G��;W���OHf8>
(��5��
w���%�����H5�����"��u�io�Z�������DvYF�M���p"m�j{�F��f{*��5���c?�$e���sq`T�������Y:KFz�%�\�tF��}�"����$,�t3}��=�k{8���qv�P0lZ����"�B�"�{�K&���*���t(�e�=�����2��R��:&]n�!I
����`t�`���:"+��.�S��$�K]k@m���5S��,���4VI��=��P@��*9K��3I��44mL����m�/������o�+��k{�:���(*�+-������>���	����"$I���ev�v-�&%�y8u�N���2�NKv8$����c3�E���}���!�n��zl�mj�����%u�h��h�����_�'|L��(�� I
�Z�v��'��i�&�]u�Qj����$G�����{��t=&��.��v���T��W(2t��M���_��_��p��e�������F��}���q I
V��^��$�(5I�e=�h���H��I�g���p�<�����`��H+�rI]�����������n��o�WG0�y�|�V=����������a�o/��}�{d&y$��@���+�����c�R���8�)c>xA%��o*��u���T##W�~�N*k*Zt�+5�M|�F���������5AS�s{k�J�v6��=r�J��������\#�'�']����'|LKf�f��N(�o�L{��������
Id_�_���II�?�85Ird*���H������e]�c9�
���Q���/WG>=�o�/%�#I�L�#!{X�[����2�>7��oS�������o�g��~��/�����0t�@��������$���]�.�qy^����sI��(�������������r������X���}
��Yv�5������'���M�zu�sZ�����o�������i���ZPz���tuVt1����`��u��]���~�~�d���p���+��^��,�d���:�y8�	�Gv����E��]���j���2�A)Q��6��8���6U������&]uB��C5���z����Z_�:n_mc����w��:��T��/.��pE���������/��2��)�@��.	�hg?g�K2��q>�(���L9���k��h��3JFU����h����k\�)S�>��C��;g�}
z�����r�=�Pgk�:����z����a8�Q�8����p�S��c���EC��c��|\�:X��E3q�K���j����k��
8��PGKP~��g����-��6�X�����z���e������	E��\\���I}Nu�_�pW���04���t�tsM�qB{�K��%�\&�{�����N�����a��[��C���.�N�p�����D�H(�����w3%=���z��G�)8jQ�8��*c���&'�y8�.��|����G
W�|��u���oW�f�mG�(�tk�����S��������;�Rg 6��?����������'�S�������7+xW��^��j��a8*Q�8��w�]����Sq�z���2�ir��]����d������Wa�0�������O�H������?�WnZ��p�M���Usm�Z�;5=g�ff���'])�<���K ��K���������B���ev�t-�\�oH2�N�)EGv�Z7��E
�� I
�~W:�S���4��/�:N���O�P�]0�.}���z��?��������e�$C�&�V����u_�%��8o��x�'��@��l����D'�Q,Xa�6n�o��q
�`���Kg:q$�=iQ�:��]����1#��������j��l9lM9in���_����l})>�O�c4}�<{�0�]�9c?���c�3�(��B��E���<��F������ihB������v'��&�Uf���=��������j������kj���v��q�d�g��n����6������C�L^bO���p������N�w_HM��5����,��c=�� M.{��d��D�[��
5�r����"m��]�eOC�nz�R��=�y��<[��J��w4�4�CZ2�T{�W�}�����S�hO%�e�:��o/����A�|�T@�(n�W���
KFc�/S��<�P�;j��
����
�&
lxV��^���W�sI 1u��5��|.N7�5V�����=�t��u�q����d��G����\p�=���[^�7o��vTo����@�(e��qO���6IFu�N��8��hV��7$��1;Z���wi9`O����oRe}�F�93���=���h��Z2�L{x@>{��T6f�=����f�����Q��"�Q*n������	�M����2�8��oMX��fv��������nw�=������c7=��o-h����iJ�9��e�{��u�Kk�I�O�G��)��?4N�7S?��_��S����:V�����7�j@���RFp���u��R����p��$�����ym;�X8������^��[�v{x�4�����g�=$�a�S3���c�QZ�=�7��#5�.5��Z��:wI����S���%����_&����'�_�����.]v�=������6�"�8G�H�AE��kW�q*�b��&���0,��i�������DT��GGL�{�o�#�Qu�����O)���n�����x��������ar2���Yh'��a�=)�e �YG�9����Sb�&�]��<uu��V3���~m��P��I���V�7���-�+�Dg���_#��d���8��J��:��W��(�EL�B�����#��k�B���Ta)�L-:�EgN�O��@|�J�Ir��{�=3b����[�]�2�5r��53*u��:{z������
/�g�L;�Jhr�L{R��,`T
���N5��r����
U�M�-u�+V��@(��Ft=�(��=B\y��c����<�NU�#��1%9}���tW�R������CS�����=r��cgk��9�p�F�e�ei�����K
�"@�3��j��ju��S
�i+�R�mU�u�?�v�w�<�{{���qy�3V+��o��Y`��f*�����w��]ub�����2���j�E�_��&e��Z����2��K������t��omY���?����[Mm��=��(��8��Wx�6{8N��Z�'�h�$��:���R�&G�5�!gd�)���������o�2/�I��R{j��t��B�r�4�5'_��3nBM����VaZ .>$�&�#=�X<]_��G�L���z�v�����>�_��"�(�����������H`��
�x�q��p��(5�������]x�����O�r���<s����Mi�G�=e�n��|9#5��	cZ�����seo�����g���>���.QVZ�=���������aH9qRX`�K�PB�-/�C#������n�#3_�����^R�������N2�t(�]�RXm��MK�����{��U�k/��.X�q{�W�o~^�����R�@
�Q,\��J(�x�?���j�����1�_��fx2��~�Y��:�%T�Q�Y��v&�`8�u;^��U�����~�"��r����98�$����_�����^i����I����gw�����k������ eP�Ha�{���\^{dD���<t����v�4g�;��[� IDAT_C��c��J�����E��5����oR�����#]�����qBtO��[CZU[�3O�/���R`W<�$�S�w�4��R����[��MR�MJ�"�OS���X5��� �0N
 ������r��c��]q�����v{������P�&K&9����n�����$w���L�p$i��,>�����Ks���F�x��q���z��ri��$W���[�����A�WI;�"�1Fz�di����3���k~~������|{R
E���w���<{�G��#��K������W����Q2#���j�l�O�T��9��rd��t��[.�7-�v�2U�#���4��Xb�7T����sdHe�-��S�e��Y���f�Ts{��5������g��)U���M>���B ������C��\��x��_��`B|n�UX:q&'I�9n�dt��6��
�m�1r�^��[��b��3����;�UEg?;�J�Qu�]����H�q�t�)�Rl1���|�l��6����?�x�*[`@J�]F#��s�q�7$Go�;�v�5J[z�=1���t�oD�����cx2�,�]��6Z�#���_��d��D��FH��S�N�~FS��g8����f��u=��K��)�o���K3*�6�OC:����k/���^+����4S$%�P�)��d���7��'C�)��~���pLl����t�� y]��z��#�U6_�����8�0����Y����U�#����N�|AE�j�M���4�S�s08^-�MM;T�2<R�9���J��F�
�����B��y�Z\���{�]��������0������r"-��k��s�u�-�l������\�&G5]�&����H�B{��f&�>�KE"����7���W)������&{�F��,���^N����+�f���$c�o|���_9�c�R]�m{�S{g�*k�W �u����5w�"�# ����Uh����k�%R�����$��t�v.�����d�����zm���XI�_�=w�<�H\�n_`����%Ig��L�>��i	
�k�{st���F��|�}�O��������)��&�T�]�� Ph����U6#���=����)E����s��"�����D���a����
{H_�Y�gG���m���g%I?�XY��[�-k�����g/�p�hS�X�M���� Q�8
���/���$����t�mGr�;�u�Y]'['��\��F�����������N��K���t���=���:c?o��.c��sr\�0�D���]�|�_�,�&�8G�(5����3���V�'�4����*���v�<��X�H�jd�8��������u_fdl��5^�~�GF�g������M����ng�����m�V������C�(���v��g�$����p&��q$��d=g��8s&��*�}�Q�r�f�b�4�>)g�=q��G�I���(/�P�
���gl; �P�8
���8�g�$#k'�F�b-�E�j�������p�I�\2#���X���5I2�����N��&M���6)7<R�������okl}�����.��W�R�L�H-qR����p�����A����q�-����)�#�8���/�d�����u��@NG��m-�j�d^�q�=t�Ni���+���K'���5K��H�m2��_�=�����"���*��b�@j����B��_ryr���d�Og0����u�v�H��8��,��7�t����[�p8����P�K�*
�=�r�=<�S"�O�i]���7�����$3�I*-(�������}����B ����3a��������N������Pi��F�
'kW�$�NKfd�nE"aI�����s�/�?��;��T���}�z�G�'$Oi�u�/�� ����,�v\�U���|���y}���;�kH%qR\����?��IN�;������HP�iN��B2��-���������gk\Z�gi�=G��~\�;���#�&_��e�E��;6�.�����j�(�5G�{LK�,W�7S���i��U��@
�����:q���d�S��XW��$�&��<3#m�L�����O�-�]�#lS�����{����|����Jz�I���f�#�y@:a�\�W�31�����|���oJ����`���������y�D���{��	RG�O;��i�S��.�vZ�pIV�N��E��Lr1�x��q���o���7���6e\|�<s�������
�w��>�<�^wM��������I�ij��I�*�,,���F�/H���Gg�����������%I�T�����iL^�,%Ht��0k�#�D��BK6��C�4���)������/����IR��Am��:W���zM��������cW�;)�h�jRa��[9��85��#�k[��9m[�$���q��8),l�6
���]���ce<�Js���D�+�(T��>L��W�~�=<t�����uu�$���v~��dK���C-}|�#��{$!��m��������=-��Xv��G �Y
�m�ZYp��%�$��Vu�r����f��Xu�=<tjn�:+�����Uj[j�G�|A}�o������V�����H�,�~��t���0�ni4�h��wm�`t����L3��3:q*�~�?!���I��uR8$��K�|�=4t��GkxN������j������!��������^�R(��?�PH�j�$�>C�c�`������OZ6��G EEZ�d���Aq��m�&�JK'��@e,�D��z{(!�����s$�����]E�'�;�7��m������Z������6�r{�w�,)�C�7R���/�#���`��������E���22�,���ET����'&i'���c%d�eIN�=<4���Hb�|�o����]�1���UcyM���_�2��-6�g�+W�t������-I�;���n��-/j���2��.I��M�&�����_���{�*(--M&L���K������2�7N���$��Qj��X2�iO}��C�s�D���!I�&-��pt?�>�'/��>�=��a�M�e��=�@��z��Y�~�I3M)l�z��YW,.����#M��i���P�=o������&�?�K��������H��{�=��#��	c��K���e���Q�"`@����������^^�W{������D�{���l��m�������p�����O���^����OL8��E�((�TXF��w�a��]I&��By�\.�[��S�Ir(����3�����{V�B�m\!I*����N�����=�9Y�;CU�����eo�0u�HR�b��-��k����g-"R�.i�g����zwG�]fUu����C�X~�.=�{�E@�ttt��G�+�����a����r/����Siii���z��W�v�Z]}��:�����1�8��p���3!IG�u�������"M5�TC�)�-��\��g����o��1�����z�G��*��gV�6���&��O2�0������)���C�����Y�}�}G���V}wn��_7���$�2��K�k���4k���4$5���)��[n�pB��B����mg�:;;��������;��S�7o�o0�"m�����GG'NG�zb�2�HB�7S9_�G�����.�S��2���=3h?�;q�n/�������1�����H�3%I�r=�
�����C��;A������,����ng��O��3r�:q}z���USS#�4����@ �p8,s�����.����VGG�������]$GV�%�|����b�}e�
K699rJ����)������"�8s�9��3���j�1�kz�n�jm����$����bE���Km�)R�E��?J��#e��O����Qf�I�r���Q����G{u���c���*T]Wi@R��H���Y�?��$����p��P(�p8���F���[�4�!��qFC������.����P�_�'
��g�����f=�we4��k���=����PT�+�����O���^,��4�Z��I3!����-�����c
5� ����#	�{]�%��qh_8�(���y�L�T8V$;d��s��Nyy�-`��k�D�]c���c=grQ�f����b�gJ�:|�\f�#'�co]��^�ZR/�������[�r��8���1ZX�e�I�8t���{������1$��������(9iq	55u��^�1�;���E��GN�:V�q��e�$'{g4�������ZD�
����0H�`�:=�{iH:��.�^��Ha����1nn��g����*�����������"H, ��Q��%�h����hc�W_��%6DTD0��E����.,�.��������9s���,���������y���ew���}�
���77ON�bj��\\>���\�/:=�d�#�u���mf�l�a�qH!�B!B�q�B�):����m�L&�����D���dP�*�Ui��0(��SR�K�����b���;p�+i�c<����C��1u��
<v�
�e�z$���Z��
�����h�>�^������F�_G�ktB��Z���t�����[H!�B!B�q�B�)++�^�����c:BQ,�F�2�
!N��@�@������
=.��#�N��_�f���T����9q�r6�4�uY8��b8�����t�6����kX�Smv,��fv!����N1/0������8*��?fB!�B�������rss����)(( &&�	&0u������i_�5UUU���2c�.
��zY�r%[�l��r��O.��R��[o���7����EZZh��B���l6c��p�\�l6��������z����(�3��CC?;@�p�=�W;�d��[=�r��4Ul�[Ld��i�6|h���������ry��=n�0v���R������������|����5uN/����J=�?K#>�oc���R���^De�V�����8%�B!�!��[�;h���<����Y�����]�x��y����K[�t�R�z�)v�����$;;��s�������z�<�������=z���j>��s~���s��Q�GX�b/�����A!D����x�	\.�
1��LDD�E����l�f���f�V+V�������l��i4hP��@B���g��3��fBSNI�X�d-�h	y� ��h?x�|hIS��LL� ����kf}i�NBi�3�_^E (�%u���u:��WG���m�o����?4	!�B!DH��L����/�Hdd$s��%%%���Z{�1����O�N��}���������g��a�����v:���>�o���g���je��l����/�����EQX�j���c��E�����>�����7�����
|"!�Arssy�����������)--�f��VBTT�
b��M��JJJ
uuum�|����9r$=z�0N	!N�Z_E��p��o�Am��[�rJ���a\J
���	f�?x�q�-���6�����,f+o�l���J���%�8�/�
<K�����%��V����rkK~���B!�B��N
��[����Jn��&RR�������O~�?����_� �������t�M��v����9����+��g#G����>#&&�k��V��=}�t>��s�n�����@O?�4$$$PQQ��tB!@�]Y__����v�mL�4�
6�e�JKKq80�i������
7��3�<������w/��������wo^x�jjjp�\�������j�j�[�q�]��_�?��������T���s��?.���2q�%G�f��[�bN���_J�st��
���{&�2�RNF���|Y�/l���2b�6��^	v
t���'%���=�"�:���B�L3�n������x;P�M!�B!N�N
�l��
���G��/����4��m���,�3x�`V�XAnn.������0q�D�Y�~]^^���0��������������������!Dww��!�z�)�7U�f3w�u����+L�4�I�&�/iU������w����������������K�={v�!D�y��Q��w������h��������������.��/�3q���� N��/�=����Xz�&n��\�W�|�"\�@��s�������e��y����Y1y��8��Am����J<MAKz	v�2�4����T���1 1V�a
!�B!�C�����#G����&)66EQ(+��lI}}=�������HH���.++�����u������w��q�<��#��%�L��(??���~:(�s�=�h��a�����%�r�J�o��[!�h7���i=��
��z	oI�q���-w�k�b�����g^�#��|�{���������ET����Am��]�>��h���1�&�f%8'5PJ���dT`���7�2m�x����~�+�7��d����8��������Ri�fM;�p�0�8$�B!�!�S�����c�Z�e�(���f��l�|CS����e5�J�8�N�_Cdd�~	�o�
�������>i���gaN���G���UTT�h���jW^y%���~���~��Ql�����b^}�Un��6���+�v��#��<�c��Dl�!�ps*�uS�r�g�1�v��=���H���������Pre�b�W���T0E������n�����v��]�)�_��(���#C�jH����VUX_���������:�xMM��2����j��
�\5Dah�I�Y��������c�bIZFb��D���x�0����g���@�Rk�$&����_kx����������T!���:5�->��i��	h�VUU�NK�j�-������w�}W�7phXyr��f.��r- ___������!�#k���6YJB�P�.1%�s�����}�W�i��G[Ky�]�6L�O^�A�M
d�WY����.`h��eLFY��A�/����,�����=X��c�Aq��9��?�o�*�Zm���N"lmopX#�z��(���c!�B!�
���c���x<x�^���nC�������h��ySMK;Mc��Y���~]g��j��(����T��.C�����Z6o�LAA>������;��CUU����[o�����]�1�}��n7o��&���s����Rk�������������������){��zN]�/�V�=������1��>ide%�/������&���
D+D�����������l~������G������u�:��Or�xZ����z���C�G���?G������, ���W/��������D�2{����IRl�n�{k���O��v=��v-�Q%��Dtj'!!�#G�PQQArrSQ���DUURS�~��bi�wNEE)))������	!Dw��*���,^�X+��DQ�����g��NGL�6�;v������{�1x�`z��mX)�h�)>�8�&SB�q���[X���PX����{�c73i@�q*��|�s�3��BEu7������x�d�\'�n`BRf�����vPU��]u(�����2�G�fi=���
�X�V*��y�����0�84�
��H�M��B!�"�tj������<�/q�2=�����Fii)���As����������p��gO��Bt����������������r��z�8\pA�2aNEQ���[������z����+-f`
!���m��5�
9�8tJ.o�>�m1�P�����G�p0�u_�S�5�;Xi'���&��������9i��R~
��=!;���hO����:�q������g�4������>��?�h_�v\��"�B!�/��1b_~�e��_|��(L�8Q+((`��E����V���#QU5�c������Mrr2$66���{�������~rss9��3�X:5�H!B����Y�b�/1�t:q��x<�NgP)��Q�!::@x�� IDAT�;��C�oVXX����
��-1'��1�z�p��C����8|�x}*��.��;~�`�����c��!K����c�5��$�P�6���8���������8>AS���M�'pM�8�;��k
b�5p��\�����bO�V�!�B!�i��7n�z�b��m���`��<���l�����;���tm�������s�=��p�Ea��y���X�h�|�	������b����L�o��+�7%�y��-[��������7�v;?��O�R!����_�������m�S����r�wb7�=����^����7l��I�B��������vVqD}�#4�L[�j9T��>5�^�E�g]&������PP�,=G'Z���i������� ~Z���#���@���Q���HS�
^������cFF	�s6f�B!�"�uj�d2��0z�h6l�����};��Og��9Ak�����&���<����������p�B***�3gNP����'s�w���x��wx�������w��]P�H!����z�����1�4�QZZj�=5f���7��7����	!Z�X���&g����lk�T��}�������0����s1������bjGY2�9��X���V�����������n�d������4��YOg��B#�l����?���*�!A!�B!D���mt���<�����RUUEbb"�e��3��/�������o�eee�\.����Z��eL�>�s�=���b�f3���Zy���}���}���a!��2*+�7�TU=n�����d2Q^^�����f�X�����;w.N����z^{�5~������\�����+h��um,���b0s�����,u����m�3��B���(�{	�Wl�:FT,=�qV�f�����[2"��.�I)������l�������(1B���?>ptR4�G��l�g�(�M]c
Q����B!�Bt_��]Xtt4���-p���:--M+�����$222Z�41�L������"7���^d�����(����4e�9u��������={������V!Z�=�hN��c�����D����l���{��C!oY�O�W�[K�wU�g����^�pY���}��)�,��3 rX��G�q�����H�j�5vz��k�����R����G����K��<$�:�B!��#T��	!��qqqZVM[Ar����(DGG��G��)5e���������vl���������qzK���*;:VNmh�6�P�S1�M�L��[J��_a�3F�S�����!{��������l��8P��i�J��\C�#y��\8<��9hnh�H����G�F@��@Y���0��I_!�B!D8i���B���(
�\r	6���lEQ����.���6�=���(�|��$$$��zy��Wq���p�-����-��OfK^-n��8�*��0�v�q8l���pL���k����2��*�����|�u9w>s1��y�}�7����p[�@���kN�H���'����s��Dm<1�������i�0�FG[f���(a���q�B!������B���N�Jff&���p8�Z��L&L&�����(����/��x�i������
y��w
��z��� �9��8�r��Cm���W�0���D�~yt%�Z��>�y����G�m<fSSY8{k8\���
�?�������wB+y��������N�����D�@!�B!B�q�����|8��p��`�Zq88-;g�������>�Y8zC�	
*}��Wl��]�B��W[��6p���1X7{�U�w��I3�&$)JPV���� ����'{���L�LI	���h,/��Q�>�n�������8R���q���0�c��VT���{IK�$%>C��!%��B!B��E6wu999dgg�����Tjkk�������������B!�Nvv6����?�3v�XJKK��|dff2q�DF�i�*4��5�]�vq��a,X���>jX%������bR0EJa��([;�%tVJy�fN���z ���QMC�x�8����mn�����j�{X��R.:�Z���'3>�q{UJjB�M������4�
�y�.:6�B�4�[�o<�6���T;{����B!���d�v���������������pO�>}?~<��o��9��/�LEE�q�Ug�u��M`���,[��s�=�I�&���r^���^z�I�&1n�8�t�


x��w9p����HMM5.!h����X��������z_
�J/�=�7�p�]v�aEh� �Bt1�v���������x<jkk����:�[o�5�8�Y,���������������z�������W��H��jY8���iI�~���q4<Y2��cW�w�n��k�5$���Z����1��tY8[+��u�_�����S�8���h+e����
'��5!�}����~<�|�?.�@��3��.����["�B��#''�}��g^WWWS\\��}�X�r%YYY�{��$''��g����6�_�������
�m���a���������/�n��-_~�%,����]�j�]w�a�8Q%%%$$$`�HX ���%�]D}}=�/f����)���3a��p����W_}5K�,`��Mdddt���]�G���`gB������&�\22	�G���n��?�;Y�*�f��Ql�DL�����X���|m]�IerJ`'����N���\����L��8�NG������8}��3q��USX�GFRomL!��d���/			x�^jjj(((�����������<�����{�(�Bff�q����@��PQWW�3�<��]��S��b�
,X��[o���3g/'d���|��G�����^z�����$�#�]�����7O�u�r���|@���d��7���Gm��b�:�����u+{��KF�\���={V	�}y��t�����G��KF$�|{�oOk����^����Dh�US=�|���3��������{1s^D����m�e���"���
����X����<�!3���<6g~E�qr��?��
�9��G\T"�Sp���/�&A!�Bt�����*%�v����f��466RTT�_|���^��*�b����O�C��}�x�������e��x�
����n������?��5k��c�qX����`-����[��m����*


x<|>>���������RZZ���K���<EQ���~FD�������O>�&�B������7
�=XB���R�i�
Z��������/p�����/-p8�������/_����mTB5�z������C6]���8<��B�3�h���gB Pt���s4,D�H��S��v8�o g{�F�X!�aJU���}p��O���Ej�V+g�}6��r�6�����V����z�|�M���{B���r���j�����J	��#�8B�|����wOK�
UUq�\DDD�z�j���*�qYHKLL��od��y>|�U�V1c��J!�o�����E`N�,5�E�O�����e����)����p��D�����!\{W����q�E����}����9��G3!��2i�v�67U.+*p����KN�L]������	�vd�W������@���%�>��������0)��M!�G�]������U��G�n�q�-`
l�	c����KJJt3����_g��58�^�z���_V���������3������?�������k2&&����7�UWW����S������UU���b�V��a��*����zeff�����:�N*++	<��A^^�������@VVV���TWW��~����Z�$%%���V�mll���J�����������Z���Qqq1�������p8����e-���d�����������!C�]����}��QSSCDD�������%EEE<x��������
���%A!�sN���|�no��k�
PU�����!77���Cs�~[&N�������i���>#F� --��R������cN!|C�����1,�h����{1�G�����;����P�T�]�p���j``L���?l��cf1����%']f|�����R�����7L��>�S�\E`Kcx���>�GmC5�
����&!�B�D��������q���������%17=�(G
L��!v5>����H���:f���g�}f\��={��~�zbcc���{�}���rssy����������++�/^�W_}��/��������������f����'//�_|�Y�Q�^����~�����-[��?����_������63���s�9\��DEE�����?���^C6�����s���7�l����^�g�7����t��?���{D���,]��#G�����]t3f�h�������w�a���A������3gS�N��VRR��������mTNLLd��Ymfj2��f���je���Ac��k��B�n����i������;.���(�t�M����������?BtG�����c�_(��c���1]*��+k=���C�Xin�L=�����1Nu
��DRt�M`I}�cBJ��`o�JS�l�(��-��jB!D�i\�����'u���8|����h�]�����c����������
��,[��p��7j��P�r�x���x��')--%::���Xm>//�'�xB�O�����c�"##INN��.^��U�V��#�P]]t���,X�������>����~��}!EQ0�LA���d
�����|>^z�%�{�9-��p8HII�2~


X�x1-w3}���Y�f
&����$�ff\]]/��"�}���
������?���7��*V��������������/4�^8�C=�pE!11���8�nw��7�I&�B����h,�EQZ�#��i�Orr�a&|���p�Ei�}8�_|�\`X)D���e�X�B?��WxC�+�����g�GZ������kSb���}�N��x;e������08�� d)�<�<�?-�2�`D���;�S�=gWN���"!�B�8_M)
+��7Ul��/����9�1�at�q��hhh��w����9��l0����+����=��������Yg��c\VV��-[������������L&����0a3g�lw	����7���won���
�o***��g�%''���2V�^��^h��/..�[n��	&`2��x<������~�#G�p���������0�W]u.��+�`���$''�����;x��7���d���l����c�j�N�6�i����+�hYF/��b���%K����_�����9s5j&�	UU9p��~�)c��������q��Wr��������?��>@UU.\��q��H���<��S���b������8����@�?��k��Fnn.k�����\|���������o�6._p���5��xF��}�x����eP�	�!D�3���1�-[�`�Zq�\�%X,E!!!!�w�8�a��i�P>��F�-e�D���x�k����)��&O���K�s�+���'w�q�E&������.�
��	���@�;�����K���Sz�tA��/�[�hF����o_`��-��.����Bq�|5%4�y���8�.���������[��?���8�\;�-��^�%s�q�����[RSS�X,������Kvv��a1f�&N�h�*����`��0}��	� ����m�����R�������~��U�V������4:����Gy$(�����/~����~��}�������4i�vn�X3fYYY<��������w����G�^��uS�La���Z@��z'M�DDD���������q:�����?����y�����yEQ8p ��w�6�����;�d��j��k�%''�-[�P\\��C������f��%TWWc2�x��2$�����y���x��(//��?��.��|.\�����k����������w��O<4$�#�]�5�\���;����4o6����_}�T�pt������Ouu5n��������v��M���U�:��VO��W��t�L��Y4�_��8;D��/�!��Kt�L]��$�5<��
�x�T��	��C���9�������q�?����]!�B�_��O����q�����p�������K�w���F�/6i���/�K�p3���im<��(
������L�4�=zPUU���~Kuu5���������k��/�Z�~�Z�
���$>>���J


�����YDFFr��������F6l
�(���=z4QQQ���q��a�t��X�B���=;(��MYJF&L������� Nmm-k��`����8M����9s&K�,������HEE�����7��Y�W�5��7�B�. ==����������l6,��'FQmW��)S~���P�p8���[x�y�.��j�*f��aX)D��/�fN��b��n�Ja�>����OW`NH�9w�������86n�� ����U������3>�����Q�3�(VH������})Wc���k�r6��8�B!Nk�q$�YOl�QK���f3��?�F�
o��j��7�0w9�~*�����;�=zhc�]v=��������z�������=6�_���9��K�����TVV��pb��F��<xP7��z��e{�������M�=������Q[���?QM�d�fs��b'J_�_��y����}���8��h�~�rII	d���x�^�_���`Y�� �B����*JJJHKK�z�45�kb���={6��M�]������������z����=:�{��^}'=���T:�{/k6)��v�Vg�_]9�
�2N���D��%i������Ql\���,��o�4=t�8n/T:�)���/���T7(VF���}��u	!���D]� ��A�����)��{�7��VY�a|�q�}Ll�/1�����>KTT������[dgg��z��wo��8��>�q��p������kx��Wv�>������n����<-A����)�Q�rq�������l�z��fs�6m����Y:����on)�������?N�����'�|�'�|���������jc���
	�!D��������f��@?�&��9��Gzz:#G�$**���K�����{7���8�N�z�-~���t�]B�$(���p|*�/��?{;���l�M]����J�e��6l��_�}�{8�3E!����O��O/�&���_F��_[����sjDXM$EY)�sa�'�B0����<��u&D�bbJ���C����4����L6!��+P�8��1��Z_E��]��Xc�jQ��b�s�q��)�����*Hl�����z�-[��)S���4^�-��C����y��Z�X*,&&�����1�gr�#����d����t*|���������q�:u*�&22���R>���f���r:�Z6KD��������4h�����������ck��IG!���_~�����?�>�EQ��F��o���yW�
7������s'���j(DW�/�f	�L�C����u����V�X�����$�����g�?k�	��P�?���@UA���g������ �?��z�l2����
�cd&�A�@�����S�?�P��V����X����#������A�~��B!:F��#����[��q���kNK�(..����������x�7o?��l<���![��������1�F?�{��3s������S�A�={����3�333y���U ���ot�f��D�lG�t�e�]����u����F��cW�u:a	!D7q��!�y��^/n����zihh�����GCC���*.��xy�4~������/��u`�u��_��<���,Qy����8^���o�����[�t9&����i������������2y7����^3+k.�,��T���T+��g�nl���i���j�>n'�����/�)�B��g}�?����ZO#��_N�3f0p������{Y�j�aE��/�����=�{�4�����?Q'���_ IDATZ��T��������V�\��X���~�,��Q�~MME!))	��7s���N����X�8�W||�v|�H�}rW!A!�#����o���p�����6����|���h�S��o�YK����e��El����+W�v�ZJJJW	��E?h��#Sl�n���u���^�Nk��f�U��.Ih�u�)h��T �|��P�h���������0�%�|��2jz=�A�p)��z`����VX�_fdW�:��B!B��y�����5,���9*���u�c���(��3;NEQ�����l�w�y�GgMt�
��:������/-�Nk}����r�L���t���kR}y���|������6��^4�^DF��
��v�a�����0|�p-;m�����Z��Y:�_��"A!�#�����j�N���@W�����Y���
6���/�d�������{^~�ejj�W;Y�P�'mP������\�����0����=]�%-���l�;l|R�g���4�:������q[�k<}o(3�ozK:�~��(]
5��m�SO�F����B!B���b��O��Ww���?�q�Z�}��!���O�>\t�E�����oVt?#G��J�}��-��������3F7�~���Zc���Ziz�m���iS�^?v��r�J�t�2e�6g����������������h����K��9S;~���)++���|���Y611Q+�VPP���K
+**��n5j��=~���l��r�����7�!Fz�!D)(��K8^�o����R\.�����6m|���j��zQUEQ0��l�����w����.(m[�p�)��[���B����O��:��+j`hF�n,���I�)��@Fd#������t����J&��rjn�Ji����nE*_ai���Jv��Y�/0N	!�"�)�h��@o�Pv�5��~�zJKKY�~=�7o��3����z�������f�L�B�~���l����������K�����lf��Y,\��#G�����s�����W/�����������=s������>����SRR���>����IMM������������ 9��.]��ng���X�V���Y�n��-��X�^{-����F#G��������p�Bf����f����a��x�
-�������jbcc���>�G}�K����1d�\.;w�d�������3f�������Jz�!���*��Gbb"uuu����e��a6��;w����(7�x#�w����������.�������(�~�z�/_�m���YgzZZ�V���j,X���>�E]��i��������e�/^�]N$�#�a��=n�
�)�]�����BUU\.W�EQ��l���2�|���?t��Ft=^]����n�J]�Mtm*�qu� ��'N�������E�&J���FR���1 ��T���H��R~�I��h� ���q�M#�Y��A�8B!��Tv��9s���SO����3l���r_����|���������� ��={��g�q8H��=O{��/d���l���={���c��`�X��/�M�Q�_={����v�q��f�������������l���<��3�a������_4v�%�����RZZ���~�_|A||<���8�Nl6g�}6_�5���h�"~����6lc��a��-TTT��O�>���KZ�g��9����n�:���X�`�1��gC�1�������~����S]]Mvv��3������8\p���������|��f����I8��WB&*++y����n��4'RSS�X�G������?��7D4�7v|>�b��5A�B����P��ex��I���������T�GaJ� 
����8��&j�o�����1\3�gAc���/����m(8������k�P[���!�B�1n�8�<�L�_=��w�5��^�f3���o�={�VZM�O�><��C'\J�I��}���H�>}��#""���K��_�BDDD�\g�6m����z����s�=�y���
���<���Z���MII	����G����r��w2e�E�������y��_����=��Lqq�vn�X������/~�bEQ�����?�9YY'�����y����>}z��&��"��'?��0Np��wr��w���~@Q����w���d������B�9UUy��7������Y����6e��v%te[�nEUU<O�)�M���v;�7of��i�%B�_�QTW��DQ0��^p�)
��U��j��bK�v�,�&��,\�~8�&�bK�a��`x\�����x�XA���GBL��'[f��m��
�����pu��|O�A�+H��r�B!���|�8������2���q<S�Ne���������/n�M�����W^���_NNN���(�BFFF��������?NII	%%%8z����C��������W���,Z��8��#�<bjf����s�=���R\\��b!99���D�� �����O������RAe����^n��fJJJZ���v���^n���=��l&::����f�E�~����)--���IFFF��[o��[o��8d��a�},���;���[����������������f�(
��w��wEEETTT`�Z��p�$A!�;v�`��m�������p`�ZQ���-E�n��(
={���/4|��������5=V����(�'��@#JsBO[�@&�4�[�E-��5����=^����`�����<:�eV��
��o�Z�1��&
������������:<�}q�T�A&N�l�{���Zln��ld�W��B!�����v�m7JNN&))�8���L&���S'UJJJ�L�S-99������LKK#--�8����;n�#11��A#���?Y,}��5����p�=�-!D���u+�������f�a�X�X,ZvN�������f;)���] ��`����v�.�� N� �L���0"UaGq�!�X��[&g��,}�;o�~l;�cK�X�]�)\6�dc\�Tl���]��t����o������aP��8��:����B!D7����s�h�z	6���k������B�N�}��	!D+++Y&�����f�l67\0������f�f���2sM�j����B�n�"]?����\:�Lb|4_��{���h���d�h��WWb�=_�����F�\��C����M����	��� �����������IWv(�3>����l@EE	��B!�I1e�*+[~�~<M����O�8B�e�TZM?f�X�Z�DE�K�t'#G�$55����V��L&�V+f��s�=�8-D����8���Pc7�]g� �n�����M�79�	}c�`x"Vs��YnJ��b�@u5����[I�9�t4��u���#�f"�5N���Jg�q2����h���^Q
LM�C^�Az�vn	!�B�Pp��W��!��Y!DH������ln�[]UU���,�����V��@�j�b�����)x����K�]���:TW=��|���A�&&]�yR�8����J�v����i���q^]$����CMjd�����c��PfM�����m��w;�7!�Bq�,���DFFv������ �B����'��ln���b�l6������BVV��~;X,���8�V+�olw�%��"|x����3��"1��~?�
}o��*��s�v���
�8-I���C �\�H��,^��>5!�Bq�����y��7o�&M2Nq\�B�0�M7���f�n�k�p�f3v�����7��-��5�<y2�=���{.���X,"""����RuW^���%�_���qt�U�+s���)�J�#�H��Y8)Q����	��K�#�UT�
��kB!�B������B!B��q�����Y�p!f��Yi5������;vl�xw��|>����Muu5^���7r�y���"|x
�i��t]FG�rz|��zTIL�	(qu�L�`�[UH��\�,�$�2q
*���&�E�t@��k�Q\�%�p{7N	!�B!�)�[7�BhbbbP��()
�������3f0w�\�M�f�B��'��	�����N7+Dx��8����V�����Rc�Y�������/������mjOe����k��P�/����(��~)?�1;�8��J���u�l��h�B!�B��B�8BF��	���0a�>�,s������'11Q�R�?^;��oUUU�Y!����-��S�L�#.�8#��)P���q~�!u?����t���8G+b1U�P���x�wh���aQ��%Rq
�����GZ�0�'��q�B!�!C�8B&jjj��}�v>e���8�������/a��*��m3�"�����:��ss�@�lh
����}K�������i|
�T>��H�	<���������G�~����@��+���;2mm�&�\�.J`O�V�!�!�B!�	�!D�X�n>���@BBC�5�mQ���Gk�[�l��
<�,S|G�n64�W�8=�q���=
��<i����Lab��xH�����(j�xK�
��j��ja��0��z	�Q�����1V��g��q�7?�qB!�B!N	�!D�X�v�v<i�$L&��Qg�q�v�k�.����CB�4���8�{_����
�#� Nf|�
��;����fr�nF'J:n��e
�ZLZ �s84��L��p��@������0�YH�(����	X-Q�=F���!0/�B!����8 �"����������u�Y�Y�^��n��t:q�������d2��W/���:
��"��q��M��s�U��n�}p����C���RR(I�]3q����{�\F'�8[+c�Q�M����6�����(]95�T�ca�0a�������j(y�\��.gd�	l=����;v�B!�B�>��[!��>�������fE{������q:Y>����\�|�I������"4��G���l�Pk�Yp7�k�4N���zh�u��Rb�A����|D���������],<k)�@pk[E�v��I!GS|�6J�u���je���:�%���q���w�6����4�zP	!�B!�� A!�q>����l�|��)�Y�^k��e��e������r��x��|����u�x���tW	q�x�w���%�F��W>��(�+'��6�3�m�Mm~3]������]��?���u��������`sk�;��^���aQH�$�q�GY����8���y�~���r��S}�:�9�F!�B!N	�!D���k55��:��	B�tR����a����?(����p\.��������|�
��_.�iQ��A�RYZ���K�'7N������]K����������7�h�H��7C��qU(
�_��@`'�d���|w8��1�������/0)&���
����jB!�B��K�8B���[��5��H]-�.�W���v��*N����i���;������:�f'	!������!.u�zKqk�^Em{�z����V�j�r��.��*h�X\
("" ���=,aI !!�$�d�3����3gN�2!�����q���92c2��?���������|��iV���,�_��<�(���h���C��;�IO��A����`k<�SgD�J��,��i�E������4� N��qP,�6�����C��c!�B!���B���x��y�~>i�$��h�;v�,Mk<��.�����!�W���y�i���k�A�!v�%�8�
(�km�5E(��S�W���@�0���N\N
 iz��l)�1j@(��p�~*��Bk�B!���IG!"�����z���cbb=z�i�h���`c��2p��<u�!:��hy����5u(�
e��L��XN�j+h��y��a����S?�U'M+"CX&�wP��"]�e�co!T��wJ?��R����7��!�B!D;� �BD0c)�q��a���I��KNN@�k8���y��a��}YS��((c���%��y�C����K|�Z����Wj�y��n��XO}������a���
�PZ��@U���@�y����((d
0�T���B!�B�v&A!��0��QRR��]���k�>>y�d�*�u�;���d �j�0hP'/$:?�����F9'�%�>�������ji���sV�@�H�=���C��G�#a$�i%1&�� ��c����}q�������$�#�B!��H��[!"D ��o�e��%������������yt�?~<�������8<���V+v�EQ���7���.��{��Y�Z�g�
c�5��n�p��~8]��@�0�
�����O&@�.���/���`'����u� #�I��@Ay����J��p���q�r�|a�8Ee�W�G���vB!��T��5��RD�m���v�������Y�����#G�0z�hbc�_��\Y[6������������?�8�@@���r��������P��z����j%**
����;���C��������� D�Sl�o[�1�)�}�x�o�_�F����jC?C���E�����
�T��t���?�"��5���8�.�T�?�\k���iI��;�6��B!�-��?��%K���#�������l�����[�n��'���g��^�������������{���"��M�x��Wy��W)**2O��$�#��������h������vS[[Kmm-^�M�X�h�}�A={����HLL�b��p8�����t���n��Fn��F��BtKR:	w�����������Xbo|��#�z��1�S���8I�����Q��>j��
�N��"��5���8��6%t^v���CI�CRRM!�-WRR���������S�.��z�j\.�y�Q�@���~�^x�}��q��rrr���Y8~��yHt!�B��u�V6m���i������>�i~�_/�����7X
L4O���������3���?���a��'O�b�_�"�(4�W?����$��w��]q}p��T����yFW�|���<
�Z�k�<���SXb��C���SP�:y����8��A�y�NeG	!�B4��e��4�PPP`��(�����`�����&^�u��6�*66����c��V�3�t�R}�Q^~�e���B"��_!��~����|z�43UUQU���Jv��a�-`������y�������D�=��m��V
!*jI�/���`�dd:^���������P?��++���"��
C�X?e�y���72o~���Z_��p��0q\�@�$��{_VU�����5B!����*��/��W�\��0�����7�a��]������Y�f
QQQ��7�a����g�,-Z�@��$�#����q 0��������f��R�1cB�F$�#"�Zz��2q,,)�D���P�PZ����gi������5'�)9���[���QjQ�y("�:�$���s���0�	��[�������$�$�/-S_�=o�~,�B��i���������#T�{���D�EF����7S^^���^�����m���
n����{���gSRRb�>��[��p�B,<�4�B�����+�]LK?��t�hZvv6�|�
{������tv��O"��E��ckr_[�g���j�u�Rjj%�wCY��mNY���\��e�1�2,����n?@�?����������Q��x)�|</��_���8\����6r�����B�Q����|6����,<�>����������as����Xrr2�������}�vF��������������������n����h�����S�����w/���������F��})..�������E���9sX�z5���������m>j�����w���Q��1#l�dkp��TVV����n7�*))AUUl6��w��=��������������2�
�g���5F�����n��Gnn.����l6RSS4hV��xY�
�����vE������o���\.jjj���~�_��IKK;7�4�C�QTT���&!!���[� IDAT��{�4&??�������������.?_PP��#G���!>>�����UAi��i<x�c����*������q������s��	,K��c �5����dffMMM
~��]�vq�y���	�a�S�����Hf��1�N�R�Ep����c�|�q
N�:hFG����u���o��p�������8,�V�)[
@��q,\7���6�X"��B�U\ET������}3��a\o�E��^�>(�Y���}{p����3y������������z�)<)))�������>��3-Z��O>�?����|��G|����|�����A�������c�������Ka��111��9�i���x�b��M[�p�������u�]gZq��.]�?��Of��Mff��C�>�,EEEddd��/��[�n���3�
��g�a��%|���z
�?��������������dIp3��~�+>���z����Xn������z���i|��w,Z�������A0w�M7q��������7/�_aa!=��~n�Xx�����:^��/������r���Ea����p�
�5*l�����y�����?t
��wo~��_2`@��!v���?��:d�b���z���9�<����a�����'$$��O����F�@���M�<��%V���J\\YYY�iql6[��TJ��H�)�8����.��S�6����8
<7f7������?��<��c�~l0H�:�����{�����$�poh�B!���Q���
��4����F�T�g���e��4���(����q���a555����.�� �M�XOUU�������?C���_z�%.\����f���=��������O<Q�������K/����_^/����7�V+w�}w��oo����b���x<����66l���_7\Q����NQQIII$%%�����j����+��R�r���'�3gN����r�y�������^�K���bi0�������g��G����8z����nG�4v���G}T�k�`��3�<����q8$'��^;v�g�}���{K�.��g��8111��������<�{�9�.
n�2[�l�?�����l������b����+���B�v�y�1f��n�JTT^�7,#�n���[o����h}N����l6l�w~h��@E����4r��QX
��w� N��v����)����ye��f������f���{S�����f�Pp���T���eD��$��rv�#o#�z
7\$�B��~�h���l��/X��tE�����)?3O5��X���G����b�
�����d��	,_�����u����K��W\q�^�l��
f*l��Y(�UW��_}�999<�|���$V�Z����7TU����^�	��)S�C��~�z��3f��/g��
�<y���h����E]��I�"��z��eL�0��3g��gO4Mc�����kTVV�i�&�9B��}���������4�����Y��y�p���[�����:��III���/���\���1���xJKKY�z5����������r�������_;k�,f���C=�`���������<xfG�~�����������W_}���4����n��������2e
V�������7�l������O>�����n��m��3M�HKK����"++EQPU����3g�����;w.+��s�N�~�m4M��t2s�L.��b����Z����~�^�YW���DB!Z��(�q����s��!����4
M��v]\q��?�p�h-u.4M��r���W�V�A����������_���U
�(���� �9���_�	�p=�%@���Tn
�6����<�2q�(�t^J0����i�RH�I���zg{�zn���5B!�h	������I4��n[���/�|��p�(
Q�N���V��y�f���Y�uA���,bbbp���\�2,���_?�Bnn���c���|�r XV����<������9x� �/����~���v���[���[�la��M�ymm-eeel�����W���pt�=���^�=����+���Q����7���7u6�y���zEGGs�e���_?�z�)TU�_����O���9s&QQQ�l���)))�p�
��n,X���c���a���Z�|9����=�G}4������;��c��cfN����z���C������Oz�!***��a��{�RUU�$''��SO����Z�L�<�=z���O��������o��7�|S����2b��z���E]�����X�*���BD�n��1k�,�\Q=���o_}�Qf����N	q�����j�JI5)��<8����X�"�pAY(k$9Z�n�:?�l��I�_��eOvaq4����|�����nmq�
�YC�,�J_�:�K�Q&�C��l����C'!��\��8��8gM��]��y�����[�����#6�M���w�^N���s�W��xX�vm�\]@`��iz������8p ��w���c�z������@��Nrr2W_}5��r_|�<��y3s����v�����6�Wo���	
4h�^.�����{�������p���Pg�����S������rk��������r������P��-[�����o�9,�c�������}�v���
(..��oc����j~	!�hw��,=z���{�!99���D�*�V�����o��x���B�?����Z�����C$�7qz�t�@w[!Q�y�q
Xbj	x��3A��#�
�CA�H��<@�;�#1XR��K2���=5�1
�����������&�������	!����#|�6�*!��c�35�������0q����&L`���h������7���M�8���TTT�b�
.��R}n����VkX&���IC�� ��������*++��
�o�������.����=���b�
�����C�.\H~~��@�+�����������_QK�5�u��p������l���PQQ��b�g��a�g�����G���z����g�$4~����V���`oH]�����"11�-[������'A!�����	&H9�v6f�>�����)--
�0'DGP�B��:C?��rC'�0�����r����E�={�c�������.�D,�B��b��{w���[��f����C��@�s���hG�e^�-��O�����B!"����9�Wk�j���T}��y�QQ���n77�b���4�U��e����s����l�N'���+Wr�M7��6�V+�]v�}�������J�M�0!�\ZLL����������`o���S��6|>_X@��[o�D>|8S�La��Uh������6J���4����q��1f����1hRQQa�	����OY�h^o�Yhgd+**��+w��I�����P?~��7������:�����e�#�q�"TTT����?�|��hiii����i���m�] ���e����wJ$0�SK�>��F�U���;O���<��q�D]��/�}���3���������b�����$\
���O*����,����w�E������1�{~~��\16��V!�MS��(�3���q)����m4O�c��N�����@��RU�+V��'C�	�w8�3�u��Q\\���{6l�>?m�4�����O�Sv���?�������u�����OII	�V�b����\ `��E�yk=g���X,=;����3n�8V�Z�/��{wz��6�gE��w�2���*�����W^INNf��������B~~>����L�x������Dp����$6�f�@UUJ6���J�8B�m����INNn���q������7�|HGD��L��P��H�h�B���Z&��YY]y���3O5,�z�F>�s�,���R9������5=�8���c��F#�W�i�����k^�YJ��'\�v��2X��S����=����IK� {`0#I!�mH���'�x}����W1����8��R^^��(u�+W��$''3v�X��_�����3�,�A�1xp������l��	���[o���'�����v���_�Y�'On����X*++q:���^����~l|�p�����wv��1����K�L�8����O/)�� ��1��� R{0�{���>��)����O{��M�VB�.`�����y��'�:Hvv�~�g��!:�V[I�J���8E./j �x[Q�{�����pf����u���P�Q�3'a3��SO2\"X���uZ�)��:�����6P�GnS4�x�i���W��X�{<��$	!��uX��I���2B
��,	i����a�������~�8p�y����o��
���k�������+(--e���z��+����L��W/y������|��?���~�_|��� (�5k����S��������12�M9����3-u���}����,Y3�~��_�<Z���33��4�k�-�ug�w����z�����fE��B�VSS���������1x�`�����g�����r.Ds\'�l���`�>���D~�&c)��(�u��B�@<��v�O�y{2{��������v��2\"Y���n�6*j�5���<$���Itj��mm��eKi7NzB�R']El���F��
!���X{$��9xw.����B��Dl�����JT���Vqq���=99����LG�%//���Z6n��;g��ddd����[o�����[�nL�4��'����/^x!,@�4�V+III����/��	&�/9k�f��=��~������~������u�}Z��(--5����0�k������������8YYYa%�Z�.����1%%�=z�e�JJJ�;mi��Qz�U�V�e�5������?x��~�z~���V� �Bt������*qqq���m�j�2j�(��_K�IG�M��u��^B�
���|����sbo��5-r�����8=b�^�.����-��T��5u�8�YSC�V�% =��q
�<��h��&���3�
=hhJ�UeZ�b>:��+�+A!��=Y�8F]�cT�Y*�i��ez��UW]���^kZ�{�n�y� XR���>}:s�����\~���l
?�-))��'��f����2d������I�X�`_}�U�L���W_}����f����g�M�65��?>.��<�n/^L^^C�����v;���iZ�_��-[�c�?t�`���@aa!���Mg�O���y�PU�7�|�G}������&���Yc��Orr2����X��I�&5�,--%99|s��)S���g�}���c�^�:�}��.�?R!"���vvv6��h�H��j999��-�-���R��S�8u�������(?n���L��m{��j�5���m���Oa��5��N�I��4�:W�TIs
I�_r���5	!��PUU�DP���'�V�6l��{�����^����S�'6��i�����^����2�����������?��7�x�?�����K|��G?����7<._����z��G�R]]���y����X��
kqvF�a���?�����)--�������+�����n��m���������*^�����o��{�`�X���;��N�S�c�m�6V�^���n7�}���������h��Q��k�����GQU����dK�������|�I6l�@UU��QRR�W_}�#�<��Z��n��;�DQTU��^���?����@ ���e������[<����8q"���2qb��duu5����X�x1���\._~�%.���i8�+��]��~=��|w�h=�F��b����$//�A�"��������?�p=��M�����_�Mg"�d������#�*���q���\'�j\(�	��)#��1�:��<��[���EeG�CB!��6m�Dyy9C��{����Ea���,]�M�X�j�_�>���SY�d	'N�{�4$##��1///, `�y�f,X�=���E]d�>cw�}7O?�4EEE,[��e��������/~��p�9�Nf���;����i��?�������2e
�����(�O�-����M�E��{�������n��g�����������oGYY�����J��=���!??����s�%���W^y%�}���������c��s�������8y�^x��=��C�x�����FK�.��o<�^Efc���?��?�3g~���>���>��������[�����nN�8A^^������{zp�N[g�E:��-�h�����w�:F�aZ!�[LL��[�;f�hk�k��y���o���:��;��N
h/���)�
s]�!���<����tk��%>5�~�z��a6r��8�o�����G���[�Cl;�����B!�c���.0�4�.��%���O�K�5e����~�������IBBC���K/����"++K��x����`SkHLL�������/�W�KQ������-��\�_~9�f���JII����:� QK��G?"!!|���ba������l���<��c���P[[KII	v���.����g3k�,����`�L\\�?�84OQVVV=�{����=��o�����������?�j�:�]vO?�4�G��Wa�j�2x�`���nf��6�O<�u�]�g^�q8\~�����?�b�`�X�d@G2q��m��U?9r$G�I��8�������F7�t�i������<�$��������#Aq� ��^R� �&������	���in6kj&�#��
������1-�<�rjno�r����Nv���z8�{�h��������P0G
X�k)7]x�a�B!�u�����C�5r�H���g������SO���h��~��&��/X��>��������:u�y���������67*!!�{�����'//���
h0�p�.��.��b���q�\$&&��wo�a~c''Nl������@��|�m�QPP@EE�������^��l�������9r���*���IOO�j
}�|���(**��v����'����)((���L�����h8�Nn��fn��&
)++CQ���g��[��^0�s��7s��7���8�_�����n�;���%66������������[�1c�������������P?��OLWu���J!����ey�������l>��#�;�d�@!ZC���q���cv��Rj���.�O���0���[���M�fM�����h�JK<,����8��!�(��y�Aq6?�<������-��SB!��|C�1�������u�@Z���<��7��(
}��1�+EQ������5��(z�����5�7�(==���t�p�E�W�^����<��bbb���47��j���9I95!�� G��*�����{�'�^ZZ={��II5��,	������E^P���X^�K*_������0$�y�S��������a&�i�������(�w&6����8M�J�NH!�B���i/��".���������_���$!"S'�"'��c)����,"��1cX�x1|��M�fZ!D��gN���&�a@{�$�L�3f��':���dWc��c���k�aA��i������i�	�������B��V���G���]K^U��F_CN!���}��Wl���-[�����s�y��������i�&���5jT�e�!��q���H)������q���KMM
��]���hKQ�n�������p8�\�5�����[�L�N�����/�~��w�'0��0����<3�����@u)�����I����;k&N��_ww��TG�n�3eD�	�B!D{HLL$11���r�n7�W��2�?�����<,��$$�#�����������<�
"66���j�;v�`����eB�
����O�����J����;����
c�7 IDAT&��aA20j;������b�zD��eZb�Qb�����@�����1�S+��L�T�����k�i��=K�t2
����G����9.�B����.`���l���-[�p��A***P���$233�2e�d��!��ALL0�Z����$A!���,�=z��_��b�0j�(��]_3	����?����W8m���I��o�Dw3�t��*^������H
�����u��(���S����//���E���`Zy�A�j����O��Nv�a����pr�y�Q�%U`��`��\;�V��B!D��Z��?^�W���������g<��,�!�m��������w�}�E�B�F�-;:"�1C*''�@ ���gM������T���{���}�hD0�@�g'��u?b������:�� Nx_�����*!P��w��ji?7�4�n	p���������t���B!���t��qB��h��?���~���6OSUU����f���f���X�VTU��v��~IC�J-�6�o&��o���7��>�N��0��X?C����������I�=�N����q�cXC��{bd�X��N���<rZ�@3��B!�Bq�d��B���?��9s��v�QU���������n�:^y������*::��C�$�n�j����'�������T����������u�8�;pX��p|����X��i~?�:�2q:���L?6�':��������k
��[���B!�B��q��
<x�/��������������z�����i�v�b�����E$���������h
���<��S�m��� �8A�Rj�\q��������8������0��}q:m95k���<�(��1�e�U�yJ!�B!Z�q��
}���h����CUU�4�@���J���c�QXXh�����B��CIHEqFV�*
���3<f�~����L%*KB�~�5��^G�|� NA��.��������������+��B!�B�*$�#�m�������7FUU����>|�<-:XJJ
�����d�����cj���p�P�+��Q���#/S�M����l����5����x6'��2
����:P?�,}q45TN���RY�����f�I��Ge��-�kB!�B�V!A!�h#UUU4M;m������2���RRM�����<�$k�P��Hq����c#�a5���P�g�8
���cQB��[�3�_:V��pM�Y
��N�����s�^�����_aiR�2�<$�B!��B�8B�FbbbPEQL��������wDd3f�~�o�>���
�B�9c����$�2u���`IH�b���<��@�y���jf�/����1���,�8������:��7_�U�����B!��UHG!����`��`9���������������i��4Mc���B���)���)�����.�Nb	��w������8��}���k�!�� t��i�������D3�4i��I�	��B!�B�5	�!D�����`@�b��#WQ�`�������nZ!"��(�jN.%�Dk���3,	���E]��f�mO�l�.��s�E�BHM*������e�1@?��^��|�l�:g2q�n3�4L@aMI2�����B!�Bq��?QB�jF���^�����p`�Z�Z���v����X,��������t��$��8;v�@UU��gF��'��O����)��C���^�p������U2q�W�G�V��<rZ�#KR�~�YJ��e�t� N�d���h}
||�7E5N	�!�B!��q����~��\{��(���f��t�t:���(���I�x����,�&:��#����v��h4."�=s2�������b!j��H��][0k/��j�T{B�.SN�w�<�4���K��J�u��9�LW�����>I���a
m���h�WUn~�iV!�B!��q����l6��[,��_�#�<��w�M\\��
����:t�~.%�Dk��
&��Y�����k#��/���A{dG��	QV���H0��ai���y�Y�����A��1��-F�������o`��~
�����o�j
����of�=!�B!�h&	�!D;��=Tb%++��{�;���a�Z�8Yt,cI���q-Z�Z|H?�O�������D�Rj]�@����&(�t�y�Y���c��A�L�R���(������5&��{�_{�O��!8l��������@'�>B!�BD	�!D;0qF�m���1�SXXHQQ�aV��c�ybMd��\aA��RJ
��c`�nmX�C-��9�j,�VrT_h2��'�J�u�L�0�
)7��\������t��^��Q�|q[��j\��B!�Bq�$�#�m���8�aVV�aVt&)))��*�#�8�5�qB���,T:�Ke�8�`�����bF����G����XN}\��'�/�P�����9����qUO�=�R���P�u�t�g<��������9!�B!�h)	�!D3f����������l��8�G�����T2q:�?���`O6����_�h�L���@�)jQ(��2�A�N_N�$f��^s�����i�������_SQ]j�B!���i�y��m���5k��}|�����k ���< ��u�8�F�2���(;;����
���\jjj��>���B@0�S�G�j���7|A��Uq����.��S'�b���p�*�u%Id���fZ|f���P��PO�Z���cz5~�<*qN�aEgf�nS���w�dKi���YeM�|��<t���)!�B�c>��Cv����������C  **���D�������9r$���/�o�eee��FM�2��S���;w�d���g�K.��I�&��;UU��_���I�;v�y�I�����>���<���������{��GQQa�3�<��_9q�?���:t�yI���a���'33����K]f~;��g.d���x<�V+�����K.a��i��wE�� �B�!�����{�s	�t~$..���*�;v�`����eB�HX)�������2,b�V�#�kn}p����?���������5g��:v.@=q�4��b�D�-��@�����1�U�W a
�SA�a	U�����^Fum%�Q��)!�B�C������5�r�8q����|��72�_��W
V���gO�z�*�\VV���1b�>�TU���_g���-�Z���;�������l�2f��iZ�6��Y��u�x���y��gL+�����Kii)G�a��q�3����OJJ�fk�������e������9x� 7n��Gi��S4O��������o^o�g���`���Q"I4�b����/�h
�����Z���U��h���E���hZx��i���Z��0�L}q���j.�H�83�
��t�	5�RPr�<,�B�sX���9���=z4��}6�����g���i�3��(ddd���n���(�����`������Z�d	�����|(���w��n��={6x��z����j�G���`��s�=��>HMM�y��m���y���iqqq�x������p�
��7d��������A�fB��v���6��n������Y�f
,��=�Y�[��8�#�klX�%K��V����c�Q�X�CA��`���PK�R�b|��n@�G��==�����J�{�\�q���`��+������3/���KB!D�S*.wqQ	�m�t�x��GHN�N��|�Y���s�R[[KQQK�.��k�1\b��x����/77��^{�����im���w�}W?���;����
+���a����~Gaa!\p�y�]<��C�]��������n�f���a��Z������� 66�g�y���4}��K.����-n���K�r�u����z���IG!����������s����b��������df���[���dYS;�{����%U���=��8Z/��]E���K8x����w%�k> ��'��m��BG3���� Nrb����������A�^�}�CB!�8K���3����9��,�58=��.��qC�}b"��n���."���o�y��F�8������O>a��%���-QZZ�_�����
7����:��
c��a��v�e�]fnS�W������t�Ma���4���:>��C|>�6mb��iakD��m�B�F���8v��~���e��Ytt4C����m�f��e4����~�)��%E���v�
q��z���['������ �*6O��<������c���p95��A�c�~>�[�}q���#1��yX!�g��Usx��;��o���W���?|�W>�^�}1�7).n�s^g4g�/^L  33�K/����I���?��
~�3f3f�0�h[u�Q�����4M������r}����e��-[��u�|M���Y�v-�}�999z�}��������g�}������a���j���w��0uj����'����	$NO2q����������T���������'��t��m�|���B4O��h�v�Y�X;��}�7@Y�_?���8�b�����u���D�g��SM�����T�$��{��U����(w�����:�����Q�	��`XB���df�9���_���Bq�����{�`'��}�}1�������2Ou�s�w  &&��3g2m�4/^l^��={��n�:����Q��_���q�F�������u�]a�@UUU<��C�����+��}�v�~�m=�T'++�Y�f��;��u���������N&N�6����RTT��w���7�xC?_�~=��_�s�'�x"���'�d���ac��i{���O�>��5�a���Jtt4555?~�<-��q������r�J�����#G��#F�����������8v�%%%����V	qza�pR��%�t3dVD�-$�FV�]��}���vJj�X�h�Dw���*B7pMQ��������)7���8;Qv��`�������`C�sAl��������S�����5v��{��zu�6.�B�3W][��������S������9U1����������)�?�|����3���`�����n#>>�0y�n7/��2�v� 99���j<��=��;x���P����c��������M�p�\����$&&�(��(
�M���s����<w***���^�B�8���LAA'N�0O�6&A!�h���z�j>���z)�;w��������;�E������gO
�`6���g"�N��SiK����M��<����u���V*����`j������(�q'��[A�	7��;+�'T�q��<���B!L<�Z������r��9x|.w�y��T�g��b��3�/b���4|��=�Sg�����>�H?����
���K�,1V�*L�2�<�,'O��3U�����|��w�����X,����0a��O��l��������?����w��vi���;<x0�f�"==M���ao������BE��o������t�v��3g�W�&��'�����V�3�x�	TU�O��6�mAS�Ne�������,_��7�x���^����qRR�a���������ZTU�j��
��
	�!D+X�b���>����*���(
v�������?���OK��9$;;[����HG���L��x���W�|o���gBW���Z?����ZA��;Tg�9������A�s�/�.��8?�8��m�u��x�R��4�B!����X��_��6��`�
����M����^�k��U���b����������Y�������i�����s�����/��8g*''G�*)//����
����d���,[��_���mV���t��G����M�������nV$P�	&PPP���W\�O~�����f�����;)//g��=�|>��HNN���Kmm�~|�@��
%x�^���
��-IG!�RII��K�������D@��W�/��s�����Q���<�G�����`���x<��~��,<�3�0Y6���U���	�����uy�L�6~N��P�Q?��8�q���gi�nOKB����-c_���s4�S�v�z.��|�^�5��PQnD�oB!"As�h"IEu(K�%�����tc�������y�s��:��wFu�X �}�t:�4i�{�����U�V�r�(,,���^��g�m� GC233�:�%�`�	���:�u����*.��������+UU�����������D�� �B��o�������o����ix�^�V+{���������E�dff����~?�w�f��1�eB4J�yP����H������������k��m>Gw��	i��sS�Vw��4���Xz&����:�,{�d�����������I� �9���`(R{��{
g��`v��c�$�#�B��y��$�$�q9���|����=!��[-6����<�,���&u�V+�>�(�G�o��n��w�5�s��BA���f��M�����k�������R���Y�b�_*#�y�f��_���5j��x;���k�4��5-\������f�+��R2K����1�;]�"C9� ���b��E��������#����Z�����|���;v���x&L���^X�M�i�&V�\IEE���L�6�^�'UU���o��u+^��~��q�5��+]TPP����9~�8���>����7AB����
~�4�^h����l6���+A�s��j%++�
��+rrr$�#Z$P��n��kR�57=p�����(��Z�,�9��>��u�=i�����X|����,����������}�����z��c��d��L��j?no�G���:gD���C����d�
�����j!�B����������v�U��^�	��3O5��+a��K��m��W^!��g�����������7���	adT7p��V��^m���^�����j���U��Z�V��V�*��,��R@ !!,I��{23�9�?�9s�deI�I����W��~�'L2c2s���<����������u���v�����V�����3gN@ ..�k���7�x��7q8��U��s��������=���}�vv�l[Np��IZ',������|�������qz�	��������%�/������b>��#����=�]��c�?�8k����r�k�.^{�5�~���u���?�������q8�[������n�:m���������w���������l�2{�1>����};�>�(+W������{���{��������!Dw466������Nl��Nc����w�����@=w�>���8�H_?��pU�8�k]���������������]p��V"�$�;�`��#���qP��u�e�f�?�����;�\����Q������sB!�8%�����6�kR�9Lq�q�W(�BXXqqq��7Ok�x�bJJJ��/}"���#u3~�&M��<�����hRSS��/666`]5`��6?������Mtt�v\S�yoN�|BBB���Id�����TWW���3~�x�n7o���W�f�����;�xI���k�����%%%����SO=�����5k�����E�1j�(~�a�v;�����'�d��L�4	���_|��;�������Q�+V���o����C�h�"�n7���o�����r��3��s�N���1b���
!D�bcc��������h||�aF��1c�h��������i\&D�Z��_�^�����M(�5�9X�BU������!�������l�<#�xX�F{��4~�ZKv���L���c�O7N
E�f�UxwXW;�I�c�Oc������uk���6u�� �-�D��?!���]1�V�mg��5�)�9�*IC����P��szo�����o��������7�|����{�AT���4@dd�n�/**���0ZZZ�M�>\pA@f�t�������w;z��n&���������T���i'�m������73a���xK��|���L�vk�_����.��r����[1Aq3 IDAT���������a��-CUUn��-:;x�`�;�<�����g��9���\w�u�/�Y�f�������o-�������a�o���c�PVV�B�����u-������huF�8���e���
�o����s�� �P�Lp�l����N�����:�!�q����uQ���J��-:5��9������_�>��������Oz���B������i�Art$�������mpB!�89f��Gn�=�]�����V������sw������
���������_���c������|ZK���������>�3HD�a�#""���8���;,���~�����5���vBA�;v���KJJ
o��&�/������}��������u����8p���S^^��Q���D>|8���Z��C�j�s||�,����1!�����g��l�f���M�(���>}z��"���JG�� N�e�D��M.�+�zBo/C�����f;5N+�i#1���g�-&3��y��(v��Dw��_0���)�n�aH���^���m '��Y�@�8B!D�PP�5�
������o���~����[�����	VKp��P�;��S���������U��o�=x��)..����&�� E��Uy���B'��<��n6o�l���'m��:D�9�O����)))�o�)���e���8p`�xLL��PYYISS555��;�rD������?������������w�������/�`���L�>]�8B���y�P����n�f�a�X��l���a2������n0^.�}_�}��u�7P��������A��(+�gE������S��_J�G��tDQ0'�������YF|�`�X]���5����8{K�/�B���&����2�|F�H���{&eeeq�%������+��1c�h%��/_���������j������__���
���
��C�����p��}�����y�9�W_}x$�����k_��O�:�����mkZ�l���#���QSSV��M���(�l6MMM@��������p8�����Q��x|)y����y������,_��!C�p���k���S�����==�����������t:vF��A���������'�z���tEUU"##illDUU�/_��Q�������9�
��"�|���
P|���_v3^09U��`o���>���'z}OT�_��z�{�(%!�q��c��'i�ve�fb��<{����Q��{w��K<T6���;{%-�.	�$����_����=�M^~^P�����y�O���G�S!��k���
6PQQ��
��uk�Y
n�����8���g�P��g��m�������q����{��l������������g�y�������L����Y���	��^h�
����CQQ����/p�M71|��v�;�1c�����?����XF��������g��)�+�6u�T>��c���)..�w���^{-�������p�B��p���/����8�RAz��������x���7��j����m�x��WILL���.c��e��;�p��ww����3)))����������C��Z�(
���Z)�}��IGt�\sH;v���rB	�=nJ��]�*%���7K�R��������-�]��Xy�2q2��~8�q�ej���O0��+X��r{�+�T������f��8�����A�yCK-uMU�F��
!�������v�m��������f��QZ	v������M"����j7��g���xG222N{���/f���l���={���SO�`�X�����r������5khnn���C<��s�������qF���q���m���<�������:111c]�Z�<��C��?���&v��������������W����8�l��6���l����v��z���%���JXXX���oL���X�u.��7�x����x�	�������GV�\Iff&s��1|����N}���T��>�������k��L&=�P���8Uz�g�[���hhh��8 ''�MF��X0>�=�i�g���Dd�")����2[����l=��n�33����T"���p������_�#jW�o4��1q�1���T&�9�;�������2UR��]�
�{���H�������������{�+��vs�@rs}=d�O&����BQ�7�Br\e��%�����\�A��T�<yN�yN���'Nd��I|��wTTT�p�Bn��V��~�l6����d��.]��<yVV?���N�������������3N���������3���H�0�����w`��A<��3����l�����Vm.99�k���s�9Gw��M'�1������&<<��Rj��iSRRBuu5����PSS���$''��b���Rw�Wuu5III]>�����������K.a��n8���]w���-[X�r�	q�b�.������~���F���l��v���HQQ������41a?��?�(��W�q_v���)�3,����A^,���V;�[�[U�M��~8��_'��J��Z��X����g��8}�/�)�'@��y�jr����8��3u�,�B!���}�Q�P�~�s�U�_|�8�m3f����9s��=V����W^���_NQQUUU(�Bjj*�����'l���<�����q���������|0������I��\��������aM{0Fv�����'�|��>|��LTT)))mZ����$|�AZZZ(--������xRRR�z�ivB���,Paaa@������2F���>wjj*;w����0 ��o���FNN��0p�@JKK����"�������cTTTDXX���l��b���{SB!N�>�#������p�
������C�8�S�2���`�(�>�l��\31I7����8�Rj�]��=UL�I(�HT��d�W�a;s��1A[� =�_���q���A���sb��[X�?����!�B�`RTT�UU:^����&�S�d2�������cbbN([%�$$$���`>iaaa:�8,N�
��9����u���������/GUU�M���mjjb���4(���������/������/_��(���1c())������+��_s��u$&&j�j
���������������1c�Em������J� n����Ejj*Bq"�N'��q��1c�hA��>���������y��'�	@u6�9�K��o��7����v�}*�y����K�� N����o�:����i��K�8"�$���`��{���L�	�A���a�Z���05���4�Q=��8�&�B����W^���c5r��u�]�~�����P'&&�Y�f�|�r�~�i�=�\JJJ�������H�[�t)�|�	�����/k���'�������y���9r$��mc�����5K�����K��������ill$..�������Z~��k����J^~�e^|�E������d��e��v���j�|8p �����?���'SUU����o�+!�8{��������1x�����+--��o����n7TTT�y�f�O���7�(e���"�X��a���$���w����t��@s!������H,f+�SN�6w��:����v���z`u�^O����d�3N�v�L��-.a�>��?J^1�j����O���I�k�!�"8�}�������e��!�!!D9� ��y�0�L|���,X���<����j�eff�(
���DFFj�&��Gy�?���l���
6`6��5k��v��.99�G}�7�|�%K��m�������u��M�����>�����o����{�2����������g���*!!�n��I�&i_O!��������1���Y��555��?����<.�Kk.h2���l�]������?�Cj�
C)��A]
�������}]+
����L]?���0\r��c5�|0�y��;���.
�<N�����+X�m�jV����ZC��1����p�Y�h�b���k�a�B!�8m�����"�p�b�p���s�M7QYYIDDqqq�eL�:���\"##��?�'$$��#����@mm-			��P>|8�?�<���8�N�Z��e��5��3gRVV��l&11������T�q���!,,,�'�B�����������������8���Mxx8�7o����c�����E�.���0'�l��SE_J-��M�~EWJ��gX�m��x�����m�]���[���*�e���{�q��2)��{*[oI�>�)��n�h��<�P�$��!�B!��9�m�v�����v8>			m8zQQQ������0`����p|L&)))$%%�	��EEE���!!�I������C����#u���khh`��5��7�>������,r��e�Y����	�5�Rj��������~8�����CWW�*�PPH��fJ�J_�������o2�!�B!D�N:�#�����=@ll,�����B�:EEE�����i7���v{wk���_;�W`'42qJu�8iq=_B,����a�v�qz#���8�)O��PP���)�C���8�)Ok�qH!�B!�$A!�8I�Rj#G��4P�=����x�p p���#���	Q�xj�7�C%��/������6��f�����Jd@���u=@�{F����=(�I�.�S\�-����/���5�8$�B!�]� �B����wk�RJ�����4�:�������]�}���b�����
N*P�+�����8���T�e�F�����Ac�C��d�i

��_E�G�7(��6�t�����4��B!�Bt��;NB!:U^^NEE�v.A��g�������(
f��8��X,�;V���9w��N�j�Ziv�o�����rj�����Rj�
�X2��o���M��8���XL���
�%��
��������Tv��_B!�B��� �B�}NJJ
			�Y��L&n��{��f����Z�X,�v;�\s�qZ�3�p��������n!���u�wy�������q�e���z�b"�O����Y�ywaNa
f�B�.�X��
Y���
��{������i����
!�B!DwIG!N��R�'O����BQ�v;v�����f#<<����(�|��0�x��g����st3�K������*�������]x3H��{{��+����NI0s�`�o}S\��L&�����s�4���x �DW�/�����C������m#p�
��hl�7.B!�B�NIG!N����(���w��-����n�l6k�7��`2�x��G�>�{ewD�������	^���q]g���%;���7��Y��j���������x���z-�c2���,$|��X2F��u��?�^0{�6+}_������c��f�L+�Q�=C���OxX�v����X!�B!�C�8Bq����ihh�7�G��6�w(����3y��������;w������`�Z
W��Hm��SW����C��Z��Ij?��q�:x�_����@n���<����l)X�g��0��[���E�=�b�������_&=^��+�8z�4H�\�
)u������Q(%��B!��I�8Bq��Y8YYYDDD�fE��)S����:��~�.�q'K�)�HL������/���������������������+��D�9q�v���9��k�>�����9q����>$�l�q��������-��?'�B!�� A!�8ARJMte��Q����"�/w�����l�`��tS�������rj�� ��&#�Y7f��7k������=�u�f�����n���?����p������16�&�k^���l�]�e#RR�S��B!�B/	�!�q8t�~�!�?�<;w����7������+((���#\�O�L�����+�f5���K���0,�_���e�ps�����b�P�iY�uo���Tk��S_A���I�W�k�

f�Bj�?X�K��
�?p3,�N;��+���B;B!�B��HG!�����E�1�|�/_N^^��/�v�Z���tW����l��N���B����e�L��/��k��}���
����������_a�p�P�p�������'�y�_h=��8�"�A�n-�[�9Z�e���1���(���G'i���#�B!�8�B�nx��w����PU�������p�r�X�~=/��"��p���,��
�������{&3}'��R�N�����i����"�c��4����������E�U�i�s��������uG�Y���u��-�<����������!� u��I�g�HG!�Bq$�#�]��m���GUUZZZp�\��n�n7.����f<EEE,[��x���������t3��Q������(�N&�?KB���/�3�r�u�8����N�0]����:q��h�P��=xj��OU��������"r�U>�T��o��B��/N�&r�r�S��B!�B	�!D/^x�a��i��*N��&�����I�@�g��}8}�������)*Q7�3q�Gg���\?i:�7�
B��
�X�V���q���R{��@m�7�3�^��������}�XVS'�6+�T�C����'�r�t����D�6UP����B!�B���'N!�a---8p��{3�=�UUinn�����i��
4��po���MAA�a��/���Q�II2.�JY�?���S�j�����Z��o�c#��u�cP/eT)��P�����-n��?���;�����6��� j�v:(��}54�QV]��!�B�5��'��t�n�:��[GQQ�qZ��WEF�-�-aB!�hh��������l����CA����a���};���s�=_zIwy���9R�����lR��8������cY8��00>�I��p��;�
����4SL�����|�Ql��N���P�����7A�+o���!�����L�zo	<[�R29\u�f�����B!D����2a�.��"�TPr������L�:��'�;�m�6>���f3�=�V���������/��E]��!C+����:eee��7�������M�6�h�"rrr���;0�z����U����/9p������vF���9s3f�q�1��jB���((��1���{7�Dh�����������M&N(���RK��b6u�����[����s�E?��/��������7G;d�|-����j����h}��_�b�����%;m�vZP"}q�B������;v�z�j�TPr�������]����:�t�<��_x�����w/����F���n�:6l�@QQ����q�W,X����b��N�����N�����_���_���P+��p8��m�<��-2\%B�q��6��a��%u,����f3��Mff�qZ�s��8������~J�'d�8���U��G;���qr�Gkc�C��yX��A���"|�}���"6�����;�k�R���c�!F��h���B!��+V��*�����w9���F�y���_o�������W_���� 22�_��W���s2RR������)55��JJJ2�����y���y���S'����g��M���s�-�p���2s�LmC��E���y��2b$�#�]����Q����l6Nc2����������^O��/##��o?��#}q�!��OC�v�A������p�sY(k�c6Y<0W��40����X��g4��1D���58���;�am�vvdhRx�(�`�{�v:2��/:����e��Bz�n7+W���W�Z��2���<��c��u�M>��#���f������c�i�a{��#x������{��������g?�w�uO>�$�����>K�.=���C��l�2rrrx����;w.��w��s<���v�����=}��B�����m���8v�����j�b�`��CQ�<�L�O�n�
Bx�h���o�����fE�/����b�L����j�v��2qt�������� IDATP���a
��d���D��_"�y
��I�{L��	���6�Y�+N/�I��	mw"v��I�_t�8��0)��_W����W!�8Y�����h)��z�o
����|T��i��l�BMM�v�v��n���	��8@SS���.������{���m���%K��x��COO_�#F0s�Lm�mo���`��Y���/^�X{M�y��������L����9t��)/�&zO�U �������g�������M��d�l6d�(��W\��9s��;G�O��g��m�q���~8C!~WxT8����wz>���j��~8�~&���`{)�����a!MK�@U�l�F&�������Sf��gL����g�L���`n����l��@A��d
���B!D79[[X��[�.��8�����a����'�z���XBBUUUTUU�c��<�LmMKKG��e�;~�MMM���Glll�|cc#yyy������4h�����w�����o`x���Y�v-����������X����[o�����z��gX��ZZZ���
���!<<\;w8���W!������w���L\\���DFFj�Q\\�����������=���
�n���d
(�VWWGss�����U{�}p�.�K+����EVV���M���;��s�V�M�	�!D/^���QU���TUEQ�f3&�I�_ll,\pA�=s�h�/NXX�n���\�pl���
�A[8�j�r*�������&GuC�F�4�X''��8:�d�q}�0�(
<|q&�+c���6{c�&��''3g��L3������KtA�]��^!����j���PV_l�`����������~OZ��t�(//�n��x������444�z��� ����7��
����D^z��v�|�	K�.��'���8���,\��e���r������MKK���������������n��Ff��������sK�,��wF����_nX�����;���7`��;���.���m��K/���Q�����o.\��%K�^f������Jaa!��_��>�����?�)����o�2������k��|PJ���#��g?��M&����v�]�����#;��9x�`�X2qBW�m�B� PSS��yq8��UUimm��t���������F�A*DG�/N��6����W���c�;�@m��k��-
=���JwE�)���Ri%���)�J�Np7�V
�;�r����
]%��&h_W6��[�����r��Db��.>#�K�������5����`l�?x_Xz�5��B��|���OKkl~���8�+V�X������1y�d&M���M����-�u�������q���^����>|�6��/�d�\.����k=�������������6��&L��/��\�a��=.��/�����]w�u\���v���g��_�����Z�������y���y��g)))!""�����C��?��?44x?+t�op{c�j/'�W5�4�&!�_����L7#B�lB�v����������v,xw���fv���UW]e�B����/�6z�h�*�'�>|W�&����k��2b�zL'�����T�K���,��s�1����Nz�`�� �D��D��6V�l������5 ��axT���+�m>=7Wz�)�'@�7/'��=XV���������B!N�����+�?�p�Jj
�x��
�k��Qn��o����'b��9���X�r%N��
60s�Lm�E]��0���o8������l�B]]�\r�6��g��}�v�
��>H||<k���O�n�����v+A�h_��7j�g��q�\��M�6QYYIxx8�
��s�e���=��<y2/���w����_7N��s�Nf����7�LTTN�����h�"m>,,������c?|�0/��2�������/�����������������}������~���q��Q222x������[u���?�=���m&�;%��q�����K�p���PU�;�Ep�����g�aV��Mw��i-�I���6�6��iUT�����l���Pe�'Y8u���I�5�F����6z�a�����lX|�u�����O���q�=�,v���7������m6+�B�{m���O���^y1G�0��#����Wy����n��-\6�&.���a�[�l����IF�MDDMMM�Z�* ����Enn.���Z�������+o��i���Z�/_��f����?c����������`���e�N��s-���[��,��SS]]����o��]�<���3�5�v;III�����5s�L�����f�q�5�������;�����<��~:55�{����{�;vq|�.V����^�������/��t��-��"A!�h�o�Bww��`	�_�;x�$����4��'�[)B�����m�h���, ��[�������������%���v�&'���j�L_?�� ���cN��u�� Nyp��1�gw��8C�M�����*���z!{����� �B��d�7��H�q����#��mFIG�89Z]n��������8_}�������;o�X?~<k��%//���2����k.��"���q8�_����?_��Df��������XC�e����'O�������:Y�������!!!�)S�Gii)k����v�e��y������4jT���322� ����OVV111����&^}O��J�)����I�8B��a���?��?v�������1�HUU���^O����-����g�������;������+jS
��"���&��
��U1�5�rl���]U�u���,����U��~Uyu�~8�i7

����rY�e��q�z�jt1 �ww/���nYZ0&=S�H_!�����3������x������i���q�9�8����rv����)Sn��u�Y�]�UUY�z5�\s�67e�����R[[�7�|�Y�j����I��O�^�4�pz*o��Kyegg��������s�����FUU���.��R�����%K�P\�����_��!C��A!!!����S�s��o��ne���GZ_#�k����v���Jg;"�IG!������������f��t:�rL&V�����^0'��;�����k��(����(�L&���Y�`����p�
�+E(Q[��C]R����Smu~�7��p|v�4�rO5�����rH�[��8�T�x? ��@&�����PHk������P����YR���A{&�R�y�1�����������B�~����01��'���`�����q�C���������b�0,�����X�B�w`�73v�X�v;��U�Vq��Wk���f3�f���O>!??�#G�����K��u�Y��"""������bTUm�)���D;n/S�D�\�����7��&�4r�H�O���5kPU��7� ��}����7i���
��=��3�7o�v���;�'��P3>O"tHG!��(
��~;O<�N����������(
�E�+z�e����i�
B��j�������\�L&-�c�����/?~<����/!B�):�{�A6K{L��C�J����%&>�Z���}3�PJM��cH���F� ��T���
S���������A�33�������S����{;\y���z"����B��AA9�
2�<��Y����]����\1�.#S�S=��v��7������s��fc��ql�����r���1b�6?{�l>��S���p�
�����G����\r���g��I�^����
��Y�9����y<�.]��O�0A;>����� ���3i�$��Y�-�6`�RS�>/d�JKK(��c�����d��`j�~�T�D�� �Bt ))��z�7�|���r-e��l6s�W0g���q!�TUe����w��/�������`2�������/0'B��%c4��mw����4S\�/����EE��8���FeuN���T|]'��'u$J�����8��x�FoYw���	�|_�mj\Z�����L��8���D����\@����9�,�j!�Bt�b�r�����7?kS-����w�Z`��-�
�������>�b��UA���&N����Y�z5�_��������}�������y3MMM�������1z�h���X�l���`��i�4�%22���z�v{��X���mp���t3p�����@�=��q�
}@���#��@���
D��Dh� �Bt";;��s��`���IMM%''�Y�f���f�B�@�����)���epy<-��d2i;j���Gcc#���^"�D\�s����[��s2�����;��R��f`�q4���P�Q;��qNb�ho�$g�*�w�>�C&V�t]_����K@�	��8����~[
�����]�B!�CV������D}��7���l��Q�1c������W_i����v��p����v�mF/��"6n�HUU7nd��
��WL{RSS��/~�+��BUU�-b��Ek���=��0v������g�Vz��I���Y;��������1��km��}�qGYS"�IG!���cx��gs�m��f���o'���Z��t�V����=z��C�j�"�X��6�6ZV�c�
`�|-�����$6���;�
p$��Oi��A����!� �9y�.�����`����*���A����X��BO3Sc�R��*(��V!�]�:���`e�?�s�;��������8����&)�w������c���Q3zt��t:DQQ---|��w�sF�EFF�������8�Nbcc�:u��+4h3f�`�������l&>>���3c��:��o6l{���������vK�8p@;���9��}	�@�>�u2RRR������������HHH0.c�F�����p�n���~B�S+//O;�?x�xEDxo���9�6�mUU��t�(
f��
6H'�E\�S,)�i����l	�S��D����W��.�����t3"5�FB_l@�+���!���w25�{�9��'T�8�L����71a���y&;����{3�B�9FL���|kJ�7|�Bq|"l��usG����+V��2,.��.��2�
���w��SO��j� ��^��o�Mc����\�m�3�����'��b�������KLLL��1����SY�x1�}�Y�L���g�}���?^7�}���������������9BUU$&&�EQ�4i+W�DUU>���6����k��z�f�
���� �Bt���*�~��������FDDMMMx<�6=����l����7N�P�(��\���[[�n�i#	�z#��sQ"b
�^7M���np�Y��C�	�q|������������ �>o9���~�b�-D��49��Kk���?�����g��Pp3(��A���h����
b��]$�B�P�v����o���i�:��1b�������s��6��s~�!���X,f����:���k���f��!����s�N���8r�555X�V
�9��sJ��2�	&�e�V�\��d���/&!!��G��������
����{����0���)))���������K/%''G+I*��C~~>���
w�y'iiiTWWSZZ��g�i��k�^z)�W���v�r�J�V+�f�BUU6m����~
@TT�^z��jJ$�#�����oS��RS����db���l��9��e{|�������]���M�������]�2�8/7�o����:2='��Y������ N�d�������\���
S���i0R��8{��%%Jk��kA��������2#�q���%��B!�������2���h8�EQ�<y2��/GUU��Y�W������8��s���/�2e
qqq��eddPTT��/�l����e�/������s�5N������'�|��G��b�
V�Xa\BBB���q��\{�����Kl���M�6��+������/��������*���y��G����t��y���IOO�����O������_���_��Z�������D����B�2})��9"��1cI�����Vk�kEP���V�L�`t�9i�:5s;��f������z��x�q�A����qB���)��A�]�o`�b��{��oG%�n�����[���_������qX!�!@�8���u3�2e�v�j�*����^xK�uf����r�-���a�����!77���?�K.����G�(
n�����/Z��T�����'������j
,��+�5���.6e�~���2p�@�TH����W��U�����������s�=�_��W����������g��q�)b$G!:�g��X���5x�`�������A�3"y��Q[�s}�D02)p��V�h9)�6f����!1��}p|��k��.;��#��P`N��STx��X�N6�.����e|w�^;R�d�we|����&%s���B:��B���;�d?���B!����>j��g��|`������������7���;��s��5�/�o�.��;vp�9��h�����9s�������{����o������Zl6C�9����Mc��i���QYYItt`u��c�v���2eJ�s>���c��y�����o�C���oj#%%���~��������[rr�Im�9r$���������2TU�j2}�q���G�*������PPP��j��j��\Ql6�����?�0+B�>���7f+����#��3��r}�������-iah�q��*�@�����@�_y2���Y��r�\��V�`�Q��:�c������\��8d�������X!�����1r��=mKK�n������R�$99���d�p�IOO'=��W9���;��3<:�,��������(�~��X�V�V+v�]��Q��LXX��0a�&M�d�
"��Y{)5���v�o���a���I�M!62^v��wY�v���%�����������<���S���F�mGo�n]Hr7G���g�	!�BtEUU��y�,Y�����t:������gee�f��B2q���~8RJM�������>�~�m���1���%�;�y���T����������U;O��A����+���BY8�%����/��
�p�������D^�kl�/
�?
<*|�]�q�C�����C�����
&;x��P�Px�Z�B!�������u+[�n����'���'##��Myy9�7o����Id��1�,�G��$�#�� �8��<�L�z�)����u�Vjkk����$~���H��gE{?�R]��b"�/���i�o��G5Q��-?��6J�*h��f>�6���:i����SG`pz{n�j���m�Pay3�.��, `�C�\���8��j5�����
!�"8��g���������k�K�<y2��w�qX"$�#���������SX�8�T�����[n��[na���<���TTT���Bxx��
�Twy�vjN
���Rjiqv�EHQWJ�@c.�7X04-42q�W�����8�����i�o���O��^U��������V�c�=�BN�P����j*���D�2N!�Bt����f��)l����[��o�>jkkQ���xrrr�>}�d��$�#���g�H?�S���������UU)((`��1�e"y���:��<B%��Z�'Do��Zgw�?���T��%����m�S{S�@�T��;��1��M�
9�B�]�v����`_��#���m�M!�B����f&O������SB�>"�!D��Rj�7(��#J���M������
^�rj��d���{���� 2�3OS5��J�p�����C�*3�N���A�!��D�B�#K��0aD�5��b���#�h:�V�N��#�B!�>!��H!z�qDo�q���u3"���8���(�������A�U-����u� Nv�m,���q�k'r�)d6)\31�8��k�cmP��z�9C�e4P[qE��NKw���B!�	�!D�G�&��k���8���"t�����P	�8��0� IDATZ=�����~���+�V�Ie���\v�(m<��"�Q"����R���C����	�L�4�qnnc3����A��I0�1�����R#������c!�B!�	�!D�,���D��#zTFF���>�����
��e��1T�8�5N��jVH��=qt����E��Q�	� �	�����N9���8��~qq&����W��p��d���j��#L3E;���HG!�BH�8Ba�/i%Y8���L&�����������RK��cRt�}�.���&�!�RN
�o������^R
�n11oZ
����1���hs�F�q��D�}�E3M;L��h��
q��A!�B!�� �BH?����3	��>O�aTW�vnN��
^%��~8�������M���Nz�`�m��VA��/��-�N��GO��I��p�@f���kq�V�Q1S�����D���9������B!�B�IG!t���9z��v.A���8EEE�'���pL�)(��{�RC&N���<���jb_��&z��R;��f��)j�����N8���������L����+(���B!�B�{�B})���D���g4(�/Naa�a�%�2��*�� ��Zz|���SU��v��������{���3g&�}�$� �� **�{]�V-Vz�������_������k���*��
.�Zl��EDQ
"(��H	!���}���|������%2���x�����3a&�$�9��~����py|o�����'�YG����":�q���B���;��D���1�k*���w�
	���U-}q�B!��B)�&��b!??_�7E�	� �K�R����#���?6,g���})5���?��7����},�)��/��<�#%.���w��CBv��P�|>F,CI�����vi�q�B!��B	���"}q"�;(�3�0��7;�^��E!+9r3q��Z�_>{�1I���1�P�{/�T�X(��v
1G��Q ����$
6���|�3�"�!���-��k��i�h���B!��M�8BqHSS����x�����tF�]�����S��.�8U���-;%�r(%"�8\�����I����
	v��8����owm0�&E!�'$�����K�/t|�,��e�BMp_�(�h�X; +9U�/���8B!�B	�!�!�G�#F`��.`��nv�D�������������Um�������}Eck�����g=g}�5t�(,�Y�v�gt��6���[�����BBN�!�
�8�AM8��a��4}�L�8B!�B�C$�#������#N6s_)����p,�CQb�
���x��x!=�������v}������u�����t���y�G�=�7{�g�DAGQ!i��;e�G�.�� �B!��G�8Bq�1g����!N���}�x>��a��K)5�`��8��XC&NO�����������7��{�i;�s�*���3�7;����%����������
�!�B!��HG!���f8��K&���aYY.W�e�Dh�j��pFfB���r�%P.�3q�e�BU��N2f�����g
Y�}����r���<4������������FW_�$w���[;��k���	!�B!��q�������t��#D^^11���'<i5����(��jZ�h�R��{�	N��IA�X|e���������=�b�P��:;�C���
d#��������%����7W-��?J���m!�B!D�� �B�d��q(��^X!NUU���HI�0��������RN�x�<+9����b���������	��=��SF�����'�cI�2���m
	�L0c�����#��3s}�vUKG!����=q�e���;6n�����^Fz$;������G`5!D42q�(�����|
�w����W^iZ!B����C%�up^�|��j2�R��~8~c�Z���]��s���Q�y��(zq��3n���1��6��PH�I���������H>��(H>tr�U��B!�o��;v���p���������Kjj*#F����Og�����8���/���h���Y��={6EEE�����{���yf�l�@�4��K�r��g2m�4��aUWW���oSVV�C=Dff�y�1{��W���!77�SN9�<
��K�.��������������w�y���|,X��2�9���>]]]��7�<uX}=�����W_����RRRBss3n�UU�����SN���."##��P�,Y��p:�8�N�n7^���NFF��3���T�CC�q�Q������u����~��8�w���vc����p`��cI�A��fC�1�!����Z6���~8q1�\v��\7{65�������m�,\�6�������m��~��M�e���/N�_b�|�;v������j��B!D8(//���BKK��������'�0v�X���nl^Jqq1555��^������Ha��O��	����i�?�<_}��1?��k��|�r�G�g�}��7�hZ�?6n���M�x���Y�p�iE�[�b


�������3u�T����HKK����V���7�d��Y�����1����Y�bEP�j?M����������W�/��/z����������*�n��?��n��6���c^���(!D�0f������FJ��e�������w����3f��2���2}�&�� 8�!�3q��k������&��-bDf~�ot�B�����<m}
�z(]`ID�U���� �9X����
��z�$j����(����������a���\6����xaXe�	!��,//���44M������j�$TII	�?�8�-�n�����(������III1
���v/^�W�8�W�f�����{�����/�0xQ?2dH��'Svv6


���c�IQQ���.EEE,]����$�����zy��7�����SG��c�z�jV�X��_SU�������K\\������&\.��W�������X�
RMMM������
/��"���L�4����t�W+�Q�\J���f!N����Q�(..|o�%��A�p�������(��1d�t��A�/`S0������PdI�"�����$���5O3�R.��P�B����PC���P��"#�fX�O�<�:�Kl���`�<nJ*�QR��/�>��+"1.���Bj~��_������\.6n������������5k�p���`�Zy��'��!����?��O������h����X�B��������+�_AA?�0`��������������"//��@��
��}�y��ihh��^�S��������?3g���[n�V�L�4�����[w�r���r�
7��y��wx��w�z����{�B�pa�1����qv����{Z��8�������K����CS�4�h�8����1C'���N�O!������9��
t~�X���{gHpbm%�8��+�P���� ��3v1[���q����T��/���iN!��N�]m;����hhw��R0$��&
�1$�l6������a��e|����Y�����+W�z�j<�y������W_}T��CAA���&>>��s�������a��5��o����<}D}=�MMM������UW]�k�5UU�;w.��w^�o����k���p8�����C�q�Q����g�G"�@1KKK�4
UU
+D���h+��p��1�R�H�!�:�M3��!���>�������1S3F�1
����4V��-%&=��2����� Nu����������7\�<�`36���
^�����>e����Qpn��Be����+��������l(m���2�b���+�j�oRWWg�	o���
6�z3���3l�0��]kZ���^{���6��=�)��?uuu���4���L\\����z����n��"N����"IHH`��Q�J����QVVFgg'�
�������7�����i��o�X����9vvv�c���ttt������l}����?��a����;w.+W�^t}=�������������������p�����jkk��=�@�8B��fl:���Jff�aV��1r�H�V+n�����={=:<��Jk���������B��q|��R�:��}w[} 0��A?kV>�CA�����N���J�@c�1RU���UU����{��Y���$�#�"������5��nq���yy��ZbTO
�4Kd�4��x�����o����g��U�%�*..f��M�/pr��w�E�����ox����,X�I����}��G||<�>�,��m�������4i��~;/��2[�n
�ONN���n��3���������SRRX�d���y�f�.]��<��CA��<�H�+�x<,]t7�p555G���1�4�O?�T�������q����K/�N7rKG��A��c���!���fc���z����	����Rj��(��wV��� Njx<�>k�<]x�R��@VZI����#����_����P�c(b<G#�������2�N�b\4:{����z�yH!��.���u��p��������J�������vnn�gH��N;������z����_�����IJJ2�����/^���IOO�������u���<��(�������l$%%������������{����c
�(���b����%��A����5t�P.\����~Cb_���={�,����~���i���
����O~����%A!DT�~8"T�7N??������KM+D(�jw���RJ
����o�Z���PJ���������A�pz�f�G�6<j>���x��l�TNw
�6����c���|0��������%��+B!"�(����u�}Sv�t��9��p�n/�\�y�XP-
c2����������������9��c�
��xX�z�y���$�:�,����5k�y��<xP�TIOO��r�����~,YYY��1�/����>��~��<��3����[�KO���3f��~;999x�^���k�,Y������(��5�\�UW]��n���C/;��xX�r%���o����C�iO?�4�R�~�g�f���,[���?��%K�u��H&L�[u��9��v���O�59��������f��vS__���~K}}=������������,	�!�V[[��������!��0��������"4e�d�2��.���o�/����8�Zt�s��a%\��Z�_�?5�?��:]����%��s>Yi�x���D��70&��� N��a�B���M-�m��2:�����{Z��Gm|v<��<�<|D���'33��J[[l�����s�:uj�rZF����I�F�rA��*,,��J���x�����[[[)--���>�����v��������������>���Q�3fPUU����7.��"����?&>>��o����"���(..��r�_#=�W���=m��Cc���l}�D�4�7�|�<LBB�^{m�2�R�~B�#0F������27b��5J���p8����7�D�	d8�K&��vw�Hc	��d�|s �7�3q��<��h
{Q3B;���o���w������7���JZ9c�/�36���8g�5	!�acw]�){8(�����_�j�M�6�����<�Mo7��6���Q<v��3�<��C��������iii���<��S<���!������yK�����f�1n�86m���i���0h� ���r<����]lB���uo~����r����������4��(
��~��outtPYYI]]/��2+W��_��_�6m����)r?
	!��K�O�P!N���F��w�����@�N������)�����l��"��`7���(IP�����(F��,Lk��hu���ZmY�q���qL�9���pf�����_���{����vT��v���_f�P~4k~��BN���I��N�<uT��]G��X���7���K'����(zv�������L�2%h�'6��+V��#Nc���e�<���:T���+x��ihh����/���.�@����o��y���7y��>�x;Gs]��q�7���>� ����_|��/�14�4��?������8�+%g�Z�����k��;w�d�jkkY�x1�����<y�yY���o1!��� ��f��qAA�K.���B���^_��EE<"xA���Rj]�`�� ���|��X}.R���� NML���"�����^��3��p�F�Y�.��=�����*^b,�'tR�����'p���`��)�B��1�q����_<�lt��;e(�����gfq^A�%J����>KBB]]]���kl��M���s�Qq�Egg ���K/
��������_��e���ysP����u����~����9G�9Q
��}�y������ ��Cc����ZO�9��n7.��
6�����q���/�����xx��7X�h�yY���[.��w�4J?	��P�S_z����A�A��V������Z�+Pk9�K���4��Pf,FCGA�_���1�L�1I��jC�������0�T}L!��F�iv.�vT���c�36�<|R(�Bll,�����?��x�����>UUU������~�����������{�* �/#;;��)))A����A��}o�����=q7��14����{����p���s��7���������w{�������"�H&�"*������III2��B��7z�hTUE�4:;;��w/yyy�eb�i�e�v��R��rj���S����� NV���j�k(3+x��w���PPH���}�3sY��77$-�A����W!�77��b���������srP-�"%%�o���_~���K/���?|R32BUbb���[O���Dbcc���
��p�e��`���/�C'���1c���EEEtuu��������o�>���IOO7�-��#��J�Rj��I�"���)))	L�����2f<�2/�L_y���uB�7������=t������������i�
M��b�C��������3����V}����Q�s,�BD�X���?�e���G��F$�����
���?�|��}7������>���":Kouuuf4M����=Y������@8�c8x�`��[WW�|��>����$�%�C$�����x<��8B�*��i<oE��j������M�3P�oh$�Sk�
_��������O�n�%7����uj�0�
�y=x�}�qBY�]%9.P4�pw�FC���K���j�l��QJ�!�~1V7����7���9C�~Z?�����Fs���H���C������UUx��7ijj2��>�L�={�&*++�����[}�p���Jc����f��1������w�y�[�������?WEQ���
^�$�#��
^�������c�q�w�Q1"<����d����H_��u9������XJ-%�J���a2"J�5�����]sTv�%�_��EEX�cI�����:!�F�m��;#�W?`WU��-�B��+s����S3�`B�i��-�:b�.�����w����g���z9�5k��r�L+�������N�j�96��D�������f�GRR��
�:���}��z ��t��c��}���5F��c�r�x����4
�)S�}OCUh���������G�zG��%K���NAA�yJ������b������Iee%��7/�S_�v���x��Rj!Tf�_4�8�;�_ 4?J��������������C���v���9��L_6��8-S��C�SwUq�����B!�?�_=�6m����M�6��w�q������io���y���3g�����n�Jkk�4kORSS������'�����G?���_����������7�a�������U�����~>!!�/����^~~>���x�^�z�)~���0n�8��|���b����������%%%����N'EEE�q��G���=�����������455����O<��)S�1cC��n�s��A���������������uK� IDAT~�z�X,����g�6n�H}}=����?����$A!DD�z�|�����������3E�f�������?���>JZZ��+1��}qv���]��s�qB��6�����0�����AC&�w�����9���f������8�������Jh|���j��B!���n��[o���#���
&L�n~O��x��C����1bD�A���b�����Arss<��rZ;v�`��-�p�B��V+w�u�qeL\v�e�_����N�����O>�����q��g����	&0u�T�n�Jcc#�-
�_�t)���Ac��x�aff&�<�O>�$���������B�����D���k�i��/�`�egg���������*)�&��h����8���h���������xp8��n:;;y����"$�;V���8�E3q��_��L������f
8�3�9x�c�.'p~��Pf<7�'���8���6��������B!D��6m��O|���~�m�����*��{/?�����\F#F����V��Xeee��CED_�{����3g���(��*���Ac'��8�YYY���7�|s��UU�����[oe�����1���W6����tN;�4���-ZD^^�yY��L!DD[�v-������������@zz�y�j��q�Z�
��Q�m�6�NJJ�i�8���8a�"8�������?��W������x�d$�d38u�y:��Y����T����bO0�=�s���M�C#1��7�%�(����a	.���piN*jJ�-�_�B�P����z��_��<�����CG�������K/��K/��<�+UU�������+)//���EQ���&''�������x��Ghii���dff��r�)��/	�KJJ�u�o���G\s��7s��7��u�>��y�����w��M7�����QU���D���zb.��1�����DC�����_���_N]]������b��INNf����l6�����P(;1GU!B��iTV����������*�!��Z����3�<���r�-r� cY�p	��ti�v~'FT&N�/�������m�vJ1�g��l���aI�����VW�5w�iUhI���hWis����F����F4k
$L�v_���r����� ���	�!���)//?�M��3x�`
d>.����G3zt�~�JNN>�%��Czzz�]8Q�0##����p�� �"b���^r��o^��/�~�)o�����i��`�X(,,�������'O6<J�^g��j}�&������*�������a8~�1.����<�j�(����jKC>���2�<�<U5EI|}qq&
���(�.��i��	!�B�?��Oz�c5o�<������HG����---X,<�y��b�����2�1p***x����x<�\.\.���~111tuu���/������ P���\�Vl�XR{��j���r#)g�����ya��U`?���H�f�qjJM��)'��1 #^��p�����(��v�B!N��3g���d>*#G�4	!��q�m��i�]��������UUQ���3b������_�5���1EQhmm��w��g?��y��G��pF���:����)���e�
��/!c^�T�S3�bZ�n�L�2��1 #^���f�VA��F��RYWN�����(�HB!D������CB�W������j���QU���%���j������?�6/�@���������c��_p��-��6'^P'�����L����aMkO�y���}��0��Y��T�
�LC�1��8	@��i�0a��/�/e�;��B!�O�8B��������_��f�j���n�n�KLL_|1'N4=Z����K��zM3��^/^����NZZZ���q�C]Df���g9������g�������h6��&c����M�3Z��H��������K����B!��D�8B��7r�H,X@\\����*��b�XHKK��{�a���*�#B��ztOE�3���1���j����#����h�t�������<r*��c�x��A(q����@d�JM�g|d��lCI�q���@ }q�B!��6r�G�JR]y��L�8�Q�Fa�H<[����\E�b��(J�9�Njj*			�Y�_�]mxZj�}c�C(�6\O����G�[�c-��j�y4�)
j�h����j���L�B��/c���W.��������E�*)��R��0/��#�B!D��+�B��P]]������n�s�W���/����8��S��f���ss����N'�Vh
���$gfCW���Z���9c�9���3\�6jV ���
�����1]�8g��VO�q��~�����:}N!�B����"*TUU���G�FUU������n"..UU���AAG����C��������^�a@3^��~8��x���<5�����8���UcO��gq���������?��B!�B��&A!DT��w��=v�X���+55�;�����dTU%66���8����NNNw�q���9�4CC��R���� ����$�	7�G����VS��j%��cTe�@P_��$�#�B!DT� �"�i�Fuu��?n�8���m���,\��s�=������iqqq<���:��q2h5�L��E�P���s������e`�0O��X�2(���i<_���x�fC�1�x��E��c��p� N^|����j��-�B!��l�BD��r��Z����/"�%$$p�-���3�����N��������R�,Zm��m�1�:��}��rSc
������>z��S����Q� ~�y*�(��X���PR-=�F�-���:��q��R�{���X��?��FQ0K!�B�(&A!D������G���f3�
>E!''�!C��c%%%��d�v4e/�K&���w��BjB���s���a�h�.��Qym�0�P|
C��4���Gci�P�C
�8QUR-q
X|W�Q��t:��>(+�B!��\�BD�}����c��1���}�$�s��p��,	����Ui���f�%_%�xa������.����UL6��e������~&�T3�v�x�
������e�/�B!��A�8B����x�2q���� ���;
3�d*��9}�BYP?���V�4|l�&F�����`���VAA�0(�����1 }q&�����V��B!�B��%A!DD��oN�����Q�L+�?� N]]���f������8�������Z��H��,e���<����V�����I
d�DU95���S�o�VKG!�B�h A!DD3��9r$v{�\�Q-==������v�2���f����I?��L�~k<����#QI����uv�i�o�
M��c}���c��p�L�Xo=�1��S����|�B!�B��%A!DD3��2f/�����z�jL���@�����@��H���j�
�����2�D%���%5[�7���*#1���t���E�{�����S}Y����F��B!�BD:	�!"���
�P� ��$��N��3��<m�v6�����6d���,�'��aJ�A�1���
��w�-��Z���Qj� ���j�l�i����]�G!�B��'A!D�������EQ����w"r���������0+�����%qJ|�a6t/xM���g���#����������f��0����2��OQ�����o�JG!�B��'A!D�2f'dffg�"�
<���4}_�qNcG�
��p���wd��9d��������]���X
�o8d�@p_�h���P�P/��%�#�B���������}�7n����7O�h�FGG�	9^��3��!��y�X������RZZ���L�8�K.����WTT���S]]MRR3f�����FQ����e���������L�?���R2�;�>���n����d��\~��A����������f����)S��B�0��x��u+���l��U>|�a��OQ������_g��i�U�D
��I)5�Z0^{j�[EW���<�s���AW���ZP9��r�h`Q
+BOP&N�qO�!�.,^'#:������{i�j%!6��!�B�do��;v���p���������Kjj*#F����Og�����{�����466��{5k�,f��
@QQ���>��{.g��	d h����K9��3���juu5o��6eee<��Cdff���W_}���rss9��S��8�.]Jmm-����v��d����y��w���g��X,'/��v�j�*���RYY���EUU���8���8���z=w������?������={hmm���C^^��~:s����f���V�y�N�����i(�B||<���L�2���:��b���A���~�a6l���l�����7��#�c~H7��m���� 77�~��-[��k�.,X���������+ILLd��Al���
6p��ws�Yg�_O>�$��m###��������y��G��4o(..��N��Q�����"$UVV��+�PQQa�����������SB��q���A��;w�fE0f,�U�p�;7��8����`�9�\��+��L���y!h\�epX,����B;�5c�yYH1qjZ��4/6��"#�%�B��L�f���je�?0e���B!����=VHhii������>������w���M���������{e�����Haa!&L����i<���|��W��\��]����q�\|��g�x���U�c���l��	��_���V��+V������{�>}:S�N5/������4��>_�����O<������5M������2�n�����{���G}����w:::�S8�NJJJ())���>����'///h�����~3����������;��{o�\���Q~��Whll������SOE�4�-[�?��O��Y�e�]f~H����%K�����G%##���6.\��5k�;w.yyy�����;�0a����~�v;{���w��+V�`����l6V�^��m����+���Q��>���^z����/���������'�|���=������nxfB�pTQQ�O<��ix<4M����(
V����z~������3d����K��8�P			��D��7���5���`�1�!�9��[}� �����s�>D��yN����)kK`�����@����G�������H�aS\���7;�k^�����8�f*�w���R	�!�!'//���44M������j��U%%%<���,Z���LEQ���1w��z=:���Y�x�a/��f���,_��}~���q��/�G��Eu�(;;���TU%##�<MQQ���.EEE,]���������������;�<������`��58�N�����Y�E]dz�/����/�~�z},..���'������TUU�m�6���$&&�Bw��3����i444�e�������g��E<��S$''�q�����c��-L�6�SO=UU������a�7o>b��������[n�E?!���ky��g��iyyy|���x�^n���[^^��s�W�������'�j�*����7o���5w�\>��c���{v�M�x��g���b����"��n^y�4M��v�r��jv��nl6_�W^y�_�����k@�p1d�������]�v�z�����I���tmx���`���6jFJ��1�����1��081��x]��E���&���*�s����h�f��85e0��}@�����bgoC�+uA�����k|VwUI_!�"���W�"==]�w�\l���������EMM
k�����/7<*�j����O��C^II	������7O���[Y�b���m�q�V����~�a8���3��'�}���W_}E^^^���
6�}�v��q�����/� --���{�={�l&M��������1������UU���k���+��q~mmm���{8��������������������G
ikk��O?��k�	Z��ts��m������0d��K�����5

�]��[���L�)��_��������SWW��	����7��Mee%k��a��}L�>�K.�$h�"<m�����J<N��[�5�����������BDEQ��qzJ�}�u����f����������yx���B�����T;��u�,����������:}*�D}[3�4�
e9i���Q�'9P�>�Z�lnvUm���j�B�(�uB�?��Mh\
�f���`���3g��������[�������������>��NCC/���~=����>�����=���j�����;w�I-V[[���{oYPP�p��N��g�TWW�������8���/���k�p���q�M7q��������f������KK��s���S&NU�������RSS��������)Q��a�O�����(<x�������.P����p��A����������Q�����PU�.��O>�M�?~<#F�0=R.�)����f�^/��a�X���8����K�Kc��e�_�qN����?Z��+�\������B�~�'B5:R������Z|����is:�(F9��H���5F��j��	����X���F�q��#��._�rLR�6��������t�,$�BD.T����M�a�9�#�%>0"����7��W^y�
6�����a�X�v�iU�^{�5��|
��N��
7�`Z�����hn&''��{�^jkk�����f��IQQ���$$$0j��n%����(++����A�QPP�c����>����b	�Z������������IOO�1pr$��i�>���[||����+W��W_}�^��p�����_�[4�S���>�~����p6������f��9�(
1118�$�������C>=�D�������={����j���?�!�����g���u	!Fyy9S�#3�--��?BD��tvv��wS��N_�(��9�U������h�c�BNZ�qZA�:m(���oxV>v[��:Fj�!�a^����HTg����q���L�o|3��E�B=�.�v�/���������{p�Z���W�H-���x�����o����g��U�%�*..f��M�/pr��w�����|�
/��B������������������g�e��m�����O~�&M���o���_�V
&99��n��3��i����SSS������d�}���,]�T�x�����y��z��<x0��������?�y�ff�������C��h������0���\u�UA��a��}�v_^o8�S�p?H����rF�������y���/��K���nn��F�8�<��/����~����9��s���B�~�<rL�C{{;�����7A`^�49���d}O����^/���tuu��z���/Nj���*�4��|�����_�W�C�5�> ���5���q���CW}O��Su��y|����/���d$���O���7���a�jC�\��P��s��#�����>��z����:?����Y�z�?�%����l�K�|��7o�@�:L_w������O�i��c*������1�,������1+4�oB��
��}q�i�����T�P9����A���o&))�{�vtt�x�b�*Lzz:���8���o��O<��(�����FRR���x�^ZZZx���HMM=���(X,�^�~]�<�u��(���y�x���x����������Kp�����k���3i��yf���c�������o�@FFF��K�S��mc�<T��\;�,&&����i����{<�n7�����w�c�u]]�j���k2N�:U?���������E�X�n]��8B��QZZ���RUU������a��~�C�P�(
�����/���� N���[��=4K!�4h�\��=i9�Y����u���
���4=�X�Rr�6�.&�M��*�3���,i,�p IDAT
x���vx�L����p�(�2,�YxP�l�rxB!�q����G{��
�VB�<�������������9��l0�����=����8�����j��Y���r��A=S%==����?�����X,dee1c�.��B����?���y��g��cG�l��1f�n��vrrr�z�|���,Y�����P�k������
��NGG�^v����r�J~����_���B�4�~������=���g�l�2>��s�,Yr��^�f�����w�}M�x���X�n)))�������'><�q��4��:555|���l6:::���a���tuu1z�h���>��H}
����566w�Rj��]WUUEcc#���'���&�^/���$%%a�Z9x����>����/�v���u��6s��	fLY;V=���I��T�iX(,,��UU�f�u���(
6�
����j��+��V�Q�X���#?��N;�4��S}}}X~_B�������I���S��
��n��`^v`SfL��$]�>�c�Ww��7}��$��j8�:�<�g����n��n�#>���m�CA�K;��y����~�����d������^O��l��J6��`Z6�����8�M�bo{��{���E9�-���{rL#���"U�2d�<Z�}7����W2�h��5+��GG���� -PR�h�_����L�V+mmmTTT�q�F�����S���2�4�������u�P��Uaa�~cnSS/��R�|kk+���|��g<��dff��(v����������������>Ea��TUU����
��.��y����xn��v���hjj���������t �Bd �p�
������_��V��r�]v���g�����m�9~555��/1����u�]�'���*���C(++c���������I����dgg�}�v�����8�w�.4����(
YYYTWW���Brr��q��!���ee��@+//'66���\�v�9c��g H�}���q��X�Vl6����/�h�Z����t	���c�P_^^���������5g���8G�:t�y($T��
��j?i������6�P)]�-�����U
��@�K�	�E�rR�z'����I�0	��06����q8\�T��3<S���B���{��������|�^�0��M�G�����<��6mw�u�y�s�,�������;�m����n��3�d���477�~�zZZZ8p�O=��?�xH\������yK�������fc��ql��	M�hiia��A�e��t���O�7K'&&��x����|�	����n*�����o����.��b���c|������fC�4Z[[��g���<����1��������C#N��d�?���������7P^�f
^�7(�����~�����"��&M��O>a���A�k��AQ}l���TUU�v�Z���j��57n���������b�0|�p���KII�~2������
�>�l�V+������QXX�����m������C�����b��p8����b�t����H�)����n��p��x��{7���7/� f��t~�<�V_)��Qlv��~d	AA��
��8��!��CFe�Z%{E���8�a�I���L9�95����8�fXXs(#���H�8B!B_��������EQ���VU�����)S����f��bE3������2U}�Q=y��+���������J���.� ������ys��������\��xMOc��p-N�>����J�0_|q� ��e����I������X,����[�����q��?�����q���zGPO(���&��.//�{��'hL�4���K���?SQQ���Y�hQ��1��>q����;w.k�����c��9TUU����2l�0�>�l}��~�?��E�����S��M���a�(,,��g�a���l�����B����g�\r�%�]���+W���Njj*k�����Y?����j�{�9/^�e�]������?�n�s����_�W]uo���=�3g�������UU���+|OZ6�,������g�X,<^�W�C��=(D��X,���STT��f� ��QbI��AZ���<�^���?�����?��,��
��>�7��C'���w������oWJ���"�����u�8�g���`Lr+��|�����S��
!�!'�YH�
�>�Sk�5�&�G%yd�h=:��P~��}�Y������^c���h����;�*�-�U�.�����Zz\��,[����7q***X�n���? A��q4������������>}zP���H/�6z�h~��_�7G�q��?�e���r�x���y��g�����oZZZz-�������z�������R��JUUf��Mgg'��/������{������F�>q�����ba���zdx��	�y��A�a���(
�:���_������7�7of��M�����s���[�u���<�����K|������[o
�a<������������7����_�B\u�U8>��#����/������}��U_��\]m��-;���x��$�p&!$�)��=(���
eoZ
mih���_K%i $!d�EYN<b�{���l����C����N<���~�xq��\��X�-}�=���#I����|�����Z��0p�\B��eY�����}�!r���#$q���%Qr.T9v�c�}�:x�����a�[|����FdC�N-�8j{�p���3�2)�3
C,Mx��
�P
e�T�U�"NH�Z��<������0J�=������;�B�5����tu��6��k�Q'��Bd�D��F�0�j��j�X�j~���l6|��(((��O�!n����3g��8~����^�F�Q�����{��x0^���n��Gw�E�����6mBGG����X��gd�7!s���>��bccq�wv��}�I���an��C�(���R��o��]w������{-[�3g�����?��d�#�<���X�V�L&�5�XNN^}�U477��p &&����K�,��������e�#��0���j\v�e����B�@RR�0W�8�����y8�N�<�Z
�J�J%�O��j�~�	6������~����_	Uz>Z�3�v
}$���[��f�v�x4�9���`��i�/�*3N56�YT�386.��x���=�gPC�n��<��H�$e_�9��x�f��8�j@E}	��nhT��	!������?�Q!����$p��F#���Z�������;������7=�,CQx����y*����j�������K�.���!����N�R����xn��+	s��b��M<7U{eggc��-<#K�����R	��������������h����k��d2�H�����#11����7{����B���l��q���a��h������TJ���V+���xzn�\.tww��8��T����!�(--M���r�z�5K�
�v����B����B�U/�:��V��o
�`\���TA�m��P�{>�(�D�*�I�X��A��|*����-�@�o����n��w���7�B	Z�?2^�~���oR������.����6��N����[%W�&q���n�{)���pxnN�V��:���s����t�>���{��������S���'N���T��$��.t���[	f��/$���f�����7�c�������.tuu���[H�X,����R���F��Nr��z�]FlL��}3��T�Z�%Dj�����
��]1�qfb�?xd�����G�C����j�U��QK�)�|���!���������@�e��{S�0�&��y���M&�����*�H��G�;�=Tdee	��u�����}��Z�
���7���B�#""���i���yUg���
�����s����~{��^�������$!$ y+���C��y!���Gwl�`'n�FI����6��8_�L���	A9�����i��>�VjC����8\C	0Lw�������U�~r��ZW�
G�����w6�$N��YHY�T�_oqB!$��M&~,��5����it�9
Ujj*.����ff�����'-�6o���)�����-O�6M�^hjjBcc�$8�	`�>��������E<�N'���	�����(p��W�������s��������v�e�X������E��9��!������pttt@�PweHy�r	CL��.mB��8�SXX��^z	���X�`�_�:�AT�#�X��jQ%NP����8o?���j��DJ��R���mV�;��������V;��M5��}�6xx*�>�[��%V�}ab�����%j��8�u]��!����$]��+��{��ESS����C�a������q>��C�r~�^��ky����H�\�R�<�X��O�S|�������/�����
��������_~���w���\|���?a�233QVV����k�����CNN���=�f�������xfE�F�����p�����=��vw�-Z�}�����p�%K��`0����}�����`0`������d2�����������8eeex���0w�\L�:���`�����};N�<����X,���z�<��j�����}���.--MH�3J�B�B����K��g�A�V�n����0�jO���3g�D�L��7r�����%%%��u+.��R�X��������Z�V�c���!\�4�w�Y���c20F	Ex4��V�\}�,�8����u�����7w�w_W����C�����h@�
ty�����@]��-�h��"B���RB!���F��n�	���ok��A^^^�Y�n�6l�[�Mjjj�I��'O�Q���4�IX�|9
q���<y�>���(�J�s�=~U(C���;w�DWW*++��+������������<L�6
�FKK^z�%���o����l0�O����c��m����c�������f����v��1c|�A���[����������JNN�5��UUU�7�|S�,�6m���na&O0�O6��`�b�
$''C�P@���eY(
0�R	�V�a`6�1k���UB���f��/����b��n8��va��q�������KJ�;��n���R���x���6�����hN3�&'D�"L{��B��G�5�s.�'�M�x�Y��@���4QK�I&_��b��!�Bdm���9s&Ok���W��e����k�Z��������?�Vj����O<���i(����(((�1b�e�~������o�-�����8i*�
s����/����o���x����l��>IZ���O�����^x����K���h`6��`�<��cx���{��	FT�C	X,���{��{���'N��s�����?��/6B�����/���
	�e�T*�0x�����R�����1s�LddN5�X�O��JET`�������&*�A��S�T�<m����SEB���
�	g�'�>���c������d�����
s���&D��[%�'pAf��'�B��W���t�O>��t	����K�m�����*Y�bV��l"�eq�e���K/EYY,�A||<������4<���hkkC]]bcc��S�N���k���"""��y��9s�kn���p�
�e�3�<#]�A������%���z����eY����l6C�<��~�a�t�R,]����hnn���@xx8]�b0p��7���nBUU,l6���`2��������d�k���Y%����������vj�����7o���Q\\,y!��j�b�����F����a�� ������{��W����+���	�"�*�<�x����#&�
�<*���
��J�������8�9PrQ�����{���t����Uh^�J�8U#4l�����B!d�����p\�����DGGK���B�@FF���xh0��	$&�	&�������>���a$''������8���WZZ*$p����������>!����3��v3��-��n7
�J�0���Px,��"����I��	�y8m��g@i���:!D�8���
�J���,9����`�Y�<�6P�w�1>����T��!�B���[o���V�<(W]u.��r�2!dP��N�:%geeQ�����N��\��t��tB�TB�R�h��p8���w��JQ���U��8IA���%v�'����{Y����.d�����<�i�R6:Ez����\����.�H
��H�����a�Y�$N{�
-5����#�B	Nhm|�Z���t�!d�P�������-�����x�8���y�t�^��<��a���_|�4Lz����1R%Nu��'+��$N�+��b*��
��F����Jg��I`�)��aa�*��������~n�A�a�������U�������!�B�����
�!D���#�B���nGyy�p��������f���j!��p8`���t:��<yR�G�>�6+��M�y $q��9�.�������J������Z�83q�pL��o.�(�)Cn
8�l�G4'3�Mh�VR}BX'�B!�6J�BZii)�n7@��!))Ir!�M��!..�Tz
l�0����q:��8�Ppq����%��ftF("�����p��h_=�����M������,�vz~N>��J�k��2,vWt���<����7J.2cu��~%����	D�$N��&��gI�qa�B!��(�C	h�y8�
kBB��	�coK5�V�Z
�J�J�Z
�B��a�ZQSS#�Ho��Js�g^�u�9<��il8�������<�I)�]�oC%;�&��.��q��E�2��GY��<3q�pL�N�I��#B�I��U0�3�(�u<�MN�
��fim!8w��	!�B!��$�4��C0u�T�s�F�a�v��t:�r��q�Z��=��������6������PsvN/9@c��Y�g\��7�'5o�f�c���SO`���&��d�86V���T�w�k�L�I�����>��\��*i$8E��qr6���@EC��N!�B	\��!�,�����2���8$T����eY��p8���
��)��������j���w\�����E������%V�r��i��j_��@��9���g�4$�1t��	��J������C����!p��������yp��j��v��XLK��.�p��kv�J������$������Z�B!���.!$`������lVh4�����J�All�p�����8N��SXX($tH/�n�vRrM�|_~v6� 
����[p�����:�"�Q�L��Y��?^�=���k��}�:���t�!���l%����p�r�m�Zq��S
>�$N��J��g;��!�B!$8P�������B!�(/�7�����wf��fCuu�4L��Z��;�='66���h�pJ��U�&��X�Q�P��t�S��.�ArUG����no��<�����BW�YunXw`���7E������
��F
`�BZ�'�YB�8�B!�J�B��S��cj�FB��Y�<�Xa�����H"���
'*	�Z'����p���2p��)������~hI-�s�������9�#E�C�c��j�����D�Tic�������BDLN�"<m���e�J$B!�B�\�|�'������O���!�.>>����`�t�LL�W���c�|���&}�������]?����J����;p
���^1.;4E_K�GU[����`Ym�O��_K�	�v����:!�B!$0Q�������*�
����+	-z�			�okA�a�P(�V����"
����8f�&��f������X�)]�-�M#]��:P���d�����~��|���`�
��]��SJ���h.���.��Z�B!��(�C	H�VjP*C`���,_��V��P��+^��l�[g� IDAT/Y�j�g���U_,�9�c���y��
k 7�1#*,p~V�:��������F�B��{Zo
��%�BR�vHI�����Q'R���S�V\}LX'�B!���DC	F�$NNN�(BH�*((�����0�Z-T*X��0P*���tP(0�������y|w�w���%�-��:���H�f�7��s�P�1�U0�jf,�N�l'����r��@�S�e2
����^�����R0�����.�����6�iSu�pzUj
���(��JB!�B%q!��8������<B<���������V��:�j�� //>� T*�����Y���������,��/���A�*����	`�$��l<�i�p
���
x���q���X�pZ"�����~lw�{��(
�AP�,�.���8]�4�.����0�r�#159\��:�n�tyB��z�O�����.$�B!�J�B�x�R�����%W��z=n��<������Gll�_��?�9L&��Z�s��A������^p�g�����jOJC���<���*��o���K��lBK29J{���t�}s$^=����$6.��K�{��J�=�B���c���'c�$S��I������u����V�{��Y��*� Z����:��	i�B!� (�C	8EE���TQ@H/���p��w��^��l�����Nt~��t�'7��O�8��	9�n��	�(z��T��w�����_���N��������s�_�����u�&w�W~�H�(��3���x����p����F�dZ��z���4P|�s���3���UB!�BH�$!$����P+5B&�%~��~x=��:�r���"8Nn�.�F�(����7R����M���*������L����9a��0���������`�����J���\Z�������Dk�NO�nH(��m�����${!�B!��8����v�Q\\,��7�	!��$N�\e�K���<�_�$��<��K�X}I�0eu�������19w�Z��_!r���10�,���0�*��H�6��bZ5���G�����@W�t�B!�"s��!��3g��n��mN�pq���MMM�hhs�Z�K��m=gN�E�V�8���c�i�+��m�TJ5Rb3�9��Dh���2�a�k�����{������%�)G�'�3]%�B!�B��Q�P�U���P�}=�	!�3�����i.��"b�t�_�_�&9�v��������E�x�������t�9�Lf�e\�p����gF���)�7#���W��X�te`����B!d�����E;����w�FYY�4LF�p<�������O����"N�P+5B/;;�����7������?~<&��A�9��_I����,�.�B��
G�R &������p��PR|B8�L�Vj#�5��8�Q��l����IfVZ����	�8@��+���1j |�t�B!#���^�\�e��IC��q�~�m��33f����u��a|���`Y�>�(T���\����7�|�l�2���K�����x�������U�V��~�����n�:dff��[n�B1v�c�r�={�����(**��j�����������S�l�2���F���v������p8p8�8�@��#>>S�L���s��Q��!�$!D�:::p�������	��]vv��*BH_�V+*+}�|������O'N�M7���$�C�f�
t���6�U��Pe�3�S)J�$FjTy9�v�q�"��|#�f&��bdX�q��1�\�ma'g)&-~��Tj�gD/H�8�+i�w��� ]%�B�jjj���G���I����?�{��A^���k��n�Y�[�l�T*9rd�	�s�{�n�������g��\1���}X,TTT`����6m����������a3��?����uuu�8�CUU����i�&�v�mX�`��5N��o�O���3��g>��<��!9Z��8���y������k���k����? 33�Z�����g�y�y���y0�R������'����?��r-d�*�]�4����~7�M�~������S%jL�p%t�����nZ#�g%N���bM)���.���r�%�#��'6�Z���������C
}�3�F��BH@��u+x�Gii)������(�D6:;;�����������?����{7 ,,?�0��|��#�l6�z<����a�X��l��&�7o�W_}�a��+�H��b,��M�6�������,�	& ))	:����8r�Z[[�t:�T���7n.\�J��`�Xp��������	/��^{�5�usR�_5BC7n�'�|���w���y
�J�[�lAyy9y��1-S%D�x��{�����p������Z�FWW��Y��~8$_K��	0��!:�=W��e��j|>�.�
Q���U%���$�2���^��q(nq���Q	�9f������<�	�����s�(�����n��s�`�T��F	L�8y��MT�tx��x��]������ �BB�q��m�p�}�v\w�u�d���o���������������V�G}t�+%rss����uuu((��	�W���={����k�n��
���GRR�44,��9��?�{�=����7�x#"##}��Z���o�}�v��3�/&�+���om��U��o�#G����[�l���_�wM��$!D����������6�8�/�r���hPZZ���7DY2!����c8q�x�������u�F���<x3g��^��L�.�������@;��2fC�1r�OVi�%q�M�s��*JT��%5��p��y	tJs���q���N�$Dj�*pn.7��6#�'��'M
0uP�.P�.�~�=?�]<�G���+PRsy�HL!�.��cW�G�:�bs!L�"�����H�kX�������hmm�w���k��vLf����^o���l�����i�&��������X�~=@�P�������H���Enn�ty���z,Y�D�<���9lmm����g��'?�	���Z�>,�b��%������_�R��+���#G%%�C6��!���g�}���t:{$p����V��?��/��j�H=�iC�r���f)o�5�B��G��l��b�X�>�����������%������,�";.�f&L����`���s\}1��Y�P*��BeZ��I������������`���=��}�B!$�UX���okP��?���v��H3n]�R"�b��;[�d2�b��b������2e�pMww7���xZX���1)�����F@dd$�F�_����N�Bkk+"""���466���_��w��cs~��5��k 33��������8���>k^}��}��)����Z�~k�:�N8�����D�����-,,DWW"##������0�1PVV���*�<���ddd���hjj���R(~��������%\�r�����|Z���s�q�F�l6��	p�5�H������`EEE	�Ng����%q!���������mLJ��n!�s���1���9����W��{���b�DB���H8o^��x��A�����w��
eD�p����Q�<3q�C:��a�|=��:��C��MQ�s��V�l�O:�#:)�C!$���9�����p��9�����6U���I�O������Mu�^{-�������;v��K���n<��S�������o���F���~�
6�|�I!��r����_}�U�����tww������:^{�5h4��\�n7�z=���Z\t�E���/E��������]�&M���^*�b�}��������v�-�`����������o //������������xY�d	~���������.����8$''��{��������K��F��O���]�����uuuX�z�p�P(���C5�!�qB�����>�o�Kee�p���#����ut�2�����p8�������xKK�$B�}���-�]I���6
���yS(n��d�M�1��`��PF��6���Y�g&Pg��f_������.G9J���'8C�a�p�kh4����c�=�	!�9�y�������[����=;{���[���yh�Z��������.��Jz�^�������@z���c�@ZZ����q^{�5�_�^���&T����������x��'�8p����^���K��	�t:�i�&�VY��v��?N�8�_|Qh�����s����y3^}�U���K����^����KVVV��^@G��[� (����k
�B�;���x����*���$dddH�^�������%�\"�"���������j��,8��0&r "bl��	����,���J����6�������>n����L8g�'�Sa����VjPRS(��F&��������3A
������������%I���6B�qP��47��QT\}�r	��B�X�98t;�>���m8Y��<H[��>������Aa��P���3f��F���Y��m�68����/�_�l�����o����=�<xmmm����q�FaNHVVx������;��?���j�B��9;s��y��A��o����6m�m��������:�)))X�p!���3��������o����B�����p������q���#<<�_|���['��Z-���^��^[[�7�|���hmm��_��/�\�3�x�	p����w8s����u�w��;�����Q__���$���+����X<����V��]S__����C�R�f�������Cww7222�z����B��B�c���(,,�R��Q���c�e���������h�J��kI�T�eY�F����s;�p
����r�J��"�B���8)����J���\��S�VPY��|12���,_�U�Iq%Nc��N7��l>`�/�jl0���:T(�$!��1��d������j���,�x���F/������:x�������>i�$��z�l6l���/�������l	�:��
��m���"���y�f�Z��}���77d���8}�4���K��v��������8|���:�����hii�?��]�v����������CMM�4������;���j5���
�:u
���u�]���������w��G��v>z��_�d2T*����9�!�����C}}=��]+]FRR���
���P��h!����S�R�ZZ�0�����/����yC��_������h��,����h4��h��U!�NM�J���$��r����VQ%NT�T��mPDwX������y8�G�RM����B���P�%mB���6P�6��#:����	B!d��.m��p�U2�v��Y!�<�s�R������N�BCC�p=������={������p�E	����.��?~<��{V�����)*��Kt��0�LX�b���:,Z�H��9x� �{�=�������������4_����T��Z���=���������U1O=�~��_������K/��=������s1i�$������
���
{����BU�Bd);;]t�l��F��)��Q(P*�`f��]v������rrrp�}��o�Z[[{$E5
n��fL�:�o=�p��$�9p����9�~���`I�Xw���Y�aSP*j��������P����)�dfq���X��Y��x�fM�n_�<c;��9��9(��7�B!����(�5u�s;���0��!�bkll���G�g����5k�,���<�c�����+���������V��~�-.��B!�}�v��n�,�WI#n=�[�4�Nj-��J<�8##������.�s�=������b���HLL����GUU�p��|�r���K�e�d2���mX��}��_���Nb���/z�5:W�����8���Seee=���7!--
�����q�����������3x��g��K/!22���`FIB�l]s�5����'�|�kY��3p�
7�#��L�2�<��n����BTTT�4�O��wwV�r���BoZ����W�gTC��
�Y==����n�D���oU0
��s�x_R�m�����+��%qB��e��M8M�u#!�?F���I�j��zB!d��J7 ?�� f������g7�:����!'b�������n�*$W��J�N�
�F�������g?��0k�eY,Y��~�)���PWW������Jm��Y~���z=t:���PUU��{�.W,�V�s.�N�_"������D�0a�����;w��y�������#G��eb3g��mG��I�����U��K��|�Cq����Zo-Z�����]�vI����,,X���.���{hkk�����a�z� ��O	F
���/��� 11,����q�]w	�������z���?�C=����^X?}���������8l��N�������b�e���3��+�h�v�q�"�T�Z���eB���NC2���4���,��9�V��.H6��7TZ|�CF�?�#������}p`�
�V �B���9�����0=�����b�UX�g��g�?���9����znF���Av���Z���i�x*vN��u<����;�?�������K.�D��k������&����/�v��a����.E��J���l�i�e{�;��7�g+���h�����O�HU			=�6������|��s(��3���-���;��7�p�44d���C�D��G�8�Y���@w�g�eY<��c�V:JH����%)�������Z�~��/������@F*,�xkk5jZ{V������Kq����5�|#w7�&�n\�����Sj�6�X%��p�'=�0'����_�bO������������JV�_K#�B��1n��G���a�����/L���7�<��V�MF��/��%����};rss�s���3f`��}��c���j�
'##YY�Y�^?��Oq���l6���;hhh��I�`����W_���0w��a�p	C{{�0w�7����m6��Kw�y��9���+�H����<����������{Tp���P*�p�\hjj������$#��sp��g����)�C�00�L~o��w���x�)�Z�	���76W����j�t����h���������#�)��(�9!��(�3���9Q�@H��fCu�9�v�����|m�6��������B�E��x�����.
#5x��tLL���p��e�p\ZZ��k���o����5{�������~��e���}��a���<�bz�������d�����u����O��W_��#G��M�w�!y����Fq8~�y��-���g�����^��|����!)�������Z��$��.�����@A�8�Yo.��P!�����466������#�"tpu�$��g�|r��m�r��>�S�����VO�pY��sn��/�2��c2:X�$N�/ SaQaJ��M�T�t#*��M����Y��/��;8�����B��E����%)8^��#Uh�t"B�"7>3R#�bG����G���in��I�+|*++QVV���n|���~�s���������*���;p80��~^KII������_��y�,���(���a����5k��!�-++'O����BUU���������?��>�C��
4��:���X:��p���x���������S����w�p�Q�t��!�����FQ�oN��!�����=�C��N���������}�Eo��n�Mf�������U��i	Ge]8���H��!im8�6q�m9���G��%Gi��������S7�8�+�R�=�|B!$1&%�aR��V��f���B5�%�\�����+|
������T'q���/��5k���i��t�R(��o�655��'��R��<���l!a0R����/���q���>N�7n��O�.��� IDAT��^���PTT���l�%w�uuu�X,hjjBLL���Qu�������e���p�����}���gS�:�|��p.}���B����wZ(�JdddH� ��+���#n���i%����o�o)�������X�4$o��~'�:[�QRs\8�H�Ze�r n���w����!Vt��$�48R�I�TX<��B�*p�JW�����%B!��q��[��H�`����+�����h4�j����c�X,0�LB|����?����.(�J\t�E�G���kZZZ������c�����uuuhmm�J�BJJ
,X0��������p��Al��
���/��dB}}=>��#afInn�9wV�j�HLLDuu5jkk����+W�Dfff����<y�p��[o��[o�			hiiAMM
�L�"y��:��P�P��{��SO=���Vttt��^��)S0k�,��fh4477�����w��>���b�`�������yV�����������iii���K$�n��!����:`���P���(!�|x���zK5��
��N8g����qq��(���=��������^�w+�jCq�/��I�p��3@a4���(�8������n�1$���V.�aS���}B!d�8p�������DG���0���������<v������'B\��b����if�����H���%%%������oJ��_|��o�.����m�����~�����u+�n�*�&�	w�}�tyH���J�������c���x����_�`������o`�XPTT�GyD�%&&��W_]=:��9�����O>�W^y�����9"�c�Mxx8�,Y"]TUU���xf<�}��P�T�PP��%!$��<yR8�Vj�?��*T[��D��}$�c[����p����D�^e6`��o�p3~I�,��3f�-�\�9Rr���kZ��1�y.��`�:n���+��B�B	$�����Q�o�g���o�.�x\|��<���3c��x��HHH�F���`@vv6.��B\r�%�4i��qx��w�d�p�����O?�E���Pg3g��3�<s�m�f���{��qqq�P@	���?���{��nii����.���x������/��n����eYdff���n����>�9M�f�,�c�=��~���|�D��"K����D8��mB��x.�8iJ�Z_G�#�9*���T�+�JC=�r�zD��m�xNk8:���JX�J���4g�y��� �#%W	�(�<)��G]�����N�������M���R���<P/�B!d�~��_I�4q�D�]�V�,HLL�SO=5���?������H�,���/��G��t����X�`����+�b�
�r����N�|��(++��j�Z�Fzzz�DC5w�\��;


hnnFDD�_|���}~=g���g�k��UX�j�t����?/]���3�H�z0��x���P]]���!�;ls���9T*�X�r%V�\���F444���]������H��L���P���	!�@:��;!�G\������s(�D�L��x]7;�+;`s�?G�`p������5�X=IE���9#� c3!��w�2q�Aq�S�T,�x������{h$q�|+�F�wN�4�����T:nN��fi�B!2��=<�&L��3E��F���occc+����������D�����p��q7n�t��'j�F�%qU@FFF�{B������
�jW�/����I#%J�����V����U0XU`F���T��8p�A�`TpY�P.4��'�����%99Kx�M��d��uPi�
�w5�_���	������"�]U=�B!���y����X�~�p#�������.��������@A�8�Y���y8�����\466�$q��9(��O�r����4R����
h�p���bu�e~���u@�R�ax��2�;���I�2�Q	�U:0�.���*���|g�$���s�
p���:�qFu��U�@�C��h�����a����03i��c!�P6n��C����C����0}�t$%%��8466�������(5y��a��!��.J�Bd��r�<BFInn.v������y~�z���xp�mM�T��I���Ul�qF���Y���L�����\`ZEI�B���(�g&���d������C�?��MB3t��r�v�Q\�%�7��?�*AB�7���&�:
�$N����SZsn�
�wu!�B�-22���hmm��f��]������q�]wI�	!��8��)//�����T�T4��$N�Z,455�L�Z�h8�2.P���|�*�}��s3����9��I&������.�'fPg�8�~��?�����;Yt����� 	<�dR�R�j��_V���)
�����s+�D��Y!4c�0O8����<�64�� ��$��B!�����g����q��!�>}V�� **
����7oU��(�C��<��~T2R�F#�f3���x^����D�p������B[��
")&�(�:��V�1�������)�F�V�h����������}�g��m`��r�������U����p��qz�H
��+C�g.�������3zTYJ)�C!�8�e������|i�$�v�";����1�R#d��_g���u f0r�������
h7��0�� �-��>`#P��Uud%L��������~8^������.��M',(o\{��������L�a����9��j����!�B!D���S?!$�8�N���6(�C��3�����p��$&&b��e(((�9����Z|��8#j��U8��<����?'��8c��T�u��t�O��O�|W�&]�������NLI
����q��p��	�����!�B!rC�8�Y)--�����j����_@V��m��u��s��l�VWWc��5�����&������h��%����'8�8<`��;5.��pF�;��y8c�kZ�F4x���X������u�*������ifD'�X�����d}	p�z�B!�2�(�C��<���,��C�***�|��	�����.�?����q��Q�]�V������Q���h�DQy;�����y8'g��0�Ge�i8�&qX�i����
*g���!\9�����
�`���i��
�	4��^,x�����^��B!�9	��-��"N�L�0A!�'���5k���1t8B���8����y{�����G�x\�/���y8���J��h�(��U8�Se$J��K��l�X��2j��4�R��F;���������D�@J:�IW=�9/�I��~�!�B!D(�C�
�����O�4���s��)466��v��tJ�<�ol���h`W�������l��j%�qh��$����t�I�.�,�e&�<�����A?���{e0?kqN�t�Of�Yqz�rpi��y�jX�?��B!�"��!��FII	�n7@��!%%Er!d�TTxf#x_s}�����@���h���H��b���d���M�?m��G�Y�#�=����Z�+D���
� �����b�M�
2�M6?+�W
��@Kg�I���K�~5}"]!�B!������E!g�[�eggC��Q����x�m����\.I$p�6+��z����y+g,�$Njt���*u���
=3�w�����m
�l|.�V>(T��@�wY|�����E	���J������Q�������+����B!��G;���(,,���!#�l6���Ro<>>^	\��"������E��L�o�<�4�&���Z7Ut���T��>�M������v�li������p��ICPF�`��c��A+5�p
�.�'Q=�c���Ub�.����C��B!�2����!��Q����3g��&LE	!�m�����t`Y,�J��a�Ry������DW���S�sm>�������A%���k���5B��`�.�-�F�LF	����A�oCs�e��B��3��{�k:�j|����V�R������^O!�Bq��!��Bqq���)<<����+!�I����k�h4���a��h�P(����������K4���y8�m�]�E�dS�'qx�-���@I�u���!c��EB��P8wu�DQy����94�!���A&��p �F�*!�B!d�Q�"�Vj999`��xBYAA����h4��t�h4�j���tP(����-��2`��@����������gTC�
����Z�I8-D�����$cG������������33����$$!	 k���U*.�]����uy��V�Uk�����>T��T���Z����N��/		!@���Lf���s��I	f����z�����'Lf2������t�Ow�
������}����:F,2�v�=���&!�B!�M��B�+��7�RjB�
EQ�������Nll,��`6���M\\O<��
2�2p�N�����ep�d��J�

�,|��7S��������q���LQ	(������k�l�K��^����j;�A`���X�3�U��p�<�8%�B!���IX�oN�8��-[8q�'N���322t���m���L�0��'O�k�.�-[@SS���\�:u���d��0�����3}?���@?j�A���3g��a�AQ0���N��D�?�FlXU�������rcK��G �j(|�W��J���x&St��A���(�B!��B2q�}��p������O�j�*�Rjk���n?�����E!99�y��i�8����[��\���?��40�~}&N�������t���%�6�~�/��*����A�Y��Y	������p����A�o�����E��x�6gs�uQ�6&�B!���B�)UUy������/PU����n�n�����1�f�/^����[!z��fc��a�������Y��0'N�_]���&�v��8����-k��L���~DF����'�~R�Ro�)1.)�g
������n�����sV�����OO�����1!�B!��� ��Om���={��]�������������TU����l���pk!D_���:��8�
���f'F�X�
���J��j�Q���WG��#.��K�1�~���q��c��}�L���k�1rP�q�i�"�������k�lEL����	��(�(����[$�BqvzjS���`��-l��������@�����t:q:��	E�9O?�!����|��g�������n6����_��9�L�P�=*33�������_�t:�X���n�O���"��+�����
���f��=�t!',8�k������
n�[,��a�!,�*���m(b�qO�"6,�)�_I�Bh:X��Y@ZD#��#9R���aS
��B�m��`��I\v�e�)��r�x��W�>}:�'O6Nwj��=|�����fy��o�c�����_~��.���j���n��W_����0jT����};K�.e���z��Z���PSS����/�������>&##����3f��-:VRR��M���o%%%455��#�5k��M��{�����O>���8�N\.&��������:u*�����|g��"#�����:u
�kN��r��*����:u����!zQZZV������������~�kW�q��o�!��S�����g�����/i��9Xw� ������(�:���0���j 	�"?~~"���M��8�t����	"�@����&��n�
�BcI�&�7!��TTT��~"��r���_����[=z�q���n7o��_}�AAA�����A���e��m��{���SO=eX���y����8~�8YYYL��q)���<�{Baa!�>�,���>�---�����{�r�
7p��W��������{��n����544�g�����_|�C=Dh��&����v=����������u��������'<<��LtB�8B�>����p��j�Y8zn���L}}�q��c���#G���ir}���s#��/�7����
}�8��Q���P;�J&N�����Z"B��S�Y"�� N�[e���/��_;��-�p~�)"���8��h|���30:���{�I#/��B!���f�TU%??���"�b\�7y������5Nu��v�����-[��o~�F�iX�{�����RBBUUU��f`�f����\�EQx�����g��r�h�"-�3a�&M���ba���l��
UUy���7n)))��������Ha��3Zll,c��%&&��I~~>�FUU���	���tff&c���b����BYY��o��pp��!���?��c�IFN7HG�g""<���K�l6e�B����L-��}�v����C���4��o�@���p��x{�|�v�vX�b���k�E�6)��o����q2�o����N��EE}+"�]��@V�N!�����(�=�e5�<����l�����HV�B���{��5���r�X�n�v�a�n���?����������0N��|�p���y��G>|�aU�����������/��8�'���>�n�Jjjj���+Vp��)����Sg-77���R&N���>����3����e����*�6m��o�������_�8���,X�������O�{�����������������������C�����/e�U�vB�K���HLL<;�O�-����!D����)--e��E<�����+����V}&N ��)�i����U�EapT��~�f�v�[��������m���0Gxjd$�A��8N��������Jo�|�r�xu�*�<��J���[��j�R�����B!�N�z�=6���q�ed�����nM�?�v�����`���g�J�[:*������%Kx��'�*��g�����d��{���N���������?�BCC�;wn�~�EE����&M��x��9S;...��x|���=z�d�,\���x2�|�Af��a�����X�����9rD7+���WQ��\{��,^�������\.�y��������k��B���K��������n�EQ0�L����C�q�=��iz����8Ku��(������L��b��qr��V��i�;����2q�P�	��������{���-LI�Z �\�����=YHE���`��1"��J�����"����@V�,lA���B!��
�����5N@s>��?�������������������*�����q��5---Z����0����d�kjj����dL+�466r��ajjj���`��A���P^^���G����v���z���70b����Y�v����q8��o�S?��ON��������d��)�n�k�I[���Z<Hss3�������������'O��*������ux���������d���\WWGss����tj�y�A���w����������MCC+W�<s������]�-������g"A!D��0a��Og����l6�N��#�l6kY8�&Mb��)��
!���������tjs��`�Zill��7���'��f��w}9jc�vn	� ��Nl��Rk��FO�>���T�Q;����3�y���a�� �`�������1?646��u�����7�x�p�4�iA���l���/�����G��:j�qJ!���ow���Z	������3}�������p����d���q�O��v������N||<�-�0P�����b�
.\�q�N'~�!+W�lwa<--������y���x��}>���nBCC�������K���/t����������c�r�UWV��;v���>c��z+�^z�v�g�-Z����y��G���Y�|y�����s����o���y��7}�\�����/~���3�<�������W^�������a���tii)��w�vn2�x����������d2�v������9s�O f����qF��g����c�{6�?�1c��C9�f IDAT���'Nh��B���$���}��[o��?�!�)�f�Z�Z���fL&�\s
w�q�i��!z���f��%@�x�r�v;.����
-m>�K�����N�-� �9�kw��uR���{����kJ??f���8�������u�)�<���l��
��Qi�q��B�?Z+ �W��������o_Z�f
����)S���<�F�����BCC�.���jsz.���7�����q�\����,_����V,���ZFO~~>EEE8��{��&�I�&���/r���v�Lkk+�Vy6���fn���n��?�����s���g���m��n7�W���^��EEE������=q��>�,

��������{	�m�d2i��l8���=m���X�p!���L����2k�,�v����Fo*((��/=ez'O�����
+Dg$G��L&���g������I�:t(YYY���)��XAAUUU���.�������lf���Z@��9Kj���L��SU8^�����A�������c7��m��r��tx�g0����U"B'�v>2�7C��9J	�L�k���I]������#�������{����7bB��A��m�B��9���pz2c��ao�n{�{�q�kLA0�&�^���b�z�����'c���:u*�����p�m�6����������f����0#b��]��y�o}_��?��}��0r�H~��_�����i���.����Z���������C]������	&�n�:�o�Nee%!!!���p��3}��^
�L�2�E�q��A^}�U�t;`��9�x������p8X�l�v}�����_�B��%%%����;v������K~��h_�����r��?����Bm��w��w��}����S�HJJ����7.;k7�|3���8p���:�}�Y�N�����iii�b�p����s����Z;n
����\,&����:N�8��]��������~f��8y7.��z/�:����[7+��m)��^UFm%+**p:�X,��v�U|H;6'����t��AK���V����(_wZ5���Q��^GKi���H^���((T=��1��?f}&���p��b����>V������f:�<�=�[8�����@��MRX����I8�8$�B���e�G{O�~�g�t	Loa�3�v�����I��Khh(MMMl���'�3t�P�������2u��N��[x�����^��������p�������|����v���}��}{����w���S�������j����������{���=�f�1`�����S�3gw�q�vn�Z��������������BBw�y'�<�����	���������� ~��_����SRRx�lms�>�h��e.���FOY����^5=a��}ZpQ/++�y����c�����_��8����+^�sY[0��;�:J�W�}�{;���1]���h6K`<�rV�~���q�����4NJ�KD�v��������@Ru�8�kI�K&^@����Fo���J�%�&3z�D��BqvTO/���v���W_}@DD\p���5q�������)++���'�n��u�V�����%�\�]onn����������n�F�8~�������i�n����X����q�
70{�l�D��]�x�������t%��}nRSS��:t�VZ����0��N�:�o�[-�3`��szkk+�q�����ffwd��
<��������1JJJb�����5�i�������je������e��E>e�����Y!�9��vs���?�q��mo\M&����o�o{C���A��wm�vnI� �o?�@���m97A���Oz�8���cL6JHjs-���
�^,�GC���w���J�'�2����9dZG^]8��=��Q�
�.��SP��5���B��3b1�������s����KBFB�\�h���`�-��N�����g���i�|��L�:���7��*7n�)M=m�4�}�]jkkY�~=���w��
6�v�1��>�4��k�JO�E��JfwWuu�v������>�s.��b�~�iTUe�����?�!C�h���/�����y��/��a����Bll,uuu=�8������U�����[|������?����r����u�]GII	��_9r���'���'� *�SY_M�L�OMM
�a�v�qH3s�L���j�����.]��+��muuu��w���&����B��c��iw����R�C���@ZZ���X,Z[;�u��
��f��>G	��1P7���U��8�K�Z�~8��r��;�)[��<��F�m��xJ�{G2q<��;�x���r��*�<���W��c
���`T��.�B� �`�G�h�9J!;
\�l�N�xb/7���5k�h�c�����c�����l���k��V��m6��;w.�~�)yyy���2x�`�[Jm���>��BCC			�����'O��j��EEE�qG�:g��������7��.�����E]��M�PU���l�d�������eee�m����������|��-[Fi�g��e�]�M7�@rr2.�o�k������W^y��~��L&n�����n�i7h���h������\��(88��n����r���9x� ;v�������#��H_J---�g���(��-����b!((����F�l6��(���3{��������$fz�?(�����/<$}?��9/;����=�Mf�$33�K:K����j���TZ��;u��
���9�2���81�������n��VvM!����0��A��7�i��r�~�g�R|||�>$V��	&��}���Jk��i�:�z���7O[�&++��+��i�����f�����I=�s2((H��o6��}�m���/�GBBB������Ubbb��&!!�'����V�/44����N��ss�m����xg��������A�O&Ng��&L��w��w��#�t.��B�x�������B����j6n�H~~>G���32�������s����d�}������q�m���N�o���(���irR����S9����Oo����x��
�-(�����E�q�^o�jP��� ��)�la�`o_����B��C�bpx.��j`Ge4������B�1�nh��og�"/��6���]�vQSS@TT�O��>�b��
>�Dbcc�<y2���l������'ZNZZ#G�����������;ijj��7������c�������+9v�3f������0�����l>%����hmj������;}������8�Nii)uu�~�#G��)��FQ���������#G:t(���Z�;vh��M�MVQQ���ieF!z���l���?����em��mi�B��7y�dF��'�|���;}^�6�����7�}�����������SL�����y������N<�y�:���3J��,}p�Uq���bm�!�_(
���w�s1�|�x(5�?`tT=;*�9tb��4YB!��	F�
������&]FK�@Hy��J��n�����'??_7����[��O�S����.#;;���*������S����;�(JHH����5�/�����K��t�R�5m�=i��!:t���a7��s�d�x���lw��x?/�����ltt�v���2e�����W_q�Wt�i����q ]W�o�B���������'���ri�6���(**��g�������	!�_dd$7�|3?��O�����GAUU�v;���ZJ��S���*�����O�N�'5�����R���8�����~8�����n\����xJ����q� ����/�]'3����� �B��������R�!��<x��h���<5c��5��:q�����c���9�G�&))��'O��o�p8���b������+%%��3g�l�2TU�l6Cjj*3g�d�����|k#G����C8�NN�<������]����m��v�P@itu���lDDDh��ruz�9�u��'2p�@���������������0 ���^'�	B��� ��������'��p8|���n�N'6����&�,Y�=����,���(
���6L+�x������#��?�b�����o�L��q�;������9T��RY�)���������*t�� Nj�w7���v�����h"����4�fG!����B!���������5k��y��q��WVx<x���z
��T�q������[oi�^zi�e��S�j���X,~��_���Nddd�_[�>}:��-���?o����������O�8Q7�u����<\.W�foDFFRZZJUU����tK\\���STT������,������_j��Fy3�E���o�J�m����>�eN���R\\l����\V�^�������u�@!z��U����>��g��			a������!���G���8���\vY`��q���	�xA��c��Z�F��Y������~8�,�������1�W`�7�!\�������NV�iu��{�b�_�pVcB%3��]UQ|]t�q�z~��Bq.q�\ZY*EQ�1c�a�������������TUU����5���477c�X���Kt���y�f���6lN��PVVFii)555�����Y�z4�a��aL�4�]�v�n�:L&�_~9����:u���_�w���q������2dEEE�����?�����3b�L���lp�����������~Fbb"���3n\�*(�����Y�|9���:eeeL�<�����Y�t���h��	2D�%�0aW]u����q#���c���ddd��� ??�����S����:s��Q�o���f��tRQQ����s�����K1b����t$�#��5�{v��\���q�\X,:$A!�Tff���0//��y��`�D����a	M����y@�S��x��A��{�>vy�#%��&up�v,�q�x���_w�*)�����r���*E�v������`��'c���U���{%�#�B����;���<�qqq��Ea��)�^�Z�#|��Wk������5�U�V1m�4��&FII�J�����Y�]�v�l�2n��v.��b��Y����x��'8u�k��a��5�%���r��w���G?��-`���l����������_���k���"//��zH�2d/���nu�\{��������BZ[[����������HHH������p�
X�V>��TU����+V�b�
�RMVV����aMvv6����a���?�|n�����D`�,����SS���\�;}s3!�IKK�j����gj��/\����%1S7�����B�&�#�t��v�v��2���\���l�Z<#v}�V�\�J�4�}��.��U^����Z���bRH���)��8@�����O�����9!�BtL��jy�i��i�6l��x|���<��:3y�d�������Dl6���������|�y��1v�XE��r���oj����O<����	
����(
YYY<�����l��i���/~��A��S%<<����w>�8Euuu�����p�B���OXX�q���p���J�y�"##������<��sL�2���R������3��������>��:�(
������r�W����s��7�z��s��o�B���h���QEK��H�/n}�5!��X,�9����S�Y_O���&\��f���
�x�v�&����x���,����������#��ry����"��`l�W���������8@��TKjX��V������l
���B!D_x����Cg4f������5C�����=iii��v���
���
��f��e���������~f����3��������=��iEFFr��wr��7SPP@mm-V��a��u�A�]3f�`�����QYYIDD������O�xN�6��sm,X����>�y����'�|�8�����y���)**���Z�
8�������t�M�x�����P[[���DGG����������}������������t:	g��Ag���9��3g�E����B���c�r��	������$�E����8���8�=�'���������J����b�8���~8&�vi��5����]�2�f0(��V��n�+
#�y�9�r�>��m�����>:
lI`?	���|]Fy�_<�6P���B����{��pf�w3[KK�l\��lg���;�����g��!���|[������i����Z�]
��%����f��iX,�fs��Z�����lZ3�@O��\������=��Rj��Q���}V@ qB�@��IitZ(l�<�����;��p��P�sy��,U��*���>}�������������R��/�F�N�B��������,_��������>�L;:t�nV(d;��W����7�x��	@PPf�������L&�)z||<?������%%%NCCn����3a����w����N���d�M@q��f��������u����T��	��\�I��T�
8�nJk�$Fw\���R;&��������sL�Y�Y!�B���?����w�{�n���2q�D���p�\����s�N���z,�G��$�#��q�������477�t:q�\X�VL&�V:���I�X�`!!!>�B��(
���l�������8�j���9Q��eXL
C��rh�.�Ss�F�z��z���z�����-�(�����O6���h�5��iae�y�Q��m���Qp���L���$�B����h������������7�0e����.��"@HG�������������p�����b�z���n�
B5z�h-����-W�oTG3�����8A��F�����M]kD�oLj�������]���`�B%$��p$h�T�*���q�U�0#-����f�5k��k<e����g�B�.��B�M���]���{7G����EQ���a��\t�E��#D�� ��G��vv��
@kk��\[i5���		a���477K&�B����STUU�[�\���
�b
�8���Ux�8��\JM���e���k��'���8$��x��Z������������t-��
��?���o/��I�}�q�sU+%�#�B�����)S�2e�qJq���B��P^^���DUU�N��������vSVVf�B����8
�����g�})5s�(0�r�g������&��-�V�����3��&sy����"@A�U�����B��S����l��X�'�t��c-��������0u�^dB!�B�����!���7�Q������!��>��Ao������[�����r�����	�q���A1Ct��Y�A�������|>��������}@@m�����ix��d�GH�q�.�|���.��%��R�P!�B��$WN�=*>>����(Z��#m������~L�����4���8���z,C��f�[I��V���4)��
W6�>�4(~���.Y��t��F$�����##y�qJ���N��4;����S�p�
�����{R�/�m��[5�8"�B!��E�B�(����a�Z��Y�����,l6�aV��222�����?nX��TG����<�t�w����6�����Z�P����a�	�����
��F�G�~��nz��oy����9X�����."kZ�j�JR�����=��
��@�����������B!�B�^t�
s����c��9r����1c�7o^�.��r�J������`�����9����;w�a�jkk8p �\r	�F��Y�r����/��g���C�2�|���}���������Xj��~����~�����l����v�`\Q�Z���f��������B�����
F~�������/�L�Bzz:�����}�UrX+����0��V��c��q �R�f��8�bP������N����������8��7!^� IDAT8tZ��g���g��Mj|0���P�{
�/T�`�[�{��_O'�u�DG�B!�����8UUU<���TUU���L}}= ;;��v������y��HJJ"77��;w���_s���j�>��>��c������c��-l���{���3f����?����0`AAA�\��M�6���O����}=�7�x���wKG���w��k��F]]f�Y+���������o'""BS!Dp:�>��������{�������	

���Z��=��%1��I<.�e��e��u���9�U7��{~N2�N��ES�][b����o��7L0=��1�����Bs�q�[��r��+�SB!�B�^v�A���z���j|�A&N�������_g����^��+���
�����W^!44�'�|�����SO=�����;w.����t�RF���>��f���c<�����;dee��U���?W]u�_=���f��x�
���������/g�����������Q����x���o��f�1e�~����N�������N�<	�����v�(
f�����?�����#��1�'���4��?�kP��� OVN'=������r��8����=���O�����dfTR�7	����jo4���b�� oG��y_k5MNj��D������ud�����z4�C�~�&����Y����L��!c1P�\!�B�@vV�������s'�&Mb�D�.J����7���d";;�p���n�JMM
W]u<�����Z�m����+QU�����������2{�l���8t�_|����?�.��;���d�����n�h��=�����a!D9x��v|���3��h�"n��f	��>��cN�<���477�������n�����������%K�hx����j��������-�/�9��J�q�`w��@/�:Ns���$@���r@����dr�"!l������2�p���a�f@������Q!b��A��6��w��O!k� o��i���������n�W����'��n(�B!��-g�����#k�8�`QQQ<���B������y�?~�x������+<�"##IMM������������=z4����Q�F�t:��mJJJX�x1��g��A>sB�oOUU����i�4hP���"p�8q�u����c���vc��q������{�n�����,���������o����Z��]P�o>:��[K�{����f�W'�ll�������,�Nn���AJ��[�g�h:����~��jP����[�KxsS	K��]t.�w�,��n����=[Ry�����g��	!�B!z�Yq���<x�a������44�^�0j��Jdd$��PYYISS555�;111TVVR\\������O���&^x����y��
����B�
����d2q����+��?mA���.��FUU�N'�vy3/z�����'Q��L;�_��������5������t�H|���g����[5k��f�4T�M�q]'E�8�����lm���I�B�F����������m�8T�
�T6���P5��(����4��5�������El-����#��z����/q���6&�B!��yg�il�|�		i_�j�tX�L�������v��E�j�b��ijj:�w�/v�]�?5Qn�?--��n��?���TWW��hA!D�����X|�������f�������-�L�|YY�a�g�����ew��=�#�P��ll������vj��,�������U�;��&�'�s�����2�}3�E�{���Q1y��w��B���`���xxe}��_y������_y�i��Uo����N
C8���R��y{���N���E��B!����U]���3i�ps��]�v��x��yUU�t����{����{���a��5�����<��p��~;��X���~�x��}8_��c�W���h�\���]�d���opw������@�q�����>g��}��|-����i�%���������L���M?��=hyyyl=���&16���%@����o����	���;���t�y����Ea��G	9���#������/~�S���G�MN����3g���5���C�H:��oA�3���D����'���<�k�=�����x�� �p{��$������������G��
!�����$�Y����I�����j��t�r�~pr��8�N���;�w������m�����[�_|��9s>|8�������r�PU���r��!�^]]���#F�f��*!!�����t��8m�{���f���o����������b��7����V����6���(�M���P7����?�!��wK��{f��
��g�m:�>o�q��Pu�I[+<e�2���
j�������)�B!��yg���Q��6������n��CQQ�����������TUe���DDD`�X�����������o��g�?�Y���/�v�Z����ko��_��|���_�==�m/�t��RyN����5x�`�M����/�����~��9����l��������hmm!�l6c�X�Z�\}��0���Cg����Q������2�!=�?-��O�����#=�k�e���W;l��������X��6~���]z����ue�����}��v��o�������!u"������JB��q�oqQ���q���������7��v�)V�� �&�>�J��8��_���l���Q�O�����T6yN�-�Q%��l�U'11���|f����766RVV���c���IHH�������q�=
xv�+���A�(..��������
<��������IJJ��{�5N�d�����>|�qZ�M�~8&L��!YHH,���3AAA(������v�(
�E�Y��������2Sx����=:4�R�P��
1S��� NTH��O~�U
�L���S\QHm�gS��BfJ�7���dI�q�'�f�W���e���[��@486���[��oJ�U�0�)�
�
����3D;B!�B���*������db��-477k��W�FUUf����555��G�m����z�1�W�FQm��\���>������e����1���HRRR8y�����������B����X,deeu�_pp�6��^�}--->���:~�4��\2n�8,X��f�b�Lhh(!!!Z`��+���K.1����-�^�[�h�L�	����q���M�<c�hLb�q���n�o��`����1�S�K[2t��C��r����<N;v��C������l1a��M 2�,|w��>c[�c�����Dy���N��'�/�B����3�;v����-[���[=@t��pt���;G�6*]�r�����Y}���d����^����~��/����"���+����9s��v��|���(���/�Ll������INNf��},Z����L�����}��;w��]3o�<��]��Lcc#����]����Z~���ku����^~�e^z�%���
+W��f�q���B��'''����>,,���4�
!D�����3f��/'''���j��uJJ
����
��=���<�:Z�}`�@E	� ��'Q������qq�����q�����"1�f�?5�����i�+����:I;�>sb&�L�v�:�p��<�?���ZM�
!���!�3qaA��:�!?��v��������p}8�� b���P�_���$�
��9wn-�B��>��<��n��������&88���h���)S3f��o�k��������.�H�������e��3g��O�/�s.��W_}����3y�d�t�������������c�@�R�gc��%�:u�����n8�����������`�F�e\���o����K1b��z�v���9r��?��P_���		a���]�y*//���>c������(
`���\s�5���o����,_��M�6QVV���DDD0a�~��h���TWW��k�q��������={X�r%���VID/''�O>�����n��t�r�0�LDDD������S?~�i_�����8,�d2�v�Z�y�F��]w���������(�B||<aa�]�&���z�����dgg�m�6�f3s����?���n���<������,_����P~���r�Ei�f��Ass3|�����v�;����'Y���;���gl�}+..N�{����s�=���'����l}w�3t�C�������g���5�;�^�0���-��]1��k�`^�Pl��b��g���]vu�h��Bo�5	��_��`,��q�<%��%�p��A<���q�C�OH�}D�A+]�"/�s!G�sQU�V���2��Us\��/��VK���B!�YAAA�}����(++#//�/�����t�����m:��S��]�oQ]]��}���G��������/�[�n��}Y�v-o�����u��5\���U�c��-Z5���{���z�������;TUUq��q���N�����������gk��U,Y��!s����}���o�>6o��/����{999���K455ic��RVV����/��������w�s_UU�s�=GQQ��x}}=7nd��m��W�:�cq��Q���G||��8���g���2bD��&���<x�8@YY����[�������~���We�lu��w��b���o��n������P������>}:����������C=DCC������v�5j/�����8���;����;�9s�PVV��l&>>�K����8$�8n�[{�RJM����a�

���	������7�[F�/���p�~�A�Y���V�����	��y}Cq��9&�Dp�E	���N�7XC�h���S��z��~8�K�8� �-�2�3����q|~���ZSR#��v��\N��������~����l��8�b�}�s�B�B!@jj*111�\.���)..��S�����3���?�����6��0d��{��c[���F^z�%rss�Sg�j�*�~�m���|��|����]���������@UUf���>�999|��g�������a\�-EEE������nL&S�La�����f�;��u�p8����?��o���%(//���ijj�l63{�l������c��5���RQQ�K/���O?�s���r��K/i�q��1u�T\.��o���8-Z����'bbb���9v�;v��4{��ri�-�=�aG/33��c�b�Xhii��������p88t����x�������:���f����h��VB�t��������3�c2���E&��.??����f3c��1�B��L&�������������A����96����Y�5yh��������va63�E11%���g��&��][�X�8��2����iD����#�m��q��C�'�f�����m���v��V����?�<���������&3WL��+�^���L��("�Z1+*���`����7B!��_���zhkk+[�l��������S�N�z�j����s��b	�M�yyy,^����
�����G��p�-�p����V���������;���>?��-{�BHd��wQ�U�.b��.����m��j�[������������km��U��"�
$,!B� �������0g��L��6C�����s����!��9��>�����Y�p�~��x����c~y��mc�~����JHH`��Y��C����3?�|�|�I�n7�����[o������o���	������y�����������
***��ks��U����K�������w���-[���^{��?����G}�S����J)���Fqqq��_��[)�\^^���m���\w�u>cMMM<��#477S\\LII�9)��?,%�C�-�����7�Nqa�m����ti��W�X��a���|g�h�S���S��
�LJ�Rj��)u�z�l������=��9q<s��\0��c����"�\7#�1�~��9�R��<��q�fV!�8?*++Y�v-o�����>����U*X,.��2��{�x{G���.�x�
�x��!p��������Z����u�8999,^������9��%K|J��M�����G?���E�(_O���j����>�uuu���0{�l�(������;�c����O������oW�<V�ZED����S�N�������\EE�ff����Y�b�z^ZZ��={N;G!<�������T
!.L��.������o����
��5��A�	�z���	"�~8(�p*4�8�3$�3��R0D���j�Q{���U�_l���������v��6gp�4<G:�W�����J)E��*!���koo����&//�g��O?%##�������A���YICC�f&�����l��
�	&����W_i�����o��]f�������[qvY�VZ[[}�F���9���%44Tm)�����hnn&22�����*����@YY����9�������F�No�m�����<��'��-�4���~[���`0����Vi+h9�����/^�3�1q�Dhll����$(O�o���~?���f����-[hii����'C����'p����w���%��A����!�������n:�$�#�8#���|���G��%!!���$�	������Kt��G�c��SsJ�q�.75M� N�� �8Z�]��0�r@������_$�8����9u*�C[�/N q<��,D��h�*7���V�h�s���q+�8�Q&�g���F��~�BqV���������.�����l����'�x�|���L���W_�:����"""��+W�t�R��[�_����b5�b��|�{����l��k��}����n�l���x�"""���~Gaa!/���|��2e
�W���W^������������/������iP2S^x��<77�_|Q=x�����=��/��v����`0����3_T���w��wzz:���������Idd������<�����E��8z��O���J
"477s��a&N�f�����N].UUU��
DMM�z<�������!�8����RRR��Jqa�f�hw��m��%�8Y��d�<����:��z�;�7���
~�y����e��~8P��4�H5���s��%�9��#�Q�4
T`\�w�ey�w����c����������Y!���x���imm��r���MOO���Nww7����+��BO��tq ��pJII���Y�f��3�p��W:�����w�q������������>��~�;:;;��������?���/���~E~~>����x��������?��C���a00�>__����g�_��(++��M)������6��4F�q����Q����o0�T�s�g�����J��dR2���]�d�x��0��8z|���R>���;g�d�!�mG�p��&O����<x��}V�D���R���������M=="�s��i��=�]�g�Py��7������~��� ����v�!p��3�(8����l�f�	��B�1������[����~�"���QYY��P��l>;�=�v;F����:6m���e��K����n�}�]�����v\.���~���h,����Va8q������n��G���c�F����7o��-R����;w.�=�EEE��]�9p�YYY�^���c��v������^�f�q��q7�p�]w���tuu�e�\.�������~�Gy���o�[�/�^z)�^z)�����q#/���Yzi���,Y��Q�tZZ�����S�:;;���������g>y�Vf��E��q�F���������{7]t��������������f�F#mmm�������.��{��Gw��#A!�i�����a�~<H?!����l�F#.�������IOO�/;�5� N�R��Rj���s�����d�LJ�Rj��y�$%����mm�y�SB�~Y����Y���|�R IDATL�^�����g�fFpb-$�nB+�B�SXX�������c0<=C��(�!!!���{����/����W_��W_������[ILL�l6���AUU��oW3f������������^�Ji�@�UAA��:�����K/�����SZZ��
��O�������Q�8z��~����~�a����``��y�����{��|�rn������V�^��hii������~O����0�KUU;v�`��Q,\��g^H���G�l��!l6e3����>���k��u� ���c���K��q#�����������(++���/�������~3q


((�]I`��9�X����V�B����B\.��NLL���Bxx8���jP�����&����	� N�	����`���S���d�����.��*	�o��HL��8�J��Z q2Gyw�5��i�v0"\n�<.J�C��8��VJY����(A!���g��;�O��D_<�].���x(>���!q������T�g������~������5��%�\.�����?�1c�������[ikk����<��3<��S���y_&L�������7n�fFa�X���f���8�N���������W_U�V�Z�L%���)e�m��u�^�=����tR[[@ZZ999������Lnn����w�Z)d���X�V�o����G�Z�����OII!%%��BOO���TVV�k�.v����_����}2���B�6m)�i�����IB��4y�d5����!�����	W���
��2E3��@�f�z��7��e��8$	".�@��b�2j����S��qBg^�[8�"-���i�Vn���H����p�5v25%�AC�?��&�	!����i�(.�flU�������7�2�L&>� ��yK���b�������/8����qDDO<��Oo�k����~���&�9��M����+��={������{L�:u�%�N�@���Am@�lX�v-G��s�UW�
2i}�����0e���c��N���{�n������kjkk����4_|1���#77��oW6yJ����KZZ��*++���Q>���E���:������5k���O��s'mmm<���z�O�q����tRX��?�78B���I��r�>���3A�$��1��f�����N�U)�%��F���(m��@�Ro��P�S�a��>��s�@fb8{��8\�%A
�){�":����80�{��u�~�B������3g����������ob6�}��yv�_~����x��d"))I?< ��������j����o�}�v�N'�Pg��~\}��������r��7��?�	���\� NUU�7oV�="""�Kg ���~�������f��9��466��d!!!}�~	

U��e�i^=��}�l6[�Am	5�5��A����X�nuuuTUU1f����'��R^^�g����0����������]�v1w�\��3J�8B��r��a�]����I�t+��IFF���tvv�r�(..>�}���-����AB�0}d�%8�5���@�7GJ�	�-u��/�m���YX�B��>�o���f��Fq��DFE���N&��#��}�$+�84�'A!����1���l�����JBBB����2^�f3f�������Zbcc}����@XXaaa�y��������.>��c.\���c��K��]�d����3G
�TWW��EGG����3J��d����������^R���x��}3
���ttt�dU����d#EGG�c���DE��8�-���d�����"!!���Fv������Z�x�����������8}Y�p���w�^	�![~~�z|�E�����g4�4iyyy��3�\q����������l��S��H=����{���9���:ux�q`JH����n7�#��d�.�p�9\n�����%���;lN�������;�'�$gx���1�5���A����L��Bqa0��}��<������P�]�L&����U��KG/&&��+W��+��p8x���x��G�iFF��>�����>"**���0�V+���>sW^y�Of��u�}�����q�F

�����T���o�V�9r$ttt���������(�G��d���HMMU��<�>�Z� NLL�O�n����]����\:::o)5���t


������h?������%�8��n�O�l>�B�)S�}i
{��;c��������{�8Y��� ���{���Rj�F�!&r�;-��`�����q��b
$�����<�{�9\���G����j����t&�a?�'����TB!��1c���������h$$$���PBBB0�LDDDp������q�,]��	����b�MY�aL�@�����t:�rZ�e�7g�^������zP�l�����A��h_���2�����T.���jS��������X,>��<�����`��=���[o)5�5uuutuu��
�6�����L� �b��;�m�~8BP�Hz455q��Q����8^��~�����il��st��\��3!1\3$|��,���[Jm�(�%���
�b_��&+�7*U��~y�1�v�~x�0�,LH�A�	�n����q����D!������c�=�m������IIIa���\s�5<����??�2]��s�������O���*++K=����Nh9r�Ky���4�`���%�y�=�oO�3���_V��-S���}
=�������@���3�q����R���0y�d���'�,}g��q�=P���Rj�`�������gn ������e$�#��}����RsT��#|v�h���I>����1X�gWVM�U}l4������U� N�2�d?�Jo&����	���O��QS~n�����[p��i����_3��q�#b�����35�����{����(�Bq����l�2x��qz�!�����(��Ozz:+V������_]�b��:u�ZRm�����v�
���������T?hll���dI� ��#SRR��9=��og�n�^.>>��+W�V�7g�5`�e�������v;������^~���\ZZ�����Q|��m���;����������~8Z�l����^���,[R�����_�^=_�p�f����8B�!�RjB��L�:U}SUXX����I��������N�������.$���PB�A���V
��t���pZ����7*G=��2p�qw��<Q�)!C����f�
DEc7����_��.'����|}�L�t:�D��]�)�?�%;����[�&��Y�B!�Yt��7�s�N�����{}2<�N'��_���,\��q����������]?�#66��~'g��d������������_��W�r�-��������u���};����>��	&PQQ�����g����o';;����z�2u�T>��C����CNN===8p�W���hoo�	*&$$�f��
_3g�d�$e�^BB.d��m��v~��_r�w�����c�����������f�����]w/��/��L�:���v������8q����@�8|�����3f����g������<BCCq8466��~v���f
]y���X:]�BI{{��/9)�&���:u*k������tuu�;��G�7������k:xi�QZ��DZ�[l���8+�&a1N��Sj��{�
�J-cm��c�
�M�e��4j<�z%�8RPA�cp��z�3����o���/p�
�6�r�h����QM|��������?p����^*�B{���|�;����x��W�4i�Z"���r��'���KOO��)..VKP�%%%��q���*�����{7���<����%��f�����d��7��
�n�Jww7555<�������;�-�/
h�&Mb�����������k��_|�W��?���mmm�yII�)�|���� �]w�Emm-���444�������VL�<��o�Y?��%K(--e��������o�������3�)�g2�|z�x������Bmmm�Rj���KII����� Nnnn�%����7�����SgE�m�B���5�OJJ�n�b87n����r��~����j���rL=7g�����&+�~Q�7�����&���^?��}����.��k�Q��(�pDo��gtL�~��GX�C��������>c_kJ���o%����3�]�����B!��`�����3PJ{��������d�G?���v�ZZM+==��~��+�$%%��#������
:?��Y�pa��O&������WVTT��.C�c�=�5�\Cdd��\dd$������O������w�������Q�|�M&,����b���>s���1c�`6��SY�`��Rj��j


j��"""������O?�4�V����-�C��AII��q�F/^�3.��'�,?���?��={���W\qw�q�nE�����Y�jo���n����48����jM���.��"����={v��A�}M{|A�;?��L�����v>������T6Z�S������L�t~7�H���<��;���[Wz��X:����zM�*���'�k���_:�[�^���z��n:y�r��[�Tv������j�=���_`J�"����V�?�J[yac�~�/�~s��F.�hz����������?���n^^�O�Y	T?[����J`g��[�G�q�����"��kza��S�Ss�\TTT�����` 99�o���jkk����$&&���?455q��1L&QQQ�=������t:9z�(���DEE�����2��Ouuu455Brr�iU����������d�T����q~_U!DP���>��Ow7����p8�Z�����F�l������m���%�\2�]+���(�v�x��8�4S��`��g�&���.U8����v{���|���M��_``h�����S�����2��N��������1l<�L��.�T/�LO��P�4�.5�t�����%�&4�A���
�R!�B���
zz��:#!!�Wv��2�dff�����:�F��kca0���'>��L&�����KJJ"))I?<$QQQ~���Q�;n!��Gqq���|hh���*�8s�n7�?�<��8N�P��uww��k�QWW�M7���t�|�8i�Hl���A�?/Z�%��:"�p<�.Y��}�x����-�)!CX4nk;�]8jb?W���0��K��_�T���w�����0������G�}{C����J��I���� ���B�@�����c��e���[n��n�!���������y�N�2���j
!���[���j���6w8�L&BCCY�n3g�d�����@��V��M:-i���j\������?/4�p����{���������Z1��S�`/U�n;j�L iD�}���y�M�ZP��y}c�HV�M��?�q�KO��+��ev3Q���#[�ZOJB�F�B!�.���E?< �����B�+��U1(n��'�3}z��1B�{.���������p:�������������%8k�K��1��cJ�����^� 1��3���+�lK�f��Nk;�J6�x�5�)1L���{�8���@b��K�p��DJ�����:;�$F����IW�������[v��6����d�7��QMl�������N!��e�������!������fS�zk�!DMM
�����n���?��C�
���:_=6�L�I3X��Da��9��E����`W���ppA����!��}�5���
1�f�f�`����p]��r.d�b�Y���zu���1N=���
nd|r�f�B!�b($�#�mNff&��{�'�<���2p��n�����C?}J��p;06��
3��~%���|r`5����K���#�.��h�}H/�s���������J�"�LH�P�K���o�Yv��U,�~�����Z�?YR
�bps��3��V!�B��N�8B�A�qf��f�B����5���Z��&22R7s
nm&NZ���vz�����	�����XL����o��e�=nRFI�l�e���8A=w�^I5���p������n�fv�1�|��G���gIK�'�9N���'��8���B!�B��� �b����������~8B���4���1��}��0�������#44T7�7gCnk�rb0bN��� ������L��O0el$�}S&����-������q,��N�L?,�9m] ���e!6��J��d�0+����������K���M6a�:p�z��B!�C���!���f�$&&2z�h��B(��+V�7#�h4�u�]��=5��^S�����9�LFM��I���uI2��q<?�:��Q�d�j��R���6p��PJ���DG����0���)���%%��5�+f\���h�'^�8��f�B!�b($�#�0mg���~�
!��W_Mzz:F����0,&�	����b!,,��2u�T�������[���������X�z~��Q,�(����^��V���Pk4=����7F����Yt��
�����1ASR�p]�fF��M&1vN���FoI5��!�B!�d`w�B�a�f�QTT��K?!D_�F#?���Y�p!���Bhh(���X,J��W\��w����� ���q�h'��7""�����b?���%�#z3��`��>�w�jfO��g������g�5e�����T���s!�B!��IG1 ��P�FDD0a��!�B�EFFr��w����x�b��������/�@��q5�����)�Q��L��4�7
W�~���o��L�-&"��Y�����K���Z`�������8�T7Yu+����h�������m��4��B!��%A!����{w�O�:����B����������>��W_�����[�j`�,cL�������5A����%PZ�)�-L#��t��|n��]B-A�u$�	mI�@��b6�>��.���8zS2�L����M,)�&�B!�i� ��_.��W?!����g��555���kf��
�S���v�<(�8��Rj�^�mW�;Kf^��	��q����0zp=���bN�f��S��
T��j���G/6j$)����j�����=B!�B�q��*//��C�En4��\!F���1c���f��qfjf�6'#!�������~8�-%���������V22,�ES����+OX�3'��i�$0)?n������2!1B=>,�8~M9YR��5�NW�2�vJI5!�B!N�q����R���!<\J�!�F��3� �����b���<����A�����h�v�k�gv�l��v5�7������7<IR�X�z!�`��bN�Q����@41������NKW`g��������q���w��B!�B�A� ��_� ��RB�m����'Nhf��8r\J���)1K�"0u�]���]����
�_�t�B� r2y�6�K�f_Nxh���B��4���[�5�GY���f���j�LN���d���c��u�W`\	M!�B!�B�8B�S:~�8��W�g��>B��3v�X������f���RK���xs���K	�D������-����Wlv+�e;������c!���-�������d&$yK��JI�^�C#�����-n��J��4��.B!�BXp<B�7�,���TF���B��1C*���'x���5�����(��������s%��w����C�)��T��0�NS�]���Z�jfOV�7{�^�8�L;YR���}���	)�&�B!��HGqJ��yK�H)5!���
�������������QS��K�
��	�~8�*�>�=�S������Z��dQ��c�HL����^RM��h��q2�NxM�z�I�f�e��i�B!�!A!D����)--U�g���<B��JKK#!!A=��g�f�7g�a��N��h����d	t5MV�O6>7����) IDATd��MND6���t9�U�E��}�w�C�
��5Yw�(#!���:��M�	�n��0f2��0�[�h�	=9��~�m�B!�B!��HG�����'k��������[!��g0�5k�z�_�^���oN����I����Y8��f���f}?(�������3�,��\�]#�����������b2���(J���������D�]	n����>N��*�/
�w��B!�B��IG�'m)�3f`0c3!D ��T+))���d������q��R��)�63K���
�����[�I��1���H�\��0�y3}��e�O	UV�7�\Z���k����[_E[d���x�83���}��p�A[gM!��������������};���?V��C�1TV�u��������G?,��~@!�v;���W�g���B��7~�x���hnn��vs���>�8��;��%��as�<�����
����p����q�&�����#����3%�c����
n7��B,Y�����p8��p�d�xT�����W���wDR�JR�
07��?|������S(�����_��Y�f�|�r�T@r:�������?�g��@�����`2����~��rz�3;::x���X�|9�����P�l6^|�E������;����/9����X�f
&L�����h<7�s�o���_~Iyy9V��
��I�X�b����+z+..f���8p����d"==����t��Sn���l�]���[�R__���&::�3fp�
70z�h�%�}���n�:~����v����>����;��S?���~J^^6�����v;.����bbb���d��E����/
���It�����yhh(999�B1t��j%%%�Y/W�q\m�F����W��g�Rl��tM������1��T����rL�3�2�!��`��6M=uTy��QVb�z��a��d��������t9�������8�(=z��/�'�B�	����e���d s:���`��m�������r�x���y���9|�0eee���5��og���TTT��[o�����_���j6l�p����c�����v�������?����@ss3��m��G��?�\����ky��'��g6�
P����y��W�����>�{���x���Y�f
uuujO{{;[�l��?�)��}��+((`��}��Xw�����������3K���#:t���J�=JCC'N����c��'���������k}~�@&A!�_�_�S�L�l��=!���
�TWW���{G��a�1n,���l����R��E���X�����pv�f�d��B\Tp�"�Y4%��U���;��#-����*=,%�8T���
mI����
�Qr�P�B!��0m����MYY�����������~�+v����:%��������K"##y�����s:�����8����0�L�5J7�������g��O
�W_}��_
@xx8W]u��o������2w�\n��w�y��{�o����������v�
7�����=���o��.((�����J%����������M��{�����b��)�R�������Y{����
��;O�3������Vl6��~�.��Rn��6n��v����M��~=>��s�����/	x�TV������G!����,���ioo��rQZZ������j��"K��!o s���q�����-��
qK��q�fK�8s���oG�������2!)��vJ����1B�b��������3���a�	Wv�.�Dw���B�9.�����(���������7s���{���~����������;�������g?������:�rrrx��G9~�8����<�;v� ##��c������O���#%%E?5$�'Of���~���0r�Hun���|�����{|��g���{?m��y��7%����O�����/^������tuu�~�z���Zbcc��/�����2V�X�S�l��e���k|����l6>��#������� NAA6����P�
���������~����-c��	>c�������5.��O?����������K���M*++imm��GS�N��B��g4}vg�+����	�Rj���t���B&��)c#u+�@���:�e��il=N��C��y���c!N�y�$o�������������L8\�;�p8J��R��m�l��	M$�x!�C�����/�����=���os�=�������}���g�ZZZ��m����2N.�K?@WWo��O<���8����]�P��~�����GNN�/&$��l���`��%��������O>��>������+����
��b��m�8q�o��'������k%��
���n�u�����\�j����/������Ne��f;e�5m����r���M�2E}�i��8r��nE`� ���/���,���4�Bq�h�8>%���v�����9=8�8�Rj%Gf	��[>��.c(y%�����T�$gCH�LL)�M#�^R-+��������<�	$�'^������������B1_}�?��O��y��	�����{���_����z��w��s�S^,>^�7�����B�r�V����*����
�tuu�k=g���N�����
������P�]=��������*�����r1a���������W^QS��z�9��b�Z������/�m��������������;������w�L����`��-l������>p���>��������6�����G����s���0����gy�z�x��.����������W�KKK������h			Q��[ZZz�A�d�x�����{466RSS���H
T\\�zl�+Y��B��	!z�RjB�s%;;���(:::p�\����`��'��)�N�Q6������{q���iW�����q��~8y>��c�N?"�Y2f��Tv�i��Q��0,&v���M�	+Y����pt��[�r��o��dk�v�S�NZ��`%���>B!����?����a�~�)����p�
��s���A
��\��7�x����l���i��u.�����FBB�=�����|��|�	�=�111�����w����>��`:33�����Gy��gy��g|JV�\."""X�r%K�.e��u��Om������)S��Y���]�����3v��ws���=(��{�9&M����s�}�]��]��3�,Y���������_~�W�!55�����W)���z�'�/�������l���w��qx���h4��[o��g��c��c}������!��Bjjj���	��������999��^zz:[�l����>e��A��{�b��{��Y8�\�t:1�L>��	��������
lA�5Tq6566����S!��d4�5k�z��e�������{���/�0��m��u��NM�M=�����p@���vo�<q����s���u�~8�����S��(��F�Gy�6%u��%����{���Z����C�;�c!�b�l6[�O���������\��an����0�����9s���6S$""B���������9-���>��� ;;[��gX�v-v���LFF			��������Dy��^=Gf���3�<��W^�g���������d��{����������~��~@BB�p�\�_�����7����������F���=�������%��a4{�k����!#b�^��(�����:l6��59�����L���zuL�s5fL�%u�e��J� ���o�Z)((�.��p<�zzzz�b���j�[o����0���&�8B�Rj������Bq���3G��t�p9���	���w������D�zsj�����R����S����l@�`X!r
{
?��V��D�1QS�J�3��:
�Fp�p�:q��`J�{g�������J���x�����p��:����m^���8X�;��9l	��r�Y� r��!�6��I~~~��Wu���~��y8�N�z��>KE��d21}�t���@9�N6mR��g��Mhh(���c�������s�N/^��_�|9_}��6mb����6�����6eS��+����������,~���%��n�������t:imm�����K.�
Hnn�����1��7�����''--��.�����������sy���(**��_�O���~/^��U���������?��5k���aaa�����~��1��y*++iii��/����z��Gp:�������]�z�jV�^�<@]])))<����eg���d����R.M_&���I=������o�Z���^����~UVVJu���Vjkk����)�n�Z���%K���J�����Sf�xJ��\.ZZZ(**�������U�������<	�!|h�8RJMq.���B�����Ak���o
=\�Mt��?����B�l�6��Y8�����\M)��/�h�dnq�B"0'���Uv����tg��8Y��p]n�"����T����-�P�>v}Eq�����#��@�.eq�;���j!����z��>�L?|���C3�����������={hii�A�)S�AWW�7o�	����3q�DJJJ�L��o��70b��>%��!!!��?�y��h�"���Y�n6����\�2c�C��h���>M��V+�������m�����������-44�Q�Fq��Q��_�/f����yHH7�t�R{�|�{�c�������d���>~������6���T��;���_�;,X@bb����jU���Yzf�7|���Cxx����zm��ztww��_ZZ����Y����w�p8��������Y�|9yyy���P^^��3�����2��X��y��������!T]]]������B�FLSnr
�����j��{�K�����ps��6���p�� �2������C��{��8�������J����F�������{c:�00a�$�y���������U{p������o��B!����������@}���DGG3u���n6��9S){��!��T�<��\�����' �t�R5X����~���������#���53�G����r��W_�������_�����g������|�4i�~���MFF�w����t���6%�����{�J�e����J�������6��P���e���~l�5UUUj����4��`WW�Lo?��c�2v�X������P��3i�$,X���^���sIOO��v�������5k����`!�8BUaa!�������7n�n�B�y���L7%�	�X���������)���e������c��8�7�a#9��+����Z�=�����<�=J��PKS�yo�8���3�k����j/��pKp���P)q�iV����ug	��,k�T"B���u�p�)���Z���0t��(o�N!��m��U����O����Wo�S���:e��S1��>�����A������}p��7�m���v���e7����p�����o�����M�|�_m������d����>��W*
|�Yi�����f�833�����>��e�]����v���i���7}���]�����UW]������ikk;�_����OR��i�u�]�f����������_��G��~_�����{�n�6���,$���k3v<��@	�%''���NUU�����1���f|��?P>������Z-�����+�0Ay���������g
Y�f
.��[n��gM � �B�/��_4^!�gc���Dt��80r����;�\-G����zX�-�6el$fc`>x>%mND���w�d�
`z��S6-�tY�����Pt������]`&&E�q.��[!LF���cG�r+����Z�*��&A!�FRSSy�����VWW���������;Y�h�~����a������L�>���Pl6�7o��oT�L&K�,��>�������3z�h�[Jm��y>��"""����#G��v�{���6����3v������U�z�.��".���n����&77��YAA�O����9s6�����M�����w������Gnn.�d]{���
��e�)�e��)�f0�@�6�d����hK�i��d��F5j���TUU�k�.���JKKioo� 'x���v;�����^IHH��������c�������X�|9111��I��
!%r��t����Y!�8{F3&�L	oU�
��xj0�������
��(o0!XK�-J����v��U�Y�;�r��g�!"S�w���*�K�e��f�:>�����Lo���e_�N��;Y���!�B�ORR�\s�~�/O �\q:�l����LHH`���>�!!!j����:�3�t�R5���q��������4g�@�2������\.�|��z>k���4a�X�M�&��������A�Rn#G�$99��}0h�3fL��Mrr�)7[wtt��+�J���{��3S%:�{������|||���^�����~lm���
���G� OI������|J�y=iiix�WR��������t�V��sM2q��R����P~��U'T!�4Sr6S����T���XG�YR�4j|�q���hh���OO���	������.���AZ:N`0�=���b��e�,����+�:�F���11��9��Ck���p���������k�����$��l���F(7�B!Dn��f���(-U�/������i���={���111>mv�������Q�����={6���l���[o�U�����$++K]�q����{�n���x������g��)tuu��g��e�,X0����DFF���Nhhh���Q�F����y��w�������O����)�J@����T<ABzzz���������OMMU���cOYC����������%33���2v��Iqq1�-���BOO���,Y�D�(m6���t}�������{��I�&���B������=1���v�
'%�,��O�o~�����R�F\D>���
����f����C�@���f��"��3f�����J_��mad��|�d��7rD�������J Ns�]�7��B����c�=���+��qZ�x1O?�4III�����/�Y�eee����������kv���������hjj"77��;wJ���������������Y��_����7����P���^�Zw������������g�0���g8���u:�����e����\�R��WDD������#Gz}zTVV���6(��oTVV��y�,��9z���+G�YJ�`��mj)@O)5P��yF�����`tvv��} Q>aB�in��}������^!�8W:��G�'?aJx+y]���k\��8�������	{�5����0��s���`A�&�37�2��g�9�[���V���(�8��b 1��T��L��Xt��y�F�.�RR��A���[��o,Y	�����w!�Y0���B���d2q�u��|�r���8q�QQQdgg���?W��L���L�2E��������
�V+�v��)�6i�$RRR8r�/��===����d#�����h�">��c�n7&����8222X�h����_r����(..��pp������Y���:]}��'+L�:���y�������%"��-����,���p:����[-g����0s��w�6+,77�[o��W�[{{��M3y�d�'�';zq����_���V+�[J�#==���2jjj���~���m%q&�/�	�!�����IyPj0�6m�n�B�]�ch���0c�_�;�����w��U�g��?��YIB6��=!�KX�(�Z�ui�:�����jk�_�ig���]~�L�3vq���j]@D�H�a	��}��]�����s�%A@���<��������r�z�y��yJ=�t�V\J��i���S�H����	PZm�}?;Z��4��8���j8KE�i}I����b��5u,�����{qFh`�#�#'qz7k�"��z�C�{�&�������!$]~I!�C���
��<P6o���XX�z�E��9r�'�x�J����Y�r%�=��~b�����f��n]]?�����l<���������x���m�9+ IDAT����[�����_p�����~�z}~���9QZZJ ���f����?������HMM
�rE^z�%����s�����]~~�~2����b��y!	�����������	�Xvv6������PUU����Y�$����5k���J+W�������$NJJ
999z�(�)�n��	�9s&���$�����H���Qu���W!��RRR����Ob��A*��_����N�3f��}��6�����a����5���q�p�k#�u">�ee|ZL��H�q�K�e��������)����dD�Et1������8��E8g��!�L�4..�m��� �y�U-/{N��������rf�����~5�HG!DT
|����YQ�$To&O���a�hnn����444������.]�+��BGG6��������P��o����q�����9x� 555�?���&�v;���,]�4����5n�8���CQQ[�n�b�p�
7���Buu5/����od���!�.���b��QTTTPUU���{n��f&N��%�n��$��O������~�����c���466RYYyE	����y�����t����M3=��������y���������s������;�$!!���R^}�U<����/|!�+�������>���>K[[��O�����7�s�N@+�fN�u'qbccCz�t[�h�E�8c�����N��1�S\\Lss3v���CUU���zy7EQ��W������B�$q���!������MO���PUT`Z�
��7s���r��~���n��~8����������p�!h3�i�8��M�1�
9H)5�������y_�Q;>�Hr�����@J������y}�nu0ml>{�@�����y�����+LzZ{
B!����{ijj 77���f��0o�<6m����|����z�q����b�������,X�@�]���RSeee<��SaQMQQ�����_�*�^{���?�����'?������7�$�������=|���y����w�������B�~����W4�����e


�����c���Q�F���O�v2��������;����,X�@O���v���������v�9|�0�?�x�#���n�1��b�
N�8���[�z�����[HII��G	Y�N������`�^x�233{,������(���k_�7�|3|I�W���OL�F��JY
!����:��=����������
:w���|��Q9WG������&T�w�H�����~8�?��k.L��^�����]_��+��D��������*�M��hd�����h��T���������;!�V�t5:�7=r�B�(bN^��W�'���m3E4���V�^	5w�\���>F����$11���>����z�j�M���(��?�SO6]
III��'?a��e�%Q���|��O]6l��<��#ddd���J||<��/������C466��/j���TWW�/_���l~��_0��J������Cq�]w���}��_��$---d�j��h�"~����$5hk�>?���6lyyy=��-����h'q>��b!!!���<���n~���\P�0(��SA;�$.���[X�|y���^�G����>���_~�z���?
����s:����^@�����9:���
&h(<q~:���&���r�?�+l�3�v�c��<��i��?�M.1��G�i+��L��j:�|w�4bc3�����pyG�>����i��S/
�D���=�_�.xN?��;�L��'������h~�i5��v��Z���oD�T{�`�u�	i1��s��vD���>V�x����]���#o�V��v
 �o`��wq�K�����{��.�|��QZZzU���[�N����C�t�������������f�����	�+USSC}}='N� qM***hll�o���}����tvvRYYIgg'���dff^��T]]MCC��#F��3�\���'66V�=`�C��	1��c9�#��/��K��?�/`Ee����v��>w6�	_�c���W|�U�����A(������<��]Im�]����j���7���*��$�������:|�(x=�����EU�v
���Ve�m$q���`X����B��F //Owvv�"W������7�#==]?��F���Q��s��r�xJ�Redd\��R����KC�|�bs��zF����*�z���u3c�c���DZ�J �7���~8����Fkt_��5i
���<|Y�~ag�T���	)�i����sj����vJO�l���Z���0�&�v���B�z=.�B��SU�'�|�w�y��������o��1c���B�h!'q��������LHH`���(�!��~��������Y��mP8�N ���%���S��jZ�T4�feGA?�#q)�\���;���O��s�q���@�Y��{��=�&g���\;�w���Y��#����t
�_�@Y!>��}����EmC�+�j�\B!D���_Oqq1������[��=���G���e���z����_��=B��%I!����}<k�,,9�'����������j��K�u$s}���]��t
gd���D�)����m�IY#10,�����'P�5,�����$���qz�������1sp��x�<���������$N�;��k�nB!XRRIII455�v���}{�����C=�,����b����<xP�K?!D������A�u@/�f�6�I�R�0�������+���������+���%�
?B\-����$���g~����:2N��u���uh%���as2ml>E'��L�'v0������&�'N�:H�7��B!��x�b,X@QQ����:u���fE!99��'r�5��	!��$q���=�7�s8!�����)61�������n���x������
EEE,Y�$|����9Re����%w�����%��qx�G����/	��l����5�vU�j�E�Q�Ncl�t�QU8R�f��(ym�g�'-6�8'wp��oA�p�?�
5k$�#�B\"����y��7o^xH1HH�$!����b}<m�4�(($�T\���m�����e-
Lw5����St`�h����:��dDQ���g��_�@�7G�w����W��s��M���@���
D������*�D�5{�b}|�����*H��������\!�B�!L�8BA��^�G!���J����{;=�T�:X��z}z��QZ[�~����}����j�0	�bsa��`M��N��q2��A�RPb`)1��e��sO�Z����9h�����
I��&#y#L��������=][P}P��B!�b(�$�CPYY���(�����#A!��G���Y�OZL���2�������INN �w����AU����gVV�KJ���0|��N/����yL��+<,D�SU����@���i��M4��sx�q�����$Ne���v�)*��N2�c�-���^wj^6�B!�Ba��b2�R���!>>Jr!%������<���y��aM�BQ����xaa�>(eu4whfffE�kh�G�8���c�=_/���gG0&3���F\������{��m�l8G�k?����~oxx��'8g�����)~�n9�����v��������=tz��~���q3x���B!�C�$q�����"�������������������&�O�@(:c�����%��%��nh�h�3�e{i�^�n^�2#&����Y��7�S��n�#[�����������;|�ZK���U�������q�c���Gm��f��������e�0l8��v��5�B!�BQ��b������#TUU�k�g�6�B��g>�c��n�h����������={�v�/s?�Y�z
��vhck��)��<����HG�@m���+s��i?G��D�r��p����:O��7�-^���r*�<��!�j�1k�"}���G���66II5!�B!$�#�PPRR�O<��?���k}===���T�N!��_���Q}n;��(�rg K����(��������@�[�8�F����O��F��1��1���`���7�`��
��������{>���/���+	^��k�������j-;����!�B1IG�A����������OS^�}VM
�kkkY�fM��B�'y1��m�AG���a;4,��'O������?��Rji	vF%;M�(����mc�z+G���y9�P.R�J���9�tQ}���
x���~�dmG��������(�G���NT��Y�cl�]c��B!��$�#� �n�:v������������n7^�UU��q#~�a�#����*�Ci}��4�����]=���
]���=�#F����S���K���N��TG����J�)6:��s��(Q�`�r},D��RJ/��Mi����b�19k�>�S�������jB!�b���J�"��;w����Z/�@ r������h5�_{��o.����
���]��<���.Tw��������aP�������H�x�AWw�Go)�7�q�u�-;H ����Y3����Sy��eL_�W��^����������\�W�����}q�J�m��B!�b��$����;���~��t�
<����B�J�����T�+�����F�h	�$q��=KUU�)��V��h�����#b�vD� ������A����4?�Z��b�8���K������#�*5��tQ)q���!k^����l�)��B�d��Z��W��B!�C�$q����=h����N�TTT�E�����������[kq����e2223f�>�������TTn�R�1:�%
����o�6V���n���N=<�tG���6���_	_��
1K��5}`O����_�Q�������(�L�"+�8y����������B!�b�HG�A���7��K�]�~!���;/���g�;����e �4NAAA���PU(9���g���Rj�����8WF�W������1~�b��,{�'�h��.����������d2��P������
i&F��
�����Q��UB!�b�$��Twp�������a!��:To���-��$�_u$|�y���������M��s�����o�����h��>��I�=����	�p����� 6�����;�%yTx���$��o(�ON��5����_;���/t#�9�{���
gN��V���\c q�����oB!�b0���]!D���[�n�����X,�l6,����a!��*����S	G�v�/�����I��yAA�)�w����r2b�w^B��H��<��&��?O��mzx�'�xb@(
�7���Z���1+�A��>G���X~���LH�	������e��}�P6&s�)Y�|w�i����5j�rr\!�B=�	B�A*''������N��������q}�M7�I!D���%�8z���k�v��'��j����RR�����Zv��R�Yc���SZSM������IK���FQ�$�����l�&����#�����q|��1�17������a�N/�N��>�Y�}�#��4=��B!�*�S����w���q�P��ELLN�S�UQ�M��g?����
!���X��._��%i����e]~~���nll���4l��U���LC�>�s�
�#��ZS'����nL3�8W�&���b����;�����������g~��~��������jA�
}|�L	������dc]J�	!�B��H�8Bb���<��#(�V�]Q�V+������<����-l6[�#����]�MGl�r��*������(			�������w��W_���ZF������i+x�kc���z;��>���&_z�M��f�d�I��a�D�I���_@���������y�'�@EeWO%�j_U�O&�B!�P��!D�jmme���]����^/5�7��M~����_���K��	!��K�a��~�1��k��k���|rY���={�����E��Rj�]��(c�{=e5g��n�����HGD��E��z��c�F�Ea��8}^r�x=�O�^��8�I���]�j��+�#�B!�!I!�`0������G������k��o�>=>s�Lf����1c.��#�}�9��i���:�i]�(�7?���������zn��C����::}AWw����~8A������K�1�"��yO4J>	�����>[�����(lGd��e�`,9��T��"S����[���)��MRRM!�B1rW�ABUU��?��5k�����|>�~�~g����=R!����0�����������	_�
��w<c�v_\LL�f���}UR�@E��������I%�"P�{�o���X~+����'/��BD�����4�����2��5�^�7{MQa6nD.������t�>��+7���{CKN!�B1DHG�A���>���UU�x<x<|>^����N|>�����������yB��<��c[�bW~�����.����1�T+))�����:���f���j��bj���So�|s��'����f�BD������g#;���K�}�D���J��>o�h���4)9�'������%��B!�"$�#� ���x����z���_�N�t��q������!q!��kj{#��E7��/��Wf��i��j'c�^/%%%a;>��
%g���������	��2���Ppl�>�6����q!��}���	��&�Te�FsI�}��G_O��0u���Cx���'RRM!�B!��b8~�8��8f����}r��?x���VB���c����J�l6������.�v��MK���jQ`��"l��}�(;d)��}�(��`�g�����<
�)�+���<���#Un:}AST����+��u������ `�+B!�b0�$��@}}=���/t�[ZZ���B��`���� �3�v�9L������C�hm�ze��L��r3��wZM�(Q��1N����&J+�K������T{#<�31=�����@P�P�$ �:�n������%
�p�����
�!�B!��$I!��������v��5
/F
!����6���q,�����)������h��={����rE�FBhNv���,����y���J��%�`lf�"��s�$������������y��T��SUG�|��!|���Z�� X��)*�B!��%I!����`�Z/���N�L�0�����j��^��y�aIL7E?EQBN������r�-^*���Q���/�86��}4������@D/��Y(N-1��<��
�vD��Y��H��6T���;.-�e.�fi|����B!���$q�RRR�7o�����b�����Z�*,*�}#P[��T�>w-���:�I��'OR[[k�^�bS)��IN2�]��o�G���1����n�Py���0o�"Y��'.���^Rm��x=m���s��#$>���_������vm������
B!�BB��b����{����j��r��S9������`�����1#��B�7:M�p��9��g��W����9r�>��{�)ze���Z�N�8n�3���t���FK�N��iF\�(e���+��H>����21#V�����n\f)	i���
;���j��b��B!��$�#� ����w���v;���t:�����r�'p�-[�}���H!��jg��u�������I�OKQ-2����s'������	p���t|��(,�v�yc����!����.GQ�m��~�I���+��*5'�vDsR�����
�������]���q3x�z�	!�B1H��w!����g4�MHH --�y�����}������O�!D_��E�j����a8f����1�T�������F�2�?�F�+���21��s>*;B�N��2�v����-���"�Y�R��6N�y�l5���>]�Ic���M��%�n_�������Yj_�!�B1�HG�A��?���Q��< IDAT'O����-���/����Fnn�i�B��`��]/�S���P�}�DNII	y�{��7���9z�(~��]$-:c�?++��?<�����@�6��A��=�1�����s%0u����n��e��wt��@#���'=��4�AA�����o�G����0�N��������jRRM!�Br��!Dtjoo�����z���FP!����v���D������
}`���;v���s��a@;���/}���|���*��}*����~8��m���k<;�|�/����E��������MO��<B��K���VQ��c��p���o��l��2�)����d���(:����3��<��2�=����P� J��p�I�A-;��\cL_I!�B��CN�1H���C��<11�Y��~�p!��T�S8���X�F��W��C�X���������Jkk+��x��L�����n�� 6���QQ���VB�Fc��e<�JN����]g�������t����m�h���m�T;T������Cbl2�g~�{W|��?�c��WMS%G��@�l��1P+�q�B!��%I!UU��u�>_�t)6��e-���2|'w�s�S��>�v�y�����|�n7���KGG��m��QXX��P{M������e���J��t]v����������b��?��/�`�(����So��T���%����P9P��C��$�1�����d-�@�=�&)�&�B!�(�2!�����G���@Q�.]�C!�O��5���1��������;����D �6f���^z��9*Zi�n���A���2��v��/��^��j��b�pL^��}e����M��,
3��S~{M�;�g�g~V�<�nO[h_��p5�B!�B"��b0���6m���FP!�������(k�Zx7(�i��WTT�kr�DNwi�'N���h�P����s����Z��(5���{�{�c}i��F\�A��5%v�6	�����!��������TMAq�����si�u����C�C�d�7��1�x
!�B1�|�zK---�����8q�����SY�z5N�3|k������a���$$$0�|�,Y�v�g���l�����f����������
���q#%%%x�^����7�rA���Sl������CVV�W�&))�����MMM�����A!��g���Q�(1�p��)l���������l���2y���0E�Rjc��H����Q��s�8�:p�e_�6:�n��fM\d�b0�Xq�\��+��=����a�"���x��@P��3��j7�����D�����7�^��l.^��9�k�q�J�M5�������B!�B��+>�����~���[G[[���c��5<���x����=:p�?�����};>������3���s���o����k�9���a���<�����i4�
����+/��UUU����a�����SUU���������~H{{;����]��o���<yR�ZBD��>��`P���������v!D?	CJ�9�?�bw�6\}���
h�$/�;�p�\N�8�K��������@+;�m���8l�~����1�:}�;����>��X���#���)�����u�>>Qy�35' �TR������B!�,�8���s��������=~��_��SO�t�R�����iS��x�^�y�bcc���~��~�3~��������M�8}�4eee���e��)<��S�����'���p������ieO��}8�-���������_��|���v^z�%|>������?����%���o����[<k��.|%�� ��m����-�b���B��xK�l��&��_��Ea���z2�7���c��	�@Kg���	"���Q���{m��6Ro��RXj�?bQ���X���6a!�#���rw���2��,.*oE*�]�����0NQ~P�\c q����c,�B!� qEW{kkk��w/s��a����v���{��b�PPP��������&n�����������o`�n�C��
PU����O/�6v�X�-[FKKG�j
,�{�=�����;mW�XAVV������0w�\�|����7�ko�+++�5!���}�hll���K�,	�!������G��[�eX�)�wV�������^O�8E!//�����}g[Q���&�����'�����2�iw�%���
��j���9�3�t�S�AH�9�������h��|����KE��=Ya:������x��j�j^��B!�BW��9p�3f�Y6l���������d�����93d��F}����?����]��������SUUEmm-S�L�fm����������s�[ZZ�{"�l��U��;W�!L���S�����S�o��7�3f�(
.����'s�V+.��������{�����07;!
:*�Z�����C�q��(�f���3i	N�vBA���1�8q�=�!��hdI��11��w�WJ�}�%�n�n�Jb�u�Pxl������s�wB!�b��$NE�V*��;Y����x<��Cz��5222B�Q���z�n7MMM=�>��������hz����h=|z�}�'???,"Dd������C�|���FP!�Y�.���53[�,S�o)��W��f����(8�Nbbb�����tb�X���<�������?_@e�9�}K���q��E�w6�;8�c#�
���|���.����JBv�I���"����������\R���vs��]�+�EyF����G&$��$%��B!� z,���k�9bb.����Y���!>>>,jp�����N�(��������v�����h�O��k��OgggXD���_������?]������%�"�95����(���@��O����u�>��,�-$���O�4��������T��9]�j���S]]������������O4�x�Z��lm���-"�w������`��Bx����~>j��GKL��v������J��t��>~ E��|9��|9a���@I�����^j��N[ %lG��]�8]�I��R���c$<o�*'m�X��S��]����d�����S�7P�x���.��Sqi�9B!��+:��[�y����$�+~������^����W^y���n��v"��[!L|>������w�!�@p�%�%��<c�	��?�{��{��<���|����O�����iV�`����b�vE����5PGF���������:�^���#f��
�Ua!�g�B}�8S����%5V!5�xw����.B36m2��
�'���Z��u�5XO�g�B!�"�]�I�i�p^����~��@ ��j�%����\���>�k�}=��1�3;r�|�����x��!�+���}/��v�����~�����m���m�����5����t�����<�$�����z���_$5oj��K�W����+y���8x� ���~�@U���R�a/�2��I�_��W�6�����a��:�	��z������R|������>~@l;D��|.xN��_��H����#i��'��x�kk�>qQ��������%u����?gl��>t�s%nn�"/l�%g>����	�w��`��c��[�C��h}NE��9\�D�B�+qE��^��Lcc#111-�ZOUUillYojjBUU���IHH�f�Q__��� --����u�z���O��I"	�TUe��-�|��E��B��M[k����s�]����K��=Z[[)((�������5>W��u��/G��7�{���0!����b���9%�@Q\�!I����h��76Q�v����$z�|����ZB����=�A�=���7 x���B!�BD�+J��9��'O�����SSS���C�{2b����q��)&N���(dddPWWGKKh�O����@YY.����G�k���*����\����W!"IYY�����3�15rB����t�|I�:����`�4	bccY�x�>��qcH����Z����X\zc��|��r1�.ss���_�t���s�*}�=�����"5�8!��t�)*z������{�MEo��[���#�����B!�����8yyyX,v��IGG���i�&TUe�"��7���k�������5�i����(�k(����>}�'�n7;w�$55��'���Hvv6���9�z��q�������f�*��8q���������w���"Zl��Y���2j�(ST!��������k��L���b�
}�^����X:gL����������(���e!���e`�N��-�N����$
��q
�Bo^=�~��������im��[�
5/c!�B!����ILLd��l�������\{��TTT�������%K�����.o��&����SO������s���b�����w�#//��������+����U�^��-[��������NRR[�l����o|�X,Z�s��O=����o�����z�l��������������#���t:����}�]�����BD���
�����B����/�c��Y�F����c���L�:�C�����
�������������N�(��m���^��La�D��C����1q1��[�|�����0\�j����o���Ob�}T2���CfJ�����A���3�n�yE�P��`�}�B!�Q��?���X,�l����?��)Sx����S/YYY(�Bjj*qq�h���c�=����g


��{7V��+V����������'�}�Y�y�@+���p�5F��E������5kx�e�����t�����	����SQQ@UUUU]�X�������f��m@�M5k���B�?���x��#�N�U�V�I����SUU��F���$s�v�~����F�����0�z)�&�4��UF���n��~:'�LL�%9�F�������VVLN�&LV�������K�����c�
�������}1��B!�BD�+N��l6���/s�=�P__Oll,III��X�p!999����tKRRRx���hkk��������������OR__���%55����m��,_�����V+���(�Qz��[n��[n1=B����u�>_�|9Vk��nBz�k ��4����"��)S=z4��������*}�����#V���;����h��x��V_3.<$��b�]�bw��:Q;[�����U���%��P�e����f|��6?C �������{��z;�N�P��$q�B!D����8fN���#G�������rA�,>>�Q�F���1>|8#F��1���b����IZZZHG�hWTTDSS�%Q�����B�?T_'�=o�s�����IeEQX��ht�s�N���������S � ~zx@W����rh��Y����/|5|�C������}�����<�}qU����������s����B���i�z�k���B!��V�:�#���7o�����$&���?yK�E��o+��so�������t���Q*�HpY��k���i���T���P������|�h*�[�������T5���B5����������vS4�LL�%9N+�Taoyk�������KN��|pR�k%�z��-=.�B!D4�$�Q����?~\�_w�u��B�#U�s�K��9�VW4�b�N1�\�����G	x����%Z�����}���{�q�G�<�gk�G�	����������!kB%��Qb����x�l	�9�3n��u����3��iF����� �.cC��/U!�B�h%I!���M����	7N�!���.�e����S4�]{��F�V�k�~�dGG
�������p�PM����NP��	1�X�8�7�DzI���$���vZ:�������*�i��%k�
7�4}>�|�B!��F�8BD���f
���.r!��o�;�S8���X�g���/&&�����skU�3z��Q�����q�~e�)�;��KK{c��C�s����wr7��zS4�L2�TSU((��j�b���p�]�u���l;8GiA5�5�B!�"�HG��e���mJJ
s��	�!��#P[���v}�Z�%S4zX���*V_;�{v���PU�@�������
��u��/	1d�������M� ��C7DE�����o %�.U�3����d��=��/j^1�B!�BD�6/!D����f����9s���g��X,�{B���/�ck�D������A����b����
X�d	���q��|F�n�� �^��;~�d�(9m$D_P,8f�D�G�����J?����=g)����D�����YP;-t����v)q��]"�
s�`S����<�Y�{du�?�9p���!�B-"���C\ �������;������9|�0>�v���je����`*�Tw��w��k���[��LE���V�s������PUUEkk��.�}U+�`q�M{ 4~�,��SB\M��4}�v��;�O�����h�� �Xa�=�������%mT`����
�Gc3s�=C��}��L���!�(�B!��&��"B���������~�~?^����'q��<���4�B�����Q�^,q)8L=&���r-I�����������?����o����G?b��=zl��p���4�K�q��I�i���N���]�5�V���j���������������EL�X<�(�����T�T7����w��'�6#(%��B!D��$����Cl��
���N�^/~��@ ������UU9}�46l{�B�1���5��9�.���!zu%q@%)6�����TVV��?��g�y�WK\
���������1�X~����b����������EO�1�[ki����P�����t��E�$NY]'��#��(
,���aqZ�0_���5����B�8a��B!����"�]�����IUU�����.~�?l�B�����;�m���
�%�~N�v`=��������������{���u�W�8i�i��b�p{��PBl#R�X4�:~������?"������:w�����$zo&Pm�"H����N6zY�:%�q.���`������E� n�����!A!�B�h!I!������S�V2�7�;;;9}�txX!������E}��q#�^ND��3��\�����v����`�Zq:��l6�V+���h��
�9sF��;�Q�_g�G?�7�����]Bl|�~�����;~����}Be�S��K�;U�4`BK��g�"����c�X�k>�9e���jB!�"
IG����������7���ip+����{	�?��]��d�F��Rj��c�JV:�V+������x<x�^=���*��:�������N��7�y����V��<vkt���/���K)}q ��ZE��3�����MJB�V���s����B!�BDI�1����Q�_A�����;<))),"�}���8�c��k�DS4zt���l@q�i�*
�����������x<<�����V�Z��[
�/���C�[�]G6S�R��bc���,q'D_�����������`gRF�>�qBJ�]���Q|�$�t#(�q�B!D��$��f������{c�XP���X��B��.P�1��D�)�����iF�EK�[,��XO'!�>�UUY�~}x��U�;�D�H�~�**�L��%�V������xS)������~����5��8;N5���J� g�t������6�2�����B!�QD�8BD��n�
EQ���X�Z
o3EQp8�29����z�#�W�g�K�������>iq�����������8����8r�HX���P���|�7�����"NV��g�����\��C�5!�R�1���;m�`|"���sc��#U��Bqq

7��[��t�=S�qZ��1!�B!"�$q���&M������t�p8������,����Xa��B���v��)Z��]��Jt�m�P|�H�,]4_/Oy�I���~.ct���������� IDATq0����;���3�/`l�v�Sq!K�p�>����X�R���������2ct�>��x?�E��S�gX\2�n�W&��5�X!�B��Wc��V�^��S��l8�N'6�
EQ���������}s��j��}��5�Vb���us���q��M�'����d�Xf��\z/�a�.�N��E
����������T�QJN��C�[|�>B��1m	��;�a�!��N�W�C������L4^
�Z�{���j7��d=�[���>�p�nk_��'�B!�C�
8����������i�Y�f1bs��e�(S-o!��K?������yw���R^���TJm��8b����N����~c����N�����E�25���7m%Z��
������������6._�!zg���a�������KP�M�N�D
�!���kJV��"���V�@�?�o7��aSX���s�q�.���V���7>�o�����w���9�;a�5�B!�"�HG������-[��m�����+M;���xm$�R�M�6���!��5�R�3F+K������^��m�p8x��9V��������o�]=A�x���� ���qT��f������������GU���L���%,������	XE��j�Zm��k�no[o�U�^{����r�ui]�h]W\AAD@@�}	�Bf��9�?�99s2�L2��������9���$0�3g������@���r��T���J�*�N��/I�|+��{����i������
��5R�7���#�tO�n?��:���4�$)�e;M4C|�P������P}ZU��$2��i`���,���|�u�Y��LC���4Os�+g�K������������[��W\q���o/��%�����leee)++Kn�[n�[���o~SIx
����i��GO�HR�R�%^^���M];���~�j�h0������f��n����6����1���K}zl������5v�y������$�x~h$��H�)VTT�?��<������ci���k��6������f��������=jo�����;��C#G����0g������r�U�V���5mZ��%�o��-��F:����U\z@�>�,�t�w�pp$���eu��%)b�tp��3+C�"�K�l�W����CR�NghP����U��*h�|��*��-�����)����*��.((����m-��xW<mg�>Z���,������5�p���i��n�I�7o���~���by<���[c��U�V�������������}��Z\Q��q��"��&
:��@cx��V��u����o+8��i3�p����V�^F�.+��i|�<{1$]8�m��F��YZw��F�+
U���?=�1�fH�)�{�n�Z��<���K�r�,-����R����!���=���__U����8a���S�~���*�Y��^A���KR{I�%����-�r�O��MG�I�|�^P��7�������� ����g/�I���W�=���N-?��&�S��t��$�	 }��B/��LW�N;�4�3�R������Z���������
���)7� j�2[=�{"�S��a{ot��f�m�A��^`��h�,y�~�<��~QFuz$C��X;���j`�S����'��Y]����������bKK ���R��/�������/�\_���QyLU��f�{�_-e��+klK���;l��6�������,�M��{��rd���F�1U�[`k�����E15���f���j�"_'�.�-�,;w(��B�2�������/�h��y��4h��4/�'5��-��3,�g{T�
}���<�#I{�4V������T�J����h��(Gn��#.2��+��N�A�JCNk��-�_:q��m�E���r��QWH�����8�����i�$��;�E�����<�x@�v�2��� ��U�}\3�3�J9�3{D�������S�d;��sK[��t���N��S+���e�=*:���@�<���N����[fk��<�N]?���8��g�kP�4{�KC3F}S���-��/��Z�L*y3�!�FH�Id�V�X�_���z����~�zm��U_~���f��A�����*h^�
o)X~$t���{���
2�u)���Z)+�����(u��^���>���MG�B�nW�}��E�Yh
�v�)��t����	s��T���f��s��3[��q����"�e[�5t�|�V���`I5�1�8@-Y�D�?��*++������TUU%�������Jeee�+������6O�Cg�����A�1�������������H�n�R3y#�����z�@�j��X���e���]���g�����T���!���K{ih�VQ�9�y9j�v��Q��]%�Z^l��;�@
T��i�$�$�����%IUUU��|

����z�
�����O?m&u�9U�X�@Q��@���-��i{�	;��$9���i���_�>*U��JiGy���L=�������Y��^ AY]*��h����'k*S���n���]�]�O}������[����{����K�}�}V������W�R*Y�H$q�$y������������&Z�a��Y�v����goI�]Q3'��x�:���f�������L��A��������iY������$����UCt�������t��������g�k�H�g�w�����(�VS��]����������$U-�����\4�;�6Zur�1I���k��4BH���7KR�N�a
���-[��j ��;T��C��3�Km�Z��&�3�G,�V�_Z���F�|������f�ue]u�����:vr��X�v8�^�	d�'W�~�y:����v9t��v��;����m��9��!��m���y
U�H*�/������r �H�Ir�x�!b}��������xW<c�:�Vv�q���TTV��Gk��Hy�����t�]{E��
���]e/��G�>:��$��r']g�V}���G�s����m��
��Sv�����Z �K'~WJ��<��8X%m�R�t������>��{0�\H�I���/Ir:cw3�#��;//�V�cT������=��N�e��������C��5[��s��u��Z����������d�J�8`/����p8��!�23V@&��
9�v
�A������t��������MIZ�������bx�Q���}�8O���
�I;~J��Y����2�F8p�$)++�^y4�C.Wh���j y���K���g��r9��"3�8���_�J��G>;�/�0�r��*��}�����NZR��{���p��s~�>]B�/���R��������)x��� }������Ui������c�}:�e���������^
4+�8@��{��j���\.���k�w8r����I�&�S�N����J��/���1WJY9��a��r�{�+�)��w������:Qe�us0�'�����K�������J����2P�]��.{UD9��p�@����@��+��l�&:����^5��_��X���I:�M��;{itE��kF%�,uO��6m��������>���l�\.���u������p8��];}�[��]
�S��u+B��8�r��M[��WY�����w��C����UE�������3�$5,��"��]r��?o�v��j�O��wWA^
����,+G������?H�|�_T��9r�H��o/�A+��$�=��';�4��6�V�P�b�������r�����f�L �������gj����N�rrr������l9�3F�������k���0�]^3�<g��r�lki���P���=�{���:x,�t\�r��r��Kc���$���V���4��X8@��G]f&m�������Ez8��[�{�$m^��0�q���d/�����E@�a&�d��w��5k�h��m:q��:t���C��O�>���T��>R��+��3�jKm��lo��(�����0���8�
�)�{�^����z��@�8rr��N��gI������p������w��Z�3������>��=Z�Z!�Xe�2|�Xe�H� UH����vk��	�0a��
��u_���������2C���6lf���j{Q����x�TU����t�_$G�^8R�3�[�~��_��e�}��<��7K���=�����>.Iz��b���Z[;��6(��UY�z������� �����@�6Uo��<�L��R�I���>UV�U1���h�JV[��'$W{M��~*��e/�bOk��\i�{��S��aI��r������^��J���c-��7_�<(��*������H�p����q�����,��a��c��A
����$J2��!��(�=�^#��K�I���H�	W�qrF������jk�N����%�^ZS��8u��m����[������=�r�����Wg�w����G�[��y��x�����vC���"{q�vi�^s�����S��4f�4���S�����_I�f�[H#����u�y~����`�f6��F���K��Jz�

�:�x��Z��P������Yz������Ycg���$�����@h_g��E������h��^SN�S���%}����-\!u�Vj3�=p���x����`�~U}���Ez�����=���/�)V���&����O�|`�~���6k]3k�!m/o���x���K���1��Z/���5gT{�]=�<����������*������vQA����H/��B����o�I��eO(g�yR.�u��s��R�V~uL�{��Z!�e;������W�i�g��v��]���Y:qr��C��Y8H�����T��E2*�I����e�2IKw�g��+li/�F�L��y8�]U[��T��n����2gm�L���W�~z���w�q��Q�:������I�e<�}�O2��8H"f��uf�����=�b9r3sD�im�j�v���^��u�������Up�r�OS��K����I�UH�\����c���k��Z�U�I�U���e�tFf��'[�+G���.��l��%z�����
;�h���5i��hN���k�z�r��8r��*�>���]<������#�K-|@S�L��y�/����~�����?]���^���-����5������2�!F�9E#��h�?���:~"4�hn$q���x�<��7U�v�,��g�����>��M]I�{����k������I5��H��u������{UJ\:���TT����8������\V�����|�![+�y���k*p`��w�6�=j���T�����U
=Z=p{�4�K�Y�qE�T���(�*�C0��E�������f�9/G���h�����7��K������[Z��$_S',�p��TV������jG���0��vk�~�-4�KK�;�����t]=��r�����*�/���Z�j�*��{qJ\2�@N�l��.��~tP�^[�M�+DN'�Ycg�O�������S����H�,{�|��C���-��3����p������]Yd����Z?;7�����%��\��W_��!Uo[!�W!�����Y��h\�|��V*I��T������:�7�aN�S?������5
�:RvHO���n��N{S i�
���w��R0 Ir�uR���m-2����u��Z��r:t��N�����C�%p�P�`P�����PeU@[T��M��=�6��E��*������<����-��-K,-��"����QU)���s���$WfO�=R^�����3�Sa^��$�#��7�{I�{��"�%���J�.��*<�S����XV��������@����k������$GN�G^jk�y�]Ud>`l���K��Z@�8����IGn�\�]���jw�WK���Q���cUzws��'��.�z�o�}2�w���]t����f�!���I0(�G��������iei�y�8P��_�������"�[�����{����:�G]&9]��f���r{QL
m������9�V�|������7--���	_#U[�(X�7t�p�3nvd�4�~t�<?�C����oi�#��[��cv��CO�N��^���V��E1��C��}��i������HY����2{�|���i�8g�t9�v��f��7���y~��B9��L9-����T>�m;Yx����Z��������#�}�"uZ�4l&PKw�����n�h�~��u�W�J_�~���:���:X�G��\��2@g
>_m[��'�I�&��6���S��3�;���S�h�'����}�tF�\Kh^�Ng(��gtb�?U�n�GvIr���t��] ���%Wz|����a��g��!�y��3�6����$I�|���0�?��=���'��s~�i�/�������0@���p��
QV��������b���$w�S����R����)s�;e��KG����f`��:�C�v>a������9���Q�q��co< _u�LQ��
�e�=:Z~X�O�c��=q�;�������	�Xj3��#^����<�xx�m��i����	Ir9���.�r�?���;�C�l{1�����Wg��C��>�]E'���$_���%��$g~���fk�9Czj�'��(������G6����n�bful�c��$e9:��Sg�ok�B�W���U��c�4C��_/.���h����_�|k�m�{�_��#�����R}y�f���&*�U��2@4�
[���{i����lO�J*��2����-�'�Tm=9x������*h�M�c����"�AH���|��&�[.Ir�[�=�b[��q��s+����������,-
��rj����5$rV����"�Q�c5K}���D��FPN�`�q�� ���~��y�y��������E*�$I9YN]3���������(���y$p��&�`U[�(xt_����g���dg��e_���W�,P{6���=F��tI���2����"�AH����+�i�8[�������J������<:w`�F;�l�s�t���$�*��\������+�!�@����(��u��g�5����tWP%'B��t��.r9��@s�����}{���+������W
B��]��y��m���
����@��?����W+�������<�9�$'��{���&>�^%Ij�i�[.��.�x��
h�,{H_�cE
��`�WU�6�3aN��o*�[J���W�!ul��UA����S�]1� �B�L��<����t������TT�O�l�zw��I�f(�U{�%@��� �w�U��w)pd��J��B���n/N+��W������C'�L��UE�rg�d1Q��u�~�����&C�4W��<��-�se���%{����^�AC��W;{�U��R�v,��PW�X����i�	I2*����_K���*-����z8�T����A{1�)�$i*xx��+��G���Q�U���)gHZ��Q{qTIm?�r_z&��I�T���IF�)86U���R��7�#���M=IAC�{�g�8%�� A�w����(�n/J�j0t.JU�kNq$qHC��2)Pe/�8�-���j��F�69�"�SR����f��ia/���mW{Q�������^\���<$qN"�@�0��(�!#P����-br����(-\1��\q�q8��I�����,{hf���+�%��*XV*s8���#�]�6����^�r����>:�@��L��T����b�SIR(X~D�����:{��;le�9�����?��������G���u{���V���K��83z�3?����F�T1U.�7JG�a/���j�e IDATW���yD����U)U0���{"8�z��-�O��cU�S�U��:���W�\}��V���H��2U�?P��Kr�����E���
���6�r��&��������t�����:�������+���=Z��i�)���im�:���r�!�@����r�(vG�����}�Z��d�J��~:^��������t�������m�N��F��F�L�*�����$)8���(�@���N�$�����������,k���Yg�k��J�9ZS>�O�~0�	�F �@�A{ILF�a������������UV���%e�h�k��A��Q���<\{��bru�e/jVkv�kQ8�\4����@ $qH��!�����h����������o������1/G�oC�q���^����NfBZ^�K9rr#������:v�o/���m��Eh �8��������� �2i'�7���p�r�Y������b�_�����$)�������U�Y���ni�1���G���jq��,���h��6
l�(����e�(����;�mW�[.W�.r�w��L���������7�=j#�@�pe����\��4��sK�o��#�����������XN
�+����'w�G5�[+M��g/@��q����5��\��7���1W�O���[ ^,��v��|Z+=��Am9X)�dy~�,�7��fn�94I� =�{�_�T�/��
�<�Nuh�-��&E4JK�K-�.{1�{��!�8i�$@"���H��!�8i�$@"���������2-Z�H��m������u�y���v����)��)))��w����u��M����
�j�*��7O999�K��)��y��'t��Q��;W��W ���>�e��i����9s���fwJ��S\\�5k�h��>|�$��r���������U�lW��)������%IC��(���Saa�v��Q�*�Tg��}����B[����/�����r{@�;�������$����j���I���S�V�l������E�p����!���x��G�E����"�o������BL�~���Occ�7�Y�X%e�����1���[��_���Uc�)�1��!�_]�t��)��q8N~��"J�����6u�T��4��������9d/�Z��x�<�y��P��}������J�Xg��UUUI�<���~S�N��)��@ 9N�=q���%I%%%��������m�RjM��J�����}{DyEE�:�>}�D���)�������N�>��#�8q�,_�x������-�R����M�6�>}�/^�{��GS�L��}������[�n�4i����8��8�t�����t�����SO=%I0`�n��&ee�r/HS�-[����o_{�������#G��E�����Rb����N��8an�[]�t�����G 
��HC$q�I�4D 
��HC$q�I�4D 
��HC$q�I�4D 
��HC$q���"�S]]-��k/��a����a���UUU���bF���a^�7��{:klL�@��k*��n^�W�����fQUU�@ `/�K*�x�KeLAL�����O�#�1M1�[S��0�F�o$r��H'��klLAL��1m,�i�3C'N�h�k�J��4���t�hL����b
��,{A�(--�k���U�V���D���x��_?��5K�]R]]���zK��-���{e���w�����k��r����"�|>-\�P~��:$�0��uk
6L�^z�
��DX�t��y����K~�_n�[������������G��y�.\��7�����r�G��:u��>�l9�%��1---�+���5k����#����l���G��O��	�|]�{�9m���^\��a�t�W��M�4�;v���^������JIR^^���K/�T�:u�]���R=���������G{�$���X����>�������p���@�����_���\�%�T��t���6E?%�uklL���^UTT��k����4r�H{�$�i�4&�EEEz�����Q�v�mj��]D�4��h����~�m���;v����*{�Z�OI��K�4
�i���%bj�e�����(�G��`�ir�Z�Jo����m�f>�/,,��q�t���zm�"�����~�������}�.��BL�-[����o_{]���k����^?~�^%Ir8�={�.��{�y�}��G�bS�N���_�R;v�WI�JJJt�}�i��}�*IRNN�~���h��a�*=���Z�z���t������/�K�.\���{���UC����seee^n��1����m�����G�[
6L?��O���c�����O�V���2q�D�|���bb���K������QBn�[��~����o�����Zw�}��m��y����3��7�����C�7�v:t��w��:��R���]�b�h?%�uK$�7�p���������?��i�����$ilL���������(��C=T�A�4yS���2=�����u�$)??_���oUPP`kY#���D�81MNLS��MLk���O?���{K����n��OR�-�2�i�3C�����{���L�:u��y����o�5ELS�O�,Nw��iXc�xX�}����-|�����[#I�������@ �������1l�0��9S�G�VVV����a��=Zyyy��%I+W���!C4s�L�?^��u�������TQQ����k���r:#W������k�.I��/�PC������C���'������5�������K%I]�v��_�����u�������/��gOu���z�V�^����o��V�Zi��Y�6m��v��={����ZEEE�z�:th���.���\.<xP�v���)St���k���j���v���`0������5j�y]��l���S��g��Q����_={���X��.�����@  ���i����s�����u��q=zT�@@6l�9��#��e�uz��G�n�:I���oV�������N������1c�������b������R�7o����#F&�����T�4�~JL��hL,X���*���i������3x��Z1��&G"1-++����%I=z�����k�2�g���r�#g-�O�#��Z�����{���;$�b<o��������$��%b�����}["��bz��m��Q���1��!��/I�5k��n�n�ir,[�L���������[������UEE����5n�8����i��i������1�����+�^u��p�4�i�&<xP�4|�p��;���:u��{�9-X�@�a��?������c��_�J�
�(?�������\eee���V�\��'F�y��w�}�vI�y���k����;��s���O��������k����������g��z�-IR�>}t�w�@�:�,
:T��%I/��B�����jsZv��-u��wG���:u����UVVj��������IW��t����<y����c�M�6M&L��w�-�0�t�R]q��������k�p�BL��d��QJ����5k�,��������.m��U%%%��aC��X.\�e����#<������z���c���1C���o�c����C�|��F�m����g�T����������b��S'�p�
�������T1>|����J{q���M�)b��Ci������N;Mw�q�Z�jekY#���D�81MNL���}��F���A������f�h������}�����D�J@?M�l�_������y>e��~������'�|���JsM�1�j�~��gq&hlL���q)��BLaN{A��N1b��&d��I�����-55�	)4c����y��.�0-\�PRh����gG�K�UW]e~��\�2�.���B7�#X��k���g�8p��[�|��u����j-a��S']x���B7�k����Ow�����D$p�����3�8CR(~_}���Eb�i��q����tj������u�e��uz����������|F�q�+��J���~����q*�x&HULALcKFL�A?M�T�4�4����/��-[�H
-�u������?���D��DL��D���"�u�����J��~D����~����#�KR��m5`�I�=����"��+��H$��~g�Db�HO��S�U�%q�S<KKK-5!��"FO����}���m��}W&L������z)��hx�Dii�y�`�i���G�M����6l0����C�'O6����6$3��/3��&�����x����������#��0��q��������S�FV���o_s���7������ U1M1���c/�i��*�� ��%�={�h��E�BK���G?���N4���$���i�b�b[�1�K0��/�,)�}i�������	?���Puu��6����i"�i"���"��6��'�W�)�*��8���7��y��7j����0������~G�5��v�j�	�Q��Z?��#6v���'NH
�����gO�8<�0s�]�n�����cG���>�#�%3��}v$�Z_6�0TRRR�f��4�����>�����,����k%��t�7��������������������oob���X?7�O����������"U1�&�~JLck��J�����#G��z�U�����1�z�*))����>����hL�z�)���e�]�5K�>%�>NL���4��61�?�uY�|���������-[�u���
������3�<Q��z�������Z�X1�Ks��D>�3E"1mlO��S�U�%q:v����:K�TYY�y����:d�Lk��]�#����|�fs-[��
!�F���JX7-..�$����,����ylg�����C�BSh}>����J5��������={�/7���{������~W��r�n�����?�3�<c�Y��&N�h&B�o�������7�\�R�6m�$�3&�k�����������m��so�p?m��M�_f��qIU����]C�)1���bz��1�������t���j��9�;w��~���Q�a���i��n��U��~�����[n�Es���]w�������FE?m:��t��f}���u�EE��%���D�81MNL���}����i]��+��")4Z�>��~�\_|�����o������f����3�/����g��S�����|g�Db��>�h_!��,{A&��w����bm��Aeee���{5f����[^�WYYY���~u��U0������~����***�����9s"���"gt�m��R�z]x��u�O�k�So����{����^��@�6N���iee��n��;v��7����W�V����}������?����T�-���ku��w*//��#���\.��;W��s�>����Js����)S�M�;t������ve���~Z���$��oT���#FY�aNo��u�B�B�����}<S�"��4�����*�EEE�fP���OO>��6n�����'��a�ir5UL�#���6o�����_���w�}�D?m:��t����������c�i���*//W�����o_��1������D�}��t:���491�k��mb;�uY�j�9"���j��MD=�4�:w��[n�E�<������t�R}��g6l��,Y")�7�9��c��n����9�i����}g�Db��>�H_!�����#�6p���1�a��U�������R��}-WD��zu�=��������UPP��n���,�p����KM�����Xx�mx
���k����	�]��3ES�t��Mz��4�|����_�~�7o^��'R�����������[o�US�L1�x;p������G�'������~�����Ouu��}�]UUU�s����osD�|�7�|SRh���	l-"�|>s��X1�"_��(�T��L��1�kh?%��K4����O]������u�
7D,9�z�j���[�9�4�������q�t��7k������kTXXh�?��3��c���H������~��g�����d�>|X^�W���Z�|����Ns��D�S���491�k��mb;�uy���$����%����7r�H]s�5���c����c������Z36b�/�v��O�,�$���1}<��BLv5�����H��{�9����@G�Q0Tuu�^|�E���G���x���i��M�����8~��<�5"��B�����]�k��M�aQ����h�7��o&HVL����q��Z{�M�2En�[s����4~�x
6L?�����<EEE����$b��k��#�$�S�N�h��j���={v��U[�n���?.I5j����J[�����R��5�����g���iXc�)1�_"1�1c�\.�.����>5u�T=��z��w$I�-��3�p8���D?m������@�����)S4t�P�|���:���u�=�h���
�z��7����r5�4����G��
�:���5l�0��nm���\o��������dm"�)��xbFL���T�o��cZ��?��L��5�|����&���������R��m���?��3-_�\S�N�\Q�xb��~���>�3I"1mLO������)�Jb���!�������6���5K��t�}��Kl��Aw�u��;f�����\=�����/~��#G������_����[k�v��Xn���#����
�F[�{�Yk�E�i��:T=��n��fu��MG���O>��{�|m�F���n�)��q�����a��#��S5��w����G�|>egg���o�C=��n�Mm���az��7��?��������>(��������?�a��i]���R�~�����7���?d�T�4�������HL%���/�%�\5��g�6�u��s�xc"E�K��G��������������	s���={�yn�ga���hlL��%����~�����+��E]�_�����+�����|���*��O�7�1m�����}�����,X��<�k�F���D?m���{�|�_PP�����z������^�W�>��.\h�2�xb��~���������}<��oL��q���h��S�%q,X`���{����������n��i��y�6m����n��_����p8��C
2D��v�f��%)�Y�?��������)��X�����x<fY������Z��z���Q�M���lu��I'N�=��c.���{�i������<x�yl]�8����1}��'���o�Y'N���~�}��w���B#��_j|>�|�A����M�6����z��v��/;��������OU���i�����4���4�Gg�q�y��4���3�<�]ZZZ�5��~�8���u	�������<����TPP )� ��m���_W��}J�}<��ML�x$�}����hv��e&�{��e&���}]%�iC�����g���k�W���z��%���/�P���S���%I�=���n�j���xc�d��D>�3A�1mlO��S�]F%q�����+)����o}+���r������u�&IZ�~�v���&�+���\�t���q��R�uv���$�}���"����%r�TS��]��#w�Q2c��������<���-���nh]W6����1��g��l�"I0`���Q��M���?5�����H��{L;w�4����/���?o���Y����U���/�a�9�l�RR�>*E�G�K���i�k3A�b�x�)1��HL�e�K��#�4y�S���	�����~�p���� ���O��`��ri��������%���J��S��������a"��jVIDAT1�W����i�������yk�F���D?m�+V���R�4s��ZK����Ks����.[_b.���+��4���bL����b
���$���UVV&I:��3j�[#�>����6dZvv��|W �HX?��#H��k�JR�.]$E^�qMx91I������oUU���X��L���Z�����+�%������/���n_~��ymY)�%r��!��������C�d� K�=�v��U���&���H�v�2����������V�~���m�X�7.M��3A*c�x�)1��HL�e}���D��&Gs�������%�uK$�����������y~�oL��Oi�>NL�.��J��61���[ZZ��>�HR�����cm-j�O��:#7�1c��E��B�x��!1�W��i��O�>�3A"1M��'�W�)��f��`����&??�<'�e�)�N-����y�}�v�5�<�
�ggg�G��j_[�����</��E������T{��������d�������� �15��i0���o��d�������cbZ7kL�%����������sg]{�����^�n�V�X!I���K��sgs
{�.]���������[��{�6g8�c�\}<�2��������4^u��~������7z<�/�S��{\�i�DbZXX(���@ �=���?|/��}JS������4^u�SbZ�Dbj�����{WL�6-bO;�i������p(??_���1��6$��j�~����L�HL�����.u�b
����8�)�����Yol�c����g�[?��k��Z�*bDi�����y�fI�������Bs���m�jmL�j�*I���3�<�,��@ �5k���V�k%E,�����C��k��h��A	)r��^�z����n����b���B#�$i��Q�4iR�?={�4�2d�&M��:H��O�Y�n�������k�����T�4u�SbZ�Db��k~!
�qf�K4���KvL7o�l.b�����6\"1���2��{��:g"[��>TN�>��h����4$1�O����iH��Z�����j�BP�ir�S��k���O�q1�O������|g�Db��R�>�h_��%�S5�p*r��Y�������������m-BSQ�y���~��g����'�,l��%:r���������{���������ys��9��c�;s��az��������k����������r�u�Q���J��uRhjnx_�^�z5h{�5EL��[W�r/���y��KM���n�:{�����������"~/1�����n/Y�$���O>����������B[��5j�9�h��e�~wuu����/I����Yg�e������T�Tj|?%�uk���[����!^|�Es�������K��di��.Y�$b��0��o�D
-9bG?mz��t��q�B#����{�����k%�fWY���}J"}��&/�Rj���i���}�����������#�irX����6?�^x�����Sj\L����D>�3A"1M��'�W�)��u����F�\33]9?~�\�4���e��*//��U���?�Y�����a��Elh����?��W_���UNN�����c����z���
�]v����g^+�>�_�>��3y<���j���z����l�2I�)��g��^���B���{2C;w�TYY���k���R���;z��gd�Z�j��o�9b��.]�h�������[��c����|Z�f����?���B�C7�xc�7�� �����������%K�r��������k��m��?�������6U�u]���ecl���m�K5��?$1�\�$F��,Q��"J���hBB���DH�\DL���0�16`lc���~�X�_�i�<����W?�f��}�g�}>�s��)I�?g���a�����^{�����W���$���7n���#*//^��l���m�id���:{��n������:uJn�[���jnn�/�����rC��O2�Ouu���;'Iz��g
+6�
�������N===:s��F�)�����j}��7���������
>W�^���h�T����42�1
������~�����t���[W�^��}�t��QIRBB���['��|.y:8�����Y_|���;&�����$�|>]�xQ�}�]�~t#G���5k'�$�t0X���q�t��q�|>���_JJJ��#t������$-Y��������9NL'����&�������{�'��.]�	&'D@����L:tH~�_������
��q��5UVV���c�z��\�f�!_����F3O�|�:+1���Vr��$��.]����>�>�O[�n5,W�$;;[[�l1,�������~<�����bm��A6[�U������|$�G[�n
+H�����s��������;���3f��t��5m����'R��aii��;�Y�����w���Y�l6�^{�5��?�����������&��TRR����G|?������u����6��j���2%$<������B��e����;::��g�h#�2e�>����WF+�c]�b:yJL#����Zm��)dV8����_=��}������~�I���!����n}���-:$�t0Y����
��;�y4+**�G}�kV�S��81��F�s������V�_�^===�����sg���0#O��^���/����.\h��1�v�Z�.�uVbj5�����+����aH���z�~�;w������z������h�����a��n�a���h���jkkSSS���c��4q�D�\�R���O0H��Y���xTWWg�����3g��}�]��tB�?^EEE�z�a��������LEEE��>���*..��[����h��G��U�VV�%Vb������\��yS�o�6���v��1C��������n�3�<��������{3�+V���@L#KOO���������$)++K��/��+�r�A�6����+�����z����vk���Z�vm��\)z9�����Sb���z<M�<Y�����B�$$$��'��[o����g������JL�������������>���*..VYY�a��>����SI������3������f�����Z��m[9N����t�c��mb�L��������M��y�L3�G��������@���a��f����@k��UII�a���i����wq��S�9n%W�)`���	����;w�(h��������A���Ny�^��{W.�K�G�+<H�@RR�������>---�q����233���/�������������#4z���z�C����������������VNN��v/����R}}�����t:����������1����K^�W���JLLTFF�#+��~y�^���)%%E����������.Z1�<%��Y����w��� ��'�����G��r����<Vbz�����.����������y:x��T����������JII������71�r�b5��i��kL���MLy:8B���t*;;��}����v�Z�.�uVbj5���
1��S�J�!]��7}E�����:�81�"@J4w ~��������n���/I�w���]����Nuvv���{���Rbb�����r������#G>�M�C�����x��n���{��)99Y)))���Qaa�233�O .P��c'N���]����UTTH����_m���4.99Yyyy�5k�JJJ���n�������g��CEEEZ�f�����Ciq0�:;;u��]�pA��������/�n���J�8���J�P�.����" �P����������nI���Q555��q����
��O����������"9�N��������:�4i�a>��"@+))��i���_��jkk%I������/M3���?��+W��p���G����z�:w��~��7��u+8������g��|��`_ Pyyy�-I����^x�C�$y�^>|X.��<@\���\.��III��6����d.�K�C�������4������P/������u�����#G�h��%5j�$����jjj
�G,�HRNN�V�Ze� n$�;���p8��oh��)���'O_�r���[��qE���f��}�����!#RJJ��
���"���\C���5���t��H����6��8x����Z�1x~��WC��	E<R


�vZZZ�qAA��
lWWW���"�����"�?�����<yr������E�BF�h����x����xG����'
E����S����^|������Zm��M������c��Ds0����?���C�����������������_�w����G
cUUU���R^^�JKK5}�t�8��"��c�TSS���T�l6utt���^MMM�����Rii��[R��j�W����s��?�m�V[[�;vh��9Z�z��>:��80---jii1w�;v��{�=�����
�y�fUWWk���:s��a����~��>��
9���=q��dddh�����}�F�e�W~~�6n���������0v�������@<`%��I�������v��~�\.��n�3FO<�����d���O{h'N��M�t��AUTT����O-]�Tc��	�
��Ff���Z�l��{@�l6-^�X7n�����%I�@@�N����+l��!i��E���+Wm�:�8�����t:��;w���0�Q�@\�r�bEI555��|�vfff�(CE����&�>}��m������w�f��eh0�%�;�h:r��������<��7O��OWFF�$���[UUU���T]]]�9c����O?l(� f��~?~\�T[[���ZI������R[[����C�"�����~[v����PG1���Kjii1w�����'++Keee7n�y�!�"bFQQ�>��c<xP���SOO�y�$����������t:�����K�����o����C����������!�����TM�0A���������jI��@�6l��N�j����`�@�Q��AqbE�D Q��AqbE�D Q��AqbE�������:�Q�J�SPP`��!k�Gp�IEND�B`�
raw_data-read-only.txttext/plain; charset=UTF-8; name=raw_data-read-only.txtDownload
RW-ramdisk.pngimage/png; name=RW-ramdisk.pngDownload
�PNG


IHDRB?H��	pHYsg��R IDATx^��y\T����0���""���������n�Kf����k����n�d�������%-��}�PDP\p�XDE YG�m~�k�{�sf`f��~�|�8�p��s��~�������� �B!�B!�B��l�+!�B!�B!�B�[�����'�B!�B!�Byj����!�B!�B!�B��(B!�B!�B!��z�!�B!�B!�B��(B!�B!�B!��z�!�B!�B!�B��(B!�B!�B!��z�!�B!�B!�B��(B!�B!�B!��z�!�B!�B!�B��(B!�B!�B!��z�!�B!�B!�B��(B!�B!�B!��z�!�B!�B!�B��(B!�B!�B!��z�!�B!�B!�B��(B!�B!�B!��z�!�B!�B!�B��(B!�B!�B!��z�!�B!�B!�B��(B!�B!�B!��z�V��B!�B�����QVV��
�`+!�B!�iC�BH�KKKCnn.�<y���"A�����666P�Tprr��������nPqq1��������E�d2�|��}����J%�6m���u���P��h���x��233q��y����Z�o�V����w�;G���PRR������A�P@�R�Y�f������i�9�gk�g�yeeex���xS��l�R��	

B�f����+�Tew�����3�5k&���CmT��/mT^^����9��hXU^^�R	{{{xzz�Y�f��g������Bj��p��	����-o������=�u������[7����7�	%%%����R�����xs�*++���7�G����*�
M�4A��m����\.��Ji�Z��}�o���G�P^^����m�����������DGG���{����B����|}}��];���������_pqq1���+))�������f�:�$s$&&�����������I��Tvv6�]����������������������p��<~�yyy(..���\]]��C�n�����4WC�y����Gtt4�{�9�T*�f�����x��!rss����
����Z�B��M��������F�Aqq1{f��d�mi��e�����'Op��M���:v�(�����<\�t	���������������www����TZZ�k���kQQ�����Q#x{{�C�f����j\�z����������Y�fh��=��i#�
RU�E�!�m�������9;;�_�~3fL�~<�'�|"^m��[�B�T��%K�@���=t,[��m��RSS�l�2�m��/o6�F������3g����g������k4����,Y�D�� ;;;����=�\�����-��G��u�V��*��
��/��u��V2���c���x��1q�D���j��W}j�BBB�~g����1p�@L�8�������/RU�v���c������b�
4h�@�W�*++��+���<x0�x�
�^�#,,�w�Fvv�x�������c�����1����[��i�&ddd�7T*�M��a����>s�����Z-��}���Y�f�;w.:u�$�,��[�b��x��7����r�
��[���@���{��Lu�I�*//���k����B��Q�G�Vc��

�Fc	999a���:t�xS��j5�=�?�����p��M1n��
�����c�koff&�l������%D>��c����7o�����}���s�r9z���^x��{��>����{�L�.]�`��q����x�EBCC�m�6��	*M�c��6�����]�t����nr�B�uc��}8w���k��J�B���1y�d888�7sJKKq��A�8q��v�����O����x��iw��RG�������X�p!BBB������r�J�7�%++K�,��S�X�s�F���o���;4
BCC�x��zy����������F�;��x�"~��Gh�Z�&bj���wn�rrrp��,\������O��c���������_'������.T��FS����W[���{�~��
� �����]��z�j����7Ka�����j�[�n������8Z������m�*�������?��!�$q��]����
?��r�
 ))I��r�n�n���z�v����$@^^�,Y����Wx����y�f��p��9����8|�p�I������[�r�J����7��6��1���������?fI@7�������*����5k�`��������t	���0|������o6�V������j�*l���*�������-R���OT��~��
|��Gf_B�[M�'��{��a���8v�X��~@w?q���������ofJKK���_�����������������{����hD!�N��d���1z3XTT��7B�P�O�>���^U�|�M�r����|�r������-��$JMh��	<==�T*!��QRR���,����`hII	6n�gg�:W�*��;�~		��)S[-s��	����*���QU�wh��������
@.����iii\�����Z�
k���������n�6�I�&x��!]Q��������\��.GGG�=����p��\�p���X�j�x��u�:��k��1�������'O� ..�"���b���x����������m����S�Nh��-d2n���%������ys�7����?�������-��ys��j��� 33�.(�q�F4m����C���Z�Fll,�v�*�C���111t���\4j�H��a5�&���q#���Q�pssCAAn���%��;__�
���Z-v����'O�7�����5c����L���K�1��j]=��X��{��U|���\��c��x���*�	-t��}|��������pss���
q��}������rJ����P�T���(//Gnn.�����fPP������/
~�<�mi�����D{�OYY��[�%7������G���fX�Z�/��k���(	F�5��}BmIOO�_|���<n}�&M���;;;������\;�V���w�A��`������9t�+����eK�k���������7�����:t����������%L��BH
�����u�����L���R<~����Gtt4���X@�V�����k�����1c����P]��]�V�c��a���F���R��X�j�$������h�c��S��W#77���������/������J��T������o�WW���������������@@1��r���������PL�<�h	��<y�[�la��GmT�����3f,�����7���8p�f����h���J�~����fo��&6m����<L�8���Wmqqq���s�w�^(�J��=����y�f�����^��zrssYr������
�
&������������8q"�y�n?@�	b��
��I����$���7�d��}�0h� I 7%%d���������{������X������>��3���V����rdd�����������n��	�0�:�$C4
��ooo_aI�{������wm���h��1[WZZ�]�v���Sl����+L�l��g���������^@``��3���BPP��9���"L�<��^��x\��y�MNN�7�|�%A|||��M��������s��e2�a������k�JKKq��u9r������E�����h���x5���q��i���������#,Nf���


����w�[o�����������b����l>|/������PS�	�A��`���\�E�x���$���s����������c���h��9����������c��y�{���r���'N�`�~��WJ�X%B!u�p�;[[[������
=z4>��s�������(4���!���u"(V�rrr��? 66V��"?����M�R���>����Q�F�?>233����
+MMM����ho�B����k���xG�p(��,���YYY�}�6|||���HHH�������K��Am�����i��%/^����'�K�.���\i��!�Q��m��X�z�xu�3p�@�=kK�>}��Q#|��7�7o��z������#88�.�{���=Z��na�Y�fL28<`s�h4���H��{��eAR�B��J0r��f�����R			HNNF����}����\I���/������O�e�����LN�S�6����(����������J0u�T.	���3f�@LLr��m��+<<\�
<3g�4�������M���#q���o�^���j��
Y��[XX�������l]�V��p�B�� %%%���o�$���#��}��^?
+  �������x�5h�&L@AA�=
@���|�2F�!��4�D�L&�0h��h��px����P({��;,X��������`L�:U�0&�X���{O___,Z�H��tmS�����[7�[��%���C�����f��	7779r�}��4i���������_FLL{������{���E�����B��Z�h!)�a����]YY�?����j�#((�{����X�`A����B&��_�~�:a���UAA.]�$^m�|�����y3�.]�T��FFm������+//���J�j��%|||�����hDO<����O�f?{yya������'re���������C���Y.���g����_O���{�r~~>n����3�P"���&��#���������2���U[ZZ������#"4l�0��;�hD����?��x��j���s���u�d��E��T*{Un��}�����O�&A�,�e]��)�da�?����K>>>�*�x�"rss����S
Y�qv�)((��;w{B�%33�����l0I)&�����os����T�s��;k��5����d�����{��(By���M����;t�v���z�)
L�:�`/9S���a��=������s�����N\3������	�]�w�K�.����[����c=\]\\0a��^O���b��w������U&7�
j����2��(��Se���<$&&�������XII	������"--���z��RVC��\�+]/11���]��<n�Hbb"7�x���F����qe����[�G_.I�PQ(##C���Z��:mRNN����UZ�H��]�0D<Q��w���S\��-Z`���FK����8�����7n�@DD[�������+�S���B������Y�fYe�������2�9�*a����Pi"X���>$B������C���#55����5 %%���x����m1GVV��������
 99������`�<����Arr2���a�g���"��w			������U�Z�����;���8q����1��B��z���!�1m,%!��!���<L�7����f����M�b��}��L�{�n���g��3f�`���x�����s�O#}I�6mv��	�F���"\�t��^�B�d�L�#F`��iHIIae�)//�-b����7/^,�K������;�v������c�o����������w@.��]�vD�~�$����()j��Q*��J��OcU'O�48s�v���Jo���������-Z@��x���������������y��:99'N�@tt4���T*����&M28y�w�}�JE
�3��������w����C�����z���L��m
��������]��M)���];\�|���L��W�^e��T*�j��-"����MV�I��]�����(��5�h�^��rrr���c����X�M
g���}��[���i�-?~�����]G�s$�d�8���h$���g�\B����q�{�-++��m��u/���E�2����D���/���#�������<3�������tI��={������2nn�:L�	�l�vvv���*3��7�n�:�<y�d���._����������$(+�M�6��5k�H�i�V���p�;wqqq\"_&��M�6���?�
f��nff&��;���/s�3���Y�f���7F�Y��CQQ>����������]��o������|W�Z-���q��i������aC����g�����G�����'N�@XX�d�����k�a���g�����w��}n>���g�[�nHNN�������6�f���}���Au�j��(f�B����o�������}.IIIHKK3:��"����X�U!��"�i!���w��Q#���+��B�JOO�.�NNN�2�m��V-[�4X��i"��X�P������e=HCCCM2�������$amNNN���a��������Q�����\�^��v��A���olY���w����;wp��)|����]��Q�Q�+((�� ���n]���QU�V��vJ���M�
�.h������,\�~YYY��u��YYY8z�(����d�DGGc��{K��j�9s111���O����m���1�>��`�Z������������o���
��mmmM��-��222��	_�M�6FJB��C
QXX(	�J����"..N2���,�^rrr�!�j���������t�C7j���"##������_��

�&�54�����\��V�ZIp5�����������\����#G��a:q��Q�Fq��A��t=�-9^��]C~~>�y-�#���Cn��)�9�L�&M��Qa���������
++^i"���3���BDD����Phh(���k�N������_��Q�j�HLLDbb"N�>�E�Y<���_q��Q��Z@���������

�;��c4������?��h����l#88����F����?���`z��	�����b��y�]�:�}��w\�(��h���Xx{{��w��|������QQQX�~��������|�`�cP]<x�%�|}}�.�=z���#G�rBB����V��F~)��>�Q�&��Z&�q��];n���[�nX�v�E7�b�O���,�'O~�������{7�������y�L
^�e�a�P*����[w��M�7��<�������Mz���C�)��?����Y3V�����$���:t���m�r�[
M�[�����6�WXX�o�����������SE{=}��6�6l��[�lAyy9�������-ZH�1x��V�X�� 2���������������3�L&C�F���Q#�'�\.g�����[�2����R�&��K]\\L
:�{��� 999�<��1���P����z�
��R\zj��+�%������V�������d@���M��I�P`����=�����v�Z�� ++�v�b�]\\�'�*���&��q�{�=u��Y&����^�������+�T*�����j��K�p��q�<s�L���������U�	��-�v�r������X��ddd���3g����
�H8@�������e��$���-|||��o_���r����t,[�L2��EEE�$�\.�����:��������h��������d2xyy�����e2��\���%	WWW��������N{���������$�R����7|||$��d�IG-C>|�� ������F�V� ����cG�l����	�8�I8��U2��8a!~]S���s�[���-J�^���B��{G����Jk5��8�D��4k���,}]a��n�.\`����h��-6n���7o����������3:u�����K&��I)))���`Cf�j5RSS�zI9;;��w�5:��Xaaa�����C����j�P(PRR�V�?���=����������#���X�*$$�'O6����#��q�-�9�������>�^x�%@4
��?�����{�������(���m����QXX[[[h�Z���#))	���,���m[����&?���s�io�,5n�86�v�Z�t�I��#Gb��)l�@QQ��L IDAT�?����~_ooo��;^^^������^����������������x����z1�������W�����'V�Z%���s#X�"	�|�C=`
�g��g�-&G�=���c�G��7��+�������*�>^�z��:j��!��&s55Rm��p~s��=z���i��{�n������}�6���?����?���c���	���Z]=������s����,����������R����+�t��a���%%%q%����MJVVUnn.���(�J���@���������WY�������*�"���=y����rtt��&J[�V��j�7G��}q��9���.]2:*�����:�����������HV�����{���o�����l�{���;w.�����{��aI���|���X�lY���*�������sppp��1cwww�d2���#>>;w�d�p�Z�HF#��$�suu��E��krrr2������<��V��:�(
����D�^�����l?~g��5x%%%a��
�;����W^y}����OZZv�����������b��%lC:������_g�MVV�T��k��&.9gj�YL<����7�0A#F����e�w��Reff"**
G��z?�;��4��~�L�4	�&M��[�s�W�W&�a�����keee���Dff&BBB�������K�5!&&�h@P&�a���x����zo���\�TC:u��O?�T��Z�' ���]0�s���gMhh�IA��0r�Hl���.��.]�����p�{�R*�\mVa/:gggI�;;;�5
={�4yb���6�f<mm��c����R��S�b���f����R�(K(�J��$H����JPJ��&MBaa!��M�6���O$�����1{�ln$���W�D��- �&���>��r�q����5�G�{
�������'~a"D�Tb��18r����������I_X�{��h��-[���Lu�IzZ���o��������	����������V����?��@�8�lj'������������X�f
����'��>������Oc����:u�$H/�O���u�����~�A������x�
IozSEFF�k`���+���S�*a�������&��^�N�����F�K����JFp����F�����g___n�JTT7
���,�|'�J%^{�5����dMbb""##�t�;;;��7������~���;v�'�|�����t�3g���G�<��s\��X�h233�����,�����K���1�G���O�V�
6�������/��vwww,\�?��#K���s111��*))���?�}�]��quu5�y�2U=5A���OS��kw��LJJ
7/�����&UC�BH���h�������*�
�������j����,^N��0tu\+�+V`��ef��W'}����$�?��'a�*����Z� ��gO�p����?��S@�����Mr}�����V���4h���SYY���p���5�Q��>�QEEE��cbcc��s�
,<-�CU�<<<���w��%B��/I�����[�ne��x�����C���-�G���t����O�		c�AK}rU��[�z���4���6l�n���QU����w����"������977���&�*7��m��;w��%___�'�����$b�N�:U�v����r��BZ�V�X�q��U*�X�������J)��������������m~F�4Xh�����^�mll$�hs��}+V����#1z�h�m�1�Q;���t��B��-�Qp���2��{�f#�������+	�FFFJ�������/K��?�J���'O�d?��r��3G��6m����q����%�i��FS���a���������w�������p�1C	
!s����\"�������d2f���+W��{����
!
�s������&s�AM',L��"�=��l�����X�@�>}���#��D!��)--ENN��W��L&����1c����1�����Ob�w$|0�S(>|8�����qc���#,,���c��������',���3�����A���B�� //)))���Eqq1�����w�!44���N��P�BQi ����v��m61" }�
����Y�'$$��@Am������Y`/**
j�Z��������L&�L���MV/8??AAA5:T�������QC����'
lllPTT�G�!11���(//��+W���{S�L��D]<W�KU�*���W�����
<==Y���������,`NNNx���{T��v|U�
���pD��G|�>}X"���Kx��W�>qqq,��T*���[[[����@aRRR��'��&�YZ�	���/_���vuuE�����EEE!99,��_�^��Jg��h��G�W33f�08�P]=����j%��]o�1c��c��P�T�������������C�����H�D�����'$eb�T*6o�,^�quu��Q��P(��A����������q��������={�����fM������M�6�����m�T��}Y���j����s�K�d2h�Z��������8q�`O]�]��P(���


������*
r;88����}����Oh4�u��:t��-gddp��x����Oc���gC�����8111HII1y���-���0�lT��
����F�	'�6�G���l��1�	����I!�3�p�ze.\���`����0�E�c�n�B� ooo��?��a�#F����&��V(���O%��:v���;b���l]pp0�}�Y�=4�K�v�0v�X�j�^;w�Dpp0]��u����>��k��5�-[&^]��"�7F�N�[u�:ub=�"""��������&�1�Mv]RR���V__O8�k����1c�p\��mCzz:�}�YI��FmT�z�����{��$--
7nD||<�Z-<�R�	&�w���s�.�Qeee��a�x5coo��^{M���$���kRDDW�Il�������x�AZ�����^�/��������q�T}�M�|�g�x?a�������O����C�T���YYYHJJbA7qY,�w������OJJB`` ����h�����������V���k���� }�����sagg���x����e����,|���������`����'���Au����Z
%����;�.]��syxx   �7o�F8p�{�f�@q/���bn�����`��q��t���� ���/(++Czz:V�\���WW������=���*K�*���41��M�����E�.]�!���,hncc����c��ts�M�0�K�
�b���s	.���g��"����!���HJJ��_X*--
7o�Drr2���PRRggg���^�M�6E���Y����t,Y�����Ie�����cii)V�X��S�b��!����q#n<==�(^/�u�����B��X��{@qrV<z�T����[�rrr��/��e�B!y��j(B�S�����g����EEE�h4��eF}��]�o���51��#	0��������������F5M�Ra���P���=^�z����
�����7d�>}$=K]�}�Q�V�����I
�wwwt���M�w��.�V��	�G��~�k��
f������C��B������8{�,��c�J�'�BmT��Om���;/^�?�������J�S�eu��*//g=!
i��Q�y�4t�k���w+<�:t09r��i�W���/ ��'��akk��aS���>X+2����������{��^����
4@��������d�a�p���e��\"�*��&�����a``�$�]�'Nps�8���?����}{�Z�
[�la�<y����������������h4())�4�&���}���%������j-��.��9�h���3g������Wjj*����F��G,�Ke#���������W���
}�m�6�Q����*��0s�b�����J��(
IB�}�������Fv�����C���1z�h�<y�=BVV�\������%��aq2H<W���O?��3�re%�L����={����[�Mj�����������|��!��Y�-Z`���������e��1HJJb�#�Z�m�����C9r$�n0������###���9���PZZ*I���Z��*,=���P��0��B�D�}����yh�5k&��T�ec|!�yyy�c�����z�������m�����y��n|	O|STY�J<�Z8���O�+m�4�p��?\�������'7�K�e��������������???�Mh���x��������b�={.��
$u������S��(�R7I�^II	���iP�(R7dff��_e�
�s���a���`�u@��a���4c��aD8�L&��6�i�N>d����b�	���:azE,m�BCC����CJKK���]]]1{�lIRO�P`��y�kgggs%����������������?�P�K���q�&�uW�R��MO�PH���k��3�Vd��i��T�����CCC+��KIIa��m���E-i���a.��eee������^�G��%���z�sY�RIFF��Wq�j��g~UK>���K�.�$AT*\]]%�)c����t�RI��{��a��
x����&)d2����g�}�+������{���w���C�$�X�5�R*�J�����9,=5E<r����!��Vz�����/��!�K�2z����7�B��A�!$$�
����Cpp0�*��T���Ye=v�=�=z�-�-[�d�&]��i",/���n�&6�����];�s���������:��
����!v���L8�<�o����`�P�^���sg?~�O�f��V�EHH�_���J��Z�Q5�>�Q�z��FY���
,^���!�������W�����i�K��^0�����3*>~�X��0�~�`����g�p?�\��l�{�.������u��*�
j�HIIa#(�,�'B������WWW����I�v�]��� �Xll,�9rd�s��������b��CCC��/��m����o|||��=_����������WxoH������{�?���[�M666���FLL]�=--
��7��?���AQK����~�_��I�K�.a������`=�[�h��Q
2���Gqq1n�����t4k��K������QX5m���8t�[V�T�0a�����+�j�HJJ���~��3F�Ra��E�q������\�����u�0t�P��3G���d2����0`8��/�Q�O�<���{q��|��,)/1��G��c#�j�%�����j��[^���O���_W�����Ht�h���&��e��B�<�L�9s�`����g��]� y@%U#��A7�����:�C@�
$����V�����E�n��z�888���#�=x�%�P`c��k�L��L|���t���M������X��
1h� ������_|&L����q��	v>���`���X�fM���F����F��L
��OC%����o�W�j��G�*�e���X���������0�I�&l��Z�6)�&.��0���s�)L�*|=777�L�����lmm��G6z���K\�e�(�-Z@&�Mb��cU5bn�t��EV��o��FK�".�UY�gggt���%�222�V�Y0�}��8s��?""��Z�j��Z�J����
R�#�����k���77E^^n��ir���&��rrr�&B�Z-K��rnR�������-%%%�UM��r��{���X��j���G�f?;88�_�~�V������~��q��F.�G���N0F|�&~S%$$����l��������L&����L�.]��K��u���+��;w����/
~��7o���zS�L��}����v�Z,Y�2�Lr^zzzJF=?��9���P<���k�P^^n�h��W�r��:
�m���6t��������O�Bj�����V����?� � � N_C�2�}Ly8�
O�<������2a}^@�kn��=F���z���3�	�rrrp��5n4��A��:�T*�L��5k�p��

�������Q�(q��4��m�=�?���;���W���`��Szs
�...h��1[A���+
����s�aPE��r�D��@��

e�5qY,�:a�N�X���m��G�� hE��n��>C��Ja�����K���s����&��q�&�\��{24g�������+.)t��)n�6������y�&Khu��E�����;�5�<�{�.�#�Z�o���}������l�!�|�'F.\����`����������-�����C��1���'���P(�p�BI��|||�|�r���K�����WZ��i���?>>��Cn�`\\�\��5	����)���8;;sI���nd�)rrr����Je���bbb��L���%��J�B��?�<��s��EI��T���\_�����,�a����!++�{�vtt49�R����������IV�������@�L��!6�����}�3����n�FU���F���u�=R��(�O&^��l����.)�Sq�������b��������Zm������������q��;wf���,�����~�F"D����M���d%a�������������i�wrr�����y�$0_j��Z��<MOOl1L|m��1b��|�r��'�b��$�����X���&����$�����7���]�r��pqqA������'��C�������b��Z��������^�����vJ_r��8�U3��u����2���	&`���l�����W���3g�����NNN\R���[&u�I��O���$qU��"S8p�KZ�����4O�<��-[�u3g�4X��X��"�<54h���gc���l���[��W_����o�o��!�Y)$T����o����.��	�'L�`R-��w�b��]l9$$�����e����G��3�;M�l��f���y�����)�k�6����6J������{%N�?z���D��@t����������\����c��i�=*��S'�\�����K/m�###�����������p�SHHz��%��'�N+
��N�N���r����+O���2�e��lbukL�nN�d��z��W�\���!TTT��%*�3aaa\��m�����&��q��n������t��RRR*�{E�|_{�6m����s��M�6�i������Y�bcc��
���Pqq1�������w�Q���;��RZ����FK���s�(��m+��X�o��,X����'G=z4�)1#=��������������V8�Aff&7��}��F����!��R��w��}V���
����0l$H~~>��?_�����>��cPS�����~��u������$	Cn�����2���
����s'7�������=�i��B�0???�yVV~��7��*����^;�����h4�Z���Am�|�2�=��3��.�@��r�7�����5j�=!
i�������7F���I��Q��>�QZ�{��A\\[�T*������F�K�\�|�[�;��(**b�R�K~~>�o���{����n���H����I��������-{xxH���u�F.���p�����q�A�q�����������xT�R���/=a@������`��,i��Z�I��8s���c�I),���[c������g�b����R\���qC��Jj��Z[`` ����`+/%%�%�������k����x�����+$IC222L.�d���4l���[7p�@�A���hv���G�������#G��Q:z�(7���k���K��4Z>�{����B��M
~�z��}NNN����Z-~��g�G}U��vb�V�/C���������{�y^XX����V�xT���7v�Xn���]��2��X��"d�}BU�AM�����)S�u��m����s���]���2��h�[�nq��J��f��A��\
� IDAT��,!��Q3f���k�����S���_?I)���TDDD�W��aCIi���|�^z��)����&O��z�?z�_|��|�Mn�����~�z�������{q��j���2�eee���FRR���$��+�\�>[�bU�' ����B�@@@+3�����W�Z�S�&�1��vww��W�����_�C��4i�j��IqO��FmT�z�����\� jqq1���/����������S�N�����b��C%~h=r�������]����Q	��o�����RDj�666�G���m���nii�I���?~<W����CP*�;v,k�����M�6q�u'M�$	|*�J6��g������?��uPVV���p���O��t�
0a��;?Q����������7n�����X�tTIRR�d
=k�I����h������"���h��
+���h�������_G@@;>�����g��\3f��7u�T��y�K<�������5j�������G�?~�+�c��v\�M�Ra����sQtt4����b���\�/!!�|�
;v����...�3g���{��)((��5k��kW8~~~\{���C������Sf��RRR���\888@.�C��"??���Ctt4��������+^x��+��1j����;�

�j�*���[l��Z����G�d���g��4s988�����]Q�$�L�#Fp�;���2dN�>��9{���J����C������}�v��A��m��gO�^����a���]��[�$s�h4���C2���$��p��5�7�F��������	�	���0l������s�=���s�y��]gggL�4	�w��k��/_�W^y�
����������8v�>��I��,�O��1�I��Gxx8+S��h�z�j�5
#F�@��M�Fk%$$���8�<7J�I�&�>}:[*..��M���;u��?���+�i���1���D!u���3^|�E���Ot���7c����@TT�l
ww�
Giii������+�u�V�
J]����~�������������B�&M�V�����=�888`��9l���9sg�����\Q�b��?_�Z�����~������7������'7�ZHHH�2����;w�d��Q�F
��{������/������k�V���nA�LV��\u�6�z=Mm������C�L��n�0a�I����K��(�o��=���`��
����1w�\������@4m����MLL�;���T*<z����x������]�rE����4����O�����?��Z��w�����������I��Hzh�M�4	��_g%�j5���+4n��������fg��%�5-L��B2��z�b��+:�\]]aoo�F;$%%�;��&Y#��O�_|��Knn.��]���A�V��=j�(�2�B���_���/����?����LGGGh�Zp�(!S��u��Z���?���h��9�<����j�
x���~��o��h�
��JKK�q�F��]�v�������J��Z����2�larr2�|�M�?3������?6�����c#������sg��{��7�|�r�~�����>�3�<�\���L.Acgg���~��{es����%BZ�lYa�6:t(����>��!
4�?��O�\����;v����������q��U�3������_������#""���(//���+��G�l�vvvx��!.]��������3Stt4^~�e�/,,��+WPRR�����������#\\\�����k��\y���h��2h���h��5<==������s{�F�$�u��	x��������7o������}{4j���{�.�^m��+W���yc�}BU�AM�������|�r6R���'N���'`gg�R���<��|��'F����w����%$+B��~'��:N<qfrr�d(+���y�$A����������������x�b������;;;L�:}��E��kZ^^�T(f�����+���������F�P`��!t=�M�m�-gff"<<�$��3j|D@mTu{��(�Vk40�������^o���Nm�?��I�M�Vs��3�\���z����j5�����7o���<����j5�n�*^]es���
�j5RRR$I���@��=�['�T*��GIF�=~������ 2�S�L�������F�T�����,����W�M*++c�+�\n4�b
����/HNN���h�3f�Ws������c��a;!h�Z���!??�`�Y�fX�`�Y���t\�M�T�_��W����			�z��$	��m[�������>�����h4x����$�\.������g��7U��3�L&C����z�j�e���c��}
�_�j��-Z��*�j����������J��;��OOO��ZY[?j�(�V)�J���?���������skzz:���p��a���pA�&M�`��%~�h��%^{�5��j��t�~��7������CAAd2^y��4QAA���K�|��e�3)--Ell,BBBp��un��������333%�srr2BCC���J�,0D�7o&N���+,,DLL��?���$%%qm������PU�{�`�cPS���~~~�M�h4���5x����3�.]j�]KHH���'��I
�!����L&��9s��'����~�
={�����hob.�\������8t�WE�O�>}0m��Z
0
�d24l����h��:w���}���
��BBBPZZ����������At���%JKKnt���6|�p=z�
2��Nh��e8}�4"""Y��d��������e�)���^Okecc�J����m�����G@@@�������F���c��U���_q��E������m�b�����i����k���K���TXo�Rr�����^�z����k����c��16lX�=e�����_���c8w����O�N�������B\���DH�v���Gq�@�E�lb��w�B�5m�ZK��7n���[�n�9u�5p�@�n�G�ATT�����@.�������7��R���9s0b�?~������+:u��>}��k��&CC��q�6�Z�
G�APP���p��
1v�XL�0����"~~~�������0$%%.��{�������W��ngg{{{xzz�C�����d�!������cG�������{)��F��`���F�Uegg���������5j��������C|���8t�������&M�`���?~��:�
>�7��?�,i�mmm����)S��2���<��}z�J���s����999a���x��g�������+W�������f�N�
z���)S�}^��d�6mz�������F�G�.]0d�I)0k2�>�Z��&9;;c���

����nt~�\�N�:a��a��ts�k�H�����i��EB!������{����L&C���������$�*._���m��]b,++���(,,�L&C�F���eK:7�f��"�������Cvv6Z�hQ��O�{�������j�h��!������a�@Uu���FZZ�����aC����������Tdee���NNNpww7:������'''��J}WVV��kEEEh����W�\+//Grr2=z���<�������u�1���L��"11������G�
��iSt����� ����a�t�k;::���
�����EY������o��l**����)�f��G[�����������=e���G��)�myJMs_SAp_qGeA��ff~�����gv���:�����a����:����ZJw���*dff���z�m��A```��{&''Z���;v���uJ!'g2���zYY\]]}]���dBZZ������`��RVV���Y�.�Sf��N����3��k����Z��F�������Cyy9�j5|||Zk�[N��!==]8���������8�Z}�����AK���GVV�pR����������]���^dNw�@�s �q�z""����X�������U�Z�K?+�=(..n��s��m��hu�k����"�������|yw��5��.��K?+�=��t8z����Q�Fc�M_�k����"����"yw������Z�{�g%����������Q�J�����5���������!DDDDDDDDDDDdw�5BZ�V="""""""""""�Fb �������������!DDDDDDDDDDDd�!"""""""""""��@�-B������������n1BDDDDDDDDDDDv��"""""""""""�[���b ����������������������&UUU0��B�s�>L&��vpp�B�� """""����\������>��S�>}��cG|����dKjj*.\(�����>}��f���d��3gp����yz����Ddd$��o/��=���k�y�&z��%jV%%%�y�����BCC%���2$''#==Z����
t���:u������J?~W�\AAA�j5|||�.]��������QXX���(8;;�����
���

����|�Y������������@EEt:�J%\\\������`����o� &�	�V���Q�|���������������5���Dvv6������##//z�z����00P�Tpww������(�y�rrr���*�
AAA�����p��)���������pqqA�v���S'�����,a������k'�aI��#''Gh+�J�f5!DDDDD��$''c�������	���0s�L���*77���>4
���k�p�:|�0bcc�����o���_�m��A���f���S��+��k�.�Y�eee�!�]����x��!�c��[�u����m�E����E6��~�����/��F�!nV��/Gjj���*///���`��1�z��<y�7o�J��O<!�� 66C�������5������_ ::����|X��� �lQ��G���1|�p��j�����k���<==�����f�������X�9sF>$��];L�>�j@���������+��}�+V�\���x�=q�D<����'5k�Q��s�N|��g6� @u���w��u��)//����/������z��~�)��_o3T��Y�x1��Y#�`2���7�`���V� f��_�G}����������w_���������������]�����V����[��o !!A>\g{�����&�I6Z7�'N���J:h���
HKK��4Lee%N�>�+V���^���S����x��wj
��A���Lyw�$%%I� ���x���nO ""j�!""""�V��������%};vDXX���������$!�JQQ���I�1{f2����_���k�!��a������Pt������j�8u������
6 ((��Jj��u��b������GYY���p��
��������];t��E���������"���M�h��?�YN�4�B��R��1�PQQ����C�Vc��A�a�
���������g��G��������p��i���[6���hDRR���EEE����������Z�������o����)S�4:�[~~>�.]���
����QQQ���Dii)������.\����>anC�����~�j�/��k�Q��'
��6m�,�M�2&L��^����O��/^Djj*�v�*�g�~��waQ�N���A��=��_�5._��:��x�b����\������/Z|/����~�
��m�V�^]c $33����x��7��m[����V�X��{������/���>��)�����������x���:�����e�j6�	�_|�����P(`0PXX���,?~@ee%��@�O?����{�+=X||��gNHH�w �d2����B���#u
�������Dh���#**J4�f/��2���'''�F���";;g�����{QPP ���e�z=�{���w��������A�0k�,��$���HLL���g\sE,66V������Y����!DDDDD�j�:uJ�:  ����V

�SO=����N�;s�L�����-[��-��������ES�BQ�"���������6m�|`���R���O?���$����7p������fk���kj�o���$T��>}:�^�*���t������cG�����?�X�]o:�K�,Aqq�|������vpp��������o_<��������`Bqq1�;�a��	���d2!..N�w��QL�>NNN�~[���%��N�8����v�qsZ,����:B<<<���T*������p���c��	��a�$��k�.t��111B_}TVV����B����g��z*��������q��C�v��!>|Xhw���I����H��'6��Z�na�w���I��������%<<\�.,,�����������������c�d��A3�B���HI_nn��
TH�'hF�������T*&N�(�;~���}�2�L���o���CK
		����%}�O���m9y��$�P/����+W$�[�n�����>k�B��Z�����1}�tI�O?�$���Gnn�$�m5���Z-V�X!����0{����DDD
�@�]B������HOO���7��
�+�V���4\�x��_�|�i;^�udee�na��hDNN�pz�^>����������/";;��;rZ�����|�r��M&


����K�.!??������/#33�fA����u�������Z&�J%i���K�b��j����(..N����`0���Iaa!�.]*�������,�S�X��9rD�:t��-��W/���	�.�F�^��g��[�^�zI�7o���m1I I�U����B�b�=���������5U ���D�~��vII	���/����_W������?HR�M�6�IRm���������a�v����Y�x1����q�F������&L�q����`���{��_YZvrrBtt4F�����������o",,L2WL��b���8x� n��%�;88�{��4�1�LHLL���{q��EIPA�T"44���Q���hD��---
��-<���8p L&v���]�vY��7nF�Q��)))�����3g$8�����#�Th�`0`�������<6�R�n����'���R>���
����
�AAA�������@���k
���3g������P�<������N_dv��5���)))�����i4DFFb��!����E�����J,]�T�yzz�}��8w��l��G����#i
d���:t�=h�J�B�N�����vq��TYY��_]�-�4iF�)����c����
�A����C���<���bKAA�p"H�P`��iBJ�s��!??��������k���c�>}z��'N��wA�����������4i��{������R]�S�Y;e�����$'����������@DD��!"""jEJKK%)<�/_.��-��j���D<���)]�


�t��w�VTT`����������js�}aa!�z�-���
RRR����^�z��W_���m~~>>��s�����T�.HOOGzz:�n���s�Z�G������[��K��X`:''?��#.\����g��%�����7���%n�����#22s���qw�V���o�-)�kf4q��Y,\�3f�����������?���B��dBVV����i�&|��;G��_�@u��%K���w���������xvvvF������PYY��+W">>��SA:�'N���'��];��;����~�A(:�V���k�a��]�Y���$	���j��0q:�N�:��`-&�RZZ�������E��IL�k����L����^�����<y�]"��F IDAT��5El���N<v��C��o�����b!���#��ne��@HQQ.\��n����X��2KOOo�@HXX�$���������A[�R����'N���[����.��x7n��/��"�=<<��/�f5-��""""j��A777DDD�s���������������j�*I�YYY-Z$	���� ::C����>44�-�:f��j� H@@"""`�������Z���v�,X 	��T*����G�		���j�����j���%,Y�D�����K�.���������D���O�'����w�}�"����n���k�������)�J����Y�����k�����3�j�0�d2!66/^�Z���b|���� �Z�FXX���%iV,� 0z�h�)���|���;8x����z�j\�~]h?��c���TZZ�?�qqq� ������aQ,\������7o�'g��Y�SF����T��x�=,^Z�Vr�����5���@��[c��%��1$$/����5�n ����}`2�/�cbb�P(-��5=VQQ��������<��YYY���B|��6%4��9�����Z-��SVV�/���f���0�LX�|�$���3,�{DDDM��-~DDDDt������'���!C$�����6o����H������$Gy���1k�,����|�r����k�PRRb��D�G�x���$�EEEB�/sM���,,_��j����R,Y�D��T*������'y�%%%��y3�l������*|���X�d�������pww��)S#<��6l�����i�
&��JJJ�t�R�BX�=0u�T�]�W�\����q��Q��5����N����;�~�i<X8�SVV���YX�3��������S|�V��������{��������F�IIIX�j���+�spp�������_H-UVV����{��EXX�m�&������1c�vK3�L�����K�.	}����3�<���(I����$&&b����5kV��[qps��	2d�h��m������>(i��"�����_�JKK%���V����[h���[�v�RUU�e��	'K<<<��o�����yi�����y�f��R�j��T���?�J��}��0`������Djjj����A����k��N�5m�4�k}rr�p����#F��]�			����8q"RRR�����g1�|<������%�j���B�C���������5����������1r�HI���1g�<��SB��d��5kD����;b�����+�X�R����O<!�
���D3,������!������'��������8q����&���R���k�a�������
S�L��3�>sp�|���>|��ytpp���?.����c5M�/��"IU3t�P����A�z1������e�j]x����'�|��C�J�����`��Y�����w���f���X��n��i�6J������E�����fJyyya��Ecg������9s�X,@��}��I�������?�Z���'N��_~���{K���]�����JX�������~������CDTT�hF5�.v���������i	^^^�
�%�b�
�D���^{��:��i-n���m��a�������c���������S<�����E���'''�3�����@��8-V�~�$��5��ly�6q������}�QI_AA���;��?���<
������Wm���� ""j��b�TKr&L��d�t��d����3���c��X����� �-���������0��5K�'Z���K5c��E�>}nO�b�����8e�5S�L��<�w�gddH�yyy��7����1c��������)Sj�(
�?^����c���	#9�Z]��m���d��LL��`��a��lK3���q��V��x��W%)�����(--����/a�=((�����s{/[�b�$���S�>?��;�e��&�Vc}���;w
'���C��x��t:�M���^z	o��������s������*�C��W/I��&HNN���V�T�����>|��pz�&�����`8;;K�o��XUUU��?p�@I=���������$�^��������s�='{�rrr�|�r��;�w���{���
�~�����g,Qsa �����.�P(,R��;wN��������DM�j5������b�u�����t��$�������r�BQ�G111��B
%kj
������"�b���iC���Z���<����7%���S�N�����k,n��
��7��
�����t�������?K~?-���K�S:111�����/��R�Owww��?�f��^�o�>���
�^�z�<�/���Z���:s�~��W�=v�X���Z���V���l���Y���uo���E�����8����h$'����&���2?~\4jI�����j��AB���G�����B�@'''��������mS���>����=z4/^�!C�X��*((@ll,,X I�Y�M�6�����n�Y�F�"""j���""""�V�[�n��x�A�[��$��|1�� yL���r����i�eee�5��Z�m������8u`�G��\�TZ�kjN���P(B0�.�MSZ�n��(���O?-9m3x�`�]�V&>|�:u*����y�;vL�����
���
z��	�N�u��a����s�c�7I�����g���Bx]7�����S�N�~���7�jA��p��!I*�����G�����j��/�m�Z���{��y���]�f�y�9u���knn.�������S��f�}:w��9s��]�v�!��E����kL���74�PH>!!A�������9��O899������HKK����X��yPP��y���f�i���<�dC���a���x����u�V���I����x����`�����ni)//OR�+88YYY��o���_|Q'""jj�����i#Y��h����~�����$�AC��h�O��kJ�����7���!�=\������16jQ�!����
N����'���7{��G$�1�F��s����>����q��I���������[QQ���X�������S�NE��}�l�2a�����S'�;V�mC����v��h��DL}���c��B{�������h^6������������X�b��I����/�!%��w��D��M��^-��VTT�_��JJJT_�^y������F��|���RTTT@���?�����dddX�NlINN���� 4S�����RZ�:u
Z���3�\�"������_?��{��� �a#����J!MI~b��}�������{'N���k/|.������?����m�������0}�t������911#G�l�i��������UDDDDD���/v��Y��]O�������M�a.PkVZZ*|��b�r
)&lV�)�"
���s����+�{�=I��d2!99�1.\(I3#�g�IQ��S�
A�n�������,��[��Q���~U*U�SSS%���p�m��O�����9������������%��1a��K������uI^���1�L�������B��C=���/[�vN�>-I-T��cu
5���`t��
QQQ8p��$��`��?�X�4{�w��vssC���E��
0@��h4b�������\�"|�P($)$�Asz���l!��9-����DSL������)������/����zK�������}�D3k����3f���S�L�M&V�X��""�w�D�/��DXX������<x�EN}�^��~�I��\y��'0�F�$�Fpp�E���j���1�w"�S���~���|n��f��������o�>l��Qr����X�`f��i�;|������+�~{P&$$�F�����T�4;q�����uU��W��m�k�d2a��������h�"�����uK��9s��f�M���m>������SRR��+W
m�B�^x���\��_^��&�y*���i���y^���/$%%	m��$	��f��m��m���?�s
��4l�0$$$������qqq9r�l�TAAN�<)�h�J��O�>P����8!!������|}}%z��
���!77���HII��i�i ���[���������P�Ar������TU���gO��9_~���w��Q�5J4��B���/�(�.������]�v��������I���#���@����}�Y,\�UUU0�L����1z�hDGG�����]��M�$���j�����57��O�T
H@�"sm�(-M��9������]u�R�0r�H6���k��hUUU�������-��6���.]����=h� !T��iL ��?������PUUU��kM�Fc�(����S?����9�k�WWW��P�S�.��;??�z�N�Z�y��
�3f��[o�%�+������o_����H:P�2l��M�R����u����HOO����V(�������NC=zTRWJ^7($$D��0--�I!III������6�T5�����Wx��'R�3f"##��B����?�w�yG�=�]���w���3QC��������Z���\���6m��F�w$���K����PYY	�� �,������L^|Z�����[.�������1�u!�nS�T:t(�o��VHc2��j�*!RQQ!��"�Y#/$���*oooI;;;[�6�.�J%x�y�Mg���W���?�Tx� ))IRc���K�N�6���j1\�~6k~�F��wXX�h�u
��k���\�&1""��� M�x�b�����q#�����?��W_}U6���hD\\���V}k$���$�,!@u@�ILLRL��b����m+��JKK���j���-[�H��"i7s�0s ���F����4~~~x��'��		�C=$���\8���^��$""jB�����rg�����-�4������_c^r�F����c�������q>z�B�.]����!�}qq����wZ��]��XRR�*��@�����_��o�)�222P\\899IvJ����|N]�'M)<<\R� %%����������o�@���k�o�(//���I���>k�����;
�����'Ob����Y�]�t	:�NhGEE�F[�~���_�~�����J!��?F�!��z<��#8t����T��:t���Krr���UC<x�<��p
�<3����<<<P\\,��Xf����@Hc�������B���	C��h���5���V�x���q��a����~�9��u��$""j��������Z��h��]���B��Z6++�V�Bff&
������
ooo�m�:t@TT����
QQQ!���\�1���+YH��e^y���DEEIv���x�ppp@�^�$��Z-<<<�T*���)��IMMEII���'N���S��!"##��� ����kF�]�b����_��v�>}l1�������#�l�����V��^O��8::�����'�|"����b����h4�����`��9�����Y��� J�u����
@Z(�Q�T0`����NeMhh���X����:y���~�7��?�������m��ip9'''L�6
��-�V�X�E�5�>������Y$"""����!Y������bpjj*,X��'Ob��	�����l�2���{x��W��SO��������8{M~��gI�"y���{�C�B���C�M��j��t`�)::B���C����=�999����n�w��9�?����8Oxx���^����_�-w��5�t0={����������
��-�������h�����Y:{���Z������}�oRRN�>-�q����� ��
f3G-�W�^4h�������!���ySR$=$$111������|PtO��3q��F�-&����TcM\����T8�R���X�n�,Y"b����&M��?�����wKRZ����WR��O�>���0`���OVVv��)�ADD�8<BDDD���\�O?�4���%����X�f�����mo-w����QYY	�B��={B�RA��"??999�~�:������___t���:u������L,_��?��E]�k��a���8~���)��5S(x��g��G	�.?��#���1i�$�TG���HLL��5k���7z��.
�M���>�LX�����q��L�4	�������c6o���S�b����q{f4��W_A�V��GELL�$���s�$�	///I���C����#B{��}0��2e�P8���
G����+Q^^.������Z���?����[(�����V���~�"MVUU8�?��aaa�7o�d����z�����RDD.^�(IT�����x�l��U�[�l���#,�VUU����X�b��=1a��6tg������'����;#�)�I<x��um:w���QRRn��wwwI���� (
�-ooo�9-`y�$--�b�����q��u��KQQ���p��	��Hx��W}����S�����M�0b����WR�=##����\�1~�x��4�s�=������]����p:5	B����Z���<x��u���/***����+W�X�:�:u������d�G}$��*<<�g��qq�l��}��?z��ooo���"++K�n�����^z��"Rxx8f��!,|�L&l���v�B����������7o����B���7b��������c����7�x�	�^�Z���c���/t��m�����n�����T!��u�V<���^��[�<yR8��|�r���/������rss%iT`��1��DTT"##%;���~@�V#//O777L�6M��R|||��+����>�RRR�������#88���(**�������������Mk�f��kHRR���$}5B���CJJ�P�����/���7���q��
���������'��;���O>�$V�X�:����?��?�)=�BQ�@�B�@��������C=$	��b
���;����<tuuNS���Y�(1KHH��P�I�=0o�<��
aN1f>y��@�V���
�����)@������7���m���4i�p�������+^~�e�L""��cj,"""�VL�P�`0��������������)	��T*L�6�"����a�� l�p�>��a��5��KUURRR�o�>?~�b�C�X�p���������*��^YY�s��!!!���8{����������Ls�8q"f��)��[UU�K�.����HHH��s�$�DJKK%�0���4P��|��	$&&ZA���>�;V��P(�����k���~�����ldffZ,X�����7��1eMK����}�]��xvv6�9���x$%%Ivp+��:�n��\�t	��o�w7�������?����B\�rE��R(�<y2�
&�I���Q���sg�����;v ))IRK�K�.��fu!\$$$���[�	�v �����L��1�CCC1o�<����M��tHII�w��������NNN�={v�g�0a�$@|��A�={V4����ax"�����{����u�V�%NNN����q������0�|l��
��tpuu���?�������R���<>|X��_PP�M�6��g���#p�����_��]��m�6����� $$�G������T���f������+6l���Jr��i4t��
1114hP���9r$z����������V�B�@HH��#G6��������G�����h�5���7n\�:777������gv�����l����#F`��1pqq�����;c�����};���k�����������Wm�����[S�����E��e�������'""�<�"##�C������@�P`��X�`�p6����i���pxyy	����8v��dNm��.]����]�t�1-�YHH<�� IDAT��������d���V����
www���!""��wG�l���4
-Z�M�6���#�3'''����0aB��spp�����h�"�o�����OZ�3��������&���������_�^R666NNN(..FFFn��gggxzz�C�M�(PVV�w�}W8������K�
�)))�j�����,>_�z9990���@@@@�RV�Fddd���z�nnn���@PP�����d4������TTT@�����!!!�.<o�JJJp�����
���

��Nm�V��W����F�...h��}�i�����������DX��85Bw��k�������R��%�u�ZHR��9#G�����������@����Cw���J\�r��]CII	�J%\]]��}�f��Qs1�LoE�M����������`����q#���1b5=��� ��L�T�S�Nu*�~�(�Jt��Q(�KRnnn�������������A@@O|�b����w�J��_��=<<$mj=�u�&��k��j���Y��!""�[���������z�������n���777��4y�lq�""""��!"""�s:��|�	���0y�d<�jJ����{�"11Q�����h����m��I!]�v�+OH�i���U�V!77�������GTT:u�WWW�t:dgg�������h4�8q��&"������s�����999HIIAAA�0�P(0e��-������!"""�c:��O���i�Z���#>>^�/�����s���Q9s�bcc���� 3f�@xx�|�������Y!'N�@BB�����m[<�����[UU���/$''C��#44�������0'--
�w�����������`<�����ccca0$}��];�t$"""���h��'�`��=��g����S$
���1u�T�k�N>LDD-,<<�<��V5B�B���O�]�nnnh��
:����_��A���-TUU���>��S�����Z��;wb���������,^�F�AAA(,,DRRv���H���o�>8::���@���������V*����Q�T=z4F����,�={iii(,,DEE�����Mt����������.����yzz�[�npvv���/BCC��m���Q=5K $==���C���1�|h4ddd`�������
�Z-����]�p��)L�0O=�
��������^�uTVV������Chh(`�������������oK��C�����%}DDDD�����1|�pyw�	Fpp��������������n""""j��bh���;a2���3�@���B6���8����v��wwwL�<
�0r�H������t���/^,A`��� )�IDDDDDDDDDDD��f	�������:t�����dffJ��rrrp��
t���C+���0�z�*X��>Vl��[�p��%������������������4yj���2h�Zt��U>ooo���7e#R������E�

��;r� ::Z6R}�s����w��	s������l&��f	�����lB]�N'�*--����F ;�����T�������	�F��#<<111(//���{�������c����u���*�""""""""�V��f]""��4y ���$�M�5A�1��.��U�P\\��S����]2���"$$Dh:������g���U����������K����������HMMe0��������
k�>�}NNN�)[�>j��s��a��=		��1c$c$A����z��������S�@�?H����O��zCD���"j)��QKa6""��X���;��),,�Zkr����Y��^����0s�L�T*a�777�.DDDDDDDDDDDt�k�@�B�@�v�������b�XZZ�s���~�������e#@zz:���$��Y����x��k�o1sP�x!"""""""""""�������'L&�������2:t����`Err�P�����!!!�z������������h88Tg��t��o�<��S�\�k��I�Z����P�����}h�!���#..k��Eii)������"��3Jeu�E��c���0())���3���8q"���+|���;v,�z=v��	�F�G}`0�|�r�L&h4|��w����� �>�(***��{��C��������N�������Ur;"""""""""""��i��-�z�-������e����>�,bbb�yj����Bhh���
Byy9V�^���@����5�������'=rrr���#��>�F����8x� ��=pvv�#�<��{L|"""""""""""�#�.��k����&q��M��z���B�V��QYY���"�����T1����R�����B!�Rgz����P�T���N�4D||<`����~"��fN�\�i""3^o����zCD-��"�{��s�YN���i�F�%�V�k��R�N�4���#��o/�&""""""""""";��#DDDDDDDDDDDD�!DDDDDDDDDDDd�!"""""""""""��@�-B������������n1BDDDDDDDDDDDv��"""""""""""�[���b �������������!DDDDDDDDDDDd�!"""""""""""��@�-B������������n1BDDDDDDDDDDDv��"""""""""""�[���b �������������!DDDDDDDDDDDd�!"""""""""""��@�-B������������n1BDDDDDDDDDDDv��"""""""""""�[���b �������������!DDDDDDDDDDDd�!"""""""""""��@�-B������������n1BDDDDDDDDDDDv��"""""""""""�[���b �������������!DDDDDDDDDDDd�!"""""""""""��@�-B������������n1BDDDDDDDDDDDv��"""""""""""�[��#L=`4U�@�A>LDDDDDd��DDDDDtw3�B�������L�bK`*�(���)�7o8v���A��Qr?DDDDDD���"""""{a2Bw�O��\��L>Z��A�d��9������Pw�nO|
����IDDDDDDw9��"""""��B��E5Al1���Q�tLeZ�(�]�'B������@��4���N���!�eZ���O/���
&lH����(���R����������DDDDDD�	!DDDDDv�"���"�M��B��C_���%�r�U����y�%zK��n.�sW�d�{9��N��sWK��)��������F����}q>����"�`���R�������
<���z��J��=@DDDDDt0BDDDDdL����F1��
���e{���je0���X�:S�Q�}0���\���,�NDDDDd��~���qrE�E-J*��#uVXf�������������.!"""""j0B������������Q�w���byw�����|_6v�-�5;B������r��7��B���P8���� h�UG�p�V�t'"""""�+B������VF#�v,E��������dB����.�)h�����-[Sn��)����������""""����R����Qq�W�O����s\/D�PB����?��A��M>���n����\������n5;y�n��"��mWN
}�v����Pz@��g��p�L�
�<���D���Q�r�{�`(2��0
P8�@�iG���K:l8]
��Q�����*|��*���C�z���������!DDDDDwcqn���n�	}�.1p{�(4���4}'B�w"�ja����!+a�(�����m0�W(
\�+Glb6�
*Q�]er��B_S���u�t��+�4!""""����6���������(^�"��l�O���NxP�D3o��H.�����RP���{��
���!!U����8p�H���M������������?�sQ���4�2�;������CDDDDDDM��""""��@��t�Z9�[�B����<�E@a��FB�[O�.x�S�GN�^��@�7&G���&��jt��������s���D�G�*�7��05�����2yQ�a ������1��Xt
G�|C�Uy�pk��0��\~
N���RJWiB��y�MA���?]��}�~�B��%���1�?1F���@��#���a�T�%cuU\a�w5B�����ZCV
��~
C�9�O��M�h��������u*�:�]h�N�Y���
��dW��jT���NP)-Ow�;
���U���!���K����X��,N��O����,!""""����8����������(��0%���T��P(���p�=�v_
�����l��4Z
�����A1��<��
�h�����!e�|J�"��]DDDDDDM�v�D"""""jq���(�[n��P����}e-�'c��H�����u��bJ��.���A��#}��DDDDDDM��""""�;�d��t�G�n�L&��*��5�s�_���?
6�j0��x:�~��`��k��n"""""�&S�_&DD�?{wU}���u���	�%l" �(*
***��������������V[����z���m�u����kEQ\paSvD�@B�g�s~��$�LT 	������s]�Htf�s}.�#"��c5T9��
-y���8�:��B�o�w�;5aH�3�0�J�
c��zn��������78w�2!��i�o�ma��|���i	E)��p��\N[�����DDDDDD2�B������>�����\�uj��l`me��B�n�oM����k�h�;2��#��`��:n�r%�g\��[��i
�������~~�Z9M�(���v�0x`Km�%�y{u-�O��"�3������tO�{�EDDDD�+��n���O[��c7L�?��X���2�#����?|�����G�������3mL����<2��M5������l��H0���������W)ZYFx�Bg8-������n����p����__0��G�9S���L�����h*�c�������3%��.���.����-|[rmEDDDDD�[��.FDDDDD�4+J��Gi��7���s��3�! ����6������B?}w��(>��w�e���J�k���1��9dhv�zL|G^�o�sA���$^��R�������K���^_YM8���Wlmb��F�)�.�"""""}C�6�;���u��g2�(�J���0���x��������u?�=�s�1�=�������
��
:Sq�L-��a9�}�~��v��\�{+�!��)_�Lw*��-��e��g���}V��B������|!:KDDDDz�]���C`�o�y5Xa��`���B�F�v?,<*c��}!Z���w�]���=h�����������7�-�����c
��//��~�m��j�#�)�V�TC7��������Q!DDDDDz��&X1Z����"���kP��3�W�~�D#�@>�S�������?0%���f�]X�ec��]!Zv��Ur�t�������~9G6�����/"""""�F��="uP�>��������7@�1u_Z6��:X���!��l�6��?��C���������O�������z��
���
l��Q�������/�{���PF��ML���t���~�d�"""""=_��~;�y�&���QX���6V���E�?K��>�k�}0\��/�n�w����M�[j�i��r�x}=WM)q������t��s���\����'�g��Zj�"�
��8�����/F!""""��5,�����Pj�X���G��c�A� ��1�<������Y��A�f�g�mu�Ab]!-a�����g��n�����ZY^�o7�9����������� """""�	BDDDD���Z���A������_�(T�
wF�0������&��S��f��$meWW�/�������p�|�������+���sF2����+�t��iG���6�4�qF�"vz��81O�K�O�Z����m��^����qV������J��x�{����m\�J��v���d��}g�Q�~}�(~0����8e|!3'��{v�D�����(���"""""=W�������]o�q�$
��M����:>�p��!0�Fg8�(��!C2~��Bg�+cx��\~��QI��%?9��#��H��M�I�r���\;u�5������t'M�h�#DDDDDD2�B������,���<�
7��n�nZ~6�����C�g�[\E#���e�a�?�j���(��������Ax��<O��ENO**�	����N��`p��Q���y�`�aEdyc__s������""""""�q;"""""���MwA��������3�{�U�v������a��h���9;��a�����b�
FN�G^�n�,�w�q��C�L�m(�ja��V�����~��hvn�Y������7�l��N���I7`�����z��c�����"{���u.����C�3kq�����	���wc8������*�����HO`G`��P��3�=��X��#�F�J�N�]s�;2cG��v�
�A�;�)�`-s�Fh�l������N��8�*�n����Q^�q��6	Eb���y�~P!��o�A����\N��� ���N�/�@^���N����W����X��t'W����$*���������w_��;{v�-��j��7�r�gA�tp���Q��/^iS��w�:��	���9V��X�����(���3�����>*����n%j9��J8zT�O��e�t}d���=�t�g��yv���'/�?�j��N<&3'�����p��Z��X������IDDDD�_����6g�{������L�=(�Y"_|a��=%�&�_D�	v<��`5V���E�@��v$L�����du��)��lK[x��]����c� ���������O��Z��������
E,^[���CDDDDD$���.IDDDD�O�s�9��s���� {�3���?���:�����3@�+wc��9��D�������)m�^���Pf��G?�N����7�"0co;�]��������mr�����7W�R���x$"""""�L���������~(��\���v��
�������+!k,�����g�a'�Uo9��j]8+6�6�����'�i
�qg����d�
�;���:���I���rP!����
�+DDDDDD�I�������7������g�?���{������>��7:���pFhy�������V�V�`�3@s0JK8�n�6�
agh��}y�:�a����]��M�<$�2gu-�Au������HfT�}+o�3�^������uf���������/��z�K^J����^bG��������\���!m��&�4.�n����lfN��,o�+�5l��������wI""""��>
g8��0`�����N�����]�����e�!I�u��ecf'
rO�q��w�;e��2����)�����W������,�19}B��z��Z��-#"""""�'BDDDDd3`�
�`�����qF�Z�������S�g�������w��`t����C�we��|�ng�G�N8
cw��	~��cG�f�/�������Z���:�%""""�7D������	�?��w:_=w!�� IDATLZ�n�QTH.X���_��
�n�N��3���8�4�n'?���)%�p�a����L%�:�i��7�#��������k��	G3��""""""�-BDDDDd�Z�h-�].���
�!��I������>vO1}����*����G��SwB�%�}o���4�~/V��D.��c�$��w��}�r��wz)������������|�/3�{�����]����>��@]K�yk��=��O���DDDDD���g��_���_��_$������L���4��o�(|v�������}�:�{�P����hlM����X6��y�<*�3&��z23����Z�:�?�w�t����nN[��U�c�^]^�	c1{��/"""""��
!""""�w��/A�zp�B�x(�#��?���X�T��(,=	��y
��]�����Kp�8����W����d���G$������������Dw��5�@����:���W�b��"��
�=*��MDDDDD��X""""����a����)���P�4T<��=���
������?�/�����1iCzf �����w��!��������?J��s��{���u��O%e3S����Q����KwbQK�BDDDDD�=u�����d��m.\����NEE---X��a�\.|>�?�3�8���"�S������dh]���*������m�P�hZ@��r�>>;���Ff�H���������?���e����
��a�?�r�;-��U�N�FV�������Geul�n���V�l�r=9"��/"��K
k"""""�Gu�.MDDDd?WWW�o~�x���[G]]�P�H$B8������:�l��;����7��k���eY������I�E���Ap�3���>�0�q�`�C�������9CjEygMb��c��Y�	���������;vt����@����ec�����j~:���[3����K��4B�w�q6l �$V;E�Q�� �e��s�����;��_Z7���8��������/��M���������d��B��r�*p�7%=o�Q��:���]��c�l����t�k��ry�%}Z<
V4iCz6�����o���cms��}s�
!gJDDDDD�3*������1k�,v��E4%���Z��hii����c������m�;#������x����l(!��8�*0b;��U�����#?'�������Y3��`p|g,�XU_OW���w^����\���n��o;vt���:�78���"�_�������~������5551w�\���#�9��	�<��s��~��}�|�3�^0�c�z��,���4�m����?y
f~~J'D:��4R���3
8��B���������S�����$e�{sU�3��U����SW�������L��N�[����m���>�����������q�&X�ubu�w�3����|O���T����?D���`d�|NR7��#����I��
��/�_G6.&�c]R�c6�ag��*S����_DDDDD���tAI����-�OL�������,�����qh)sF�Vp�3���G�s���Yq6xr?��� k�3Kms����b}U
-Q��H�N���A����{�8"�����g������c���#�^!SDDDDD���nG�8C�b���Z999�L��g�k�J���x��G���� ����b����O�]�3+Y��!��������K�1������b��/@�u�;�$��������~D��D"��b]
�a���r�\:���lG��W;#]��vF{>������
B���_^����FK��������^�@k'���;�4�@>v�����;��<"��T^�����QG���������wm""""}��u�����y����1�7�;�M���������JMMb��~�;�I��D�����������/~�uW��>�JJv��1�S��!����������;}��������YW�5SKp�m�8"""""�?R!DDDDd���f{�1���.�m���\.L������W�4�������;��������v�q��:#�
�.�s�z�����L����%;3�w1gU-���"����/#�3��L�l�cG�,��
'��I�v��q�=2������s�����E���/~�������I'���~�;�M�������a����������1�Q�F������s�=,^�8iw6�2����v,���3���>��vF;��{��$hY��mM�lZ�����0�s\|\8+)���������0������I�������������MDDD��Y�no��66l 
Q\\��I��>}:n����Z����d����
:����:^�����9���y���Y�~=uuuTU��4*..��v�����q�8���4h����?�8�e
���_��\�g��i1�O0�0�X|$�f��������[Y�,Z�&k�&g�su�����D�a#��N�������K�y��g�b����K�XQ����1���v���Z\I]K���ud{]�����L��|
��""""}R(b��Y��;�N=TWW��u��7o�~8o��6---������s�a�����m��UW]__q��{���X�i��1`����~���x�����cW]unw~)�����6E��X$k�3�;X�-���l&��C�[�cG��n�peX����v�/����XdV*t}<[o�=�pV�V�-��_ p�
�m��eP���!�KE���EK�bgc���
=*�k�"����[DDDDD��>��[DDD�g��_Y�l�p�h4�m��Y��mK�0v�X���jLzw�7������w�}��v���s�Nn��Frrr��#��(��90�
���H
O�~g��N����hz�N�������~#�&k�gP�lJ�3#�K8"�m6v=W���r�����E4��G���#0����-K0b���7Q�v������)��g��SiDDDDD��4#DDDD���~8^iii!cY�m�Fimm%M����k���~��A�8��n��1c��ck������m�8���|O�G�c�������3{m�y�hx�{�� m��gc548�iM�}���i����(�[�&�n/VC���I���3�*�Qr��Y���w��r�EDDDD�S!DDDD����2>�� v<V��X���`<������?~�������?�S�N��v����w���5k�v�n{w��?
����^*��#Z?��3�����n_��55�u��5�0�����#���"#���S��������k
[������k���!��T�>����_[���i�-���2�n7_���9�������f���^>����������P�/�rT=����ulxzog[4��g�Cvk�����h�������l`���v�H�������������c3C�P^�J8�����m��4]a"""""�����z��TUU�y�����BH[GH���=�0�:�,�C=�_���RYY���3�hg�W��eX�&��qY�`���h���yF��ks��d��04�
��ey�T�g{Q�g`��#��2�����{����F������	��_��Z����w�9d����G������H��������~���*em��_�������=������?�1�����K/��#�<�2��G[�]XqN�E��&�������M�P�B;
�Z|�p���y������SK�����]������E�F�6��?����6
�tO�������"��""""����z�������ib�&^���c�:�{��Q�����)))��>�����?��.�/�������h�h3|v
D���^�����N��I��a�p�x���s1�4�����;\���Vc5�5��)�Q����w�C���q���+�RT�>c��!�\��nl���r�+�@������������Bqq17�|3x`<�j�*���njk�w��^c�`m��[������^�5h�3�9l��Px�3�V��q��<}@O��������YI��������������Ld��J��3�S�L�?�n7�@�����������1�0}�����'�����~�QG�m�������l��
�}=���,\��e��QWW����z���h������y��;���o�%��g8����9vt�3��J>+\�1
O�����$��K���]F���p�A��p;�m�����g�&�����������A:WDDD��K.�����SWW�eY��a���/{


����z�`r�����_O���y��������������b������3��0&M���W^I^^^<�W��9#���,z�=8Y3o"�q1vk�3��=�p��/�H5l�%Dj�[�	�VF/���q&H'�%c1|9��F���\�oZ����s~�g�����cq��,�h;����v�nn���6r�E����MIO��EDD�O���b���@���
#F���?�i�"��a\t�E\y����wss3�>�,;w���m��(�ea�6�/��[n������/���Qb����E���[L��b�;/<yFE�E��O1x�sK����C����K_
;������ NV}%
��7�����
�����pF)f�����<9�3,"""""}�
!"""������l���:??�4q�\>�+����o������G�,'�t7�xc|�	@(����`0H8&cYMMM<����B��g��rwF���D_(��G���1�4q>��so!���`�L�\������6��u
s�.��XIZ���h�zg�������+v|\��+k�v����?�eWs��>DGc���H�aYO<�D|]ZZ�-����-:���=�P�~?MMM�A��(n������������_��/L��19�B�T�����������
"[V��y�z��	`vv��?�~gA����-����w���)bx�,t������ji���`�E1�5����d�wkJ|uEs��+�+��r@��>"""""��u��MDDD���7o�����W\�i������]������qX>����aX��rD�o��������0�!0��D{����9��Vh���k��P�CISI�=���ckaZ��<�:)�������euYi.�(em�����h��~�]2x�&"""��577��s�yG}4x`������ �	�r��m�`0Hkkk���(�h��~�����d������f�w��`�?�+�b�V��_�9-���]��
�+�w_J�9�8q������r����S�P����?�Yj���T�>��_��16X���q�E9v�.nw��Y�0�C����,�"b�6eee��7/%�G�?��A#6Cd�?����g�#��������
�@��M9�;aF���ywS��������H�����Bg(-3�~��!C���N�L��g�_DDDDDzBDDD����es�����<�L
��ajOSZZ
?���(����a-Z���A
�@kYb}�J��#>������ ��R���i��g����H&�m�3>�)Y��Y����u'�;�
���z?�qD�"�n��#�!�;��;��:3'�'��r�EDDDD��������He�6O>�d�HP\\��_�N�������#G�g��+�@"�v��^Q�d�:�X�F�8b(�y9
��~�3c[4=����!�ZU�D}k�O�N�>�/��������)3 ������d.7�i�93�z�����p;���9��bgXDDDDD�BDDD�W[�x1k����/����QR��a|��_��=�;�a�mGj�yT=�X�<q��EB4��+����^����N���z"��5\�HT����o�:���y]�fC���q
�x����SK�t�wb@��[g�������������^*����H�
�x��g��	&p���&����������J����3l�0Gf��>���
'������K�j�3�!�y�O^p�;��,�+���|3�lZ	�'��1��K���3z�38���A�M���.:�o7���
�4��9��������~"�;j����^��&6W�4M.����;'z��3g��L�����4�x�	'����!�O$�O��C��E6~��.�������4�b�&^������*�������%�^�gr.�=��f�~FVb0�
�����l����r�q�������=$���������<��������"""""�Wt��ADDD���s'���z|}���RRR���o�x<\w]��w������{���v���8��;vl��{���g�W$���%���	����������4,'6�{��*��H]b��3��D�������:���Th�������D�DH]s��;�yi�N~:���>��.�>H����y�"�������}���}���c������|��n�@�^��������x�R�Dv��0�Pt^j��3�������l�v(b��<Q49zT^���|p�
MoI�����'�����	o\�����U-��z9�p����P������T��kT�^g��U|�I���/��@ �����6m��v�'O&`F��`��?�K�%�?��6�v��Gx<�J������h��!��c2qhn,a�����������Y�xFO��C��$e;��<��6�����h;�tL�����H��B�����*�e��SO���F�b���*�%EEE\���w�}�w�}��oc�����+��Bkkk�#��v��X�<q�D������q���7�,g�CoH>+�;��H>�q	4d�����|r�:������Z���-�Ag�CM�(�����$"""""}B�7EDDDz�w�y�m���W\qE����0�������f��y�A�3g��=&���X1b� ��L��f�M��?%��;�L�������_R�"K65���c��d��B��u��!���=��T���XW����&
�3�p&�:�'6;����;�&�V4v<V�'xF��^����g6Ck��8C"""""��u��m�F�����,Y��P(����9���(**rn�T}}=���*�����rq��s�������{,X�G}Dmm-����;��O>����L"""��566��/���w#F�Hl����2c�^~�ef����'�HNN�c�W�2��C��c������d\q
M�����������-M#�c����������'������}@k���?��g;S�������z���M7-�faR�Gx�tF �����}@x�[]B�Qg(��P�������H��O!�h����w,_����b<�g�f��y�~��4���vjjj���[���������V�X����/���e��Y<��sx�^��g�}����y��7�������v>�����@/��"���;��~������1��s����HKK����\r�s�����%���%�{;����?9��2���� �by\t1_���:�6��N����Ec��{�~�����(�S��XY�}����]���L����������/��>{��3i:��r�w�Sa�>}�$"""""_�}:#��7�`�����9�?���s�=|�������'�H����?Lmm-?����������������
�3'6<1�r�Aq�}�q��w��?��c�=���
�|�M�3���HO�u�V�y�������&/�o
����g��8��������&i�Wd��`�b��"(L�j���U��v8�3 �uvk�3��p���M���Gv�skf���%�O\'�����A�]���6�7$��
Q+�K.�?�.�V��x��=!^���v����#������34������i!���_'77��/�8~�����)--e�����VUU�x�b&M���������+��4M,X���^�M7�����rq�1��UDDD��{��g�m���br�� IDATN9�����I'�Daa!�H�_Lh�U�|2q]|1}��y������!V���x'Vlm�5����;9�M������4�6T�d������t|Yn���wB|n��������V�a����-=���w���:�znR��:/@9����1��������b��RQQAUU�����N}=v�X"�[�lI�;-_��C=4%���OII	������������@orDDDz�+V�r�����K/m����;������_���TTT$�����P�Vb=���u`f�;C���daf�K�w����c��������lbI���[1��U!���y�����c�t�8�;(�<5�������s7���r	W�u�-|���G�tR���B��SK(���������6�~�`�fg;DDDDD�7�g��m��PRR��$�]������s�A�) 6<��#�pdDDD�'�,�g�y&�7n'&���)S�0`�l��j�B��v���
���1x��k�����a�F���e�i��X#]	�h�'����~?�;��|�n�;�ci��*+6�5�LYe� �	���u�5���������Z�^2C�3���ut�:�]�������p���jr}.~{��(�;S"""""����[)������rd���������j{�@ ��$�#���z������e�8��7n\J��>��sgHDd���7��Z�dI�
�08��cX�v�c�����~}������,Z��y����#����)�~��W\��T}�.%�S������&'����Y��3������#��,��h�
n�������4xp����k����<�6���� R�{o|�W���W�!P��B��!���}����m���'~��G������tO+�-����-���u�����
��)���Ro�yu�{�D���H]��d/�	?G""""�������� ����B��9��o�Fy���0����*%'"""=K0������9��n���7n������y���_�;��@����!pvR��hs
�����v���!4l�3��5���
M��4^���� �Q�y�������l�\�e[���I;�j�8C]Z��]���CK(v�QO����mM��vePWjr�8��wD�(l��^�HDDDDDz�}�����mH����-=���)
����_d��M�r�)�=:%�E��v������v��������Y�hii���q�5�����qD{[O��y�����?��u����z1bD��t�����r�u�@�|�OY�av�Ii�5u��7���pG3'L��q_����b�;�:4��u�>��H�.a��Vl\���S7;����SU0>��AY�T4�1B>\x��uA���4����5��?���>��S���i���J�z�[d�=��"���_�*���8b(��}�y:��7�lK�8�j��S�t��=��oDD�b�<��!�������������#���y�f^x�
����5�SDD�����a��9��g��#� =���>|x|��g�T>��p����l\���k3+��)������"p�w��"���oV�ClcWs�#�0��a�|�2�s����l65%��������������-ig�vU4�d�i�����y�����51��'q;����~4Lx���
�84�~a����������-��2h� �����a~���C�:S)��Iu>GSS���)�e���D���k:�+""""=���?O$�����3f8vHg��������/_���>���?�[o������5��ib=���Lb��V�_N��W�Y3������M�(���>����U0��]�\~����~TQS�w�&��� �F�i��0��'�D��:��mA��&���H7H{�*����t�{��g���2���G�M,M�q�&HMS��6"""""����BH^^��
c��-)m�k������#�<�;qr�o��+���2?����4M>�����s����m�LI�)z���(++c��IL�����"""�ol����?�8�>����GbJf&L���a�����g�������Or�����������~O���Y%�}P���vk|�wBR�s��~��2��|W��2��#���2j�#x��
;G"��g����P�=��f���c.��7�h�&�%�h����+vL�W��^�k��p�z����������$���|/���,���g������H���!��{.�������_�<�LB��g����q����X��Gy���B�=�X VL�>}:s������5��Mc������[���r�q�7E��og��Y@�[����N�������>b�6K�,a��TTT�r�������a��!C�:u��Q����*+�{@4��,���r1�|V�Z�-��B�~�����������}T��w����0s��
�����UP����>��m����
F����u�g�4D�,�.dj��c`�?E�N�\_!3'|�����w�^�>{��m[��E��n�*��Vlv����Mm_����r��	)���3zj��1����At�\�����:tho��}��nn����#xEDDDD�o����)S������O?��O��60`7�p%%%�}����F��a�����1M��s�����0~�xn���xG���>��f���c�$��-"""{Omm-�=���-s���=�\Ls�5��J�m�������J4%
�K;:�������c�=����=��>��������������i]�,����Z��qwR�A:+�6����fh|������J%�}P]�(�T�B��1�����}�/�k�����s������{*j6;C=�������l�
q���������B����D-W�Yf"""""����B����9�������rQTT���xqq1��w�e�����s��\{��\~��TWW�������?�i�ZDDD��p8���{�o��m����x��i�x<,X��I���t�-[��U��m�`�����	�B��~�/_���+�0��;���N\�M�����[�iz�nB���L��%"������&����� m>�������5�����xJ���%�0��U��O��"Z���<~g��p��/����'���Uz��/���`\In� b���-�V�0�$��MDDDDDz�q{�i����P\\���&''�]$���c����� """�3���Kl����hmm%�`Y�h�p8LKK�m�h�"/^�|���t�R����������OeCe��X}mH�m���m�� �����F�c��j�v�RT5ts��?�9E���.��%'|�&��I$�?B��o�7��0~�p�+8v������!�iIJ1�����l&��5��~-���;�����1�T�X�9��9"""""�k��B�����_�� s���_'����k���^sd%������������^[[��
�u����%g{���7	���{������RG��w;�)^�3��������O��on��o:�h��X�����1�s�7��i��JJ�M<�y5����|nn�X<~�{|��[q�C�����p��3��}���J�?�����_�E�����}�L;������mQ!DDDDD�/��Gc��������<~VGE�6�h����|>��HVV���L����;8�(������R�&����Th���J����QYb�HW����t���<���-W�	��h6����0�*�G��v�[o��N��m^��'�M(�����A�r+>���Bgx��m�^�;����2Z?~����v�37qhO��T6V�R�!?��K"""""}�:BDDDd�knn	���ijjrd�3�G���J����o��`A�3���K�}�m��Id*�e�37ut>~O�h��fn��r|�@J�0L����� m��B�����3t��s��oa��V>���>x����;�^�Aw�m�m�����L�!�>�e�:s@]!"""""}I'��DDDD����^�����a����f�I�c�9���<\.nw�w�{<\.���L�<95Y����
]�����H��
m�P�����kh���3���[���|g�kE�k��M�:��\j�20���o��o<���'�e���a��8`����'����V�_�k������"��8C)�����`����������3���
F^^����\��XNm��?�������l����q�����z1M�h4�eY���R �����Gi�%�Ux
x��>���0��a5�8S�ru��m���|��2�{w��@�v�H�����+-W6_
��[o\���KY2�_�?D�������]���u�����_�������}�v^������1�4�w��`��&,��N��,�m�""""{�i�\tQl�v��N.����i�\xa��H�&M��u�]G ��v����|�xd��iL�81�qQ�z6(�,q��x���u����{�!�0k��bSe��w�����v;���mBU?'��.o}�b"�]%�$�k�Jt�|��� �Y�t��d�b�(�H�P������W��g(-�`�3����sp��|4����j� �}���""""{��)S�8q"�a�����|x<<>�/>��s������h����S���;8���6l�������������!\[^(:/%�WN�#+�#����1�:�H��cm��p�`����`��U��p�?��;��c-v���i����O����!E#���w&��Dk��G8J���y8\b�Zu�3v�3�N������-:KDDDD�oP!DDDD�	�08���������999|���N�#�WPP��_�����=�����x����
6$����W�~��;6���1s��}�-�8��&��w�g8.�4k��%�k��&��?z+jE��n0a�U�����{�aL���/����x��{�xQ�+`d�8����`�8�Zg�C�������������*�����>��;������8����1c�]w���o8��#��+1t�P��_'���i}#�f����>�;~:���F�QPm.��N������w�qq�W��?�L�w�@!�����[����8N���$�d�I��iN~�����M�8�Ev�"[��,[�!��* !�e�-�?��sa�3��;/��<�<&z�=������lsV���o�5���sJ �x��_�BHW�����������*�3�ol�'^�6<C���s�'!O�m"}Y%�o�6�y*�yEf!����_�3������h�`!��������b��-���n�G?�Q�v�mX�|y��4l.��Rc�y�ftv������I��� z�l���yK���Ac���>�~��!�kk�����E�U<�������4L�o������+�����i��}���z�	������j����OQ}l���(%�}�7�\�E@�{�Gp������1��5@q������T��V�X�B�����f$''c����4R*++�Y!��������,m��W�����U��Fc-�������1��n��p]�l���{�	���,�\p#D�lR���-X�1P�7�,�����0���si�58�	G���P�4US������������"��5H��;p/��H�A��,���	*,�B������h�c!���������3���/����=�Y�q���u��AW���{�<�;���`�Yq�}���K�5���>��*<����o�
|�Q<��o!�*�s��
�f~ ���\������O�A��z>O�4�u6�]qw���c�gG��	G���zn`��l���>��'�NL����:$�zbZ�W,��XY!U'��<�������!DDD4�N�8��G�{�Cy]t��>u�n�D�+�R��k��yK	@9b�gsL�\�u
?��W��������$K!D��m�$Q�e��������|�u�9���ds�}�gqsq�e6��k�1�Mp�����}�v��o��r"�!�{<��%��E����v��c���9�%}�
3]��}�vl��
���hkk3r%%%(,,����������g������ ���I�����j!���>�<<�zOQC�����~���9l��`�$@����x��O��p9<�<�I�al1��v^(��L���<�uEf�b$�Xt3�����k/n�+f����N�>G�2�w������B��KqI(����i/�P{������Qb���"""�!hmm�c�=�_��W��y3jkk�
!PU��4�D��Q0��+2��d��M2���oa�����8�(�7k�d!�i���A/�������5�Xk�Z�8���.�����[��/r������a%@�g�y�yeF�/<��g,���1�C��{��jc�����qN�y��"""1>�?�����`>�~��`�s�N�^���a4
�y������}���������hkk���?�S�N�>��<l�L��ko�v����A���������,�a��hy����N��v.�_��p9B���|xt��P�����EHJ�<q����=�Y9���/8��������h��BDDD#��g�Ekk+4MCww7�� 4M�����wx���Q[[k�h)��o�
 T����������P����'��~N�����4�3���e�l���Q�ABD�Tc��w���)h�<4o���}�
26�'���<l�k����m9��ip�Ks�HvIU����g��9,���hoo�������~[6D�4�A���5kBsh�����B7Az v������������������
)�,f���I��At���#�vz���$���G�`�=]��1���n4�/|�g���<��������o�
;U�6xa���;���{(IP^h��b{,""""�1������hD�����C���7
E�����#;��LG�����������S�L��������$�3���2�N�-����aF�\��pr�#��&�##������]8�����W~b;�M��/\�-L�-����\4�3	z�PP�n�z��?��R���,`��N�"�R�����(Q��[����h��uo����������`��O�
���7��Ez[��7t=|>���&a���aD�Y������i��U��=��g��GF�Sv������W�P��q<QeO
?I��t��J{�������� ��,�,�����oN�8���0������P?~Y���Q���`o>''����������<u�%�������+,&8
!�=;
�/.�-�G�~N�%@�����<`�������g���S� ~��#(�kU5�TK{�!L�L�1)����f{,""""�1)�o�DDDDCPUe��[���e9��s��9�����J���?�$A�$8���{�1oH�AL	���D����e����Gp���g�W,'F���i���L�5�����=��/4f 
-G�������Qf���h��ll*��[!,��M��J
Q[[���p�\�CdY�,�E�]w�=M#d������$Ip:��tX��n@J�� �|0��X�������B-�J&L��*(���O�gW=u����R�[��{�S�@�9�|��������H���!f�����g)�T��FP�~�������O�'DDDD�������4
� ��v��tB�e8c����~
A.�w�v8e�,�����r��tkA �2v�����~��2��
�#����,r+M��C���=xg��F�W~���I��FlE�c=��t`��w%����W����3������������l���XC(�L�����)�h8p��v������]�~DDDDCTVV����C�$��~8������\pAX�F�����������_����gQ���C��a��{��((0�]?)'��zd�N����������� IDAT���������\7D�����p�����hT-t3 �%aJN��7�R�������pMaOa�i50����#��jE��I��F���C�o{���`ks�C0{b2v�j�U^�l;EDDDDD�,������b�h�"���@E���@ ���`0EQ�����X�|��S�Hkz�)g��+��[��QXXh�z�_>��@������>�(��P{���z#�1����������o�K����g��|�nt���3��~���]�Ys��!�������in������q�f�����U�����@O1K�l��Xc;1��"���9!DDDDDc!DDD4�\.���n���0Z-��
UU�	�u�]�������k��7���������BQh�M��(
|>4MCkk+�}�Y�'[�
!S��X'�����|g:[�X��~:�*k!�0����)h8B]Z^?0
*��aJ~l-�����r���1<����� g���O�����d�����(��BDDD#b������!I$I����������$IHJJ�=�����?�FZ��=Z;��v}h�D��;]����_���csF����rb��wL]��~��#�=_�(��������N�A�\�C�x� `sK�h^m�G�$���u��$�}�S+@fJ�=<b�E���M�Ll&�91!-4����[BDDDDD��X!""�SXXUU�}ff&JJJp�UW��GaK�xiz�X2n���' �{e�{CD�4�����cB����|Br&�������j�4�������Xe���4���������u@=k�G��	e������I�TE��B�rt;te�����V���l�EDDDD4�$�omDDDt^��y���8q"y�K��Bi��0�����v{����X���t�10���~#���t���D�
�k��4@�}����*�{�����U<?��_�������}�t�F�']�N���������������}���'����@x�+(Gw7�bUQ����[�n���)��a�����(&�BDDD#�ZY�d�%Cq����������W����zJG"�����m��A��>�?�3�d�R�����7U��k�@����(s9�X������=�G�{
�|�����?�C
���:��f�?l5�$��E��Z����d�=�������A�n�����(�X!""�Q__���zc�BH����B�MD��� 4�>Y�!222P\\lO'<�L�����Z��Yh�":�!�0�!	�1!q
!����u���,��������7T���It�:,'F���P���"f�'{��""""";X!""�a�
RRR���<K��BiZ_3���n��f8�N��Y6;�
�����m��9s�18},���rJ �O0�S���4pG#������$8���hF]�
@t��J;p���|��x����
���w�����9�2��������%��I�9!'X!""""+X!""�a��:�b%���X9@�%���<�v[���N�n�.����h�7n����mTWW�� Xc���������+������X[�g')������=VR<i��Cw��7��v���#�L���k�����Q��(4���M^t�UK������!DDD4������� t�`����am�n���%�\�;�����E�$TU���7�QU---x��Gq�����.�=��-m�t�h�jEe�rL+4o{�����&N4�s-�J��=V�����'�UK?�O������n;1B!�=�efL���\�L
��FPu�+�%$B���h�Yo�L�6
����,��zh]k�{�bY��;�����������G0���x��'�(���$������(�1e�jO��[|�����?�
����p�����,[�O\�+�����Q����*�d_��e����3,oW2��������O����l�����>�"�`��&PU=�c����������i��e��g[����98[�2.
����g�^/TU�X�P�$����v�����GJ�5�X�E�?{?[�N4��h�,��Zt+&�M������rd����4������������g{�����T���������gt�;��wa��gq��w��
;�r#Dk?�������(J�����"U':��(;Q���"""V���3����(&�C�q��Ys�s 8��E}}=�PK�Ht]7��e��j�(]�G�{�O����/�r�2\Tq
��{� �����
HH������u�Hr���%���6�
�@����S�!M(3���1������h��������(��BDDD���k��YHM5��Oq�v�����[��Mww�a��i�L8���Dggb��U��dc�jw��>l9�?_��]�c��@sg��y����������@���'�k���3	��m�k������XJ��!).	����q���������!DDD4lTU��m��=�b%�����]�r&�yyx�"--t{B���(���gee�2�E9�h=��w%������<�-g{����E�.d��NX�s�$s����N��t�\t��z���������?������=���'l`��-�E��Xo�>�BQ���.� TWW7dY��l'(.��b]�-L�2@���[���*������%�f�HR&W���$3�����u(���o�l��^2�	d���B�$�?�������f^��7�����_�����B�<��B�_��	���vb`���ANu����BDDDDD���"""6�6�mf***����c(N����X9���~��3�&M�(�p8�LA���� ��������GJ��,�H%��W�j*TMGu�y#��0��b��B��i�
J ���d�y4o�����j����L�<������4��$g�W)E������7!""""��c!�����E ��;�=�b%��W�ZKi@��yQq�=���p@�ex<8�N88�N��nH����|���xk$h�-P;�b\������ 4�$���Q���7z��,
�Y�k��2.��?�����������f�?��>���>��=|N�f{,���!�(`��fP�����BDDDDD���"""�w���z����BE���k��fK[��k�e�#�4i����`��iF���Ho����?������O��rd���'@����������`&
��Qe�2}B\��Zt���iYc��S����@���O ���!�rl�@O�p*,7�v�BDDDD����oqDDD��6o6�PWVV��tZ��/|6D�9�z &L��>��|�+X�brrr�������	������ob���l}.�5��c��A���|����S� �>��a����-�!���U��5q����}�v�����8����2�pW��R
B���b��L?�@SG��%""""�D�B�3�����w��K�w[S���=�T��������Y�f���
���B-��^/�^/�~?TUE{{;~��_������H��f?��Hv���n�.D14�;\���$����PZ0���������ce>H��k���RRb�	��v@�7`����:Q�c�"cB{��&f�7���y+�����(Q�BDDD�l���P������g�NP\4�6�����"a�����%�b���BQ��]���*�~?EA0���G�z��7F��zZ�Y��K�@���n��*����cFQ~��?��E������+��$L�6g��	�I@�\c��n�$�'��
Q��"�����9�-sB�R���B�������(a���`Y�b-\������iT���_�>'��XVo����M�HE�`0I�p��!�������~d�k���xe���l'4]�hy/P��%���{�(�� ;m����b�)L�����#�^tU9g�;�g;0�$Q�����n�=�/�3	S'o��:'D=uzW��L����+J��=��*{���j:�1�"!"""":�
�mXDDDD6��o��_�d�%Kq������_t������:���w�"D�uhZ����#Gl��Pj7A���~LB����zZ1i0[2e�M�����(]����;�[h��S����#��<��T#��K�������z�g���w���S1�,
��V����������jN~�:�<B�����l���x��������NP\4?g�3��Ts?�@��W�m�?fPh*�����(b]�C�H���"�W�jZ:�8�n������ ��>�=7D����|��(��������o��^T���Z�
+A���,�Zg���)���o��c{,""""���B��M�����/� D�L�@W����!������(F���7����KJ}5N���Fc�k�����lw�=�*K[��t'rR��"�@�Jc��I�9!p��_�g�yng��5�������0���[�z�Tc+��B�B�8'����)�����!""""���7Z"""�(Z[[QSSc��+A���BkAr������y��$IEIII�9s�==������$@�k�����}�Y(V{,m���m�^��X�g�Wf�	��o�c����pa�JTLY�l���u
:t4��?��5���O���A�g:������K66�BH]�g}���Q|�BDDDCf�������'[�7M��u����e�����FVV$I���wF�5~����{f�o��A�L:r�@�^���
�����|�^Y+���1�+t���YvZ�[�q|��o���4�J�[��j����o���41-RN�������0����P�PGx������!DDD4d�B��%K�+!���Arn2�C�v�q�=���rA�e$%%��r��t��v��rA,^���/�����P������h�~�����w�0�`��q�iK�}���:�<��w�o����hj?����K{xHS��=���B��%B���hHq��1c�x�bK���c+�?������C1s�L|��������n���l��>}:>���&D!L9�P�	�k�41;�6��|���$9���-����x�US��6Koo�|�o�\j���-��@�4����DW�4#""""�^��otDDD[�l1�'NDaa�%Kqc�
��p��s����x����p�����������i���<��H���#@D|h�ea��� c�-V��������92	���$�|�pD��
�G��AsLY�_���V���NlNa2z���^�[}������(�X!""�!��������>��X�)((��e�p�w@�$@WW��/�����:����e�������Pt8e���;���J������@�+a�xD��_9����N�<q��J{����\���u��������	!DDD4h���hhh0�,�$��}@�� 1��^IIIF�,��}�%Zg��c�5_�DO���%q�E��l�FP
57r;D�����6��4s�`sBr��!���X��E~�$[|hS��XC���CU'��jDDDDD���ADDDd��)))A^^�%Kqcm��R	�K��X�p����m[��c)��;���dN����3��dw*���k��]��Cv���m�f$C�?�d����M���o�J�6Yg�O]fG�cvq%��3��!�K�b�R�
PK66E���������"""""2��Q4���-V�j�Brn4�#d���E�����555�>}����	6_�����+~���k��^r;fM����\L-�Y�m�:(�|�y����s����c?��$��@����{��^���m`�I�p��_�'�L.��N@	@tC���x��XT��$9Et4���}'�PY�j?FDDDDDq��r���hL:z�(���w�/Z������:-��F�����3�9��m�dG�����Q�!��z]Jh������^r���3�*�A���mG;���&������-���~��y�k�@���������C~�$|��!���[$�\��(�+���L��pX
Ci�%��X�c�f{,""""���B
��-[���i����e�R�X��{��s�������};t=>�������6���EX������U���5t����K?�G_?����E>I�J|�}���8�U{����@�_��Qu��k��O�S��Vi��X��f{��Y�c
�����L'""""J,�Q�t]+��-V�BrnD�0��VYY	A�o������.��(	6��H�3�����j��U�o5�V�_��_�S�.�jOA�����j����������G�w�+�>��i��2������������3Wb�-��]g���{��8w�)�9!�wC�7�b5�r���l�;�,�!DDD���Z���A�
@ql�-�G�-V���t���-���K���zu�3��"�,
sJ�}��ux�@���{i:��
'�����h]cFl:��g�0)��Y��n������[�5�p6��[Cj���b�������g{,""""���B��zd��HKK�d)nZ^�����@�����{{,ME��Vc�U0���c�WN4[f��t�O�����
jxzk��1f(gu��}G���[��c��vN��d��(A.1_�Cm�Ua�R��XDDDDD	��"""�������|��x�bK������:�z���x,0��O�F}}�%;������=�e'�n>U���v�0����#�^�u���i���8�?GR
�*M��G�nN����=�o{�L�eN�2�B�9'doCm��r��������[2�Y���3���(�=��8�������(�������)S���n�����+�������������O�\����o���1Ap�����i�o�B��o2�o�zAexgp�BN����|���IpH���/��Pc��Y�����h��BDDD1����9s&RSS-Y�����!�r:�qqx~�X�c�~!���;5mMYr���f#g�q��`�<��I�����5�����,{4!\\�
N94���{�{�v��HyS!$g�6�����������I����������o�6GDDD�E�����l��@�-m��>Ns?������466Z�#GtC9�����v�X/�}9�����(�qCD���l7dq�hrorn�C�k0���h�Hv�������m�[��@��b��6�9!�,��v��BDDDDo,���:��g�������������Es�s��e����4i����}�%;r��m@�<�S�T�=���]��Vcm����|j�=�����!;�����	S�<��u@J�g����o������ZK��9�������BH]��������c!����d�>k�,����(���Jkh-��������:7f��cY�b�K5�S�g`ZQ�������#�#��}�����%���A���������I3C��^y�f��UV8%�������V��t��V����=m���0���d�������%""""���BEeo��h� �.��j�<����[�������CKK�%;|��:t�}O|���~�w�f��� �}�R\\Y��K1�f��4�wq��il	����,�������:������{
�A����3&B�(0���+@E��=���!DDD�b%*h~���\o�����&L0���KS�[��y|�D���A?`�(��W2.(�������q����X�G���|��"|��"�����y%�js}�]@7.,�
ngh y��T�a;q�sB�l�$cWai�UU�=�A�DDDDD4"X!""���+Au���`pd_k��D���X�]�~��~�q@
<z���d�X{��p9<��8�m�������_]��%�=+cX�-��Y)zh7<��<�$|��l����,�s�(5��k�V�S���*�Y�wy� IDAT�����wk��������"""�H�����l��@Z�e�S����>����jjj���n��R���������(XJB�pg�e7��
�-���-�q@��L����W�u��r�94�`�m��d��<���N;������M�K��\� ��XDDDDD��BEd}���X	��R���\�������Z��:v��a;14��O�����������F���*�Z�w���j�4�d^a�[�����?e������1-R�dc?,��X!""""�B���("��JP�c@�����Az	�v+d��c#��l��2�HUJ���`���6f7��$L�t�2W�k�A�Wg��uh���W�uh�\j�2��Xs-����^���%KDDDDD���"""������m��g[�b��)�f��`���~tu��nM��=k�6��=u��z�A����%��s>����L�q�=�L3�m����|��Hr��
^�������9,��v3�2��4�
�C���o���O������������h��BDDDat]Gss36n���X���R�����c���HMM�3�k�.���	��D�w,��4
��g�Bj�����e>H�8l��+k��>�}��}��'���' ����5�����yK��8J,sB:[�6����:���6��HSg;�w��N�[�<��������F!DDD ��z�����W���z����������+Q(���w�}�u�:A��v+�z�h(|�bA@���a����(�Qb���������A���q6(�W���m�������l���sC�X02C���LH��2� ������?�
Z��$�Z}���uh��SDDDDD4�X!"""����G?��y���nyxWWW��_~���(���'�})���{���@����	�Z�����~�3<�����kW�k+J�!�E�2[����i�.��I3r�8�m�^OsK(�t������h_g����UW���A��iaC���V���4�
�����p~E���o0^�DDDDD42X!""�t]����'>|��������^������u�?�<����N#��������7��9���^jp���>�tw��74M��}��n�:<���x��G���b9��\�gv��$��_I��e	[D�G��,�Gqlm����X�
����(�}(���5����h���r+���5�64�Q��X�lzf���=�(��7�6t����&""""�a�B�8�u�V��������BU��|0D <�����e���T�^��������I����o~�����k���V]]������x�D��:�B���w$	/�"�D��x���R�'�h���>���
��G����~h�&��s�����2�C���!�+��m��x�v��O�E�X�k4_�DDDDD4�X!""��{�=0��Q�����
�����i$(�������;�9@i�G����O=��P
dY������� �u����f��~ig��(�/��e���'��nA��K�G����8�j������a�D�6<����v&���t��y�,ck{�N_xAy ��w�CDDDDD4�X!""������3�������q�o�?��u���W{4.^{�5�|>��
Y�!IA��i�kH�)hl���x�ErR	�_=�����S�1#�k���� ��p>�?�����){$�\^y��������d%;���6v#�F�;�������n��*���h\����a6�����#���n�������(B�����n�|>�|>x����j�7o6��Ys�J�A��(�8S������f���I�s>�#����m�$����(-�i���V�c�YQ�n��o{���CQ)���f�	!""""),��s���I�l�pb�`���B[�F�r��N=c��E����"�������`0hC>�������3���P�]l�+l>H��7H�K��#�
�|X�����*J��o(����$t|�jS-�x��,�P� �iQ�X!""��-[ 4�!Y�!�"RSS1k��/�F�����5�����4cm�;#����(����9��s�9��.y�W]~�Z�� ���|H�	��j��O���f�&��W��34������o�N��AH�0��k���oA����������	�.DiQ�'���DDDDDtnX!""��-[�Y�fAE��n��G��A�p�]w���A3
��U�Ht�=?BJJJ�n~��[�}my<���m�O��<{"#%��*#e��M�� in	��|�^��p��5����g�=�p��$\X������������k����@�h����E�����WfO�!	��{�-�)�$�m�0a!���h�w�}7����X��n$%%E����
�6��A��@�J{�������qq����GX�����{3�q;�?�J��CQ��,����w�l�5� y|����*7��7� 3�}��IX������D}s��UA��oAko�g����+����q��<@L����!���$""""��`!��������/}�K��iA���&M��>�[n���!4�`���TG�����q��+..���� p8p8�u�@^������E���o/7]�)xzZ
��%�#;m�������XV�������O��g�9��%��+S'�B��i���
���m8�r�qh`��OC=���W���
(���f�'aeyVL���W���-��a"""""&,�`��������4<�����O~�o���>=�[���\E��=�k�=�s�h�.�g�FE\t�EB�A���EQ�����PU>���c���8x���9���&��+��6=��&����`���Pq4l>�8����2����-��	�8�)�h� ����ww��w��y|��������b��z��H�lA�n�=��-�����\G�w5c��N{�������!DDD��k��^�p!�O����L�	�9P�������s���f.A\��HII��
UUm'Bt]7�bm����5]^y=���{�C�%�>���G�{�����S�A�KB�x����_h��^7�c@���v�b�����W��~�������t�������^�������@������h�d{������@ ���jc_YYi�R\��(�����c_J�[.�s����M��i�=FUU8�8q��
Swb��.�(�y)�2&b���Q6q��d�tm]Al:b�f$���e���Z���|7<�����c�i�k�y��
L)�����2I��UI����-���u)8����JDDDDD��������h\���F �o��x�
+���1��$|�W����vX�V0ij?���c����e�w��-'"�!������358�>�!�#���"�J��g7�����W}l���"t	C�S���g_�����$@���`�f{8"�������:�����!DDDDD�������(�-Vyy9d���H�/���U�:�$)z�AC?��2�u��bP��c��+,����GO>�_5��O������k;�#e>����h�����g����R���}���\�n��"�rK!U������u$������h@,��s��c�����m���(�ei��u��Np���p:��$�(v�	�`T_�t�-�C��;_0��u��E��=��4�w^
!�c�u���=-�0A�����5s��N4��CQ�7��C��+���a{�/AD����y�J���pT�Y�;ODDDDD���:�+�FGG�������m'(n�B�nx��2s�����q�-��nw�[F�(��vC,^�s��
��:tbN��:�<�bj�M���Z|=:������������Z#�Eap���b�K�����	yr����p!���!E�{�����PDSr<���B�p�o
DDDt�����>}:���,Y��VK!${���u�����.8�N$%%��v���E����y����4��z�XO����%�ldj�O�AU������d�B|��y5J�K@���CQM�-�����9H��wHZ���b{�y���[h}xz���!�>w��^�DDDDD4X,��s�B��y�,�+=��a�3�2�c� ����q���c��	B7A!����v���RSS�fP� ��k�DX��p�,����x������o�3p����U��,|��.LqYZ�%�K���c)��L��Y���}	"�KoC���G�7��<�,�)�G,�'��E������qJ����(�t�SDDDDD4X!""�������`�YI ��jgh-������c�������?����/~�(��|>�8q�v�������nj��:�����I�)"�T�$�� x���t�<R|;P�]{*���������u��_@fj�=� @���9�B#��m��,3Y��*���`bF�bGQ�u�>����GDDDDD�a!���h���2�������������l	����c�� A������J������7���m��k:��'BL����l���/�������:6�:p�;@���T��q�}X2�b{��?��?xt��h9����c�"c������d#�������Sq����{+��xqW3��|-����f���b!���h�>��?�%Cqg�2�bESQQa������Vl9�.^���Xg���Z�m�����$�(`ii�=<~5�Z,��h�
������Wo�1�|��P��\�^A5��������6|P��=�4a:wJh�iP�E.���/O��-�����X��?Y{�g�

B����)������{��i���I�k���:�
!�lG���3g�����^�>>�����������!5p�
���!Sr<X1'�g����B��r1!�����G"S���_��q'@���+����y���t_����7��z����(B�\il����dt�'����V������xc_�=LDDDDDC�B�8U]]
EQIII(++�����IwI3��y�������~�o��_���v�������E���s,n[���I�#�Sg���iXUa�Y@�N{$��������{O�t[�=���)��S_��#r�����u[-�����Z�}���z[T-��DDDDD4 B����)�|���r�",H�k�u�
Dz�?V	�v+d�[/����qU��5�����r�",�,�'�kO!7����_���x~}}�����~�':����=���#�m�g�K��iS��B�,�h�i�m�t�Uk���������h�u=���X�D�^7��+��y�Z���.F�����Lg�=�^=��_9+?��?�}�N�\�~��Ht��I��N�
P`�{y����~�3 ��CU�r���.���E�0m��[{DDDDDtnX!""��?�3g��;����v���s���"�yYX�|1c��\��F�����H�J�m���
hn��5�N�@^��<�c3�2.�G����{`���=4���5�P�D	r�|c����d
(�#�CDDDDD4,��C�� S�LAJJ�%Kqe�
���{~�_dY��9s��7���-G���j�Pt��Q�����>J�xh8��=w)�48=��)Z�m���XGwX2�s�"���~{&�)��JDDDD4LX!""�v�6���-V��J���\���������H�����%�z��$���k0�?����0�#I���	����&d�C��+��r|�\D�ua�=��r�z%""""&,��3������5�s��m�(�4��������kOT����}j�L{(���E�zVA�%CQe}��.p����qw�%�����_���H.�
Avt%���v����d\63��c��$���m��BDD4�TWWC�Co�OOOGqq���M��P1�d �C���LZZ

'���c��R0�4��IP�Q�3o��,�nMS�����]�H��OY�����d�������$�I��+��X�����c�8��o{\1;_���BDDDD4|X!""g�m����A����a��~1 ��m~>[��|�@��Ox�Bh2o3
������:e�9�8��R{$:A\���-<p����}�WU����r�'������Jq��Vm�uVm�_����X����j�~QQQ�V��M�!�$��w���q�������@�����s>��
$�$�����~?GDH�v��^g��k��dh_�5��X�����u
W�������1=���G���1��r�&�B!��$W�B!���t�����KY�N�r��8�2�q7�>x�zl���s�f�L.���$���a�B�t@
=Y
�	��o�=��@��x��/����"24���Y��!3�S*���_����}�$�����R����c��l{����������/}c<A���3��B!�����rss��� ##�����jkk��caa�v��j~�)�B�n+//���Zt:C����^5�=���?H�$�)"�6�Fp��>gX%!.#\�c������������6d2eyJ5
N��X�6���k
�v�����jG;��������9������~�;�������`c��l�^�����+���3���w:���t�j��q���4��V�%�p��]�`Q}���!�������X,466b�Xp:���f���HNNf���6,`f��o�IEE�v8�)S�0u�T�����������8��eY���?����Fn��F�T�


X�lG���'�$>>^�DtB���g��U���k���hVt���"����p�-�p����/�A$"�B\@��������5+:T�Z����3���\N�f�`����v@��?���]:�����X����em�e��[.sUkq�S����F��1	R�����/:�
����}GI�5��{�A�Y��^�"q	�O�D;�C1c�9�	w��-o�B�$����r�����f�}!��B���KNN�v���jN�:ENN�|�
���<�����i����Mqq�v8���=%A+**�R��a����+�����2e�v�Ek��e����l6��Y���s5���*))!::�A�w%��%�B\@��AD'R���8j&��1hq�I����?�\`�%���Ao���7���zn��'��	h(F3J�>6���d���P%e���>=�D��hE��>r~�c�s�F����}�;����|���a�����MC�9\;���2V
���w��y��KK����l����n�Z!�B\xRRR�����pPSSCAA�����}�Y��y���_�)�B�^����DFFj�:�����>��/��N�j��U,^�p
���.����6?�������������	o�:Qt.B!.UUU������d*V{��q����=Da���zpE/L5�������DQE��-������<F�����[+���������y]z��O.�_���=$��b~��MP����#�;������6������#�T���%{-3F�X;���<����`�����m�"�
$E���ovQ=�[n�.�Btw�����S�f��������ill������Ws�UWy���`0��/h�;���r�����~�T�233y�]�u	���s.����[�o�6m���)�i�.�B\ �/�bccIJJ���r�JD��w3K�.T� ��5�T�j�b�X�X,��v�(|R���CD�#x����F����>�7�����_W������w
���C���n���uG��C-:R��C�Qj��YW��\�9�FC�<}l��a�B���Q|��
�P��y�����th�u8����i��������;wz����N'�V���G=� HS��9��9s$"��B!.��A���6�r��8x ���w#[#_o���3��
w������{��r��H- IDAT��Z������jzr���1$5�E���Jj<��)�����b~y����I��>�\
������6wC���?uD;���>~����;+D��Y�����d�3���$"���s5TS��KX2����z
%�����j�:��Q��������m��ujI���f������t��������Z��5����4+~��Fy���Yxx8!!�{�UWW���.m��w�\.N�:��hT3}\.999jO�^�z���������J�]��l6s��q���p:�DGG������r/Ap�:DUUF����X��������TUU����S����\����`4.mz��)�������l6��_�6oN��������������������"''������IJJ"99�������b�=JCCQQQ���j�tB!.��}����#F�����+�}�A�O�jw�u6X�Q�F\.W� �7����``�=��wk�q8]��q?<n���*���LI�>S�&zN�����]�>r|t/����t�D'K������aL�	{�fE�'y&W[���*�kB!�
WC5Uo��YY���~r?Uo�B��1���Nw(��{^�9�Nt:�f����n���������l�l�@DD��{o�t�U~~>O=�s����?�_>t����[��7�|S��Q[[�o~�L&�������7���������O|��f�]233������y���wo�2Uz��K.��y�����m��������f��L&f����y��4�n����}��|�I����~���4�1���>��SN�<���g����=��3g���������>����W3}BCC����������JJJX�d	��o�y-��6�^{m�CEEE�������F���#G��u��'�B!|9rD��b0<���z�Q\�!��z���FK�z��M����%M�
V;
�� ��S5�v���9\U.�%Z��8�z��������.��.�����F������7cH�< ��mw�	i��P�O�t�
Bq.��R� ��a�v�|\���<�rss����{{�tm={���g����n�����{�z~���v�&�V�����^x���R������P��?���?Occ�����K���"$$���85p�p8X�f
��������5.�����
�����r�J^~��f�EQ��t>�
�N���6��t:Y�p!���� ��l�G���oAAK�.�������_~�M�6������E��PWW�o�����5�p;t�������m.���H�=�e��~�m^��f�+��<��jDQbbb����f��s;;�b$�B\�������a2�B�N��X�{�#�{����������@�7-����;�_���v�N�����qa���T��X�MJ;��i�=p�gh�P�>�IIe!=��.��8��qV�ka} �C)�q�|�.�c��C!��lq��-������m��<�V�T�hhh`��e��%�\�5�����?���L�4I;����j���2233�N���SO=Eaa!:����&L����_��rJ���
���/��v��y�������KYY����G?����n����v�mL�0�N��n'++�>���'Or��I-Z�o�[�5��p�u��d�~��3f����hhh ++���{���Jv����]�3�s}7u�T�N��?��O5���7�h1������w�
C			�~���1�N������#|��W�3F-�UVV��9s�����f��|�r>��3\.K�,a���>�T������K���������i��`����y������g��M����+��B}}uu5��_��_�f���k�%**
���^{��f�<]�B�B��w D�bu2�� ����	t7=��I��CQ�q�P@�)(��w'�����"o04�t�nD�Sp8��^K���TD�d5L�B�����@���o^���PP�����q��N��������������]�ZX���6:���B!��L���,�~�fo�����U�a�?��m�3`��S���R;���7��`������|222����F����.�����p�=7����;] �L���G�����d��E>�555>|�5k���c��3�����?�O`&!!�����Gyp^�!���c�DO�V����Q�HMM����������s��q������<y2��
S����1q�D���������-[|!�UPP��+���f���DFF����0p�@~��_�c��s�=>���F#7�x#���dffr��)�����������?����N���>�����y��'x��G)//g�����5K��Z�d��=v��7r�u�%_SSS���;y���}����w�B!��V���(((P�����fE����}�b�V	���c
��T��d�bi^�JQ5$P�Z�Q��>a����N�5�W(�f�E�83z�NO��$�28v�F(�/������:�����V)J����c�������4�J���
N��	9Yi���A��_�Bh4nzgU�v��q:p5�a�hX��Sm�}�m����!���c��������'h�+:x��z�t:	

b���������*6n�Huu5EEE����<����z`�o��������W/����������
�U�5�\�;���{{xBE�	�x9r$������q��1�t��Z�J
N�|��>A���%4a�5���j ����M�60i��fA�&���\~��|��������������� #��a�O�>\{���W���x�Y�	�!�����{�����N�H4�����9�f����7>�#�V�.���B��p�0���l6�����1�(�Bzz:�'O��h�n����uX-�
1�����]����Gz�����c��rH�'$����"B��
����L;P�V���Gc��_�y�4�ma":�@E����z��.� ���d4[��;�q��vA���Z�5���y��G���n4y��w����w���,X@��=������'�x���rN�8����}6�����[���M����2e�v��������R�q�^��W��=�5��p8����������b�����'AAA���Q[{��?p7e������3�7����o��c122�Y�sov��z�������q8�%�/������J!B!D7'e�:��}`+9}�@T��]Yq�	���X4�6]z;��y��Ag��+l����v�m/��v'������~>%��H)����8���o z���3NAa���Y��mFF�����&C�(��QrW}JH�v�)��ceq�#8PT'�!���'��i�%g\�~|/u��I;P��c�8O;�6:�8O���x��W	

�����������/��+���'�
7��?��.o�u�V�@H~~����[HHH�B���6=�o/��������222x��������C=�����b����P�M�_��"O���_~��_~����������cP��	�!����j%;;[=��X��w6H�h0D{��������� M��zjs0��c���`���=n����M�v������F��mB�L�<x�e��9�7!g#}\;�������m6�o7L�%������v�G�1�_]���Y�]h��rl�21
np3-1T
��>!B!�E����>~�]��~"�n�&JP(����.2Q;u�)���l�l6s�m��{�n��������<y2�z����;�~�>d���q����m����p���gM�i9�������t8��f�w�/_��e������/&--���JKKY�|y�I{Y,5�"88X3{n������
"""�k6��}���ZMBC;o��3%�!����Z������
�/�RSS5�D���Dw��X��e�>��#:���4F�����r���}��1}�t��M>�q�����&.�c� wU���^,��mZG2�����������P;
�����'���C�h����~���!I����e��[����_ND!�H�#��T�c.���
����7����d���������v-Z�SO=0k�B�zx��l�����a9�{����Y,5K�;�������/�����G�)1�q��1�L1���lV����j���5�������:v7rE-�Bt3{����g�����c��E�xJJ��f,:'Tz��w�F�'��N���R�	�y�v�VZk���2�r�[fO���m�!���=����gV��|��4�����+��DpP���G^�E���}iH�����OH�� �O7Hw9��"���������C��J��'	{�v����9����k�xm*��y��jl����p8�
r�������:��\�z�����o��3>�`� H{i��4Q���X�]��f�iV�;=z�P���m��H����^3��9}�c����;������g������i��p8���o����j�����UW]��u��
������[��)b������9s��B!D�c��y��������1��������a�����3GvNu�{�~�������������P��!#G�����{���f�h����s���~e���1�q1���)A���7��R�)�_��_n��!J��X�{�n|���[p�j�{�'R����bl_I6HKa{�;�&���Q}<;=�B����'����b��)�CqV��cLK���E��#�|R�_���<��8>��#������B4h� �8//����'N��e����Wy���??����y�f���T��'w��O�>�x{x��hhhXzj����_������[�[��a���(
.����������]������[�2m�4�����e�|������K8p��BFF, #�
�qA^x��{�=
����������������U�X�p�������~�z222|���w�v�B�%}���j�j������g��p�\�X��-[�h^):D�Z�q�8��������Ki���P���#��7ZV�����*(�m���%e��o'V�9�v�>���pT;�)�Fc�0k�O�����+>���u��T���V;����^�gH�'C%�H2B�B�;���y�\������_�M�e�w� H���df��
@}}=���9���O���jy���W��@�����5�k������@�����>������t�|;r��|�
��L�<Y�3�L�����l���"�����
��T���Gir�����|�ee����N'%%%��3���*((��O?�����8�)���#��q���l��M���_�AWpN2Brss���O:t(�<�AAA�����?��w�}�q��5����j�*����5�\���sQ�5k��h�">��C���G]k�Xx��wY�n���������>�B!��'N��W_�th�Te����f��t��~��a�6��I�:�q�t�q7�����yx�v������d41d�233���b��a>�rK��p84�S�V�!cH�zJ���9���khW��F�3��p�`l>�-�	�m��c�;�a��/[�.)c5�Z���'$����I��k|
�B�s��n`��-����e�v��������&��>�@;���������v���LjjZ���UW]�>��z=�^{-K�,����<��s�x��������:V�\�nL

�yH�AAA6��{�RRR������7�L||<eee�[��/���o��l���O	

"==����S���y3������		�\S���s�����Y�d	7�|3&�	�����[y��w�l���:����e|���������K������Z������.�����3s�L���[*++y��'����;v,111����������^�g���������PSS�'�|BAAW^y%���(�Bqq1[�l��/���?��O���h�'?�	�/��W_e���L�:���$�N'���,]�T}MWrN!_�5.��[o�U������%�\��U����&==]�*_+W�$<<�o�QM��1c_�5�w��b����_~���
����F��B��n��M8�N5�������pP__����������g��U��A�{���;���]8�Fk���h���!�}����g7�|���������?�Vj��Q����H��1�����\Uy~��
�\�	�d����wkV���w�9�>!}c���t�[�8�.70�W�>&B!��(((��o���^z	�w�y��C���n�n�/���g����d�����l�����>z��������G8p�;v����3�<�]��`�����A���������m[���^�z��w�s^�����W^yE;��>}:W\q����W^���)--����b���DEEQ]]��b�d21m�4���;\.~�!w�}�Oi��C�2j�(233���������`���j����o������7SUU������Vvv6����=z��#����/R]]�VE�g�����v��5���<��[�����/�h�}��r[��9�V�g�"""HII�o�Q����3�UXXHII	C�m��5--
����u;v������Oj5�PSS����)..�N	!�]��c�����5�7��n7�O��T�y��|7�#2���fS�`D�����B����������}R������l�N3�����I���u��6hG:���P�O��r�4�3�>}B���V~.��S 5���Q�c	!������q�(--e��e��^��?��7���������O<q�e������������d����`���J���?���l�:u*�z����W/���^����f����x�����!6�����v;#G���w�u�'OFQ����C=������9u��zn0����}����'��(���r��w������A�s�=��3���'������G�Np�]wq�]w�4_��y��Q�s�=�t:�����g����SYY��0:: `]�&$&&jf<�����0`�G�f�����|�p����u�����C=��U!��j�~�����4�Ukzv�e�������Jw3>���Mc���}��z#�,\�t�o�������g���u���{�1������y���uzG7�g�������kel'D�"%1��"w��-�k����kVf��z8��,u��s0$�����P2���3,���E!D���c�i���o�h1S�5_|1_�96)%''���j������3�k�����\���Q���$�A�3����s�=GII	%%%��fz��������~��~�+����5�����?_;�Lzz:��{/����:u
��@\\111��>���x��')..�����LRR�O	�x����g����
*��p�-�PXX�^�',,����f�EQ�S������b��			!))�o���;���;���:th�_���h���N���N�8A]]�������]�CQ.��R.��R�������h4�|��N��yU�wN!��j5��X,�_uuu>o�&M�T����o������1e�X�f
G���7���'��.m���!��$?oDK�~g����B�vkyO�E��Z�����"7�������Z{?��p�l?�Q=�5�f��K���T�@Ep/
�����{�����7��woj+����������3j���;�����D�'k,�TRe���ya`�5�>�+�����WTL?%�(��5
���S.��	l*�gv��M�y/
!��Ann.V�U;�&qqq�����e�N��0`�v�����G�o.���#.��
��HHH��"##[
����x����g��`hV��=Z�Zu%g=���]���Vm)����;-y��g����z>m�4~�a���������(	!�]��!C��w/�����w�N��`0�)����[=�t�M��z�QYM~��S��m��bsod���Lx9f���
wY7[��������u�V�?��n�`0�'"���?����o��8s���2(����-��:�����g���
@AE����	���
�?D
�Oe�0��Fu[��,� IDATW0�lv'�������B!���^{����o�v��7r�u�i����Y�4el���h3���_��om�Z�Ap�~��l������3���$!����SR~�����������m�

�j��l�����������.���;B��?kv@Q��X1�{�M��4���y��������7�����S�W1����q���Jp$��]
�g�{��������X,�l6\.���6�����E�fG�G��G�S�Rk�v��������e��\�/b
E�����$%��A���J*�����9e�e���tl����/��C$��}k����d�t���������cgu�~�!Dk$�L�k�'O���t��v���]qn��@Hxx8��o��
w}�������h��c�ES�7!��+)))A�����w���t�r���tj���a������_*���u��n�d���x���i�Uv��W>�=�
�M�~��Q>Ap�q2��Lw�AVV��
C�����>9���?[XQ��������9K;-~�go/�w���C;�aN��/jG��ICf��
o���Z~<�g����T��u�8����mV���5�]X����T!���O~����:�UfE!!!���R���}��=
�;��$))	�#G�hf�u�����PMA����B��]����~���7�pxJ�t:�z=��������?����8�*�z���{�����b���U��_�����bC�h��&��W������7��}��pg:i��kG������S�,�S?Fo��t��[��`�.0�\[�3�h�����,��Oy��L	�D��������m����nB�S\������B!���`0BHH����3r�!����\.�����������A\\�O $33��K��M"""���/'N��Ia<t�����7��o��'O��WVV�����h<����B�se��|��X�Vl6���444������O~���S[��%��*7x��.�w�w��k�v��2��]:�{��<F3��)**���T=��O'x�)
��
bzZ�����=0(6u^�e�ca�v�9�y�R<sa#���7%'$!���jK�W�
)���=o��L�
��p�{�bw�W&��B!��0�;�E��h�"&N����U��&�����Y�v-�������#**��k�RUU�����N���X�V^~�e�v;����y�����3g���y��W���+�Z�|���q������������~�����K}}=k���b�p��W��i%�Btuuu,Y�p�N��������b����	

b��e���KdG������"&��w9'<Ym���IF#�$�F�M���HLL�����"++�������K��1}����g��M�!��W���	�r�W��]�)(Lr)���}�X��n��
��<��`;���^a@|0������z���B!�B���d������c������+X�d	�~��L�2E]g4�2X���5s'M���w�������>��O>!$$����w$&&��m���d��q���������'�����u�]���s���B�.a�������p8|� �������N����,V��w��
���{kT\���>����tO�%��X��� -1�kF�wQ�RR����mW6��<��c�T�5�a�w�7g�I��(��m���:��m�VB!�B_��8���4����PVV��j%..����FQ���?RUUE\\����3�>}:�N�B���bI�{���{��G;LHH��s���/(--E����G53E!���rssw��%N���tS�.��*�y��aY,����:�������e��>�o�����l�v;������	�t��a`��)���!�Z��.e@���F$PV]�[��1kl���u	���p����U/�}�!���"h����^dHR(��t��Eu8]p�Z�B!����v���������,��h4�
�4��t$&&��G�� ma2����'			B��56��V���n�k�4���e�*�� �=���������p�6Jo������n�n�X�rGJ���&���X������
���s�E)(\4���r�m%�\�z��x^
�8kK��@�'OR���8�Ox�"����j����d��j,vw�[!�B�6
B!�������6���@��;�Q�>V�1�w���2�r���k��I�����S����HZZ�z����89X�)����^��w<��Xmtv������S�P�5�_��4nY�V��vP��\��K]�u
���D��~s�_�w���9Nq��k�B!�"����!���;v,z�>`���(jV��1-���wY����@Qt�w���Gh�hz���\��pb�9��z�g}B��?H�=�s\�����.*��"Ccp��l?��f�/���X�VA���M��4|��v�GA���v��z�>P����5<��Q�����B!�B4'�!���Z�l��p;����C��G���a�|��yv�i���������.`fT/�t8���tK��r���C����1�s�����g���Oy���-N��q�.K�����\
��������T.kh�;ykc!���V*Q!�B��B�B�.�_��k���=@t:���a2�

"88�NGtt4��zk�@�8���A"�{����%�8�]�z���/�9w_��x��������g�m
�������e��'A�S����q>(���
�c�9����,����}�Q�\.p:��roye�8No�/����B!�4	�!�]���� Hcc#


�l6�]&�`0�������������E���Z��b��������F�c]��K���1������P��}G����.��{��<@�83&�\�v��w�G�C��	��ac����n.k]�� �2B�S�*�����3G�B!�����B��|�����f��t����l444`�X�Z�X,\.UUU���z�\t�Jw�
������e�N[���������;�c}���(��5��������X��w���|h���wQz���i���^�>o�9�h��H����tQX��F�����!�B!$"�Bt9G���p?n�r�p8��v�$9z���:��!��?�������w��F��NU�ly�@�!e�z�iii��#N�]M�{\!��)	B�x�+�
����x�w3g`�yz����)�����(�=�&��)q�Wp:�L!�B��B�B�.���]3�)���ty�E��t(�����DM�wS�=�G�����0����K=6&�/b2�HKKS��Uy(@j�B:���n�0 ��x��B��-�:��f�[���L�a�Bf�t�R��:�����-���
�!�B!<$"�Bt1=z���@Z�������jf�yU�
���c]Dt�� N��-����C<�����8+���6J��]KW�G�s��� Z�0�Lr:��������W��}l2���{(����\J���}����������B!�8W$"�Bt1#G�PK������t�F�����O�I�k_������]T�����u�
�H��ET�~����N�.��k���J}	)�v�Y�iD]����v
��|�����=�.;m�f����<q.���]T�v
��Y�!����r�k���A���m���,!�B!.DB!����g�^��d2�h��t:L&�������)����y�/�� �e��{���]4|�������rj>xgm�:�			(f����<���<1�U�����9`"A���7Z��}t�f��q�D"�)a�^"x�/A9}��C�h8���������x��_�vH!�BqZ����B�)s�w`41��fL&&�	����lFQ�
���^�i����@�&�y7�h�b�,��Q��Y�a��H������EY�{d�z^Yp�3):�>!������}t�NAF3�z��o>�r#x��i��_v�OS����`;�W���������~
J���h��B!��4	�!�]���Cy���������`P�a�t�M<��Cj��Aj�����]0�O���f�C��0���w���[��\��`Q=������8�N��9�`s�H�~?��
���W���g���4��������5���������������P���4nY.���YCc�J�Gl�����D���B!� W;6���{�n222��k�v��8y�$dddPWW����B!D�f2��Z=��g��M��}:t(aaa^+E���9��,�������6��5n^J�����~,����������9��A��KEGq�`�,�\��q+��
��@�D�l�7z��z6������v0j@���Q�O�;w��>���e������e�#��WA�{{�(����l:\�����n���������l���B������g��1��5K;�)9.\���;v�v�E���|��g��z�q�F�v���>��N�8ABB�G��Nw
;v�`������������\1!�]��}�����xn��&L� A����Ap7/��r9�|��b����fpj�D����z��pF�R����G#�n���� M�p�p6hg:�`S#�[�[��tR��|�Ao�#�i���vp���x`$�%�����^%�	�!���JKK��w/6l�NuJ���_�M�6Q]]����t��[o��/p��!�9��={���PXX��jB!�(�@��a��fD��l�����n9tr�5%�P��O3MY#����4:(�����"��N�Zy���WN�];�%L�*��5{=��w�����������M����	�^�0(>�+�c������[}�D�B��f��5�\.�9���'���J]]�=��7{��������_��o�����<����&��^��Gy�W^yE;%. B!� ����������=MxE'Q����������L�WY�!I�iO^�bG	n�@Nq�zlN�����k��8��W�Kc�U�?�#]�����uz��+8p�-h�����{��a�v����IQAD����)n=�(�B�I'���p8X�n�z��w�y&;����q������������l6����K�����/���A4q�I D!���rss��w?���<X�Bt�
����@���}]��r��e��k�E&z�h�i���f�8X�	����hO� �)����#-k8
����1�Nz?Ops��������v�E��|�P3
�����9P���:��66�B!�8�OQ��?R��l�����O�P�����3�K;���;���T�7m��aM��E������{,X����R�t�233Y�b:��|���� �� ���B�.������	
��M���J���3=�����lJ���v&����Dj�<�~j����A�eh����N
%j�p�V���{�4i�:/:��=�@.�\�Wk':��� ������k���~��h�����Y1��C���.�v�����j�y�� ��������Xt���B,�+���\�����������l�|�\Bf=������RQ111���S^^���{1b�������bwy���P����9���zJJ��\���������������TVVNBB}������?����w�}������6m��f}��a�Z��$��V+o��������5j�f�S__OMM
��:j�^ZZ����`0��[,*++	

U�QZ,8@EE&�����#T��"##1��?~���<�N'������b6�~T]]��C�����h4K����������w)Q����W�$$$��{s�\���Q\\L}}=4���&�'N�����n'))�����-/����;v������III�G��e~�\.�=JAA����x�0B!B!D���A�bu6Nh85[=CQ�~����^e���"*,R/�<�3>�Z��7����|���bw�Wv����B�W d���8��6�X�s�LJ��7����0������\N*jK�9�EZo�CC��8����D�s�v�G�������X��{��������l����+�	2���B���y;���)�������<�>��yQRR���{�;w.������l���'�t:�?>����8������6�������/x�����v��e�����_c����0`�����+����/�lDs:����0w�\f�����+�^��+V�Y$����k�����V�^���KX�`zJ�z{��g)..�w������xff&���0`�<��V����>�bq��k2~�x����fA�����7��{�6��������K�7o�����&YYY,_��o�1����3�7o^� ��~�SN�������7��N�c��%�y����_~���+���U�!C�0g����}�������[oq��a���={r�����_?�qo����'//O;E�~����[Z��g�/^LQQ��xDD}��������B����������K ������;aSlM�������q�"��'��"�&�!W�/�7=����!i0��|�i���)���j��t��6��cf��!j��������8�"����_�f��7�]ADH4C��V�7{}4	��������.�'�����>��(��v�T����!�*��B�g����Ng(4lxGQ�f��hj�n6�?~<���`��m44xzd���0y��whii������7���&%%���4u��_d���l6)))jfIS����x�|��f��c����_���.���f��j�*����;�������#,Z����c�X����	zl����_���-]����,BBB���S��5k�0��f���������Z�VV�\��/���l�N�k�Q�iL����7�n���b��,[�L�������G�F#.������l��f@MM
�<���d2������,��z�j�}�Y��&$$���x�=�������'V�^��*�5k���?�Y
���������/',!B!D��~��+""���{kV����8x��\�:�a�E0t�jg����CW�P�/|��,�B��i�`"����OL��sh�7��*�5(!���10`��;���
�y��!b"T��C���d�t��`_��X�m�?���}m�=������Z�z��(��������p�v��U���$-��1��D!����Nl�6�jt�;j/��}8+��8�����Wu��
z���P����9��_���c	

b��	�[�����-[�>}��~��Yj9������1�s�N������������={�0h� ~�a����y��7q8TUU5�v�2e�v�M�n���}F���u���meee��o_�M����;M�d��5L�0��s�������"++��^{���w��U���������^I �$@@����XF�u���X����e��8�����q�QQlc��cA�t0� 	���S����}��)�����y�g��}O�9��^�Z���Z�n���#G2d�����4���_���S1�L8�������/
),,d��e�{���kEa��%����,^��3�<���X��g���:UUU�������s��gj����[���[���{��v1r:�<��3<xpo:�����?��ng��]|���t�M��^

���og��Y��fjjjx����};


|���~��^���s'��/GUU������DQ�N'�7of����������2|�p�{��{����/��*6��������>���@\.������_n��t:�@�B������������=qau�ue�
��v�OW��hM�7f{v����#&<^7����c����&]����W��`�833�+�x�bmN��!�v_hm_�|i������>����e�E��0<)�kM���P��i����x+�H��c�y@h�A����Q��y�B����gig]a� IDATZ��q���l�~`�q�g��4"�x�K�`�M�[
���������k�!����������e�i��W�������Zw���_�Z���=�����_�������Y�p�62v��4���};[��7W���Iee%;w�d�������& ��z���7o��r�v�(
������/g�����4SG���������k���	&�����~�;����������*�4s�L��Kdd�6����	

���3�6m�
�t������ug@�?�x�+k�j�2i�$&M����l6���?0h� m,<<�_��W�s�=TWW�e�n��6�^��tjA���h���?x�!1����1���8y�\.�|��0r:���������d��`�O�U���Yg�EQQ�~��6~���XB!D?���W:k{;�D����-�AZ�m��g�����Ja�!���5�>��g�n��q������3N���RO��tC �U^^uu�f���D_	�G�2Y!�a���STX�W_���c)V!?D���:l
��������S�����8���j���B!g��Ln�:v���"���$=,,L��`�X�8�]�2''��R�R���{.�n��q�F��������L�����>|�W��VS�x6+9rD7srZ����Htt4��>W_}5g�}��~��m�������4zt�%���EEE�om�����y���"���� zg�q��W�d?���E��ol�t��DFFzAZj�m9v��6�}�v�}x�e�u��}�����a����\.�]����p���A=cp�t#!B!D?r��QmgH �����3.��	]��^����8��l���|��W���8����i�������vow��cM�8�����8���!C���V��;u�Tm^��Q(y�8������a�!����=Z�G�'��]Ncc�J���Wy�V��3����J���c�v��p����bj�5;c5wm�B��#��_����M����-��4��c��^�Q�l�6u)(��;�o�>m�4���S�Ne���������e�]��M�6�7�x���j��Y��y����k��r�0��^��������C7sr*++��#F������{8����������*k����/$99Y�����((���m�h��N�q�}}����SZKS9�Nv��ANN�����v
��f�����6EUWW�����5j�������>���9�����36��k����LMM
���l��]�����7	�!�����(55���������hOP�'����#��9����������4z�>���$D���8
��:���K���w&�H��,��� �����?�����H ���!�u������4�ps5��{@m��A�i�x�����"����iX��(X�M�!��������#����a1���?!����#	��Y���\��T��bP]>%j�w/���W~��I:���q�g`��hnnf���\z��Z���lf���|������R\\Lbb"�)�5u�T��W������HAA����Z(,��������T���k�bF���Y�X�n���y�f�,Y���������'O��@���y�����U���~�_�
6��o����;�@UII�v�Qi�����N�����y��DZ�^ksu��Ljj�n���@�B����b�w���a6u�"_��������� �BGw���<��c<���(&���X��g�)	�+}���OY�V���^���n`E_P����� z������_�?��LbxR�����]���2���8������y����H>�}�����^p���#���B!��d���H��e��6,��c;�g���o�KZZ��|@@&L`��M������CF���a����������W^IVV���[�$���������)//g��u��3G�s�\��?���O�����j�d2iY*�?g���'�n�:�m������������g6���Is�w��O>����{pgD��=���t���)//��O>i ���zO���.!�����9��3}���X,����L���`�^{��@�B�O477{����X}����9	`i���?kli��/�>~��C������o�y�w�t����P��] D����1cPUU���!??��vq�.��_G��j�����g�����k��M����lO��X�Pl!����r�(�s�f�	�\>9��7yv+)
�*\7=�� ��B�����`?��x?7�F��)4��%��e�N��IzDD�W��~'���k�!���L�4���7����s�Wh� #F�`��Q��V�\r	[�n����e��QZZJff&


|��W�n�3f��L���jkk��l���������n��6������Y����������$''�������Xm`��u'��?�����Z�
���o'44T7{b��������:B!����\-�700�#FV��VPI~E����S�����e����F��j��Z��+N�����r����&wF����v2BBCC:t(yy���O=�111dffrad�]k2-N������U�m4�_L���[�����;BRL'�8�	�����o�qx�	!�g�PYo��=��$U�������
!����_�H�o���y����J���	�����&��&�������6n����s����{.�7o������7�i�&��;�=III���<��sTTT��������`'L������5v�������������f}��fz��nw�V�����]&��o��J�����n�
}O#��m��JO��


��{�������������O�g4�I D!��'�e�F����!�{T^Z3����NpSaK��?G����C��N;��8����l�2x��"eyv��F�vG���{�n����(,,����������k�z���w�+�#�k>�{7j���.)fC�Gp����fc�*�����"K���@�o}BL�;�c��p>�VFvq.��
��{+8P��
���&B!N&���m�e���ZS��e�L���I�$=::��R������������?���Kd��1���PPP��e�hii!""��������!C�0{�lV�X�����f���:t(�g���t�F�";;��AAA�6.�����qk�����**��>s:��nr~�l��Q;=z�v�����k�g���`Pg���X�����k�P7n�Vn��u]��5�����y�f.���
��NR!�~I�O�b�����0�OtzYe�t7���e������&3�C������(��=�����6$;;�g�yF��r:���v�N'����4����������x��j�c�G�����k��N��bM��;�w��������\99�0[���}%
<�I�����!�BO	% c.��K	w^�A��I�y���������]w����k�f��s�9�������z�������a����n��y^�u�}�Y����	�^��/��B7�f����'N�\;tEBB�v�o,����RSSc�5��o�����3gjs��w�^FGqq��l��l�7]x��wZEE����Y��������_�no��cCC����T�2e
����Y�������`�>���{5~�;�f�A'w�B!����H�t�3���>��@���"=I�����7o������M�u�,�
d{�f����������\.inn�n����LSS�v3���o���,zX��t9���]�H�1-��?X�Mi�Q�l[��L0[P�M8�s+:��p���
�n��f��RycC1����SB!���7IW�3fVx��� "���h��=m��3G��`�XX�`����������$44����={���Ox���y��'y���y���(**2���6Lk��z�j�-[F~~>���<x���zJ{h�����,�V�����>��C***������������'�^�3>��#�l��]������OhA��K�j�/��%�|x��7iiq�qs:�l���?��ZP������N��x��������tR^^��]���s�=���T���z��G��euuu��Jyy9_|���?+V��^w��V+7�p���t:y���x���)))��r�������Y�l��w���^�>|8��M�?��~�/�����2\.555|���|�Y��tt*�
B!�_�������]�9�Ie��<�{��vW$@�� $�}���:���$��|��[0�b�?��[��(���Ne��Aozb�n��k�5�����f�����������������n�Z#z�m���:O��j�2������3��cG���M����C�`I����]���[�����(�=q��
����K�w5$%�B���[�j��������1���(
S�L��o�EUU��[��������@�����_��i�����VJJ
yyy��o3��m���+Vp�-�p�Yg�����o��G����U�V�jU�����h���N���l6W]u���
����e��Y�����L�S����g�y�8��;w.�����\��u�� ���~Kdd$555477�Yg����kQU���z��n���7��E�������� 77������\rr2��_w������SO=E~~>�������oY�dI�{�M�4��n������p8����������w/�����k���o������<jkky���y���������t"!B!D?��"e��D���kn��	�?�&O�^���<M��3�9�;/z�8��c0):��xy��e���|��i#<��Pkjk������.�������pO��OL������t]V�/��,��X>�	X��������(�j6!�~E��E�L�x��<�y��g��6i�$���:
��f#<<���4����y��Gff��S���_�6�Bdd$�>�(g�}6V�;S���(L�<��{��7�-\��[o��M@(66�o���-]1g������$''s�wp�-��yX��?��
�������p88��3x��G���[�9s&���v�Z�����BCCy��>|��8@ee�W���{�1.���6?/pK&O��}��w�� �������>����1�����fF���7��W\�5�C=�E]��Q��y���\r�%�L&L&S����@���Q���V��t�z�j��B���������3����w���|���~�gt���8E��aK&8��]{�� ����:��7�o~����+.W��w�
��=�>A������OX�2��-�J����(kr�7��3��qv�����QVV��n��~/�ol66��������a������?��0���awvN�c��e]u���x��1��v�9]��t�r�;��e��e�k�/����:��s�Q���P�#���J8�Mi�����e�;��)L����/N���B�*����-77����W�X��o�
�w���9s+N^ss3yyyTWW��a��}2TU������"##4hP�?��i��_���;�={6������b�X�����c�HII	���������uu5eee:���0���TVVjA������R\\Lee%��Nbb"fs�}�N����=JKK!!!$$$�xq:�=z���:���INN���q:h�w���	!��D^^�1�L���V���B��'���b~A��3��S�b����W���/1z0�g\��3���P�o����X9%�F��� �.y��x�6Z�(�8�[�w�����]���aI�^e�6g�yS���ker�;����
U8�a�f\��������������B1��� �e#45�L�-����> �R����{]lll��\���EDDh�c:����nVJ{E!))��$�
Y�!88��#G�}b6�����o�4�B���e�F���.�Cj�A������������Qmc5
���/�3���5�����y)
��^���N������Aq����Q:x�����Z�[�^d��=�c�������PP��1O;����n�-%0s�'P�Ky,��D\��� ����[rL!��i��������>������$[ZZ���O�s�����!���I?S��8��������s��R��s�����~6���pV���;��[u=�"���
j%&��f2�E]���+���X��v�c��f�����K
��W�-�aO��G@ug�����G�������Fw9���l������(�*k�D���t}����&_jX���i�|���8����`��$J!���_|������};�|�	'N$%%��IYY[�n����q����,!D��|��B!�TCC��%�����>�WG��M��������	�8{�A��#P��W�8[i/��~��_`�Z��lZ�?����j��a-\���x�����b.��P>|d�� ��~*-9���}AT������,���qv2B~vF�OYV��Ms��B����hhh`�������|���Y�F�L�2�{��?����$#D!��cYYY���JXXC�1��������_O�'46����&�|����YG�)��������i��������� Fs���������������Y!�oA����
�����GKQLL����[�`c�*���������rU�US�)������/����o8Z���@���Ms�!� B!Dgf����i���m��o����TWW�(
QQQ�9�Y�fI&H7Y,������[�=y�	!�~l�OS�1c���Z���E���Ewq����=���TXP��L0�p��2B����]Q��$����2#)D7�����<y2o��&���455�r�Kx���q���}DD/R,s1����P�B�WF�M�	��9�#�M���V���b1E���(�����gX�Vr��'����e|�SEM�w����ChhqR��$<�m�P!�f��)S�0e���8I�&Mb��e�a!z��
!�~JUU����F������H���G�%}Y�)�gc6�}���*�UU���w�wEnI��:<�B�;�###��/���>���Gm�X}(�u����/X" l���j��x=d"���� N��-9��
�
}-���WK'����i\<1�kn��Z^YW����cMnU���!�B1�H D!��S%%%TTx�KH ��
�G
�O�D'��G3�����O�����p����S0���f}�/���LW��bccIH���{4E7+�F��q��
��S3���7ew�����s�=���5|���8@C������M%�)!�B!NB!���,VJJ
�Y���a0�G~:�����Q0�{���8�/�:��f{#A���~����/����;�����L�x�B�S���L�ZP����i�?��il���z�gO9K��6T�f;��`
�t0T�/w�
2
!�Bq:�@�B���e��u���DQ\�9���1����1�3�O�T�%g
�o~G�8jVK����N�Qz����r]�S�*�����
�1���%g�n����2�N���8�v��[gX�a�J��������vL���������z��w����B!�8-H D!��C�����\�b�#���=�0�0����LA��~�H�~��&~���<�����Q���~P�Uw�����u�$�����6�t���hX����4,Mv+0�}�3<��<��ler��\�g�
E��������LQU3��|���W�@C��8,�B!��'�!��������5j�a��s���
����:�s��m=������"�`�q
��V>��=_�q���2�'`����]V��tOZB0����t�f�������3�����`
����������f�'��H_K�y�LU��8tBU
�N�B!�($"�B�!�C���tmg��#�_{�C2!�{��Iym��������v����$eU�l���bz&(��`dy�K���J�I���#��>R����h�3�O'0��>n�7����
�P] �hj��!�M�� IDAT6�q�C����@��D!�B�~$"�B�!�C[)���*t���s=�������pvi�����_�?��S�(��T9P�y�;:)D7�u�>!����V7+�B�T0�=������~�j	��Q�~A�:�z1��B���,�8
N�K���Q�A�6�}[/�B!�@"�!���TWWSPP��K�t?������@HmCJ|/�u�z�Z�e���j������6J�_�����`11,�{�AZ
4��`O�-)�����������f��cm����]��
�	��	��/���&����5���
r���B!�b �@�B�g�kcbbHHH��
�P��u��&�<����)�,@���������(��;@u�V	��;T��w����Xi	A��� �8EQ;�T��X~j��	�8r&�-
�:������O�o
�/��� �����935�#"��B!�B�$"�B�cY,���D����.�S'!�	��j:!�9���n=�� �F��'W���$O d���,[���?����r�*������-����6kF���;+��/+���	�767)p��!��A�C�Ec��k^��"�B!��F!B!�QU��~�I;��X~J�(}wA�n��3�K��`[(q��?�W��n�q�T���!I'�(��t�_�)d����q#}�>� _|�.�K�
�'B'�%�}�:��{��`z�'��%g
NW��x,�c��0��fG�+�j3s�����R��IJ�;��(\55�En��B!��K���B?r��a���%�L&�G�6�}�~j�Nw$�&�/�5��Cg�;4�b,f+js=�"��Zk7��,k���.�e5+��;�,UUy���|�x�iii����������?d����W�^��!r��|����6��@}S-{m5�8��%e�v�2�b��n�3�'�'�x�����/m4�B!���"�!�����b�1����{,z@�J����!����;��E��",(�8�F|� ��w��]p<�B	����_��l]Y�qAX�'W�g��-l��UUijj���Y���������
��s�����y�	Y�9 �m��1|�v�1�;��7}0��C����M
i	�?rt�w�B!�8I D!��#�F�R�O����.Hj�> �p���o��$E�������~��Uk�D0u��2�X_�������G}@KKK���Z3D>��C���uQ�@H�N��.�F{�^6�|�Km���vg18����WS��	����U'���)/���#�B!���{w�B!�8�9p��v>v�X���*T~��
��Xz�cF�h���a����t�
<}�[O�����=%~�[��R�-�7J?�� ���Z3t��i��h�;z�(����Y���GC@���j��x���~6&�}�U]_I����,�G�7��UU�Y�C������4���O
��;�����kEm�B�3�����}�dTwQSS�)���s�B!D�����v�������jX!�\C64h�{` `�����E��e�Y7hF��\�jo�Q��b�n�����h������>�QSS�n&��������(TWWa\"z��.�U����j��
��gaA�:��y[����1�������WnAmt��p9i\���B�����m���bRp�TZ*y�M��?���B���}�]���hnn����\.���$55�)S�0v�X��R�/���������5�9s���+V0w�\�O��_�'V�XASSK�.5Nu�������{8p��z������}����SRRBJJ
g�q�qZ�������?�p�B�9��t�+,,���^"00��o�����-g����g�}���{inn�l6������sY�`A��]��$"�B�	}Y��.�E����"t�����������]����E��/U�(���NW��Xy2E�B_�gd|�����BB���/���5aaa������h��Z dS�w���^��Y"
+��qD���7	��`OS��X�
#���9^v.��^!B!�^^^��m�A���PZZJnn.�|�
iii����$66�����lJJJ��>|�v\YY��]�k�1c�h�}��/�����f��Y��N}��w�������k�U�Vq�UWV����>��c^}�U���C``��7}��������?��k�1�p+++#**
���="����x�����@�N'��������������)|srw�B!�8%TU�j�.e����?Q�z����������F$2,)�����k�l<�V����*����~�V�tre����DQ�f�qZ�:��^������h.��S���2�*j��w�'���h�^
���v�.�~x�8�.���5 "�B�C�e����?�a��a������\�x�	���u���(
)))'����UU��7����_7N���_�K/���nGQn���^����k����	0��yIII�qbb�,��{���?��������F�t�m�����zUU	

e��%�q�\|�����v����o��#z����B?PRR��c��si���\��}��^��{������mSK��Qz��8]*_����=��lpx���v-��EQX�x1���:ZI���������="zX�0
M���U� ��W�{��1d9����A6e�"-9��/��������C��H��rr�p�`���B�~����'::Z;���l���W_}���&JJJ���o���u���X,<��S�a�WQQ�?��~���a�+v���k�����p�
,\�P��������w�^&N�������/��	`��I�i��_���T���Z�*$$����O��s�����������[.��"����z��(�B�6v���2���p���5?����jSD�����
(��pM����4r�q�{�$�������+����6A�W���.OP���������j�b6�1���.4a��N�jx��3��=��<����1k**jS�n����<YT����x�������&�
!��������~��u{�������/X�V�:�,���zml�6������r���_�����[A��JkI��/���� �Y�`�W �7)���3�
������k�/��R� ���/��"�4��u����y�"�B�)��T|�9��&Oj�@�st.�	@xpC&Vx8�f����"0[��t���{�_Z[�������.�w6�04&����{��BQ���N>~n.+��b���49��sX�d�d�����P����r�w����L�������UG9T�Kr������#��xh��bbhl J�����z���n�n!�����X��_��������������	���Q&x�Q���t3�����y��WwI������x/��o�A]�{s��	���++z���j���*=��*����l6-�����{�RYYIHH��'..N{
��������222�-�USS���Ull�V������j�5���44xJ�FGG�{�p"7n��!s��1����1�w�}p?X�@WV�8	�!�}�����!����S�F��?�������s0o���!�&K�X��C?��fw�o;�_��(O/������6���&od���l�?GAA999Z���c��{%�P�<�q�h<A#<c@Lx#�e����;+������.�O���i�g�e$k�������1�Bq:r8�<��]��5�������y[x��/0(&�0�����Rop�\�L&�=�\���
JJJ|�dgg�i�&�����;����>UUU�s�=^c3f��W���v^WW�=��Cpp0�>�,�w����_�8�233���[x��W������[xx87�p��M���wX�z����O?��A���y3���?��z�!��Gy�����$�GUUrrr<x0����n������HQ�f^
d�o!����ov�p��1b`=���P���=�!-�fr�<�����H���k�nM�-�|mn�q�C���d���ehL9W^y%��w��y2WNu]`q
�������<����P�"�{�OA%8���n2wht�'�*�����2�B��>��e�gU�����������R�{�����<�8%%E7��
4����������ep�X�B;���k	�������y��}�Y�����������:���#O>�$;v��j��wjjj�����|�(
&��+Hd2����N�����fw���Q{{Z�����fDO��!�����fdd`��?�~��[��-��A����f�N��{P@0��M1��q���5��(=��x)-V63>���T����������B�T�|h�rW���[����������PX~���<R����u8��to�5>�PL�,�=JH�q�Ci	A���kvRX�LJ��3��B\�UG�x����v��f����{���S}������{O;?���u��Z{n�',,�3f����1c�C>9v���1��n��������DBBS�N��s��
6�j��������pp�}�����w/�F���[o%99UU��e�?�<����(
K�,a����l6X�|9�����r������^���\s
K�,a��|�����9s�0g�^|�E-s����?��QEE�v��uZpp0�.��t:��]����!�����KY,?U�/��������9�����fa�t\2�Y���|<[C1a<�{AZ7��'��?c�������[!�\�|8�w�q��������Q*����U\>�&���k^����`�}��B	��?��t����3Cb9|�QzVQ�B���;Rz��|��f�J�U��u)��������?5��l��h�����^���#>>��B]]�f��
����>��HzN�S��a����w�����k�v�]UU��e���kkk��?�V��w�����^����d"..N�vp")))<���Z?EQ�:u*��������{��,]�T{Mpp0��z+{��������l�v��5BCC	

%((H{Mohjr_g��<og�[ZZz�{=�I D!��C���k��G�w�X��r�c�Z�|Z�	�b�����@����<%�FV����$Gv~�qqq$$$PRR��B�����H�����R"�eP�B����F��B�Vr����@����MZBK��������%8��A�VI�Z $���s��K2!����Z�w��_o�1uM5d�{J�v���=L=���s�y��w�C�I�&q�]w�����HG����<����f�1}�t
Duu5���������b�~�i�x��n5?�F�����/w6l�0����j%==�M�6�t:���!&�o{�9�N��D�-}�-����=M!B!D����, !!Av����=����N����f�w��;�m��b�2q�L�
o^��S}+�0kd����� ct�
N���L	��3k�N����Z5 !�3����8\����|�`�D��+	=�����UY���Sx�wqf$��w������c#������l�����b�@7�.(��&��l6��0~��3��V+����qx���������y������?���x���������5k��p�Bm~��ml��Y;o5n�8f��e�q����>z:���g�QPP`f��EZ�F_��D��~> ��,|q�I D!��CR��g��M��Vm�^��HKP��nm�T��Q���A�N���}U�wi�ep��$,'�	����LV�\	@VV�Cz�����@H��:�1�\�f�7�����`c�w\2�z�5��LQ��*p�N��E^k|���	*V7:(�n!1Bn�����v�/�z&�M��)��?�_l~�8����S�7�{=B,&g��������>KHHMMM���l����INN�O���Ecc�v|���{A������/��_`���^�����v�';�Uppp�B|�K��T��kW��'O��B���[��w���p�$����O!��#�����
��@����2��b��l��N;��I�t�Y�������N��vNQ�����W��2� �F@��b���s�����X,8���9p�����e�/�#<�5a�Y�@��0�O& 2-c�[���Um!���h>����@Hx���H��?wYE�B�~����4j�q�g�G�gk���V5NyQE1��s�fh�(�t�S���@������s'


�X���3g���l|�iI��b�������'k��#G�x��������5��;��������?�����������GGG�j@GH D!��3����v���9~�����Q�]����XM)����H�<����1'�D	��
R|XO,��>:@I�{7*�
��	�J�$#���l�����O?��X���#�
�3���G���q_@p�7������@���?Q^]LlD����3i��o����UI�Z $���yQ�B!Nw-~�G^��8�QPPQ�t�/�$b�UW]�+�����`��e<���� w��V!!���


%00���&�����.\��!"��v�m��6���ZK�������j�����+�gu��E!�=F_+==]�b�Q�:p�c������>dhl:!�p�l[v]k�b��M
������NK�oW���%�z<�J���^���#e��k:����y��� 5q	Q�����c+����� j��xWd��c��	Bq��z&����<��.�z����8�g,X���#w��U�VV����������8�N�$�>�A��Mw	@AAA���:���������I D!��#�����������9�]�g1���2Y7�U���nI����]Ae
-�@�I�yQD��n���3����v�\���.�h�j���G��i����Ym!��dLaq�������2�<A�c�v*���Y!�����_�3w���3���BH`�����_��
���j���_EQ�������o���\��Fy2v:���)((��r�&�������y$���r2ZN���[=����M�'N�<_�zB!�@EE����� �A���RXv��c��cOqU��-��-]���]�i�>,6�@k�_�&&&�����W7+�D�J�������-�H�4}�<�8''Uu�t���`�e_9tYY]l!!��0K�9Bq���������3�yp�>���^�4�'�����T�;�<x���+N?�����c}�����m7;����2�&t�w��XQ^^NY�������������t����{�O>���������+W0|�pF��5/z^�n�B!��
GBB�nV���"���9�x���9��������m�}Y,sL*��X���r�=`�{����(dff�v����={�5k�a��U
����5�����6r�b��9VS�������;�2�5��3i��p�}B�)�q���.n`�����B1��������_~9�6m����M�6�}��vw�;�N������9s&��
3�c�jkk��^"##�������l6s�%����oRXX��O>���K<x0���|���l��p�9��s_�w#G�$//UUy�������IOO'((�����7�O?��w�y���222hiia���L�6����>}:|�eee��?���/����0rssy���hnnFQ���
��E/�@�B��,V?P���80���I���/�55c�g�^e���D���U_B������w/.��+M^�2���&]]������y|��]6f�j��)�Em�C	���{GF'��&�]B$���Q�B�_�l6~��������,_��1c�`�����\.����x��'55��@Hvv6���o�HII��@��E����b���dgg�����`�X������!���.`��u466����SO=��w������K���1c�0a;v�����?��O^����?	��w���j������������~���{���K.������E/�;=!���9�N����s	��)��X��s>�Uq��sc7-�S��#����������FO�����=Z|444tXSY���a�� IDAT�.�iv7K����	�{h+����Y0�
G	v7�Du����5�+}�������y!���I�&i�����y���+N/f������+��R+�������>xRe�x���HOO7N�;���o�9s&��}�g6�)-�B�V�!C����O2u�T,�M;����q�,]��k\�����J!��G8�5d�X,�"r�qyg��� ��Wk���C�J���K
���qU��-����x�AR�l����.�BPP#G����������V�^1������������Ai��~'c�D�DQ]_�Ku�%g
�',�,P��i9�L�~h�Q]/�j%&���:w�������nG!��'��w�3u��{�5��3��|6{�l��nHMM���|��f6���������������EQHJJ"99������#�<BMM
������{�[��������ZM�<��k���Z���Z����������6{��l������k������Lhh(���m�]��w�MSSG�������(�]D���oU!���{�n�8==��O�Z�'�v��6� ��[{��B|����2E����6��D/33�+�x�����]��_�spQ;W3������M������f�Gl���;�;��q�~���������8�.��@�Bq����hiq������Xbb:���U&��#F�x3����.���G���DGG�OZ``�l��3B!z�>"e��T��,V�T�Dy����J�����}	��u������@H��B>����9//����v�	�^1~%��3��^�+ �b�L�3}�'���&���y��^}B
����P�����2�B�@HV���(�B��y���(**2�d���,Y��8,��B!zQee%��B�T�W��X������w��F$2,������ �m�^������[.-��!�&<<���TU���~b����e�Wu�oE��"2v�$B��o���r�5ws����[�Pl!����t����u��W��h]����fj����]�:!����9s&UUU�a����]�3$"�B��={�h�qqq$$t����A�z�.�V��<���lwypg�('h��;���a���!��� �!V�C�����(
��������3*��>�\h�\K�v`�������Y��36f��
�`2a2�����<Vw!��D[�<�(=���)C�Y!���\v�e�!!����t�B�~F_k�����7���z<k�a�����8T���Y+�yp�6>5c�gQ�����c��^�E}������_zOff�v�g�T�����Xc�#������}e�hO?�������t�U_K���
��e�dKy,!�Bq��!���UWW�s�N�=���;�q)�����A��8�c��g������������=!		!d#;;�d����[-�j��w�����Zkm��Un�*UlU�^���"�l�$��A�}�����8�s��$���efx?=�eR�������op8��z��mvk:�I3G�>��H�b�,���0��kw(�e����a�q���Q[[���h�62Y�V-���#Z-��X���B�����f�	g/�@V�:a]#	�\:X�������_���@}B!�B���2B!��	��,����'�|~�!8��
�/�c2���i�B<�?��j�K��xs�sC� `0
���?G��G�d�\u���
f5mb $�
�����!66VKK��)0�'�.F>;<� ���Y��Vj�8i�0>YrP�
�����4�b����n�Y�>!��
�3��6B!���(B!�L�����o��O?��d��j��l��b���8o��&���4�&S�X�K,�xv d�����'0���x���i��k�a��[ ��e�`�)�Z���:�
SLZKZ��L����|v���p����%-��[~f�$h�TC=_Zj�V+2H�=���(m��B!���(B!�L�'N���3�8�F�f�&�	�A���c���e�&S�c�x�Ot��������_G��O����(�xV>
0K�*|C����I}�����>P������B.\���1{�L��u��=�v�e�P`�A  K���$dA���;S?�U��[WI���/�O�$+��!�B!��Q �Bg,����>�L&�,+�X,����_�e2U�%:^�d�A������/>;Iz�\{�A$����?�M\\||�?��(..�� �.�Z �H�0�&@=]\���z�Hi�:,��\�,����6L���o�3���J�$+�B!�x
�B!����===�8N�	2����G0\��L2�j���������C����)��J�(}��A�,���� z��{P(HOO��'�M(���svIo��]������)k���eGa���^�j�\@9X���KS�����H_�����~��~>	!�B�@!�2�:;;����8��b����q�j2	z��v��Q�b�~O�T(�S���U)��K���U-9���KF����R� !��!�}y���p�`S��VC�}1�����^eq�UP)��>C
���$��A%���JWDi���Op�}�!�B!��!�B�8���a�(!d�c{
�B����,�$��	�-�r(fz�|�/�3X^��B� ���r���i:hT��T�������F�*�r�@ `�8�8 ^{����3���Yy�Iy�16Lg����z*�E!�B��{��B!,&&*�

�
����*��I���8����_2���/����C�q.��`X=�F��]�tu�B������ ��
AAA���sSy,7�^����@,K���K����#��2��
KW�H��P�tB!����v7K!����z�Y��w�h4�U�0����_/[%���t}'�� ����<*���+~�Y�d�X$�x�
�]U�(�q�F�R��X��I!G�(�����UB����_<+�����I����*a����U�,aG!�B���@!�2����c���P(���v"j�z�� ##���3'���`3bU���~�C�_�}|o���`�2m��^���_>
�4K]�0k���>3���F��)--��d���)�Pf��@�I�u/��@z����d�!����A�$��AKWD��ST8�7�_�_�]��]�9�B!��P �B����_����!�C��A��	e���Y�{�����djt����������O�E�����'��<r��V�\�\:�V���{��
i6H��A>C������h�Z��bAii�l�R
-�J{}y,>�N�')�%��2W��'�`f��w
0H�@:�,���������j��#1	!�B�d!�B&HHH.\(��j5�������'�x?�����d��{W���j�t6�?n���8���K�VJv��+�5k0X��U���� ��
*�
������c�!iy,/n�K�W]=-(�+��YZ��3|J��>R�o�;�����>��U
�*�E!�B<B!��	���/\_{��x��gp���#11Q��L)C50P&��,�SvD���>i1��w���]��1���r�F���������
�{rK�8�2��!H��@�,>(\�c����
��a<�SU�����O��c�����iB!�B<B!��	200���ra<w�\�*q��k�d@#��@N�����d���#��K�k�t��EM�A'N���������&���HV�����C�k�
t����hY�:��d�Ap�3?�@(���,.���}�U>5�o�:��:!�B�x!�B&Haa!X�x������8��:��,VW_;�%��dIo����o��uP�H��pNe���j=:�3�u��Thh(""��*��b9"�@�Zq����2S�fKg���5�l-��
��VU�b�r4�Ce����B!�OD�B!d�H�b��3
���v8��CT/��);&��0�N6<�>PU��(�����I|x:;\���#Py,7'-������0$E����J	�c�2`���F�gt�5�B!��z"C!�L��p��ya<o�<�*q=�K'�����v��.�L,���Jh�<��?�J���Ue��&==]�>w��z�)����8{�,8'6�	&
���zq��2S����Ni�:��lG�0��N����6����)B!�L��z�i2�p��	�8qUUU�e2��`08�AK<����B!�������
���r�F:�������8�pF��U��K�,���VX.��cm��q��f1#�S��@WWO�s���&455!77�-�=������������x�P��;����~�Y���8�:���".5WbVx�!P�����?�0W��6d���C(`�L?�����M�^��P���%���^z�%,Z�6xF��j��-[�l�2,^������<���J�O>�$���;�����7�x�a��K6�Fl�������q#����[&\NN�o����g�g?���WU8r�������X,h�Z����������^`r��!��+�4$!!>>�u�����A�Uf�<��C��A�����
p���O*
�3��k�2�w�� !�3~X��o�������8�L&��f@nn.6o�,�"S�
*�4q���S%��!���pGF��Y!wgN���v�B�Okk+���q��Q��[�Z���_��������[�<"�e�������_Fyy9***��+'��'p��)TUU����������>���q��A������e�Z�x��W�e�TTT�b���Cyyyx���}�v�����@!�2�,��t�'���BrJ��Xg/�J��I2Ms�p��9�J#Yu^��?��-|4���s��}�����-X���0���q����7�|#9�LC!�S>�]-���:Y,f,�������N�	�������!2��|v�|�B�T�q���@]��e �R__^|�E�<)��p����_�*�������~�;��I.GDD����)22�T*&[8������|��|��G���DEE��{��C=���W�a�!��o��3�:!��JcB!���������Rh�T�!�Y:��~��=��8S~Lg$_-YuL�T$\��,�K��$�{N6���|�4��8l]f[��V���={�~�z���L��5���8�GH	��*��52S���Co.6_@C�%D�D�e��]�`;����Fr��i�
����
h����p����a�4';B!�j���������#�����
n����7oFkk�|iT�~�)N�8��tx��'/�5�RRR�������X�|�|yR<��c8y�$bcc5����_~���&�����+.]�$���=O=��Z-����������k��m�6��)2�(B!�����|�:$$d�7p�
H�b��8�pe�������+�v�F��X��K������%�A<�Qzss����Q�+���uuu��������'@�0{s�q���D��bfXj���*>�[W�
�iP����Z
`�O��������w�5m|����8 &TK%�!�
`���]��(n�F�@|������7!H?�D�d���Eg'���?�;��sJ��,;l����~|�����o����#���������%}��I����� %%E>=i|||�v��;v��%������ �Mff&������|\�t	


B�
�,!�B���,�T�I'N�BB������#�uZ�B���%�#S�U���Q���[6S����N�0��F�|�f�L9��p���B�@�z�@H�#��^fY�Z|��.��` T���@����o��dTZ��q��@m���``q}?�F��vB�&5�%���������|e[!�V|�[�=�e������@[�������������v��
����%�BCC�5���~������h_������������?�O��Y�f��������_�rH�b���8~�8>� ::��e,1�Lx��������~;,X �5������������F��9������Bqq1���$���
����*�����8��1			�����
��> $-�������a��b��6��O�;�l6��bbb#�����<P �CQ �BGV�EEbi!���*��l������2�����U�����X��s��u�U�]�d���[������I1#��6m�l�L���������Cg����L]��������b�t5 ,0��%0��>#d�R#}�@HC�l�B�7i����G����Gd�`[�k�!+����hii>�y����������G���g�,�?��0�

�k��6���;v��/�<��3B �b�`��m��w/�f��IBB�������b��MvY,����w�y'��[�={�H^������RZs������=���w��i����vs?����~���-//��������SOa��m��{������k����x��w��t����#�<2������'��F`` �z�/	
�1�{566����
�bL
�kjj��P��#g���
�����L���\�B���r���J�Brr�lq�l�4@;~5f�ZC�%�
��%I+��Q��K���(�U&�2�g
��&((����z���*��=66���e��	x�|a�z�&��*f�lL_�*�O���	���9���H�ge����=!��?�c���������wt�7��'��I�N�CFF�,Y����������Ekk���4)����G�C�������j��M��{�n��f�T*���
�%�&����x�����NZ�h6m��r�8���}����R�x���O���"������s' 44J%_b�eY8p���
^z�%��������/]��^x�����3
���d�9�B!�\u��E��Q�GHH�p��<5?��y�q)B!d
H�b���y�L��]Y�
��8#��g���!����X^VY ���q���i�j5X��;��7�j����;��[#S@�V��q�  �~�a�`Y�����S��pS��P��A9m�m������n���)�����Q�����r(o��X����;��op�a�������`1Z�U��X�|�E)�R���X(��b[�V|������C��b���8|�0L&N�:���W�7l� �����o���.��������p�u�	�_��p����_��WB���c����o�j����:����+V������-�y,X���#''mmm����5kV�Z�e��Mh�$##�������e���X�z5���n����d2a��]��}�������#����������Fgg'���������|���a�Z����555����>�|�=���,�����/CGG�pm���V��A�>(B!��#i�t*���83�1����+�#��JY,KS���:������da9T�H�{F����_��V���jj6+�J�&t��y�5k���d�����<m��e���!�������~�P�.!���c
�( %����B�����'x���i�����{������������(q����?��I�-�0g�������G������ ))	eeeB����>|��"+K<8q���F����>j�@����Bee%��������l��Q�#//O�>{������vttt���s8~�8}�Qh4SnV��",,�����a�^�>��0�h4��~���R~�addd{"##��C��'���7K!��GY�A�Y���k���.�3��%�B��Z[[���R �MugV��
�|����t���xC��J �J��RE���8s,U�j���T
q�c�8S��;��<___(�J�T*�T*��x����o�[�X2E�%#�O�}� IDATV�>��0#���K�qb��j�%�R#���'�B������\�P��8P���l��'�q��[�5I������s��.\(--R�h�����h���'��lAX�n���}``@�8������>���R�\eee�5��		���_����W_}�P�)77�����w�������������MLL�P&���]�:5��������X,�
��B!��iY���H��,q3��X�WJ�&��;{�;��7�����5�$�H,�����)�%���Zyy7�S�a,[�����[o�%���Z�`Y��atuua������[q�M���'��o�
,�|�W�Q �z�.���Af�|y������v������������������S����B���9������4��s��W��2���-CP�T������PK�$=33�����Kq��qp��G��?���������������~�5k�kG���P*�v��_���`�Y2���e���SO��V�Z������o���7����(a}�������6�^{-�����n!$$�����y����7����}��'���~o9�3I��e��F�B!d�H!�
����?�iIY���+�����0����X������<�,�\ee%����qL&��~!*�
�_|��������u2I%�h�?�8���X�*B�jr���	�0(�������6W��v�����O!���y��x��/��N����+��@���K������'��I:0��������ja4q���v�m�I}�R��k�b��(++Ccc#""�,J[Y��K��������^����jkk�q��~uuu��p#ca6����}��C1���X�b�;�����mWN����B)*�%K��m D���H�������k���h4
�r�rX���N�B!��������-}��K_�����X�f�]8!��$���:fm�n`�\�B�����`���a���8��?��O���<����f3X��g�}&_&�IZ�u;��0=!�-�g�C�� ��X���APU���T��<��O�Mq��3M!�;��GF�5p&�7��o�OOi����P$%%��k4,X��9RZZj��n�:��������	�}�t�%K�?[[[q��1�5�e���_
�E�IV�N�VC���*��!O��
Z�k��i����=����1c��&22R��|�5��H��+F&e�B!����T8�������(�A�B�7O����=�wGE5�0�,�*
��/����Z�b	��[���n���m�����8�a���b�Z�Fii)�xNM�xm�
��_�\$nt����0
,M^�}g�N����7C��~�\u�8`'/S#}���E�'�B����=�-������2C�
�\�4J���d�6I�B�HO�9r)))�8$$�/Fvv6�=��o�]�IHH�>��[o��3g����w�y����3g����w�^TWW����5����===�j�#������'<��Cvcb���_�O
!
j466JV����������I(B!��iY�������)&-�|
�)96���p=7.Z��e�,�@�y����q�Y,��A��s�������q����N���D�*���������O�i�w�u2,K]+B�Wf�����OHw��:(B����J��	i�>!����j?�z���y�md���/#:8	w-����/M([�t���@EE�du��'O��?�������ggg������8u��w�p"##��_��7oF{{;�o�����cm,X�|�n�rEEE���&�i��\������F{��,i�G�k�����H�;��Q �B�L�Q��ym�]���U��Qp,������*Yt��,Vr��f��	=��:��=�F�d��dA��X������B@-���ti1���D�@��g��b�������
`���v��I��J�1?���B���Q�������g����t���G�����H�3��Z�M�CBB0g����K�PUU�����O��IKK���3Q[[�w�y&�	���X�l��#��5k���*����A�T"88��������t�����JLLDII	,jkk-�����z<�8���	l�����???������hooGHH�|�����z�����U�)(B!�\���:���c������96�������Z��T���WIV��T���y�00����}i�w�������
�b�F�_����V�������0bcn�~$�]����
%2����<�Y���CX5����H!��],6Uu��R#}q�f�<V}B!��������+�4V�&��]wn��&�Qqq1�{�9|y,yS�k��[�nE__�q���P������g�y*�
������������\�e��a��]����zH���l��_-�.\(Yu��������V��c+������hmmEhh�|�K���%Kp��ap��?�|������By��k�z���xS=B!d�H�A����a��j�d���4�S����,��i�w����J�������?H��������g��T*\s
,�h4��3�Z
��Yn�@�@o�|vd-������L]#\�U������<��*��2i��X�'�B�D�6IgYYY��RRR(((�;�+W��uU*��[g�.u��qttt�����������z/��"6m��m�����A���'4_?|�0�y�\�t	}}}�����/����V��W��:�N(�����_eee#�qg�C��7o��K�`�Z���jw_��o�Qn>|[�nEMM
�����g�a��-???�x�w�Z��
%�B����;'\SY,7f��{�b@N)���VJVF'�b�>��X��B��@�
��uOt�
7 77������0�L�
�B��Z��0HII��U.�##���\>���05yUtn\�Z_�`���{�;,�],��=����@+��Ii3�@Hu�}F+|�t�B��8s���$=99����p�AFF8��p��1�|����N����+�o�>dff"((H�j{3g�e$�����o�Vy�����k~�������x������������-		�/�K��K~�����^��� ''�7o��;���kq��!������O<����W^yE��9QQQ������~�a�������o�Z��/�K��G��QF!�rz{{��Q �Mq&���8��� m�M�h(�K�W�����qk�^&-��o��P�T����O���F��N��N��D222��_���A��Bl���������,�?O��7����9����\v�������Z�����D�3N!��7i`������eff
�G����ll���]w�l�����q�=�`���j�@RR��Y����s���0�Z�x��w���x

���G\}��B����l���>{�%�233��#�`����%��������w����/���c�Y.�V���~�;��-���IJJ���{,X�@�D<e�B!����@�c�Y�f�v��u����
�Z��;��4I��Ft�����X�j��
�`X���n��F�I���ixpp0}�Q�9s'O�D]]Z[[���������z'L	��������T��Y��,e-����)?c�]`�x�k�
F��n���_�S@1zf����NUu���,����"�B������F�����?�X>-������$$$������p�
7���v��'�|�����|�\9�����_����^>=���<��C���{QUU���.h4����kBVV���������6�����>��?����#��l��7n�O�����$���������������?���:ttt������:�����g�}���hnn�q���22
�B!�A^�r�x�	$-��
Px�����,��������a��A����j��@�l�P�2 �=�Q���4��%|��7�|��|o������*&�H3�h�!_^���'�e��,h�z�0�pb�����&��b����0���}�����6C����QB!�����$������%d
�de�h��1�qExx8�����'**J�}2�����5E���"�B��j����P��?_�J��4�Ee��=(��KSV��N0W���qb_WU��l�O�kT
�N��'�������C�H��sY~�����^A��bQ�XB��a�r�������)[��OHm�]�*!��8��+�����w�h4��a2��s�Na#Y%�x
�!�B���������T*�SB���[�1X�`�V�78S~V�
�
AR����8���c���,�&Q���cQ*����R�}���� ���hhh��3$;���D��J~k��<�E@�'c_w��,KY�E�����o�'>�v�����/��� �G��~>RT�����.B!��}���8{�,��=����X�p!f��	������9s��|���s��[�	!dr9zL!��������dh�����kt��C@9�W�;���������0��}��9���,��:������N���bi���*�5���@������_�!S(h5������	`j�,2��=�:L2�}&���Q���`�R�t�A���T|�Q!���8~��;�
]$G� 6T����!�\�l��:;;���������222�����	!�!�B����7%-����#�h6�����q�(e��g�@��?���}��������|�!+��L�(=�
����-�������N��L*U ��*�����J,�8��(z��^E��A��y�@.� }�&�l�E��f�}b9���������G��gWEb����SB!��,_����������gQYY���.0���`��=+V��LB<B!��1hiiACC�0�@�������������8	��o����"=v�lW��zE>=������@��M/�a0�����p�iD���y��k�.@yy9�����se���B��������}^�%�!B $O���VJ�)F���O�����]���|	p�R/���
<ssfSF$!���T*�������!�K8��0	�V+�����^z	�>�,>�������9����O>��=�^x����s��F6�a����iB!�i����###��eW<V_`�����kw���p�8�*�������g��O����g�|
dg�4�76T�j��^N���X���X�Eaa�l�R���4+��-�_*>z\�T�rF�|����l1b3`f��#��:*�E!�B�p��x�Y�V�������������n���O>���)[G��������v�Boo/jkk������g���4����b�[o��;v��!��I!�������!��[�����X�8]vT/K]+Y�\>|���80V3����#*i����~�dD0c�4]�3����k�kC0pA{����C�����\P�7
�7�Zp����B��-����!B!�B����@��}������}�{����_l��	<�������������u+:::�������3�x�
�\�UUU8p������<���8v���<!��
�����Ra,}J���$���:_�����J�	Y�,��Y>���"����F��3|%��OZ/??G����f�;G_Y!�i1�L�Z�U0#v	���)0:?����E>+l�����'�B!�]Mi d��=�����~�#0�'���]���h�;w�ay+�l�9s�-����5����n(
dgg{�=����7hll�VK5l	!��]QQ,�y���e;�[`
@���8�Z���}W�_�^��Z��Z�
_��Y�����:�5Z$_!��m����P�o�{zzPUU%�A�T�$���
�+�/x�7>f0���*�9�R��
M�j�y��^�|���QJhB!�2��,���������A������������Z�y9[	y����@DDD���F�+,,���K�?��?B=gB!d,�e����#<%n�����S�.�_�Pf�	9�G�qV�:�������S�f�LFS,)�;M����Y���v�P���|R���o��s�����	X�3�!�/i1��{�J-Y4�n�.�n����4��,�5���B!�2�\{�;������� ((������:#����^�&������?LAB!���8��)��p������=I~U�����J�E�+d;��]u/����g��1n%�������I����Al�����hx����g�H����y@�w�����������^�9���A,��Hb�k?�IWP B!����,���������Y��T�S�mC���V��a+� ]&�B��������B�9s$5��{i�4J����p��e��^�f�{)9����-��o�� �����q�|zX�4��� �!���AW5��r�y@����\��
(�`���D��W���x�����
��R�����G�<�E��1=����N���d� !�B!���&�$������a9�1&�ieYY�|�B&��q��������D�^Tl������]I0�M���d�|Z�f�,>$��C�:�����}�	>��c����d�.����������P����l��fS%i���;��q ���se�&�h����m�3��c�?�Z�����@8�W���������e4`�����`�^R2X����*k�l���8|pn�����m�Uh�/8�=��!�B�����GY�,��A�O���2��`�}B!�����u||�d����2+g���=XY�y��R��H�K�q
�����4a��	�i�b�d�]�<���r�#���D�1���/2�ABB�0���������T@g.�O�(����)����?QR�+�X��x�����!f2�=]	_��?�J�!A�E�SvKI!�B���,#�Q���@XX�l��hC�����O�4���l�	!db�NJ����������Fa�~�zDFFJv�Q,��W�����d���������[��������Z������Va����!�]�}���Z|�����HJr>�2���q��4V&�	������/">>*������i{�<�>�����1QZ�������KH�=Px�����y���|���<�/�>�u+���W�d'	��EV|��������4�d���I�>��&V��%���!���A�g�B�)��=8��\UUt:f��)_�3c�.�}}}hnn������	!���!m���7}�{�c��_+^{�cN�����KV�c�O�+#�� �`9��A��6���To���l��\^^.�A��;��s��q��:�SzD>=,?��/	������]-�W�`eG��"�B!�LY $  �f�Bmm�]t���555X�d��I�}��a���v�CRSS�P(p��	�e"�63�q����!���u���e0�|�����������n�Se�~��/��������e;Fg�>#\�cKV\s���>#�D���Wv D�V#55UKW�I�;G>��&�+�A�����G
��O�*i�*�o�����E�#�B!��MY n�������]�va���x��W��jq�m�	�


�������?��'�����]�===x����w�^���{��m���q�UW	{	!���a2�PT����y��IV�[i�d�d�`q��������A�TKV�c�!���B
��l��0=��)}K���(2�|R��M�@�n��G��N4��(�����_>��F�@�t�0.�w���B!�L�)�k����<�e��'�`�������o~��r#��O�N��Z��a�l��6l@mm->��8p�����o~3e��	!�x����/? IDAT�R�L�i|�NG5��Y�^�:x�x��:z[q�Rln|���}�}���T
cu���k����+�,��4������&�*�<���8{�e�G�'�'�r�j5#�*G>=*i)�"��B!�B���wf���X�z5����T*:��HXX^�u�,����5�J�{��w�u������#4Q����.�"�B���NOO�`����]��q�wB�����AC#�6k�l��,��� �PGIV�ga9�4���)�Ftt4.]����q�5��v�I���y�~Z�2<SP��@��+eE��,>(�v���V>5��H_l�H_�����FE�"	!�B�{s��8
�b���~~~�);Z�vH�!�28���s��1��rc����_���v����X�,�g+�CkW*K��Us�����k��Q�.�����y&�Q+$���v\����G�w�
��8����!��k�R�a��t�N#��rVB�Z�F�������B��8n����:{�,|||0�|�2� ��54�LP����q<�[B!�wV[[���v�0qg�� A�\(��>�Z�������@�
�.�r�x5J/jK�$���Ip������/����a``z����80���`���x�b�|�)���f�H�O�J�`�������Ry!�2^>��S�h4�`0�h4�eY�t:!&&HOO����o�����^�X�+W�b��]���Wc��e��Sb��]0���~$_r�����mCEE�~�i��������?DSSf���0��g�����X�~���������w�t:����z�D���aQQ���������v�F0������a���HLL����[o���&�	&�	��A��",,)))X�j��^]�yO!��I&��������d���vI���hL��������������z	�>AX��V�4"������r������93���Tll,�����������",^<��5��i���!��t���NB� 6���"6�3|�!�B�x���BYY�|���hnnFYY������$���BCC�[QRR�R����x����C(����&�O�={���O>��+�K:t���>�f>S�������;e�&FSSv��x����r�J�t:����s�N��������w�-��kiiApp�������aCC�n������8�C[[�=��G�b������~&�������������;v������U��[���}�	!�/!
�8:�B�����4{V ���v?�0b���������	�/
�\sV�V�M�2d�d�yf��?��(
�H)
��;�}��<B�H����=����qX��|sv'�|� 5��b��R>_*�E������X�h\/�G!�8���`X�V������F����O�^z�%h�Z�+y� *j��x��.�������>�W_}%_��}������?��{��fe���}}}		�F��o�p�����p�
�s�Nb��-r�q*��eee��iz{�+���D������EEE�����Q(�����@Vgg'���QSS�����~!!!�3g�����!�B��������T��uH�A|�]�8����_�#�Vw���w\��|iX��l��r�����|���U"f�}��7o�] d<���1X
_t�����3%��X�nx8<��|	�W(����0���c
������V�>��4�a����@!����_�!!b���l��'�����`0���	��7�(y�H�R���_�O����v����(**�/�*//|��0�����~�z��������s����.�B1��%n��VDDD@��{0�����fL����������_F?p->>��?���f���>�-��"_��T*q������}�vl�����/���@��'B!��
��Ms�D�"��X�
����S���\)X��co _P'��I���������.���������~�$��w@�'_*���N,���t<|������a�����@�(���@���3W8WFKN���>����cB�G�4u�P�����Xm'_��Z���U��q�Fa.77W����,�}����'��t��w�)�[n����!""����dM&�a���5ld"M��p���B$==O?���A�3g^x��aK�9���n2�.\K0�;�!�B������n�3��c����|CG����O
��m���R��3$����S��F9���
�������������n@����%?z�����"���x�	YX��hh��G��@]o;� ,uE�����/uJ�_���@}B!�������N5���$��j��a�4�4o�nx�e���uKK�d��>|X(���k����?����?���$���=�?�X�����tv��8�Css3�Z��h�d2������E||<�����������6mRRR�-�����������P(��������.�=���B�?�j�Z�b������Cyy9����<���%�l.���0Dss����P �B��l�;�A�A�X�)���_3���� ?��;�:w�JZK8����U�����n��P���7O������[o�� ��w�(h�
�}	���Sk
���o=EdH4�"�Q�X
8���&C?��0W�@��N���I��\j7�{��=�^B����{��K���3Z���f�Tw��kg!��~�OE�����,
6l���o�MMMN?D/))��S|�g@@~���z�=���x����������#����^<��c����������|����v=->c���2������������Cff���?��O>|�nn��M�1c ;;[�l�[������<�������5U_�}��	�7�t\?��
�����V@RR�l�}y�oB!d���
���Z����I�!��C�J@�y��������8�J\IK���3���|�xs�A���NI]	�A���tt���C��"��2����]'��z��ibY�3*���|al��� -�|�cE
�IJB!��`q��A��V�o�����p�9sl�|���3��s�a���Bsjg���K����<!���S?^}�U����BSuiCAA^x���������Z�FHH�����o���R������B��0(
���
>g*��,����������=h�Z�u�V�,�J����K��m�WH�Bq#��X���P���M����A 1*K�V�t�Q����a�.�G���8����P=��g����������,�w 	$B l����". U�����W�����V[�{k]�_[�r��Zw�Uo[�Z��hdh �!$����9��c�9s&'!�I�~><:�%)�f��y��s
���/��� e��CLLEEE��r��v�a	���?3*6j�a`������?�j����0ZU{�'DA�
��h����;�oO
!���
-��C�O9�]'j�{���c�{)��x��w�qW/}��5t$44�y����b��)�)�����QQQ8|�AN�>��b!&&�9s��t����K:<�������������Nvv6&L��[n!>>UU��s'�?�<MMM�9sEQX�j+V�������z^y����K\.���������y�
7�j�*6l���M��o�E��h�"^|�E=s�����:�p6�5,((����z��f6���b��
��vZZZ(--e��=����O�S���������B�UU��>�Q5�f���?���/���'��k���w��+~Ip��o���'pU�c[���T�9������'�ZPU!>$�2w �|#���������I?��m�eQX�TqU�*/������B�"�������/���i^����&.�t���<�����O;c�(\81�q��Kg�m�6�����l������Gff&��ZI����v����N����,11��!=��~��vee%/����zMM
G�e����w�}DGG{������Q��������u��~��0g�
y��w���KY��},((�[n����l*++�����p��#$$������6���kXU���������N'o���y���`�����^�B!:PXXHyy9�������v�Q�	��1����k:��|���7�R�?��D�����151���!c6�56��}E��5��v���� �af�<x����:�uk�_]���������K�@��?W�PT���!m�k�)�q0*T��	!D_{��3dk����k���VWv�V��S�]�����6O�222�������t�O�����X��r������s=z4UUUl�����j��9��O>�#�<��f��)99������YG/��v;)))l����Iuu5#Ft����9��a]��0JPP��i��������������\EQ�={���U__OAA%%%�������{���?$#�����&�!���l���;�W�KE/�(�u)������z�j�3s�<B�"�<6�yS�o��t���W�����r����m�<8��	&HCC������0}�t�61�R  	Oh���!�f��!k��%���YN;��������c�7F���
��LU3����(%��K!Do�
���6���[tEQ�S�m�V+��{�W�Uv���^{�<=�����_��#3��+�d��u���SPP�����%��a{��a����Mjj*,0O�9ozt---������RPP`�f��ejz�\���`���u�����=z������l6���.�4�����������z�_������B�B�HY��B����XF���@��x���z���U���&ZN����	=��2�I#e��a���6m;wje�����z`�A��BN��
�7�@���8�GO���lvY,�;]8�o�z�b-5>�3UZ����B�~�o�bI���qi���F��t���MB�?�g/���Ea�����Ax��g����7�x���L�N'���*����z�����#EDDp������/�c��@H^^[�n��m���$�
o�%�e���|����if���k��s��3t���uf��DEiUv��A}}�i�wRRR���{����q�\�_�������H D!�0����8%!�V�
��Z
D.�XlN�����5�X����zvjC5�_�������PM(~A��������AA��yfH �k3f��!mu���Mt!��T'(V�=C���K<!+\.h����l	�L��nZ|0��!N���t���B��	��p�����kr��w�R��] e��X���_��EQ   ��k��o�>�����a���'>>��!���y����
+n�f��_��<y�c-44����eB����S���#:��	0O���|
ccc�����.�9�/_�_:t�����c����@~~>'O����\��*	�!�&�FeQQQr���*� �`�B���� c��3~��j�������q����P�4~����kA���oc6Hl�1a���[��M�K:TVVr��I���@��;�h)��]�y���d��Kx���(
P�����=
�L�FQ@U������FG���!��/��������-����]81b@� f���\w�u���������K/���v��w8		qT2f���@cc�GO	�%K�xd�O��z�y�����0""�Q�FQRRB]]999�Sz[dd$�������| �{O�B!�0���>����&7����?��.��t������K�V�xYD��0���ww���������dg��t��l��			a��	����E0k(�/t�+6����Q�qL�w<v[��3����\w�Y?�����B��+B!|���a�L�e_j|7��1O������h��7o�l�1<�(566V��N'��ZO���d
�}h��~
g���_o�������KJ��7��
!����pp��},e�|����ly��G���N+/c��� ������f��� �6X�P��}��gq����_�����7��czVz83��������o())1�&�2�u��	����>���bAU�%?jS�����A�o��9/�b�(��Y�<t�yL�	�Xj�����c	�����������U�=���[TVV�v
?��7'N�p/�ri��y���&w���������c����p�������,�l�����������(���N��3B!rrr<NY����v�Q�\�7��P���>����N��� �7�
g���MWTG����<����q8�(J����8��dqv�����KJJx�������y���;}�������2���y���%@>
��������
��������2�'+�Bx'9:���J���)<q�x��a"���.��enr�JLL��������y���L;����T����M�p8����g���4�J�i������pOh�������
+�\��111\q�����^b����f����Q[���+���^z	�S�34}�t��S_%=B�Bc���S�b��?�>��$r�V����-e��m��;M�[������r���L{��e���ck-�#�s��!���G�=(X,���x��GY�z5K�.���~�
~����B��}�y��4",����*�~~��(�u�8�fbO�������	�[ht�p8U��j�B�����>����k������SZZ������w/����m8�N��_o�ng����w�y�i�����q�w$""���@�Z�\}��������c��z�j��C]]7n$3S+�|N�����zC�'�|��������e2���T��}�~�m����4i���dggs����;�7��k�����#:tUUy�����e, ))���`jkk���f���^5Jw�\l�����,uuu�8q���LJK�CDAAA�]�����I��!��TUe��}��|�B��!�����j-m5",������V��~k�6zw�GUa��?HF�����%


���K�����|�Nd)���f�n���;�0a����<?����r�emX��a�?u�!b�j���}B��)q�����B�w���������o�+����)S������r���?�=�:����a $''����������,[����{�nrrrx����[��l�~���tr���/g��m444����O<���c.4�^�L�BZZYYYTTT����{�������y���s��l6���>�}�Y���@~~>o��y�H�����������yZ�O~��v��|���B!Z�<yR�1�(
�����g4�C����`����9���|��+�(���Y��W���n�����*�[PH�� ���PQQ�������#-]UU�y���:M[},�����_@�v������=i+��,;�����F/�&��c}S�]�U!�����f��he��y�����j�r�]w���~W/�d�����u����_LL<���(!}��w2�|��F��Jqq��\������??������{�8qb�?[���8V�\��O>��5k������DEE1s�Ln��6��Au�K2B�B�V�l����o>�����}8���,���t�I}|����ggOY�<�����/���,{c��Dh��(��TUe����V?�3---��v���)**"66��E���%�XAu��jvC�l��!)*t����`k��]zy������������7�����:Q���d�B��q�}���:u�=���x����S^[�p��d7$&&��?��<�)�����+����������EQ���#>>�������x���������3DGG{����N��������5k�Y��x���x���i���_���_o������w��
7������Z�����k%��k8k�,f��EMM
�������(
��������]���7��z��*�z�5 IDAT�B�� 3f�0��c,�5��A��I���Y�Dz�`�N���4�|����56��+���u��9V�A�������j@+������j������U_h���@��)K�@���	�������q5J72�b���	�����o
��pb�i�B1����������]#G�d����sb�X?~<���7/�����~/�������2O������2i�$���%�!������I�����M�S[�b�{y��z�ih�#�����8�� �Y��w�rb7��\��N�&�;�	����U7SP���g%I �;�V��g�����1��E-��$>��>�eL\��6�P�B�9�N�!��W�oK~���ez�,o�&St@{���V!B!����{���O����z�jV�Ze�B���?	!����,VLL11��� �Q�Nh���?���cy0�2����2g�E����v�z�_\����y���_� �p�2�� 	�����V�����Mqq1V���i���X�S�c��1��~�r�]WoG�{�d�/��-���FG%�*jKy�������}�#^�-������������������	��Kf�B�!j���z�����I��oH D!��32c��N��	P��}������C������g�7�v�b�C�k
~�/��8[b:������^2��l��Y�h������


�e���Sjj*����U�oBf�_4�T��D�`�5�����G������S��~�?�O������nS��d�!�K �
�MV4�=��9��q��X��T!��r�5����>���=B!�����������q�� ���?Ha�	~��/I[aX����l\�e�@���A���-~J�� u8|�^�J�u���^���cQ���,�`U???l6����t�M���K�(C����������`�����zk�������=�Tx�����sQ�`Gn5��$W�!�B!��B�B{��������	L;��p�A�����r���o�~�;�qq����ax�i;%(�������^(gT������;V��[o����,D`` 6���� n���^o�)z �
�u�?�^DC��o?6Ou�����C���=|�]����3��]|�Xq�m
�
!�B��$"�b�������O����>�r�+5��<�cy�p�Z�l���x�9f�4jm��M����=K\�����n�If111�[���+WvX����.b����i1����Z����N��!�	p�3���Sey��.��0O�T6�/5Ow���$+D!�B�;y�#�bXs�\���_KY,g����������T����[�X�����{\UE8���c{��U��5���r���-�A���f������'�����=�_~�����m�)���S/�  ���j+��J��/�kC��b5Ou�j���GqM3���g�T5�P\�l�B!��OI D!��v��1jkk����i�3�`xP���d���t�����'_Lp����� ���#
�]s�T�O����26q���A"�m$Gyn=�(
!!!��;W���������K�������!F
G`�����1���.%�t^2���i�:�����B!��B!B!��}����)))V�O���O�,��cy�(�)a��L}�8�j�j�4!~)x��hq���8�}���;�8\���
�7��%..���}l,�'@�a8��<����;Y#��%�(�g�X��m������:���)2���B!��7H D!��f|	)e�|��,V��E����g�>Dm=y���t���QM�w7��O\hX����U���\NU6��8x�����M�E�P���4},��V��:�o���mP�bf)	�Y6�Z�t��.'�������?����42�<�!@dP����B!��B1l�9s�3g��c	��8cY��e��ADU]|��}}|I�
��n�Zrw�:���_�������9x���z��l?^�WG��������_999���VE���f��Zw�������I��;��.^��G
�5/p���,�N����8���B!�B��s{�B!1�I���F�iX>�YU��O��?Hv��+O�(.�q�iG��b���6?�j���UB���?��>��u�����q������(�'����<�����a~A�|�{Q��!/|�jyb���Y6�,Yz*,������!�B!��B�B[����
��*?��]�"!t���`a���<���Q��PU���C{���������t���-n0O�s`�X<�B���kX�* �<������AMA����t�N�d�1�47�����	�����nvk�����B!��B1,���p��Q}l��/|��?H�RP:~���j��~p�>�$}�a�g�%�qU�co��49\�7;����(�m
B�^c�|���45y��B�����3]P j�yrPkr4RZ�.����\��U�Z8!�����m�s����V[,�f�B!�B�7	�!�������	���$%%yn����d�������8���G�1a�iG�9���FO�2���1�UAQ��o��-coKII!00��Avv�i���?��q���%�	��g5����m��c���,L��91\2�].k��Z�.!�B!�W�w�B!�e�2c�E��������6����	�O��]_4�
��aG�8�|�_�'.2�t�jQH�2OwJQ��~����Q�o��=�U�o����'P��['h2���yv��[�=�{��c&��:�>&D�>t���f�aU!�B��#�!��������q�l��T��w����s�+rs��{Y,��G�����&WN�2G�	�-L� ,`��"f���_���������7���:���	�3w�eh����<��Ic���c����Q����
��L;�B!��B1�����������<y�i��)���X������{�M�'�M#n��7\v�.�t��-~�iG�2C�;.����"�l�47�<-z���S���444p��!��o��@�W0c$=���T��92D]>�:��M2O�c��q���4OwIQ`��P}��d�aU!�B��#�!�����{��)S���w��(b���P��=�|�A�
l�vs�{��+�� ���Z'�n�����Nr��4K�}�	��l������������`�U�I\_p�����B�x��Z����7��N6�z��Y�;V<H��$�yo��u����_��u��B!���{O�B!� ��*�����iii�U�s��gk)K�/�\2l��I�3�3w�%�=��8�|��&z_�M��Bl��>�[��06\�����_+�#!��.���<���{q�\�U1`�&A�x���C��7b,�����w/����Q`�RaV7{��I��j�+�MN�7�v!�B��$"�bX9q�UUU(�"�A|]�F�u��`|/�7g��b-��{�a�g��GqUkE�2B�IU��c���������+��F�/.E��1c��l���j�;f�!�#�r�6���(�����~�����w��?x��|���|�c����,L�u�W��XB!�b H D!������_�7����K	�|�AN��q���{���so��e�l�SQ�"��9\TOY�����f�!�Cpp0)))�X�c�c ��Sp���C��X����SH34F�z��s�������V�B��T���R������L�*�sN�����^���Jss�yZt��<!�Be�@Hzz�aE���SP��=�Z��$6g}�_'�L��!�7��|�_�'t�,��G�� SGh���.����39x� �w�f��5(�d���E`��*p5j�cpd�h���L��������RBBG�v�]����Z�.�l��F��Bt�/�������F���p�\Abb"�g�f�����/�������<���h�"�����A������;w�q����a����^�����S�N��;�p��1x�����[����_�������.�+��������%K��t�R�r�+,,���	���n#"���z�����7��_PPP���X�V�����������;��5�����/�`��}�8q���TU������$f���%�\B``��C�������������f���q:�(�BPPqqqL�>�y����?��.��B�B%%%��Jg�	��F����j��}�����D15 �	���C��}b�����Tv�V�����U�����Y�~=�����������I�?���A�_�q���.2{�
�~�GjPi����_v�y�Y���1:��S�M��r���I!�rss9|��y���j���9|�0�|�	'N��;�`���������?�3n�8���������XS�L�����y���X��{���l��������e�o���������o����
�W_}�E�p�����������>��#n���MII	����l�������G}����{�;�N�;��c�����������v���>���+���3����9|�0����>��{�m���p88p����Q^^_�5��_����<��z��,�B�0UU���#33S����!66��K���X�����G���N;�f���hZ���w��	��-n�i�������I�v���$)�5�"""?~��d��=�f�y�;R�!�b8U�����U�����B@�
qBj8���^!��HRR���8�Njjj8u�MM��%���G�����D��(������	��CA���~�z>��#��Y}���������w���}�_�2���������(����[�\\\�~��svv6���>�������V2���_�� ���\|����������M�hnnf��]l���K/����Z����#���K����Jtt4V����B���������!$$���5j\pv���Iyy9�w�������R�q�|�I����3�B�BY.���?��-[�PVV��6iR��(}Dm��O��AX�������|1!��sc�8��~m?�8I��/
M�g�
%����!zWFF���{7�V��*e^�����XAuBsT���������,����8^WFAI.	��3�:�����c��o����4%Y�o��.�Bt��?�9QQQ���p�������Jcc#EEEl���+����Qn6��'�x�<�������������dee��k�������Y�d�aG����&;;����.3���W_Mll,~~~ddd�����/���o����������JGFF�����0�-b��i�����[;�����z�j����|�+����3�����>��������������k<���]�o�[���Omm-�~�)�V���3��w�B�JKKy��Gy���� ��A��_��;���1����R�V� �"�e_WV]��������$U�q��0�����f{�j��|)��f���_q��i��0�(�WH�2�f�p�<scp���eWk�L7M�$�5��t��8���B!z��@:v7X�o������$�@���\p��]�V���g�a���v����E�� m�����+W�{�Mll,�/�d�'EQ�7o^�A��R\\LKK��4�KKK��7N���m��������/@��s�=�Z��] $$�n���o���������^���=jX�$"�b�q�\���K�8qUUijj������p:�455���/wx"|@��,V�`
v����}������gj��%��p����r�;�'�3�zg��jN��(����1]�R��1r�H��Pz��F�p_�}��&��	,�wg�m��c������jQ����ys�L!B1��
��+a��P�{(yN�/����C����	�^�%%%������>��W_�KJ_T{��7���������Yc���\.EEE�������N,**�����Z���{��y�f�o������������-[���~����[������t��[�2�����b��m}U�������n��{	

2��{���_�\����t�j��%�<22R����y���XB!���?���G�����
h7^MMMz��W_}������n D0�de�T���Y���K�V�(�s��X�7	K���w�u�����"���b������Zy�+����C�+��=�u�7���/
5h)
����n��8���Z�?�]�&,"`�,��g�>6��ZK�.s�R{�g�B�h.����h����c�u!��������Rp�\X,.��R��YCQQ���������}�v@��������q+++����=�����O~�}\[[��w�MPP�<��|�
����N�i��q�-����/���������}�?��d��o��g�}�1���O2z�hv���/�����x�z�!RRR<��1r�H���)..�������9s�����O�Ku����Y!!!�Xa8��G�������y����C!���u�V@;Y������?~\J��G1��r��z��x�&w'%�����X�xF���v�j����,Vy�������)��S�������� p<Mq��Yy�����I�K�r��,��m�Q��j�v�JOv%ml���kCT{�qB!z�
G~�yD���BK���Jnn�~���`X�F���?���k��U:�
��'7�xc�5��+���<��S<��3z������~���>�c�=FVVv����(=�S]]���>��C������(X,� ��b������(�^�Z?�������DUUo�������~%����������_����_v��z��)�B1���Jaa!��������\.�V+'O��O�P����Mv��O���A2&, 2t�a����'���zR+�X�^�?&�����)�b����2z�h�d��={X�l�i�#����Z�e@�O=��(g�	�_�Z���(d����B���\O��G������#�v�����P�.s10���b(pAk)�n���3�v��
�����W�������



���;���/4�zj������P�����t_�2�p����������(>� �O��b���9sX�t�G���EDD���O�����~�3�r;���L�0�[n����xTUe���<���455q��Ea��U�X����y��W���/q�\���{��W��?�
7���U���a�6m2��i-Z��E�x���������G,���������o����[	���\���;����=:z;;����?���N}}=EEE������F����w�Mp��*E�SB1����7�36G���f����b��D�@���d{�g�xq����s�rb8����0�13L;��_q��]�>��f���3g�����wK �W�\���]W~����
��*�����'�h���P	U�F�;�[�����S�'��q�C3���!��E!��)�+���;��O�x@��#H�����pV��m#::��Fmm-yyydffR]]
h}0�����N'����y���D��������g���J^z�%�����=������������X�-��Q�Fy�o"!!�u�����Ea��9����p���zdYq�-����Mee%9998�s���������Y������J��o+}p�M7q�����6��"qq���FQQ�����$$$p�5�x�
�$"�bH�X,�9����Vk�A�����}�!��*����X��NW�!#IO�~���8���b���k�n�N�5RP������/q���>��C�?NEE��z8�Y���}�VBDm���0���]C�#o7-����U�9�����"2-.l��T��i����y��H��P^�<@i����fb�����B9�^�� �9si����?�[�����6O�222�������t�O�����X��r������s=z4UUUl�����j��9��O>�#�<�Rrrr��c����k���n���������&9� IDATq:�TWW3bD�{'����f~�����v�������O>����d&N�h�0����=w��������	��e��������Oe�����v�N'555�8q����x�	���;���7����'h!�b8�����O���af��nGQF����� 5��Q�]+6���s����e�.N�
����8�f���X�M��G��G����7Y�<����M�D�S�0�J8��6.�`�BZ����s�����Z�g���c[���vjT���H=0��d
�S}���B�7@��@Kc�����n�����j��{�e����������k��!���B�

�����G��+���u��Q^^NAA��9K���S����;v��6���,X��<�����a|��h����~HAA�y�e���{����/�A�i��q���c�XX�~=[�n����Gy������a���~E��������GN��Jw��YRRw�y����������O�yyy<���<���DDDx�j$"�b�������c����������qm����'7�|�W7Z���b��T�g�|KA����������UQ����>�O�^�����!�P���,EQ�������'�v��@����)�T(�O1j�Vv�h��2����z�����r�
5��]�96T��9Y+�!���������Yk^�N��p�]n�������g����/�<��g�y���`y��7�����tr��!�!�ECC�~�|��v�/#""���ky����c�G $//��[���6AAA�F>�������y�Y�fyB����rX�����?�������nc�������8~�����3�xf�TWWwZ�",,��.����bh�a�MV��E��������Juu5|�k��5oR��B!|���?��	�j���


��AV�X�q
C��r��/��d���������Y�D�S����,�ud�Wu���O�Q���,�Z���@�/������=�Q3X���`im0�R	U_x�1���_Z�w�dZ-�Z�CX�F��g���nHz�LuM���B�	[�'�����x�ymc��sx���A�^v���k	

`��
�v_���'O6����5K�>y�}�
���qqq�~���3h�'�����8=����O>��o��F=���/d�������e�}��8~��~m�-���-���+����wW�������L2B�BI��ww�q�>�(��x�IHH���n"99��b���C�v�x��o���l��������s�8j�2�e���_���	!4��Jv�������#(++CUU�|�I���?~<���#$$��!�?X�!b��
P���/�!����������v�x�b�	T����}��'F��
$�O��Y�����Z�[$���)�]�g�*I~�}�\�;�������x���iii���^�����_e�7���DHH466z��X�d�G���t�����:t��a@;����bZ�\|��|����v��������O��{7��������l6---������$#D!���v#���;���Gy��zH� �Duh�A��z�c�X�����m��_49	��I�v���������A.v��K�HY,�WYY��P��iv���_����[���;����d��������1��d��W��#�����$ S�)���P�+�eQ`B��{|O�w'��$��v�yE�S����W�������C��y�f����X
��Q{&1s:�477��d�z�����>00����GM���g��z��p��1}�/555�=I,��&�B!���1�s��������M��g�
���ba�,8��{-`����)�������_���{��'��6�k������bGn5�-��}�������4������������RTU��p���Dss3N����Z���?�����?T��W��H�yP�5�����KD����XY�B=���!5�T��N4B����b��B!�I�dH�&�Ykhq���;�}���P���X�Zv�[o��e���b��	���'��Z2t��;���^_���������
������:-m����_���y\������/����+��'��}��$"�bH���������nX�Y
�.�c�h%����������M�D
h��w�Q���J�@�w��������a�J ������TUU�t:ill��p�t:iii�"�����H_�9~��'g�����"% ����m�g��4TB[�v��\i9�����vvn\����i���"�tk�W!D�R�Z���7`�gZH��`�2��	���\v�VB�����^{��c�IMM��cm��	��a�|��~���fX���>-�������V���xV�8�������aE�p8x��w���_��5k��f�����7�����c�QgA/o������o���/s:XI�!�CRVV���EBB�i�P����4�z�����{���S\��SR3�w�YG2�k{����7Jj��q�\\4���-|Oqq1�����Jsss�i�---�	��7r�M7�v�>7b%T�]���y�1J@(��3sV��*��fXfb����
��	���Bk����Y���#��������w\�\!�0���k��};���l����{�vx���t�~�z�t;����x��&++��|QG"""���+����j�r��W���oRXX�c�=����3fuuul����L��"88Xo���������}����zRRR4o�i��������v)<<�I�&���Lvv6���I��.\x������-[��t:���K#??��������Z����NTT��v����q:����r���2o�<f����#P���B�n�JNN���w������L���PU���*�9�W_}���JJJ��C�B�BI�w���322��/����h����' f�����,.\a���%��[>�U[���!}��F�_qg����g�����2��=��\�� m�N'6�����D�r���k�j%�=�!������0wM��r��E+Mr��p�	����gy�c����8���W����m���B�N���s��7�����W^y�)S��������r����c�#���Brrr���9!!a�!��-����������~�a�l6��~�G6Dw]~��l��������y��'���������2e
iiideeQQQ����4���2���Fzz:]t�}�[�ne������z��}���j�����{�������������i3f���m


x��g�����4~���=J�����!��P]]��
kFF�aU����3]pAI��b_�
��Vk7�?��S��v��Qw6�%<���h�Q�mG��iM��>��Z�.�*�C=x6X�(hNt�����C���-����r��2�0�iu?Z����k�8��1euN��~9D!��!##�Y�fZ���J
'V�������~��z�,���D��[wNe�bbbx��HII1/
:w�y'���owh�j�vY��+?�����wbbb�K��v����c�=���_zz:O=��^zi�����������;y��G3f�yK�������e��E�����?��?:���$#D!�������(g����b@�w�{]7��#cY�E���o����C�������Cg�)���I(
,L��X���A��0f�������k
�\���
K��?��2�XBFj�	!��4�/��1�ba���EKX��������Q�/������!qD���B!������<��{���<�SO=e�����}&�!11�?�����NY�VV�\�UW]Enn.���(�B\\�����=����C=Duu5g��!::�c�n�w��

�t���Y�����o��o4O����z���z�����n��N�>��j%$$���Xl���2W�%K��d����(++�������������{��7�|3���S__Opp0QQQ���w��u�����g_U!������K�NOO��A����n����#������{�,.�c�� �,����$=5>���n���~7y�V�j��(J��!mfm��0B�����#<����Xc�q5/1���=�'PDa�����{�96T��9Y�wf�2�B!|[nn.�����9r$#F��=��ba���}~ 0,,lH����"**�<}�F�q�_[EQ3fL�2>D���X!��R__���q[���!�3����zu���3>a�^w9��bS7��z�ZND�o-me�`7�sC.�7d�H��Aa��Q,\��m������a�t����f#  ����{��~6�FC�)P�P�!��l�5d-����o���B��E�E+q�i�0w�]��72Cyo�V~�Di#�u��}3.�Bt���������i��^��U�V���}@!B!����,�N'���N�h��.|C��A���a^i����g�������S/����cY,[�t����:QCS�V.��BF��+��5k���������ZZZPUEQ�X,X�Zs�5k����5�-��N�A��uHB�����}-M;�3/1������#�j�y���H��gT������=y�,�i�%�B�����SY�],����!��B�B)�w���������R>$h$���W�����{i�_�L]ck�j����.���G��A�V��Xk��p�lRn�

�W��o��&YYY����[�={�yZ�����������C��d���c�M��_�Cm�JYLC%T�����X2�����V�_���VK!B!�k���<%��A�vH!��Q__���~���,�{�����?�����>a�����������Nm��%�}l�������N���&JY��&""��o��{�����3}�t������a�0��5+����,�!IQ��}
�w}@�U�����H�*�1�p���C�y����}�����&�B!Do�@�B�!c���e�&M���
�)~0�u�O0�@�\��)L��x�RXz�'��cKe�a�w8��U{�Gb����G�� q�~��4���BQ�L����_�O�S�����={�v���a�
���������;��<?��-�=!$!a
$�a
�* �[[�����Z=��V�9��������U[l���Z�ET�,"�@�BX$a	dO��Y��C�y��BY&���..�m2a2���s�=�1�/��wr��8���t{���p����o��q�x����
��u+�B!��>��� �B\���t����"i��]�I��y�SaN%LJ����q?���'j�`�b�o��������%i&Z���(��I�5oD$��gHIIQ��5��E��m��w������ Ea���z[o���&
��;p�J�A!�B!�I�>U!�~����'N�}���
�~�m�N��y`����������}cy8�����(>���6��:v���jO�a����X=��q�0�=����������]��b0�x��j(��;����Fb��<E��f���[m�5Y�+�B.��'�B!���@�B�a����	���H��[!�N������y�~l���T�U`�b�l�������RO�`hS�t�m�	����l���/((�1c������kfE�1B�-�~�;P{������` `�|������A+�*&3g�v�UM���y|�����^�5B!��B!B!z��{�.��M��X���Ti6r����������X��.W��9N�V��c1��VG������j�I�q�7�<(���E�&R�1�;�����v�;�C�g
����b����J���Z��p�v
�K!�B�����.�Bt���2N�>���O���~�Ds$x�xO������;w@��8�cn��}������,-����J&<��DM�}�3L�8QM�UUU��Pt��L8��~;��}c��C�l���;J�����,�7r�������~r�:v5)��X�U�{�A!�B�{I D!D���
����5��/}�mG�	�����C��&�c>0Y3�>��*��3��ex�!�Y��X��"�3��

"9��}����>����7ctZ5+E�p����P����rU������W�E��P���pW�c�(�)����k��f��pW�kZ�2$L�iPZ��\I�*>/�B!:�B�Btk���{�7���i�0d������to?�no�O9\v�^��M���8����tG���Zl9_VOnI���?R�b�T��
S�yyyl���>����#	,��n�kV�u�7�z W���S�G���-h�0)0CS�|���b��f��5��d&16H�Kz,!�B�^$"��[;�<���j����]����v�������������0[�?�f����8�I�5|����vM��a1A�#�z�C��f��n7N������BA�Z���k����C��i^�N����v_n7�������r#����E8N��]S�Y�<mz,	�!�B���I2,�Bt��������{������F�KLL$&&F�Z�%m���{�i��8��|O���@�F]�Q�84�AF��L6��V�u�B�K�����������(�����	v8�N���\�p��k�r�wh-������G[V{�������������_QHP�^���f4p����(��(���R����>O���e�W9�	��V	!�B�6�;f(�B����R^y����?���Iqq1������(>����NC���81_������s>E��t������RO�`hu��C����w`1���[!z�
6PUU���j����(��{�)l������7�E;��zh5�[H��k��?S�k����@��f�#��G���r+D!�B�	�!�����
��GQ�v;uuu����9�srrx��7QZ��"�@��6H�xi]
����A�m�!��>`�f��8N�T����0��f�6M���	��4���8r��y-l��(�\.�n7���O��d���h��G�G�-ch4��P��j��`����
�L1C}�`J�7��_!B!��H D!D���g�QPP����������(j����:E��������P~��o;v����N;��S��'��!E��7b1G3�������<I��c����`GK���ZW�A\����#���#�����D����QU��0Ask$-�/��h���i���,������&�B!���@�B�g�����/�vS�
�D6n���~��(�hN���Z�='�P]W	����q�t+��R[�3�s�Z�~����fal��y�s`4���{H�|/t�!?��a�����~�����0����f�����WQY�	��FbLA�r��"���B!��k�')!����������n�EQ(((���{J^��"�m��i��@�b_�Xm���`k��`����.5�1�/����w+�i�n��+��E���\=b2yR�
>\7#��)F���3^�=�N��t{��B�~CH�+���Qh���r��qd��|K�[!$"�B!�S����B?�P�� ���i(,���K����A��s9q>C�/N�]3���Y���e�\�.�U�TMi��^����KZ��l����F,K������j�`00n�8hc�
qm����c�]0�g��W �!�h�a:����:�V0Z|��
�0N�k����o ���j����!�B������B?���'�F�I��F���po�U��@]��s�����E��
'���l;r9q���v-#�j&���
2iP}B<idD�4h� n��f	�d2a41��X�VL&���|������`�h'�H�G�U)`�/�s����|����I���������:�6un������&� K�_���!Y<W�N�#=�"�B!��B��������Ym)b6{6�G�E@@�nVt)mZ��9`���!��Fj��jqJI?��J*7s�����PU�b�Yo��F�m�����n�k_���\ IDAT�&�I
~4E�F#�x�	��������a����s�A��u=�����h���7��^:��xoyk�Z�}5f��������yB!Do�Tm�ka��IKK#--���\���@���l��%����A!�~�`0�|�r^�u�V+6�
�����d2�)c���n�9��%`�E�{�b������c����l�Y-��I^�[�~Y;��e����-�y�2.��Mud��	�:�v��/&��[o����'�u�Vrrr��������!K1P^��������!j�|��Q��o��Gc�������}����G7����a1���B��p��+8t�
�[�d����B���/0y�d�,Y���K.��U�V1c�RRR��-���`��5�L&V�X����~�����y���X�d	C������l�Z����"x�F��z����o�>V�^MRR>�`�)a;KW<�.��={�p��AN�:EEEN���D||<&L`��%����JUU���*6�
����n��ra0&>>����3s�L��+�vz	�!��&N���9s��s'V�����1����o��A�i*�B��}
��&s�n��h���I^�aE�>�A�if���Nz�b�)��L�����7����z�-�����m��2e�:'�H�=�@H���S8�70���=����+
	0[�;mT�Ur��f�^�{P�&
�d4�r+T�\d�2&>D�L!DWRR��#G��������o���={3���u�n7���_~�%�����6o�_���4����{���s�=�[���}�]���8�<S�La����%����n7]�>|�w�}����.����<�����i=�s���Tv8?�9|��s���g�>��c�q�
�_��u]XM!�h�o}�[�I����l6c4���?������t��JqA�Cp��&� 
�z��[��\�N�Q�KR:.p�*=�����hE}�3Eu\���=_�b�z���W�'O�l����d}o���*�r�����2z��6�=�������/�d12��7�q@�c	!D��e�E!;;��/���JMM
�����C*��v�y��7�
���~����j�����5��L
�
��������7���O��+����MW<��6mb�����x��Drr2��-���og��yDFz>�95-xsbbb���;Y�|9w�}7�-R_RR�/�@e���mo��WM!��#UUU\�tI���1���XHrr���o�G}�|g�V�g���6Hb�h������/�I�mS�$��W?����M}4�������KJJ�m�atx6�SSS����uD0�A�MP���_��']V/a2Cp$J�ep��O�����4���}��dJB�y�:J��Uq�����$����@��Ep���6v�\l��M�o���{���T��N����_���D?uU~�!iii�b��N?�?j�(~���SPP��Y������'�`��=$$$0`��4��9����������}���_���g�������.�\.RSS��};3f���������;}�=������dffR]]��_~���������@�B�nc��=j:���(����`0����^�v���5.���=���H������V�y�����FzO�7���V��,�� O%[h	A����v����o��pW���7R��������&F/�v`
CO�NI]%��&5�s���n�%eH���GJ��+�'!:P�L!�5�t��?�s8�
�S�$�q��h&	�/�t��eoZ�]�v�|��.��v���YQ[[����/6m��~^m��������4�<��c��@��F�b���;v5���,\�P?����9�|�2o������W�����5+�L&.d�����o�X����������3�=�B�Bt���{�n�?s��k��/:P������
���@��c_Pg� �������G���y.C�[F���6m��
lN����)	����r�^&��?�
������.;�'��{��]�
(�}��_�c����X�E9�2����<���cn���w;"��$�q�����*%"��d��2>�W����c
p����~q�Y�|gn<Vs������f(**���2���8r����W����SXXx�EGG�sz���{n&FFF�3_SSCVV�/_&,,�~��1x�`�����o~���>�h���w�a��]�����A���u������v���?�(����{�i�.FG�������g,<<��� �o����Ipp0�8q���:"##1b!!���rss���CQ���Obbb���KJJp�\j�h4���������N]�t:���A�~�|�m�U��������|�=zt�nu7��k�>}��m�����$"��[h(�@6��P���#-�9��r��V�������}�����w��	jC�0�[�K������3<������E1���Px�c��d3�x�!�z�E��@�-���n���=Cq�V1�������o�o���i���po �lw���V!�h��������b��+2��]S/����#G<���/_�_��W�����c�O ��v���Oc�������W_mv�x��5|������P!N���>���76� NLL����K�.��+���K/a�zoy��n���Y�|9�-b��
�G�l��uj���dn��6�����~~�����=����x��j?##�W_}�1c�������>��u��5
^,\��o~��dgg���o7��2h� ~��4Jm��_��'����������}�7�pAAO<���7����{j����9t�\j�����k����\�pAm�9R3�;t]HW!�h��\��y#z=�=D�=	����W��+�);�9�'��������8�M�e9��f�u���s��7GyO�`/U����>tD���6(��s;��s���v���d�}��>
KA��)��,y�6
+��Y!�mU�p��o��f`��2�\	Fw��"����L�:�)S���
uu�?Spp�z��������\�r���c			�F������^b��uj!����fIC����X~����A&O��K/���7����l����M�O���z�M��
������5�~�)����L&�L��y3/��"/��/^$88��p�-�.����S]����ZF��QZ��1�����UW<�g��Uo�8���D���U]]����9���e��~]�"�����n�����g����~�d
�;m<Z?���8�-�>j��&if������7�gu�� [Ozs#��f@d/�5 Z�P���C���<�B���~�*�����)\�����C�]�U=J��WP�M*f���0z6*�c����a���*q�c%��xn��2��n�B��BZv��k;Xt����Z�~�1���oi�L�M!�Z&�'�b�O���04@JJ
V��i���m�6�v;{����nP�/Y�DMe������c�����SoO�	�~�z�n����y����B;w���7���rQQQA``������4==]��L�8�m���o�>JKK	

b�����7�3f�zs�ZL�:�W_}�'N�j�*�t#G���n����#44�����kY��s��������@�������k�q��Y._��_|�S��g?�.�������;wNo��������O���W�\�_v���9<}���n������[���Bmm-������S__Obb"O<�D�4f��B�B��c���o.�f�zH��:���V���~������y�s�`q��������b���%q�n��z��������6�h�
7��B����������.:�1�����P��Q�vg����&��vdT�_vS������	�B�I D���}O�OxS�v���:����V���e�tOR+*Cyi��7lR'''Lmm-��o�	�2�#Fp��)�������m�O���3g���7o   ��{�����9s���a��
�l6���}RF]��o��C�q���___Oyy9�f��]<��c����j���K��%�����?�����;�������|�{�c�������xy�V�X��#G|!QQ���K�f]�z�Cm]���x��
y�����8�;����{�7i9�B��i�&L��g~���������g���ol�����0f�^�[���'���,I31XZ����]A��s�/8��4)�.�1u�T�5�f����]D���sO���]Y��O[����^�e4����Y��)���3��T�5��B�����[��;��s���xC����0�����3��L�4	���,�������M�j��X�h���^WW��>��
�o���v������53����Sj��v�M7����������tO�/������3F?x6�$$$x'�2d��&���L7�=]�sXS�9\�v��O?�O~��_����~�*<<����3g�f��Irr2�������r�J�z��F�[z�"������q��!��=�#�HXo��tl���PP��)��`�mX�s�
����6�ku��n�MZ���#0��<��M�5k�z�155����7��/:Q��`��Rp�����-���p��
�Q�$:�3F(����\j���b����8W%�����}��a�����X�U��yk�]Md������e2X8���� ��I�>}�O��i���k�.Ea���y�����������FEE���,X�@���};n����s�C���j���f���~���r�����D~���������/�KE!55�[n�������#//O�7X�t)C������(*++�����?��������|���nT��Z]�s����-:����\��XX����^BB?��}�\.�w��������s<��s���DFF����$"������_��Jrr�n���w@�
����j������2'�g�W�I%�$��a�#8�����R��h$`�\�:gK��-��"��X�j����B.\�@NNN�_-0X �.���/�G�
�C�0F��}�����
\��!�=��%/�]�����c����J D�{��Y����
��*�q�?���j�5��g�1cX��Hn(��k7L�0����fc����q��������Y�f
�N�������8��k��i>i����	

������<Eit�D{r��#���p�����F����G3{�lv����(���������TSQiM�2�o!��mGj~�=����kr�����6MVS��������p�k�.�t��L&���K]]��_������>k��Gw ���B�5mZ�i��a6K�/�#a�����47}��+h���:���A���g?���`I��!����[������f`��9�$z���x���
�FE����.��bo�'1�y�~��A�Y�����c������=������X�.�\s�`!����B,���nR���wbD[$=::�#F��0q�D�ss$++�g~��E�
�������E�4��,))a���>sn���?�\�O�<Y3{�,F�g[�d25�{6���������/����~�7�{����7������_��u����.HNN��n��>��?�7�q�u6g������7z�MB��JJJ|rnJZ,?};$�9O�������H?�e*j�I�&�L��� (
��[�n������lN7��xO-�����n��uc ==�{�����P�*�i"��u�.����B�G��z��������B�~J5����\@yU1���Fp���3�-�(�;2.��@��.\n��U�Jl9�,��i7�����Z���Oa0��@������W���-���h�=��}�vF������HII!==�;vp�=���A>|�������58@mm-o��EEE$''S[[���9{�,��<��7-BBB����j��������Q�����x��G|�����+�C��z�C����c������ Vhh(f���III�~�Gk��B�������d�5�gb�{>5i!j)LL��W��?�0�f|������',�)#��V�/WA�r�����I���-�>��N���m��Ij�`������u+D�2B���������h$t��X�{O������w�@A!� �7>{����!5��p
��<��{����wB!Z�h���?� <��5�d0pSr_~}�0�C�u:CC�t���l���F��������g6�M���hzYY���������hJ||<����KTT����W��3����/���	�O�8��~X����P+�n���*��������M�����Wg���0::Z
������_�s�f��)���vLw�?;B!���(>i�f�����D�5*���0pL=
�<����[q���7-�����I�1���i����ao9%�������IR$]���lf�������<�!/�z��b����z���v������b��5�G�c;�)��S(�p9���7k�q5��hBF�V��%?��K�n�LIg[����������6
!�52s�G031��%���8��H�	"�����"�QQQ-���p���������~�Z"c��a��������[oa�����`����������3gk��EQL&}��!!!�9s�0m�4�C�����9y�$N����<
j�����sj����������=mp�+]�s�t�RV����^�z5&L`���>k�����6=Wo �!�~)77W��
���U����{�����S�dd�Q|9�������[���QOk��1�4������S�}�/E�E[��7�����(
����8q����,�YX

����~�?�*U`�33�o�n�����w��� �����c_0{��To���C��w��9�<�.�}���a��p���q'����h 16�D��S�J[$}��e�z���^'N�����<���E�/^�;��CMM
7�xc��&KJJ��/~��l���g�����w�A�3f�v�Z��_������`���j��I���V��N���r5�������SPP@YY%%%DGG��t��}�����_~��������������k6�
�\���2�{�=���w��5�
 �Bt1�m��#Gv�����;������1�����C���V�SF�#*����#���q�z�>c[>���
2�_0���H�h���h��������mc�n��L�w?����[�^��h�������8o4p���M%�&��4
�W����_���[ROnI=;OW�iF	����8���B��A[$�`0\�>��Q���������G�RVVFTT�:?w�\>�����0��,Z��!�]�vQ^^���Cq:�=z���"


�|�2����3w��v=A?t�P&O������mF���K�Eaa!���?��F��������0��/�����~�;n������]j�q���uD_�u����������t�����=�c]�sh4������O?�����������g���L�6���8�V+���������n���HKK#88EQ�������������zX�l���=�B�B���Izz���� �H��w����j"G�!�	�����<�}�$�����c��X�b�l�CT���nm���rD\������n��a���,:_�}�@H����q�kzW�9�6zR�]hc�����>��J;?�$��[$W����/��e��C�?D?-���8p@-�>r�H����[��`00u�T6o���(�����|�+�|`` s��e��ML�>���H��}
8�d%x���t�d���|���e����+��C��3�PXX��-[��e�~	QQQ<�����6����x��W��o������_�	uK�.e������q��)~���s��_����������_���+W����X������iJhh(.�������^O��G}��sku���B�+9rD��l�X�2e�n��r��A�w��(v8���g����(�����A�:U���i!co��4��L�+}�V)�.�]rr����v�I���u]*(	��{��t�=T����8�8
WK������=� IDAT\��(�����
�4P�?��D���uB!��v�x��Y���M�����}�v��GC}���zOII�������X�V���1b,`��e$''c0p�\����j��=DFF��3�0��F����)S�����^w���������~��������P~���2l�0����������=��~�������o|���:2�L$%%��o}�W^y�Muk�V+qqq��;���z���G���o��b���RF���-��m7�p���B���k���u����=z6��N��#�<�[!��=�����B�B�C�>�
?�p����w����S�Z�8���O��u�������_7��U�K�k�['���1�s�LO��8�e�B�7���7�w���z�z����m�v7w?�� ���yo�5X�~=�W{R��<w��g�V���o�����fD�\|����������=�t_��I�����@�1����!'���D^~�d�U�r�y���}sfK�v�S�B���#���V;u�T�<�k������L�������su+���f#77���
:th�7Y�UQQ���$%%5���N.^�Hyy��������.W�^�aqq1EEETUU����w���+5���XB!�JMM
�V�W�
+�@��Z�������6�L��{b����aB�E����&�m�?�� ���:5R$]\�9s���'��r��r[8^�|�"�yb����Aq��"\�}��[���kJ� �H�B��[�G1s�����K����u�R�B�B�K`���j���B{�Z��jHt���Xbcc�����0`�~�K��sCLL�����$5�B��o�>\.aaa���5&z�����U4����6����������N;�(��lT������<Q����!>�n���),,�'�`Z�|��R�X����/�������)��}�������Wf���+�������m�z!����(�����[���{ ���n��O?U�C���
!��"�����������cjC

�I���Vqxn_�����9y�{�h���4��U������o�>H�����J�/E�E{�����w/gla�[%:M��t��]�\�S�+�m��`�M�UtFKQ��wC���3yVs�&�N~���`0�����m[/���Z�~=����C|��'L�4���r�(..���TWW0n��v�e"��\���B!:Yaa!���j��E�D'�iY� �H���I�?��x���b?��
b0c���o�<]����ed&eH�n��&))�'u@jj�fVt����9��v�@�'��=�u�r����<�t�4]����������x���W�s�K��o[�����B�^���j���Zv����~����/RSS� ���Sy��'�Bt#rLF!����{��4h��q�]t�����
�vQ7�G�D���G�����
��`���v�k���(����?"�������
����x�����k��~;�z�K!����GO��]�����"p�W�����9�	��8������&MU)�,���`����mN���4fa���&B�;��5����s��A:DNN���CRR�g��� BtsB�E�I�%E��X������B�W{/�M��v���csx
��1k�b�����tw�EO�`h1-��K5�Wx�
�R$]��3f����������%==�9s�������o �|3�.��n���	s�H��Y��
E��f� Z;��g��)����l�������Z$��B��3�LL�:��S��������C!�~!++��2�ix������u+��0X �%0Z�3�� �w��.�����Z8�+����o�#�� �!�1��jf}m>���2aP(1a���/00�� ���-[��4��Ht��Y8�JG����L�$���]i5��v'�������Y�,��� �&������I�%�B!t$"��/ho��;���+���Q����>
2����_����0%,���.q��.j
�/I��;�Q�.���X�qK5���k�8+E�E��R����?Onn�fVt.����[���G��	�b1���~���$���r�p/?�-��Z8��#"�?D
���
���T�B!D/��w�B!D��l���_�K�t?���cw������~�#d�
L9��
�(��.�a�?���a������3��t������L@r����f����?ja� )�.:F���������"�P��PoI���
o���` ��g5_?C~Kr1
��w��g��C|n������B!�h �!�]����l�����L�8Q�Bt����^ ��0��@�x�L�*�,d_V��_6�n�l��gz����!��[N.������XG�Aj���4Ks+d���TUUifE���>���w������{K�=/`N��b������%��L��\�N��������YB!��
	�!��r�v�R���M�b��~�r/\le����{�~�Km:�1n�SX7&"���;�8�b��~�{�>`�M�Y_�WQ^�<��o�[!D�x���p�N';w����*���v����Z��n�`  y	��E���B��gH3A��$��bJB8�+9���]d�yo=	!�BB��������R��g���
�P�����$W5����v������7Y�L������8NnE��`��`9O���KM��iC�j|�Y��d6(�������mn�'X(�@��`��pU���ph�z*{h�,��FN��~�YQa1LJ��&8���������Thf�B!��@�B�.�=�OBB�wR���c���Ug�G����[���,�Ml�����e|���.�`��zT�9z�{�����SWE�l����h�|(--���#�����������4��#�
������l���2�h�7��[��j	�����������
!�B��N!B!����f�n�i���gc0Hq���u3���;����"�����i��U%8���}��[5����A��2".X3+D�����O=��[�jfE�q���A��fd#�V��;i���n����oe�U�z�>�[LNj����A���:�K!-G��!�B/	�!��2������l4�5k�n�����#-��9�'9��=��l�=���c?���$1F��<����ew��~����qt�i��j����ifE������m���K?�cD���G�.��r1@���&�6M�1����D��������B!�BH D!D����?~�Z�W��~��G�g�B���.�q���vR��$����vE�v�S�k�p34S�dON����j62{x�
q�F�E\\����m�wRt7���~�y�~IO�b��e�df�~�p�j�RV�p-�^�?��-�QS�r���#���9�u���<B!��G����B�VYY��C�����s5���D.�~���6-�9���v���Jv���o�z�f��8/�U���ZH���qoZ��IY�m��\���V���;�����C��{�~�y��PN?�cN�Km�o&* ���JX�'�Qo�e��O�5M����j��
B!�W�'n!�]b�������A}��a��q���$�?���s�o�h�����gC7,8��cn����C��m�����6�)�#��N�/�G3+D��9s&�����~�
�a����s��Gz���1\���8l�2�a��d��������P�M�7�[������o�^b�������B!����@�B�N�(
��oW��g��h�I~�	��`�G0�C0����NQ�l:���_4��X������8��3��P��������
2�_��	f!:Spp03f�P�R4�Y�G�.��~��0`��}����(
�����d������_�k�24&P�-bw�9t���/����X�qY�>��B!D�`����}�v***���e��E�9R��Y.��/������v;C���[n!::�g]ee%��9g���d21v�X�-[��jU������tj���_?����7*�B����,�(��`��X����������u
���m�:t&���<#K&wN���/Q���7X	�t����bON��_<Fn����p�B58������gIHH�]$��u���������oM��(p�]��|Wq.�s��L���q������{���qK14�s������7[I����/��e��C�?D?-�B!z�;~������/s��	l6iii<��������6��r�r�J�������Oee%7nd����{s������SO�v�Z��������?��g���q���Jjj*iii>��9��B�9v������K��}5��/��G��m��?��	�?A���PmO1���x�l��ir��]����&[j�e.�6]x���	��Bt��2|�p��e����P�^��4/�
k�)c�X�f���}������c�Y;{P�7P���KWM��Yg��:!�B��t�����\V�^��1cx��'�Z��={�g�y�w�}�)S�`�x�77g��M9r��n�����c0��eo�����>��?��;��Cyy9O>�$�&M��r��?��;v�y�fn��f��LHH�W����B�����8p����7o�fV���?y�1��9���#��������o��u�l�q�_���O�[�����r+���7�����XL�H����9}�4����s�=����V�v����6������{�g�~�G�N����9����k�����LL��������	)��q8���i����f]f�X��Y&�B�'���p���v��<..��C��V=�����"0��S7d(2�;d^�A�<7nDQ���~5=UBB���g��M�<y��Eq7l�@XXw�}���~���l�����c�����������0i�$L&��w�v�"==�'"������S}#��	t+���;�5'���������T�c�2V�Q�Q��AL1C1j��:3���*O�_�J�t�'&M�DDD8�Nv����e���DG��N���w�~��>k���+`�<�a1������~�3������9xz�s3L}��K5j�5�^��@�Bt#/���'Of���q0��r�j�*f��AJJ�>�ddd�f�L&+V���a��������^`��%�Bl6�V�����x�M�
���}�X�z5III<����ZK����|��g���SV�9���Q����[;v��M���g���dff���Om���Fhh(III��;����7�w;v��16�
�������ra4	c��AL�6�	&�K���i�o������7�-�����s>�z���3f��F���#G�t:���S�Z�?�gMDDqqqM����8s�����)!���v���������������U���m���Y������9�n�zO�9���	��O��5�vO��	��{o��	�o��}�����f������n���-��:�<�NA������0�=u��:����u���S�����7lC�%�����������lIEm��!��:%%%9r�'��?s�\���������J�t��n7o��6+W�����dgg����_�a�����w/��������������r��y�l����][6�=�;w����l��A
����������?��u�4�h������z�'�|�5k�����A��������^��g���kP^^��'�������RRRBQQ���l����+W��s�Q]]����v�R[[����1b�~�>}<�KKKu3�.]�x�k�EFF�� /^�_w��%����k��.]�����zy��a���?$&&F�P!����c��x�L�FI��(v��-��o5A�f~N���f2���q7�Vt����UW����X'������*;�/x��.#'���7o�����vSZZ��#G��^g��DP`�Xo!�K��W��=�5�v�R�n�'�`�^,I3����y����qd�.�Qa��raAm�h���B!���-[P���l.^����K�FMM
���
���O���v��o���CBB���~�S���i�W��k�������a2������y37n�`0�r�J��5q�\����TUU0q�D&O���l�������EQ��?�����<x��w��&��o~�s(?**���d������$;;���,E������ �������INN�l6S__OQQ����n�s��I~�������Ln��A���k�f5�d6\���l�_55�k�����<Q��uM����l652r�Hf��M]][�l!''�7�|����������S��CB�!z����ERR���kVZ����",�T������

������8d���iVt�9��j�6p*�/���7����H��`��������7
�����SK����������1��'O�v��&�g7h���#�r7�<�����8�������j��(|@
<��J���Jw_b�C��������{���	��h�
�XKm��o!����r�m�6��}�v���^�?r��)^�u��_[|���j$00�+V0l�7dg5j?���)((`����������������;�{3IB $��Af��Eq���:������Z-�n�~k�Z�u/D@do��%�0B�2�w���{��'����������3n��q�y����Y���e]�t�6��t�Rrrr����v������3g�J���\]KIIa���,^�����M��1c��J�W_}U
�DDDp��w2l�0�}�d�|��g�9���~��1u�T����f��Maa!$==���0k��4VM�n�����5���7E�.�<���?�O<��Q��4i�<���������'O��T!D#(**���c�XN�m*���eA�q������h�>�J��R:������8�m${��[zV��:\�3��fplS���<}��?Na�7�'�VI���t��0������4;Z7K�D�:0k;����u�L���I=��]9��#JO|x�~��1A�u�+���I���9��:������c�����������\���T6����O>����{��� �v�R
��zy��&�x$%%����0oj����7�I����C�YQ�9R��T1�5�|�YGTTs���6J����?�����Ku������#>��|<#�7C�3g6�5+�|�>�|?Fm��f��6m�l6s�W�i�&�������[���J�	!DC��Vl�?o���+�
k��4iR�m�X�C�fu����h�_�w��^�q%�5M����j@�O�Q7T�dCz��M������6�y�:i-?o��+���M�8���S���}={�d��
�
aFFC����A)�P��
H�V��8���W�ky��:����=(��1��,p��X����3�O�������c�Wr�dS���?t�������? {p\}:�h����d��U	���k��!�DH����������pAA�����_��bQ{����������B�JA�6m�����9t�EEE���C��������������<������Y�o�������]��oOMl6|��z�<}�t�������,���~s���~��V�U��x*�s��*++��� 11������:u
��M\\��w��9@~~>N�S��z��X%%%TVV�{G���111~����w��<|�^��Eeee,_�P�?������+O�����"���!aaa��j��xN�UW���o-��q�}AAAjY��x���!�h8V��M�6��q��U��G43g>@=	�"�&�P_�E����m�x���>�����1<��F��|s�A7���I��m�eDPn������~
(�.o��FL&�f�h�B(�
����(�=��N�9�f*V��u����G�)��M��?`��/�f�m
th�s�w��
�9�W���Tw]�A� B�,����|�vEQ��]��C� �j����c��=�v�m|��'����q�F�@�����g��j�����^�����Y�t)s��Q!���Y� IDATy���|��*��w���b�������k����~��\.����v�m�?�~�����[�d��E��O���:����m�6��������7�a�o���]�x������7O=����c��%U��������5G���������������R���_�l�i����~[��l��A�9s�Y�f�c�^�
�{���^���r�l�2F�����}�z����^�_�^=���_?.��r����[���%�Z
~������!??����5O�P�=���bcc8z��fE�$��f:u�D\\Pu_yy9�����s<A�H�B�����?RY�<�0��������\ ����h���H����M��x�u��^o$�}�5(o�u&L���P��$#�{�B����n��a�����J�l���!�Lpo��g��{}	0
�
����4�!��5Cn��W�J���{���N�&�\���������v%"�{��X��B2��9��,�C��[����<M��f3���<���4���S��{�����;�N6nTPu��E���t:y��WY�d	v���H�.]��O�����3{��*D������	j�T�n��b�
��w_�^1�������o,Z����h��V�Z�+������w���&<<\}���'y���(++S��B�����?�����z��p!��o��1c%ch��9���|o��������(F��?��o�>���1SFF+W�`��A���[�C���3B���KVVk����������ODGG�(v��������k�o���p:w���'HOOW�[�&33��#Gb4���O?���������Z�
���Wo-++���NQQ�v�"  ������B!���f��U�x���-�(����z����1w��7[�w*o��N��N���<�eI��O	�;]��
��>� I�������y3�L�9R��Z�f
�G�n�7��V�G�h�r���R��tae}[]H$��'`�������'��X"����o�����M`��t�!����2�[8��)?��f����S�������/���B�x�\/�������+���t�~�z@y�k2�2d����f��u�VRRR���&MR�Q�_�����;v�Pm��YX�l�w��2��>�(���l���w�y��Iqqq���#F��N�Ijj������?���#--��g�D���=z4��
k��a�������8p�������*���KJJ
3f� 44���������o�u����?������y��79~�8EEE�\��o�Q���g���t���Sm:���������g��Yj���_~Y����}������w�^JJJx���2d'N��b�`4y��G�{�������nZ��~�F#z����N�<��;=z4��{���|%2y�d��]����)//'""��k�R\\�C=�F�l6���?q8���q�}��������7����^��k��f��|�rL&7�t�L����U�x��=z4YYY�^����x����ba��9t���A�QQQ���k�Z�\{��U��	!�h8{��QS\u:�_z�h����{��:��7#��@�U9Mdfl�k5;���!'��%��[}V�J*l=����l�R��������,�����N�Q�5`��cJ������K�]��9�f5b?���,�����;Y��;�n7�E�y}�l�5m�cx��'��]97(!�p���������\u��<B�`%[����Q��A���u��t����(A�����Z�6I����Cpp0l���/���@bb"���j��o��u����D�����{���<��#j�F�����~�j�����`���v�R�w���W��b�PXX��?�����y��G����d�]�v�6�NJJ
���:d��i:tH��x��INNV����2s�L�����s�@HT��{Yhh*������&;[i2�����=��SU�P9�N�����HCW��{���5x�`&O�|�>W-Y�B��o�O<�{����%K%M����������'IH�o�4|�p*++�����;w.�|��3g����a��w��^�g���|�������|��\�������������� n��F�M��~,!�
����)������-�*���se��7n�O�R��w-A��9�`���z�i
b@��X�u��p���]�Fw	���y����O�>����5k$r����a8z�v���0��wZ+c�����S�,[��<��>{�N����M�q�$���7���;�=�Q�ctbKv+},�(d��Q����B�A�sP�}h���PY�|}�~bK}*�{�������o_�F#`���:t���\��o��f��I���c�Z��ec��U�<A������+++����[�n�m�V}�Grr������������^�\.���:t(�>}�M�6�t:��c}��_��b��S�N����]�t�_D	V���SRRRm���)''��^z���<@�M}��Y\.v��������PZ3x�����
����x����������:u"  ��Faa!��g��ml����C�r���W	���5J �t�W^y��g�b���������t����u�|�7���rss1DGGWI3��}���~���={����*���`x�~��������`�]�vUj�	!�hX'O������x���>�����T9u`��W��7{2���?���Nn�&�E�v���E2�g���r�����`\R$�<v-��q�����;wRPP�w�'�P�{��lp���,�~.�r:�����^)a�����x���p��A|}��c�vM���C��B���:SAR�`�+�����H�^�P��m�>t�P��C�a�����n6n��w�y���|����~�z�@��
p�\���[9�J?���>hv8>+���w1(
��z�)������y��p���_��)S����_�d	�N)�}]u�Ut��U;�,DEEQRR����������\.�4��s�_����?��52e�n��V���������#G��w/�=��>�,m���g���������V�Wg���L�:�o�b���7��t�R�n�JII	��_�</�k�@�Gu�T_�A<�z�_HML&��<�&�����#�����xHHH�g��>��yr)5�=bg*����e����=�$�mg����a����M�J��R���4�,q�QV}������0�u�K��������v��������b���~%D2��w{���z
:�.��S�)T�|�������=KI���Qm�]�w���7��rE�Pv�R�)�>P(�!D��0��G�v�nJ�(��jw�>���]��@H�y��C������d2a�Z��a7�t���`00n�8.\Hzz:g��Q�)z�b
2���Upp0AAATVVr��)�nw���YY�z'r���ue������1�J �W�^�1�M�6�v�IMM�{/�{�n������7�@��s��<�/�;����x�b��9(YEw�q�����3�>���k������o��O<(2�^��������U�����;�������\�L�l6s�w���Gjj*`��m~e�D�="���t��Y��&(o(��M��@E�����������'����7��k�T����rd��|�38s�/p���]�������t�]����]�e����;�y�������6MQ���{!���p%DN���J��a���u�"�:H=�S��F9���<s�.�+R
��f���a1���f!DK���_��3b4�}�U�W�7A��CP�j�m�]�/C`` ���g������q��!���ej���w�}�~�[o���}+}��{<��7�����M�5j���r�X�t�:8p�z�K��
C��������I�����j��-���~sPsf��&..��j��o���v�e������V��J���}����#G8y�$�w�&33���t:111dgg�p8�m��������������+��R}��s�N	�����B�(V�X���h����bn)N���n{�R�Z��5n�Sbqm���~����y6����U�?�sEH)������*�����f�4I-��#���o��l����m�6@) �X�eJ���s��N�v�BL�7c��Pv��XZ�N��C"��C�6RX���r��p1�^�0'{��E�B���c��$nM���dA�o���M� ���)�
6�B���4h���l�������� ��w��J�
7������������#77�>}�PQQ����9~�8��3n�L���JKK1�L~��|�������Y��3����R���JY���9s���z��Ym�
�NGJJ
�~�)G�Q���js�m���ih�YM���>+�6���!��@YY7nT��&M�1ET4#�\�_��6�f|Z��
���N_=d::]}�\�/|�� ����\%J�E������:G�I��+��
		a��a�x��5>���uz�{]�T���[9c\o��IxK���)@9k���S�p��B|J�!��%t �Y�5���(A���jW��t>���G���/��/--M��e��*}&MR
������[�wFubcc���HTTv��o���g�}�W^y���w����nV���a���z�����T�%�����W}Y,�:8��{6�~���	�w�s���~���o����h��~j �B(�l6�rhh(#G�������������	����7�^B�Uy�d
a�S4;~9��m8N��NW��waMUJX�.6�f�L�y�T���o�����eJ
eqD���+��S��^�v�����s�u���e����"�����[jcO�R*K!.IQWC�^��$����������C�o�~��M����=zt���dfX,�s�^�{��S�N���{�l6��i�w�C�s���9���Htt4���G�O��_�����Nq8�6=���T���C�|�A�������aa�~���c�|�<��@����!��~�`A��x�O@	�����XB!��ba��U�x��q
��Q4d������Ioz���v��O�����#(���;�q|�v�V��mx��7.����������-[||<={����������j�.�4t��Q8t�S���i�o���,���T,�Gs�u�5��1D�y??�!Ftc{f)��rE�Pu]!.9�H�wI��+M��I����k�Mv����y@)��m�>q�D>��C����	0������9s0�<���$&&��=.�
����X�lY������e����|V��7�!==���b����9s������R/m��%,,���R�����ys�����<V�\��/��{�B��q��w�e�6m��N���{��6��n���� ����{�r��W����T�@!��@���Sk��L&����!����>M�u��I��#?�]p:�2]��a�-�t��pW( n`�OY�������+Z�q��y!g�H��!�L����J9C�N�
	Okw�J��`L��0f�<��&���Q�s�]�'�4�{E����'J�+��.,@�K!DS�m����>|�f����$��iCqq1{�������(o_�Q�F���_RYY��h���t�����kW{��%77�3g�PTTD@@�;wf��Q
z��k��8�;v�n�:�z=W]uQQQ���0w�\��CRR�_/��0��t�����,���y��7�2e
=z�hq%����Kzz:�������{���������Os�>��u���3fK�,��w�%77�A�a08p��|�������jI3����s�u��A��7�{�nF�IRR�l6�=��������{}M�;FZZ&�	��A~~>{��e���j�p��	���C�JQ	�!�hN�����+���c���K4[���^���x��Y���z=(q1�J�{C����d������t9������$]�$22���Bp�0��k����7C����e����I����o��u��\|��C�C����_6�G������Sb�
�9X�����q!������&��]vm��������HNNf��U��n6m����S�u����Q�X�bC������)������o��YU�������������Gk�/�}�����>KNNk����[TT�������r��7�������FZZ������G-�UW]���k)(( ==�?����Z��y��W|v��M7���={����n����_���_k��<�����o'00��v�)..f���,]�T�U5x�`��j�������������)S�p���k�D-ZV�O!D�����[o���?���3�5k��8,  @mR'�9k��6'�A�u3r2���)��m�7}=���1>����>o6H�x�A����``�o�!�g�N������>������z+fh�c��D���r9�'�/�c{a8W*�h�fv��oT�}�t0���i��C����_�[!D�|u-�3t�P�z��
>+��'J���4�_��W���a2�'11��c�2y�d����N���t����������>��1c��N��t<���{���:t(?�0111��%44�����t��M�Daa!.�R��>�f3s��a��)��

��k���_$<<\���6m���HNN��<xDD)))<��3<��c�6h�����K�.\s�5������1�����6�C���k���� %%�o^!�'��9��v��|���,[���7={��O���bn	�?
�J}]�]`��c�w���U;���W��]#�!/��Il{~�NWq�@�g��o
��y����{�����oYu�����_l����1��!�-�������(xz Q���@ii)�?�8���3g�����%�L�Loo���J��F����~������}�t�@"_�����`���xy�������=�z�c�r�����cs(?L����$D��K~���/==�A��/^���s����2j�(��_�j����Aqq1���t����L�������g���G��KK���Eaa��j���/~��v���������MDD������6���'ORTT��� 44����_���{@2B�B���U�X�t).���Nee%���X,�v;�f��m�W�f�e���x�q4� HYe	v���r[�AB��}5%U|���sb���@��	�����	�|�^��gU4�N�����`�w����>D)��v���\�^�'����F�=���w��s�"���+�{+}�;	!�h="����w��b�Yi8&����$���%��}{z����� ������={�$&&������t:�������{�&..��>n`` ��wg��A:��/�\� ��B�B�K^^*���V+v������V#6�
��?����2����&���
����_o&V���C����>���7]pL�u��y�d�+��9��;�M���;��U��hQ|�9r���L�U������������^�v�L�nP�����V2Tu��5e�����������}M���t$������`K!D��v�y��WX�d	V������fc��E�8!!�gU�RH D!D�l��	���6G������tRVV��������p��y��g@@�;��t9�!m�:�j�4���{�m�����:6&�4��#�$���f����*5�:VL�U�~0��Nl��[B\l]�t����k�)�P��������g���3
�I���<{��4u���$v����Z�����K[3=��c�
B�K��e���s'_|�=�o���-b�����;����W�k����`Y&B��%�!���9�[S���~��q��|�l�R��#��^7#[��l���b��4x�fG���}��B����	��Bnx���%����i����5I��
���K�^����[�RZZ��*�TD
�z�{p�5�u+���#��HulM�Z��������������/�oV��G�)����F!D�������`���|��W��?�����U����5��4��E��t!����A��� IDAT��4C8��R�E3������(�7#�o�R�q�D"C?k�m����ul2]�G_ExG2�z���>T�5rF���@���q�f�h::����/�v�;n��CnV�m��:4��5�^�����������]�t
'<����f��B�!����W^��o���Y�HII�s���i�����v����y��g�5kf��.�hy�w|B!DEGGs��!�z}�Y!z�k������f�z��{���^7#GN������������6k�<\�J��.��y��5;�t����{���)���*D+�7�h�S?�n�:&O����M��t�x�Y��C����K�]�R@��#�p������U����1c�C�������������E`�1>)��;�X�#�M��1���.�	���m����B\\����d����������!���A��������n�z��Q��8P�*��S����\���������-_��I�����g�q���Tn�H��oF�����)]{�����%D\�1W�����v����!��.:>���/8����L����-�h��\�CI���s�:���?��5U���i7���"�����J��+��GY��,���$B!���@�B�z���/���G��a2��C�z=&�r"~���������f�Q��z��f���7��g���:�2�v���c�2wE1�� ��������
��v�mh��C5;�h��!~'&W��~��� �~0(��pB�����X������p��b;��o����S�3s��y�J�U((����'������f������]B!�-�B�B��N�����5f��^��l�l6c2��k�NG����6�i�Z�z�~�J�?���^��fbY������m����
��]Y�e����<|F��A.7�����	�"1�����5?~�z}��!N�:��*��1:����P5��5��D�{�:��z��t����>W��������dD���6fSi?��j��<NJ�3!�B��J!B!����Tm����������N���O>)���#�N���=����`�U�j�Bu|��[����hL�?�m)@g�|e��A�+QFt�M����u���+]�tQ��r�u���]�a8��o�53�E����3��w�u���J��������E��}�w���S��������g��B!����f�B!���v3o�<��jH�o���n����
���ILL$88X�*�l�|������_��������6����y�0V��TP`0��7~WI�-s��y�]���}v�[�_i�0�{BM�����I��1a��{�=�l���i�
m~��K��+��	��+�S������i����ch�g�Q�i�	����z��x���������!1������3�)!�B�BH D!D����������[o��~�������	'����
����Eb�[�r�Y��e�MlG_q
A�s��Q����v�����<|�f�WF~%Gr+���������<x0_}������v6n���W_��&�J������uP�B�mi�t:L��P���Xw~G�����[l�j�Z��wp���m�.�B!Z���1!���p�\��7O'%%q�W���Z�WP���=�?��|1�V��w�`��/�
��ZOai�v�A9�2���V�������}�lw�)�DK8qi2��������������+��`�����t�
��������(Z��|+d�?]��p[���]���:��
{�W�ng�v�VmC�SB!����@�B�:��a�O+e�t:��OG����-��	��{�13 ��w|�|���8SpR;���4�w��n�rl��r��R1���1
�I�����d�Q�E��4�U!.=�{�V�m6���:t�������~���W��E�4�{}v)��~N��� ��V��B�?E[���7n>Z�O��^n�>���u����I��	!�B�TBQ'|����������������}
�
t���~�������sb�6��7���-���8�����8h�#`��z����8\���� ��y��SRR�[o�(Y�6�
����j��p`���;w.��-��R4��������@Z(��]m��������8���[x����@��n�Y����]�jd��+�j��B!D!�!�u�x�b���������x�����r;!�9���m|�w|�����������|���Cc�~�������f�o)w�pI�xqir��|��g����t:�X,8\.N�������e������B�����Sohg�YO����m���x���=Q��_S��V�>��Q����v��N���%�d�.	!�B�B!B!����3�^�ZO�2���H��Y���/���`�d�3	*�[�C����-��C����T]��Kpf{3:��zLy�U����+
z����!��#;;�;v�v���l�e�N'v������u��U	����^�8��l�`2]���]���e�l��>��|�vA������0��B!�hA$"��������\����h&N���!�7d�i� ����
�C���v7C�����d��yu���|��r*W����N���gGU+�{������dI	q)JOO��X���������p5����>�K�L��{��s%�6���E��<�=�V%�c��f��L����m�����V��@!�B�4BQ���w�{�nu|�-���C4�/B�Lp��p�4\����G\�2=;��N�"���Uv�1��I�hv�;Q`�@��s7��(�U!.=����R"�6�@����h$��4�����!� o�N��Lz����������]Wv��1I�	V��\� �B!�hv$"��Fv���s�����$��C4e?�����8d���^#.�DXp�v�Z��P�\q�v���
Na��sulq'�6|vT�r��7H�h3=�7l��-MD��������^��rHI�F�������[��i�S��\�Y\�!����]U�����MS�S�G��;2K9U���B!�-�B�B���~ /Oi2����1c�yx�����uo|��z���4�������v�ZwMz���v��V��5p*�/}x�Q�hv�+�:�|�HO�<
�N����{���0��n0�����Y]B#�
�L�B�kgZ
}����c���c���������NW�;@�J|�I���x]!�B�4BQ���|���{u<a����|v�f������P�^;{Q�|W^>A;�
0���3��u��f?��k�q�U@w��#����9��?af��yk�q����d����d2U	�`0��W_�]
��N���,����V��|�z�8�3�K_f��=�t��&���k�@lTgu���/�+�V�:���� ��c%,����;�Xw����:@B!��r<K!�����/������p����D��v��[��N�������t�~j�:
����&$�>]s��������_�a�b����1a�}���P��
�|���M�$�P�����o���{����MPP�C�b0��Xw�qaaa�/
Mg��>��WJ_���
�n���.'��>���s�@����'�G�~��������Q\^��a��Uo�������5���@rJl��;��B�&E2chAr�P!D��v��=�r!v����b!88�~��i��������d�f����f�`0`0�K��v��Z���f��%K!B!���k�v�R���rAA�����m��4����X��E��������7���_�6<F���Tn�g�Ie��r�p���]'J�S�zL�%}����'�����f��
j,_F���G��g�L&��uc������P� |(\�?8�08+�������.J�C�T��#���N�qeS������_��{���y~�����w�;A��VXn����}����}�����JxP��!����W_q���V+�������l6ABB���\~��5>���w(,��A�#F0j�(�������HIIa��a�[/���c�X����b8}�4���������=����k���'�|BNN�:u�5���_�m�6&L�������.++������fx���]c;r���-c������D��=��������E���m%%%�t:��k��a�������lf��
�\����L&��^�zq��W��o_�vUaa!���7�t����e?�v�b���<��cT�;�o�>,X��j�j��p8p:���z������g��!�������� ���B��Z�|������.��/kq�E���y�����1Z;����7�������Q� ���X6����C�c�����z+|�Aw	'*��=!.eAAA�y���;�����g����IMM�������U���k��e��E�}��$%�������Q���g����%B�c�Jb���W�*����Q��jb���m������m�9�}��x���z���m<M���@��2;�x�G�wj��%!�h���k�)))!77���tV�\Ibb"��������n�������h�k��[7�������wJ?����~`����1B�T��k���G�U��Y�m�����8rrrX�p!}��F�j���E��_G��=3f���P���Y�a��Z�b�|�	.�fnee%�w�f���l���?��5�y������^���{���v����w�}��?���O?]�������7� --�o�j���]�M���i���=�;�������>o d�������dff��G�2���8������������[����${�1BCC��E��u!������������`�W��U�F���2���M�RU����mr+w,��T)1b4p���hv4���_�m���$h��U�.��7�\O�����h����������;wRYY	��nW�2���y��W�9s&����F4sW�=�v���!���,����th�kd����+��������C'r�����������Fj��Q���rz��h��B\�.]����������Oc�*�����y������^c��N��c����*��i~���n7���_���Z�b}��|����&��'$$���r����nit���
:t�YQ����E��o�>�������YYY|����\.�z=������������Y�n6�����3o��j3yyy��_��������1cHLL����5k�p�����y���x���<������ H��;v,!!!:t�����v����o����
�{-������m���o��ZN�S
;v��@��^�z��O�F#����\�����l<x������=����1H D!����S�\�RO�<��
�h��{+�����+��{A��l����3��x���5�~h����q�U��
�n��������Qf.���*����())��ra�Z��!�E���>#11�Y>�ht`���m�\���u����g�>��w
�V8���������3�L!B�����?�=�d�����������X,����j�*�L���*/����/���n�


��������K��k�.>��cu|�=�0a���/((����}��1`���7�n��:X�C���7�w��W�/�����g����d=6�������U��>}z���/����r���?��!C������g�y���222��m��a��'O�|�rz���SO=���C�~�x����7o^�����L@��:x�`�Q���W;;vL�ZU�~��:u��\AA�g����������e�]���14�W�B�f��r��qFGG���R4W�i���n��M��\�o����"����4���A��
��x�`�w����U�]l<��A�i�3*B�|�Y�P2C|� v���Iyy9?���vY�g���SW�i�9�(�Tjy{������_��B�����������2k�,�z�)>��C����[/���F���w�������gG��r�X�b���/(�	�x�{]��M��������d5%�N�����}��L&�>�(�>�l� @RR���b�X8sF������Cjj*�
������]w��-[���*}d<������*YRC�U���<y���l�u�B��R�����@I}EEE1y�du|�����#!B!���o4��;��()��YOA��a?c��r��7B�p��E�W����>W�S��A���k@^��]\��j��\��y�lH/�bW�K!&Wv?�B9%�v�q:��A<�v;��}��i���`���j�v�(~{'����5��i��2�9C!D��g�>��c����JKK���a��-L�:���������M������<��nk�n�:��UTT���c�����j����RVV(�����kv4.��U����l������0�Ljs����}�(,,$$$�n������a���<�=Jee%m��%))���%%%j��Gtt4�P����~{rss�zrDEEU��|t:�Z&�:�}0�2�[�lQ�7�����y$&&M~~���g������HHH !!A]�5|�p������{��TVV�������������-W�����j�V	���o{O/��&�!���7���!C���Dq�	p�{�
�{�|�����`w*�L"B�r��;4;��L:��>S�A#�������������IzJb���u(Ds�y��m�����}�"�/�8
}x���7���d������lG���~��G� ��B4[��������\.�N'�C�o�	|,\����&M��y����3
����4i��O'''������u�V@�����V��11k�,������������2f��Epp0o��{������W8}��������>`��]~�����s�=:�o��/�d��u~s���*qqq��������o}���~�9s�4x�&��MN���D����}{�u������			���SRRByy9!!!dff���^�zi^���K�Z�����w�������Wi�~��I�`���"33����8y�[��B^!$"���s�b�X���n���Z�F��fX���f9x�g6�Uj���� ��z`����E�������������T�=Ye�)V�5:`B����-DK�9�v��o�zH��T
GD�
OS��C����Lw����r#�N���F#����A!D�p8���p�\��v���N�������d2�p�B���GLL����/�r<�:��^Xqqq<���t��U�t^�/V�����_����UTT��k��%����(//�j�J��K/��N�#;;������(,,��vSRR��o�IDDD��-�N�^���v���������G������={��	
����e�h������k���8qB��������<��N���[�V	Px�At::�����c���;����?��A�j�G��$"���]�v��6�r�-����|��v�a��=�����q3�t9�p����n�I��?��e��%�,om���O��[���}�l�	a��j��*����`@���X�� ��:�B�=�r�_(_�28���*j*��v�b/�������*�Gp�RvC!���&33���O}ddd����B���X�`c�������@�n�.��Pu*++�7o�:������Q���0�o��=.�a���g�����(�v;O?�4�����zbbb2d'N��Fu�������������]�b��}���������;�v�IKK�����j�r��t:7�x#S�N�d2QQQ��~����q�\��?���zJ��3f���od����Z���OS�5�Q�F������#o��v��|{��7�gE�~�dHGF�^2�7��i�^XX����z��j3p<�A�F##G�d��u��������}�GU��N���� ����� �ED,(��}u�]]YQw������������
�����[Bz�d���s��I�4��\���S�l�I�3��<�=y��<o
�.]������S�*���~�f���W IDAT3F����<N�8��A
<��S�n�B!B�VTT����A;vd������;�.z�|��]04�����."�L���:�)���9���=K���mk�[�����Q�syv���&�i!�%&&��={�m�6p8��!&�	����b���j*!j������<�E?TJ�L
����.�L�!S�]�s��EZ������BQ����o�����$X�r�0��l��M]�:t�/����R6l�Y�f��f


8v��6mRw�w���Tj$-���������op����{�n���s��������������<��3��2���H��M�
�����2c�5Hf0����N����� !!�	&��3m�4���GNN���8�N�9BCC	

%(����<v��Z��i��0�o�n���_YuO����sx��^]�����d?��BZ�l��A�X�v-YYY������'�t^^iii���zjj*�N���5[���w�{�n}7�z�b��Q5$�
	�!�o��E���f��)S���1PQK�����v�V����v!?�/~��_���:��RE�p�K(�
�!8��QO�&�o��l�K�-"�\����(B��s�������7j<�_�u���k���;h�������8����M
tV��y��*��}����]0���L�]������-�st-�zB���J�QA����JOOGQ�j����/�]��={��?T������_�<�>��4���-Z� 77�
6������g�={6/��r�.>��}��e~�tge�	�X,t�����d\.yyy
��QQ�������4i�_@��{���G�7��N���������\.N�:@\\�;w�q��\�p���5�c����w���l66m�������l���Kll,�����8z�([�ne�������i���I�J!B�����������1c�����
^�����
�9���o@��|�b���~H`#~7���f���e8�Ym��~
Cp�j���n��nN�I�>�	!���x�����7�_~����i����e�v���=��Sj�����/M]����vs�h�t��_�2p���tn�7\�x>�|�1�FQhw�$�B��`��+g�M���3�����N�UTTDaaa�����b!"�j��z&��#FT;�E[-���SO=�5�\��_��������Wmj���`f������[�1c����<y�u��1|�pu|�������m�n��q�����k]U~W����~mHLL�����nF�Yf�Fk���:t��/��60R���=m����?*���r�y����S�����a0���/+W�$%%���������3����`���G�Mw;p�@n��V�>������Y�l������1c��*���B!B��p8�n[�j��Q�43D�w�]��W����n@�S"%u�����G	.?w��p��h�l�m�8��n7ifTl��\���e� ����u3�U��ys�~�i�l����;���$++���|E��p�;���#p��y�h����[k�M���^{3���A�'uDEZ)
}1�I=X�����y!G�l���o�$�ldB�����	���L/��
j��-�=�������9�s�=��l��t�
6�����@{��wr��7�f����~���l6�~�)�6m��rq���*B~+���n��&� xjw�q�|������B�;��I�+88�^!UQ��Z�w�f����nz��Ua $++K=�Pn-���������
�xO`hObTt�6��oZ,�B������+9w����E����I��
���{���s���@HY���{���$%%��u�Vz����Z�*�
!��"-Y����L�sq�}�Uz�R4 n��{_;�/���k7 �E9|��wR�k\����
R��g�{N��!���+T�&YVk���A�En����'���i�6l����g���70�t:q��|���j
!.��B�
e/:�ej�	4
�J���2�s,���c%n>�|�W���]z�Q!�SLL�Z��j��:b0�h4��A������` 00����L��{�����T>��zu��E3���W/�����5#���111����{���I�&�~6111�����3g6�
�q����ys���@H�'��tOY���S1�B����e��iO�����QQQ$''�o�>l6�zo���w�b��iO����C3R;�D�B������f��=r�H�H���x
���a����o�����zn�,����g1�R�t��p��Am'�cx�7�e9p��S9�4#�T-���j����n��v���8��l���������}{�!�%h�TJo�y����<�F��(�u����Q?���&�3;�����8-��3E|�#�;z�NaZ!��X��������:u���@\.�_=/����j����/U��>���3q�D>��cJJJ�3g�?�|��h�BCC���u���P��l��
>����������*�v�Z�@x�V�����u3�5i����


(,,,�u���<i��6�d��5��=�>��n�O0��	�~������DRRR(((|i�������{�EB7�e��~o��vV"�B4HN���s��P����r5��(���k�|B{��
�����q�*�}��?������)E�%�N��[_���8���}�9
rm�P��+�i ����C�I=EQ���r1Qm��{k�����%to���o�=�J��g��I=[q�k��,����Q!DC`�Zy��g9r���X,��f]�ve���
j���a��M�����m�����@�s�\jj��N2����A�b����`��s�����4��5LKK����\.5h��];5��eKuNy������;�����=
���N�>��
_Z,/�5������E��\e?��P���B�+Jbb"g��|)�*+`+7z�_S�-����S��y����u��%�;�����Q�
�����<s!c��J���
�l?�I��"�B��UQ�,��/Dy�Bn�F�@���15k�)�5�v}�����.8O��`���yu�<�����k,��������&����_���{�B4L�0��^{�{���[o���'������O��4oS�NUL?���
S�Vt��A}|��Q�����'�������Z�m:8m�����G�A�#FT����5,�p=���;�`V�������������������}��� :u��������@H�6m���<6mZ,/o�TQ�9�7V��#P3�����
�B�����GY�|��������s!WS���;`��m(�����<O������c�^{)���c�
�4��ajR��k?��w#P�����/B���}r=�����5�����_"��}E�c�����%h���-�KJN�mLg�~���}j
o<��w���\���Z��T���y���B��DFF2h� n��V�N\\\�M9��Q�(**b�����=��uS���Y�WP�k��������kF��[�%++�/���F[W���C��K�i�&�m�x��&N���Q�^�z�sIII�;w�o��t���_��
7������(,Z�H���q�$:t�L,�>���T@�N���bA������~����z!�����	!��uN���>�H=���iSn��v�,��9�A���v�X����n@'}����BgSoz�����C)��h��j����~�43*�(Q�)�WtnD�H��>!.k}�����cX,�rO{��f�F#aaa�N5!jS��p�Y���qP�-}��i������F�D�K^=���v��x�R]���E!j�w�Arr2YYY$''�c���^.���>�L�]��h������;w��_������J�?�6���m����8u����*&L�U�V�r�J6m�xj��1B�U��}{�9��(��=�����N�:����u���o���/�����p:w����`��}�R@UE~~�_`.**���kf����]�v<s���q:����+�s�=���r���,Y��������>7�|3III�\.��]��ba���(���-[�@Xhh���kU!K�,<5C�Z�h��b��t�IOOg��-X�VJJJ���b���l��M]�>|x�l��@�B�,]��/%�<��j��
������#��Ph�o��b��-|�n��x�H_s�fF�*\��B���`�r���������K���(`62���@���:�����'Ob�ZKM7��j��)S�4�����g0|�t��������|E`��wp�?�I����R�kuy-	!DCf�Z���{��?����s���k���n��e�����%>>��@Hjj*����n?����9r$`��m�������S(��f���?�������G�a����9q����:�<��Om��v�J�����s'.\`�,_�I���{�T��2���#//Om:t���&�5R!��?�N�����dff���K3�������;��w��eKz�!��}Ea����^��o��b��G�;��=%b2��j�x�����S�J���I���X�9Rn $%%��t_���o�����[?T+��R ���������+�������O�����������5�������L�Z2��f��-yh�_����$��p��^m
S5��+�*M��A�	��"mB���f|�A7n��d"((���@�V+AAAj$88��C�����/��V��?��;/C3�������\��ij�G��\B����gO5PVV_}����d2�x��������4YZ�����1���b4o����{��8���?���Jg2���(�>�,G�QO�\���`^x�n��BBB��BBB;v,�<�L�E���3�<Y��cG���R����I�-������2�byy�ceff��F�c0�u���=��_�I�&�z
j�����
�W��[�v-C���B����Ap1�N;f�����g�M�/� �/'%���+8N{����:�s/CAq�����=;�h���:��������XL�t���t�]]3����sJ�'��9�a|X���d�����n���#�q�OKM��I��p�B����R��i���zS}�����h���Z_?W�n+���� r�v�H��n�~<xq����"���+~��g�h��M7��������
����q�'��q(���
�j8�w���������v2OX�������-�4�u���{#Dms��9r���l111e���Tyyy�={�f����H~9������3�L&BCC���.7(PW\.�O�&??���Pbbb�X,�i����!##EQh��)����)UVPP@~~~�3�-����}U�B��o��V
�xSbI�2���/b�B�9�g$9�'>\������JL�<0���AQ(��e5����f`��4H���jA�'88�����;�������p8h��	6lP����������\�B�ch��H���p�[���,�O��hB_��r�
[�����L�-A!���9r��z������h�������F��kG�v��C5*,,��������K
���D�V�"""���S���e�2�I D!�Piii�Z�Jm'$$�����a���}��� ��� ���
�/{E�]�������j���c�
�T�A#��)��7���%$��pM��X3*��m���t����v�m������,�n7�����g�-���5���6�;����.
g��"�@�L���K�����d�����!�������MU}��B���;�������	&p�������@!Bqr8|���j���h����%4W>z��������Xf���.]��,�j+�w^����mK����S3��~L�������p]��
B\:}���������3z��v���`$d�����np�p���x��xL?Se1����y���;��`"6�S}��$A!��-0`999��*)�H��vH D!�@K�,���s����l�?�c��3t��������bs���`��Kw��4o\�yh��og���
�Bn��E��r�~8�I�0�KcL����!�F�.]<x0���`������p���v;��5�G�jQF!j��y{�����6~�������.<����3�7����`��s��?��
!��I]3!.�_9B��<xP��0r�H��m��!�?�����q�!���]v���������[u�����8�Ym�~
cx�fF�m=�ONQ	�Im2�S��OB\�	&�9�KJJX�t)III��������/����~Jqq��J!jF��i#~-�vQ��eP���ttNBO�B���/II]�� �B!��B��
b���;w����X���\8���z-�����IN�y}W����/�+�E+=�r,�c�>F3�zV��}}���$�d�h(��������v�\8%%���u�x�����5�D�-�������o�F3�l�%<A���j���3��9��!�B!��B��
��W_���xRbM�:����)����$��{��i>�?�YxH���Ba�5Xx���p�s(N��pB�>��Keu����g}i�����&��]g��e��������n���������(����'ILL�]-D��tD@�aj�h���+	�[�<9�U�(�����R�r�f
!�B��&�!��B���O��0z�h)�v��^g?������i���������{��.�m�|JN�V�!��ch���Y�9
��im�iF��m���8�N�Ng�'>E�n��b�
���R�H���kJqE+���QZLd+������������kf!�B�� �!��1o�<���1�6H��y]J�� ������0��j���\{3������u��~����f4W���������s�������?��R�������rq��!��5����a��m���8�+��u�U	��n��^����B!��gB�+�����0�LL�:��j���!P�������i�B�O��p����I����wkx�T5����'uc��A����,���r�_t��g���.OA��@}���f!��������������)^��������s�.j���WPJ�e�o��n�Am��t&�.���B!�uI!Bq���c�6mR�c���U����/�H�������e����g��m��o�<���2ks(�h?�W��#$��~����>�s����q�p	��V`�~O�`H��XLe}/B��b4	��W0+������Q���wA�J��:��G�������&�`����W�Z<����s�t�U�!�B��W��!�
ZAA�|���n��5�G���
����K�A�
���]���;�k_�Y-����S�g��G���F������ng��7�~��4	k�{��Sr|'�
��v`�������Q}�O���Y�2`X�,�.��1�:u<'�c41�L:v���F�[t!��]j�x������&�#�I�_���3��[Uy�!�BQ�$o�B\�>��3���0��L�:����!qC�}P�kZS#�4���O!#�4//|�"�'M���3�I�V��9��nv�Q��,~O�S�x�F<��U9��M�/9�?]D����y�]�=��$���B��r�-��������20t�P9"�D��Gp�[�;?\N�_����y"�x�H���m�X��t�����G�f
!�B���0VZ�BT���[��e��7n111���;����k�����(��/~�(
�0�<1�e:��V7���|�7���H��1X���*q�L���������h��[�+�|U�'�������WO7Z�V0�L�L&,����F���7�W�Z��d��|��j���������o�����y/�N�?��!�B!j�B��2������v���>|�f�h�
vA�3�v��}��]�������9�}B�{��FX| IDAT����
�Y��y0	�������b��Z3�r�����d�{�y�����H�,�w!��c�r�=�`�Z1��X�V�V+���@�=�>}:Vk���B\��.C�t���V��8W3�lSO���ZC��,�������!!�B��"�!���(���((��+
����X�w1�����b���@��5������/�$�L��7i�#�~�fV�P
/P��L�mn�����������O�Z��|n>X����B��`0����9s&c����k��s��<���Gy���p�eB�.���[���RT
/P��m���5�h�����>����f�T��%�B!j��B��Lrr2��oW�w�q���L�jQG������v��`i�k����.����;���}���������P�����`02�%0U�Ve��\�ij�T��;[��1��,�
�P5i��1c�����7�����z��%X���_y��^3v�d���S��YA�V���s�n�B!��i�}X!.#999,\�Pmw���o�Q3C4x����;�v��Y�S���Kg���
j��n7q_�����}�2�}�R����7���)�wUh����B!����Y{�]����*?���7>B������+�����43�B!Dm�@�B\&Ea���������P�����8�@�}�v�5��U_��((|��u���T�zw��Gn}���o��g)Z������K`�;53�.���wU(����BLfBn}Vm�2��m����q�����(�����&��2�C��i��_?C~Q�n�B!��I���!��Fl���={�������&M�?���*7���LO�]�1�ZSP�t�����+P~u�^<1�eLF�ff-Q�����d�!�!��
.2T�TZ���7_!�0�]���8�]����}x_������ym(�?�JJ�k�m��w�������y����f�rKp^!���\�*�B�:����_|���u����53D�w�pa����M����'��������������]���4�j�m��8�lQ�!c�ck��Q=�Z���*tu�}�BQ%��~&�����x�r���Z�J�s��L����}$����f�B!��IB�NQV�\��f 88�)S�HJ��I�8�W_;�6���k��o6���u��������"0 X3���2�(Z�o�pu�FifT���6���b��3��`�ih��8���3>L�-�BT�m��*�
���8L�w���ik���nt�����S6��A3C!�o�R�{��p8l���M�6q�������l�������f�]���r�p8J�(�N�A!D�{�n�=��'M�D���}D�����A��F��:��:(@^����|���j�eTk�����6���E.'�f�)C���2f�nR�
�.>�|�
����*`60mp���2!��L�sNS��LP���pJ��i�_��3�����L���3�m��VM���B���Y�fq�u�����j�\.�������g����
����%K�`2��>}:K����������-!!�6m��fx��v�{�=222�2e
�:u�O�u[�la����o��x��n��o���~����tuj������+�F��]�v�+JKMM%11�}��a��1�L���3d��
V�fV��Nbb"6l ##EQh����w���o'::Z�j��]�\��?���V�z{������0e����/g��-��vN���M@@����k������� �!�h���?��?����w�N��}53D���������F��,�[�e������_j;:�/��]���.�V����T�!��
CP�fF��nf|�Nf~y;q���y0�� &�j'G�B=����U����=�JB�y��7xf����;�y������|N;�3�V��F�!*��E!���eee�g�
/�@�����w�e���t��U?\.�����s����@�������H�X�6m"99����/�f�����������������w�O���3������MQ�}�]~��g�.\`��������y���;V?E�������w
��r���Nzz:[�n���3fs�����l^}�UN�:�����ORR���<�����,v����]���};��Ea���l6&O�\f`����<����u��RSSY�|9#F���{�-�9��?}!�
��(��?����\���h�������v�s1��������V����E��o��C�FM5�jW���'�U��>�����Q��S�U)b5�!����`3W��{�FrD!�%qeU/����1}�*&���>�Y_<	���<��x�
sP~M�����<4���U�+U!�$?��#�������S�h���~J�QXX��o������Cr������l��	����~�i:t���Y{��*:�P�bbb����d2��i���k�������`0����������~R� AAA<�6m�`����o[�nEQ���K��������<�X.�|�

e��DGGs��iV�^MQQ�w����?g���~��\.�|�M5r�5���O\.[�la���8�z�-�������1�=Frrr�����4rs=�N�:Ell�n��A���E�F#���?~�={��(
�V�"$$�	&�/k�$"�
��(:t�����ODD����i��I��W}���gE���?����!~��]�l_���g��&a���������W���Q��9P�#c	Nx\7�b�s���z��������p����[H!��2�S$�\����a w~�E���[xA7RO���'����0�G��R��J�r�X�v��^�~=w�}�oBr��!�y�����C����/� H`` ��O�m��M���sg��y��=[��zmz��'��y3�[�.3��l�2��;W�"~U]u�U�l����_���4�eoHHH`��%|���|����!N��O>���^|�E�7�}�2d�>�,EEE�Y��1c���������0j�(��U#F�`��y�Z�
�����K���{�q/o d�����v�V�n���m��������G�A����������Y�p��,_���n���S����I�&��\�����=�7�x��K���O?�d��-[��i���������`����0GB���P�~��-�/{Um7	k������u (^�o\�]���fb��T��'��� ^�N���B�Kb������)���#{��l��^��.a�����"BQ\.�&99��{�R\\��Ro�o�NNN����q�E��Tn�g3�^QQ�|�	3g��� ���;ILL�h4��c��y��s��2����I#���C���o��9/��"O=��_���oT�Uh~����?�q���A���c��<Am0BQ�u/3�7i�$��������,
=���v;;w������}��8=���#���j�u�x��N�<����U|�%��V�<y�W^y����(��xrML&������%%������p���y>X+�mQ�Vm[���_S�� �{4o\�_�3}��������`�+;�iE�V�K�BQ��!��	�2��Uo����e0b��6}o)���J���)q9�`�,^����BT��($%%�p�B����~��LBB&L(wwy]������$;;���l����5�\����l�;w������R�������� ""�T����B<HNN�5�y���������k���#�<Rj�~���l���lbl��?������8>��c5�s��w�[���l65e�WXXAA�
kv�]��x�sss9p����DDD��cGBBB�k�<8y�$����E��kW��FVV.�Km�F��Xyyy�sJJJ���K������r���������5Z�7o<k8�
��z����/�����6l�Vg(�dE@@={�$))����R����A�RRR��D�����'�vYA�������r�\H D!�������?��pPRR������b0�d2������__�
�h`2>������&���ul����x�l���)���:�(�
�<��M��4���Uj5��*R��B!DeA����
��N���8s�.�Q?.w	����.W�������IX3��BT�����7������r�X�|9��m��g��0�P�233��g'N��O>������$�@����o�v����(�z��r?;k�/���j ��������������n�v���l�>}�7�|���g���n7���L�8�a���r�J��KLLT����j��@]��u+�����x����w���[o�E��]y��g����HLL,�:t(�'O&--��>��T�V�Z�����J����/�6��������.\��������gy��'���hd��j���9sF}��(��o���_�D�Y�fQ\\��|Pw�\�I���x���8}�t���;v�t:KU��A�s����d��geo@�j��m�$5�B��u��q��q�nw� x�T�v�Z��+��T8�������Q�����~A���hf�����4��F��������h"d���w��s�gRUu��|!��*�N��
�,"(`�>���O?R���l�_SjV��l��N!���e����gQ�s��������ZW�E����7�z�<����������YYY�*w�\��r��������?{�lq:���fZ�n���E��5k�s�=W���u�]����>|x���8�NV�Z��d������a�������|���DEE���n��5k���o0k�,N�:Epp0aaa��'N���W^���z���F#F��2���h4^��~U���C}|���jF<v��y�Hdd$j���F�-��z��]��L^�@�����l���[;����s8��TU�f�����w�Y�I��JN�!Ds8,Y����W��'�X���`�X��gO��D=p�R�pp��;�����9�|���[������b�{j�ix��^��p��}��F ���1W3��V����kDZF����F�zn:�B�e04�!:�h��8�����sl7�n���c�i2�L��)���}�W���l-Z��.��={��y3�����*����u����'V��>}��v�Z���2D�������Z�nW]u�:��}�v5��Q���+V���:t���W��l�������Ennn���_���JRRR���{���]��-[�p��y������c�������V$�{������������3dy�����!C�4i���8���;/^�������_��3g�������G���a����~���s>��s�\.����:�0m�4�M��O<�K�����j���b��5�'c��^x��������M'f����U�^��L@:z�(�:u"77�S�N���B��=�96�M=}2t�Pu-*==�����������nrrr8p�iiiX,&M����#��4x���Bq����x��W����\��I��D=R�pb�'�U�g'��U�.H`k_��((|��{�o�\��i��A����(�y~���6��B���53������Q����]���<��N�!�Ua��D���
n�������#E������2
FZF��w!~#233Y�hEE�;I����Y*�SE>��S~��g}w���f��X�*m�to�����&88���"��_�����c��:tH=1�]@X�v-���
�x�x�����Hzz:+W��n������2�Rh[��������f��������7��c��Zs��J��M9}��~�LC�a��ij;  ����s��A������{z����������f����'��
�xOL�S:��5k��i����O�f��(m6��XJH�l�-�;���������_�U\\�~}qqq����x�b�m�FII�z��]���&			l�������������ZF��Q�F��O��eA!BQ�>��3233q��(��D��w���@���T80
v��;�y��j�4����#

��z����j_Ld+^����]\��KU�b6��_&!�f���w�:]
o�>�����Z�L���a���Y#�B�(�	c����o0����|�q�~�L}:�@� ��B����e�}w����)7�VU����9s�T��W�[$�Q�Fj�l6��G6n��������[�NHH���C��v6o�����T6l���^\\��+j���_"���{�u?�?��x�R��n"##���/�>}�
6�r���};����>���]������U!�[����
#//��4DC�����_
x�'N������������{�������>���c���g�������/�����{���{w�W�e���l����xrrr*-���kW���1���l62228~�8�}�+V�`����7�Z��M!BQG8��<��vL&&�	�����e0�7�:�FE�r�a�(�����`����{k�[q���Y�������i[����D�������u�w&���������fF���
��x�g|;��nBL���'
8_�$8�D��`�uiLTh��M$�BTf��IN��3�+_d+(���,&����#<��B[���rM�����F!�d���m����I�����"q�>}��q#������������}����������u��!�����vc2��Nth�T���
�Si�/���S������g����K/���(�[���o���Pvbb"'O�T�^#G��M��yj022�����9���>(3����_�	��s��'�n��6�^�������G;�=��=��M�^��-��oZ,��bbb������c�����{wEQO����Mv������+,�>q�D��o�������~��={X�x1n��	&��i�$"�u��F���y�!e�qZ,�F#������C?,����*���fH����+�H�q�Kx���y�'�'@��N<w��i��Yw��\��������x����Q�����X��7�C8��6�`�RD!�e.�l�O�g����T�{t+3>�Jx�(v�m�3M�>�~�����E!��m����k���Sc9r�
6�����}���b2����W�v�{��C���^{-V��������v��L&���%K8t�g��%::�������_����`���(..����(�R�k��.����p:�~k�&M*�����_=6l@QRRR��I���[=����W���lk�7��7eJ��K�l�BJJ
�9�2f�����-�^oJ+���3����^n D�K{��t��h$66�;�;���[�:u*�&?���o��������������]����O�O>�$���,]������&8+�!��#�� �7b����j%  ���N7j�`0p��7���(��g>�w�/s18�<uCj����?=��_6�}�b�a��o�H3�n�������9�������W[2X{�W'�G\#��:��B!j]|���������;��[�I���]��[�����8�q2k/��v�h�v�����K5��!>���
7����2����}��N$��`00e��R;�k��HzTT;v��{��$''����������:>l�0�.]�>�]w���8w���X[$��W�^$%%�����
4h�:�v�Y�l�����������y�{JE�}z���K
Z��r5i�����u ����-Z��}��4V|�����w��,��D�F�����t��GFF�� ��.\ 44Tmki�[������V����_~IAAPOV�l�R
�h�9r�Z���
����U�V�r���g�Ok�$"�u�����p�\8�d��
622�����ys#��#��]@�s{
�G\����(�0��'9p�Wd���}y����Z��%��
�)�n|STk��jZ��<�������Cc1%
"���`�2i�#�}���_����"<$���[q3g�����?�e*o���3�j��3����!D`` >� o���~���#G�Y�������!������ IDAT�_�����g����������w���i��]�)�o��6�m�FQQs��!##�������"���{5Q�����h\�������Z�����6m�>��z��������������7�x�j���?(�
����p���]��_��U+���-���x���i�������M���];���HNN&55�������� ==��C��cU�=U���:	�!D���g���v����r�0���L�����k���|�'N���@�E�2�����*�0��>����{}:��q/a1���O�V@������e�KJ����|�������O	�0KD!���`0�_��h0W�z[�������N�����B��G&O��_|�W�@���������w�*o�t���4���4��m���{���/ePBB)))dgg���Brr2�	��%&&�?������;dgg�x�b/^�7�{��5^��e������p8�L��b�^r��G[���������$"""�,��LDD999�<y��^f���G��_�6�������F�^�����o�b��A���O����	�����q�Fl6�K��1�Z�"--���t��:
�������	!��Q�l6�-EQp:�8�N����{��~E�D=
�S��T�T{��2rN������ C���'��Z�A��U����k��d&������n�6�e��3j�yX�)����{>!��J�M�U9Eq�����B���t�M��5���{�e0���#������P��nm�I���d������=�a����u��i�����h��98����v�����1p�@5a2�����W�^<���<���5����N))))��9���'�����EC�}}���P\\�G}�����>���53��}
].�ZV�[o<H/������2�;���������J��J�B�����`P� ��X^����'�
�VD[��&~/���B�TRRBZZ999��M5�cJJ�Z�j��G3�L&5����	�<��3D��s��#ek���{k����xi�cj�p�[����
�w�%gz
���TA7<���������u����!���'<Hn]�B��e��6	TEF�i}�B�bbbx��'P������0����[[$}��Q�r�-�>��_<���E�G����s�����/�������^�l6������cG����<�Q�����w�}��+J�8q:��X�Bmk��C����!\.W�������0��=Kvv6YYYDE�L]��r�����u�]G�>}t3���W/�l��7�|C�������={V=���m[���������Y�fdddp��6n�X����_~���1B��������H:v������ ^�k\.�����*��w������P����	
X��!��EQHJJb��E~y;�F#�&44��D_��k�@����y|������5���� 	�����E��������m��Tm�������zz��cm�V�iO��h������k�bEE�=��%B��M&3s��2�\��dx?����^iX��o����~������[�:ujX\������U�����#_�F��]G��o.��s������'�N���S��������?���$f��!#������H�e����';�2$�c�n~����?��h;?�?�>���/"""��g�O����x�<�vx��zH�am�L<z�h������`��]�������O�>�7�x���:����={v�����YCYYC�����k�.N�>��S�(//��p0h� �O�~^��:t(�&Mb����Z�
����9sHII�������_=zt�Y(MFF����<y�^x�����d���.++�;#,Z���|�;������2N�8����{��a�����].���Z��ps��	6`���*�y����)((��g���;�$!!���[oQ__�a�u�]����r��������j������b����[�l��kl������5�h����6B�|}���f!��m�����A}}='O�d��M������8�+�.$5BDD�����h�"����@S����i<��Q��}����Y�z5{��������x����7�<�J���������_?����u{>���~��X�j3l<z��13g�e��g�VP��"<7@]F\2DE�/?����F�mO���i�	|����7�n8w�!�����&���X��'�
�_����KDD����?��'�d�����!�ng��-�C�G�����P�a0e�V�X�i�|����r�-�|tt4��O��O>!77�������5n����o�[K6`���,Y���~�k�������z������r�����RRRx��������;y�����i�6mb��Ea���`��9|��g���r���x��`.##���������z^z���m��-���
6B.��������={����O[��[o���&��Y�8x� �V��������Z�������?kl�XW�4�����W_%==��C�
�a����9!��������Xx��6��M�w(DD��>�����0M���������r��HOO�?��������'/K�,�~�?����`���PsnOL ���H�?>��:�~�<��F������K&e�/������'/`��spW�{
�\��~-?���u��d����B5��M@�Q6��9��[����4�s��|��}|~?m=�1��P���o{�K)�0m���L�rssY�b�+����>�������<y2��s+W������Ezz:�\.


��{7>��?��Odgg��X����d~����x�b��]v^�aL�<������
���\�q�z�-������������O�h��&7�������Z��|��.�y4�_������kl��5��@jj*w�q��O�"��?Lff&���>������n��+�����6III�xii)���@�����$��v8{���hRSS)**j�����F\\ ''��3g���������~j����	��3g��E��R^^�������zq�����O�7����0���n���:k�U��>U�/6�>
G�:��`����v�?�y`6@��un�yb�~���������X|L"?��s����Ow�.�/���j
7��	�s��5��5����`�������-9�g���[���S6Dd������3����}�g��o�����S��������Z2�w������Z2"����"z���x�����0�a�������)������������~��%,^����Gm��vg������OEEN���C����K���OSRRBfff���{���B���p�\$&&���z��ui��������nz��Ezzz�����"JKKq:�����]�����S����������>�!""]�c��^/>���&9s:��������|5��A(~�\,����.�v
��@<�z~��S��8X
�or?�����=8d���-���&@�'/�=[R�5���g��i�=����9��%>^DD���c�x}
���U�f�9hbl/���� "r�;M�1c�_�����_.�����tDjj*����p����AFF�5|IEGG3l�0k�����HKK��;%=�����;5BDD��q	ekM8�?}��%#�N�!�}��<�	YB��s�����g��
�}
C�G��������{����k�EfC�[�N��G�����p%�N����?4���p����	=�)%��n��[���1�X��5��Fu]}����9�������^��DD��i��_��1c�p�
749��������?<��?�&"]�F��HDE�h[K����*_8��v/�?�����P�!���������Xr�,9��]��)*+�r�������������W��w��5�*�����������'�r�;;�#���j�����`X�����~f
��H,]��m���m�6�{�=&N�����|�e����YYY�m���\\�#'"��O��uWc�����"�����
E	��}
�A��P�yxn�`�/��8o�{�m�?���u�����n��y?�n�8_Cs|%G��6��,�Y���v�\����-��HNN&99���rjkkY�f�uS�L��G��E���twUDDz8�4�[]�l6


�Q�r�ap��g�����l���j�5`z�� �8�2���\�<(�8���9Yr����~c�4b.G_�\���������o�z�[���R��a���P��=k�ME	�y{s���K��"=)|Y��������4m�4rss��u+��m����TTT`�z�"33����Z+ADz85BDD:�����_~����c�����L3p��n�/:k�,�/�J?��?o�	b����@��;\��k�o_���}�2>�Q}��;h_��(��;��[~�5�����x|����}�g�������v�8�&J�q"z+n������DDDDD��a���2e
S�L��D$B�""�A������7%%%�Xlllp5HTT�i��2u�Tn�����r������3k�u����1M?��������f�u��8�I�I����?=pB���_y���xv.�[����[b_v�$?�L`Tz,s��X�""""""""�F��H;�����+y������������;��555���{�������fc�����7������$\�1�<|���h��M����9�|����u$������2x�����k�5uA��*<�W��[J��-pv%�U����f������9H�9�A�������7A �g4}D2�\�FH/QDDDDDDD���i���j^y�v�����m����y�0���x����b�&uuuDGG�y��\f`%Hg� �J���F��[���~o
�hH���1�����#<���3IB��G����3k��~D
�@��������?g,�w�G�1�:�Q��[��(-����X��Lbl�8kZDDDDDDD���i���{���HE��'����x��G5jT���0����Mt�����l�5�~���h��;����n���M������pds����S����)qf���5{���4Q�'�������=����+��I��u#qs�#p&���h��j��n����y�1������������;""-�x<��oc��a���,|�A���M���}uX��n�wUIE�5��wo=�����o�xO�4?v.�_Ul�-.g������G[�Q�8b�����1�U`�c����0M�hg	��n�@`+����	""""""""��:��4���������:u*�����;�d���a�K7�9i�t�
�������Dk�U�G���Y!�yK�����#�4���9�:�9�q�lv������W������l?^oM�w]q~V���������4G��,��IAA���x<���5jNg�Mg��������+0C����?=��
-���7����k�v���+,Z8��j����fQb��Q�k9�������lv#���3��k1��]��d
�����Zo0�;����Y���_�?�I�x��~D;t���������\8j��H�;u����
�
������o|��S��m�6/^LYYYp�a�p�
�v�m8�`\����p�k�m���
�?h�t���]�i���	b&�^}�5�"�SG��U��-���:���C������8����dM������5��z�s��K�������[�O���B���������8�7��*'�����o��+�&�30�m��Q#DD"Z^^�����z�������4Ml6�������l������}���MOO����'333,.��;����fZg��!OB����g�v��������r�2k�&7N����WZ��>m�>�#�~�������:g�<\�s�%�������|���o?�����6<�oOK'�e�Pq/}q����`�n3���i��<n$-������RGDDDDDDD����U]]����g�^/


444���v;N��]�v������;w.,�*���[�~	����$�@��$����X���>����}gv���/_a��������Q�RY[��f��2�N�6_���5`�xw�����O���ZG`KL=����=mD����������G8r����X{����5d�g����/��]<:3��}���[""""""""]�F��D�?����J|>_�&�������r���q����o~������rQ����},�eU�4H�F�[���������������>��~���p
����9aa���r��m~�#E_a�~z'�q��������
p��+���+_�Z��24}�����<	���z�����Ee8�\I�
�ncX��a�����������K�i��x�c�z>d]?k��-�9�Z�����e�����������8������������\Bj��H���5p��=wx�����4M���[oe���=/����
~a�Mhn�z������6X���c\0��vp�!0i=�~J���8R �ZH�����(�*�����]G���K*��`�_X�g9��)�����e���Y���&�R���������7b�mN��k��sm�|��s�U�xv.�������t���s�t���q��#�}+V��T����J��V�Kr�����Jo�$�������(-
������������v�����T�n�:j�nVul�1�P�?<g���O��	���p@���_�0M?�����s���#g��8�/��fM��u�WPV}�:��^�~���������X�]�g��x�������e��c�8���w=Ft�u�y��XU���-������6�]�7"""""""�}��.��HSZZ��fk�	*t�,���<�r���o�v��0~
�i����|�{�6A�=�|��
k���c���oq����mvk�)���/�~����M���p����5[b�~��q�����%Q6CM�����Q__��-[X�n{���V�n���=����h��!�	�8���Z���}{b�X3����w��6E�L;��W|��c�FC�����f<yK����]m�-�?��y8s�a�;���`j=�7B\���I""""""""r��""=���c��=l����[���4���p8�g�X9�N� ++���TkZ.��e@�W�3��o�vZ�������p�f�,����')��5�4�����c<;���n��
#6	��qe�#j`\�-��&�9Q�����t�����Hk�����DDDDDDDD�5BD���z������[��m�6����>==���(


��������V�DEEa�������{[?CB. �Qk�u�rk�K����4q���� ����A<;�Q�s��B�����������
�������c��J�������R���������������H7�F����������m���c�����C���a��)L�:���L�����_����q:�������|���kJ.���L�J�F:����5���v���HK`
�+9�g�2<;��+���lv��pe��1z��r��b�J�l8\���J�Z�+�egL�X6�����cR_���:"""""""���""�Vii);w�d�������s>������&77���l�sO������#�����g�}��#G�x<���2i�$����l�D.��k���%]m�����������{W�*�������a�������k9������gy�a5x"��y8�]���FN{�&*�cS~%��Tq������f�3 ��G$1iP������S�54���0���>,��mM��������tKj��H����9x� ;w�$//�����������g��I���c&''���kX�����k6�}j�4eD���F�e�~�������q�*
ZZ�NAQYnO�+�B=r�c����ex��������9~���cKL��/�����5l=Z���U�n{5*=�����rh"������#���{U�~v IDAT���WPMiM�.;���qSvo��m��MDDDDDDD�;Q#DD������;wRPP�i�ddd���Mll������b��]����{�njkk�C�bbb���a����?�K���T&&�5��>��1F�6�_�e���'!.�
�o�cg�&�|�%��������fr���6�z�S������Q���
���Ao�j����e����+k�^�t�L��������~���G��QP���U�2Sc��H��DR�Z?�$%����������������\jj��H�������y����V�7��
�N��a��>5M�c��W}���c�pS --���lrrr1bv{������=����K|��#*j�H����Y�����pzj�X�'�)�AX�4�-:H^��Z��c;h�5����L{=���#����������w��?~���Ma�����3[v*,`�3g��Ys�[>gk��~>�Q���JNUzp�
��������24���CqUCp���S5�[��0�_S�$2yH�b;�����""""""""��u����\������t�R|>�ib�&v����Z^~�e����������g���������<***,�����(F�Ivv6YYY��]�-�����p����).?y6��^QS�����a�g��m!�X
%K�}�I�4
���������#�9��]���yd3U���%�1�f3e��5��^M9�����a�(�.#�����0�o�5l�2p56?R3gt��S������s;��&{N���d
WI��k���2�#g�l9Z���U/�^g��de�3ip�'�`��JDDDDDDD�r�F��t��������x<a��744`��q�\����?��A����dgg�����1c��U�qW��o?AYUqH4|��������_�{����@}���S�9�c����}����
�$iI�+�	��bb��Lq5	���!a��x�|�g�
���H9�~��^8���s�
D����G��/���������|��o!s�zW~��4X�%F��8(�I�����e��l�""��[oa�f�&H#�������t�����j�06lX��1`��&[hId�����4A�WRy�_.��S�j�O�o��0����a���~�Oe����m����&���x�~�g�J|'�YG���G�W��l�	�hGA5;
����?����	L���Xl]��DDDDDDDD"R+w�DD���������6Ay�^G�������[^���[��HU������6j����v��n
���DF����_c����E'X��3�x������=+�������s��8����>��4?�T������jP�IN�i�e�9z�(��-���$$$p��Wr�5��It�(/������D�i���7��
f��IT�eUr8Yz�
{WRp&�=�����:f6Iq���"������%��)�<����|��3<����hK�3�a1�*;�p��p?�5�Be)F�>��� ��&
���{x#���h8���3a�P��L��f�7{��M>��r���jS�Y��s�}��������t�esGe�����W�`������-[���W_���ZF�HKbbb���Vmi3v����	��5�������?����r�W���n��\7�f��#�������R*j���.������J��)�>Cy�J�NSZu�������qs��9�a�#I\�k|�6�D�+�����o����81��������x�����5���Q��3�������/�zo��l�5��g�;��.�;�������������O��o_������~��+�5kC��^&"�HII�W�^���a�����o�7��l�A||<����tD31y���l?���6Gm}5�_�sN��������`L���SGm}
5�*j���qWSSWI�����J��*�vWRU[AUm9�u�T�VP���~��n����%�G����9�!��4AB�}�'��{r/��Z�f�1d2�1�q���-1�:��KM��vVI1Qj���������t�e�Y�~=����s�=������xn��v��y6l��F�H;����sY�x1N����i���6����9s��la�H�r�l?�h�����k���Q39 ��cb���PV}�Zw5������P[_Mm}M���
����l�+:��l6z�}���&{m'�m55y�5�����@��E�t�Lo�nk��#s*��3p����drQe���EE]�����2���ODDDDDDDD�M�E#$//������������!"�~�f�b���|��WDGG���<3�n��a2�9s�X��l>���W��nF�%�����������<�J��w�����5uU���W�\l��x��z��BJB_����+�����Ob	�������]w�o�S�O��hg���0�4������������9f&Q�r1��\w`��?-��?-���H��s��TkXDDDDDDDD:��h����
Jbb"�aPRR����?��?�����q�F�����L�0�{����[
r��+*k����*=���~o
_p�('q�	�E'��'>&1�+:���$�cH��EBl2	1I$��"1�{��k���o�`��1M���y5�FKk!����j��z��d;���<�WC7�w7eh"3G%�j�5��|gz������������t�e������p49��0�N'���a��X�j�5$r�9r$qqq:t���
L�$))��C�2p�@�m�f�$�������+�a�i��u��������:�����������V��	�������:��uT�� �rM?C�&��8`_2�or��OjW��2���?��5���4k����7mR��6����"V��������`
��o}+���G	��L'N���z��g���2gk���}��m�k]`�Z�>�H@$������o
���e��;a�����|i���222���V�#�j��>��u$���!�hh��q9bM��
WTv[F;���T�-�k�f�,��(��I#���g��X�uFM���5x��P��8��*��
�����j���"=�*�3k("��������7����{(��5$"""""����;F]�t:�z��|>��s����~�^/���!�;f������\�|>��
u�Zk�Y������^���8p���	��z���)@��&t����x3���0��QN���F��?�^����~�B��f���w���������\�7"r�4���u�M���^�za�&ee������c�&��:�VD�����W�g
����>l
�x���8�M���e�=�w`D'`���-)[rl�����&f����2�[Z&a�k�-8��f\��~��p����������<{�MD�<���{�>
��m�����#�[�=�a#���p��M��F�m���pY3��$��"��7�.������0q7�kFDDDDDDDD�L!��������jY�b�a����
�-����\3~f3w�m����y����ck*b������8�^aM`ON���5h�5�������!�����t+Q�rp�B���Izt11��(��2�29#d���8���<��y���������c��Y���[/����d��m?c��[X��N��n�bPj&3snbH��%��+���������pp����DC��9��7/���1�*kXDDDDDDDD�U�E#�f���O��K/�q�F6l���ng��Y�w_�������S����2"�a�1r:�H�LDDDDDDDDz�������O<Auu5���c&"""""""""""��i�4���'>>��tY�."""""""""""�'5BDDDDDDDDDDD$b�""""""""""""K��Xj������������H�R#DDDDDDDDDDDD"�!"""""""""""�����F������������D,5BDDDDDDDDDDD$b�""""""""""""K��Xj������������H�R#DDDDDDDDDDDD"�!"""""""""""�����FH3�n7^���h�n7�iZ�""M��������M�FD.�������ED���9����\,�7""=G�5���������n��	�����x���|���:t����������������Opl���"^x�k�Y.$%%�`��}|���������z�v;�f�����=�0����%p>�M[>��C���y�����/������s��Q�^/.��1c�0o�<����������������Mqq1���>�7o����0���/W]u_�������^""�@W�����Y�d�eDSIII���?����2GQ���Zo�:G��/~AMMMX�9��~;�'O�����*"!���[���0aB���+x���C����|��'|��<���L�8�:����������~������x��|>|����y�f~��]"=ZW�M[6m�����7n�5j�/���M������l������s�wp�w������������������o~Cmmm0f�&�O���>`�����'?i�a�x�Zo*++�u���d���QToDz������Q�9Buu�5�Dee�5�����dMg�=PRRR��j�1������s����\.}����k�%%%���R��]���Gq��<��s<��3���/x�����:t�5��S�6m���_ >>�n����tN�8�������%//���s���Z�������5���w��]��@���k�&HFF�]wqqq�����?��4y��w2dH�'�ToDz�K]ouf~S\\�s�=Gmm-v��3f0r�H*++Y�r%�N����3��7���?�y�Oy���w>���	HNN������9]������,���tf��())���]����R���"�����Fk��e��E��;����`�o��<���1����t�M<����������?��z��`�j����u�]�p�x��W����g?�iii����3���Lmm-+V����on��
�8�ZoZRYY���k����������l�2233������`�����������[o�5BToDz�KYoBut~������x������+��9s���SO���O~~>�7of��)���\|�����?����[�-��E�F�g9���3s�Fiii<��#�p�ToDDz����t�������X�`�e�=:�	`7�tS��C��d�n��5�����'C'�xc������[�l	��H���zc���x���(..���,Y�$���w���`�Qnnn�|����s���`N�F$�\�z�EEEl�����'��$p8�w�}����_����3����2GQ��<��t����H�wY4B��Y�!8w�\���,#Z���j
�7�o��a0}�tK6`������v�
��Hw��z��+��o�>�hq����
��?x�`l�R�P��<��t�����M��3g�'�9rdp����w[�"��t���WW�(�7"��B���P���"����y������������h]iii�uFFFH�en�����f�jd�&���`���-�������2��n�~:So>��V�\	��t:���N�����1c�X��2$���f���D�YoZ���
���{��G��	������n3!"�Og�
��+**����TPW�(�7"������s��x�^JJJp���T���/"�i��u������g�8�n��+�������LS��?�!��vF�����Jvvv�������������Baa!�O���D��h���{7��_���V��~;~��eT@QQQ�uk5#������z#y.d�����[�$&&��uY�Uk�������z�r�J-ZDee%��9a�����&����vi��z#Y:Zo::G	UQQ�3�<���;�+=222�����������V���"zE�i�|��DEE��i�#G��f��y���]��7�����-#����'��}�����3�<���KCF��4���WH����X ������dE�;�h�)**�������1d�������MMUUU�uk5��^TWW�7"��B����oL����h����H7��z��c� �S�_��'�|�}����l����QToD"Kg�MG�(VEEE���� ���������������D��^�u��`�~��ia�������=z������vhzs� 77���'���'Y�b�N����^c�����B�]Z<���:����x���E���H�q����W�������$.\�fh|Zhu;k���Hs��M���o����7Z�U^oBk��t�7�g��=���Gcd�������v�Y�h�����u(�{���d����z#A:Zo::G����d��������r��Y<�c��M,[���s�����D��n�,Y�$��=O4���p��AN�:��r��}�2u�T���Zrrr���'2{�l~���s��!�~?K�.���O*4�.��
}j����dD��ho�1M�E�QXX���`�������:������v{H�����B�F$�\�z���������F�7"�S{�MVV�'O��{�%555�<y23f���'�������R��[<h8t~��9J���7"=_{�Mg�(������n�k_�ZXm�9s&���
��/���s���0�oDD"D���l���8p�q���j���G<�����?����M�x�����DBEGG������7r�\|���~�k�����7���C�m=} "_G���o����[x��������h^����jF�Vp�^���D��Qo������ ��7�����t?�7���c���aM�F������v��|���
4�����D������Q�q��z���n��o~3�:���$��D�FD$2Dl#$������d����Hff&��s�����aTUU��s�ux��Q�F�p8(//.�����ik�d��6�a��T�jo�Y�vmp���o�����[F�,�{����X/�\�Q�����GK������V�	�QZ�D�{ho�i����������;���s���q>�MKs�����f��������oDD"EDn�UTT|�_�~L�0�2��&M���	��m[�0��'Z���n����HII	����r����x�VK�)))�>� "�N{���������x��������h�!������G?"--�������Z��5n��z#.V�i���7�aGuu5eee�������e��\��7�z�p]]]�u{�7��E�F��;����9JG4W�4��������[�\��]��7f��m�����;������Y��!6>e���CEE��H���z����Z�� ����n�=\�����5.�nNqqq�uc�P�����Ws�����j������!...�u��}���dE�Rjo�i���E���3s����|�h���G��E�+:ToDDz��k���n>��s ��z���zc ��B{x����=:::�FKrr2���P__����#G�o�#G��dE�R�H�=zt������K/��������[��>}��:t(���������5C�F������=Z�����?x���C������|���������"r~t���W�����������]������l���6Gi�������f����H�q��/��2��1777l�ug_�N��c��}�F��!C�r#F�`��M�|>�l���i���7n���J��:RoRSS�=@��O��5�\s
�w�����S]]���)--%%%%�R�\����a��Q����H�v1�M{�5�Y�n�+��(��}{������#���v��|=t���L��(�7"=���7��Q��v���EEE1p��`N�FD������?������3g�K�������7[��a����c��
�|���a{�6�z������������,\q������^��Z�����3l�0���K�3������4y��w,#`��59r�Y�fa��[C@�IDAT�9����b��F]��4>�z��&��444�?_O�����z���X�bE�v4���9��e��7W3ut��z#��u��@��(hV����;��<}����C�A�FD$D�������2���{3z�h����������`��iL�>��}�RQQ�W_}������� ;;����]{�����?���o2w�\����������%K�p��A ��X����*�y����)((��g���;�$!!���[oQ__�a�u�]a������z�,`����|>V�Z���`��Y����M�������g��a�����\���te~��O�M���5khhh���w�}7����������c��7������E���l�Y�~=/��2+W�d��9dff�����?������L�<�A��]��9���H���z��9�i���/���3��5���\���)))a��U�Y����-��v����H�Q����W_O�:�]�1����z�jL�d��5�7>�4����u���|�����o��oX�����}bbb��������OS[[��={x������z���.��K�3���222x���y��1M�����|���1���{��6~�7"=���7]��<��r�����y����C7nw�y�5,"�Pg�M��PG���_�d
��?l
wy��z#�3u��te�r��aN�<	��e��V�52��������7""=����
����4M���?�����{��?�***������GQQQ�������������_e��37�x#���Q]]��\.�N��������%C%%%1u�TJKK)**���s���|���f��y!W�����z����>>����T�O��;`�w��<��c�r������ px�����f������R���S�vi~�p8���k��|�mu����y��G����K�+�f�����~N�8������$����w��]�������MW�(�7"=OW����#;<Gi�7#F�`���9s&kd��3f�>�(���a�F�7""=Sc�7���oB���rg�&���TTT�p8���w�
�U�V��X���P\\���'!!����w�
��vs��	�n7�z�"==��OE�H�j<��Z����9}�4�i��o�v���7"����MW�7>��'NPUUE||<����s[D"�i��<y���rl6�z�"--�:h��@��(�7"����Q��7555�<y��M\\���MV��F�FD��h|������0����vi�q����6�iVrrr�-��K�FD����������,�a�����oM�[W�(�7"����Q���������M�FD���Y""""""""""""�B��Xj������������H�R#DDDDDDDDDDDD"�!"""""""""""�����F������������D,5BDDDDDDDDDDD$b�""""""""""""K��Xj������������H�R#DDDDDDDDDDDD"�!"""""""""""�����F������������D,5BDDDDDDDDDDD$b�""""""""""""K��Xj������������H�R#DDDDDDDDDDDD"�!"""""""""""�������wg1V���?�ufXUZ6;8��"��&b�j��i��XcL�[���k0��z�i ��HZK�b--�a�lC�l������ s�s��-C����M��|�sNz3m���=BPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPXBPX����O>��k����#5jT>��f��)��^��3g���f��
9}�t&L���s���������G�r�����#555����2g�������,^�8===��uNsss>���Wn0`!����}~���f��!1bD��[����/��W��Y�fU?��3g����$�6m���#SWW�x �<�H�����3&Ir���,\�0���q�r������e���������.�,I������������"�@A
Hy��g����.���Y�`A����k����?���K3s�����U������l��)�_}>������*�W���w��e�����nK�,Y�$�=�\,X�k��&g�����������U�r�u��>s���Y�hQi
��������7����J���8qb����������eK�;�w���g����7o^����$��2n�����Owww:::���Of�����k�$555���S]]������H�
f@B���3l��L�8�l��~�g�}�l����������������he��)�����={�i��$������><�G����;v,;v���*G@�\�Gcuuu���3�'O���o~s����C�r���K��=�b���MoJr�n��{�&y�s�������3d��$�>��[n)]�~��W��_�zF����@AHI�����IJ��twwWL��8q"I2h���IJ���:u�t�B��w����B�L����g����Y�zuv������g���;�����m���-���
p��{\*��p)������
6�����y�;�����z{{���B�����g��^��s}����0���/��������F6o����wg��q������������]��%����r����u�]�u}}}�,YR�K�J}{


�r��Q��g��w�>}:������>}zy�������!������+!�����7�YZ���$I��������s�%�K�����J�?���566��u!}���+!UUU�9sf�v�������}������6lXi�s��$��I�J{2f��$I{{{�$y��g�����c����I��{�{�S:s���<x0��M+�]H_T�*@�TWn\W_}uz{{�f���^WWW��[������a���������GK{��
�����g���{8�o��g�}63g�Lmmm�������:������'K�V�Z������5���w����$�����
RWW�����P5��z��%��#*F���1c�f��������S��{w�,Y������??&LHr���|�;y�������3f�>c���Y�~}�z��������-���/RUU�[o�5C�I}}}:;;�e��l��)===Y�vmV�X�q��e��������S���o}+7n��'�q��,^�8���u�]�w��������]�����bF��o�������b��$��A���/|!�g�.������1c�{��R�3k���<y2�����|��$�>��_�rF�]:w�M7���:k�����K�$�����W����s�zg�����3����f���I�����p�
��'?Y�,�X��n���$�'O��]�������������q���9r$MMM��$�"���SSS����TUUUI�tww���C4h���q�������NMMMF����y2���zc�C���B�$(,!(��,�W����9t�P���6a��$��M��?�����tww����y���S[[����466f���1b����bz{{���Og��-9|�pN�>����2$�_~y�N���#GV�
��:��c�e��������e��${�����+�����OKKKf�����gg����G���SO��{�����+GeZ[[��/})����#���.���;�7o��������&s����>�����TM��X�"��/Oooo��<�7o��c���@����&g����Nr.�����;r�������l��O�~q�g���immMCCC:;;�}���/E���2i����0������g������.����4���I�����u�]'^������SWW��g�������o_6m���~8�.���?��{��7_��K{������{J�$���?��|�#e{I�o���Z�*����#B��Lcc�K���.�������U=b���1uuuI����6,��
���S��O|"��sOV�ZU:��C������Q��$��oOGGGi>k��F�$����s�M7Un������>uuu�?~���������z��]��\��!�UUU�9s�������������$2dH�^KB/i���e��G��^744��$([�kI�%���������H�f���5���^��������
+��2eJ
TZo��-��-;/��kA�%=���e����m��uuu�;wn�i�b��,\�0[�l)��KM�E=���e!���&��M�w"���>v�^{{{������G?J[[[�.���
H�]z~�����,{����^�����;y.�,X� K�.�����fmmmikkKKKK���������` 	!op����c��:4UUU������{���Qy4����7o^�v�s��������w�;�����{,V{{{~���]�zWn����{E`�!op��������>��q�r�m�e�����2S�N����m���w�}����V6������+w�q���sG/���)���g�h���5�r��&O���o�=�-���S�f�v�������` �E���I�2v��?~<g��Iccc�+��"W^yeZZZRUUU�����o}k����e���Y�lYi��u���r�W�;
��7m��|�������������~4��U��$�����_�*�0�<�Kf���e�]�v���bB�d������PZ9r��.>!�����{^!�Kf��9u�Ti=r��~S���^����<����e����t����3f���b������C=����/---���k3}��455%Izzz�������g������7.3g�,�` !�*g�����k�$���iooO�444���1��KOOO��d������[RSSS�����u��tvvVn���Se���inn������?�r��������~��Y�re6m���g�VI���-o��>����3'


�cU[�n�M���'W��������;w���#]]]������C3q���3��8�m��%��.�A�e��i�������(
!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(,!(�����m���?�/B���j����%:QIEND�B`�
raw_data-rw-ramdisk.txttext/plain; charset=UTF-8; name=raw_data-rw-ramdisk.txtDownload
#55Tomas Vondra
tomas.vondra@enterprisedb.com
In reply to: Anton A. Melnikov (#54)
7 attachment(s)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

Hi,

I took a closer look at this patch over the last couple days, and I did
a bunch of benchmarks to see how expensive the accounting is. The good
news is that I haven't observed any overhead - I did two simple tests,
that I think would be particularly sensitive to this:

1) regular "pgbench -S" with scale 10, so tiny and not hitting I/O

2) "select count(*) from generate_series(1,N)" where N is either 10k or
1M, which should be enough to cause a fair number of allocations

And I tested this on three branches - master (no patches applied),
patched (but limit=0, so just accounting) and patched-limit (with limit
set to 4.5GB, so high enough not to be hit).

Attached are script and raw results for both benchmarks from two
machines, i5 (small, 4C) and xeon (bigger, 16C/32C), and a PDF showing
the results as candlestick charts (with 1 and 2 sigma intervals). AFAICS
there's no measurable difference between master and patched builds.
Which is good, clearly the local allowance makes the overhead negligible
(at least in these benchmarks).

Now, for the patch itself - I already said some of the stuff about a
month ago [1]/messages/by-id/4fb99fb7-8a6a-2828-dd77-e2f1d75c7dd0@enterprisedb.com, but I'll repeat some of it for the sake of completeness
before I get to comments about the code etc.

Firstly, I agree with the goal of having a way to account for memory
used by the backends, and also ability to enforce some sort of limit.
It's difficult to track the memory at the OS level (interpreting RSS
values is not trivial), and work_mem is not sufficient to enforce a
backend-level limit, not even talking about a global limit.

But as I said earlier, it seems quite strange to start by introducing
some sort of global limit, combining memory for all backends. I do
understand that the intent is to have such global limit in order to
prevent issues with the OOM killer and/or not to interfere with other
stuff running on the same machine. And while I'm not saying we should
not have such limit, every time I wished to have a memory limit it was a
backend-level one. Ideally a workmem-like limit that would "adjust" the
work_mem values used by the optimizer (but that's not what this patch
aims to do), or at least a backstop in case something goes wrong (say, a
memory leak, OLTP application issuing complex queries, etc.).

The accounting and infrastructure introduced by the patch seems to be
suitable for both types of limits (global and per-backend), but then it
goes for the global limit first. It may seem simpler to implement, but
in practice there's a bunch of problems mentioned earlier, but ignored.

For example, I really don't believe it's OK to just report the error in
the first backend that happens to hit the limit. Bertrand mentioned that
[2]: /messages/by-id/3b9b90c6-f4ae-a7df-6519-847ea9d5fe1e@amazon.com
memory. The response to that was

Initially, we believe that punishing the detector is reasonable if we
can help administrators avoid the OOM killer/resource starvation. But
we can and should expand on this idea.

which I find rather unsatisfactory. Belief is not an argument, and it
relies on the assumption that this helps the administrator to avoid the
OOM killer etc. ISTM it can easily mean the administrator can't even
connect to the database, run a query (to inspect the new system views),
etc. because any of that would hit the memory limit. That seems more
like a built-in DoS facility ...

If this was up to me, I'd probably start with the per-backend limit. But
that's my personal opinion.

Now, some comments about the code etc. Stephen was promising a new patch
version in October [6]/messages/by-id/ZTGycSYuFrsixv6q@tamriel.snowman.net, but that didn't happen yet, so I looked at the
patches I rebased in December.

0001
----

1) I don't see why we should separate memory by context type - without
knowing which exact backends are using the memory, this seems pretty
irrelevant/useless. Either it's private or shared memory, I don't think
the accounting should break this into more counters. Also, while I'm not
aware of anyone proposing a new memory context type, I doubt we'd want
to add more and more counters if that happens.

suggestion: only two counters, for local and shared memory

If we absolutely want to have per-type counters, we should not mix the
private memory and shared memory ones.

2) I have my doubts about the tracking of shared memory. It seems weird
to count them only into the backend that allocated them, and transfer
them to "global" on process exit. Surely we should know which shared
memory is meant to be long-lived from the start, no?

For example, it's not uncommon that an extension allocates a chunk of
shared memory to store some sort of global state (e.g. BDR/pglogical
does that, I'm sure other extensions do that). But the process that
allocates the shared memory keeps running. AFAICS this would be tracked
as backend DSM memory, which I'm not sure this is what we want ...

And I'm not alone in thinking this should work differently - [3]/messages/by-id/20230110023118.qqbjbtyecofh3uvd@awork3.anarazel.de, [4]/messages/by-id/20230113180411.rdqbrivz5ano2uat@awork3.anarazel.de.

3) We limit the floor of allocation counters to zero.

This seems really weird. Why would it be necessary? I mean, how could we
get a negative amount of memory? Seems like it might easily mask issues
with incorrect accounting, or something.

4) pg_stat_memory_allocation

Maybe pg_stat_memory_usage would be a better name ...

5) The comments/docs repeatedly talk about "dynamic nature" and that it
makes the values not exact:

Due to the dynamic nature of memory allocations the allocated bytes
values may not be exact but should be sufficient for the intended
purposes.

I don't understand what "dynamic nature" refers to, and why would it
make the values not exact. Presumably this refers to the "allowance" but
how is that "dynamic nature"?

This definitely needs to explain this better, with some basic estimate
how how accurate the values are expected to be.

6) The SGML docs keep recommending to use pg_size_pretty(). I find that
unnecessary, no other docs reporting values in bytes do that.

7) I see no reason to include shared_memory_size_mb in the view, and
same for shared_memory_size_in_huge_pages. It has little to do with
"allocated" memory, IMO. And a value in "MB" goes directly against the
suggestion to use pg_size_pretty().

suggestion: drop this from the view

8) In a lot of places we do

context->mem_allocated += blksize;
pgstat_report_allocated_bytes_increase(blksize, PG_ALLOC_ASET);

Maybe we should integrate the two types of accounting, wrap them into a
single function call, or something? This makes it very simple to forget
updating one of those places. AFAIC the patch tries to minimize the
number of updates of the new shared counters, but with the allowance
that should not be an issue I think.

9) This seems wrong. Why would it be OK to ever overflow? Isn't that a
sign of incorrect accounting?

/* Avoid allocated_bytes unsigned integer overflow on decrease */
if (pg_sub_u64_overflow(*my_allocated_bytes, proc_allocated_bytes,
&temp))
{
/* On overflow, set allocated bytes and allocator type bytes to
zero */
*my_allocated_bytes = 0;
*my_aset_allocated_bytes = 0;
*my_dsm_allocated_bytes = 0;
*my_generation_allocated_bytes = 0;
*my_slab_allocated_bytes = 0;
}

9) How could any of these values be negative? It's all capped to 0 and
also stored in uint64. Seems pretty useless.

+SELECT
+    datid > 0, pg_size_bytes(shared_memory_size) >= 0,
shared_memory_size_in_huge_pages >= -1, global_dsm_allocated_bytes >= 0
+FROM
+    pg_stat_global_memory_allocation;
+ ?column? | ?column? | ?column? | ?column?
+----------+----------+----------+----------
+ t        | t        | t        | t
+(1 row)
+
+-- ensure that pg_stat_memory_allocation view exists
+SELECT
+    pid > 0, allocated_bytes >= 0, aset_allocated_bytes >= 0,
dsm_allocated_bytes >= 0, generation_allocated_bytes >= 0,
slab_allocated_bytes >= 0

0003
----

1) The commit message says:

Further requests will not be allocated until dropping below the limit.
Keep this in mind when setting this value.

The SGML docs have a similar "keep this in mind" suggestion in relation
to the 1MB local allowance. I find this pretty useless, as it doesn't
really say what to do with the information / what it means. I mean,
should I set the value higher, or what am I supposed to do? This needs
to be understandable for average user reading the SGML docs, who is
unlikely to know the implementation details.

2) > This limit does not affect auxiliary backend processes.

This seems pretty unfortunate, because in the cases where I actually saw
OOM killer to intervene, it was often because of auxiliary processes
allocating a lot of memory (say, autovacuum with maintenance_work_mem
set very high, etc.).

In a way, not excluding these auxiliary processes from the limit seems
to go against the idea of preventing the OOM killer.

3) I don't think the patch ever explains what the "local allowance" is,
how the refill works, why it's done this way, etc. I do think I
understand that now, but I had to go through the thread, That's not
really how it should be. There should be an explanation of how this
works somewhere (comment in mcxt.c? separate README?).

4) > doc/src/sgml/monitoring.sgml

Not sure why this removes the part about DSM being included only in the
backend that created it.

5) > total_bkend_mem_bytes_available

The "bkend" name is strange (to save 2 characters), and the fact how it
combines local and shared memory seems confusing too.

6)
+ /*
+ * Local counter to manage shared memory allocations. At backend
startup, set to
+ * initial_allocation_allowance via pgstat_init_allocated_bytes().
Decrease as
+ * memory is malloc'd. When exhausted, atomically refill if available from
+ * ProcGlobal->max_total_bkend_mem via exceeds_max_total_bkend_mem().
+ */
+uint64		allocation_allowance = 0;

But this allowance is for shared memory too, and shared memory is not
allocated using malloc.

7) There's a lot of new global variables. Maybe it'd be better to group
them into a struct, or something?

8) Why does pgstat_set_allocated_bytes_storage need the new return?

9) Unnecessary changes in src/backend/utils/hash/dynahash.c (whitespace,
new comment that seems not very useful)

10) Shouldn't we have a new malloc wrapper that does the check? That way
we wouldn't need to have the call in every memory context place calling
malloc.

11) I'm not sure about the ereport() calls after hitting the limit.
Adres thinks it might lead to recursion [4]/messages/by-id/20230113180411.rdqbrivz5ano2uat@awork3.anarazel.de, but Stephen [5]/messages/by-id/ZTArWsctGn5fEVPR@tamriel.snowman.net seems to
think this does not really make the situation worse. I'm not sure about
that, though - I agree the ENOMEM can already happen, but but maybe
having a limit (which clearly needs to be more stricter than the limit
used by kernel for OOM) would be more likely to hit?

12) In general, I agree with Andres [4]/messages/by-id/20230113180411.rdqbrivz5ano2uat@awork3.anarazel.de that we'd be better of to focus
on the accounting part, see how it works in practice, and then add some
ability to limit memory after a while.

regards

[1]: /messages/by-id/4fb99fb7-8a6a-2828-dd77-e2f1d75c7dd0@enterprisedb.com
/messages/by-id/4fb99fb7-8a6a-2828-dd77-e2f1d75c7dd0@enterprisedb.com

[2]: /messages/by-id/3b9b90c6-f4ae-a7df-6519-847ea9d5fe1e@amazon.com
/messages/by-id/3b9b90c6-f4ae-a7df-6519-847ea9d5fe1e@amazon.com

[3]: /messages/by-id/20230110023118.qqbjbtyecofh3uvd@awork3.anarazel.de
/messages/by-id/20230110023118.qqbjbtyecofh3uvd@awork3.anarazel.de

[4]: /messages/by-id/20230113180411.rdqbrivz5ano2uat@awork3.anarazel.de
/messages/by-id/20230113180411.rdqbrivz5ano2uat@awork3.anarazel.de

[5]: /messages/by-id/ZTArWsctGn5fEVPR@tamriel.snowman.net
/messages/by-id/ZTArWsctGn5fEVPR@tamriel.snowman.net

[6]: /messages/by-id/ZTGycSYuFrsixv6q@tamriel.snowman.net
/messages/by-id/ZTGycSYuFrsixv6q@tamriel.snowman.net

--
Tomas Vondra
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

Attachments:

results-count.pdfapplication/pdf; name=results-count.pdfDownload
%PDF-1.4
%����
1 0 obj
<</Title (count results)
/Producer (Skia/PDF m122 Google Docs Renderer)>>
endobj
3 0 obj
<</ca 1
/BM /Normal>>
endobj
5 0 obj
<</CA 1
/ca 1
/LC 0
/LJ 0
/LW 1.33333337
/ML 10
/SA true
/BM /Normal>>
endobj
7 0 obj
<</N 3
/Filter /FlateDecode
/Length 240>> stream
x�c``<�,�y%EA�N
�Q
����p��o� j/��Q�p��'�@,S�h$�-�a+��I�	�]^RPd{��E!A�@v�����NBb'����6�9��w3����C�2 C���,�200O@�%�d`���� q!�����h���1DX$%��X��)-����r�H�\����&�y2��@�����
�d�cHf����[=�
endstream
endobj
6 0 obj
<</Type /XObject
/Subtype /Image
/Width 2048
/Height 987
/ColorSpace [/ICCBased 7 0 R]
/BitsPerComponent 8
/Filter /FlateDecode
/Length 53061>> stream
x����U��7�@�PoPK�Z#�MD�i�V"Ac.���5WoM���&0<�%>��C������"�1BA�*(*" �(0��3�o}��{<gf83���~91{����{�9���^�����[�������������G��s���$����N2r��3xog��e���}�����^���/�E��~�i}�g���W�^�d��Eu;�����L���G��7,))y��wF�=x��������?����/��o���� RQQ��������������o�3����qt_C�^��>�������������>}�t���/�|����V����_~��'N��{�;�������G
g�
��j{���W_}5%��0�_�tir�#FL�<y�������G������ �x��(/]�jU}�g������yt��S����_|1l���m���g���y���g��!�/�����P"�x����I�����Ki+��<���Q^�o���������.\�a��5��:p�@��7���d��M����F��*��*_:X�bET!??����������c�z����{�!C����p��~���s�EgH~�����C���Z�lYEEE(�<���kW�����N8�O<�y��7�����x��w��q���U�3gNT�o��U�����[�p���������?���O<���/������rR����>�`��YO>�d�~�z�������z*���(M��/D��v������?~����u{�4l��3f���Ll��9������y����G�����[�����������*��3&j��{�U�����<8��1I�_�������K4(*�����x����~:�	�I���L��i���{z���+VL�0a���a���(\}����w�}�Yu�����7�|3o���������Z�������>=���V
�����$2���z������>[C�x����H.?e�:�v�9r$�n?.&L�s���B�;v�s��a{,4�3gN\!��O>�s�����g��p���Fw���_�7�2eJT���(������;��e��<8����7o����E��V'N,//O_�5VPP��<���^�����o��q��x�������Fz��v��5z�!��q��?^e7�����]:�<y��c�������^�zU�p��i�_���-���aC����_�U�'N��j��<!U�����o�w������k��KKKG�U:thIIIm���������?J��.]�r���,���L��~t���q�j.X�`���/������>}�l��=��;w�|��G��s��qo��fh����7�����R�N�6-:���o��9���({���o���k��6z�������?���2$��*s��,Y�$���1c��������_�����'���c���"�(9�N��Og����m���g�1cF������ �pz����
�rhRXX:;g��'�|2>���opd���'�q���z�z�����.1`��P���/N�81�P��?���u�y���_����
j��H$���qy
�yyy< ���o���G"�{��U\\�|(�E���;|�pJ�DG�����[�rt���#F��*<���'N�H>ZZZO32x�����w����Q��2�K������)SRn��O?�#�i���aX���55jT�&Z��=�z���Q
g:th<�H>���8��3�l��-W"�H����_|��a�����u���
G����R&:r�H�>}��O�q���b���q��W'���p�x���2���������"�S�������U��D�2�����[����>���n\XC�?k���P�~����S��?./��r��;6.���o��S>����&��c_�zu��-))�#�U�V%� ���Gu��~������Q~=zt���������?�1H�b�������k�0�X��|+��ITv���Y�dI���k}��}����|��4����|����O�8���O>��|h��uq��W3"�>�lTa���)������?��O?�4�m��<��3q�:���w�N�'Sg��{�����������$/\]��p����O�>��j��r���h��I���7.*�={vz�x��a��U�JoPPPU1bDry�O�4���3���''�'�����q��a��������
���=:���s�%�'w-Z!7�i~r�_�2�o��fJ'�����s��-[��0M�'?��S)������W�m��1��:���_�t��e��'���g����Q����U���:��������x�~��:th�������?^��&U�������3�������yaaaTm����q�;x����&���~�mM�O�H$�w�hT�rA
���/����j�$9��������S������W�pd�~������gq�S�6�b��UU��*���a��E�s����m�����6Auo��J����48z�h����������>�J���M�����G������E�{��Qe�[QQO
�f���y���8��gbI�kH����{/����s�!O�0���_�u�v���5�=E<�P��5�G�a��Du���?O��%��3�<Se�������|�Iu�������B��J�p��g��{�����O�t�;�<^�w���54��w�^�������������!�?����/���j\������P�/��3JKK�|���I
��y������q���y���5Oc�����5��$�3��Q]�x�����������G���Z�� ����]�nf�����������&� }���)��������2���!�?K,))�SV.N����-�V����?������jX�z���������_���g�#������C�)++�����~[��6^�u��5qa��������f���<��k`O'�������U������'���Z���}�Y\~��6Ns�+k#���;���������ykVC��:X\\~��G5�.�!����5\�~}�V'��?���S��;|�����E�����9h��x���'_d�r�j��O�nr�����u^|��E����[��<�Y��<��a��d���������:��K�,��'e0`@���]��=���A��l
��Y���}���5��c�����6���8�C��0��w-�7�*���'����8E|�hc���gd.#�G(�]<������u�\f49�L�X&Cq�����)��9����k�Vo��F��bq�:d���%���{�����];���������WTT4(*|��':Te�����N����`��M�S������F�j����7Q���/����`���Q��_=H^�8��������|�A���[o���?*����C]�~��	���^z)�rEEE�>}�
o��vm��<�P�s����[�<|�p\~V�����G��l��y�X������@u�"��O�������U��I^�w��
�m���������Q�:�����'N�wX����������6


j{o��<���2���[��'L�	/���8Og*��������3�p��	a���}���J�������)��M����??X�����P3^�w�����g/�����b�������[%K~����u�,Y�	��\�I�Ng�+��'O�"�g�x��
6��G���m��n�����`<���9s���<�P�����'G��m�V�{�R��������5�.5����������������#��A�%���������o��m��s�~��g�Y�xqt�w����������M��'������W������'��2+>{����7.�&)���+VTW-^|v������t�4?9��<yru��_(�U�DT��FF\�b���q�������I�&E�kX�!�i������E��%����<��g�^�����GuR���2��<�hB����	,����0 ��������x����K�KJJz����)�7�x#J5g���\����=�1��h���q��r+�f���[oEM�6�N���!C�T������(**J>�I�Ns����p4ya�XYYY<T�C��q�6~) ���G��^~~~J�,t0y��*��>v�X��A������
'N��I&2���)S�D��y��*�]�[3���OY_��������������q��1cR����o_�^��������80,,,,++K>z���x�`����GC���~::4h���p#[�nM~ 9�������������#�h�I�&�<�^RR2|���N��L�Vyz�����6lX�<E�D"\=������c�������������3��G��O�����������O�v8p`��Q�P��n����A�+�V����e�W�=z�7�|
����U���!�f�����g�s?~�����^�z%��80���wJJ\VV6v��8l4h�����,YRXX��K/=������^{-��_}�U����s��IK�.]�j����x62l�����.��Y���==�?p��L�W)�g�}v��9�O>�=k��w�yg��a��Gf���u�Z��
~r������?e��0�+W��?���C�
3g�Li=u���-z��w�|���m�0�HFu�i��f���?| |���?o��p�&L����S��qw
���������)�W}���\#�|���)gH~5&���?��1c����W^y%��5������d��!�+�,<����/��Nyy���>'�)�{�����;7��%]~~��%K��N|���q�Z��'V��Y������C�������KKK��O��w��[�"u�������+V���$��OOy������������	m����f����K���A������^{-�M�>�:���2$���I�z(UNa���$������S�����v��_.�2e��t�/q�;r��V���{w�����[����������A����-[��pp�m|�������O>�����
0`��o��F
3������YQ�
6dR�J�����K/=��}�����w��3gN���W�&��a����#G���p3a��
���/�a�����O��eKu-//_�v���c����d�=��s�=�h��o��6�s����s�2$�0�w���Y�`����
C�|�^����S�n��9��/\�0������N�{��Z�^P�3��W�\�c��c��	'���),,���~��?X�re|�U�V�NO�%�D��+9����
 ���=�8�����#��s���=�8�����TVV6l��/�0''g����><p��������B�V�Z=���{��M�����,�*W]uUr�������_w�u��5k��i�6m�{��p)W��ys�.].�����_~��w�}��-[�t����e��v��������U���|�M��������������;�h�"��l�������TTT4j����/������O�H$:v���3�}Rt�p��������K/���pKyyy��w_�o�'/**����?�U�V]t�E-[�\�h�/~��*�����?�w�������J���������~8*9x�`����~U�����P-//���CQIIII�v�B���S��c��]q���w���s��3g�uZ�j�H$N��pn�1c�������������-[���[�&��7/�p�
������n���k�\���������Ba�v�����g��;��3�m�B���k�Ehp�9oW��G�M)Y�rerh�a�����S���g��P��+�L)���h��ynn�����<�M�4)���#B�#�<�Y������?]~~~����hw���a��;�2d�o~��f�����?���~7g�����e�B�[o�5�l7�xc8�f�������W�^�R���0�w���n���)�������.���+JJJ��W_}5��&M��|������H?���WTg��Ya��{�I?a�N�����k��6lo��-����k�g2�a�?�����'��7��qc\�x���n�������{��y�������+W����M���uK?g�������g�����:l���#���M�By���O���G�~����������R&����C�;�������39�C=���������}kx�������5��{��m�����'�|��s��]�2��IWs����?����-��R\\��9g����������/�:tH���M�ph��ua���o�EEE)u����o���S^��o��
�������0�&E
�������?�#����������9q��8�/..�-[�L��H$�6m��Q�p���_?~|J��C��������
����D"=�?b�����������/,,L)���{C���{G��N�]�~}r�������hw���a���oO9U��mC��+��5h��������~����5*���/�{���p�������7�'��2eJ�v�M7���D%������kB����D"��U����W^�O5r��h�������)��z�����5m�4''�S�N��_���P���_|q(�����M��H$n���P-T��{o4��F�&N�_�������
�-Z����k�.]�7ov|����Z�zu�&Mrss����u���}�P��K.��eK���E�T����
�o�^]�H�pii��I�~���^z���7�����K��k��\���|��Qm��i��I�f���o?u�����uk��]�S�l������nab �-=���c����83z�8v���������8��p�����G���6lL��-Q\Q���Y������J���6�h���Y[7P�IY}�}�L|�D<���s������q2��>���c�=��#����[���~��D}��@���6����6:V�������~<���u�����/�lK���@��M��,����������?����k�����7���N��=���4x��l��g��De�w��>{Vd���6���I�4d��l��g��h����$��&�?�����I��M��!��g��?���@C&��&�6����L��M��l��
��?����$�2�6���I�4d��l��g��h����$��&�?�����I��M��!��g��?���@C&��&�6%�+��<��G^<w��L9Z/�Pr4��]�iG��me
���!���c����g������7>}�)�����4��]QYy"Q�����M_�g�J��?��f���x��x/Q���=�5�H���T/��������3���tYy}���n�;���?�m��.�C��� ��?����$�oh�?$��g��?����EY�)nH3����J�vm�^6e���S�]J���oU�-i���
�%85�?�N$*i�����{��N���xd���S������������O��
�9K���?�{��d���'�k���yumi�G{�����5�����?�
���������������{8[��p�����g���<�~f������G���l��a^xaNN���;�+���>����k��Y��M��i��s��V)�6o���K��.��q���_~��w��e���w*�:[�li��]nn����_e��H$:v��h�����F����syyy\m���\pA8O^^�}����/�������q*�:�V�����Z�l�h��_��U���?�|(���;t�PTRRR��]�P8u������cW\q�y��7w������3C�V�Z%�3~*�:3f��������]]���u�P�y�������P��]�hw���a��;�Li��C�P�p��3~*�:G���������
��������7���=x�`�}��B�I�&�T1bD(��G����U��/[�,�z����o���ph��5a;///l�^�:�Naaa(�����=��*��Y�f��{��'�~�N�����k��6lo��-����kC�
7�pfOd�����i��[�n��;w���=;l_}��a{��)u6m��[�n}fOU����8��2�JU���j�5<�_PPP�����=���m�3{��}��'�8�������0U�2�_�|y(���Cz�6m��C����7�|s�.**J�3o��P~�m���S�2�/..�-[�L��H$�6m��Q������z(T?~|J��C������3{* CU�����_���_�\XPP
o���hw���a���oOi��m�P�b��3~* ���S�L	�7�tSIIIT�o��k��&.X� *I$�Z����}��W��#G��f����8�����G�?|�i��999�:u�v����Fu�������p�E�]�v���K������>�|���W7i�$777//�[�n���u.���-[��u�����D�T����������5�M�6M�4i��Y����N��~��[�v����K/m��q��-������	���H�g���G5���UY����J>aii��������f��5m��M�6�=�\YYY�u7o���K��.��q���_~��w��e���t�y�R�.���/<t�P�VQQ��Q��/�8��C=�-�Ht��1''�E�w�6�n�������jK�.
'������������v8yQQQ=4&L���y��������_��W5�z���C�����W�����]�v�p���Q��c�������;o���q��3g�:�Z�J$g�7@��;~���\w�u��=��o���i��}�
[�n�m��9����(�k�.��={v����;S�v��!�/\��u��;������[�vm\�a�����N�:��*ZJ��+�L)���h��ynn�����<�M�4)���#B�#�<r�:�CAAANN���'.]�4�q�C���o~��Y�������������Y�lY�s�������o���Y���������S����;��>@�V^^��_��I�&{��I.��WsN
�n���?��OQ����+�3k���{�=����S�N�������^��m��Rg������n8;=��k��999?�pJ����o���?���{������w�����+W����M���uK?m�������g�����:l���#���M�By���Oy�G���s����k�i��n�!777����<��C999��_*�_�����

*�_#������m{��~��'�8����+�h����qcNNN^^^�Mf����������/�:tH���M�ph��ua���o�EEE)u����o���S^��o��
�������<��Vz�����3b����L�81�����v��-S�$��M�6j��������20~���jC�
������	�n��������?�P��}���������{��74���w�������'�)((���rK�;���{������m���|��g�3@eeii������q�'N�5jTNN�/����w��3g����
M����L���t�M%%%Q��}�����P�`���$�H�j�*4|��W�S�92������l���[����\q�UM$��~{�p����{��7���Q�F'N������u�]��E�]�v���K������>�|���W7i�$777//�[�n���u.���-[���N@�������������Bii��I�~���^z���7�����K��k��T+//5jT�6m�4i��Y����O�:5�l[�n���kt��-[���;w�<�]�{w%Eu/��edE�(��Q�NdD0*D��Q��j�Q�G1�D�h5qEQ9a3/!�E\7^dQ�����Q�����g��=�w�p�n������[��������X���-�r��o���e��g^���p2���Qc���|4�������sk���D�	�m�?����QA�sP���mK����m�s��h9�wi ,�����1�mKN|��������v�L[����ya��5����l/(N��p��U_��o�Q���N����>�-��5�����������|47���[������o�����U�f[��2�3��q�e�7i�����7//�l�Q��������5����������2�3��q2��X��cf�?N�����������?Pc�����8�j,��1{�����=/���g}���-�2�O�� ,}^���5VAa���r�_�N����-�2���i����i�O����#����&�����?@�^YV��|����'�m�����y�2��p�c� f��(�pn���A
�&N���7nK�r�����5,c��MK���a��~=���m�6��m	`wq��w'��_����5�,Y2b���-[��[�U�V#G�\�ti�O��}����8��F�5l��[�nw�uWAAA�j�|Pi���o�D�=F����/&���7/;;;+++''g������^�~�$����4(|Z���G�V��)��RXXX������.K$�?�x9urss��kW�V�3f$�M����S�������{�
%999�7o�J6n�x��G���S�V����8���������r�L�>=�9��SK�0 �?����f��]���%KJ�Y�`A(<���+�Q@U�t�I�Db�����;vl�3e��R��&M
�����k��	����/U����I�&YYY6lH���*:��c���:�m�����:t����?���d����Pg�����;w��P>h������������GuTxi��E)~PE�rHb���;�v�iC�m��Y�l�������:]�t	%}�Q��.^�8�w��=�?���a���O/�#^�={v�T��1cN<���{,Y�~���&�~��E%;v�����K������]�v
�=�PX�V�G�r�)�������Q�[�b�22��u�*2�M%}���u��I$�V�*�����u�~�=��}�o9����3'��*��~�:�e�������:��D"���/��>}�����3s��P~��'���^z)�0��Gu��-���k���Q@5i��]r�~��qa��(Ug��	����������m��)U'??�a���k���eK�T���K���;d��R��qVVV��u�A�Y�f%���z������my��a���_/Yg��9�0��h3��*-??�e���D���oO�[�.''���|C�N�:eee=���jw�}wt��������%�z���qcT��_D��={v�>
��^x�^�z�D�k��g�q��!C��g��y�Gl��!Ym���
4������3fL��=C��M�.]�4Y���p�����y���F�1bD�&M���^X�'��Q@}����w��X�~��
v����[o���-[m��Q-Z��[�n�6m�=��+V��SXXx�=�t���A��5������Sw������������-������v��W?8?/Z�n,Jw8�~���7o	�����;����y����t�����R^�o����������oN��-�/}o��g��o���0���������O.��2��m���_MC/.-�?�KW�mK���[���is��5
�v����
���u�7������i��������iY.$
�;xwea���,C�{K���������8�j2��q2�'��@Mf�?N���d�����������5���8�����&3�'��q2��d���d�?N������������?P�-[S����������ykXN��������������[g}�2������	MC���=�l��Pt�����\0%��[������?����an ���r�?�����Iw,���'r���y���&�����d��]��i&H�-[��x���zh�z���c�N�:]r�%k��-Yg�}�I��~��W�����'N�x�G4j��a����u����


J��%K��1�e��u��m�����#�.]Z��&�_~�e��]�D�f�N>��SN9�y��a�M�6�W�����]�~��#�7n\�����
�>a��G��,,,LV�7o^vvvVVVNN������a=|����� C�{���Db���6m�J���~��Px�%�D%6l�x`�u����j999�7o�J6n�x��G���S�F%�������U���3�o�6mZ���S����]��@���M�D"���,�9sf(���{��|�����g��?*���%KJ.X� }������������Z����>�l�~�[��m+U���/����7��������5k��:���/U^TT��I����
6���c��jS�L)Um��I�|���U�M��v��W'����>��7o^�<���n�������5�k���;��g�y&����>�8p`�O;����K�-
�999a}�������;7�4��~%��,X�����]��7F%O=�Tb�
�����3�����_��WQ�'�|2l�~��e?p�������g��.]����>��T���������5k�=�l���[o��,|���N<��s�9g������3g��S'�H����a���
�c��)����rJxi���a�c��a����w�:o��v(�����F��W_� �l���r���b��	�j���~��{��R��q�D����/�����\�?g���o��]������{��~�:�e�����KSQ[�l6lX"������u�R|��i��[����_z���>`�����u�^z����z�>}���J��9sf(?������� ����:l����?�q"�����


R�����������m��)U'??�a���k�?����<����M�0!�_}��U�U�����]�?i����s�u�y��s��-U~��g�7^s�5�f�6_���u���}� ��5kV�2dH�����G(�?~U������O$�\rI9u����P�s���V�JN�6-++�n�����?����Z�^�6n��|��tP(�={vT�����S���'�x"�Qw�}wt�����]��@��~�����'�A�
����K���C�	�B��r��gF���]�������VXX8|��P��y�Q�F�1�I�&a��/,�C.\��A�������1c����3�i�����K��� -_�<Q�����o�>e��c�9�E�u��m����#/^\�����n��5h��Q�F={��:uj�����5*��6m��{��+V�����UT\�_X����$|������'�5����}o�R���m�?��E�i����|�e&.}h����������g��b�?N��cv������e��n~�����������j,��q2�3��@����g�qk
\������]XT|��5sY�)
�����{�����e�G���d��%#F�h��e��u[�j5r���K��;(��������������3z���oX�_����P�������U���3����MK$�:u���Ocl@�L�>=�H�z������}���DT���c���)SJ�O�4)��?>-QU����H$.\X�|����|��Ai�
��.]�$��>��T����Cy����P;vL$����K�������k����	w�u��d�g�y�z���I��]����G���	���;�������z���I�>}���J���93��x��i�
��q��%�x�T��	B��W_������5kV"�2dH��=z������%*�*���;u������O$�������EEEi�
���6h� +++''g��1={�L$M�6]�ti�C*��>5jT�-�����M�s�=w���
�����EEE����X�l��_��(j���7������ 
�O�^�N�s�9�@�.]��e�n���������9��}����7�Lw,�/??��I]�t�W�����tG��d;f3g����i��a��mo������tG��/^|�	'�l�h�����Kw8���?3fL�&M��k�a��m��%�e�����p�
������~��w�y'�e������w�����u�w�>w��tG���z��=zdggw��a����+��[o�5d����4m���/��aC�#������������-����]v���_��(j����:��o�Iw 5E�<$v0��o�=��)�����Q�MT����{��!��Z�
���>u��t���d;N��x������������=f��t����M����]�N��]���_��'�LwD���w�m��u��8��f��]x����(������{GM�~��w�������;���Q�����v;�L�<9�qe�p�7n\��Z�jE+g�}v���X�>�h��uKf��C��qc���E���?�z����A8���US1X�zu8��4h�)�x����]�6m�����y�B��A$S�-�!�{e�@�)((8��cC����6������������.'�1���kBz/���(�O?�t�
B�����ZZ�ti��9��������[��;�Lv�N�:5n�8�L�w|�HR��:���t$���{W����>}��l��������Bg���/����_�vm���@�_}t���'������/���f�Jwh�����]��0���n�;v��}�W�;4�Z���c�=�4�_��{��G4�j
����3'���@l�y����Gyd���3P��9HH�u�]7p�@S1��������@5���{Bz����Q�F�B	��d;NK�,�U�����K���!�w�qG���`c��
�-�������MKH�������{K���.�r�������?-U���6mJKH,"��}�%��,<��3C�}�����2��\�N����o��=Y8y�����#G�1��TXX����7n�8�%�,[�,��j�*}q�%��7h�������/i
 <����������-�������[oE����A�?D�#�S1I:thnn�)��}�����gS�'��5o��T����������>��q�����[���8]y����x���J�Z�*>���������[F
�w�-J�,X��w��Y;�����>���2O�{/]�4Y��#F�����C�w�uW8�Lc��d���!����%�	��M�6
�M�4���K��_��3���������%���
/���tE��&L�P����������CMWT���W_
�.uYB��o�P�O�g��e����A�V��������#�GX����L�&�w�q��;�JN��{o��9���O>�m���;N�JML�6m����0��y��!��q��_ONN����t�	��w�������,<���[�n}�QG���C��a���[��3�l���?�i�[�<��c�j�:tht[�������[��0����;;;;���1cF�������K���������� 3Ft��^x!���-[�����?Z	~������=�\�S���s�1�$�:$<�v���W�X��03D��]C>W�^]�0t����:\t�E!���X���'���(�M�>=d;��J��{����������+�����_=�4P�B��Q�F��~{�i
�������!��)��w�q�����3fLX�2eJz��07�pC�j4:Wr
��;����:����`Fy��CzCo9�LN<���M�4���������E{���'K�z���3�����^z�����5k=_��IU'�q����y�1�l��-*���B�����<��k��6e�_���E��jf��H�������kC�w����x8\�<�s�P�]"�"�g?�Y�y�QG�j�j����;nJ���q�P���.Jk�b�����s���;�.[�N�?�����o��f�.]B�?�p���;���C2'L�P�0����c��+�L]is����*?���<����������l7m���}�B0��Y�&]��g��I%�d
�Z��!�i
�Z����������1~����k'o����z���2OhCBb�{��h39�����;v�
6dee]{����h
 ����}���3��U+�4���4��3�9�����_~UX�zu8����P3�l�)�I�7o�y���v�m���/��s�P��������*r�!�
53���{a�n��}h�'N�����~��%+�q�!��[�.�*!///�:t�/^��o������%+,Z�(;;;�0e��@%���W���������p�
%_
mx��?����0c����Oh���~&����_��W��*S�]��]�veo���m�^�z�%���o���R��7vo�p�b�SS�L������{���@8<��6n����2�N���������;��-c<��C%oq��#GFc����}��g!���v[�$��E��,��N���mu���=`��3gN���CV�����R��y����Q�tE�Id;N��-���W�Dw��!�;o����n��R>���t�I��:��K/M^�^R8P�
���J��e�Gy$$�?����������l�����
e����pF����s��
Y-{���������%��Zh��~���?�<YR����-
����;K�~�������"���~����>�=��'�|r��p�s�I'����{}������n��������A���{��%����?����3��]�)�)S�dee���~���a�(5:M�4�c�=J~S�]��@�<q��FP��w�y'�����+��[�n���=��4k�l����z�Vs�1\M�
��U�h=j�[�l����.Z�O>�d��u����F�
:t��?��$�1[�j�g�}v��7v������A�����?���w=�b����:u
�����#�G��3�9����]���.J����:�{�*h����?��O!�{��w������c��-���;��c���m���+4hR��#F�����f��U�6������n�������eK����N����R��O���q�q��{���?��(�!����<����;'7���'�tR,�U�b��p�Q�w%�B?-�/��{v*//o�����br
 ��D��_JE����8p`�y(��Y��m���W~�����n\p����e�]V\�F@ao�%����y��M�����������������H�G�	R<P�t�M!�k��M�G���nN^Lo�"��;
�^�0��
64hP�D�id;f�(���?�Y�fe�srr��{ow)L]h�CS�]7������w��>�{��U�^1bDx���R�����in���G?�Q4�4w��R�������X"��g;�(�W]uU���^��^�af�
6}��!i;v<�����~����_}�9��'����.�*F���<z>Hh�C�l������<9���=u?�p�:u���C��a�Z�j%��^J�'�'O��y��	��9������^{��o�������'N���S:��t��S:��@hI���5{��q������,_���We)������u�������?��O����<z���Z�R<P��3'jsJ�G&M��@����p���Y�z����?������^z����1s�v�R?P�z����%����c�=
+q�NM��'��YZ����Z�h=y�������������)����'��YZ_�u��=C����#f�|���m��m������c�w�����v4����n����0*����.�]��
<8d��[n���,Y]������nW�K�+��[o
	6lXt���W_
0 �\}��e+��#����Jx��W��.?������]u�U!����i�8 z��?���-[V�n���{W���'O6�_Q����������J
�����[��B*���y����P!g�uVH�����������	K��*j��)!��\sM��������?���r���Q�=��*Ro�/�����6m����(�q����G�3�GY���3f��������?l��=�Y�q������Vc
w��w������J���O�^_�f�~����z��~������[��g���{�����J�gi��u���F@����������������#�8�J��w���#�������^{��7z��a����u�����;J�o����p��Ie�?����Gy��%|���������K������D��'?)[������5�_9=z��W�^��
u��-�wZ?UC���?���s��<��$��o����s���h���<TZ%���Pi�V�j��a8�H>6h�����p�����0��B�m����T[�fM874�_u)(���g���Rl��m�]J]MZ�v�Z�j�����'��!�qJ�@\r�%Q����������n��5�83�7�|S�N����z�VYyyy&L�g�}�
�y���R���{�������vZ��'�<����������UT��~��7�����v8����{c�v�v�y���-\��d����
g���q�������},X^:�����W���>}��T����{��Wn��=������dytk���;;���'���K�>�{���;��K��0 ++���N3�������i�����K���?��������o8qN��m�����CUT(��7o�y��p��w�=��_m��%������r�v�;r���������[�n����c�*���t����f�k�����6l��E��	/��v�R<P���D�^���is�q��|�$)z��7B��z���7�,�+���������3�-[_�d���7n\q�i�3(]��'d������N�QVE��r���s���7o��-1��	BO;�����/Yx�-�4k�l���Q���Q������K�+X�~����VJ88����7�)Y�p���������{��wb����;�������8��r�^Q�4VNNN���7i����N;����{���	���f�a�X��8����,Y��{w���N��a�O�>�T��aCh�u*�B�.**
]��J��m[�v��6m���_�;�a��a��~���H�P�%UT���*��89P�����k������m�2@����x�����������M7�r;z��dI8h6h� t�A]tQtw�`��)Q�/�������+!�:tH>[y��M�����w�s�9g��Q!�a�����*<��YYY��+!777%C�>���d������p���c��m��yb�#r�o ���q���a������K�p �]�xD_$|����H� �q���y���;�!��B���O>����@3Mw�d;N��y��WB�����)���"EW��5k>����f9��7n�=�L#��Y�v���?���hs��mm�����J>���G����>yyy�;nJ���o�-������Z����N?��O7m�������������_�J^{��4�n������/�]�t�!�$���:���o�=*y��w����o�[��5jT��BG�q���-�x�@�c��W�:u�$���Z����M������@j�8i��$�1s�L��S�s�>�h����N��L���E�w�y'��e����O>���?����;�������*S��W\Q�J�����'�+�L�y���c��|�B��-:4]Q���N����j�����>��� �qZ�hQVVV�g	Q6m����7on�"�q�t�I���@�U���%����2N]E�]jPz��)�"�:��S�C���2������x2^U����&�'��J����T9�^�.]Z�N�=z$��F�������5j�f��t���d;f��g����@j�x d��+�Lw 5�e�4�q���9P������4Jr
���7����e;9(}�a��N��+�w��n��
�K�+'O:�����{����������!g�n�������r�-((Mw�����k��T�k��.�����L�<y��'����N���@vW��p�i�������~:d{��1����p���A���;o��=����BW��SOMeD"�k�np8��
��e�4�U��S|.�l���r������N��OT��3f���i�?u��v��4k�,��pt�f��2v�T���]	�W�n���!�R���7m�t�1���?����[F:��#���W��������.�����#��T��;x���j��u�a���@�������g���[o��9�����N�Z�p8Kq
�����������H�*\�����_���������S��>�m�^x�7f����i�����>��W����E��.�n�e��_��i�������m�R���TN��]��.��E��~����]{��%z�lW��7���{��7���]w��g�=c�����/����W���3��������R��g�
���{l��i���o����U������z���f��y�����$��,_����v��s��t�I����u�]�Q���kb�*�D��Lq
�����U�V���c,#����Gydt��;�����?.��l�B���o���n���m��{���_|[T�d��q+�)��*����!��4q��p����N�(��������?�tW��<-�lW���k?��W^y�x����s9�(w�{��'��7�xc��
�WEE�]l8�
�,YR�v��}��������k��}��M�����k���p�L|k�=�'���I��7��������k�.Q�Yg�
�	2c��t����������vGyyyM�4���.\:??����W��i�J����~��P����!����{��]������+C����__�w����4�n�z����T{���C��c��X����'�|��v�Z����X���p���L���K�Tv��U�������*4 �U�m��8�Q�F�C��{������U�z����a���$I&L0�_i���GW����v�3f�RY���������K�������+��b���7�p�lWN�B���G��MX�f��7��}�e�-\�0��2L�Mw���s���:����{����W��h�����y�_j�3gN�_�b�R��/{��g�v����"//��;�,�O��>\|����v����wXT���Ab��X���06E�F�%JT��+V,QI�DQc��	�Qb��WlT�5 �D���<���w��.��^w��>���<�����3������M�_\�|Y������]��7�A�R�G����2�v�Z���Q�FdL�n���_��RORSSa������!�n������k;�,_�\����?� K�0%%E���Bi����w��U��_�x1j�(��:�-mc�O�<�7Hu&11����d��X1?�2k[|||r��}��u��$7n���+��� [��a�n@���G�]�b��7oj�+-[���eKNf�\�|y��

6�20k��a��G6S'88X����I�(�.W��k[0�(�p�BOOOm�?q�D����L�n���l��}���0#��^�|Y�R%�Y��,]�������i��	*���/�:m���}��7K�.��W�t�C||�/������L���'22*�[���U������B@���� 4o�&�����1����`O���������S�����J�I�����E�)R!���|��f�O�3g�899�s(X�������m�>9)))�;w���T���q��y�j�`mk���ge�}~�.  `���j��2����+V���$..N�_a����}�
*����^�lY���`
���=?��sPP���s��������g�i�`m�LRRR��U�-����6�������p������k�`mk���O���#F�O����GU;�L��������s��]������am�����%K���?~�XiY>	�v�
��k�.��$@h	m�=ZiA>	�t3�'��K��)�Z�T)>b�s4o����j��u����'������-�n�����}�6#�6��)F0��9@��:uRZ�%&&����^�z����-[
,�};`F{�O��I����)Fg�?���=���\�xQiq����p��G��}�����P�^L�8|�0mh�u�~��O0�3d�(|��5J�I��6&��m��{���� ������]��e�-dr��U�V�+x��m�e�$`��0���]+Z�(��y9�	���#T�1�)�C{_����)���/�P
`���J�b���Y���'��������r
����k����O?�$9`����/��z.^������l���KR�zu��^���+�pN�#G����~���"o�)#���3''',����J�b�hY���md|}}s��u��Y��$�����������DGGC�m���iy�6�c����=y�D��@���9`p���n��I����s
�������SX�v������\�W�^IGD
`���JIe��t[ZZz{{�]�t)_�|�HMM5�lf��?�l�������o���������DiC�(U������lf������~���Q�zN��O�RU���oH��`�h{���Jb�����kiX������r��W����|������;::J{�3�b��Y������_~	cr�������`��0f��'Oz��aggG�u����3z�)�������b���+/���Ommmw��i|���)��%Kn����������
���-[��+}ZZZ���H�)��!���I��=A�vM�4y�����3K4�`L�4j�HA!M�3f����X��oo�q
 �8}�4%��)���	&_6�Ds
 _�|0�C��������j��{����;O�<Zn:1*�����Wk�`m����|5�7o�Qyb����v�����$�q����������X8�+VLOO7�xfIZZZbb�6o��fs�������p��7o��eKjA����0�^�@q��-++���s�:uJ�4,,�R���Zg��d��S�������TVH�����,Y�S�N� OX�f��!�u�F&Z�(55V�X�bxa��q���\�* �����]�|YA	ML���C�>>>_}��qtN/p
 �������7o��itt���])��g���3K�J0@�%����
i����+���7U���1�TfFTT��)�������Ao�����nDY���cD���������}P����k�FhW�h��)))�J�=//Z����%p3��]�^�;w�hx�M7������-���"�����7i���
�9�C�����-w��Uym/_��K��6///�&b\m
^�����_���&���+��!C����5k�P>1<<\��)�� 66�6����;;;���g����@7>|�����M����@\\\�=��m{��%�5���Ao���>���5�6BO�<I���!6o���J���C�&��������N���+VT�X��9s�Z�6��Ys�Y�faaa�x�FZZ�=�:��3���Q�f~d+����������+ ��4�Q��Y���i��G<s�������r�����	����&�������/���G��`��0�����tww�`?e6�cP9/i����D vvv���I)���."�3111c��<x��5kH�X��U������C7��<�W�n��]�*'�i������BBhh�x�6����w�����][�@d����+Z�n--����@XX���4�?�p��@�����
�m����GK��={�`P��F����F���7����.��M0�p��E�y��1b����f���I)�-���3�����-}����K�����e��Q	1�j)h���8f�U
����/_>~�X���W�^�[����+��X��"..�m��R��n�:�!��O����y�����@����I�~��l l����;w�Ws��	#f�d+�t�R�s�d�������	���:�n�1�����|�n�8���GukY���q���+�]�<yR�bE��� ����III]�v��J
��������k�������;w���
�9|�p����S��L���|�_�6��0�����}�����4u�����@�&M._����{gg����+-�	���������}�g��t4Z�/�)�n!�v�v�_�������
Hi�hpK��N�:Yd�q2d����a���bU�<y����*W�\�>aOn�����
�8s
 '��~���G�
��������i��_�����%��p?������C���)���t��*;v,}�} =K��k���~��:C�xg����sgm��O��6u���#�l���G�B�����e����K������?y��F���oOOO2&T���6�cBHO�
5j�?y�{�o�;v���������w��4i�;wn��W�^=x�`�-(�������g��6mJ��5��M�4Ii�M�V�Z
6L|<p��Q�		QBFFnL���-$������{����7�������u�j����c2o�<'''�/�(�6mB<H����
����=x�@i�M�����~������������:#M�����?n���2���%����C��0&~~~\�Fg���[�zuq�f�d��R�4e����3�8�����9����K�.��r�����O�Q���)FK`BCCa�������k�`t.�7�|=;::z{{��Ka���z����CDigg��-FKV�\)=������{w,��j��>�0�I��u�������������������[�t����m.��7j\�v�IOO�O�i�Z�zu��5�T�Xq��u
	k��}��m���J�bLl�)���-�<yR�J
7�:j�����;wnxj�������)&�Y������Z�R%� �J�*U*..�F`�CBB�)R�`��]�&$$($�����Xfggg��E3g�T����� %[��;����z��u`��QQQPo�:u`��'��>}J�������-����7�awww�4i�J%7FK�[L�����#GJ�a��Jp}<��t��AZ�th���
�~��g��,��!��!C�H��s
�H��/Y�Diq�����C��
Ix��O���A�.��/^����]�t��5Bl��A����s������K^���E�����+$��P�ti�S�1�R��� �'lkkO�D�3g�TyAm
�v�����A��g����5kF�T�
��o�c�-Z�n��
�l&�_���y�9y�d�����Ax��!5qsssrr:~���jSlL���e���:���9r$#�h:�����By��U�?^!��vK�FDD���3��
*4m�T���[CA������@����\������U��m��)�3l�0��`�0C���l�s��A�e1O<==�o�3HNN���)�����7o^����`��U�.X������G�r�v�T&\]�=��a���Qe�|�r��9��g.@�����&�g�v���6�d�?����\�vmQ�����h�+x������b|��5Jk>L�4	j<|�0}�o��{O�y�����������>8�)&[������[��q���w��*���W_A��������`��h����/5!B�-?Q�6����w�bbb6o�|��y1(R�[����7n\V�������aQ�"D����w���0a����<			��m��s����� �����l+(�Y���:B&�����/^���{F�<Q��L����[�l��aL�������B@<�����>��I��������n�����'O�TNd3���	���g����S�||WO�����-^�?_�x���Z�R���Ft��R���
�����w�������h�P�R%��������k�e3�������u����,���!>|8���c��3�^(��|���������4iBn	�V�X�+W.��o�������I�>}TF7�-1������
LGjjjbbb�6m(�x��9�7E
 22RQ���G��.]��T�ZU���@�Aw��>��$��0��9�'O��nnn��{������(pKH'h���1����S9���+t{��	��]�v����}��-��f�hN������ ~WPH�a�����/���)�VIL�8�;kkkX`X��*����A_g"�_O���dt�����;v�(F��\�Z5�)������������^�J����loo��7o.-Y��Fll,�7����Hy�����C��z�RPBS!B���K�a������<�h�"���3���K��;w.]NTIl��M\�pqq���'OVP`�����nILL���������_�=�X'''�)�]L3a����X����9s�T�R�"�i5�	��@�g�R�?������y�j��	/���SlV3��������RT�v�O�:����MZZ���/<m,�K�,���_�<y(�(n�s
 ��0a[�|y�=8Lox�<-�Uc�$==��t�*��A2&p���(���'�n�:y
 ���[��%��)��o_�c�3��_���al���<�F`m{{{��hm�c��kW�6,,���c��1��M��kN0z���U��7o�������{��j�*�!�P2���'O�,3Yj���k�������.�I��m�V�#�y����/��K��)F�-�t���@BB����+V������K�{a�'>>������%
����W�
(0g�???��������p9���nHH������)��
<Z[[���K������7o���Yr��s�N��5-2���1^
��Mdd���9��:3j�(KK�_~�E� ���Rj�9��z��D�P�����pA�-��?q���������[B7,
*�b�
1�6��^��<Ua����{�����5k��!��-���w���]�bj�}>���7��bp��a"��W3p�@��_���E���iG�Y�Y�S�%>>~���3g��|�2�p�1C!7&���wss�C����'g899�F�tww�n!Bqrr�<���2����8v�X1A��D�=�SD�[�U
��i�HG^�~LH��%��r�%�j����&j1�a�aI`4D��S'44�nI���x�T6�-�w���J�*����@t�������]�V��%�X�b�
RHX�'))���f���n�����J0:���+[[����������C���={�WF�!&&~x���1�#""�&_�p�
o���tV��3K��������9~����u�<y(��F�O���1Q����m:8s��x$O`��c���������&wwwh�J�*����n]]]o��AOW�Z�;wnz{{��X�pa��
�q��I
����.yW_:��v��S�b����:�g�jS[�lQHL����C�}���Qtt4�E�|�`L�2�a��	���C��t�{;v����:�pd>,Chh��>3��/���"�F7����)���-��._�,�P�������D��c�l��]�vqq�=:������r������_~��t;d��G�0,���X%�G����k�Dt+r�L���c|KK��E�R�=o��)#��(m�����w/��
*�����ySi�M�	&�!����������]�9`X�9e�������+��.r:3e��*Dv�l��.\����&Ov&""����c��������������5k�PU�����8�0��l///xkX�����o�>�D
`��a��`
������};w"��gODs��&11�����/�}���r����3�YmHKK�x��� f������+��I2�������L���^D����;����/�OE
��}�m�;v��*1�Y�T�j��Q����������/55�B���qcn��
P�����7o�"bgh�R%K���?��>��tKD
   `��
��o���"��"w��U�p�@��%K22K-�5
O����%:s��i���{���	��!D
 <<<�5#`x���`+�������[�-�u1��������Ecq���������j�yY�|yF������Z[[c���u�C�f����+>�.�jS�Z�RHLSE��!~�&������Pu�*U�*�9�Y
�����b�s�������#7n��.�&M���-}@���E|<t���S���6��.|||���5.Z�n�'�\�r��3[�wnnn��x���L%N�:�`D������o��n�Z��LTT�T�Sj�1�CE���k�.(688XC�~�^6��f�t���}�EZ/Wm���������\����0������Jyj�'=>'R�J��G�\�Xg�tK.]�T�pa�$���e=��R�����V95G�\i
 ����n��Kh&$$ �V9>�9O�H��p3*T�@|�����7��5�g��	
�l������?�.b�TLn��r��������'O�>�h���;�G��W3h� �B����X�^8�*&"�@��m�-�Pf/���������Zy0 VVV��S[��j������l6���c�l���tp��������+X�vm�����+D�"&[�bc��y�&������RS�N5���Dv��^�t�tau�>}j����sg�L���'<���>��"�������HJJ�>�*�h���2����)Fg*V�X�xqiM�7o����O�7n��Axx�p�"##�5k_�����^�����C�*O��}L�P[a^�
z�)F7�wK0�a���H�1Z"RAAA_��t����R��-�v�R{�^C
��.��O����nkk���G��x;;;������B\gI�^�j����d�a���;w�T�P���666��	�

��O����G�d.�b�l�C���[�n������E��[i����c��n�3J�JJ�c�����0�m%��9!!�{���\�� Pp��*�N������t�N�l���x�����}��UPBs�f/�t�B���]8��N(�%FC�`L,X �S��)�����r��Yd�N��f������0`��9�����4i������C���1c��G����5k`���L�������M�6����kw��1���4w���������)����`�`����_���.o��d�I�&A��w���*��)))�'O�2������`I��m�6_�|������K�����j�
�m�6z�hjG[�R��7��s����M��L�]��]�O9�?�P���tGGG++�DFF�c�y��!�.���.���
��z����������c"R�K��2)*p
@8`d<hkkKK�J%7��pT0��a���w��uK�B�����v����w����B8���?��YA	��,�tWF�c��Yt	'W�������JHj��1C�=��������S��w�1"�

����~�������+��.]�d�;�����^
�-�u��p�MFf�+��V�V���g*oR
   �o�3�����Kooo��.\x����@),�Ef;e�4'Dp��Z��Rp�x�Tg��@�(�`�����K���1��gt���A�	%Fg(�'O�	,�����y������M�t��wO1q�vK��H�l�Rmdwvf������l�n
 ,,L	1�������'O�
8��o�����]�\����w�l�W����m[�e0"/Z�d�<!w�z����"��*��> B�8q���k��_���������S�����t��\^������#y�+&+���$,������[��p��N�>�%��(0RO��'O�����e�TN��={F`��IF��|8q���LD�t��������WFs#[)�k��)$�9�!�D?�d��10*o�j�*o��|]g^�x	[�z�j�\O����v��$[)>b�3o��MMM�-�Q�n�J;`������h��z���!j
xFf�h>$$�O�>7n�������c�[Xi�St��kkk(���Qe�^
�g�������W�ti�Y��hcc��<q�D���S�APk�32+����v��
N��������r���y�~��W��P�_P�n]���P5�E��h��4Z��4�������������9�0�����~��4����W�^��W�*V�_����Frrr���DL�W�s�l�@����,T�|6�/GFF��	&G6�c��]��������#.c��h�`tgD�M�6�>�[�'�����>�����1c5j��g�;w��`V)&[ ~T1;v�ppp K
��A�V��d�`HH�8�p��E������F3�6m�1i���������J��S����~k��|�%K����RL�8q�����)SD��J�*������DDD`����
��������y��J���O�<)��?p�@Rx���U~�Sc6`-�����7o�����
~��]S������+W����Qt�T�f���~���I�<y���k�/p
 ���(R�HJJ���.c����~���2�gI0��������U9��hItt4��%J ���ys���U"hN�4�S�Z�RV<�������$NNNP����|�����A��SF@s
@��`��?�%wuu����&��)S����>|��,`�"�tww6lX���-����������"�;��_~�����")�h�����z�"x?~���������*�������;�,�����O���������f�AH������5k��+V�B�S��Exyy�{!k��qc��QF3�V��G�1���Y�TKS��?7��������Z�Z���Llll�
���'N����l����������Y�j���w�ix�S:���6c�-��d�� �2�����gO����Gg�0"�+Z�h�p��n�������&Lzzz�R��k>d�)8t���v �@��m���n�x�]�B��-"h�V~|��C��[�)��[��u
`���9#���'O�����\`�&$$�� 8� �3�|ED5E�f�Y�f�*U���p�&M����q�Gj����{��O�<Q���D����������j�%�R�ENg��6m��>O�<.
���M��}{�kkk��j���MMM-X�`pp0�g�H�D
 #��l��5�U�����s�
K�.}���t!4)
'5���.rc�T�^6311Q���������������[���X��5�6m�����]c�RZ�h,^����/�+����woLZ����
6��6��"8�	�5711�7nL�D����Z�lY�H��e����gFK�?�y�N�;"/��/�4�h���;w0�?�������g�#aXF�	eJ��C��%���-1Z�%��gkk�U��DK�����B�\G���z�
��L�2����0����da:t�`\M�h��
lH����9"}a���*)���>0�����Z�����-�bv���U���R�j���s�B��/V��(����n������h������������U+�@Ff\y��=���%�W����+'R��}||,deK5�����?��(w����v�N������12b���+R
�Nq�6CQ�r�
�]�`N4h0g����4�����nnn�cmxnp��6mJ9`@������dcc.nPj���A�����Ua.T��a�����d�t�Rv����XiH$&&�O�1v�S�X�b��������D���w���R�F���A{�!�����+�	��[r��I(���Y����X�h��k�.1�����R�"��+W��?��m�]�V``�G�:w��6��6�d�[��r�O�H�"5k��^�z�c��p���En��������w��)�*URy�U
���/^��UK%�U�2�B�0�)�]#���]p}�E�1?��w�x
?y���^^^PZ^!3�!��DAAA�������GGG[d6�1��f��X�6��3\�~]R
����G�	�K�}��������m�22�9:��I�3f���r_�l7|�p�U>v��#�]�lY��5j���F4�h�O�
&�_��������3?_�r�@����KII��R�Jh���~������&MRZX���C�P����vKr�n	m����{��-�q��3��f�����y����}{�2e��1��O�o�>e�4D
�U�S�)���R<}���[�.}D���a���Dg����e�4h�bJ���O~`�S��)���y��}���/_��/_�lkk��Kq��S�N���5jpG�l5��Y3������={�@����7o���V���]\\�.���U��v���7��o\1��{��yzz�<y?/[�_���K�4���*���A������s',��c���q�h��]!��
�c�W����@V����[�x�_z����o��o�����.]��2�d�aI����&��Q�h�(,,?��f�$G��-�j���t��e4O��[g���w��!T&���j����wF��'��k�Ni1�������"m|��R��5����/��288�����Gn��
��W��d�����L��[�T���d��[
���3
��0�!�����X������?{�l����{t�<Z�lll����8�
�vq������?�����F��|@��pOk�{��v��j7�B�$%%����a���Gu����w���~���)�A��)���U}�����0a����G��8W�����D:>*M�������n�3�B�%����������[�l�k��I�&��{W�LX///2&"���nIN��-���s���?c�����;Z��9�
���t�j�JA	��v	�9s��a0��V
�T�R\H� ;v�@�dI>����s�J��R�D�L��wX(�W��!�)���0&JRR�=z��J��
3; D<8~�x�
hV@��FA�����/��@���w��M�p�i�o��
�k�@�X�����
9i"��2�'E
��]�`IBCC���������#F��{W�P!��t��"�;�����U��a�k����4x����y���Y����FLL��|�����)���O++����[����K{D��?_��gt�W�^4���G������g>MgX0����[4������,�r�*.Z���b�	w��>|���/��M�6��������Sj�C2����C,|W�\#�?���>����'�\����+�~�x����
4�+x��	��`K�?�J����|��U���'a���s������������s�0�N9yM��k�"�k���<��������Q�N�wt��.���q���������,��;>k�L�0AX��;w�G��1X�bEw�K������`z�-[�^�zj;�"���r(�:uj��
�����t�n���
����������m�b�� ���������/K�(��_?��5n��
s��U+���%���#�h�"x�4���+'���s��eGG�
*��QQQ�$�h���p�>�`�G��]RSS���K��i,N��y��}�>}��c
iNH#J*q'��&[)�aL���k�����5����wvv��u�z�Dk�.]�`�x��6l�Q�p��+���'7o����@zz:��"E��z����j�*E5i�C�?���t����=�?T,Z]�r%�`��tCH�%���v��fmm
_ZY�M�����P�Yy
�������t1K�v������tA�S������+1���
6�S9�f��:������3���~�Q�F�|��&��PbK���%��cB�Z�U�6r�����[d��<w���k��{�����K0���'&[�={�!�|��I�����-ZN
)8��L:�=p6l��l�r��!�r��<{�L���;w�����E��������E����m������'p9Tn.s
 ����"c���K@�932��,Y�����X�8�~���P)��LV)�����������J�g���B�			*�P,5��X������i�TRp�i+��������"�@F��v��y>��G��n���#D6�S��n	�L��=�%�����}��"�j��2�-1��
����W/�����N�:�S�����T�\����L���( v���)HKK�1c��fA�
��a�������%"�
N� �)D4���dI����+'�i���KR�n]��|8���>Z�*�t���a������*U��������X������c���'��^!IM���c����jS<PHFs�Q�F���#G���l�BNZ��M�u��i����m��#3g�TI����7�d��%\S7������?r�H����8y
������Ij>DGGC�����Go��������v�2�l��6nIF�
�������]�������7�N�z��1��|����<������tWW��e�
O?�m��4,M?~~x�.]~��g�����VVVp?�z�]�   �O�hI���?����4>u�}�*����I		#			TO�HNN�3g�#F�[�������������(�
����;vvv<�t��I
0���1E?~��O���k������]�R��X������:H+J�JS�����+W<<<���{6�O�N�X�y��?�� �����l��i���/�/��b���*O�)F���#�C��A��c�h��
����P��/_*(�ynoo��mW�u�Vj�`ccs��a�Kg&�[bd`���1d�������i�`L�4i��E�5�-1�����;�Gh?[[[GEEQ
�6���=�bm�Y�V����~�z(_�����|�E{n������!������_Su1(l��+�(��p�B�QtOHLL,_�<���'O���j��a0#3����f��;,��14`�8�����W�(��C5�4�0�(�����4"M���0&
�h,[6l� �cm�������kii��+Z�^�,2kqGFF�wD
�ptt��������Y:b���N�:M�<�v��\�Cg�L�"�$j��p
�P���j,[���5kV�\���i!+@*R�������:u*�Y�pay�7n-Z4""�y�����������m�6�hj���gO�)�
�A`��8<|�J.R��$�
�d��eKFf>�J�����U�V|uK���Cw��������v��c�#�	j&[hH��i�6�D�\�GO�rC�_~�%~~��u�Z�
*Ds��;G�#L�����y��f��_7|�p��u��1��s]�`A�����(|������\�����V
(��,�t����c�����o��1�������gU^�v�.]��<?~<t(������������A�G�UBRsjLLLLKK#QQQ��T� B������?��2�g���b;u�t�������u�&?J'R|NCg?~��������O�<�M��D��p�z��%�[`�T
���Q�Nh���S����e���(!���n�1��ot��{w1����<�g�///GGG
7���,m�n�q�
x����L�C��{�}���Q�}���SNF�&�f�����?x�`@@~�=�%K�h���Qpp���	jS���_V���I��/^Q�a��YYY�8qB<-[�,��X[[��tv��s�Ef��;v����7���W�_|!/�GvF���d�)�S�N���'��0�Iccc#�����)����@��H�O�LJJ���]��
���G���)��g�!�PIdd:���\@�<c������o/�/.Z��v6��Q����w�����1�b���u��E���/j_���$^���@W-��e�����B�
�SlL����'=z�������'��z�/_����������c��]��a����'��/��,z����_~�u���!+����r��A�p�|||v��M������+���I.�;v�����_}��lq��E��E��0��.V����7��/]��K�,QBX3���7111������j��1,p1�;u�$�]�vtt��c��i/F���+Z
���RRRh���GE�����������3��������VI\�t���E��?�0&
\�v����������[�=���}�p�]���O�>�P��78	��=�X�`����l�1����JGF_���,����^X�r%���/�*41}�te�6]�-�n�z��Y��M���={VC
��j\(�^���O�8v�Xxq����U�T����{�����]n�����imm
���e��y�B�0�T�5))�n����+WA������w��
vK�1���w��~�����������v������;w������,Y�S�N����OOO�`����X��b�����9sH�Drr2��R��/��	��
m[dv.�����+W���
DFFRY����;88�.]��Z��=t�P50�d�UR�X��r���^^^�(En���k�Ef�1���;;���h��i> f�)��C��=CQz{{9r$#�p�;�4WN^�&&&�L7��WI���0���={�2�v��]�#��s�g��������cQ�_�>4,��#!��o�I]h&[cbo���>�y5j�V��p�B�F�h�����TN^��F�z��h��67�r��#GZZZ�_�>#�@�\����O��n�J�!���@E%5a`:��-���r��E���o��	���3H���~����#�V�����%�P�z�
\�~?�������������Lxx����0T�|��!b/z��5�OZe��P���YH��GF��vI]��k��#m(1���h���<����,%�����b�n��h�����uDDDZZZrr����U;`Fg`.�����K�xJUO�
����H�^���H��1��^7�J�\��W_ISW�^-S�}E��7H����u� ,�����8�<����aSg���taS�9�X;�@H�����;���k���;wvuu���Gvu����P��1c��h�5k�,�����c�AO��~������%�9����N"����E���E5|����������$������FGF�%��?�������C�7�c������n����oE�N���+�tc�������Y�&����C�����w�
.\�vm�/^lii��uk��,�����+W�����[�na�tqq���]������M�>}`g0���o���f���7���<6m���aC�����������������?� �|��J! � �J�>��9���{s������������G�I����6>|�����KjS�_��T�R�����?_������T,�����t��a��q
�a��-[�P���M�����U��A����>x�@z����V�\9���	&@����LZq�R��?G��5�J�(����<)���L�x���|3���n��Y�<����2-�
hnZYY���|�����3z�nIN��[But�<y"F~��7����QE4/N�:�J+��7��-1s���^�������%\������@o��-����|��`�THHHP�v����0 �Z�6l��x����%RIII�Xd���<y�B��!Y��p����O�>�Gd�9�0f�/��B�����U�I7nW3�
�up�����3B?���z��.�����!B����C���|�|�����
4P)S��(U���Oo�9v�Uh���D�w��)�h��_�j����D��������b���|)��G�UTF����B�[�U��q�n�������DGGC�}���������{���+'�������#G����������s�~���?��C	I�2�&M�]�6���
������� �Dm��-[��Ft��M��������o�~���qx�*)�${���1�|��;��]����0 >>^��S0/>TNR���D��G��U�T�K��v�2�l�
�6��Z�hA������9��cd��)�1K���s����0�'**
��S��/����O�b�
Jh�hN0��@�*�W�\���kq�{�������w�^F�5pgggn�e�A��G�V[���,,_�\A	�vK���[Hg���[gii���?+*�9�����������#�e`^����������G�B�
M�6Uy�6����%JH�����W����~���+W�xxx|�����lL�>�����"��"��/�y�����kkk���I.��(O0�0q�D�%)\�����H�i�&!!!44����
)3�7��������):(������F��ac���aA�e�_��o�>jzU�X1:\�m�6��)S�E�r���w��Qn�b=���W�^����������ay��-LG��U�H��g����CN2]4�5k��G;;;��
�����3��_���+W.�y��E�e�93����A�$66�*H)R�r��TJB�.�]�v�j�YO�����^�h��u�*(������/������S����Gp3>��32���u�hI��I�GGG�e�6�>}�����1B��S�N�k����;t�]`` �X����t	T
���3����;�>��w�e���O"@<XA����S�R�E�����pK"""�7o������X��������HG?~Lu��e)s�i�&Z�����`�n p^�x1��A�������VVVPl�F�T�����0�9�Q8`@���OLf:�/�����%K22�A�	�c\�N�����������j�j��ibw���Y��������2�������[r��*5�+W���`.J�{�����c�.]D���4m+��qY�p!���Y�����?��ccc��{�������6m����]�E
 22RQ��:@��O�#��V���.X� t���t���+X���E�0**�<@��Lo��-^�������L �R��������tKN�{�R���\�Gg�a8�����V��}�v�z������W/�F���������y����i1#]!W)@�l�2�n%�d��P�
���V�LXX��Q��L�GRe������F��]�~�O"it�P������qcq$ _�|��o�G+V���+�W��{7#s��N#NQ��SB�,X��,��������Y�|y�S(�"�=���7i$!!��:�A���(u"�s�N�b��1)Y�$9��������Ef��I�&��dd��[�.���'O*�?�)�n��d�-���s�;DZ��O?�����/,���%���={��WT�T����kk�v��q?k��M���qww
"E�p�$���}HLL��n����d��
����A%����*!�9��*�q\]]E������ �����<�*\HV`L�O���cG1�����U�B���US��{�0h� �����"�i��
8�9z�h����1��>~�xF���"�!��m����������k�����0�������z:����3gX}R�]�fkk�������			�b[�n-R}��E2b�����}���G�����S,d������
��)�������>P�yX;;;�)���`���/�IBg����w��U�P�@������q#��.Z���722#��'��"kkk��0;�^T��19�%��nI��v�Z��n0 i����1c��bHkD\�z����T5�y�������O�0{�����3g����t\s
����/B�5j���P���C��
_�~}��!:���C��g��_������<8�mhh��E��O�|�\��
t�����R1����+-������=m�4��������bw��I1��c�LOO�I�k\�7o��a�}eE5i�a8*�}��K�������$%%��[��K�r�����Gnnn��W�0�Z��?OU}�%&&�_8p ���3�l&��k���<���!����/�gSI$$$�=�b�����m�����	������{�K�6o���P�B����Q�*C����g�������Hdd�rt���d��e��A$�R��a>f�-�!���j����CqLq���*e���y���?���xxx4h�`��U\CLg��Ycee�+W������@���JGC��{���S77�*U��z���6i��R�������D��U����@����-2�
_����5"m�����f�����Yd���N�@�<&&�~��1����c��%c��UTR&!!�.�8H��N'*��� ����~+�L��_���0�d���q���:u��-�*4�!Rm������U.R8i
�aL�ASZ�-cWWW8l��)�9s�,\�0((H�v�U�V*)�1]�-�!�)�G�A�*���Sd�",��!CTq
 ��|�2�����7n\hhh�N��5k&^c���}�0o��?��s;;;��������9��Z�g������u�V�G��	����,��lll�������7E��gR�^�i��q�\g`�1o������
���!}�!Jy/`�aFD���m[���m����+��������)��B�
�8��"�/_��J�O�������R��:b��u��Ty�)��`�$�)��?��D�T�[
�r
]�E
 <<\��������}��
*�E���pK�W�.�����q��+�2u�TLZqgY�����S���	(s���<����mtt�"�����7n�=Qi�4k�,�]ZT����QqT�����������]�6��0A����U����0���B�EXX����0"�MmN0�����i�����'<<<���TZO2�Bl�)S&==]�)�3���B����k�/p
 G�����RD*3�������
��w��b���J���������#������������C���
STF��D(\m
���#�He|�����(P`��y�
��1cT�������A�����[�n�����0c>�X�����prrb�XD
���W^� �)�����O�1��!R�������x����	&���@�:u�/�vKr�pqqQ[�\��sc�DC
�����O���Vb��Am������z���<x@/�����������qtt��(�s��q(���������?/_��Si���hH0��V�Z��;MH�v�RSS����t�f<%%e��e�6S�LQZjs��CZ�ly��	y����(<]�r�r2��"���|��EZ���V�Wi,�����(�1D
�������1��q����s3,�l`���H-���
����o�(������O�
�>}J��;W�dI������/������z��=��l>Pc_�gy�������y����S�S���g�������(��a�����C�M�6��W�^������LvIJJrvv&c"��?e�<��8�0�E��_}���w���$��iS��Us�������_?*	����"���?�TZ�����!!!���VVV5j�-x����`�D��%L09
[r�������tKKKQ��HLL�\�2�[�R%���qx�"E4hp��1��5m`(���*V��y�f���%]�V�W�^������|<z���B�~*p
� ��@����*-����/����'#3��7o^��e�+6n�8������e���b�w�sM�����z��*)��4i�D!a�a�������#��V������|.��O
N�jwwwKK��?�����P�B�z�q�|R�[��N(Yr�g�3������<x�������U�>y��x��YU�c4��Y3�Yx��!����1c�����O�����Z�r���7���S�jUnAk�jkk��Ztf������������111666��0�l���Y�T���'J-I�b�D��+VP��
������[������<�0c8�����7Ci;v|��uFf`"��`>)8���������������(b,��I�n�n|�-���\�zUiL�'N899���u���`iiioo�gt�K�n�T����/��}��/^,X���CE>����>>>�==X�}��)����SiL��~��N��_�mq����
��e3in����9r�t����z���c��EE
v���	*W�|��]��'�a�kO�<YiYL�
*xyyi��)��� �	�0J!R
�y�l��[�|���D
`�����a����-����;�����d�/��,���O��=k|�L�� ��t&�8x� u	)�{�v�4h�7�|���?>�\�F'��YC)�:���~�����������:*�z�����'���y��U�V*)������9$$�O�>7nLOOWLz�a�O��-Z����ZW���Y�g8999#3�8��2�����l���#G����uK����o���p��s�_����l��[B{}\��1E�]����:t��a=e4 Re�����������C�TRc� T���3�Oag\]]�/� R�::v������S�0�� �&���jee�X�r=1u�T�k�+]���0�GL��{%�0a���5k��?}�H����a6&�ddvW��d���D)��-[Jo��u����n��
�f��@�r�J�(!�S��!RX"�-h��_�����+(�IC)KKKoooy��)�a������(~��G�J�
6��5g��������v�jTA���0`��G�����W���>|��a={�L�+TbW��a�O����W�P��#����y��T����A�J�*�q��{��m���������G��H��G��_�cf�@���������o��=���9Q�������)��a���P��5���������#���;w����<�����%e���4����twwG�A���������MMMU��f���`ta��x�>}:,C�F�lmm\���d�[�|J�VU///����'O�(-��#RpT�v	��&%%_<�18"�?~WW�R�J��1C^^��."�E�T��Z`�a��{����
�
���1���7m�$=z4��o�n\1��������������������+����X�Z5%$e�����������prrz���g���t)��� ����9����.��X�~tt4�"b�	��?����0����p���#GD,��X�����7WF�a��3f���T��2��G>}���;w��oii��eKf�#q���'Y*$�z8;;c���#22�����/occs��1ef�#�������dL���[�|R�@�8�p6��3��_?�`
�a���F���>|�t��dI�����]K��S�0���g���'b!S�����0�h��urr�R�2�q�����{�3g���UK��u�V��5�����a��]

�0����{����O�<I���@�%���H��0�������666�L������u��u��S���tf��=���E�<xp�����#u98�0��"Y9<�2eJ�v�������(��c�$x����@zz�����H�m��0)�?VPH�a>~���d���t��n�������8q�>��^�N0�������;;;{{{�,rc�)�a�#����;v��r��t��a���w��9�o�>��b0��0LV�uKx��a�����*::ZiYL�k���h�3F�k"���o�FY(�/T����O���4X�x1L����5�&R���qc�amHMM���/�����/^��"��?���7o(��c�!��������899������4�����-[�H_`�!4�%����o12e��7n('/��l��Yi)L��~�
���~R����km���C�p:w��
�O�M�6��(-��0t�Pi�0)[�n7n���/�L�6���1�0�@���aC,d-[�2d����U��3$)������U�������
��0�GHTT������,I��Ma1`7"##�"�w����'O�v��)(0�0!��%"���C�0�|ef��a��mt9���7�_�����p��z��xz��ac
�0�GN\\L�,�G��9�b������ D7dv�a�c#$$���r��U�1!!�b���X{���X��$^DD�B�2��r��M;;�5jy���jS
4 KR�ti��a����-�t����;�:($,�0�������W_������5���L���[���?�������%K�]X�a>^z���?�?��s���G����7�� �Q{i�E�0&|!�a���v��0��b�v���)�V��������x�0r:v�heeu��=12g��$*)���W�����=�a2������?�$k��������a���A��\|��g666�!����1hmm�k�.������h��F��a�����������/%%��{��
����~��]�_	D���0��p�Bi=�������c9;y����7���#.��0�h-ZT|$�2~����J,[�����|��a��`��a=���lll`.4h ���_?J�X�B�������Kjj��2��2|�p:~��~1���\�F
����8qB������s�����0����5k�x}���������j�*T��Y;w��wE������7/<d��e�#�D�0/^��l�kii9d�z��uk2&�7F�=z�hE%e�����a�$$$���������������O2#�5Z�d�?�P�x���s���OY�����s����-\X*$%%%��]�VVV����V��0aB�|�\]]�����a�a����AAAT�{��aX��Y��e���Y����]�V91��������u��Z(R(C@���A�FdvBdPD�1�*aB4Q��(&$�
��h�P�H��EA�)�C��.��7oZ���C�}�����km���g���������{o��9/}-+77����������s�����9�PRN�8kR uY�W���x��E���'�������]�o��a��K�.�1-��f��y������2-���O�92z�(��}�]�v���������W�����]���h��U;v��+�^�^��Wa��k�Pd�-[VRRc6 ]X�W���N�:5������?�����1&R��.����7s����'�X�"�����k��1�����3gN�Jx������8����g�rrr�F;��@J{�)S�<��3&L��}{�T�tn�!��������U����B���o,��iS��e[����# �B�X�r��%K�_X�l���4���x��7222/��j�j��
������H^^^��������?~<��@**..n��E��T�\y����muAAA3fL�s���5j��4iR|y�eY\�3g�2�R�JQ%������G��@��}��=�k��[n�e��m1RSQQQ����JR�V��>�,1��X�|yy��WG�_X����g�V�=�������n?�W��h����n����z���5�K�.��)S���H5a���u��5k���;��0 �������%�+VD{�02|��pe��M�9wp �X�W���3�;w�V��
�����[oM~1�h��annn��u���3)��/����
U"T����?T�������$Z�����P����10\V�������8������{������+V\��!�:D��p��0aB�q��������v�����_]�F�P7~���-�3fT�Z5*&ay\�� ���%@E4hPFF���3��{��m��M������5k=��r����)j��m999��~����������-��c�F�>����@����W;v,���n��<nXO=�T�]���={����O�:u��-1�R���g�������?���e���[������������wO�>}��y�_]��@J�,*D��
J�����y��Q��L���d��5�#������,..N������'�[��]��@�X�lYvv�]w�v��w���s��w��k����#�JKK|����+?��O?�t��.]��a��y����H�%@E���C��:uj�����Z�j����5kn����/^zP!��@J�S�N���?��2v��)S�D-�i�����;w�!�������Q���7�,��={rrr233/�������a�|����><����KW?�.,K����'��J��O���������������9�����:S�~�{���Z�j�;/���4i��O?���7o^FF��a����={F��{��
4x��WbM
���#G�z8����m��_��W�0�|�7@y�f��Z�>�l��
6D_�����4bYT��G����/��1"33s������-[�q���T�R%,`��	����{o��9/a���[PP��>���s�������PLBI��CP�"��8�k7i�d���ef����J�*����d�������[o�Ufj��Ua��^�%�F,K�
������2���o����(,Nv��W0 �D�3G�E-Z��k�Pd�-[VRRc6�3���7nL����1�F-���G�?><u��=��S�Z�2��,��_r���_|�e������4iR�!����b�8����
���STTGR ��UG��}���S�N3f�Hlg�����C�����K�8b��)�����2dH��=������=z�8u�T�����h�m������>����^������
��O��{��7���$�_�w�}��_�>�������������?~<��@*���o�U��\L:v��x��� ��3&��y��5jL�4)����H��322z����O��5���4�\@�I��5k��������;w��;�f,K�?�����U������9�h���o�9��j��-\�0��[�na�^�z�F����K�{��)�fR������v���[����C��M�S�N(�7�62+V��68���Y�f��MC��;8��{����}���HW��������+���a��P"�/_�9s�L������U����C�:t�=�'&L�//����%///�C�w�n��M�M�6=p�@�1cF��U�b��E���������6P!��+gY\���g_{��4k���Tii��B�h��atXwY�x���S�l�GX u��������8q�����L>|�u����<��C������O�>o��P��zR�H��@����e	P���C���������HIII�����(���4z�?���{���������,Y������({m�BhW��(������v[t���~Z���1:���g����_�v�P.���/������0;p����
����v^^��M������0t����i��(#��S��/��R��
���\�`@z��qc���:�?�g��m�G��3aQ�u���Sio��5.\�;��,K�2-�������'yj���U�T���sL��t�h������$yj���a|���1E���D�Q�F+W���;��k������W�H�@�����hp���
6����~���x��_P�t����'��[�n�Z�/^w4 �$ZU�V}��G��������m�;v�
��-�5j�����g�>~�x�����h4o�|���_}������i�@~~��}�����D���;w�\�q-�bh@��*������#G����D���qg�K�:t�������7��Wo���q����'��?p�N�8wHi�
�l�
endstream
endobj
8 0 obj
<</Type /XObject
/Subtype /Image
/Width 2048
/Height 987
/ColorSpace [/ICCBased 7 0 R]
/BitsPerComponent 8
/Filter /FlateDecode
/Length 47792>> stream
x���{�T��?����$[��uS�-�T��J����V��K��d��j������[n*�c`@^�KAToEA@^�Py; jAy?dg`�3������{z�������nQ���s����?�����z���m���K�-[���p%M�<9�f-Z����={6������`�hk�����������W����l�]d��U-�BYY��3��������g����G���s���Y~�a~���7��������8p`~~~��}kjjr���+�������[�����O>���_�Ir��^���7w�\�?@p���()�:uj�������������
����Ym+++_~����kA�?|������|bEEE��}��������t�����WX����?�8����3�����C#F���8p��-����h��To��vT������{�����������WX���+VDW��uk�[�;w�W�^Q�I�&�������������M�����w�����@�T^^��w�������\��+�����q��+�={�������~��u��=-���n���_��K�STTT4����3�/����h�6o�����Tm���Q�~��5�s�>}z���>�����

���?r���s������]����������F�5`����{8����
%�<��������.E%����3gN�����1b��y��)v��}��/���VK�.�Z������K��9r���/��B���w���4��g�:th(	s�^����?�!^@&*9u�����G���p��q3f���kW�#---]�~��)S�
�<��O3fL�G}��U;s���%K����n�W>+?:������,��?��Y
���CO��Z������q�^7�j���Q��7�{����2eJ��3���&�������J��=�,\�0��n��QG����'O����m��S�N�7��M�6�>��=;���[����We��{w�[�Z�*j5u������=^c��-Ko#[�l)..�n�����-��D������5z�!��I�2�Xf>e3���O///��#a\}��i���Y������,���cG���W_mV�����YmY��y���'�g�}��&uuu��
��_RR\��XII����0p���)gkjj�|~���g'N�g���k���~����W��Q�O<q�����>z�h�����s��I+W�����u���:'N�HiG�o��F�
z��}�O��x��W^y����O�?����MNaaa��s�L��Y}�/���^/X���W_�<yrr��>��Oa*���S��x�5�J�������0o��0��g���� t8}��6m�+��������`.\8j���T�������/=��
���g��9�.	1h��P����~���Q��������-�����
UUU�(�lQ������.��'V��[�=������8����k�SO>�dYYYJ��^{-:[PP�m����g��;vlTa�������g���F��:t��c�R�>|8�i��7e���������_�m"�{�#�Y�f�`Z>������	��0y�z����SO��j�rt3v4����K>����O?������tUWW'��5����8W���_��{�&W�x�b|�x�����x��x�S~���[�zu�6���,0\*���������������hY�?x���{�]{��Z���_�>��0i�q�H�S��;���`��@�7w��(�8qb\x���x��>� ���������l���eKJJ��u�������{����G����)F��=������W�8p`� �������W�nV�u���}���o���:G����Y�&�T<�~��
>��GZ9���O�����7�������K��'���m[�6����3�<U�={v��,��w��{x������������� �?~�x��kM����j�?B�*����tUUU����#�x�b�k~�"��&M�J,X��$^�~���v�
�-[U;vlry�O�6�����xO�>=�<9����o��.\h�S���M����%K�d�����Gu���\�<�h��t�����?|���;�����Z�=�g���f��X�"j��SO������H�����;�n� �����l0kM��aF%
�D�^oc-��%^~�������o��>���M&L�p�����K��rx�����4_�|yTm��A��q�;t��Lm�S�O?����������}���=��H���9��Z�HNAAA�G�C�)���Z3�����7�x#S��>�(�������qc�_\}V8b���p�����&�� �������J��2�_bT2s����q������?t���j�
N�>=��W�^
�uuu��@[�nm��q����,7�����N\���>���y��)���:u*n��'�4>���C���\V��������T-���3g������~���r��?��������	���O�4�)a��5��z���,Y5L_|���<��w��
�4��w�o~�_YY�.1h��FOh�V������K
��l�q������Q��B�?t4UUU�F��O�|��k^�p!��v��5O^�=9�Ow�������'��8C/2��7��o~����?���8�<xp#��I��<Z���Z9�����O�>�H'� ����J9���W_���������XRR��\���g���57������s��mV�LZ��a2����<^���<y�"�?t@�q�����4X��O?mABo��u�������bG��k����q��H������Q�s��5�a}R��|�u��-�?������?m�r��?��7��K�ol~�&�o��V�?o����h����qa�����.�����Q����7�a&�������0������G�=�|\(��(^(�iq�xQ�(�]�4�F�-���W"j������Q�Fv�mD��������oQ��f���0yQ�A���;v������l��9��H��F<}�t����?�������4>{M������&|Qy�8I��I�2Y��h�-�����/��{������0�X��i�8�JJJ�y���"�/**�Z-^����bq�_XX�H����?�_vh����������~]]��!C���#G���6�p��MQ����`��M����y��g�j�����9���A�>��OZ�*��/�������5����������n��}��)��9s��W���{��'�
o��Fs?+y������m��-����i����g��Z������bq�_PP������ $��r���r��?��7��s$y��;v��}���2�]�|yT��+XYY�������?�ic��e��[&W$�?y�dT�J\UU��_��63ej�?t(����"�h��s��E�a~����8B�5kVs?���"����2��y�����m�����E�pAAAUUU[%����Fw�]�fMT'�sryS������|��u��L��������cG\x���Lm��u[����z���%j�p��Lu�WjV�?}�������[��]��?7n\t*|����^�I��@�o��_�x���>�����z���l��}���3]9���kW�"Bq><y��Lm���F��`V�v���O�4��MR$���	m,�|v�����MZ+'?9��>}z���/�S�����H��<v����N���Vp��iQ�Fvp_M������w��9i�+����.�\�2�E���#)����A����;�&��uuu�=�\������w����F��^�xq�j.X� ��������LK���3���Cn}[�����z��eK��>�/,,l0%������iS������������+�jjj����o���o_�6~( ����
w��� �B���t�{X������7'��wm�:uj�4���������'�z��g����?t3f����^x!e����OGqbzL,[�,NP�/_^SS�|���b���q���w'�
�G��2dH����{����GK%k��?~0���Ml�"���u��M��r�zII��1c�:)g�2���M~r�:0b���u�������u>����Tyyy�'1u�������G�
W���W���)�/da�������]����0aB8%������}
�Y���T���3'?I�?c���#��}{�������3��4�o��))qMM�����q��!,X�f������������+���~�'N�!m����M��v���7�X�"�g##F�����R��Q���������7�~��{��g.\�i
��^z��7�\�~}����)**j���[7���� FAA��3��o��a�����
�+��??�yt�}d����V���y���+��E��3�	��G�������5y��%K���O�2%6��9s��yQ�F1H1v��f�E5(�����x��`|��|��?����R�+H��S/������q���[o5X�����g�������kjj-Z/�����`��5)��>���8Pm���S�����Q����z7]���3���*�F�da��|���
-���O��/^��~��L�={v�������7/HT|�yh�|j��QY`d����o)B�+**^y���m��A����F��R?�����"e	����0��M�)��@�VWW����������3��_=�Bqqqt�����.2dH���u��7N��������/�5�����
4v����g�������^z)��c����oP���=:*��o��9sF���O���7�X�pa����7'��`����.����0���W:t���������Ckkk���&N�8p����=������[�j���~����\�hQaaa�`�w���Y`���a����������g���{����}��QO��������;��� �6����EDv���`�?@�����$��
>^���@�#���G������?�?�h���.����1�_�B"�8z�hz����1c��~��7�p���_�w�7.�J��{���~���n��������Gyd��=Y�9{�����;���������������/���W���%�Ex������6��v��k��6\�{�����/���u���7m���@G�q��/~��7�|��U���������������w/--�JJJJ����P8s��������[n����-Z7�?~�s���VWWgg8@0o����>{�lx�)����K(��{wr��M�B��w��]�`Ax���8������W�X�f#R]�p!~�`����P��)
������/����?>�}���B�i���T;vl(��o�6�.�����u���?�az��������[�������[�lI��|��P~�}��]��F4�����K���?�iz����?�z������~�������S����]��]��F4����5+���3���~��pj����7��������)uv����t������~
���hi���5��G�6r���e����Gp����u���l��;�����k0����B�����^��;���m�^�}�����M�R�,Y�$�����)8q��qh�g�}�����k0�/..�7�|sJ�����������.++o��Pm���)��
�

���@&
�������P�}����e����{��'z�t�����Hi��[�P�~����6��L���3B��������D%�O���w�
_{��������[o���{����������������W�^��G�_}"�������������������p��_����>����K_
o��?�#�R[�l��������w���g����+���W��g��\�:�hm�}�������N�0��;�����n������k����W��w���>z��7v�����o��/��4�5���y�&�N���/���c��)�����s�����@�#���G�m�������sr�?�����:y�b��P[��/����k���;�Q^��/�����?��7V��3��x���������9�@8F.����9 ����j'�Q��������u1:�R��>��%7���n]e���ru�{�<'s���?���_�����xt������x���'��>�?�����O��}�����g��?���@G#��>��<]�~oM�<>8V��9rK��}����?���.����G�:������ ���G������?�?�h>)���<'��^z���:]��>T���������M��M����W����?�?�h�n����2KwT��/�t���D������_������o|#�#R�?������/|�����Z]]��W_��s��j�?�x�4��)S����������o���o��W@�>|�O��On������������D�����m��{�����������d���D�����a��[�lY"����~�\�v��P��C��_��
7��������p��\�h�����n�����;y�dr��/���$��������}����J������M1o��D"��_�:�|���=z�����O>�$.\�d�5�\�o���)/--�RQQq%�n>�k��yyy���ob��<�H����[S*o��;��x�����3�Ht����M������?hJ�}�AqqqK�m.�O�>�Db���Mo2u����G�m�+�5�v��H$�}���S��������|���������I��}��A�y�������N�:UVV���0aB"�����u����p���yyy�I���i����D��[ni�luu�<*t��9����~�w��W_}���S��U��6o��H$n���L����M�����7�xc�N�����?���EEE��$������j;�QV��	���������9�s��'�.�SX�1�7��d�?+����sx��.�s����L���9����Y&����t@��,��g�: �����?���?�.V��f��{��L�Qm]}um=js����j�[��8T\��I�`
������\������@���@�#���G������ioV��-������s=��N�?>������k����������:u����}��G��gO�z
4��'�L$��u{8��o�W[�v���^�����{�_������s���6m�a����7�I$���k�Nyy�-��r�UW-Z�(.�?~hx���VWW�}7�f����D"�r��F�,X� �����R~�����+V�e�f{����DQQQ#u{��Pg��i)�c��
����o���@�����]"��9s��>�����^{�_��_�����S��:��wu�l���v���������n��������|�[���O~�������Yx�������Q��~���d���)m���By��]��i�Q={�������s��s�����?L$?����o~�������S����+�w���)�28v�����i��S�����D"q�����K�.�����[��\sdP\\|��n���|'�Hl��!�������M�6��Y�dI(���G.:4�-���H$�m�^?��������S�6,����@����s�=�<��)�������SYYYx�t��D"�^�[�n�|���Y�.����7�tS"�=zt\X\\��{�P��g������������/����-�_WW��~�z��7���/&�.]���g?{�����/����~�����j[�l��������w���g����+���W��g��v�d����������ow������������#�����=���7�xc�N�n���_���G��I�������<Tg�<�	��k;��),��uT��;� ��#X��z���p��P���K�G5/�]��c���8���"'}�y�&��O;����?�{����/@�2l�����xfEE��?������~��c�������������3����t {N��z����g��su��k�&}��?��IJ�s2��9�c����1�?tD�������9{��%;r��C���C���?�����������@�$��>���|�9<���1���O��}9x�?tL�����g_���C���?�����������@�$��>���|�9<�{�eUu6x�2H�&*6D
l ���{��1�h����X�@�h,$ ���"Jl� �"
Q@�]f`�������? �i����Yw���{����;���������������'�0���������/�}w�����|����H�������������W��������O:�b���y7�-7��%����e�}�H/L�K$�}�������?�������u����+����3������x��d>l1{eZ~j.��O+��pR~���T���� �p�@���7vJ�u��F�����P�������(�1��I���o�2�?���7�
�(�-������c���I�����y���������c.:��(o�y[Rs��=��t8�Z��`�7�������{�G�!�lH$���;w �U������R���������N?P����
�^4w��!�Xb5w���s��:*�����G�G�'C��'�s��@E�.w��/nH�q��;���X�Tk����������z����	d��?����_?h��C9d�]v�V��~����_�%K���~��Y���E���H��u��O&�X�&��������?���/_��u�����v����O?��3v�}���i���|�MtMAAA����W�~�6����d�H����sn�?~��`�v���geeu��u���QI����������JV�^�p���	��b�?���������5m�4++���?/\��K/�����GO����u�QI�Sd�?���������}�}��{�����u��GFO�M��v��=��~�����s���3�����o���8p`�t��	�i�=����C=�V�Zu��������?�h��1�������?d�>� ''�y��k���J����U�5N8��/���#��Jn���d�H����sn�?~�� ������k��W�����S����?��S.���%K��
_z��*U�dee���{ID
�$���������@�����*U���^{}����\��Wgee]q��\�o�2�����L�1����|�����'��>dM�	~;z^������qi"9��.\X�n�o���={���������e��|���#�[N<��t.N��P��5����I"�3Z�������W'C����s���3�@��������w��1++����6mJ�����:��S�/6�;%���n�1��K:�X��'~����Z~~�	'���������5��~{�v�^{��"�]tQx����Z�1������������������k�����-Z�*9rdvvv��U���[�aP�l���)����-�9�[G�&C^1��W�����k��U��W���:���zn���k�l������.�.����;,<�\�������G@9���������M:�X���������v(up^^�O<q���6j��j��M�49��s�L��l�P�*���'7?�n^��_������G�gr����I���5�?���������B�l��������(�� �����c�2���}wc��6S�������������Q����W�f/�\1��$���m��u}��M$�@��������+���6$�����M��������Ys9�����I=>��)���2�?���3�T4���g�?~����������o���FT��g�6'�s Y+��g����X�6��hs����PAynE m3g�<��s��c��U�6n������={v�A%7a����������?���/�
?W�^��>H:4�$rss�7o^�R�^x!U8r��������/???����=ztVV��g�Y��k���|��q�D�F�>}����x��"�?�p(�����
(���?>++k��IE�_{��P~�I'%PtPVV���s��O�2%��o�>�����g�}�������"�3f���[�N���O�+`{���r���G�n�z��~����O�e�`{���?���6?��N�����������K���SNI$*�4����������/E�����P~��7'P/��rVV����Z��������n"Q������~�egg�5*U����>����� ����4iR�5����?��K.��������j�������
(��?���.h��Q��U�6mz���/X� ���������� �(*9������ >�G��R����^j::6r����W�T��'�H:��b����^{m��Mk��y��'N�>=��2���o��Yg�uV��������W�e��%Q�1b�a�V�F��������K:�����w��w�����b9����g>��2���o���}���m��B�r�i�}���IG��B/��SO
�
\u�U�W�N:��'������������Y�n]�.]^����@f��}�QG��?�I:��%t��29�YHr�:uB�-�c��M�4		�g�}v�e��Ck|���I����<~#F�����R�����������[��wI���������P�x��u�����/��(����1�r��q�-Z�i�f���I���<~�
��z�Q�<T/���Uh@�V�Z8�|��5k��+��9�,�{�����@l������0����:(�|�����dgg7m��ttl�<~�w\��
�U�f	��-X��Q�F-Z��2eJx�b�������z�o��e,9���q�*W�|�	'|���[�~`�}�
9���-c��;d��s��Y,���W�^!�>�`�Q���y�����=���V�Z��_sss�����]��_A�v��-c�?>4���|��w������g���_���I����v"7�xc�j��;K�8���k��m	 6�������rn	 N�?�|����>��E����������f�����?,����:�F���<�0��S�N�Qe69�����6mz�A���={v\���#��2���Y�m��^�n��M�	)�-\�04�g�}v���cY�vm"!e<9���_���g�*	
����
����``�j���-[�������
C��T���q����dr;�n��q�/���%�x�J2�o������7��1i����1c��p�	��z��F�������=���!�}���q�,����WW�\y�����{��G��/[�,///��2�����W^	���a������~�]vY~~��%K	,��_�>���s�-\���!�999��~�-��V�9�����*���
#�
��z�����o��U	F�y�<f�6m
C�0�,R>h�����c�&Uf���Cn/���"��;w�+V�H$��&��si���%�\~��9s��$?��S�gK�x��GC���������@�����/��u^��tt0l�0G�A�c����$?���[�n�Qx	`��������~���3a|��U����7o�<����[n���O*�#�����[�,X� �*]�v�Y�fx�Y�f�����0��f1;;�c����n�!�l��z48�]���	��1��?���s��
�{l(�c�=�e�`�����D��(r�e��E)-R������'�|2��2����Cn����"��_~y(/|�:eE�a'��Z�j������Z�����2���;zj	 ��sO������N�:�n�:���t�%�\~05Z�<fyyy999�������%�Gy�m��U�Tq�h�X�~}h+���C_%*	�z�����������[.����s��g��K����M�0!��A�����J��]M�u����;����[4S����.�P3I���+W��T����!�}�����������~���r�C����U�B�����G�+�x��������i��E�v�i��MeE�c��z����~����_x��Ph
�<D7�����V�����:�-9����[��Z���?\x[WK�-??��!����t�u��1unnn�45��A��e*9�_��m�9����h	 $<�G��``f��!��*U���whI�?��h�.u��{��W�F�h��dC�r�����;F�q�~����{o��-C����Fz��pA�d.\�`�����sHit��i����s���Y�7o���9���b�4��w^Hi�0�T��S��;�,������$���?&a�����r�-g�q����>���!�o��FRQe�����{�^x��!����B��s��mw	`��i'�|��5k��+�mw	��'����~������%�����{�1"��2��O?�<e���iH�����E�����y�Bbk���y������+[�j����E
�����?:��f��
6���c���#�<^����
2��y�Bg;��T����I�����&��~����0����E���!C��k��3��`�����rpY�;wn��������^��v��0 
�]�tI$��$��m��e��OOM�o��q�^����C�?�������x����ef�7o�'�|���S�?v�I'�����K����+�|����1��T��g_|�E�D�agWd	`��i��������lY�����-Z�G��e�"K�I�vG9��S�-���5+d��G������|���;����y����?����3g����h��P�;�<l��a����|�MY<���E^��������3�H$�L%��5I_���;!�_�u�W�z�)[���e��[���G�]��_�[s�o�>���%�|����G_��J�����&":��g?�Y����<f��>���CX�z�A��Pg����u�&������?T�q��	�{��6m�D785n���^��+��kW� ���(���{���B���v�a�}��])����7^w�u���/���O�h���4�[�`Ah��������^u�N��	&�9�Xo)�}%�[�n6l(�3�<0w��_�i�������o�������B�����&r�4��`�Q�F�&��m���j��Qx������~���!�C�-R���o�����Ot�I���f���������O���q��|����]�
5s�Z�~hD3v��J�*��s�1E��
k�&M��c��z ;�o3:O$������4{��P~������F�c6c���w�=���Q�����^|����W��E���7�/�g�y&t�srr�=���M�F_�}��w�{�>��s�GD?�GF����!o���9�S�N�����,Y������������%���Z���O�:��o�����j��e��[��X�J-h��+|>�����N��+?����;��Dtd����<�Hy��i�<~i6���	��k�����d��q�bI��9sf��p����	?�_A��
W�XQ�af9�_�������!�^xa���?�<�;w�\�f�F�m��fa��R��#��zz�]w�����;�H3D4����GnDsJ�
���{R��m��1:��w��K�c�r���M���U+������T�Zu�5���_�
9M������*�V�ZEg�o�����n
Y=����{�����d"������g��S�|]�v
%7�|�v��sHJh��`��u�����i�v�uW��%0g����>2M��7�_2�RW��C�t��k�J�W�^!uo����/���+��H��hJF�c�~����g9��,���F��>�������;<���O�8������9�_�����U+\y��WF;������5j����{w�c��<���w��w�m�p������_����|�����'�X�/S3j��T�wpG��!C�e���[�v�m�
:��C��mO��G�y�n�����";�]���p����^-�,\����~�����!)�vX��o��V�Z�����[�|y���:���[������������9$��^�v�I�-�=�M�����^r��D�n@il��9���30��4��I*�E���Y3v|��	B��Dt��������}��&��J�
�����o�gm��8��N�:���j<Af9�Y���Q�FE�t���A�p@���H����C����9rk[�~����_}	:�|��}uK���ni\�zu�#��{�G}��K������
�9�� �1�o��B����aC�
���+W��d��9�/Y��{o��9��c�_2a(
����u�Y���?|���E����k�v��Q��1"�����/R��a�n�!///t�|	T�!Y�;w�\���3��x��Y&�K)��
4h��yj�{��gtJ)��BZ�4�����I*����n]���3���"�������yYI�]�pa�����{�0�����]br��;-�'O>��S�6m��m����/��%E<���!����?��Y�f����������c3��v�i|�������tB�>a������fF������nU�V-2���:t��)�������S�}���>�������?�pa����W��s��w�}��w�q������B���	����;���p��I���������n�J�*��a*�r��1cF����t.^�zu�TM�������>����3g�o�^7��z��r��b����>��{wMRi|�����7o�����+���������L��L�y���i������6j�(�4�%J��K.9��s��������<f�w(B��*��_��|v��������b�Y���Y��l����C1�_b����j�����7o^����EHrNN�Yg���O�����Z���+�;wn�:uLD���������{D%k��=��Ca��
/���.��Z�j�i�^�����w��W9v����(���:��5j�;.6�'Z�6m���%�*�J�5�\�t ���O3
h��<~:-1{��w
?��%�u���f9(�P����{��;��.|�2�!�1?~���^���g���U�T�[���q������=z�_�����,]���i�y���>�h�it����:`���{��w(��o���5�Dti�y���'ON=��^8�����]��j''''�����J���d��:u����_bl��"T�\pA��T �h���K:�
�C�����g�%H"�1���O?9��NK��]X�re��m����d�T����6mZ��
G��ll�J�cv�m�}��G�K.\���]�v��B�l������O����{�N;�����la��_������R>�`RQE2d��wP~N>����?�0�@*��k�6j�h��ww[Kl&O������D����i@������L���m���X�^�&���;������<�Mx���i��9u���<~��ya7n�R��n��V��T����o�]�c��&�w�qG:G��	�O��-k������&KE1{����~���J�h��n�!�@*�h��W^y%�@*9��4~���y�tZ���������]�%�hCc���-c�=�z��b�+5��E���`�����G'Y�O�K�d9O;vl��E]T�Qe�	&��6�k��&�|���eR�+Y��iS�6m������[�Q�5@�\rI����B7�K�.i��5@O=�TyGEd���������&�E��Qc������K:��[�z�9� �����OZ&tZ~�tZ�P�v�v�e��������N�����7���Y���.��G}tH����z���B����[�7�y��8���9s6l�L
�W������C�G�U���3�R�J?�������
hAAA���:~�:u����=u�����]r�%�=Ji�V�XQ�~�&M��[�.��2X��#���;6�����m�WJs����N
�L�z9/+��-��i@��NK"tZ�����F��]��)�A���
6�X��Mi�x���+W�9sf��%���~����Be~�w���+w�}w�:u�V������j��
�h������������:�Z���^���+BG=�a���_�af�b5����c����o#G����Kxcx��4���y�:v���_������W�T��c��-������v�w��]���[o�!�L��=z�x��G��!�<����?��3B��|��X��|w�u�-�����E�f�����t�����</��b&�� �e����k��]���C=��S:�
h����O�%)g�uV��������&�K�����s�=4h2��[LD����3+W���s���"���~��
�UH�����A��C��4�G�<�������/�M�lI����m��y�����+�$���{�t&�.���p�����X��L�M���x������������B�o���-Z4k�l��0~���999�[�.�A6D�L�2��I�����g�y&\��O���H�Z������OC]��U�n�!$s���;�^Z����h@��NK�tZ>���Uk�������������L���������k��6����Y��n���.�+��"���^H�b9/����W^	_t�E��
[�vm�e���6�f��;~n��
��c�����w��c�����X�
���~{����������4iR<�)���7n��t���x����k7o���tJ�X��W_}�_I��&L����+�4��C�5��^�z�l�{��7��+�F
#G�����5k���,((8��#K��d�x����H�K ���<�H��m��Rp�5����5�e�X�
h��i)o:-?7�|s����?�������og��:t�P�J���g�s��#LD����K�����e����s���^qsN�����2�����)V
$b��
��u����/��G}4��������/��2XAA����}�)������:z��x���|�I�5����d���$d8�]��;�;�f��C=4����W0t��-Z�s��I��;�8�F���E��{���}�F�]������WHl���e�U�V�F@;�-�tZ4����R�tZ~:��]��{4j�(�4�X*���_���'�|r��T <�@�[��t ����{���nq�yl4����|��h��z�����;������wTl��ym���\�r���:��J�*�3���b��y�%�\����J����e������hZ�K�����U�[,X��[��4��;''�y��a������ ����G}���y���n��]��GqD�K^J:-1�i��N�OJ�����x��IR�\x��!����j��T7n5L���/^�t,���o���U�T9��#

�������O��U�:t��Tsrrf���t8�l��e{��g����O��|���|p�'�Q\!�S�L	?�����>������)�����
�>�����%�
2$��&���a�]w�}��9�;v������e����/PJ:-��i��NK�B���m�P����eb���5j�8����=1x���C�r���&H"�����_���O?�t �v
���;��c�]�w�R��/��R���k�v���h�<,Y��E�u��-����t��{��h	����N:���|��]v��]�vE�o3fL�|Ke.Zp��/~�:�@�tZ���3�����'�����?O:������<���;�9/�-��	'����>�(�@*9/+i�0�r�����7i�d����
(�,]���4��������G�S2G}t������i7����;�!�?:�7n�]��D�h��s���������*�����!�W^y��/=��inD���[�z�~t	 7^{��D#����d���+\:-1�i��N�O��g���[o%�N,��=z�8����Y�����5k����.[�,������\�b9��c����21a������y,����P��~���)P��������{����U���g��>�,z�h���r�)!�����})��W[�h���_�[����t������.��y��	��F���U������:���P��N��9�&��|�p�m��[��@��-����u���v����*�%K��:�F�����]w���+��tZ��NK�tZ~"��:��>��M�6%������j��i������3������Cl�-����.95jT��Car^z9�`:K���x`���
��x��4O���ODnn��'�*�:�}���*@��]`4]�B���rj���N�:��������:*��2�F���t4w����q���Fs���w^�

�R��%��>�{��W��C=���'N�_�~��5�����?��CK���O<�D�A�����Z��U�v����SO�^�zHi�&M�N�]��R�tZ��������[n��5��W��
�'������


�<����+��93��2R�o��U����	���G�
��X�xq���C%�����a�7o^������\#�e�7��M�K���j������!�L����[�������n��?�P�)���W�V�n��������������B���*�C=4���N�/�j��=x����Y�.���=�����{����j��Q�������~�e�]������'�����_j������f�����@�5jTHlH��/�\��Y�f��S'���zI$��j���
K�^|��T�v������o�����#�7��p��7N��h���]��l7l�0���NK��i��NK��L��$���X�f������A�����b-L�4);;�s������B5>��j�
-cNNN��v�����3h��x��l��wOg�M9/�Z�O���w��!�Lu��w�v���Z�j������vp�F��o���nJ�l�����E(�P�+��t�-���w�$�w��Q�������x������>�u�]C�C�YxS�0����<�`3��o�Y�j�����3<g����MSJ����}?��#o���?�1��z��Q���-��`��R
��������?�����O����1c
_����5K"��*�.]�dR����.Pz����w[�t�!�R�F�	&�R��L�Z�j���W]uU��S�����+��������#Ce��Y?z���>��(��*�������4iR<�e��~����Mx��g�*%����7���{�zf�E^���<x`:7��yYI	��O?
#�n���Xfm�����������;����OgkS
($k��!�op������N����h����N �L1o�����g����<���?�<�����?�Y���^C�0�n��m(�BZ���a|q����Q���S;t����{Di�b4]>B&CJO�o;�_����;��2x����E�������P��w�yY[�_�������C�|��J�*�q�IG�s������o���!�999!��]w]�K����O�\�r*��N��t�;G:-���o���n�;-�z���w:-�D�%~���zH���C[�h����W��o_G-�XH��1c�����QD?�j��o�9�3�Yg�����&z��n��E��6����/�0z��r3���t�y�����_>�����E�K)Ta���O������0h����g�^�9sfQ��]{��%Q�[o�U�Z��n�6���A
q*|/n$T�Y�s������/>���}�L,Z��Y�f
6|��'�8n���tP��������s���b�l�2�?+W�����S�.GJ���>�^����~=
���N;m��tn���m+��'�|�X�t�����{w��%�(3�]w��}���N�2�������^m�t�y������M7��_�n	������������������������e�]�D�;�m��N�:�|FU����|���{����e"���V�z�a�����~��C=T�~�����h����������V��^�`A��d������SN	�]�!C����?��'iL�V�Xq�-����������\y���/P��/o��m�v�X��'�p2��/�>�{�����o���f����@�<������^�����{��5y���v�t��x<�����d�qt<��/���������m����������=z��Y�f�%������V���u���y�����oh�:w����R���
C�v��.��q����u�f�Q\K�,i��M4�]��L����R�J�:u�����n�s�!�4m�4��3�G}�[dz��k�	���9�������H�0��LKh.7m���g�"+��|�K�76�(��vZBnC�o����n�3v����_���������o�����Z�<�(�����#�i)[:-II�|�y�%K����iy���R%�������n	�������/�PAA�%���Z�*�WNNN��"�Ch:w�e����k�F%�}��/�KK�'d���s����3-�O�c�=�$�:��0^�Pt�y���{��CytW���>���Px���&r�X�hQ�d��}S%?�e1e"�&����N��u�9���F�&EK �6��<xp�j���-*���C���g�m'�7m�2��G'rF���w�s�c��J/777���<|��g����+r�v���?�i�����gW�R�R�J���m:l����7�|3��3��#B&G��*�<yrhLO�S�tZE�������y�B�O9��"�s��i���%������b����(������K�Y~����S�)����-��o��&�w�x��Y��'%4�����c����z�������"o	��3���_�i�0aB�������N���O=�Tb�e����U�
=���m��f��iJ������|��G�v�_�xq�m��U������~��$��4�w\��S�����=�X��%c���y��'�}��|�����H��%�C��h�������`����n����0`@��;��=�v�?T��W)%����[�n��q�b����R��%���'[{���Cz/���m_�:ujt��I'����2�b��h�Z�v���m�J��O>	5���S���%���F��Q��:����m�|
�3�<3Zu~"�e����go�CK�N��i�Dl���k�������\��e(�����y��lG_q����GI.��1c����:l��;��5k��e���(��{�a��.V�z�F'j�B#U���h�W�^���1��.:|���D���=���|��M����g�q��;{S!�!�o�����������3�<�h���_�
I���J?��Cn��i��i��@�j�>���$"�?�i	U��_
�T�2`���]	�_~���Gr>y��D������B��O{����
\iJ� 
(V���F�^�+���5vb�^���a��KLTT���Q4��b������{^���w���������G>������g��3s���w���������B��������y�jBC��kWqS%����[;;;�F���������E��c���K���4�wtt,Q����d]"�7on�_�7o�C(��>}��.d�^�~�?~:J)"e������P�^=���RJ;	�k�U�\�r��/W�b�����3����g0f��-c�
IJJ
������v�����SJ W��R(�}6m�D�<y��4L��������h�5k�C���;w�6))T����}h��fv�HCZ�b�e���.�s��:�c�{h(��y��gO�"&��j�R[���� i������3��E�e��O�;� �=zDM�U�����OLL����Ce��a@��{3f��W���]Ka��<��\�p���@����jkX���������aw
={�Lz3?��D(�cM<}���^kkkooo�-�������OA���~��7>�o���z�~���F��,��������K���Q�2�:�&�?|Jom������'W�R����s��H�4AKy����E����9ZXX(����	��F���n�1��C�J�y���N]//�2e�(=[��&��i�
:��[P���O�V�ruu-^�x�&M�l���94��������(��l�cK����<xp��yU��������Wi<w�\:{�L�2�|i{�%�\�I]d���G����.�t%����O5i�!��B#��j��m�����wS�!i�9r�N��c���>T�^��w�E	 �P��g�TW�	��/���o1�Dddd��u�i�I�&�r��@j�:��-z���L�5����G��t���[����W�rJ9�5wrr��,���i�d��_��sM������+W��tJdh��}�v��t�.I����K�5��=���\��������4�
�b��QbK�;J��t9�z��_���F�j��3�G��m�x���"E�P#M��W%�����|����o����Y�)�E�i�-?~���?��|G��C%w���u������y#��g����q�t�o=��SPL-tV��P��Z�R�>JZ��%�e2i����S��������{��,X�Nx�"2I�W����h��\Xd���1.(m2Y����u�����W�X�S�Nb�
:���8v�X�[]�[�R��|�5������7���.Rf(b~z%���c�hT���E���~S�[���X���*��U�,�����9�����E��V��\�t�r���Y����K����V�P!��%��Km	t�����|�
gY�wz��qHu6}��-l��UtY�a����EKhh(M���_�F
^��I�&�zQ&,�k������}}}��)cjj�-i����������wy��z�����1�����~@��>�%�}����M}����1��MA��M�64������
(n�l�����y�)S�l�����t�7k�Lz�����Y�Tw�?~<���t���EHZrZ�����h�S���d����N�jmmM�k�U�UHZdG�	��tY-�7�/_�,���sG�]4 �������s���J����];�b���k���s�k���w��'x�,W��3f���r�^�D	U��������GC*�[Q��O����w��&>L�n�zr��g�:���+~��H�
�>}��|�*U����&bcc�|���_BB�*'N4J��KZUA	@v4�.U�E�E�?~�7������[����d��nnn�tU�\�_���4M.��-[�V-�}t��5ggg��k��-|������k���*=s�������N�\&f��{�_�h��g5A!�F�������4Y����%
>���|�444T������+����m�Sw��
�i���9��zQ����?�����=/�fRbb��7��<�.�g������)�	5M7p�kI�d5i���sss��4o�\i9 �@xx�R��P]^���8e��F����0aB�<y�5h����d������4����+V�������vvvF3g����z�M�6��/?R�.S�Lz%�:��M=F�B��-�i?��z��b���-�]��]�p���F�=z�(5m���������?P�I{��)
,�+��dOXX���I%����T3�i�k���ZYYI_�RE�i~��(�=S c|S�g�>�HHzqTm�E���c�(H�?���w��)g�] 9�������4V��Ppp�Q��V,�G����G��K�Fo�1����p��6��^��n��}��]�A�y4�4�J�V�3E�%q�T�&�bE&�$-:���%::��L``����e��^�����\�j�hA��tJ��#?w�\ooono������K�.���4b]����_��ONN����FJ]Dcll��%K����o�'N��SA�KHXX��b�%�^	�s�����D���+���_4z�7��.\�.^�xDD���?qqqtt���u��T�^�D����y���e�J'>���4i����?~LL�=54�!!!4��E�����������>��E��' m�����������wo����w=h� J�/�C��l���r����kW�M� �.}��U^�<��i���%K��N�?}��~�����7i����WlM�y��6m�������1����V]�Rm�Y�v�*
&te�R	4��E������;xu��P$-���EO^7o��i�x��)~?N���M�6�$S����t��������v����-����+W�������1c�����Eg���s�B�
���NNN>�v777N�U�����b�
9�kP���C#9u�T�FY����^�4
�� �y(���'wbvL��i�������������Avvv�����K[P�WLL
����h��wo��%�/Z�1B�qSlY�z���ziJ�C��cHZt%�<~�����(m�*i��I�8��z�����������m7
�
cc����Tu7�)�����������@P|.[����y�N�x�%����+}
!]���1��������G<?�W����t�+�V�����������4�S�L�Uo�o���r�:hP��_O�]�J�V�Z���:tP}��P�������*�����'[ZZ��t��{wdd��Q�������M�"6���i��Q�^����hgkk�P(V�^�y�fWWW~*`��q��_

-R�%	x�X��i\�\��?�~��V� /$-���E7P������JG�F[�M.^�x�����g�5�u����0���o��Q���\jQv �~��G�\��y�"���T]I�C���36���������mf�[����p���*U*000"""$$�f��&&&�J+�<y��������:����d��!)^�x�~�8?9y�$M�9W����������������U�PA��E�Y�f�Hk)lRc��-������������B�z��K�j(�%�����kP�O�w��A�P�����Q��#���)�������^v�=���������hr'Sg

�Y i������h�����3�o��:�d��e�]�I��=�z5��'N�����v���He��s�F<��%��PX���;v�hKz%<��!���r�J�z�TK>�'���;vL������v��Y��?����!dL5�P`�����4::Z4��Em	@�.�������������={���7nTzv�����w��Y:��AIJJ


�7o����x�"��B���0�����=z�1������X�L�B���:XXX�aQ
=~�x��U[�9�g��>J�D��4@Y*�/E�n$-:��EF�/ i�.�#��vn��������	��]C��_�|��3gDK��]����������������-��{��E�r���_/Zh��mkjjJ���3gJ��q	�%66Vm	�~5���c��0`�l>��W�^�iO9!���r��./*�����}||����Z�hQ��U��}+ZBCC���7n\�ti��p2.�.Qx�������j�JlF����T�BY�+����� S���2e��������� �v��M�O;;���j�����3f��o��r��y�����?p;����,� {�����e��v��5��nnn�����|j�%����D�[�4�:t������&����Q��+VLl����<v�X#,��E{��166����q����+��Qi�*���.�~~~-[�����8��+@6��Pijs��akkk��x�y��-���!C�V7n��)R�J���/@����Y�&Mv���DcLL�x�e���J�%��ADDD���)��V�]��O�P�B��{.���w�z���0`�M�z���<���/>t���a�n��)�f���q	`����vO�M�:��.�-�	P��t���B9���/E!www�� Kx�������/����\1�t#����=�����C�������EC+V����-[J�)b�W�\��v���o��#�YBi6�JQ�[�n4�]�t1bE#��!���o��)�:�����O�R�J�)������x�#M���'>��O���}i	���k:���y��9�!|&+�S�N�C�@TT����k[e
)��&<<������i��	���7��m�v�������k��m������������O��w�����Dl���,�����gJ�DZ�i_ 
]w(��������G����/ZZZ�/_��_++�����eC0p�@J.\���w0����k�f~���J�z����X�z5_�y�;��a(U���oO�
��x���W�`=<<2x
%�l{������rz%j�>�@�"$-9*KIKz%$-Z�l��~��q\\��/�����[�z�LLL���e���R�aaa��<xP�tii	�.�~~~���{����'9��
%-�7o��P�h���t! QX�x��?���X�_�_�.S�������;)�V�=Y��nnnNQH���/��M�6m�U��������|��YJ%����w�����=�(������z%  @������[W,D�Q�F4�e�����?��9������������mJ'k'O��,K:����B�
���{���L�5III���o��]z_q���kW]u������d����o����{7V[MPE�;777q#��y��[D	 ::�������V�Z7n������/_���8�p�lff��h2�N�J�*����3'�oR�Xm	4��E�����L&-aaa"bc9����B�����RB?J_���Ql������nQ8u���u�����Gy�pi	@�����I������W�����q���pSTC����+W��?~�(�H���M�4��R�\9�X=d�(t�����"E�(m��S$i	�Px�Qu[����[���%��#� ��9�\J�(A�R�x��KK�-Z����g��A'�G������[�Go��Q�xqq/  te	��4��x6����BQ,n���]����
����dOOOSSS___���x}^�xZ�:�HM���Qv(O>~��n{�����x��J�������U+�%�C��{HZrTf����0�B�
���qJ�E����?,����'O�LcN�\�Z5Q|�������+x@Vq�bee5i��q��)M�Y�6J����Y*�&���c���upp0���+��e��	���=�n�J�)�7� �D	�w��...�e�%�*��V���f��Y*�,�)B�L�|��m�_4n��&#�?�}�(=[�`�����Y�����ILL�,�c#M���r4����<P�'s���aW��!�2�M��:JI���K�[�����[��0�q���
�b����i����������� �N�<)><q��a4h���cbb
(@�
��
���K|��f����\033���Z��%G!i�E�I����7��}���|so�k��|�����+lmm�7B����\[��Z�%:��4i�z%mA	@^����t{�[�n�h��'A��������*Q��^�R�(hJ�k��a#F��\�f��������>�a����(m{��>�XTT���5�������4h���/j���Uw��+���)dOz���n�3:�q�_+�<yB'|XX}��q#
x@@��������-c�����������	�|�%����y��={���OOO:�����Jjo�3:�i���.4$-9
I�\�KZ�����va�l:t(
~�:uF�Mg>}�a_�|9�IDa�Z������A���C��@��-u�7C���3r��Q0W(���#G�����_����"����S�"w7
�(��[W��^�BCCu�=�������2�_			������0�/�?~�.U����f�z���<��k������������W�D	��f�4�����#Gg
Grrrdd�7�|�4�>x� e_jo��vql���P�BM�6�j�����G�����[���9�G[�T)�-��M�4���k9rD��P&L
T�4D������JIII���W{��IKNC�"���//��n���y��wx����~K-�(o2�|�r{h�2�4����+W��@Y*�-[�j����y�	��AAA����������R�X�����i�	���Z����M��A���]�P����OU����_��
u�A���c~��B�
���o��icc���'r_�zU�|y��+�&x��������py�g����)�x{{�|M�~��	�)S�����$;;;,>�9~^�He������-K�.�eE���+����������?�l��=
����B���%J�����!i�=$-��A�����[����?~�����o�
&����P��&��������_���3y����;wvww�T����3.�4��@bb�44�9}���c���VQ���m����L3&33�=z��������'R`�����={x��- �hE�K,�G��x��F�E�P��;�s�N�1..�t��#G�����c��!NNNu��Q����������nbb��}��}�(P�2����a}7{�l�a�����.�4�t&��SZ4c�X����O�����T�"�����
�kj����+:t��:�KII7n�:��8p �wI�1�u�6��Q�.V�����ir������Yu! �$-�@��cHZt,!!a����\
,o��}�v
�C��Y
��V�Z�`NI`pp�8�q	�%�%����P�fn��3^a��N���������

�1����M�7��Z���X������-Z�t��B�
��d���Ey�����l����/��x�Qs4�x�������G�inn��-
�/^�������k��v��I�H��w�0��	!!!4�m��	������n�Di'���5;|����sMLLh�-o�
����S����C��VFi;N�<�^h�s��[x�Va��=lB�"$-���E���n��)������q�
.L�k�����{���Wp�������w��"V�l���
#e�@����Z1D	@72(P����d^PP������#�v�Po��Y�k�F�%����*T�Ri9 �L�F*U������;w�
�J��q	���� ]�y;�����x[�o���g�_�|�U#�����C�d���Io6������7�<y"S���y�h�w����N'9?�����yzz�o��_�$���W*���|��5k��h�J����������k�@6$%%�����E�������F	@����I� i��!C�P`��e�U�J�@���El���'���8w������J����������;�f��g4A�.�w��q����j	�Q=����c�d���h������R~�%�l;y�d��_I��c�����W�VM������4��o_��}���[��rt�@��e���^^^k���nt�66>{�L�n��s�����Z�e������3����������_��p�B����/�M�F��
6$%%��Mq��}:������?/mW��Q�%]}4���L�������������Y�f��o�
I�.!i��]����!CDKTTT�r�8�KK�v����}7�47}�t�;w��=����[�n�������������wzo��a�n%�aF�y��%�1��F {h��P(�5�e��q`����9u�TOOO���hy�j(h�3�=��H�^�[���g�I���y�%���0�-)))�>4:���������_��NNN�]�v6
z��?M�h��_�.���X�|y�x8@�UuK ���g��-����3v�X~�������7���!��g���;�85j��?(U-��hTiHEl7n�4��	�������Z�l��}{{k`�7oNc;}�t�C�_��9�����^�}3$HZtI�������5kh0�:�4��*U�>,,�B�
\�q�����������������4hP�jU��JnV=|���eI������������"c��i�;k�
.\�hQ�#�������q�������Rc�m���6l�P���;w����I(�<v@���S��gP�K���
�LEN(- K�=�)SZk$���1f�����Skk�e������Wp����!�#b#�S�.IZ���N���Q#���7l���kWJ����+K���9s���J�*��T��]��r�v�(����s��V[`y-


566��=x���Q���$�V�Zx�^HZtI�������m�h�iHS�;������w���Oo
�-Z��������@�y�������������g�����}�l��t����5�����9�2���K#i�
������i�%R�8n�8>��cG�-��7/V�����e��^JLL?~<W�������v����;H��o{A6dP7�����s���@:t(T����{/\���.�Oi��T�l�O�>����P~kii�	@jZf�{)��)���?�/������O�:k ����/QRb����l��I�Igx�.]t�ACs���^�z]�vm�������������n����{��I����8p����O��B�R�T)[[��k���YA����������:�4�a�
I��!i�=$-r��������'L��P(��W�/_�n����011��}�|��cG����������Z9m����{w����>i�$�B�$�
WR[HIII��?C%W[V�X��+P~By������w��]�bE���/�"�[����(UF��L4h��6l�Q-R�������C������Fm	���Kjo�3�����?�������]�h��g4t��)�������������S;���K!Kh<����K�.�z�j:�S�J�VVV�X�Z��7o�����V,\��a���9���/(P@�F��2��\��M)��YCRRR��]irM�pz#����g�P���n����t���
�B�`�~�����5k�,Y�$��C��cHZ��)�P<�6��_?44������� �z���'4k�L��s��	�nR#W�O�>�����A���I��4��E��#G�w�roc�o���www�9'O��>RY�v�Z,NNN>�F��]�%"""�����
���Ay�����c�J��+VL���=��w������������A��7���Z���w��%�����iBG&����?���O��q����Gk(((��D4�4��������/��[�\�B&��EyqQ���U+���]��L^�h������W�^����M�7�i����cbbr�����������������#G�5����O����Rl�*���15����Q��2��5� �7o���]���1$-rA��KHZto��MU�T�X���e��#l����h�����/_hh��4(;v��Kd���y! F��|yxx<z�(5m���={R_^!{�:~�x�-�rB�TP]X4t���o���T�R�G����~�H����3���t�GC���c>�+T� �.'&&�z���ncc�y�f�9�����.W�N~M�={�7��7��J���		Q�����B%f�9����4�#F�����?/R��x����W���Q�������I)a�,�s����e_b/_�L��p��m�����t��~�4�2d�M�$�q��4�
P}�%�U�vm�l���G����)������S�����s___Y{���������������G8,,���g^���,Y������ i���A��{s��5�h���x
��1�����:�������!HJJ*_�<�������%�t�K�U��I�y��2vX���6o��b���bbb||�X�3���AC����#svv�>y���A�������:o�<�:k8��HyH�:u������bcc��k���+�6Rty}�����wG�������_f�v�?��v� ��{���_�~J�0��9���������t%*P����T�V�Q�F����t��E���!���+�����mh��-���e4��~�����5�EQT��G	 �;v��K�.���G�,��C������u�*����c�5q��
:��L�"Z��y�-R���{���x:W+���I�� i����o{zz>x� ((����n��Y3j������rss��������0<�����y�����c��)Y����m��M���e���w�V�\)m�u���B@�-t2;::V�V�����������6�X����S�=��)��)S&&&F�n����g������%���}�)�P���<q�D<��	m�h:99Ik���O�0%����}�x6�p�B�Cb6M�;�,���������#""hxi�,m�^��o���+x�����'}�Ru���r���P�ti�] E	����t�`P��I�����{���}���h9p��FR����i
���/
�XB������E7h�,]��!i�iHZtl����k���?{��7
%���hNf�m���g��_�^	��?W����{��q����9��3�m��J������[\\\��vePm9}�4�����U�9%���O?������+��x��i�;O/_�l����J���;w�C��������H�_\�tI�����d�BQ�|y�Qu`oo��7���������?���o���
0�B�8T�V-j��������#@C�^/��z����WM�4Q���IK�:�</�Jy����4!A�������������������4�J%�*G�]�~=���������B�������!�}�����u����+�O�V=�o�>���U+�$�tn��u�v������D�E�M�6��Q]��6��{���lDm	���g2u������RTW=D��5j�/p|�2�M�&^�~���L�h�MsrK�����#�O�<�������c�R���_�~�R��R����Y���;j����>|(c
[�%��j�B�
Ql��"E�D:?��m[~Xt������-AAA4�
4��V���w��q����IK9}�������y���y�mg�j�����E7�����I's���[�j�tT����o���t��z��I�0%�N�:EEEy{{+V,..N�>���,^u��Z�*?����Yr��)IR
�J��%�%������2�-[����P�|�[�n8p��|��;lHh�ieeE�{��q������������4t�;��M�OOO[[[��$%%���q$l��%��������]�@�4�V�xd��M������s{��A�$L�rJ9����4����a����2��_��Z=z��t���W�^�_�V;��l�`�;r�="�5����C���O��{���������S��5�e����>���b�$-9
I�,\��9��4���������r���[S��XMQ��D�����������ce���y��]�B�hT'M��z�W�^������:4A�B�4���|�nZ��v�:u����+W�P0�������7����S�����y����)R$22R���t�����k�c�u�lZ��|�BW����K)���r�{�NM�����yB�n~�������������-[x�g�/��f$Y��]�z��}���2u6A	@�|||*V�(]p;))�o��4������O�_���xp��Fgo~��c�1c�<z��O�8�P(hx��u�=z��T|r��:w���O�<�6���om��!I�V!i���o��080!!���7�:u�����U�4\���� ��YC��z�j�r��5>��J>l��������C�W�&n��M�G�!b���8�+=�@�d��%������A�Y�&��4��1�3g�q�oE	�2sY�i0(�S��o2]OUK4��������PM�H������/b%
 
4�1wvvV��b���
����<��L/]j���Ot��gO�|�h~�t���������[��F���{x�>�N�<����K[:$�Q��O���S��`��
*�m�6^Y��m�b�J�.���;y�rQ�N!�=J�����������������r����H�.��1��-^�XZX��E���E`��??�>�i�&�bPc�n�?~����?/�j�*y�r$-Z����o������*UR=Jq�(m���nA��UHZ����=���$����,XPm	I���T�B�+�@|��e)%J��G�J�iU09�i ���&-�F���k���������i��H�6����B����h����X�F4�Ts��x"ZC?���R��r�J���y
�_�����c�p��]��B��RGNZ����_�|����m��}e�2dJPP�������C�;���~�.I\*��("""����������W�Xq�������)�xk;..�����w�~q��e����.���h�\�vm>���V��?��S�B<��mC�������(�1����I�<��[7���Ei��G)����cK�b���h�R
���M�8�]X��v��<��mHZ�G����Y�lY�f����@s
���p����Z�*].>|��_�����W�R����S�L�EA������������{�����p���YM`` �CK��������>/X�@���1s��{yy�)SFiR���?�W��������w����z�������9s�-�����;w���\��l�1c��L�e������?�q��aC�6��4n�X�P8::�m���-[����M���������sG�}3���M��_�����Un=p�@��mK�(Q�F�y��aAW�G����[�.�Xjk�����C=z��}����w�-*J4�&&&����4�P*DEE�t��9M;w�|�����}��6���M�������}���m��M�PPf^�@��P�Qm���Y�&]+�3��6667o��C��=/J�7����e��~�0^�^���K���u+G��W�r�������x���������]�V�H>�U7�E	 ����QH_�f
}>{�,�(C��C?~�����q���{!��9b��{�|���w�����$%%Q<�DQ2�'s ���c�f���z�O�>t��0�w�0����3g�w��n�:�Q���Jle������s��<�C�;w��o@�h)>�g�.�)-:�G�����] hf���$-�;��7N�J9���G\p��g�p``�8D��c���'O����_~������c4��'��yS�jU�9���P��r�
v��
�7Rr���J9���[�i�K�J���+'�4�A�-[������d���+���
�E�[i���.��{����;!M�K�(!� �l����������}���b6
�J�\\\�L�W���W��1����S���U��$Q��?��'��hBGs���{��7���Evl.J������`��ys��m������u��4��s����A�w�0��7��W���z����w�/�C��U:�%�v��a�_M���<xp��]t���_�x�F���K�X�ti�O2@V�I�P(�������|��L����@�^�x������������������4/�Ia6
�J����������B����E5$�r��>y�D�(�A��0�|~:�&���wtt�4��Ev����d��a���c��}���Nf�-8NZ����G�6M�4�r���h�"�������O����N�0A�>��K���+6����'x�%���
&.�4����M�������e����������7�)�������w�v�+"Jt�rvv������>}Z�~�M��-�����i�t�7��#J�dA�B�LLLF��)�V����������K�����!�a%^�����>�h�B��;�6$-�������;�j�����S�dI�lll�h�">�;H��}������#F��bSl���h<�/���O\\0`�|4|� �������(�t��I�P� W�P���~��=���B�������[h�����6�Z���]�t��e&N�HG�>+�kq	�b���S)1KII��GzO����zJh6=|�p��#J���������4���Tn��%x��(XYY���@��UA	@�x�y��`bb��i���8o�����Ok��a$�v�q�6���Nl�5�O�:E�V�X!W�r	�r���k�������W��/�O&l��M��K���q�P(j��o��i����>(����V�\)w_����W[�nmfffnn��}���s{��iC%J*T��������������D�4��J�����vL� w%KK�s����=�����������=[�F4��r�v�JM{
��o�urr�\�2�C�������imm]�J��{�r��G�
.��~��A|9>>�Z�jt�2F���� o�"
,���C�����7��W�A�;!!�ZBBB4h`oo��W/���Ef[[���8s��I����g����o�N����=�����U����^:t��Y���kS���aC��3��!w%��+��
�>}rww�;�4��8 �b*�J�C�������s���~�,V���#(b�]�d	��666������x��E�6m��a=����A�&��)S�Pxx8�(�	���		�Y����Ihh�L�����[��|���O�:;;�;�P�B�^�R:���k^dl���t�,Z�H��=s�Li`)Q�����S�v<x0/�F.^�x�����g������d���v(d�������_�jU�R��y��v��4�N(hb��Q4t��/���J�;��	$-z{Dj(%%E�����"]�Jh��-]�p���g���G�W�lYQpww/X���C�(��^������0q�D>���CWWW�M���;vL�������GX�MC/^�����;v���������:�����������>}��|����[�7�i��%�l�2sssil����?��#���%��!c�~�-]�#""2���M_�rE7��@�&M���>����
������&J�������@�lll����HZ ��(����/�m�:��o����n���(�|��)��'NXXXHK�	3f��V�Z#O�4s��u~��d������~{�������PZo��a��55�O�>Q�V*DEE��������	�e�:�^��cM�>$��]����CzG�9BI��t����0�6�������y����'���v���j�����w����Kl��
�*���}�2��rQ(455U}������X�,}3����Z�lY�/��+�Mj���m���$����w�C<��o@�h���gO�L/11Q��]t�;���������WBy�B�����h��J��.����(�<x�����E�n��)4�l�@�z�J����UD	 ������C��
�v,A�	Q�X�b���U��*Q���������|��5l�P��.W�Pa��mJGQ��6z�h^��&��7�����9s����p\\��������{
z��	��y��s�z{{��>XZZR���O�;v6m���������K���{�����t���v��}��1I�>�`ll<j��k����ys���2s�L�{��D	��9sF�(��%��e�������'{��)V�X���U7���o4k�L�(J��(��2���3M�>|H�o���m��M���O���\\\t�S�'-Z����Mi$�5k�����:�X�f
��k��{
zc��(������h����!i�\H����}�������w�^��e D	��G��3���@G���u�=��#J����J�*V���!C^�~-w��(P>�zT��-[�����:t(O��=+8�['O�4)99Y�s�=����cSSS
��7������Rc�����'P��vsss������?W�X�bH�����D;���D	������srwG�EGG�>}������v���

U����%OOO�5� K>~�x1��{Hi;`%4W��{�n��%����|���6m��P(����������=���)Q���w�d�3|�|||��Kl���6��U�5ZXX��7������]����,]�T������fffXx! qI�B�`ii�@�%$$�0���pl�Y�&������%������mk�������R�P��w�r{�%��@����\�R�^=�@HHH��E�$��/�kd�����3�o���JK4�����4��w���'co@/<y����aaa|_B���r!�4����f������&Mrqq��g�8��Z��t��L�UO�U������I�Q�FI��r���U[�����5kz������n�:��@f���C�@.]�4n��N�:�;���kru�Qz�%��@.��&���OC�z�j��S�(@��@��9s�������?s�jlA	t ...$$���er�+d��7>���Kicz%��P����� J�=w�_��-Z��?M�Z�h���|%�R�P(BCC���>���455�����k���-���k�ZZZ�5�o��-IKQQQ��o����Y���~x�����Jeg��)}�E�V�\I?~����o��	�|���A�"-�#vs�����|��
]s�.]J����'111�����qqq�;w~��EjZ	�w����r!�����W�^���������=D�z������������k�[����Z�jyyyU�T�>,X��?�_%GG�������w��E���/22������b����M����@�n�(��w���e�3|��5i%�*��w�~~~2v�Z����w�>}����G�����/_>�*qqq����C!e��9:�'��/^\�p�?�{��?�j�*���>L��6m��@.�}�v��:������s�^����4i����+W�����u�v4��\�r��_��-��Z[[��v��mnn�����_���~�d�r��M''',��w�����z��i�<yz������n��M�6���wo
���S�'���t���n{
��&;�����Gi�s��j��U_vNII��-ZT��@�@�g�����er�C���y��4��C[�n]�j�#���_��b����E���������E�p������:uJ�����R����[�X(
��Z����n��1=
.ljj��>�����3f(}���K���������x���e33�f�����?����X�J�4��6(�����]��L��w��m��4G��&&&�{zz�l����t�����;���kn��w��x����%����\8p ��			���2����������=�4i"�4|�������>j����Dn����}�<y�\�vM���~�8q"?�p��q�x���
Pc�F�x_E�x�b�U9����t�����=���C9��}���?��S�hQ:jnn��C33���`���a���=V�^M�<xP�`AWW���x�q���W�Z�Z�ju���������v
2������4\Z��7/��-[v����6m���o����g��a��EFFR�i	/$]�r�H�"�ncc3m���[�0�~l���4�h���Cy���� ��P~+�1�N�:�����#��#�Jt������SRRj��]�D	���_�E�2e�P`������v����'O�����M��J���&����b��2����-[���)Q-�x��}��"�P�2`���rN������N�:u��y�����c��8@���
DKBB���i\\��'���e��/$-�E���|�r��)??����W�^��C�;@��R��4\�~��u����#W����x�b����
Z�jULL�h����S�j��_n�����su�G�3������#F��0a������&O�L�e�������~S(�����	��??|���DjK���rt��
�;v�����jK�@�:z�����x��@�{���C�����P#}�[�o�N?*��P����:It������|t��e���iS^�;>>�z������v�������#F���Gd,�����(t������O�R�!c�@/����*U�K����gqHZ�����e��)�&M���`����GW�
*lI��aC�<��?��@�GSS��������cJ}��3|��bll<n��L�:5���Y�����htt������Qc���...������r��jHZ@��6mJ��������_�V�������������u�"E^�|)c���D		
,�Z��Bi�����D	@�P�l�>��9S��4hP���E~K� �&o����i���5J<hG�q||��]�����O)�]�j�hy��A��)��,Y���W�\qpp��BS�C���_�HZ@����-[���QQQU�TQ-��s�l���/�*��EDD����N�:����???�%����s&����%�@��<y��q����+
�M�������?�����i8y���'�+F	��=::�j��[6l�������w�����72u���	w����1d��U�\9�!*�����-j���S�PP�"Zx�S�@j��S��_�u x��������}�:uU�0g��6�w(��y�@_}���:��oO�C�(���-J_��a����
I��5k�P���7o�T�T���),,�B�
\���J!d^���i�#~�P3}�t.l����=z��"�����A�q�u���_HII�Y�&

�}�@O]�t�`��[.^�����!
/���)$-�C�m�F��k���������������~j��Dv�-��E��o���_��K���q��
��o�>��u���cK����+6y�dY{
Nl7Cv�����U�V�!___��
�%��G^���i*�t�"O��i-K�@O!i������tO�0A�PH�^(_�|��u)����l��]�n��Y�b��]����/���=<<����w��X����%��0����=�'f�������JGy��~�I�����y�&�:v����g��O�>YYYU�TI����B�9��������z��6��_������###�������S~�o���www�9'O�����b6maa!�5S�kggW�|y\� D	�U�V�X�4i5n��U����B��HJJZ�dI�5\\\�.��L�E,����j@�|�T��J<��I�R�Ju��Y)h�;D�E�g�������>@n'}��]�v7n�;wn����)���C�{�J����f����?�i��~��rw
��������m�IXXXPr�G�\����/�e������>|����|||����Q��������?��s���j��y��r/�l�q��=z���������_��D	�]OOO�J�={V�N�~C��0}��<y�,Z�(::���k]�t�0"Kh���hoo������F������3|��;F��w��O�x{{����ZZ�n���@_8u�Ej���?~���M�2ebbb��8�Rb6meeu��9��B�z�����$ww� i�����Uzq�����I����Q#.
����+��������[JJ�h	

����0B�x����@sss�-...<����6mii��4hJ�uHZ �V�\y����y�����J���_OaD�P\�p�~LII9z�(5��{W����		9x������;�]�|����b��%K�����6m��o��O�t�Se�M@N@	�I���~���%!6667n�P������������g�����+��%K����~�������{�N���W�M@N@	�Id,%%e��!����a�T������E���g����{��6o���W�TI��+��S':�u�V��
 3x6�P(v��%w_�pp	�~��>|��/` ��@�D����8((H��{����/_�}�@����K^^^�G�K|�(O��`h���+w/�� i���@�|�N�:�t�z��������]=&J�����G���K����7l�@?r�w�}G���/�����D	`�����������y�v��A����@*T�0`��J�*)����5�c�`gg��O777��L� �I�=zt@@���O���=Qh�����k/]�$w�rQ���:{����!J�V���/��(XZZ�;wN����@	@v(@N@	@v�@xx���!J�����/�����+w_�p����h��7o���#���/_���������[�.|�����$
endstream
endobj
9 0 obj
<</Filter /FlateDecode
/Length 1803>> stream
x���]��4�����5R]�m	!u�5����(���%�dfs���}O��$�]��d������8�������)�$o�_>��>����9i�����n��������{����c��1�u;�;}_�`R������C1S��3QE�R���O_u��f�����*����Z��r�����w���o���r�Ww��dFw�wdr*���ya��Q;S��k���A���~2Fm�+
5[��-Qyc}�`�HyM6�����������R�R�7|w_��9MI�t��d��M[��0-)�]�-)}�J���HJo��R6fxX|�+9�i���7X�����hx�0<��5��"m��K@)�.�~��L|�����c����m��ih���p��b�0{���j^C���p��V�>A�QI��$��*JZ��\��3_\��'�R�e(�j�����t�>_/]5�q�
���Y��2���u���hP0!�1��Q�$+��Rm��I�q����^�>�/4+�B�����`J4����b�J	�]$k?/�i��U�^l��R��Je�>TJ���O����;��6)���'�5�f�o��<�RU��HU�^����V�*}���i�%����H�Vm2,����b�����&Cslz�x�z+������.�-�l����k��'�|	��KQQ��@��d[�]qqq��q��^�s��S�N0�^�8�2�@�~��CR��������$M��kf>7���3Q���M��pO��������Is�i
w�LT8�����"0�L*��r�T&�k���n���3��z���&)����E`��107I��kc&�-s/i��	7L�����pD7H����``��20w�&MC�����0a���A������d`Z��Z�A`ZR)�n�{��A��f=��I�:�$]�����)�
i���pB�
��Y����'���t'i�fs��IQ����M��m!)���t�i�|%��ty�	�$�{���w2I�S:�?�$T���7�I�i�I�:�$]��&��4�m��`��	I7��g%��#:&)���t'i�/=q�.����c�^7M6#)���t�i�4��	-��Iz�4�=bY�A����J����W��1��*_7���~�*�T&�]�Q
; ���d>���n�j���������_�@o�j����qso�������v��Z�[A��b+|F�e>,������^G�'U�\��pW<v����{R:��h��_w4^��2h��p�����
hvt|���W��@�L��]z+��]����h:X�M9�`�����V�j�[��A�>�i���M��_QM�p4��2�������0�i�A�/M�����=-�	�a@����h��T�&YM&+�k�=����bf�wjW�Befm�0�V����o�,Xf�����B�f6����e`f,��,�������3a����v��.1�V��/^a"������|X�#���
�Qu���0_TG
x�S���c���X�\����^u������Pu���pv�����,u�~<�4mV�'v��Yn?iwv~��:��m�dCN�]|��4ez����u������
<�����'�����������O�OOZ��+�����vC����Uyns�Yn2��g��[����c�?��F��}<���i�����~HV�pv�[D3Z<�=�~PQ����5�x�v����Ot�QO�r����x1?W{��������?�W~m��#5N�d����onS_=6U����o���]C�R?��2p�Pr?����{%������
endstream
endobj
11 0 obj
<</Type /XObject
/Subtype /Image
/Width 2048
/Height 987
/ColorSpace [/ICCBased 7 0 R]
/BitsPerComponent 8
/Filter /FlateDecode
/Length 52741>> stream
x����U��/�@�POPK�Z#=MD<i�"��`M�Xs����x�1����K|�Q
T�7"(�cE��X@�|�����Y�u��{�f���2�Ov�Z�����c��������'���M���RTTtVw��?�)���%K�������WG����O7�a�=:���?������;w��JEEES@����/Fi��|Vw$��z8��������+V����4�����,;�������9rd~~���C�uX�p��;�u��|���
:�_�~�
���9����=�����a��U_������y��~	���KJJy��~i���K��K�%��6��kW�N�2�l������N���<��:S�
������c��{w�:����_�~���I�}6���U��L�6����2dH�8q���{F��o��+WFQ������X���<����4hP8��C����e���������~��K�,�>����O��0��C��g��5�TB�/N�+��6�0aB�8p���������?�0:���g7��O<u|���w��YQQ�}�?~���2,����G���eee����M���c�����Q���X���<�����i��u1bDt� ��?����=qeX�����.���b���M������Q����;w�+[�`AT6x����NbX�|����������?���O<��K/���������Duuu�����y��|��!C�0`���O=�Th	��ft�gn��qc�����=;�w�)c���3gN�����m�������
�[QQQ\\<y��Q�F=��#�
�����_��eK��N���x��pFQK8�3f����1b����uH3�MEEEc��
�������?~�?a����
��Z>���E�=�������9r���[�n��4���+++�K�
��p�S�LY�n]�O�m��������1|�od������Q�3�<��,~�����~��?|�g��������A����:v��zC��;w����a{,tY�`A\���'���T�}�������g�}��q���QAIII8�Y�f�a���_����??d��m
��i����g8�1c��^�t���u����3g�����c�L�8���:�o��5�����A�>�����~���������'�&M�t��������7l�������C���ys��m����h���=�N\�>����J��?��;��u��������&�w��������:4�W�Z�����&���O����������P�t������+W��������G��cG��w��'�����4i��+B��oX��)��O?�4�o��5k�F���i�-Z��+�L�81���i�sOg��Q��5�k����^��a����=;�Q�&.�}'��"]�_RR�O�2e���Q�0������a9��7���?��a_������y���`����=�XbL��G�o��9s���5kVbz��/$�l��?�x�w�����������;7��������&��qc�W�k�>��/�;����,\���g���_
�7�����&g�u��(r8p���7�i�c�=��U.]�4�����:���C�


�������[����	�G��:����;�
��I��_�7n\�S�&����?�o@��9�k\����G��������43f�������>3fLTPXX��)]�O����OF�9�G=z4�c��O=���!C��5k����{�������G�)t<x����*++��Ie��KKK�^�-J��>/��R�u���7�%M��_�F����F�DY���e���J��;7f���Q������f'���I�s�=7~����42�_E.++�'���aC�������_�~}���;����O��>� �C�f����~���^�S��{���5HV\\u_�re����/�����]�v�;���?������������:MS|'����-����n���������M�qt����'N><*�4iR���8�hSx����]W ��1cF�5���~D>�I7��,��}���e�$������G����o��A���ox:����8�'��4iR�2���.���Z�u��1���Ee����4S�N�p`q�:m������?�C~S��G�f�K��/�7�!��w�4�|�z'~�&�O����SS��I�9_��_C$��h���4R��?~�@���������Ge���dy��D_C�������F��U&>)�������
��x��o~:�x��!C�9rd�������?�����i��T�����qX�����d��l���l��a��q�=r��t}��t_�O���:��C���� �����[�
��>��?]��4\�z��Q���?���x���Y���>����,q��t��������N�z�D�{7t���+WF�����^Y����IPYY�y�z������g
��2H����F!��i���U���_�$�uuu��@o��V�1�?���q��&���+C���~���;��'O����g�}����sOO=4k��u����w���[�l9mP9m�������;x������L��F�Kb{b����?�'�/DN�������}�����:�%H8���I�;P��nP�z}����O�������/��I���#G��A��7���@����x��H�/�=z�_�m��%��������'Q���	���������O&<��_�����G3�<�^���3�H����}��%K�����>8v��?����,$=(!�M������"*[�vm��.�;vlC?�!�iUVVF�3b���{e�$��:t(|0��������A��������Q�R5���/���KxL�[o�7�;�P,zTnj*��/��R���$������_~�e�:F���������'8p`8���w��:m���t{���z�{2��?s�O���@�t�8��~<2��I?��L}g>��?�G%�}�o|$��
�<~�q��>8#��*�(�nB�C�%���e'~�����g":��YYY�������W�'N�������#F�H����N���w%�O|@m�����q����#\�{O2��h��� �����2.���O2�9d���2q����X��c���7_C<�y~~~�0r��z��OLA�Y}�y;(//�Py���F��q�����E�����g�}�~����{.{��L������$�G�n���1]���?�!jo��>���(9?z��0��?>|xT�y��e��N�u���O�6-|6��o��Iuuug��"����l��y������z��ZWW��#�Dk��i��g�P�M�6��q�Y��g���*--��W�8O�����_7y�_���#���}��w��t���)S����n��-��g��qgj�������.�P�}�������7�/xx�����mqc��+�����(~�<yrX���/�����b%�g����}?~<�2��o���2~o��o�^�_WWM������Y��������7y��8MM��[6{����������
v���^\\
�b��35f�����k��'�|2CYx���'&�'^��[Z���J|� �d����������O�-))���:K���+���
:v�X�����[��N"?���^H������'��7�?{��N�4)�.�jjj����q�����e�y����qc�����MK7�o������.�O�_������q�����g&���A���?����2�#�%:thT�8]�����?/x��gj^#�9���6lX<&~���n��	�R�����K�,H7��E���4��??��/�K����h��-�"��������Q��1�Q��3�D���_�����*~�nb����x��������J��G��?x����Ma�z�*����?�!��X(8p`�S�����Md����O�|���V�����t���S����1e���8������98p �Z������EEEq��l���������(��m������~:�4b���{�&
�}�����D��^��0��O?��K�u��E����7n����8qb���Q�c�=��`7y�?d��1c��7=����:\��&��������Wx�9��5\���7���W_}5��%�����,�d�A��8����8q���o:v�X���W�!�?�����]�����<m��9
�c���w��AI�pMM�s�=��#F��?�o��l����g��t��+�������F3��:u��U���_�|������}��s�����g)�����L0|��l�S�k2n��x��G��3gN8��+W��1#�,aG��_�6y��������O���u����S�
�����+V���>��#�f�z��y��%��3��8q"�����z�'Gd�a��p#x�����n��!i���D�.Z���M�`������������G�k���}�@sVVV����l\[[G����K�q���f����D@�����x��t3������� ]�~�fA�7#=K����[���;z���i�2�T�S������M��WVV�{7g���:�O��?��aC���T������T��B_|�E���$��!��/O$|Z�I���k��;=�i��p5���=�A���	X&M�������0����{�L���_O-8x���+&L�0|���SF�_�zu���S�����;w��O>�����
6���`��E��p����������y��l�3��k��%K�k2p�����<��'��5k��M����{����3g���.��O?=d���V�92siii���6�?y�W����2eJ8�A���x����#N3u���������3�A�������Y�����%
�p�����e�2|�N���w���Jz�d#�8�n����G���?�{��p�����G���?d���f��1^xaNN����S***��/��/]tQ(����C=�������9�����������{�u��i��u���:uz��g�$�q��m�{�����Z�ly����u�]���g����UZZ��K������?������?���c��O��O������W�v����������QM]]]�-.����)|��x����=z��a��N��
c����e�V�����!����{�����/))i��u���������o��k���G?�7�����B{���>�����
�=�P�RVVV���d���	BY^^��#G�����.]���3fD-�����+�;����CM������Y��m��9����:����������oOl\�xqh�����;v���]�f�]�;�m��%6�����.]�D�����w�qGR���������7���9z�h��.�*++�Z��[�����;a�g����o��Ps��W&�����m�677���,�����l���Ie���������'C��*???:4Z]�jUX����G������M�6������_,X� ��z��Ps�-���v��7�Mo��VX����6lH�Y�lYh�����;;h����KJJ.���+�����<jy���sNi��U�n�~���D�~0p���f��ya����N�g��a���K����^�?������7&�8d#����%������m�e���q�����z�o��������/>���������3g��}��M�W�^a�������W_�w���T�u�����c���Hee�a�-��?m>L����G�}�y���?��������>�`�w����������EEE'�zFp���w����;���7pn��gO6�4�2������B��7�|���,�,,,]~��_���k��������u��)l��iSX���[X.))I�Y�xqh���[O��/��b/����gM�$C�_QQ�o��oa������d?��)S������a�}��I5����[�n��E����~2��/$��=:����7���yK��WWWG��/((H�w����_��e��������q��A�j�	��7oN�)**�~V�.Y�$��v�mICu��9��S�f+]�?t�����Ce�;~��P���x���qcaaannn��-����O��n�����������\sMh\�ti�R]]��C��q����P����&������g
�������+�[�������g�����>|���_|qh������M�T]]}�m���P����hJ�-ZL�2%�]mm��w����k��O���{�m�6�>���G�a��V�Z����������k�����K.)--m���E��<�����B��;�D�gWUUM�:��?����^��e�����{���qc�kkk����S�V�Z�i��k��3f�H=�������'�}����w_�4�?�M/>��Z����kKknU��]�����8��������V�s�7����$���s��i�G�r��>�?�V4���'+ny$z��'���ky]S_~����7�)>_���m.��x������k_��h���$�on/�?�T���I���^���4��?�l��&����������M�F��_������m�d�I^���h��-�h|��f���7�K������o����9�mTE��J���U�����I�4g�l�j���I^�g��������$��3�c��7&�?�������1����L������I�4g���$�oL��9��7&�c������1����h����I�����@s&�oL���TUs2��X��~7�������wRe���
�?4w���$�o����'�����>����7&�s ��
���I��4��?�M�5�h3|�������P�c:Vu��}���z�����+���m5�V��W��4���=w�����������P�s0��'����f�7�/��m�GM�:x�=�W��9��Y���:�s ����9W�{�������f�?J8'����?��pC���8�_���7u����Q�����U�{ze3|-y�	��!������9�^=���m���5'�j����(�?�w���1����`��f�Z�����6p���s������;����=��h������-�?�{��S;y����=�h��G��������[����5����_S��G�	�8�����#��s���=�8�������_����^M},�7USS3f��/�0''g����UUUc��������i��u�N�:=����WR��m�z��}�e��l����/����JKK��P@:���]�t���=���������{��6�k���S�BX���Wmmm\�j��.� ����w�������_\RRr6��Y�~�E]��}��^{�G?�Q����	B{^^��#G�����.]���3fD-�����+�;����CM������P@:s�����}�����.����ch��m[bcIIIh���K�:���z�w$����{h_�|�
H�����r����}�B��W^������m�����eeea����eS�NM*+((�?���
�R������C�-���Z��7�Mo��VX����6lH�Y�lYh�����
�R����y�B��w��Z��g��i���a��k�
�}�QR���C�
7�pf��To�?s�����o���^�z�M����W_}uX��sgR���[C{����P��S��s���O�S�z���i���_TTt������~�����P�}����8�������0��7�_�vmh���{j}�N���M�6��n�������������[o���d���������}��I�����[�n��EEEEX}��C�/��T6z������f��To�\���}�����EEE����o�V�,YVo������;w����g|( ���������n����<j9p��5�\�.]�TWWw��!77w���q�q��E3��������t�������n�:''�g�������������;����k��O���{�m�6�>���Cm���U�V���yyy}�����k����KJKK��38�N4!O���������v����:uj��U�6m�v�:c�����o���O�K/��e���������RMp� ��}�r2:x�`T���������*q�����c�^w�um��i��u�N��}�������n���w���]vY��-/����������qN�yeee�����.���#G������-Z\|���e>�`<Zuuu�=rrr��kw�)a!�������6.[�jU<777//��{�
���0xIII\h6&O��������G�eeea�'?�I�^&Leyyy�]�����K�.�q��Q��c�������;o���q����P��C�����p6���;w~�{������y{v�������k��;v���m���XRR�t����??��q�I}�w���/_~�N�on�����;o���q�;�������g���G	\y��I�uuum�����-++���(�:ujRYAAAh�����I����(''�?��?W�Zo���Q�F��g?k�������_��,�kV�^jn����1o��������
�yyyay��
I5��-�=z�8��Zmm�O��V�Z���/����_�9%l����o~��(����7/��}�������3lZ�tiX���k��G}�T�q���~�
7��3��k��9999=�PR���+o�����������/^|�����u�����3g���}����W��i���a�����;w�L���ukh����i����0�����74�&{7�pCnnn����y��srr~����������_TTt��g������O��?�p3��={�dM�P[�l��������Kaaa���_�2,�]�6,w��=��S�Na��M��r�n��rIIIR����C����z��~��{8�>|8�t�8p`NNNAAA�]�L�������O����n��u�-***N~���^x!�l����=??������p�
999���n����_����-Kj���{B�A�E��&�n��9����(4�|�����%K��m���4T���C{qq��9��������?�e��'N�H�:~��������{���sssC�x2�������n����<j9p��5�\�.]�TWWw��!t�;wn<��q���������@��}�����+����������v[(������=��M���E�)S��e���w�ygho��]�>}z����m����$��a��V�Z����������k�����K.)--=�'	���o��������4]AUU���S���_z��-[�����w��7&�����?�S�N�Z�j��M��]g���:�������
��}����o���g�����w'PRT���{XF6Q�AA�� t�M��Q!���$�
q�q��W1����$j EQ9a3��(��"��� �(�"���?�������:��~������gjn��U}`�������.w��*�����n*�u��h�k��
w��mQ�/~t{�c ����Z�����������U��eW^�}�����rk�K���������%��/�LC�*��oO�W�������;���_<-��s����de~4AzX^Y��[��������l����X�s��Jw8�1�'��@��_��s���\���^wl����mOK���p��q2�TZ��
�>V��������[������������������������2�3��q2�TZ��cf�?N���J��������?Pi�����8}�Y�������g[�;�w������ui����*��c�����?�{yiY^�;�E�O�|a��-�d��9�E����nOw,@%e��2X�� �[�5��t����Y�������lu~�c*)���D4��|Q�~k�J��?d�U��_��F^�������]i�!��,�O�[������v�;`������~�f���Wx�������}���/2dH����W���I��C�.]�������k����|�:uj����S����?//�X�T>
(�_���D�K�.C���K/%���3';;;+++''g�����^�f����'�������?|Z��
��V���g����_���c��1�D��'�,���;Z�hQ�J�i��%�L����m��������
%999[�l�J6m���k�P8y��R}P^xa"���_�RB��S��:��sN���}�����>����C�\�xq�:����]�v-�G�q��g&�E��Pg��Q���I���O�0!��;6��Y�&��l��X����z��eeem��1������O���8p`������[�ju�W|��g�:999�����w�������a��_������G�x�������Q@9u��1�[�v��=���6h� l6m�t��Q������>���{-Z�;w���~���~�y���#N?������3S�(��F�y�g<����
6���/�H���;*i��u����S��o��v(���CX��������#�>������SS����\�r9�e��u����>���j��%�O?�����~�M�]�t)����%��?k��?�d�����d�U�V�m@��:�����+���{������_�����C�g��_~�����o�=?�S�N���^{-��*H�-����G���>�h�:�����_}X_�n]Xo��Y�:����k��Z����[S�(�<�.]��W�+�������W�
���1#�H�Y�K�.�|�����	'�6_���uf��
�O�6S�(��rss7n�H$����d��u�rrr�>�7Tk��mVV�SO=����D3�D%�=�X(�����M����?�<�Gh�����(�<�����Q#�Ht������0`�!�6�?���7&�-X��V�ZYYY999#G����[�S�~��K�&����<8�7l�p��aC��W�^��������T>
(�e��]r�%Gyd��5k����s����k��{V6lX�F��W���Y��/�x��������?����:u�U�V�:u�u�6y�����o�(�����r�>�#ZV|���p �l�������_����^wl��g���[��Kw�*���
�_��r���~4qG��%��_���wV�'��+�2��n�?���?��M�r����K|���+���iY~���g��?P��[����w���~����o	���nMK�}��9R�����?P��5������\~����g���������8�����23�'��q2�Tf���d�?N������������?P������8�*3��q�hm�3���r������S���K������23�O������ey�/�=���E��s����p��oc������3����2?����_���{�W�/������-a8~kZx���t�2����E7H�|x{�c �m�����n;��cj��q��m���+�\�vm�:�rHbo;����v��5~����?�N�:�k�����������W�'.^�x��!�7�^�z�&M��t����5�����/:t��H$4hp�Yg�}��
6���5[�zuT����j��5k�����G'?*77��������}T�����d�9s�dgggee����1"������??�_2��_�H$����y���$�|���
�W^yeT�q���y��G��Q=�P�����e���d��M]�v
��'O�Jv����E�*U�L�6-��)S��:m��������TJ��5K$��-+Z8}��P��s�hs��a�[�n%T�=���-�?~(���k�9u���y�9�{o��}C���?_�_����������+E��|���y�����!k��	uZ�lY�����^�zYYY7n��F�
�&M�T���	B���c��������O$��rK�9g���y��g�q����w���s�A�z���=�\�-/��b���_�=?��O/-\�0�������3{��P�������r�?~vvv�-6m��<��3��j����g���??�~���Eu�~���y�y������~zxi���a�}��a��>(Vg��EEg��3fx�����{�����/���g�q�E�]�6Y8}��j��%�W^y%l���#G���3�>������S�z��������bu�~��P��C�o���/�����y���
k��q��U�R�����wS�?z��D"q���~�`����5kV��������t���?�������j��T��)��[�4(�H���k��u)�k��)�-�{��/��rX������:u�^z����z��=��������>}z(?��3����� ����"l����SNI$c�����K��'NL��[�.�7k��X������kW�Z5�����2�����6n��P~�����W�WnnntO��	���M7�t�	'��=�X�\�x�
7D��N�|������5kV���hs��as���>�K�.�|�����}���[n�%�H\y��%�y��C�v��}�����)S�deeU�^=9��c�=�u��}��MQ���~�QG���3gF%���m��
o|������D����_*�
6��Y3�H�����D.���0 T���\M�_�j��'&?-??�����a����
2dH�z���e�]V��.X��V�ZYYY999#G����[�S�~��K����@&Z�bE�D�g���k��I'�tR�F��W���i�!C�,Z������?����:u�U�V�:u�u�6y��=��e��
}T�f�.����+WV�oT������}g�\6l+�?�w����?l���+���6�_����p��J�\��m�g;����[+���i�����i�����y'7�l�U���O�XeZ����������?Pi�������*-��q2�3��@�e�?��W�eg:�w�*���2.y�i�6�_%��p�W�t��-^�x��!�7�^�z�&M��t��t���9s������rrrF��
�5k��?~�C�b��-Z��R���i���S�LI$m�����Mcl@�L�:5�H�s�9����������D���Q����I���O�0!��;6-Q�����H$,XP�|�������i�
(����'�>��X��E�By����P�[�N$�����������C���	����d���{�b���I�J���K�.��	�G�>����_��b���I��=�������O�>=��q�i�
(���G'�G}�X��q�B���_������1cF"�0`@��.]����s��%*�<rss��m�����SO%x��h�����4����j��������3r��n��%����/]�4��e�l��a��5j��z����5����W�\�������?�YPP��(*�����_�>�QT[�ly��w�@L�:�Z�j]t�K1X�ti���;u��@�l�r�I'r�!o��f�c�|���&Lh��}�5�9�����;�L&�1�>}zNNN����7o~�m�����;�L�h���}�{!��5�����N�����F�Y�^��:h��A[�nMwD�l��]��zk��-�����~w��%��(��l����l��M���;w�<{��tG���y��.]�dgg�j�j����++�[o�5`������_���.��qc�#*��-[�������%��Tc�����[�Ee1u���~��W������n.���{����@^��(�.T�
6�|��!�M�4	���>y��t���d;N��x�W�x��-Z���=r��t����L����]�Z�:��Y����NwD���w�i��i���8��
\v�e��(����=zDM�a�v�q����3�Ae�p��������ae�����+3������<W�R%Z����W�����T�z��������M��P!B�,����Q�%��S��]u	 �W�'}!����w	 7�|s�7k��%���3'�9Dr	���6$t��l�Pq���N>���'y�����o�1����6����v�n��������*J���>[�V�P�h��t����.]���;�X�"ln��-�e��K�m��n���gR��[E��
5|���t$���{W�����={�l���?���/Cg�'?�I��Y����k�]���[����>�h���������3�Zz���V�z�G��;7������[�l_}���
�]�t9��]����^{�D�X]�h�f����s	 6�=�\������;�%���AB�o���~�����|�;}���NL\� >�`Ho4�4l��P(���l�i���U�T1bD��Gy$d��{�MWTl��Q!�{>�%�w�����2��O>���C+���3�>�j������?(V���7oNKH,"��}��W-���B��?���2��~X�Z���;���+Y8q�����C��1�������M��u�FW�#��/�M�4I_\@E	��j�����~�����~���x�����]���w������[oE�������G
+.� $y���;v�p	 ^xa�$���%��N�6lX�������O>�d��M[�lIWl�G��t�5��v��w�-Z�������<4�_~�e�b�Ha�n��Q��������#k������[��v��K�&KB2d��8 ��j�����g�i�0���93d�7��M�$4 �\�~����^�zW^y��
�a&9���BV���-�;wn(���+�U�7n���%���+�$�sL���T���j�v���^�z�r}�<��/ON��@�4iM��@��8��|�@l�y����_��Z@�K�C=T�v�����j��y��S�b��L��j��t�Q������?�����''/�_|��t�	=���u����-���K�6mz��'���C��A���[��3�l��?���S�<��U�T8p`4�t����z��tE�az��������M�6-����Uk��}�������Jo�#�:���G���7%m���V����:���/�P�2��'�tR(	�	����]��+W�5���C�����W-l��W��/�<$6��q���2e��S��l�^_���/�8��R������_��h�%�
�gu�����{�M�*Z�>}���SO=5t�����F�V&M����2��������p�}�eee
><�f��^z)�7�����%��{�^�z�[�6�Q~��h���$K�y���3z��W]u���c4h=_��I�'�q����C2O:�����G%��-�������n���h��f��.Lo��!�#����k��
=�=zD����24��5�'�;���F�'�xb�&M,XP�{R����u��
�_~yZ��6l��������+�=�l�j�~���E���������>���tK�����
�7n\���_
G����2Ut��i��V���c�=��#�R�����]�~�b���`(_�fM�*��	�>3�%�
5w���K*�&N���t	 c���Z�jrr��%������-��6$$��^�6���=z��c���qcVV��7��,�.D7����2;s�*UBJ��N�?����n��}��Q���W�s�Pa����
5�v�B��a��!�G}��w�}���x���$9���]�*t��1��f�w�}7��-[�M����=���?��h�{��7d�i����C���3�:t�-Z��o�����KE+,\�0;;;�0{>��2�������!u�����[�����!������a���_�����Ia3��g?�Y���Tk��m������5o��{��i	)�����o��Xa�
���3�����%�I�&]~�������z	 �~�{���iS���L{��~��~��-Y�$��e�?��E�8����C�1R���>��������;Y���l{@E'���~zr3��5k��,�}k��Y-[�Y���Bn��?��[oE�v��0��v��/_��{���n��U�w��9E+l��-�������
2�D�8����J��^T8P�
����?����?�1$������~��M�=+�;6T�s��2g4�����={����=�������OZ����v���������%{>1|���!���w_���<xp�^�"//����+zye��g{�Yg�U�$���y�������>���w�y'��P�7d���|p��p����h���q����%�I�&eeev�a���a�(v	 t���w����J�K��p���A�<�,Y������-D���sp�� 
4:th���'�t��W�A�5i�$Z�����G�����V���>Z�n]���C��g�V�Z���XF���}����|��m����u�=_��o��v������[�li��m�g8P�u��h��i��Up�%d���E������:�9�|�TJ��o�����>�j��{���u������[�1f����_}���j�
���!C�|��x3f�(6M}��}���q���{��GB�:y��{����j����4����{��7�`�{����q�e;����	'���]��f�t��3��%R�\V�\�2J���%��O���=�����s���cK;�b�@8=�:�_JE������_���P�k�|����;d��:yyy�������-�3���D@ao�%����9s�L�������s��G����D@���#�)(o������k�&��i�������[�H��G���+{x������_1�e��Y*����Nk�����999|�Y
S���D����������b����^2dHx��m�
B�f|�D���o��w��/��=������oBy�7�H3A��B;��u�]W���W����W|�b���]�v
Ik����'������{��������<9���=u�T1�y&����ABK:�{������������S����W�V-;;;d;�R�J����D�z�t>�W���~���.���z���J���@`�?uQ`����}c���C�����%����F �$���]�t9�����GV�XQ�����M�6M�6��9��������M�G���
u�R���r��YQ�St�?2a����t���
��Q���l�^zi��z���+2��!�qJ�@y�9�����#;#O<�D(,�M;�Y4����gi��_�j��Q����+��3'={��S�!�O|�����_��[�P�n�����,_�jU�������a�����}k�C�
��f���o�����w�������;���C�����h�����mK{=+�f��^2�_w�uWH��A����/���o���������rh=�/�/�y����]8~��G��o�����BC[���GqD����-_��z��=z�(�'N�h���B�+��tPi�J
���>X��T����y����P*��I����Vr�K/�4:a):�OiM�4)���n(�Z4^���R<P�^�:����G�M�UW]���Y�������g�1bD	}�I�c���r��i�Zvv����]�v�3�{��7��������j���>��v����,��>���������w�]w����0$�i���|�I����~�����=��U��m����������������
��#�8��J�w���#������7�x�m�s�1a���o�9��WtwG���O�
'L��g���z*���?���|��5k�l��}���Cah"�����Y�����s��/�.]���Q��s�:u�z�{�����h��_�9��O>��[�s��/���n��~��2+C�u���O?�]�v8�H>6h�����p��)???��B�m��%T[�fM874�_~)({��m���Rl��o��J�MZ�j�*U�����'��!�qJ�@\y��Q�k�������u�m�O�������V�Z�K�=KkO;w�7n�!���Zh��|j*%���G��=�=Kk�5�~����:*���m��Qi���7�x�O�>�l����z(�h�k�\rI�������;�p����6mz����>�w������N;��{��O��jQ���C���kv����_~�e�<�Z�]�v��� �I�1�b�����s����������7++��s�5��������_�E�)>����7�_�z�
'�)>�m��%:�Q�lo��E��<�Yv���>Xr����Of'�!�{��]��l���R<Pn����?�-��b��c����t���e���
Z�pa<�e��S�����Ht���Y�f��zj�GI��7�x#���g�),2�f	�X���}��W�O��|����� t�����L�Y��t��s�������z9�=�6��V��={��9s�n�c�� ��Cz_|����w�yg�
F�5,u�����~���5k�L���L��1���?�y��dee��G?:����g����K�{�)��]�r�^Z�e������a�W�����{�GD�=�����������Z8`�����Z�xq���
��Y8����={�Ry����M�y(�Re��� t-t�l���-Z��_������K�0h���t���K��R(���r*U�M9�v�(c������S�����6S�@������#����m�8(M��v�n�����#F$K�A�V�Z�������������I�&E.��2��e3o����V�Z%���y����B�z�E]4l�����9|����SO=������v����!{�q������f <x��Q�6l����������[���������o�>�|�5�	�}��tR)�v���m^q���R���>�����u��8P�L�'���el�������7](((pSt��Y�f��e���7m�{t�F�c�v��~��}��g������7o����|p����=��Cv��Y�{R�7�|3m���9���_0�nv��~�y�����W^�������zT��k��!��p���>������f��;&���V�Z��{��'*Y�d������/	���
Kw �B�H��[7����v��w�^�Z��wT�������~��G�H��@'Mw�d;f����%��9�]�v5L���uPz��I�5Z�dIzc�<����~:y�$4#������7�U�
�������N�M���OWT�j��-�F�*�����oZ8p`��*������������;�J!�O`���Pd;N.�����YBT���7�3��
���e�4�q��89P�C��=��%�h��T��+m��
JO�4�S�R'�q*�s(rrrB��y��}O�+O������$"����/���#������K�U���K��w��8;w�l��M�:u��Y��X2�l�,�9p�����Rx��GC�����tR)8P�I�'����>1g��2\FI^8������l�NJ{����S�r����;�[��T����	G�3�<���{���z������?���)���;o�����7///4�a�{���*S���N���+B�2q��}�� ���<yr��_���������~�}�����#GVtT�v��9K�Z���k�k��t���
]�s�9'��p�����C78�q�t�_8�N��x�'�}�'?�I�i�z����q��i�#;
�������
���N����C�~������]�W��]�v���p�����O:������~�"b�H'�pB�5���3&d���.���2R�����g��R���������/�<��C�6m�e��t��_�<yrh]��,�K��zjVV�g��G�w��v�n��3�Ynnn��m������?�ab��K�1q�����<>����1y�x�Md��R��8P���
����a�m��=�w���l���������z��]�j�����]�]6��v[hz��T*�t�M^x��i�~����������#�$s������J���>tN�x��)S����'�1lj�SW����O>���{�C�>}���^�p��b�����f��}��g�������F��n�-�=�3�Ko��V�*Uz��C`��W^9����
����?���������(���m�����t�A��ylQe��>��g�}v�����-��2�����iHnnn�v8�s����|�)�h�+��<-�l����k�;��y���~bx8}.���>��������nK�����(m�
G������V���W���"�e:~-[��_�����K��_��2��8 ���d&<xp����sK��c��-Z$�>|x(�'���z����f�K�.�����^�z���%�K���u�Q5j�p���Ju	��?�a����O�X�y��w�.}��G_s�5!����/K�/����E�B�6m�j���=������Q�b,����G}�:t�P���UZ�<�H�p�~���L����%Tv��WN?��T��5��T�K�]��o?��#���:$p@h�K��@Y~���}�k�.�O�4n�8��eV�l��?�pty\z��aw�6mZ*�e���x��������[k��_������z����v��.t8J������5k��q�!�c��Y�`A<�e������	�D�����K�y����?��i�g�}����f��������/���<�E�NCR�s������h?!��|p�W|��e��Bc2e��p~�d���kt����\&�T�����������+���f�]O=���1y��g������c����u�Q��P�]~���S�H�K��G-���_|1jI�p��m%���r���_�~����Ry����\s����J�������?7@Zf��y��u��i���ZY���{����U[�ti����������w�Kw �B��n`���~���^��c�������L�:���TK�,y��'N9��/�y��c���'�������M�x��7G'�G}t4P��{����qE)B,4{�=6E�-X�F��K�
KTbI5j{��`�%��{��B�D�����<�y�o������]��G��s��3��a���sfX��������h�"///m�?}�t��u�L�n$%%���k���0#��^�~]�|y�Y��,V�������i��*���^(u������������-[��?a��111���[���i�2������0��v��bV�n[����
e/��i��0�|4�8�����?�{�� _g����PZ�/�7o�(P ��a�����M7�|	�?����C�<y6l���?�f��������S'��b��
6��3�6)���\�pQ��������G�Q�zu-S�m}X�bE60&�����V�n<x0o����%J��]�O�X���r����@�1��b����7�����2�������J�*�[��wom�	k[gBBBlll<==����M
���=��?�[�ndd��>}���/U��2�
��[�ne���F���_ft��mLRRR�)boo���3�e�"�������{����%�=j�(��"`��0_W�^��??�k��E��Q���iS++���������v��i�����m�����������}
��LoxPu�����l�������S���)�u��<y�h�����zt�1�r�}
����/_��Uz����r�����-!!!T�&3f���S�q�6��Lq��12��6��~��i�`�g��!P���k�����mL�o�m���SiA����o;;�%J�[�d)��+U�W���{J��E���a�n��Y�@���r�P9�#F��c�S��4���[��SF���~��������<�V�,F\\�t���[nnn�0,?~��hii��/��AN���������*��}"&S$$$��T�RE������N6�S����������y[N�/^8;;c�LLLTZF�B�m#����-[�.(-�App0L�O?��� ����$""�n��UV�����f�%%%%..N��@��-9`p���n��Y����s
������������OQI��
o������������\�����,Y������Ws��E)���d��f��\��RE�)�k����}[91�8$����&�"P�h����[A���C�A�����?����0 ��?��V�Lp���c���������T����5��,��������e�V�N��"HJJ���prr��vg2��Y�
*�e7��m���9r$��b��t3����G;;;*�;|��/^�#Nds���b���+/���Ommm���c|����SE���q������=7���[��*U
�����U��4��)�,��������������k��Q��o�_<�$����?�	��
((�Ic��T|�`�v����#Nd������X"�P}B0a���f�d���+���C�9""BYQ��>�,Y2G�Zn:1j�����Wk�`m���� �4[�l�Ryb��u�v�����$�q���������9,[�ljj��3KRRR����y�M7������������i����SZ777�������w�ZYYe�����������������83�$�@��5-�GXX��B�.t��H�";v�,y��7�@��kW2��G������c��5�l�Jz)�/������k
Jh�`�6l�:�U��7�|C*E�����"�,"��b���/���LW����o|����RnI�n���t��oV��s�T���hR������X�zG�.�{�s�����g�E"���z����Im�n��Q�=\A�	fN$%%e*0j�(��x�b#�f�����v�:u������l��<@�]�D	WWW�M/&&�Q�F���7����)�,����my�������Ph��_�@���
�����V�Z�M������'���o��A!yM�U�VA�C���k���|bHH�x�SY��hSN����������]t���'�������Z��n�kLDGG����u�����WBXs�[�n��7m�D_a����{�=s�
r
 ���e�
+�{�n�G���	~��GEd3V�XQ�lYD�s��k��@���R�&M����������{666�t��g��������T
���0�����;7V@�mi���Y�fA���M3�x�
V=����G��8��������M03#S)���_�o1�([�d
a���������~�l���r^����@����=*}�R���\DZg"##��3x���k����U�\?����(n��:�W�v�.]�('�i������B��q��S�)F>|��F��"K�,�_��eKi���������.������E�
0:��6n�mcV�5J�+�����`2 &&��(9s���s�x�1����+W����G��s�j��5K�&��DEE[JsA����}�R����]�2�D����f5�4j�H�I/�������={����7n�-A�c���S��L��uk�YX�~=��������{���������w��1����
���|�S�N�iN�>m���L��-[&w�������^�z�1�7�����a����+++�*���� N(=x�������:H�>777J�����-[��� Hy��mBBB�.]0���a�g��%��e�9sfTT��y�lll������8`X��=eJ�����R�.��E4<HE���!�cEhh(�5jt����?�������[Wi�M���@gg������{={�����}QN���I�s���������O�<Q@J�'�:���������!C�={3���������T�~�:�	{r�����pWWWh��SY��G�
*4j�(8�w�����L�6���[Y-�Y�9��O�>�j�"c��k[{��o��3���>������]�3`���C\g���3:u�����I���� �1b��9rh�@����2p��U8!���qqq4���{yy�1�B@��a��0&��D��A�����w�����'�������|���Q�F��g�?|���#G�4k��"���/�x��q��d~_���I����i����a�����S!�)��� %d4a��$""�B��Z����wo???�Ji��zX[[W�\����0&���wvv��"*��y�f��dL����_ww���+-�	WYz���~� �f�%d4a����HS�����g���������n	b���G�7"����/���y��U�RE�7�Y.R�H)m�2�q��yZ��q]�,���{���B9t�����W�ZU��%0�����#�3���e
��
�(�}�����T�dI�{)������Q�N�|�(������h��U��������w����z�����1	�`�l���:XQQ�u����z��l��
O��We�6���5�[�N����R�'�4��Y��Z�j�	��-�~�z��5y����k�N�v1&�����+wX�qqq+V�p��fX			��gwpp����������bB����nnn����1HV�h�����4�?�<y�t��%66V!yM�w���2�����,�9s�����7)�b��y�|����5(�zk��	c.?����s�������6n	��o��)�����I��*�1Z�b2����9R:��^
�������W�����C����d�������]�p!e9`X�P2D�%�SF@��}���J�c��������A�D�5�9`p�K'��W�8�0�G����w��z|���-{����e������_�x1���C��L(V�����^)cFO������'\�p��3g���1@;N��@c�����gC�M�4�q*Z��7�1�(P�vm�D66l�
o��E��9s���Q����'O�Pwwwgg�S�N���1��$�,_�jl�������������TG���`��F��7n`p���
�l&�[b4BCC]\\�f�)S�q��jO5���
�\�����`��UP��9s���o��)�3l�0��`�0C��P��9r�����'^^^����$&&bq��a�����3�Z�RN0��o��F���G��[�#S;n;PTWG�h��_�>}�G��_��;w�b���3�;��I��]�~iL0���?� %��QC�(x����	^�x!}��E_�v����&M��;F_����]�SFg���<==��\��hL0�����T�l��M�#���#<U�'�|�
t����JjV�[b4�J�����!������`t������[�l�t��)��-[r
���;6=�n��\��hl"MP�����O�0AQIM��������������b�Rvvvp���,y��!�?�O@gB
*et������)�<�u�V�q�ty���i*D�s���;�cL�4	�i�V��k����=s��r"�	�����^�x��������z�Ul��%�|����%KB�+VT��N�_
sQ��������8-��/O����Q�r�6m�l��P4=n��4M����,���!>|8����'�~����UR>�is��E�
D|�5"��
�G+V���-���k����4U`��O5��
vK��?��ccc������U+�*^�xQ�M�SDT3��������*U��8�u�.�Oi+I�-��d���#VIww���y�FYQM�%���?z�h�pz�)�����
�=}������{�����{���e3K2N������ ~WPH�a������/BBB(�VKL�8�;kkkX`X��j����A�����'_�zw2���j���:t#�C�\������h�������R7n���pqq������M�JK�3����Xo�aaa��?/_���{������B<�~
6�:�"���gOy
`���|%Yg0��+6o�<������}������J'�'O����f�%Y
����H1�����=z@����S.4��f��={`�&����s���X����i5�	I�@�g�R�+W��?�?~�j��%zyy��j&�<~�X���^
�������g��III������%r��������#���rNd&L�bK�.-���
o����jc�����"���������G�.�|�a�����_/O�#]�v-R�H�������w�t���[��4�-���G����%K��hm�c��K5�688���s�����M��g�`�S7�������m�U�~��W��b�%�,����Xf�$0�j�s��]��M�6]L��k���tG�����_��m�� ����\�zUc
 66v��Qe����������0�s��eQ���Jc�4�9GG��s����J�3N0�+aoo�C�a�Y������"��������{���=�i�����%�����W�V�BUv~���Rh\c
 MU:��H����oii��o��D��VJ�<���7o�.\����.�%0��O���k�R��:pK��E��yW�X!�5���5k� ��� ��p�����v�Z�9��`2�<C����5jPL�����'4�i�&�V6L��ih���3@Q4,F�C��|�w���a���Y�`���3�]�F#�z�P����C�����c����NLL�Z�*=<<��G�P���1��{�L�o�j3f��� �
c"��)��-I/�d����o�v���<�"E�P��4vK�-�hoo/M�bb�n���h�9���q��O���i��GP
���_ms�����(x#�����S�����'���Y�n�xKj��
���&OBB�����K��A��WL/����7olmm��k'F4��#������o\����H���K���

%�|��e�n(�^�z�Y=w�\,���=SN^����S���9r���|�������0&JLL�M�������)�b�zL{V ��={�������V�X1w����������������g����%K��X�hQ����u��I
�?0=8C]���tC�����e��u2��&�5��n����&���G���+�9�����\�r��Pe68�d���Y���!���2f�8u"��|X�q����3#�����-T5����N��y
���kb
e>IJJJKb?�f�&M����+���nn���U�VEFF�
���o��!C��=��a����*)��7�o��)����#�)v��
�����@�?B��7oNS�mR���7^�L;;�;w�(-��2a��"�W�;w�`����K8������Lq�\��Owr���ENg�L�B`��y�n�(Q����i��j��agBCCO�81z�h�n�m`+hM\�v-U�>|�x�Sc �����������CT{A��
��� 88XQM�]�vQp'R={�D4G�k������h���J*T�`�?�9�������+W��
bVKQ
 g������!������rY�h�E��s�N����_K���
�5�-X��3f��Ub��h���+W�T��K�����q_rr2�	�oD��
�Y�6@�j{����2d����aJ)RD^��R�9��n|�-)��7*T�A���j�<|�P��	=tK�.MS�Z�������H�[�3���S9p���)�AB�BBB�\P3�W~9�B���o�o��
�\c�j^�:u
^4���j.!���a^~���4����?X[[c���u�C�&M���'��.�S-Z�PHLSE��!~�&������Pu���*�9�Y
�����b��/�����#�o��.�F���-}@���E|=z�(������6��.j��eoo�������SxJ�*�=:3�Zp���}��)))���R����aaaF�����x��}��-�������N�<��#<dQ���,{���b�u��A�~�^6��f�t���w�EZ/Wc���������Z����0����c��Zyj�'=>'RE��G�\�Xg�tK�^��/_>�$���e=�O�V���o�U;5G�\i
 ����b��Kh���"�V;>�q
����5�f�)S����6m���[���9n�������e�]�B���fA�

,(�g���}V�����G���f��A\�^7RSS�@�p��LDz)���[�[�)�.�^2�������KS������:y����?�*U���RD`�!&&e�6m��.$�ET/�_��u�:t��7W�X!Z1�k��;w`��N����:u���d�0 ����e�������S�j�N�:�3
���������@���.44���3!!A�4��=����s���)[�l�B��5���{��/�4l��^�z!!!�1k��	|in��4{1�7l���=��1�Bc�y�7�3N0���[���DZ������o��������L���������2}�tUt[[[___�����������?��:K�p��
���.'������L�2������wO`W�P�%}��7v�X$sA[m�����eK%�5/^�J�&,Y���t��1P2UR�P���{S��.��$b�������S�B888pUF�@�/�Tl_8�?�P��/_��:1�e��B�
I/f���WA	�	����y���w��O8� ��
��1Y�p��N�������K�*e�j� =��c��- m��?{{�F�)!��p��Q�v����U���v�Z�w�4�u@�9r�h��������<yR�5v
���mll,T�3� b�Z�ja0O�<�n����.o��d�I�&A������j��III�'O�2��������aI��n�:W�\������K�����j�
�o�>j�(jG[�|�M�6������&�J�i&���K�.����N(Ejj�������������1��<d�x������W�
�hf�b�
�S����SJ�n�1)�b��Q�58�?�02G�����%R��VL8*�_���}�����%o��|�YO����Xooo�3O��-����<����HwU`�;t�`�N�pr����<y������3���OHH�R�
��x#���@����

l�Z�
����s���������0��k��g����]�3[�r�/^��I)���0�����K�,)��|��-Z�H(���P�SQVHsBw���O)W��Iu&�)�����,[�Lz�3YzFw�����Pbt�R9r���������w��/�y��LwTT�b�����h������
����/����@pp�b�	����u;s���������K��
*<|�PA���:u�@��[��X�#���Lz��p�0�g��1x�`1(��RQ�"��'�[�Nn���u��]jI���9uk^�|Ig?`��e���o<���b�CnL�J�2���m��M�Gc
���sQ2��# ���>y��^�z-_�\����`&M�dt����O�R!��g|�\LL�qe472��y��Bb���K���aIF�
���f�-r���g�u���Waaa��k����2������d*�G�t��������+�%Y��-Qk,�'�;�?��n�����f�F��*����g��M�5R7�={�y+-v���?omm
�;99�m��K���3�������+&5p�lll0�'N�(}9�c4�4U�q��u��N��{�����~�������w��P�_P�vm���P5�E��d�=i���2�^^^nnn>>>G����q
�a��s��uh���No�{qo��)[�,|	����������
1_��j2�`t!3b(3o����2~9,,oN�0�8��{��������~+q��F��p08��� �n��q��3�%z��[���?���Y=zt�
z��y��}L/�d
��jfa���dI�aq?h�����

g�\��R�ti1�d�����FLZ���
(x�:�����a��cG�6m��,]�T��`2�����F�L�"z<�/_^�7�%'G%443�7n�hee������w�Vr��}��1������������O8�0f�2[[��9sV�R�z������r��n��P��.��X��4i%���N������['}�SYM�)����'%%)+��2f��������@Oz ��cHH�:����DDD��-\�0��-[�t��]-��@V�q
�E���g���s���������tqq��]�[b>��p
�d�72����Od�����)B���=e�n��=����!5���(=<<�
V�F
���"d��
9r��PuGm��m@@�zyy���
�&C�]��q���j�KS�.]2��f��w�:u�$����O�>���~���W��!���Ghh(F�U�cR�`AIDLi��������M��
�7F��A�"=J�	���r�Z�x����de�p���_p��W�N�e<xP�Lyj�����s�.Q�����="D�D6mV�^
�������)HII�1c��UM�K`�K�]����'�
�3`����5C�GA7>'&&*'�	���Z�hQ��2��=zT{;�^
�u��\\W7^�z��.o���4t+?��n����-��d�-IK?0u����������#G���a.0occc�^q]�Y�`�"��"r���I����S�H8~�&MRK��}�#�Z�O��{���8%�?����aaa����-��S
������U+����'�E���v�)Mb���k{bmm�y[�Q�����y������g�H�D
 MUZ�Z�j�������9��e��=}�T:���������.rc�T�R63>>^�������Q�dI77��]�>x�@!a����;88�w���/Z*���k�
h������A�����i���`t��
�����
6$c"R			��7��??�������3�%�N��x�N�;"/�m�������>f�'��b���i}�:�e���P�4�8z�(Yi
��C��[B{}���\%OK�tK��9#T�u$��7o`�/.��,=x���A�}������)�V�Z����������f����HS�Y�����d4���R�D	5��o��������T����7Z]�d��8G�f��t����WF�G�^�60,��(��-Z���TqeTT�j��5k�@��J�)D��j����-� �%�7��Dy��!��;v�(F,X��#F�-[�Rt�����
*8::j\�`N���7w�\���4����{��������*7n���r
��P%Q3<00���&$$D�����c�hU�56n����)*Y-[��]5��2V�����'����)R�`A�w���S�`����:w�L)j#���	D���[�����C������-9s�����"{p
�P,^�j��w�y����E��E�����U�h�������['00�#R�:u��m��`2��-B�
�����?�j��Io����C8����"��?h���c
j���;e������=M/�h��W��W���H�s_!g����k��.���"F���QQQ�{�S��������>|������iwq��&
�V��Y#?""�B����R���������[b�R���\8ZO�^���k�^�����o���r��0L�F�f������}Q3Ett����iW����td��w�%4vOh������ @��x:l�0�8��J�����/[�l���|��uGG�:u�$%%�Q�X�"4ooo?}�tL�I�&)-��q��Qq(���#�����#c��6��g��u�V�8��QR3d������X����x��T����'<x���B�"�j�)���p
@)�?e��]��"����?��rvv�3N_���B�
4{1�s��%?0�)���|�|���l�����+>_�v����s���@]�����CwU�V��*�j�V�Z���b���������C�NNNw�����|�����]X�!�X[��?�_
���b�!QQQ^^^g��������'X�l=������14h����{������w���;v,�S�+�!�B��0:�1���?q��]������{�������III��C�"��-]�TX|���������i�(88hn�[��������O\�z��2�'����P��2d�����0`�����:���6m�(-�� RP��uP�"""�/�y�C
@^����4��m�n�����������#�y��
�L�r���b�	b��t��JS|�L7tK�?^!y�1$bW?  +�������g���p���:O��/���p1�p��]��_����/������%5tDFF"����>|�Q�������1IJJrqq�_���Q���8��?h<b�|�
|}}EUxbda&L�����Q�0�U��!>>���JS;w�D��q��1�-			�����:��y��{�N�4������g��zx{{�1��4vK��nI���Ez���A����:t�`�?�H7�RSS1��E%43>�%|����l��dL�RE��B��������dI����y��I��R�D�L�����P
����CfS|��aL���,R=z��]���/fv@:�xp�������V���Zy���_�Q�|�������*�����������<Q%Fr�D��e�O���{����7.::Z:~��h~���b���y������@�-T�	���W�^���]�t�$��S�N����Z�j\]7"##�t�����.M�;wNY�����P�N(_�#r���>��z��Y-�>b�$+��-�}��t��x�����E3(��?��*��2�����.������������ Z��y3��Lp�N��>��>$�
O�<��w��u1���3h���.(|�
*���q�'�����[�z���<}�4
f�`K�?�Jh���|��U���'a���s������>x��F.^��xt��k��[�_��M�)�/^��[�~��5kb�����p�
8]
6��


�dNLL\�p!���Y��`��	��888���G<B����e���?�����gt��D�u����a�L7�C���c�V���������u���P`�Z�����K�`[������[bp��
����������B�������h���|�����n��Y�x1<m���J��n���v����S�2e������pjG4h�@�|�L0��}
��,���}��%��4�k�|���O�>x
��1�4'�%7n�x��,��L��19j��aoo?k��9s�������N�:��J���1R�P��7����/_��e�s��;w�P�Yy
 55?D���i�suu]�z����4p����~�I:��N~���*
��Z��j0J{�!������w�����/������'O������<p���������M�6111
Jk� ��)���x��������
�)�� c��:������;w��U�V��+���Jli�>b����[bL�]K���G�Y�tiU_��/��v����O�.[�����[yb2���B�g���Z�a������� '\�Ig�N`��������2�\n�/^H_��~TT,L�f����R�:�/�[�n������8�j7�9��d��"c���K@�9�T���)����u�R�
�
�H�zzz���et&�@�jg���[�u�A)���766Vm��f�k���@x��C�6m�Z
.1m�����=�P��HSyk�.]���p��q��O�>�Gd�9`@>�������SX[[�]�v)*�Y�q�(���n���N��z����������<&�I�
����4l����Q�i�S:���2c����F�q�F���3AAApKD���AJS�hJ�,I��OHH�r��6����$�k�����t�����G+���-[�e2���;w�|������h�X+����;t�0y�d��+$���;f��p��Bc
����
�hn4h��=~������[�Ik�����4�3��5��}�td���j)�����c���,]��Kb�FBB��F�	�W�'O��<y�D9I����(���G�����T ���v���������-IS��.]�8����J�i��}{������;y��t\�}�Oh��vK�Cjj���[�%����[�&
KS�N����s��+W���� T�������0��^���|DKz����� &<����g�kzi\F�LBPP�����:x�@bb���s��1��}8t��E�MX���/�@)n��%����������3g���P��1�0�)����>}���Q�o��j��4����$%%�o�^zXQZP���s����===������f����ik<�X�\9,�k_6�a���>>>L����_�U��<�������w(���'�},R�Z�Bx2n�8WW���_+(�ynoo�jlW�m�6j�`ccs��1�Kg&�[bd`���1d�������i�`L5j��Y3�5�-1����:�Wh�������)@�H.\P�6��,C���a��a�/���%��w����{)����o������Aa�W�XaDa��E�A��{B|||������9s��W�\�i�$����	�w��H�����l�;t7n�0�h&��� �Y�������S4"M���0&
�h,[6n�(�cm�������cii��+Z�^�,T������;"@899q�Q����s�,1b��i��'O�\�F
.��3S�L�Z��A8`(���5�(Qb����V������ )b���

lNL�:���/������(��iS���
vK�u�����};L4��������� �[b�<y%����|�A�a2o��5M���49r�h��_����s���e,y��2��j���X�Hz��������K^�pa.��'p����m�����o�W��7o^��s��EZaR���r����63������-��'O�������<y�h<p��w�A����3���B)��Ok��R|��aL���>�l�r����
�888\�pA�5kw��Y9�����C���~��.O��=�t~��	%$5�������1N�O� $,T����.��p��y(�c���.]Z�pa�\���k����t"��4t���g���������hC-�8a \�^�zI��L�A�b2�b��Y����Rk5�|�r�4J�h>�[bL<v��]Lo�p!O���������)����'�}��g��8`�|�r�J����^m��}�V�J�B�~����$���V�Z����9�������t����x��[7%�54������6�	>��?�^�
����
���:}��xZ�D	�9�'����M���g�U����w����;���W��_-/�GvF���d�)��g�j��'��0�Iccc#��SSS)����@��H�O�LRR���]�������O�/��W_!�PK���jc�h. p�1c�U��v������/��
�o������C�j�xL��9sf���E�������� �����>�Uiy����c$o���@=����������>|8���t��tqq�.0�����t����&�%�>I�\��f����m�u���!=����R�JA�p�j���o�>g���T�P���]Zpi��1S�N�u���3�d�+W�P�0����p����u�����#}��e_�t���	������tss����xz���a�s�	��cG�`�5"""N�<)O{1���7��j������D�O�>��??�����v�N�0N�/����<x�Z
�������7��1Q�*�i�f�������[�=���}�|�2]�����?/S��78	s���[.���h�"��;F{�����(�k8����r�Jza��UT�;W�\O��������t����e�Y�fM�6M:~���R�>P�B����_~��1c���+T�>W�X1::������"Lf�w�������5�v���s��	��hSY������kS�R�T)�VVV����K7�-Q'Tj���3&��]�N�<icc�w������{��a��]�,R�H��)��������n��Y�bE��e���s������D(V����_�����Pu.����/+T��qGG���0*�q��!�b��qWk��������L�Z
�k@Q�5�����m{���P��#�^�������0���b��������$e��%�?��:�N7��������$�Mw��R"��0�y��~+p�>|(}��v�������SQt,ju������t�#d{���5��d�n��abo�����y����I��p����4h@����?���r��6�5���CG����9�E�9���r��
i�F��e���?=��mMl�p������(Q������+Wh$&&�Q�Ft��� �����NNN�sXu>��3��(B�*Uo��������a�'	�m=���E%5a����!C�^���k)�(��n�����-��B����������W�Pbt:����iSy
���W4NYJly{{�������aCkk���������DQo3�v����\���I�	�H����������^�z�{��wc2�7�n�����o���n��Q�xq�!
(o��;oS�AX�Z�j���K�.����3c�l���.l�3�kg��^��?�h��c�1�S�Nnnnp�����\�r�=z���f����2|6�o�9�	|�����BUjI^��SY��G��$�����?~�_T3������;[YY����M"�AX�y+jt��.��+W��������7�c������n��9x� Eg����-�tc��]u���V�����C��������W�F
��,Ybii��eK��,�������������w�b�tuu���]������M�>}`g0���k���f��;w���<6o�\�~}��^^^������������O?�$�v��Z! � �J�>��93**j��yt�X��B�X|�����


UP`3���'X��^��1����������;::�_�`��)�=���X=<<��*����
���7[�n�X���#kW�\��>���}�����1W�T�R��&L��y-�8���������
"kJ.\����V{*Rj�g�L���S�f>����e�y�����e�
�
hnXYY���|�����3z�nIV��[But������;`��T.��h^�={��V��o��[b(���W�Ja�1��K�H�Q���������'&&**���A
�1�R!66Vm�����fs
���h�b��a��������H$$$P�c�*�;y�d�$5C�K0�����m�>}����s
�a���~��b���g�=��<v�X�f���6PAW�~�%{��
]�/ciC�������}S�����g�����V��1"P�hQ�)��:s��I��hii���������#0�z�j1�E	1�
:�E������Q`�O�8����	�%YDn	�\�2����������(�o���U����wo???�4����>44t�������h��x��/����(!�9�@f��I5j�����q���x���Bb���h,W�u�V��n��1��X��v�����[:P-����0&��/�Y`���iS�J�����qy
����'�Ij>�[��R���b��t�������a#�A�����f���&?����_GNz��2eJ�*f����l�������C�5k���%?����s�`\A	���S�n ��J�*T���Z��^�f
F�������T��]\\��A@|��5Jc�������*(��n����[Bw+�,����---W�\����@BB&������O5���yqwwWPB3 44k�2e�4n�X����3�V
.,����o_q'K���s����===�����������i�.R`I�+R
�����������������{���'N�Z�|��I<�@�V�bcc�����J��}��goo�:tH�A�y��1�K�0�1�X�� ��2�_�z��AjzU�`A:\�}�v��)^�8E�r���>Pn�b=���7n�����������ay��=LG�J��H��/���CN2]4���U�W;;;|���@[Z����[�naY��-L������������n�a��[���� �?�
*P)	��LLf������>�|�?55�@��k�VP<S�3��+W.*�
%�-3����O�f|��Wd������>����HNNN0/��m<����*1b��i�����Q�w�������4u1���N�3f@��:u�}���j�������H�VP`sb����p�7/�}�6������M�r=1�1c8�6 ~~~AAA��g��Q@]�D	�\o���V4;;;>���,Y�hz��A"�8r������A�����LrC�N�?�������)4�t��4U<�?r�k����[7^�x1~��-ZL�6M�Q=1��_��z���
��R�-1 ��%�/_�Rc��e���������w���s���LT�h������,Z��k��UBRs���������{rrr|||�V�H��.�"����A�����s���jJ+O�n���:�By:s��u��"iN��Y����*Th��J�i&�n)K~����%K�-9y�-J���r�����H��SSZy
���{u����#G�^���n|��!22r��-�.]�X��t�\�����a���acC�6��Z�3��������?���A
�lX�=z�V�[�n�I$m��J`�#�6l(����k��]�h����e� ���������4�e�|I�������Ty��Q��u���J�.-
�Z��3��s�Fbcci�3�$::�R'����,XP�"E��3�������[�j.M�4	f$MuL�v������9����/	vK�'SnI�����i�/�����?~��$����4~���^Q�|y��N�����i���u6922���C4�]��v�vK�!>>��u��b��7\>�@�j
UBLssU������]?�����i��<�*\HV`L�O���C1����J�*A��+W���{�0h� ������"�i��
8�9q�D�b��1��>u�T��D�i�j�}�vz����rrr�����"3c<�������<~����A���7o����C�w����3i������-[�@��}��1b�������=�����b!�7]]]�V8�La������G����������iLv��
/��������3]�H����)����`��M�6���
��};MqL�8��Y[[#��������:�-�vK��u����t��H�f����=CZ#���d|(���)M�6MLLT���	s�����s����J�3N0�p��(�j����upp�_����o�=J����o���/++���%�t;n�����;�p�(Z�j��a����bn��OWZpS%88���F{��i���S�>�i����g}��F��355&��qm��e����������mll������X.��/������P�vm2/�J��S������^1�0�t�U�Ap/a���x
w����47o��������:44T��M-;j���e�zyy�n��/ 3&���{��M.���|3���y�_6SG����.\��o����"�������k�"E�/�HD�"�|��[�E���U�Z�}��������D�{�����U����g�z�V�^�5�tf���VVV��e��'�Z�*Nd���t4�����?www�X���7o�i�F�(��<y�DYiM�����h�Y��BU0V�*�/_n��i����o7���BU�N�:�SY<pL���H�
c����'O
K�����&Lll,�\q���NT�o�A�~�A���[�.�a���UM��
�u��/_�UhtC�Z�n
���.R8i
�aL�ASZ�-c7778l��)��s�.Z�(00P�v�E�j)�1]�-�"�)��O�B�j���Sd�",��!C�q
 ��v�}��K��;v��q;vl���x��,���p���/W���������������^-�3t�P����m��#Nd���t�����666�}��x��������3�S���i�8K�30���Rk|��GGGx,0�7�b���f�a�A���[�V����U�l����uK)�L����)#�S�9!R�r�:r����4KK�N�:)%��#6�Z�l9p�@���`�vK��(W�\�����Nd)t	)���Ed3w���q�F�����T�%U�T����s������:u*&���,����9o�e������?�Q
���6""B������M�6����s�5k�.-������9*����XYY������7orJ�a� b���+���_IJJ"�"88Xi�L�����
�sBz`��it�����������j�'�L!6��/������S���nI!R`��u�8��d�WD*3���#�����
��w��b���J������������������G�A���
STF��D(\c
�����He��3�:VGG�����+��G�V��'N������_���o�o���z.(*#�0�� bm���w����}c�)y)����r��-?��0&�HPT����~~~j��G&L�?)��5k_6�18��d"�������Hh,���I)F7��;�#GX�A��j����
�-Y��������111<�U����WG��S�NA����w�����y��5�J��0�%�����Pi�J��[�����i�&99O>L�.`�����/_k3e���6h?�y���O����	��U�V)' �0��!bmx�W�\����
i��v�����G���A��������=���7�RRR�yn���
���%��V����?��������a�U�V�2e�?N_/^�X�H����k��������z�����l>Pc_�gy��c����������K�S����r�����(��q����sC��7��W�^|}}5��LfIHHpqq!c"��?e�<��8�0�E���|�����$��ys�J��e������_?*	����"���?�TZ����gAAANNNVVVU�V-x����`�D4�%�L0Y
[r�������TKKKQ������P��[�|y���}x������w��I��5m`(��-�e�|��������y�F��������W���K�S�
���WkQ��_Q��O�>i�g���%J�(X����c���n���/^����;�5
����
T=`�����]5j����0����@��bW�\���ZZ>�S���������e�r�������+���G��%���[�)e!K��,t���G^^^�vqqy��������B�
�W1������&M�H���'O��HO>�=��;w�L�����U�������J�*��pZ�0t�P[[[���3�����(Y���idd���
f�����/��3k�,�he���RKR�`A��l��T��~������{�nXX� �Dr#�0���uc��-PZ���}��
L��A�S��t#55�\�r��������S��%��I��S�r��
�E0aN�>���L;H�����������=���,]�vU3>>>���]�^�z�p�B���{����UK���}��A��|q �TZ��_~�������8!!!T����4�o�V�V�?���;w����v�Z�:u��@�"�A��*Tx���r�'�a�kO�<YiYL�2e�x{{g��/R���F�a�B�Em^&c�n�
������&RK�,1�`� ����6n�4 -��0�?�/_&�P�P!�d�>>>xz����f��e>�����#�%\������w��A�}���?����KeDg�X�v-���o/���[;;;{{{�f��X�������(�����-Z�����V�\��O�M�6���*&=�0�b�f��q�F-��L���^�3�����J N����|��j<��hd���0&w�������{��.�j������B`�$Sh���^�aLi�p������g��2 R������������G�Rc� T���3�Oag����/� R�::t������S�0�� �&���lee�X�r=1u�T�k����+]���0�gL��{%�0a����k��?�H�|��a6&���:��m~�[�|!�@��������kggW�vme3iD
�T�R����)��),���6l������������e��%���a���G�!������988x��q4^�~}�\s�������Q�.]�*(�0�7@X���SX�:u�P��c��Q?�/^��	����f�����e����h��)�g���B)��E�n��)**j���������\8ZD
�8qB��3C�6l����wo���������r}�|}}�O9�0�|����a�j��	�;v�X<r��bi��g�����_��>}�]R�a>_M�a///D4^�n]X���d�B�bcc�.,�0�/��O�eh�����-�����4vK�/	�����������\&�H�Q��%�Rx���`|����@�������-:c�yy1&��<�S��xh�a�a�����666t6@:>b�"���y�t|��Q��k�q�d�s�W�^t�.22R>x���1|||��bbb���*W�����|����T�R0����_����0_"��u��0��?�����������VD�9!R,PZ�����/_>~���e�������i�&���0�0�`����
X�z��A���u;w�������oii��ysf�3q���Y*$�z���`���3,,�����K�.mccs��Ief�3���#���dL���[�|Q�@���9�p6��3��_?�d
�a���F���;v�X�bdI�����[G���a�sc���'N�B��1		a8��e���D��e��$99�{������^��<p���j��I-������{�a������n���9s�6?�)�4vK�/	�P�+`>��'O���lll�����������[�)��/
N�����������?x��:��YS�rp
�a�1E�s?~<e��6m�|��w���J��0�I���+�)�������x���aR�={����|�����n	���)�������;}�4}������`�48�/_�tqq)Y����"7&�`�a>s�<y�{�����K�1`&S|������D(-�K0���F��7?��
���"""���4�y�&�����3~M�����#�(E�y��}������K�,����o_������i��aF������K��tq���W��H���O������Jw��a���ooo�$�������x$M���bd�����a���i
�����2e�������a�
�
�l���&��;`1~���Oo����uk:���S�N����r��y3���R�C��1�V��m���c����~�m��iF�a�a>�����c!k����!C(��\���e�&I�k��z��������SPf�a>C���mll���aI7n��&^)���O�9r�i�FA�����-)����������a���������w���}�N�:����*U����c��)$�0�9���0�Y���9s&���3����A�n��0�0��FPP��������klll��e����M����I���P��e�3���;vvvU�V��4����G��X�bR#�0���[r��U2&���WHX�a>/=z���o��������4i���L���	[�r�J�?�3g-]����2����g���s����ppp8q�o��
!��K��5�1���0�g���7��!�#��+F�Z���g����c����C++���(12w�\�$j)��k�������=�a�2�����?�$���������a���A��\|��W666�!��
0hmm�w�^��CBB�h���F��a������Vakk������D��{������x����?	@���0��h�"i=������Kc9;s�L��%)�� q��a2�v��W�-���

�����1���>��0Lz�[�0�����?6660����v	����V�X!}������599Y	a��|>|8?8t��LLL�Z�*���N�>-��������siS�a��d���X���m��o���^�z��y�����i�+P����_��9�!+-/�0�)����r�J��������!C�Q��-��4l�!��Q���a��vK����� ggg�.R���_�>}��4h�`���?��S�B��g�~��Aeef�s�������p9`1��x���P�F
�[YYu��m���&L��+���[tt��23�0Lz�z�*00��u6K�4�]�D�j���Q�u��)'&�0�;�����qc��[���C���?~�H�6m�T�T)x�0&0)������2���n	�0z��~�%\�+V�pqq�����G�QPZ�a>[V�^���HW��Ro��1b]5"j�����#�e�am�������cG� V�����'O��_)��1-����
a�������GSRR��aS���a�$�@RR�������m���}�VA	��������x���������c����O���w��YT��O)�����r	������F*xC���c1PT�E�D�F���"*?`�0rKD �"�`	Z�4�"B�3�9��i9��7����O}����g���Y@2��i����|��E�%���-[����:���^vvv���#&����sqq���?>c��]�v%N�O�&�?m�����K�H�%@����_�.]�}�������=G@ �b��u+W�L|a��-�����2����W^IKK�^R������[��-[�#�����uc���������//�������s���4l�p��������(�2eJ����4''g��Y����e	p�N�:5v��
��d��A���f���a�N�>�o��������,��@rZ�vm�v��J��Y�O>�$�Jl�^�:y���{���������7��7���g_u�U��&M�,_�<�����H��-'M�TXX�]\\of �{�n��5m���7�����#���+**
_�_�fM�F&L�\��C����������x�N����_��?~|�_��_}�{�Q�M�6���-Z����_c�$��>�,###�A%�������h�{��������>
5}����k�n�����tUUUC�	n[���k��9����{��������3��$�>� (�6m�F��������n�w�}�[,h��qXL��q���[��a���iii���~������w��(--���c�L��u�b
$�������o����"y���/��:uj������@R��a���������;�����>�7o�|������+����c����I����_�����z��ZS�7o���
�������������/^�8�W�<)��,K�zT������GG#���S�7�������qc�@(��������7y��7�'[�}��E�@�X�jUff�-�����h�3g�0 ���1"�t@j������{6lx��w?��cu/�����es�B.--�����aY��w�}7(s��
>|�k��m����q�5�\����>�kR �����j�*����S��-�y���{���C 9:t(X����W_}��������NOO�^v�+X���+�'N��`��	����>{������/~�aPI�����|�����?��c������L�V��������#G���HR�����?���x���������S�
���Z�n��/���G����z8��^YYY��&�
P�����O<Qwv�����</}0 �X�����c��{�'NLOO��aC4��K��n�)(&�5
0����[o��h���a���[TT}����?.((�����b��>I"X�{����8p����w���A��~�-�l@
)))	[���Z������O?�t,��bY��C�edd�:7�W�^k��
'�w��+�Z������B��/�����"�j�������_�����m[4��������5*�l@
�Z�'O>{�l8x����n�-++��=.����9r��g����K��=g����hj��eA1���8�g����^�vmI���:�
,?����`��h;_J<���i���q��Q�����;vlp�{������x�����)#j���c������NAAA�&M�.]w4 eX�Qyy��W_�	����o��&���eK0���\��3&77���*��@2���/����I�>}�W�����)S��?KKKsrrf��_^�WD{����A�=���.����;�b�@��x����~��=q�R�e	�W�z����5[�dIee���������ndee-[�,�����H��-'M�TXX�]\\of �>|���/��������=:o������\�k�.���Y�&��M�0�i��:t�N������

<w UE-�9s���HU�%��n���A�X�zu4r���#F�-����#G����w�4o�8�1cF|y�$�Y���?0T^^��{��nt���������7n���;���+��pQ���z�\<���N�>��K/-]��c����jjjF���6m���u#+V��;w��;�$�}������3g�3fL�����n�����{�
G�������x���]��P����z�\<���q���'
���%~�3T]]��W��������	����!C�^�w��+��"�`����>�[�k�B�x�%@-7�pCx�G}T�����><���gR���~��y��\dff^��e�g�fG�u����[�������}{�Y����w �Y��D������~����[����������m���k��{��{�OYYY�@��L����sg�)���q��s����Hm�%@-Q�S�N���O�:t�P�F����S4 �D-���WWW'N-Y�$�9sfL��o*j�m�v��u�����o������
6�HQ�O�>?��s8�s��6m��������7�
E-�@��}y��-Z4k�l��qGRI�h������?t�����=z���;�h�7�rrr^~���������C�'jt��i��9�����g�kQ�������q�RU�x����9w@�Z�l��z��&�PYYw UE-�#F���/a`��q����;���m���e���������������;q�D� ��'$u*
endstream
endobj
12 0 obj
<</Type /XObject
/Subtype /Image
/Width 2048
/Height 987
/ColorSpace [/ICCBased 7 0 R]
/BitsPerComponent 8
/Filter /FlateDecode
/Length 47494>> stream
x���y�U��?��*&�SSI�����&S&�`M��S5C�����T����IfB���)g~�

" ��( �!�di@�"
�
AL��M6�z�W~g�3w^�fwC���?��E�w�9��{^����{���c��m�������~��_F'Z�|y���2Z�~}��1c����
}��������
����~E�h��������Q&N���#455�^��W�^�q�}����g��U��B��?����z��w������m�3����y�����}��mlll�s������,���u�������>�lr&���?X�fM�O7w�\�?@�:t(�i�N����:{����jjj��\��C�?e����nU����M�6������6�>|x8TK�x����}���
n��5QN�i��B���Q������(Q0`@C�Hee��/�u�w����/oC�?x���C��z��7���
�����?��'O�,t_�<�����3gN��92~z����UUUm�����h�I�?���{�G���_mmm�������Z����*x�?��m��V5���3gN�������[�n���_���!��?����~��4iR����h���zB���������-^�8���_���O�W8y���U���?h�����'�|r���s��}��7���r����y��=.5jT���{��=`����G��P�mF�x������d��}s��	��{��#������Zb����Y^z���������q��)S���O����W�����;3.%�m��u��E�����p�3g�G�=x���'�qH>f��JKK�~���[���'���E�2������.��&*9~����K��~�p�!C���1c��]/�%�MMM4�P�3��	=�:ujYYY��_�p��g��iU����|��m��o�'��s�V�W��jn��)��hW���O?�t�P�����z�J	�c������
�F��cU�c����fk������
��t�����g��v�����yp-Zd����j�m�����lF��>,�������|��Y������'Nlhh�w�����m��g�����r��{���G�<��4iR�#����o����'��6�����}{��6��3g�������={�l��������z|�h���9��n��a����n�����@;9s����(r��u){�|~���{_x��85
5W�X�q��5k���%%%Q�O<��{�������q2��W�I�&�^�:4����=�P��>Hi�6l��`��������.]��_�z�����$>1��f���Q�Z����={�S8p��9����,Y�$t,9�Ny�"[��y���|������Z�6v��e���9>���k���(��z���/^�������#���&�������7o^���g'���'ON������{����O����&4Y�`A�W����|x����g�6h[�z^__����HD|���__��8������+�"���s����]��3O=�TUUUJ�+VD{KJJ�g_?}����c�
�����K�[__/�:d��#G��4?x�����8:e����q��_�7����7 f����a9q�D�|��	�j�H3s��p�){�?>b���B������x��Q�FE�9��GTWW�g#9z������$�6l���={�$�z����]�y�~�����\���&~X=H�(G�_QQ�Z�ti�}���0w��ho����=�cH������o_�'k[��q������^�����fk��c��I���hWq��/��~�a<���o������2�(f��-{������M�6%���i���Wz���o_������t���@<{��Z0�6n�5_�fM�[%��}�Q�:�*���B��1���G���i���D~����Thnn2dH�������mS�D���
U�4iR����j�+�X�!�ja�:3g��X'�pQ�K��4��B\J��a���a��]|�e����������8�'��4iRT�h���&���J�w���V�
JKK�jc��M.�'��6mZ���oL�>=�<9����or*^]]��,���j�S�N�'M�a>Y��Z����gq��T�q��q��#��6Dr�~�l�g�I�
)[�Ow�g\3:�w���Z���3�Iq��g%j�K�����GG%�7_.\\"�/$-��&����������}{�u������&L�*,[�,�a����s��!.|��7r4_�reTm�����q�=d��lm���l��g�����F#��������E�vR������)�'
#��B8fT!�>�<J6l�������q�������V���s�S�pq	�����L����f����R\b�����E���}���SJ��@����Q&9}��hf�^�ze\����9�h���9�y���8V=p�@T�&:t(G�������8��2eJ�������8q"������={v������;q���;w������'��O>�d����_����F8Kryr���;�d;~�+�"���/��bT>g���W�	z��f��T��[�0�K����D�`�_d8}�tTy��Qq�������x��H�������[o���Q�7�|3.�1I���id�c����q��mn�I��>�_�lY�0��	�����v�W�^�=�����+**�W�}b���e�x����b-��O�<����UD�^{���0[����O���#��%jjj��<���r���?�6mZTXVV�\��W_���X��� ��}��8:th�R���>����nq�2�[�n�3N.���MOe�������^J�?f������������������d}��	�?|�pz�O���/���q��q�-��s���'�I^9[����?��r���;,\����r���?�|T��3�$W>|x��{@���q����x
�H�	a�)M�������m[��<Q������Q���G��U����7�|s����N���P��,��%�_�vm\�-�6lXT>~���y���q��-����V9\z����8p������#Qa<�U�DU� ��%�KJJ�C��8w}(���xV������9���'����yyy�j���-o�����7m���/����M�T��?�*�q�������?��3Qy�f�i���Y|�������r�K��/$M�d���d��QI�}
�?�7�����-��o�2eJ�9������O<�DTa��
�=W�,C�Km��-����j����g��ZUTT��U�<y������_RR�_<����s$y��;v������S�F��C�c�Y����q�.�1/K�����|�����H}}}4T����k�����?~HF�|�������X��Y�f��\����&���T�,}�~�sss����p>�Z�������{�N����o��5���o����\��������l�m��7F_�z��:�e�����N���z+��x���j� ?��K����x�y����������Y�&���o����lG�v���>��������'O�����y���s�����<|��I-l�������#���)�{�������m\X��������v����N��l����}��e;����A�>}:G�t�o��A}�]��?��V�^�S;t�PJ5�?�UUU����idss���?�-�?s�L�{�����K�_��}��E��o��F�f�h����"����_}���I�5
�}�����M�������������<�?S�"����xn���=��������]c��
G������3�<���I,T���O��{U)(_�������D�?~��A����"-��`��q2�2U���'�03��ysJ����82]�reJ�{�������v����7T3fL�k���G�M9���{�%�)���_�������I�����yIIIyyy��7uuus����<��S�	v�������1"���� �u�oX\���WTT���/x�����ad�o��u�����.-E�������6i�������x#I������G9d�>}>����
q���o��d�����^�s���/Z�h���+W��3gN�H��������D3��{��6m��u�6m��j��	&�mG�q�����������D4�%���17n\|�a����7/\��5kJKKg��K8�[o�������RFII��3�oQVVz.!�0����������W�m�x����g�r�������������X�$��$����P��F��'�S�n��%�y����w��~�������UVV���k����NSSS��7.e�����%K���+))Y�vm�`O�81v��lm��S�VUU�7l����]��������>}z��*�x����NiX�����f����~���g�O��;��l��|'(]�)s��.�V���>jy��o4���U�������_{<]R����?�~���'M��������G��3�W_}5���S�V�^����4��������_�>}���n���g���F�z��'��8v���K�f[�B���.������%�s8t������1���O�^����7r����go��-��������C��c����3�����2dH�sEEE��~b���[eeeS�N
����o�����e����[eeet�#F��a�v��/$���]�2V���������Z������#��+���<�������#��+��Z���q������������+���?�����~�
7�p����q��=�\h�Rm���=��M7���S�/|�?�pEEE^��w�ygQQ�5�\�1�ohh���������_>�����w����j������k�q�w����8�>w��y����� ��6m���O���o~��W����*c�����������;w.*9s���w�
g�������r�-W]u��%K�����un�������\��7�����N�>>g���t��w���\�y��Px��wF_-Z�~�{�Ki{�����U�V����������c��������Hi������|������2|}���B�i���T;vl(��/~�>�>A����������vz�o~��a���[�������[�lI��r��P~�}��_��2��.�?�������a��+����������S�������]��_��2���f�
�={�L����~7�Z�hQ���/9|>x�`J�]�v��.]������;��?���wG�1������ii���^#8�����ukI�@G�ik���e��_{��Px��������;��m����w�}w��y���:��-�=z�hI>��������g��wt��S�N���o�9�rCC���_��WWUU���?�x�6y���j��
�%%%��s �����o|#�o��=����4�s�=�������<�@J�n�����7�_�����3f���7s��������_���B��+�����[o����h��q�q��E��777����W�^���]���D����������kT������������<��C=���|&|�����Cm������+**���{��=����P�s��\EEE!�:�hn�����/�����&L�p�w\w�u7�p�]w�5s���������G���;u�t��7?����o���xe�[���������)��6{S}A�p���B?�����3��cn��z�:���U���<sa���h[��� }��+�����f���36��m���B�%���i(x&\���	�s�?@������O>6���}�+�����F��7��7�?tLM�*��=8������=:��P}(���������M�'���`����'�:�����O�t4�����������7�[���gSj�m���������s�����'��������s���m���ZE�O'�D��u��[��
0����<�������#��+���<�������#��+�{'��5�� �=C�g+T��py������cSk
�������G�W��7�|�1l��5�/�;v,���S������g3V����T�+RUVV>����^��O}���s�Zss��W_��s��j�?�x�/h�)S�$����G_+++���~�����f��?���o����1*y�����]w�U��m���^u�U���q��;�����_�^mVZZ�H$~���&�[�.>���C������n��O��O����~�����'�BMMM��v�u�]w������^z)qQ�u��w���?��7������P�Zb��y�D�?��?R���Y��G����''N���-[v�5���eee-9��s��@&�����y7�k��EEE���oa��<�H��g?kI�����#G.!�&��;w&����������C�o}�[-���8u�T[�m>A�>}����c[�d����I�=��W�����k"�x��7�w���������+S����&}���K��������k:u�TWW��w��	�D�+_����G������&-_/���{�&�[n�%�����x T���s������;�_�����S����@�����D���n�V���~��i��{��7v����_��C=T^^��N@����bG�>��9�^]w�gSj
���/�4�?��X]�>?S�1����\�=C�:�����������n�?�����?����s�H��g����9@$��3���������?�c�=�j��e�;������x]���:�v�&�C��G�6�k����=
���d~m��')�6���B?��?\y��p�����G�W�?\yN�m>�Q���z���7n\"����'���{�C=t�M7u���_���?\QQQ�^�<��S�D�[�n���o~W[�n���^[TT��{��������s���7o.`���~���'�y����S[[{�-�\u�UK�,�����z��


��M���_�%�H�^�:G�E��:����R�����P�j���� �j>�`"�(//�Q���u�M��R>v��P��_��=;������%��3g~�;���?��k���/��/��������q�����:[�lIi�r��P~�}�����'����}�+_�������|�������/~�����^T��_�z(��J����P��k�|w��g��=z��;wn\������N$������/������S����+�w���%'�Y9r�r���p���k��&�H=z4|���K����u���c��,N�:u��n2�����H$��������;|��ysJ�e����=z��@��r�-�Db��m����?>O�<9���a�ByIII!:dVQQq�=�<��)�(**���SUUU��|��D"�^�[�n�|���y�.�


7�tS"�3fL\x���������={��n����������M������~���g��3�*l��*t_ O6l���O:�Ht����?��<���~6|����+++�j[�l��������w���g����+����>WQQQ�������i���?��O����v������������#kkk��=��#7�xc�N�n���G}�����0@����������l����g��h+T�9�T��:�;��������Bw�Cx�@���u�VY]���W����=G��@�t����cM�`�R�=C��������G��2����@���a����o����=�\�=��� }���� c�����g�����(����_x7�?tL���/x>Y���U�2����+��p��@�$��?��������c�����?�
~�����1���O����n������'����_x7�?tL������_�/����:&�������^�M���?����W�/�&���I�����+�_����	�����Y5��2��c+�&���I��q�{�.���O5�;y��kzN*��FV�=�?�0��@�����g�>�������R�"�D������"�QTboAbC�(�Q#*���7�I�D#EK��H$�B0����(�4A��.,�y�����_g��2��<�����c�����w�(���C��?��z�z���c��Q�s�y�������=k�G�?�O$�g��&�~2����yez^�>��I�LX(k������?d�k�g�ws�X��|�Ee����t�g]�9iS�����?d���y��@�����q����1b��������H�>�K:�P&�L�M������O}�t�����i�ygSx<����c!����M���G��_�t,����n��mI:�X����������D��?�3?���uI��:����_o�����?�=�}���F����K$�c7$�q����[�n����=���U�V�Re���������K^S�^��i��yBQ$i�����'|,Y���}�9���I=N�������?��V�X��U�����w����O?��3��c���I�&_�utM~~~���U�v�v����d�H����sn�?~��`�v���geeu��u��5QI���c�	�����J�������L.L������������.�I�&YYY�~�i���^z)�k�.z�p�������N"@��"���������������p'O����u�QGEO�O��v��=��~�����s���3�����o���4hP�t����i�=�����;�f��u��������?�h��1�������?d���{/''�Y�f�W��J�}���m�W���S��={y��Q���� �����������L���/��U�n��3f�HN�0��SN���K�.]�*|���*U����5y��$"H����s>}������8m��N���]�[�H_�����r���V�Pa����3gN:�_}��YYYW\qE:� �L|����'|Lxwf���X�;fa�x���$K�~;nA����=�,���;�/.�7;�n����:+++�s����/O�]c��	o9����8��@i2���o�8�� N�����u�:t���������7����#G�w�r�)e�O�����z77���X�����q���I��nc��ba������u��)++����kn����m����k��/�����[n���c��������dR{�S~���]��A���������k��9������T��1c���+W�<�������W[f�wsx�Y�%�X�p����tK���>�������Db�zU�\@)Z�jU�j����N:���vd��5[�}G��SO
����]t����V�Xq���I��2�'_mI�����)�p`��p����J��������w�q
6�\�r����;��i��%?�y��@�1��������!z�:#/�p�����������x}f^"9��ygS�|��rK"9����_(���|�L��d
sS�{����]/lL$��?�!���I=�~77����@����z�?s"9�e�?~���g�(o��������������9;o�������(���_�����������Dr$��U�3��R>_�0/
?]�f�:�����s���+7j���.�;wn�A�7q��������N8���/����U���{�%P6lh��Y�
^x��T��1c���������c�g��qYYYg�yf���]������'P}�����z����?��������K$*�$N8�����)S�*���B�I'��HT@I|��YYY���/T>m��P��]�D�Jb�}�������/
���93��j�*��H�>}��y����`z���U�����G��	������P����N�:eee���{��_z��P~�)�$PW_}uVV�����B���{o(�����
(��_~9++��SO-T~�G��w�y'����������������*���m�����`l@�M�2�z�����'�p�%�\r��Ggee��_���I����~z��6l��r��M�4����-Z�tP@���������t����o���I��q��U�T��K/59�_���+T�����'Hy�b��k���I�&5j�8��g���tD�O��7{����>�^�zu�����������(��=����^�������3�$N�������;��k�P�s�1�3�tD�O���l��>}������n9���>����#�|��r����y����������.��2��������
J:�rd���]�ty������;w��G����7�@���
���ttl�<f!��k�	���3g6n�8$|�}��Z�j�!�5����t\�L��7z�����J�*���~�n	9o��������+�]{��!��>?����������'Q���c�=6��Q�F��7o����M��*��y�B����y�^������V�\�`�9����W'W&�s�U<��3��%��\u�U!�am	 6|p���{�m	 N���n�������y��?��
T�R�@Y[�hQ��
�7o>m�����o����{����-c�y���_�b�N�:}��7[�}`���9�����-c��;d��s��Y,���W�^!���
�:*r9���_���{��Y�/���
>����]��_A��m�-cM�0!4���|��w��������o������C�Xr��o��J�*���%�xq��j���u��eggG9����>�����n�����x�y����W�F���������g�]�z��w��ue��];��2���l��MM�49���N���;7�{���``���l�����B�]�v�������/^��s�9�Py���Y�&��2������/]��3O��������K0�L�e��-Z�����S�!��*Uj��Qrqe29�]K�n��<��_|�@<B%��7�t�o~�K��2eJH���>��S'Kq
=��F�����x�y��x����?�p������w�}W�b���.z����C�|�����Db�Tr�W^y%�'#F�(T����_v�eyyyK�.M$��n������;�`a����<�����~����.]�����c�d��
adT�~�P^�n�~���Z�*�3���l���a�F�����s�%Uf{���Cn/���B��;w��~�m"Qe69�]K�F�.�����%�x��7/$��'�?[��#�<���_�_��@����g��[��K��F�a��,�y�>������{l���;
.�\��Z@i�3g������u��-��k��Y�h�����%d�����Zz��~-Zj��]���Q#���i����oIE�yB������C�T�
7�}��G=��Uk������i&L�Pp��q����;.�������Kp��O~�af9�������*���C�O<�DPn��q!�W\qE���/�<��A��"��	M��5���FO-���w�
����=�����;�R{]Z�S��[�j�\p:��K.	?�-r�������_��W����C=��M�J�*�q�T�[�.���������Z����S}��0���/��0g�y����
9����C>����`���d��5�4]��]o���n��E3u�����
5��k��b���L�������o����><]�d����-8���Z�*Tp@����7���h=�>}ztnW�����PZ�<f�M�[�nH�{��W���^��p�BtCNh@mi��C��s����M��%�<����u�P������zj	 N�]w]So��!z���B� ��2����M�6�{l�i�����K0�3p����
*���;��'�pB4M���|�����W�6|K6��!�1������C��m��v�=��h�"�?��h���Jf���	��I���?��F',�v�i�;w.���e��h	��s�M.�Ls������sHu����������X�":A���N*��#�10`�g��n�����=�XH�o��TT�-������B�={�9���J���.m�K��O?���W�^�\\�l�K�?���~�+7���.�T���{������a�z����i��EOC�/���h.���eD��[�f�-[�DOW�\��e�h��.JQ���w�}�a�5j�h��A�
}�z�����^�T�F��:�a�\�R��������8��5�t���>�H��'777�����m�Q�F�`��eU�qpi�?~�j������^��~��0 
�]�tI$��$�em���3f�HM�o��i�^��!CB�?�������x�-��efY�`�����S�?t�I'���nK����+�|����1��T��'�}�Y�D�aWWh	`���u��
�����tZ���������G��e�BK�I�vG9��S�-���=;d��G������|���;����y����?����7o����h��P�;�,l��q���_�uY<��S�^���/����3�H$�L%��5I_����!�_~�e�W�|�I[����wX��GE�]��Wo�[s�k�.�����b���G_��J����&":��g?�Y����<f��>���CX�Z����Pg����u�&������?T�q��	&O���u���F����?te��m��E��"}�>�hHu���?��O>��+���i�������[������M���&}�-
�~Q��Z���k�n��i�7q��1c��-����v��m���ea����������k6o�>�}��M������Z`S�����C�c�f�2v������O�P������4���?�|����������!C��Mt�I���f���{�
�������~���|���e]�
5s��5hD��s�U�P!$��c�-t�uhX7n���{Z@/����~��y"�M7�T���s�����;��c�4r��3g�����ht�Bp��w���K/�4�/�����Q��5*t�srr�;��&M�D_�}���wx����{��GF?�GF�E��!o���9�]�v�����.]������1l����1�`���B���>���o�����j��E��]��H�J-h��*|>�����N��+�8����?��Dtd���=�PY��i�<~i6���	��k�����d����"I��5kV��x����	?�_A�
����23��y��������9���g��O?�4�;w�\�f��
n��fA��R��#��zz��w�����+�H3D4����Gn���GsJ�
����S��m��):��w��J�c�r��&M���Y3������T�\y�5���_�
9M�����*��-[Fg�o�����n
Y=���wx�~���d"����v�YgE�������k(����wx��CRBk����S��d�O���n���/�y���F��q�i9r����	=���������/�X�T<�z�
�{��7w~�W\�D
NDS<r���8 ����!�4���������'<�����<������9�_���E���Y3\y��WF;�����
6l����{w�s��<��Cv��w�}�p�{���_�!C��|�����'�X�/S3v��T�wrG���C�e�V�Z�z���>��C���O��G�y�n�����B;�]���p���_-�,^����q����!)�~x������-[�����b[�bE�j�>���[������������9$��^�v�I�-�=�M����^r��D�n@Il��%���3�p��4��I*�����F�a�����&N��&�K���/�����2�_Z�l@���}�>k�n�����k������a�<f�wZ��M�����<���G���	&������,t��������/�<�t���}��(�������w�<rk�W~���]�t��_a:b�����r����?���6|���[X�re�L������Ep�=��l�{��F���B���P��g���]�����^����]��l�������C�����B�
4���rssC����@����s��+��93��g��m���B�_�~�f�������Q�F��P��&&��i^}S�T�7�����Y�f�Oy ��K�����~�x����{���>a~�UW�#���<~�wZ�N�z���6i��M�6��{o�K
6lXHxt���.�W��0a�k���d����(��v�!����>rk'#�P���O�8q��u1��Q�<f���{����%���}��;vL��4i�����Tw��/��?�8d��N(X>�u��=��s��o�(��|�2h������x��3d���o/X8e�����+��2��B�
�s�J��C�f���*C7 ������P���/�?��Y?|�O!�f�j���n@	�u�Y!��.��=�����w�$������Y�����\�2�X�9�_�PJE�PJ����H�J�/�K��
SO�Y��.���s�=7�9��hJH�c}�"T/��?�����g������h/�5j��={����=�P����a���5kfgg/X� U��_�"$9''�������O�E��-[F���?�v��&����w�
��g�}�����5k�t�A��A��^z��^X�J���W�^�r����w��|���������;����W�������@h}Z�n]������+��\sM���#r?
h�4������������.������]����$B�2y�����LG<m�����M�0��K/M��3c��J�*��Sg���QInnn�=����SO�J�-[f��$����Gy$�4�{��CI��d��}��'�����Jf��m"�$�<���S���Fw/�s�9k���JB����
���G%r�Z�ti���Ce�/16a@��/�0�@��h4����&H9��}������O�����i@������O�%Y�/�\��M�6W]uU��e�NGO�>�A��G�N6�L%�1���[?����%�/����U�VR!e��k����������R��vZRQe�0���]����^�a��%P���Cwxxe���O9������X�fM��
��c���f����[��IL�9��4~���y�tZJ�����t}�%�h�?<���;�(��S�����>}�S��J��W���i��J�*�����OyP�����(���DJ���o�=�#������E�5k����o�����;wnh��8�_%�M���
7��t �H���+���t ����L?
h��<~:-�������������@���������G�o��V�����n������Z�hQ�v�����'�%Q���<��s!�]tQ�F��&N�X����������#G�bH�x
hd����[�����?~�F�D�]r�%I�k��.]���w_�=���e�-[��(''G��Q�z�8 777�Xvm��������O?
h��i�)�i)Em���Z�j1�����td���"����k��q�!����c�9&$�DtQ���K!o}��-�������`��y
4&���G]��!�c��-�{�}��
*��g?3D*�b7����Qj�<�	���cvv�|�t ��K.�d�G)����~[�^����]�6��2X��#����6����A�l�WB�����N
�L�z9/-��-��i@K�NK"tZ���;�D��]��)������1�H��MI�x��+V�5kV��%�%�~�sssCe~������+w�uW���+W����E�j�����7o����������������Z���^���+BG=�a.\X�af�"5����c�����c�����Kxcx��4���:t���g����3fT�P��c��-������v�w��]���[n�!�L��=z�x�����!������?��3B��|��X��|w�y��vrA��h��i�:u�-[[T���_��4���TL�<�m����><��4N�tZ4�%��?����}��!����N����/����~����_�~�d�o1]B�f��X�b�������P�91bDV�5*�YD�8x�����s�)��#�8�7��5�t��
��5+��^�z��x�R�w�����e�].����KP��H������:�j��V�K��/	�����7o��i��o���������j��$��6mZ�|���/^���F�.���Ol�e�"-�y���3'�-[����B2����5��(�N��T���O�%�C[�J�6m�l��%������?&�K���k����^����W��}��MD��W\r��/�s�����s��+���/���#F�Y�&��2Rh
C�X�F��?�n[�|��G{����w�g�}V3Zl�7��|��=��s������)���l��a��Ma���wv�,YR�V�f����NIi4�����+������������s���4��[7�mro���b|%�B��a��1����g�������GuT1��L!/��b��y1�����*���vR
����}��T���-:-eM��'���o�|�����8��?��~T���+U�4w��t.=z���Z�lY���[�hZ�t����+j�)�7�x#T�={�L:�r�H
(���7v���s�����/y��t�r�}�������`����&M9rd���tF���z��q��	/|�����W�S����K�����w���������;��4#�P,�_�����7o���S�L9����]_}��3�<��o�����Kr^T�z�
�-������l�l�2�h�4�%T�N���tZ��N�O��5k��s��
��&Ky���+;;���ON:�r����u���C�����u��=�-�0��~�V�X�]Y�n���{��������*�-X��u��+V�����G]�B�tF�r^$[�l���K|��T��	Z�h:]Q��M�y	=��c�	u��E��y���D�x���4k�,���c�4���H>���c�9&5����[������#�Ls	@�KH�%f:-1�i�I	����o�1�@���={������IR^l��)�0�j�Z�dI���r��s�V�T�������O:��B
?}�V�j��}�S����9sf��d�������^�5�1cFT��Gr�!���GQ��N�6-�����}����MSB!����}���'K�:th�M4�q��;��3���s���s�m��%�X������(!������O�%q�bo��M�^��y�R�x�����x�����<����b���K��������/�����J:��B
���k�{����.�;u)�h���^z�`��5k:t�`4]�.]��y�:u��V�h:N�<�L�p�]w%K�Z�bE��U��m[���g�}6J�%�R-����H�`	 N:-��i��N�O��I�B����'�.o��Mi�ws�w���e�S�N�n����������3+W��W�^�����[W�!���OP~~��e�
�A�M���~?zT:�s�1��o���0�vC]Y��S���������T��V�<,I-2$��2��o��{��Wn����?��F@I���[�G��p���^K4��+K�.-����������t�y��!�o��V����B���G��N:)�%����7m�t��v[�|y��u���B�r�q�%H9"��b������K�X������2�����:*R4������{��wG�CW�R�������O������)�������m����@x�y����y��e�M������U�V���;�3�7�e��!�������/8�i	�L}����sj"��P�GK��zk��e��/�h����k�.]j�����X�ti���W����u��\�2zI������O��'"|��(��C��ys��������&M��m�K�F�
���7��2[�
�e�]r>v��2������r��t����:��p��Jh��%i�4����
6�x����l���9�����p����F�e*�9,��/
����^{�.8�����-��d4MJGs��X��rK4�y���G�� .��[(;����{��>����:i��z����Q#\0~�����`?���������'�.m������\�r���O=��j����6n���>�.�i)S:-��i���w�9`���_�5b��xB�H�O	 ??�����X���Y��	/#��v��5�}����=z����%K���U+T���}lf�t�����>��5r^*~������������9���T�~n��U�a^^^�y��������^�z�nU�V�
6�p�
�Pb���Q��t�	�a�r��S���B��u�Y��h�,O�D��������UW]����F�?4��~���]v�����'�x"��_�~�����z*��:th�2Keg���!�!�/��r��f��]�v�P���%��2C��CW6T,�����S�;\���n��[�n�G�N(�Lr~��6j�(u��W_}��k���
�6?�i);:-1�i���i�������W��c�=������/�T�%�)S�dggw��9��2R�F���f���e���)�c�����/�vOx��{���l�)���HK��	���;1���������;V�R%��������PH\A����n�)U�y��_���04C��F���7_�pa�Qf����c������nx��7��O>�d��v9�f�M!�P.��{�����o��f���Sw�����y���~h4M	���������*�5��?Fp=z�(x����]�kA	��t�������L����'����g�-xq�7m�4�03G���t��U@�Gw�@�E[��Il��e�zh���'N�X�J��R�j�����_u�U��N���R�tZ�>�c��	]���g����<����$��HK\pA�r��)���-Zt���<7��������W������>�����yI_�^�t�A��d.��%�%�9s��h�n��	,3�����c�innn��z�������5t���78i����'�Sya4���_&e�X�`��~����EGu���~^z���C�����k��!^_�i�&Z!-����0�8�������>h��}H��{��}��t��)-8�����;B,�3��!C
��No�����C�~���gm;�_�~K�,	�6lX�
n���������tH�����p������������.u�%��p��'W�X1���'��:��#��z��7v�}����^�zE�;��2����_=$s�����7O���+�������-$��g�����RG��@��o����"�g�}vH�o~���ih�u�e;��G�/����q��8�L>�!��;w��/��#���9/�PQ��g�>}�5k���������Ox`��YaDY�V��K�F%o��V�*U��%�h��
(������PIf��9n�O�/Y���N�M�R��W_5m��A�O<�D��3�����m�����n��]�-ZD�g����999�r�>���j��}��7���;���v2�N��/
��b�4iR�g��EO������w�.]b�2s�y��!���w��i����_{����J��~Hx�x�t�M!���0���M:�][�I����z:a��h{�.\v�eI�����n���c�gT�o?���{����>��]*���r���~�o�1g��x�^�z!�!��):-eA�%~�=�X�mBu�h�����p���?��SB�Ce���?�����I����o��v������������W^ye�K���+��i�*�0�I:�����/���{�=h���o��i��i.P$O<�����SO.\��W��S�F�����c��a��d�qt<��/��������������������=z��Q�F�%�/����6����k��q����_h�:w������aC�m��`��M�~h4��[7���Z�ti����qD�bEg��No�J�j����7��p��C=�I�&��A>�����B���\sM���y�u��=�FBx�����`�HBs�y����:���
�&��@�F��>�a�������o�q���<��s��?����E�!��[��q��;��y�QzC%5G��R�tZ��:F����O:������3��J�~��=���@	)���_j#���|K�Y�jU�������E���tV�Z5d{��5Q������_Z(;!����ROg��e	~R}���'y��g��Bh��{����>������
m�5g��Px�-�$r�����B&����*��-�)a4q�Dw*��S��a�?4�6)Z!�����!C�T��oQy��=C���w��'�7o�2�1�$rF���w�s�c��Jn��
a�>��>���{o�v�P��!M;����;�R�J*T]���#F������	��9F�29v��T���SCcZp��R�����(�4wG�x,X2|�)�*�7o^��
-�����G�%�DDG�l����Z��M��������zKe������0�,x�%�I	�}�������K����[�������xCg���?�7�4q����A�EO��������|�����,���?+oz����[o-t�G��?���(�GuTjW�%K���F;\�z��������J"�Ls����
<��y���P�����NZ�1f�-[��|���G:���^nj���.P?�i��-���O	������q�B�
80d������n?�������NK���];~��P�|�������!C�-�����!��^z��/}���1:'�t��OK���~�B�CK��ya�}�C1|����&�4iRj}6���h�<J��G2���O��~��gFK��O$�L5r���m~h	 �iv��A:-���7v��5YZ�����g�u���nG_q�����J.��1s�������o��;��6m��E���(��{����.V�z�F'j�B#U���h�W�^���1��.:|���D���;���|���?�p���3��~go�!d2d��7����;�C�^5jT�1f�_|1�7$y��*���
�m������FKU�T���O��4C�P�%T_|q(�T����Cw%~����sL����S�:C��w�0`��M���gN�(E:-1����^�T�y���I9Ke�?��O�m�
R{tt��7F��.]��y���@��U���I�&{���/�)4�'�xb��j�����?�d	��]x���odY�ti�5����z�����v�p��GF��.e�AB�Z������a;�b���?����Q�F�=��~{�g�-[�D�,
:t�������w\��|q�)��(�X{/�Q���%����bo�
c�.�DE%�����Q�����s����|w���.��y-w����2�9w����+W��@����P(��,l���.L9s�i�@������]c
�6j��+�J%��w��mR�?~KKK���U+���������l����/W]����tt���2��0Pl���k���EL��U����w�5�F�����3f������4�����wJ;2@�=~��.����uSu����h����C���E��O���<�[���My8?�p�%�,�wA����]�F��L�2�����]C��=���O�������EO�>�����j���[(���S���F	 K����|��}[�(�:���s�[|2�������S/���9R���y7�����������8qb�
�����o��K4����~�Z�������������'O���o��!:���18p�t�J������*Y�����|mR;���>�E?��z�jWW�"E�4h�`���X�C/_��q��X���:��8��i�Fi9�������K�}XH

`��=�f�s����w��I������]�����E�W�^�����JWR�:��T�R,4�J�o����)��y7������#G��5j�h���C���s����(d�3����j3!!!�s�~��-f���Y�&?�<~�xQ.T[HNYx��E>�����x�Z�(Q��s�m�6�#}��UnA	 K���������T�-�.]���z��%K��������TJdh��c���t�.I����C�5��=���\�����4�
�b��abK�;J��t9�z��]���Z�j��3�G��m�x����R#M��W%�����|����{����Y�)�E	)�-�>}���7��|G��C%����u������y#����O_=z�N���xs
�����j�J��Y�fJ�G	@���d�t&-qqq5j�����k�������/_>:���H?$-�	WW�B�
qa���������d���_�m���q��e��k�N��A�4�G�%}��~*T���� **��������E�E�O�:v������hQ��o������'4A�G�J�J�(K�:u*osC-�����4i�t��6����|�5��-���Z����v�tg.�%���/_����e����+W�!�������=GF�e������-���4e��'O�*Uxu�
p�E��x��I�&k��Y�dI��%MLL�%MF]�z����w��9[�V-�?f�Z�����(�����o�>�������)(z�h���t���^�
�������/b0i��M�6����N�F�Iot��q�9s����c����]��2��IKV�P��{�������������hr���2
I��(?�3�.��E���������w����$..�u��tn[ZZ��Z�jEWL:�n�:�x�z��{��=q�����
54}�tN�CCC�-J�JWU�����siH�{+�7�i�����3�.p�����)c��MWO#a������W��}.J i6t��i
�y��-W�fC�������W�^������7.G�&\��
J��yt���)B.Z������A���M7o�|�����sss��������r��irQ�T�j��������;99)�^[�n�;u���]���T����O�N�0A�\&f��{�_�h��g5A!�F�������4Y����%
>>>>|�488X��������x���t�n��19eQ:��R/
�:t����9�����E�tJHH�y��R#������L677��;e<����sM i���&-4��bff&����+-i

UjA����k��S���H���c����3'��
��o��!))�F����t��e9�>|���6���3����k����+���K�,�Z	�M�62uS�Q���i�xZ��������occC�E�}5D.\�d�^�z�?NNY����9Rvr��������]�v��E�2'$$��o������J��d5��\]]---�/@���4�}�#�=S m|S�g��=�HHzqTm�E���c�(H�?���w��)g�] 9�����9���
����U���e���"�R���M�4�3\i�M����;v���{7n��
/
���U�L�j	@�;��	�X�	2I��d"i����8���w��
�z���,YB#�z�j���E7���3�G~��9S�N��f���8/[�L��?�L#������������$OOOj��E4���,]��~={�<q��=54������P�-�Yb����o/���N4�)[��?��C�W�~}��|���"E�����.�KG���#[�
H����-*����
)U��t�L�&�y��EGG��SA�DS!J]�-\�Pm	`�����#���/��$}}}��4q<xp�5�w�N��������Gi��E{��M[XX���Ku�J��d��%��^�����6
��3�X�b�)����7l���q�
,Y�DlM�e��-Z������1����V]�Rm��v�*
&te�P	4��E�������;yu��P$-���IO^7o��)�x��)~?N���
6�$S�2��t��������v����-��������������#�����Eg���s������������G�����	����vV�\)G
���wi$'O�,ZBBB(KW����`�^�$�� �y(���'wbvL�}���i���
�������A��������K[P�Wtt4
����h��wo�b��/Z2D�qSlY�f���ziJ�C��cHZt%�DDD����HY�J�>~�x)�^��c�j����t�M�Dq���(...Y��
/=z��s���}4�K�*eff��];^a�������J_CH���r9{��h|��1�Ok��%}:��
*U�D�bbb���A9y�$���I��G�����o��F��
6�hW�P�Y�f��l�6mT���<�;�b�
���������#]����>l�0����rw���
"7o��z���� #�����(�5k�l�������
=z��7���,HI�)�"q�.]���O�_@��(�I��!i�
�d�`�Q=��<��X/�>\�x���;�f��kh���Uka�	}�����i��'����6�@F���/t��u�(E����������t'''l>������w�����o��BCCy~Z�xq??��������U�cs(�x��	oBB��'��wtt�����H�"�z�������4��<\u7"����7O�n��'66���E��\�v�Hk)lRc��M������������B�z��K�j(�%���x��kP|}}�O��i�F�P��i��Q��#���)�������^v�=������LMMir'Sg

�Y i������h����3v���:�d����]�I��]�z5��'N������k�.���?��@�xb!CT����`��Q�F�F���V��9����o�+W���UK����#~2J����c�d����_�>�j����.�C-�KB�Tc:�MLL���D��X�������|��E:_x����Y��i�&�g��O��~g����>��������s�z{{��)�~.422�h�H	����s
Q�^�iZM�e��I4�J�l�����9�PDD����)�9r����|.�����i�2T�_�L�4HZtI���_@��]jG>9��^�dI��������5t���+V�9sF�t����N�8Q�M�������� QL�/^�.]z��
����e��&&&4	�1c���i�@[bbb���W8r��>}�P�����x�����R~�-W�\166������a�}��r�T_-Z��b��o��-���������/Q���n8i�@�(<�����Jq�5k&6�Q���*T������zhxh�)`��~��%�|
KC�F�K�i{���I������]�e������u�7CE�k�\�Dl�����KC�F�J�9HZtI���_�L�~�:�j77��S������� ��n)� �i�FOOO~�466�J�*�R�pa�jRR��Q�r`�����722����q��]�+��Qi�*���.����M�6����8�S+@&��Pijs��a+++��x�y�������V7o��)R�r���/@����Z�*MvBBBDctt�x�e���J�%��AXXX�"E(��T�]��O2����{.����r���0`�M�z���<O�<�/>t���A�n��%�f���v	`���vO�M�<��.�-�	P��t���B9��%K(
���+=-��(6n������a������i�����L�&������D�%$-Z�r���7m�TZO#�j�����#F��#�Bi6�JQ�S�N4�:t2dE��C����aC�u��U�G����S"�����4G������|�O�6M�������u�W����s�C�LV(�N���%���Hj��o���(R
,��Mhh���������ck�����9��k/�F���;�l���:99�����?����{'j��8��DS�g��)�i	@�}�t��l������?�.]��V�/^�haaQ�L�~--->,_�
A��})�p�B��l:���[��*S+t��
o�kb��5|q�a<v�?��T�o��5e\�+���q;�J\)����H�)P�2���tV�������,hI�,��d�%-����hh���|#:"""66�B����w���V�Z�������tU)E����[�>,Q���@Moo�"E���S
�������z���-[�H[(D�l�R��(,^�X��s	�Rt������_�,Y���z��]�u���,J�633�($KW�����E��*Uz��]rJB>s�L�����oO�M��=�(������z���W������YS,D�^�z4��J�������9������������mJ'k'O��,K:����������W�^�?���"111O�<�Z�J���"��;v�������w��+V,�|���7{����jK�	J�h~���&nD��6n��c�(DEEyxx���U�Vm��MxPC������S����MMM�M��	\�\9���g��M
A��-�������,���%$$DDl,G�ut�T(]�vU�C�G��Z�7�m}||t�MC J�N�Z�~�����(o.-�v~:�)!!�L�2JQ��?�0J��n�j��5�r��R��O��)&&�A�XJ�.-���%�v��Q�R�`A�mYx�$-
��"��`i��m���Ut��5�{�]@<�K��E)Z�/\�`aa��I�=z�l�7����[s�Mc��������7�)"���������s�fi����yCW(J��M9���W���q#�������ibb�d����x}^�xZ�:�HN���Qv(O>~��n{��x��4J�������Y3�%�C��{HZ�Tz����kk�������rJ�E����)?,����&N�HcN�\�R%Q|�������+x@Fq�bii9~����G+M��6J���/*�&����Ce���@:��W@����cy��{n���~S�oA:�@������U�(jK�Qj����g��U3TY,X�r
�����;4��_�>MF�|���.Qz6�|77��3g��Y����@Y.�F���e�h�MLL>|��O���C���C��=����t��.i;��7o�{�[�~='`����
�����Sfbq�����<��������'N��~���~?:::o��4������J��7�i�q��}��%SSS�?�HZ��Y������\�r���O��7���VPZhnn�w�(��\�����~#�hgg��El �E\��A��GQ�������K�W�}�v�&MxT�pa����~Z%Jt��]�%�@	@
4h��!�����t���W��6n���s�H�E���ieeE�z��E''�:u�p;��Z�zu�] ��%�q
���l:����Nr����'O��	B�7m�D������}�foo/b���#e����0aO���/)��������OOO:�����Jjo�3:�i���.4$-Y
I�\RKZR����va�L8p 
~�5�Ng>}�a_�b�IDa�Z������A���C��@��Mu�7C���3r��Q0W(&&&C�����_����"����S�"w7
�(��YS��^����u�=�������2��������%K�S�B�����R8s����y�����[�������G��166�h���(��i��}��rt�p$%%������J���R����?h�:������aC���u�=z���~��m�<��4�����2e��N�;j����#G��	e�4�@�KC��n��E����X�vm�7�A���d5$-�H-i���J��?h��7ox����1�Z�Q�dd��2�� ��i��/��/��7�&2T(U�6���5k���:��G)�[ZZ��7C������h�"
e���t/**�����������������too��u����(""���sqq�n�~��-kkk~�N<�����2e�P&�]Q4����kD���s�%�M�����=�H�e���4_���8q����I�%11�����k��W����s������e�����d��U�8a�9zj ������[�0���)
|Q�4�k��C��{i$-��}S��h������s��h�`��~
5�k>���H�e�(:�w����}{wwwJEh��=���a@C�/$$$��AAs���O;vL�n�����_�pA��4c255����n�hh(i7n�:�����O�Y@l����Xt��c�"Er������x��]�v�����%J�:t�L�5ptt�Q��Rl$7n�ppp�vcc���[���3o���	��D���Y�f��4��>tq���3Y��z�������bee%}��&t�X�Bq����Q(XPC�=�X��M�	���_G���:������]Rn�g]2��i�.|��q�\DFF�1�f���� i��C��c���C�O�R`I{��;vP�8p��zhx(t7k�LsJ���K�-�/@��7s�����
�v�W�N�=���D@@���-nnnb���%����@�j��mii�h��e�������$���/���F7�����8p��~y����������g�������8t�P333�lQ��x�����w��_�$�]�v�F|�S��tV

��m�����_�6mr���J��q2��Q�����3���������0<x� 9�	9t�ou�#e��'��M�o��b/�*�����0hI�,�������a��4��G�.P�}�V������_�_��7"""&L�@� �'b�1��.]��0RH�����C�t#������@����888P`�j
��-[��Fi$]R�=���B	��r@�!4����+W.$$����v�B1�t#���@���v��)����J?�����}���F0SS�C���eC��l:9����7o>y�D����s�����[��Nr~��i����l��5�nI����T�v���c�5�<Z�R+$�l=v��
�)�	���4�svvV=�g�>�Q�.$-�C��HZtl��X�n��?FFFV�PA���wo[�v��k�&��;����T%��IHHX�`A���T�1RB��DXX�����{�-����%JlD��fF������q�����J���2������~%����o�u�Z�R%i��/�f�d��}={�1bEK9�i ���k�.//��k�J7:W�={&S7
��9shxiB�z�2[~C���	[CjQ������/mY�p�R	����S�L�I�������x����S�N=���]uBGI�t�Q�DRR��j���+&��f�����*$-���E.HZt���-����K��.-����W�^�M�����i�hx�������O�n������cjj�����A��K�i�(�:t��K���4���	�B�����/_��EZ������===,X%O_
E||<�y�'P)��y��x�,����)133K�B������i>4:��������]{��!����]�v6
z��1?M�h�o��!���X�L�x8@�UuK ���g��HYtQ�ug��Q�������7ot�=C������N3�z������JGUK�9UR[F�-
�bB7o������M��n�Z�������N�6M�����i�����~�}�	��C�"#$-��v�ZL��9
i�r���		qqq��shh��=5(^^^4���W=[�N��+�Tr3���G�-Kj%���������"c��y�;k�
(P�P!�#��}||��i�������Rc�i�����[W��]�v�I(�<v@����'��Q�K���5�LEN(- K�=�)SZ�CB�c����������VVV��/��?��J3�k�������j���K��������WO�}��7v�����9s���7�1{�li`�P���;�(ho���U+
,4��\h�����F^�������hx<�z��}4��V������C�";$-:�}�vj������������t������y�&M����ea&P|7n��y��y>������gD����J����e���H� n�Kw�a�1�(QI�V���7o�LNy-�����G���m�rli��q���'N�(kO�RBB��1c�JNglxx8�s�V��i???:$}�2!����O'���3F$-�h��M������{��~v��xJ�&Kf�=z�������[N�S2[�Hi6M9X���i~��������Y'}��^m�i��tH�M:�;t����+W���v������k����'���W/�'u�%%�����t:v��d��}� �>}�'J%�����������[�N���7o�H7M��U�������iHZtI��!i�KLL���'/�=v�X�B!���L�25k��_�����;���;r�
`�.]>L��)S�$���srr�������J&�V�������_S���P����+W��
��P����!2�={��-[��������2!22�F���"6�:u�p���iT,(*����-:���Q[�t������@.&&&�O5))�O�>�s:FW+�k�
�:u*���y���<y�����y����!4�t���%J�X�f
���)%iKKKj�T���[������x�U+.\X�n]���������z#Z|�h�a��I��!11�c��4��|8���L�����hB�w�;u��+�9�w*
���������_W�Z�X�b|@HZtI��!i�NP��hC�\�X�v���������J�����?���Q#�c��'��I�\>�LWO{{{�W Ch$)z�HJK������
��5�U�������)��<yR�H	d��u�8�8::>z��)n�tE�
�~�/�7n������7�F�R*P�R�pa�7�@�����C�����I'k$�����l4�z�j��K����/_�	]�(����h�O�>����+V`��������\��[###~���n�r�
]�r�,������f����&��Og��E����'m�z�j%��M
��L#��Gcc�C��?����F�g��X�9������x~�����bW(����/�)7��
&��h���\�r���_rw\�!i��]B��{�7o�P�B��e�/_.����){��������s��M��s�N�Dv���b������������S����+���2�.�c����Bi!'�J%���@C�������/>|�p~�H�w����O�>���M�}44|z���H������\�2�[[[o���c�������J�.��_g������M��(������)(�)�P��t�:|�0���!C�����,(^�{��%ft�f|4�vttTJ C���knnN�����/S&F#��eKny��-���_*M:�4@4��_�>
f��yU_�D	 KU�^�2�������S�R��g��2�����K�,���z��m�z������0a�pHH7���o�d1)V���'���!@�"$-:��E�����C�i���)h^����V,;?p�@�?>|���� 11�L�2�+(P������/-RT�K'�E�������a}G���qc��>>>			qqqbY���
?~�/����I�����5R��?R�����se����"�!5j���������U+�u�\��������e���;z�(������2�������4�����g�z�R:��t�IJJZ�~=���+Q��y���j��
6,w��%J��(*_7
A��)����oCS�T)�M�(+�Y����i45�W�/����?JY���c��]�t)g��bfA:��?��YS�P�3#���7o�	<i�$�"��[�h������O����Z��EHZtI����s�����������n�t��F�Q���������}����������������[����l9rd�b�lll6l(cW
���j�*i�����m������R�J/^

uuu��A��?�N���PNNA�d������v����?{����U-$��3N!��''�q����M�h�E���QZ�l|���(|��������*�i���f������F�Kgic������O^�4�;wn�����h���Eh��%�%J��)J4���{��4M�U����;
����E���7�����N�h��,YB�+��P{��%� i�
�2K�&`HZ��[�bE��������=�M�E	 **��~�b��Y����V-���U������l%��i������Lc��M��������ggg<��]i�@[N�>M#<x�`�CC�E	�������lz���J�(%�2e
������/[�j�+���}��]���C���o���%<<���.]����&))I�P�)S�T�G������!��"�@c���%h4���?������}���P#U�V�����w��b�����������U�
�6�-B�����?�K�R����.MH��d)$-�D����///i;��R	�����G7l��;�C�|����_~������p����xqH�@_~���|�54������U����oA7k�+�i���o��^���1!!A�@�f����+@T��!�
�����4Q[x���L�4@���4��U���J�*<E�\��4f�����_;99�$�f�������}��	M�����;����@����/��"��j��4�t�Q�=�����#{h��.�&(V������b�)��'��)��-[���;w���`�<m	���S����O��{�����=4xHZ�����MLL���*W���n�8�U#��d5$-����CWO:���/��Y3���%�P\\\�-��,��UK���(�k�.22r�����������d���|>�W]�*V�����-@��:u����F����R=Em	4D	y���E`��e�����(�)S�����/_�pA��cZZZ��?~\�����njjJG)��?
���f�Y�������/4������	�6m���1c��;���W��7/M��>���y�f�/�v��.]��%	��,�@V�s����{s�y��L���?������;�vvv�+W������ (����|�Hi���w�R��i���^6��E��|����X�jU~�������9�X�IK�B��.�A��'
&���z�%-���y���)VST�9Q�2ex�6�%6j�(�l`��{�?~��������E���kc�M���8�������V��]�N�������+L(���d��-�;��j����-�h���4�W:Dg8��>>>�Z���|�0���o���Ui���F�{��\����S���S������Ld��{���}��[�����_��-�d�nv��U�������l%�[�`A��e�n'&&����9w������7x�`��L��O��m;r����s��'

�t�n��K���oB�A��]��������'�F:��
��7&#i�*$-����[��}�����y��]�v4�666������Vd���ki��Y#Z�_��'�R	���G���7338p �*���;w��H1Dc@@Gr��(�,V������4(U�V����94��g�6J����(Pf.K?
�pJB��M���j	���4������c�	������],�D�N�:4�NNNJ{Xl��)o��rt2�g��	��KM|���.@����s�������/��j��m������
��;y��_�%m9t���G�W>���KNy�����?����yeQ���.Q���w����fD	@:�L8z�(��S�N>|����_�v����r����p�.��6��-^�XZX��E���E`��'�>�y�f�bPc�N�"""�S�2���W�^-��@���E+�>}��?�|�\�r�G)n�H��-,,�[��d������g�:::�}f������S[@���
*���7_�zEYJ��E��@rJL�n:i�I������n�:n���|��mr����}�R&��g5A����P(��()E422R��(��?>����o����o�Z��/�jG�EC6l����B#��cG.�P0����������/_�lcc��gOY�����4t�������&}�_�K�Jq1������)�l:<<<O�<e����k���o�*������g-���_\�T)���D�<D�!�>W�^�Oc:�U���������y�L0`�^��mE	`��!������N�:�HY\�&|�]�o9�.\��+��n i���q�8���U�j'�{��������{p��Qkk����7j�H��v	4�7o^�
�
�����+�����G�������|�
��=;i�$�Xd]
�������N��n�:Jf8�P�����������������H����/w���9M����J�,�4����_R+��������0a����M�8�>��=���7o��s��z�5������+�Xf��A1�o���QQQu���hC�M���
�����v��m���
m�����������wu�7�K��4]��/FDD�.�z����-[-Z�J�*s���������_�fMN������G��t�����{��*TH�h����}||�h*�T������s��o����32� �(K4h�,���iokk���$-���}�B���<o��J����Z�hQ�jU�V�g:����o����~��'^��o���S�Fa�V�Z
�.,�m�6�<W�^��7n�����[ZZ�uE
]�~�`��|�n,�@�			���v�Z�|��YJQ��>}�dee%bK����/�BF9r$��������]�[�n����H�\<E�����f���\�9s���=z�!J�t�1� f�g����������G�w*�����������>|���o�^��Q�1��L��
��w��`�<:t(��jw��������;f0���N�2z�h�C(d���s�����F���O�P��m��'�i������E�p��1^�o���X�"���E(�\�r;Ci��)9W]�%��s�������\�r�K��nR�N__��M�R`WZa2�����pi
�w�����Q�HP����	QP���&wE�k�B&�l������}��}JG1�C%J���b&��_R�+W�����k��|���_@	�(�������C4���^������a@�"�46
%�%K���7�q���������_Js������J�m�Z�:ut�A�4w�\^�����w����\Qz{T�(�Z�j�U5w�����w��R�~��Ey///ic�%�>�E'�B�����z�����2���#J��u�}R��nnn�������wz�g�D��'��4*Q�����w���_)C��]�4i�����T���'O��~%0H������O����H�"���&���.�@@@�,�2�>}���g��C'��'-!!!�#E�
`�BmY�h�x�_�����Omll��+k
Y�%�?���j�����g��
�H[jl�����XcY[��hnnngg�SK���Ur�����;Y�	�%�`999����O�>-w���i����lz��)��@�%^� �������
�C+�T���]��V�%���0�/V���@�4i���d���QMt���F�u��#G�,V�}622Z�h�$���r�Jtt��!C�G�)6h���4�E�	S]�'66�����G���K�i���fff���X��k�P(h�]\\�
����S*N-a>|�L���
��k���Y3�e���]�g��qtT��R��(fN�<���_���#�'}�Rig=%4�<x0n���%���K�DK\jNX�s*�t�R�_�G�,--������V i����u���X~0!!a��)\I�;wnr���U�T�!�v�q�4���Nl�5�O�:E�V�\)W��	�����k�������]�*y�"E��������~���=�X�"�
�B���
6,P�����3���U�����z�j���MMM���Z�n��i���(������?rwG_Q��`���E��H/^�����1���I�,,,��;'ww����JZ=k�,�����������;9�)�#F8::�/_��j�����������P����{�����
��h?|� �W�R%:D�L��F�7j���$�!bc������+� ��O-AAAu��������n�k�"������M��}i��q���\[����~y�����O?��S���(�^�Z����C����^�:%�u����>�l�'Q([�,J����gwww��OcHQ����(�r�=��9$-�9.��3G���7���2�"����K��ynmm����/^�h�B���������oRL�4����r	��??��������U�����p���ysi���z�������Q�������+���_��E��O�.K���E����3f����E�>x� 9e������n�����w���5k]@�<OJJ����{�@�EDD����b���$���T]��i��P���a�h�V�X�?�t� {B	@HZ�������_�������u���-[�����{�W�^4z�J�%ww�|��:t����5kLLL�������=ruu���+P���c���?��?~�5�4t��E:����s��/YZZb�3���Jo��>}�~������/o��]�~}���?\ ��/733����]�������O�QPZ��6b��������51��r��n:�=%�
��}��?�(��1�������n:�=%kkk��.���&(J�f����G�|[�M�6������c�z�D	���S�N�/�8q���\Z��H``���#����z����hy���7n��,���?�/���W�^�}���"x�
j�����~�����R	 22r��%�{�;v,v���Wv��IC��@j�W�noo���#G�P���i6��ys<�MLLL���o��%wG�����)���i���qqq�]�{����BvC�
e,j���4 i��C
MLLT�n�s�?V*K��(8;;�*UJ�4�J%�@�.�l�211Q�h�������e��%��t��U)�KHHP-h]n��3��9s�����P��P(:u�$Z�F��������O�l�������d�����G
MY�?�C�^�R�/���Q��'O``����A��K�hB���-[�D	�/��J�<<<�o<|�0w��u����o�KFFF...��oW:�d�����2�4q�_�~xx85��=;���cccMMMu�S�Oh������3g�������������������7����'�}�V�|�.]�$&&=z�U�V�>}JF���(
6�����n�������1C���=Q g��Q�J`�D	�T�R{��y���������)��id�x�Q�F�GQ�,Ei-�����h����#j|��
o4e��bkk�������>i��	��-ZH#���3�G{{{�I���k�����u�S�����@���fjjJ�g�IdC�@���
(P�F��{���/!J4?R}�1��Jt4**J���:�`ddT�x���0����r��@��3�GE	`������������������u�������D{`` 7��S�&&&.7n,)�uuu��"E�HwO� C�fff���_�|)[�,��|������v$-�
������s��������:}����7�G���U��v�1}'J����k�A�|���b
����v�Jh��g����Jh�����?/$m��Y�PP������G�={���gmm]�h�w����g��-X� ���&����U�F����s��}��������kG-��-�����;q����)^HB���(XXX��i���4����[�V��w���`�D	�s��(d���kmll8�������{��v	 +P���o�+W���UK�T�P�e���5��@�c��;v���r�%�P���SX�;s�������<y��w����/�T@��J���K�F�x�����;;;�����(@�%JJ�ZH'^��R�J^^^
46l��(J ����%�>�]��k��������o�����;UK���K�G�n����Q��_�.W�@�v_IdC(hb��y4tk���i0���d[(d��3gh�(�������@bcc���h� ]&7�@:��y����/_��6�VH�I�K� �s��[�B�h����D	�I�&���w�/�
�"88X���OOO������&J(�@VX�n����X����;���I-���������,��g�����q`�Tv���]D	`��U�����G�Aj���!��EZ�G�f������: ��.[��2y�;�O����]�Gccc��o������@�����/dCt���w����3�+W���S{�b����8�?��������a� ���
%���U���*W�}��/��k��D	���a���fff:t��������777����>}x=�����S'
2����P����LZD	��J����������������]���?���>$%%�����Jll���)�PH�={���	z���.\��������5K��������
����
����.7�7��|���[7�%�
��v�K�~���|]������/�7o�7np��VVV�%�={����ql������������u����K�����/|��>}�3g�.]�|���y��-Z������S������?	

�Cvt�S�'4���W�=J��3g�P���/��������_�k�
����-������L�2b�\���}{�2+�����m�V�^��� m6l��c��r�����sslQ*��wo����N�����?2���}��2�B4������9r$E�
���p��G�����}���J��t��{yy����7�={f�����Q�F���/5&$$T�P�7
���Jf����W�.S����sG��%������1%����<��|�2�z����j������/^�hiiI	ppp0W���K�n||�t�n�4 i�z�����	E�
H7
��g����6,!!�)��n�:g����_�������'?~\4��w/o���X�^=�W�-^�k@�z��9]k���x���#GRN�o�>�����*T������i����400P���~���?E�5k����������5..�~\�r%��+V�T�R��5��,�$-�]011�,�7
�����r��E��J�Z�l�������q��Y2v������pZ��CW�\)X� �[[[O�2e��m}���5j$�?Z7p�@^�;  �.=���CC��Q�?�2t�P��z�]//�����_�V�^�h��b�����&�%K���B	��[���*�$-�EO�<	

��+�(��M�������+e�-���[����Q6�Zx��E���E`���O�>J+d���+;88H���<y���s���"c�@8p�2��7����x����'NDEE��7�_HZ@�R+|�����S���~~~�^�����w(��-$�,i�a�������{W���{����Y�����z����h�G�J�*I�\�^�9s�����g(������2v����OKM�8�b����E����P(�#'�'$-��?~��a��������� ��4:v����E���A���=jii)�5��7���?�������;��c��Q�V����?�i�&�D��m��}�G�/_N-
6������*W����.k�@ i����2dH��9E�#��@�N�(�y��)%-aaa2v�Bppp���9�������~��%�����Z&M�4~�x�:�����t�qqq���n��|y�7o�>��&&&����%�����g��
0���h����<yr�<yx����:ekkK-U�T�8q������Yhh������������
R�������o�W�V�����;����`eeU�`��/_��g��PBBA�K�f�(�PZ�e��QP(4�3f����`����W�D	���5h���M����S^C6l�x�����8Y����O�R~�z�j������e�R)V�O��\�boo���������������[�n�###+T��Z�{�n�R��!^�Ui��;w�5��{�-���jK��M�L���K��=y�$<<�~��6lP:������r��k��k�b@N�<y�����SB+m����X�"���u����?~��g��o��������@V�w�E��������Ks
Q����"mP�k��
����������S��q��������/������j����������g����C���{����~����uk��GiN]�P!����u�5�WHZ ��]����(,�y��\�r���!!!...\���J!�_�h�#~�P3m�4.l����?~��"d����~��q�y���_���k��U�h@@���z���K�����r��E�/8p�Qx�}�@O!i�,�}�v
;v���>}�U�������S�$��S�P�&M�����}�V���~(Q�E��7o��}����h|�m��[7n\�p��'��S0pb��k�.�/�^��-Y�D�}�E�.��W�re�J+���/_>�D��7�SHZ +���xzz��c��U(����)S�fM�-���;v�����gV�\�{�n����+++�2��={��-kaaA��"���e�)>1�633V:��x������
���[����m�/_�H}������\�rr�
���:�_�611������v��m��?.W�@��3��~�����S�9y�$�-��isss����\[[�2e���� J��5��������q��m2�
���Dbb���K�T����<x�`�]���@�-b����Wr���ZmPr���
/^�}��JA��!�.�?}�t777���;�;��Z���i��9s���W�d�G���;�W�`kk;k�����E��#}��k����@�$&&�l�2����9%'|���+���x��[hee�����z`��9���a����2u�T��������s������}Ig���������%Kbcc���7Q�D������g����S����@&L�6-g���-����~�z�8���5jD?���yyy����gy���c��Q������S�N��+�4o�<>>��p��)�<����1f�kk��%KFGG��q���l������srw�(t��%11Q���!@�ecc�����+���(���1**�^�z\��3'^W����}{77��_�����`kkk
#t������333��������C������-,,0�mA	�I���U�����+W����[���
(�(�.��_�~=z�(5��wO����

:x�������;�]�|����b���K�����7o��o����u�Se�M@V@	�I��_���%!���7o�T���q���������g�����)�b��y{{�~�������{�N���O�M@V@	�I�������7
���O�>*T��>{�L��=�e�^��\�rb�_�v����m����o���i�B�{�n����K�k������}���&
�FFF�_���;�|�����k���\���R=���+]�;DyrHH���Cs������{I�M�r��}��)���+W�������]=&J���G�M���K����6n�H?r��	�q��rw��(><..�����+W�6m���7�lB����K�>}��+�P(.\(w�@�����m�=���x�3Q��&�`������O�>��S��D	�e������t���=�vD	�������rw�(�^�Z��dS�`aaq��9��%��Y%�IK���rw�(l��A��dS\�]�vLL��}��s��B�
��uK��d_��}�����`h>~�(w�w����
endstream
endobj
13 0 obj
<</Filter /FlateDecode
/Length 1801>> stream
x���]o�4�����5R]��[BH���5P	��]	� ��/��I���L��IKW��x����$�$u���� ��5�|>�}����{l�!����P>|�t����O����=���v�x�>��h�0~S�D3����w.u�����������(-�L���2[����4�����}�Y	�����'��ZY>.�.��
PH'�u��:|-���w����@�V��$��������{���`��ZZ4��e�NbH�����Ne����(X��+�3%����H���k
��R���hI��RJ
�I��K�����\,:���
~�>P2H��
��]s�Y��@j������u:g���wi��F�������~)
`�JJ��$i{����M��j���������8fJ����r���ro�wg�� �.�+u#��m��@�2NOC1������[s�:��b����h��*�z��0�<�����������o1���z���q �I�����������Z���
���'
U$����8�����O
�\9�+D���+o�p��4*$8���z�����~e�-I;��i�
4�u�3=%�o�M_m�������=����'

��A��wi����:����y=Tj�8�V�{�TX����T:���0
��e��2���e�KG/Pi�.Yz3K�/��5��yM����)��'��@�Q_��S��N�yk��)u�n�<���&���/����M�� DF�l���	�/*d����n�3�h�*�A���|�����2���U��ix�2�#��)["�
�=����JF����{I�������9M�*����2�>AL��L_���M�������+[��������Qk�
����;�8#u�y8ud2]"d�����l�	_}e��-#s�<`$<����2�zJ��I�4/�f�����2�)!s���V��#�����7� ��reK�<X�ddj%d���#C��H��y��@f39L�L���>=/2�y���W�l�+���"��6 d2=%d�$A����=e�D#dn� ������:"�
%�M�L�2� e�M�B]��r� Y���4������������s�SL�@������]9�K��<����Z�|���������5�S��u���XW���������:�y��H?XT��L_��/��Z���!����Q`H�^p�w�������m��V�."
O�L�~^�(LO�(;	7�Be�SB����@
��5�%�� ��AwfP�����yxqR
g������\ya�
K��x"$����Y:2��ia�^���oP0%(�}���A���t�p��!2h���0��!�c!��������������=��'A�RD_KL?�J��*P�	@L�y��H�y:�����)A���C]��2B[cX���T�i�w�p]""���+$�D�LZ!�/%��D���{,�$ .,�#�x��d:l���J\��4g�;z�u�k����qQ����$��-_a��������Y3�����~<9S���S��7���=0�O�_n����Z��U|���Z�tj^��E���g����|��|�������;[Z���S��w�ZJ-m� U��l*�P�����e:.v����T��bw�����b~r,���b�e�Y��./	�%���������1�#����h�?&
������%�^��N.��!Y�e���G��q���)����(7D�.��L���@��=����������'�X�U`�d�
�a��d8N�/���K
endstream
endobj
15 0 obj
<</Type /XObject
/Subtype /Image
/Width 2048
/Height 987
/ColorSpace [/ICCBased 7 0 R]
/BitsPerComponent 8
/Filter /FlateDecode
/Length 37641>> stream
x���ypUU�?��R��b���qt,g�r�����'U�o���]S�?{t���t�U]]S��a�`\�dQ��"v$,�NCi"�ADE��A 1�%/	�S��[o^��KX��|>u����s�]���{�=���\����Q�PRR��'�|�Q�������ew����N6o�u�x��xn���S���?~G������WVV����K�����C'yyy����w5��\�������:��������_=v�����^{�M
/^<n����G�k	?�	&�X���o�m�����h-��������������_�����������F�z:thCCC;��Z�*>�������y������nC������c�������C��t.6lh�	�^�::��5k��j�a9�������zx��7����������g��766���M����M{��W��8������ukc�����@���jt�����z .����W�X��n��65��i������EEEo��F��|�`��'O��w�����5+��{������n��uQ�9y���w���OGq~~��;
��������g�j���qD����'�����g���������f~����
���i������+WF1fqq��;J<�PII��;
�<���'OF�������C���~z��=QI���|����d�u�;6h�����}�Rw�����5���.\����;��q*�}���[�?>j�;�L&7o���������9���h��%���-6�2eJ�|���a����3g�|��gB�������������7v��Q�F
<8����/���{���o���7k���d���a��^vVX)--����2_iUU���K'O����?d����'N\�x��#GZk���Q^y��p�pG�N/��w�������?������g�}6�^h��K/����_�=�����"j>g��65��q���S�����$��?�{,�P-���j���Z~������^�?�'8����g���1����Q����o'�k�����}��W�d��a-���P����?r�H<�K�x���&���E���|���Q�7�|���q��9����3�d2C�`��A��-k�m����0o���U��^|����x�������s[�re�����KKK��mj��w����Y�����3�6�?UYYY|�R�3���5jT�o�-��qf�����1#*_�t�E:���G�C�7�M
_{��������|~����������;wn�-�������i��M��]�vm<�{�x���c�;�qn��J������'M�2%z0h���^ZZ��{�M�:5�������8s������>Nl�Y%%%q��X��y�,/���!��Faa��E�B��g�!~u��a_|�E����q����y��}��Q�(�_�~}��D���D�.u���2�����/���&C��{�F����;�g��C��O��<yr}}��\@fq�����������}o���|��y�f�*--]�|���{[=K~�at��>b�#�(��9s��'R+���+�����?��^�������W__.'N���
�Q����92�N mo�r������K/�
�����>���r�����q��{�������������2�s���I	�C'�7oN����cEEEQ���{.4uoUUU��@�s���G�
�}����c�v���Em'N�����e�������3�<2O|zAX��[���-
�h��q����@f����[�.���I3f��h���_Mo��~fq��?��AT�Y\�����~���|����=�\�I�����l��������gO|��:�V��w
:��7�<��F�����D��F�j���������i{������8�_�~}�N{��Q�u�����G�	��D�?�3�]����k��-~��VY���2�j�<�L��]��.u
����O-^z��6�v�>q����?�������7�i����������
K>%��k����������Sw����?��������
-N��0aBT����O-O��3L#e��������_~���]�����Z��'Fm�����+��g(����G����R����[;z,u��v���S���msY���.mT������a��?���/RPP����V�a�������3f�������O�������*++K���$�|���Q���z��m��u���fP���N�|�06///mX�H���N���������X�">��N��|��s^����O_|�E|!�w��������;�O&�����#G^�Ir����-[U{�����g<��m�������Q��������xZ�������UZZ�b�|���^x!j;h�������K�.��6�����u��I����������e���w��6�������S�b���pg2���2|����U������g�Y�����3���������#2��t�����A��O?�4.���oZk�����?������ik���@�Eq���qaZ��C5b���
��k-��Feee��
�sN���x#:�Xg����Z�v����S��x������������{������g:t(m���~N5�;�e��[����������-2e�L&�jm���w�7n��������Ro�G}tA. Kq>���?x��7�����������Z=��s�8h���3'C�5k�D�
�Z��a����6mjG<��D�1r���� 744����Y����L}3?{�4�6l�[_(�������Q������ak�������j�������M���8���7n\<Gs0e��2�@��|�}����+��i��g�m���U��c3�#��s�f��z���Zk��;���b���7��e��%������������*>��������g������|>|�����z������v���������x�������Y�vu�l�jm����^z���[e�e��k�������3���|�M|u����NN����p/����y�����k1c��7��M�j��]�8h����d���3b����s��q���������� C�����������*.�1cFk)���3�������:v}��n�7�0�O��m����/�:�TY�����9����$m�������{��	W�I�R��:��?��G��e������G<�����'�q�8b}���3T�;wnT����O-?g<��Z~Xo���^^^�K�iv������y��o
����+����)
6,��z���^��={���0�m��m���G�@m=��d��766�3#g>�%K�D����Z�8

*++���)��"??�����\@f-��uuu_}�UEE�9�������	�<��C��&�'On�9�k��u_{����[o��Z~�x<�L�#���������� M��'���F��T8q����C���S�Li��9}�������(e��755�92z�Q__��skM������t����H��e�������G�	��<T��H�Bi1����>|x��kjj��|���Y1��W�\��sNb%6'M2���+V���&��W�:'N�p&UUU���khhH+O����]�Z��	E8\\XRR���+�5��;��?�w)�Wa���;O�8�Z���4b���y��z��v���2�o����x��?�����~�-��gR�����</��Z��������tcc�o��<x���~���7��7��������9��:6l��TUU���&O�������a��	Q��q���]��AAA2�l�����}<9l�W��2#G�lq��p�����=�����V!�����{���Gc���,--M-�5kV����-���������o�&��(�������1c�d���?����[�������������/��j�����LJJ?��4���K�[UU�!,X� ���:u*��G���QP��5(f���i9����VR_��d��'N�U2d��;�*TWW�o�:4m��8������8���������N���{��7���,�U�c��m6l��1c-Z�=zt��gs������-Y�$�+���Z�pa\���"u�����]���6p������'�����fh����3)�<�p$���#���Kn��I������/��b���� �'pa���WWW�{
4v��7�|������^�"���z�v���z����}�q���{���������`�����w�V��6mZ�^���C�9XSe�;v��g��/�������/++
��<��}����q�?n��y��
<��c���k��Y�vmiii<~N�i����MMMEEE��7�xc������[�pa���g���|'�?Ayy���{�t�


�q��Nl���K�,�5kV���|�	���_��9s��E�b�o"�p��
�2�?q�D���<�Cf��;��h���T��m��3gN|uC��<yr�]���O+��ys��g�����9�_8mZ
�+3���3g�Q�G�i��!C�-[�}�Dax���MR��c���3��5j��}��7�2?s��/{�h����w�n�0�������Zl>x��5k�4o~�����/��~��(�O&�iu�����lhh�?~�,������+W���F8�i����p��E�N����m�2�Id���Q����l��(�����5���d�������#G6�$$�9�����~~�����22�������������	F�5x���C�>��3�K����m=\�{P]]��sN�X������CaAAA^^���#���|���Aib�����?�<���0��*�M��q�����������c���{���5��^6lX�!���7���	�'N�X�"\�����E�K{��W?����Ac�=Z\\���O����l���<r���e�&M�����w��1c^{��p555�������3��
2d��/�����s��B���l��!�3�={v���v9���G>�d���W79�-�'O^�vmk?�3Y�������:�����J.3�D��y�d&�����.?�������#�����.?���,[�,'''�H���/��������g��]�v���K�^�������������G�������o�q��{��I��eW�q���o�1qVj��L&���
�w�>���6������W+++���krrrrss���oX���������p���?��u�]��G�����I�$77���6*������w(�>}zTr����o���+��?~����$�������d�]���S����?�����������������w���fiii�|��������o(_�ti�]��}��t����������WVV��[n�%�ISSS�n�rrr������O>��U+**
�O=�T�]�/�L����O��O86���U�V��P������vm��!�����������Y�dI(���_�]�o���Db��Y�fZ�?{�����c�5o����]�-
�w�yg��A�M�6�����;�������^y���K���3f��'�x�y�����]���a���n���v���{���}W�T[[����S��K�9n�m��v��7?~<.L����}3���x��3������������:�;vl��9t�Pv�7g��������<�0-�����f��}�7���W��y�������4��u,X� ���g?���s�����N�����&C&������?���#a���nJk�L&�t�r��W�����_�������S��=����<///�g�p>
�_��z���D�_��_���]�B����+�l��%�����C����m.\�0l���?O;�=�����]mf�p����L�6-��w�}555Q��������P�h���$�L�~��999���n�p��	���MMM�w\p�������~8v����G}��G�u�6��_�6\�~���_��������O���'����~�g���v\X���3gs��'����������k�>}�O����'�|�������?����o���_���L��eW�����O�i��K�����pq�������s.+w%;��t�v'�WA]�\�|�q���K�lW���W���_�E�p���/1�?������E���������
���tN��l��Y';���@cG�~��a����&}�9�������Y�?M��s.G�noC����Q����D�~�y���G���������K@��m������;�R�[�p�l�����~�s.~j:Z8_����?m��KUuSG�~�������_6t������7~�pA]�\lM^��9���y����: ���p	��/1�?������EC�����,�)��D�~�����;���#q4�����g�<��9��}�:���g����s.�';��o���~�5gS}�q�Ni���G���q���K@����������/��su�s��E�p�l������:���VS��W}��cuM�s	����~�����s.k>Nv����B���?\~��p���P�W�y%';���Ks�����q�oOw��������p�Y�q�}����<R��$�����.?�������lW�s.U�M}��R��q��S�s�u���o?\~���S{t��x�)E�<����#��������<�T��T�\v0�? �MgN�w��AV���;�#����w����B���?\~vh�?����������l����G�����k�����������_|�����u���{����k�.]����k���


i]UTT<��#7�p��W_}��70`��=iu��
h���'���$���������������.������$��~�������8+������766�]���]s�5������<��Co���q�,����o����k�����������C���H$f���L�4)l������F%555�{����O�JN�<y��7_q������*))	un���d2�}W����m����������80�H><����G����H�S^^
{��m������z(���}����K�f�p1����_�������rKZ����n�����TWW��'�|2T+..N�VTT��z����.�'N����?��?�D�>}���W�Z6x���������k��
a=777��_�>���%KBy�~���
�P�t��8��;��2eJ<�����C�c�=����>v-Z�(��y��a}��}iu6m��������.��~���������D"q������;Q��3B�O<��I���������~�m�������sg(���G�]�Smm�wt2�N�jS�M�M�6��_�E"�())9���}3���x��3������������:�;vl��9t�P[o�,]�4�H���3���a�o�������+���ysX��O������,X� ���g?���s�������9r��qw���'���;���>J+?x�`"����kX�3��t�Miu��d�.]����������_�:T�:ujZ�g�}6����e�p>�����?��?���\�2� ��������-[R�,^�8������������������P�v��������~z�UW������UUU={�L$�����L�6-l�w�}555Q��������P�h���$�L�~����w�}7�j��	���MMM�w��q��%������_��}�����k�������G�Fu~��P��{�G}��G���[����~����������������'�x�O�>���~��={��u��
8Ok��}���������������O~����G�����ill�8qb�^������]����g��������O}�����W_}�M7���_�����iu��
:�/�������n�������K�.w�u���cO�>�Z�������g��]�v
uz��5~�������***y��n�!tu��70`��=iu��
h��7���q"����������_�~�^{m����������N2����{���
+a���q������k�������}�����a����+//��d��nMMM���H$����~��������y��E%�&M
�������QIMMM���C�������'O�|��W\q������KJJ�'�d2�����k��k����oljjJ-�����D"������f�=�fEEEj����P��w�h���4l>��Ci����o(_�ti�]����i%c��I$�����a��[nI������[�����������O�j���i����B�SO=�}W��p�}�%���W��U�V��x�y�{��7���aCX���
����O��d��P��_���.��c�&����6g��6{���5|���k��Ea��;�����K��i��P~��wg�p555�=:''�'?�I<��3��O<��~���������~�m�������sg(���G�]���;���:����(����3� O� ���
(���� 8�F(������}IMMM��>Bf��&��J��Q�_�p�b1(���00������5x���'.��b���g���z���{�>����J��$���
���������O.���/�O�:���\�w{�����{���/^�����U��_�&�x��d��+���eK�]3f�H
T�W�n�����g��}��	�g��Y����>�O=���
����i��a����+�]�jU^^^��m+����6n��n������#G��z��
�n����~��Wg�P@5�i��I�&������u�Qyyys��)�8u�����o�d�������vZ��v��=�g<����w��yyyO=���L�0!������5k���+Wv��%4N�2%i)--���s~~�O<���}���������?P��O���k����m���+�neee�=[�j5t��!C�4k�,l^r�%����_o��Q~~�	'�0|���={�>�����2}�|(`�=���y���k�L����1c�t���Q�FM�4������+?����;t��}������m��?�����*����`��e���o�}�=����+**��a����G�>��#�4i��q�n���{���^���7o��!���_AAA����>����C��`��=z�����Wo������'�|r���U���n��3�8���,����{������p�	\pA�?�n�����3��P@u����
4h������;v������c���N8���8iY�fM�=B������7�k��N�:O?�t�����B���;���f�P@5=�������V�^noo��k���}��y�g��{���lN�<9l~����p��������>���i������\�_�|yhl��}�;n���Y�f�����y�����C����W�v��w��+��"��j�6��_z���XXXX��1�v��5+�>�����_�B�i�����O>9��j�6��'M��9����vM�2%�>��C��E�U�����������������Gy$4>�r�3�8#��<yr�}�A������+��;wnh���k���m��'������N���.�����w��=���Jo���v3��-�r��
���?c���������u�v��=;����O�=s��
}�}���~���f�P_��?�n���N�����U�Bc��m+t.--m��q��u��[6G��=��C��z�������������������
�s��)�8u�����o�d�������vZ��v��=����+�?P����?a�����W�5k�$-+W����Kh�2eJ�RZZ��s����'�x"s����/9����[�(��~���
�������
0 �1bD����l���aW�V��:d��f����K.���C�����5���?�����g��g�}�Y�`A�O���u[���l���fC
��������{�[��,���6%'���:d�����3�[�n�5j��I��='N�X���}���C�����m����~P��Y>�0�����������[�>}����)�{����"����"����w��=���(���yK�~�����������y������>��o���'��.�7���0��o����
@n��Vi�_��=��|��?���?����{��@������?���[�(�����R�v���g����G�>��#�4i��q�n���{��[�lI{\�N*--=������Z�ju�����y�g����=:`g�;6//��N(..NZ��Y��G��8q��t����]������7�|���3Cc�=����/_�����}�
�[�nm��Y~~����������K/���V�u�1��]�f��?*�:&M����w�9�T�5`���k��)�GT�#�<���7|�����8���k����<��W^y����z������'O�����N�����x��G������kz���1c��������W���[��k����GT��U������m[�����q��u��]�n]*���������3gN���S����}��5*�:&L������W�5k�$-+W����Kh�2eJ�cvNYY�������Z�j5t��!C�4k�,l^r�%i
�yeeec�����[�F��4i��g��'�=(�Z����y���G�xdvC����|����|�����[xd��������>��C4h���}���i�(�	<2�G�y��o��}���7>��c������r��#xd!��o��c��G}��i��Q�xd��Q\\��_�^x!���.����3gN��,��!���g�}��o~3���u�x�����W�xd�,|,<�����;t�p�Gl��)�A�2�G&��B
O���O
x�1n��������!�\r�%�U��A�q<2��WRRRPP��];�q<2�G�e��o~����O�0!����kC�{����� ������=z���[������Q�xd�����O�>!������O?]�z��W^66l����=�$��9�{��{����h��S��o|�_�~7�p��8���3fLH8Y�:thh�ymxd�l��eu��9��3+�o��u����)�	<2�G�w(��]vY����;/4>���i�*�	<2�C.)++k����~������i�L�i6lX��M�t�i�L�q}���Z�J�����?�1??���k��)..Nkl9I��	<�)S�����dZ6n�>"���>��Y�f�]v�g�}��s��#xd'�tR�_��W��W^y%4^z��i�*�	<2�C.Y�pa�,�H#xdO�=���^�xq�]a�4���K/�=�\#��G��-�6mZZZZ����.j���1�b/((4h��U��a�xd��o�[H5�d�������-���_���3|��EEE�3w<2�G��k��G}T�q��e�q��a)
*�	<2�C.y��W��w��9����&�����_~9D=y��d3�@:a��f��t�A�7oNw�9F��	<����W^ye����s~~~��-/���+���E��C�N�>�����3��#����


>��-[���Q�F��W����}���7�<��CC�Gq�^#��#;���C���zk���W�_|qZ��a�L��c������@Z���S�������_{����d�4���R[Nxd��o�[�:uB������s����b����'�|�t����9���a����57<2�����}/�y�]wm���i��7�xc��!��:(t��o~��s��#xL��O������4#l�������F����!�ms�t���?���+���!��G�_0 ����o6l����k��#xS�Nm��}�N�:�F����P�z����M�6i�0�<2�G�h��P����?m��l��<��3��_�~�/�<2���P�CM^�n]�e������5+$|�=��o��a����!����;w��+2-�U��P��������w��a���i-7	<2�G0h����['��G�f�����~?���-���G&�h�n������I��'�x��V�p�����,W	<2���������m���o
��{�]�n����W��n��������1��G&���.]z����	cH�a�����/������{.�y���2-���=��c���������a�O��F��0C�C�Y�f�6{
�FrCQQQx����2��_~y�4Z���l��#xdY~�-���?�����hrR��4)��u�k�,	<2�G�}
3���Wh,..n����'�\C�M�L�����?����H���$gl���~VaW���}��!�?��!�����s[�j�|�K���t�M����#�����MK63K��=���?��G�!��:��c�)((�O<��m~�x�	r��^���?{����1Y 
,�V��#xdY>u��������/�&���n�gO��	<�,s�-Z4h�`�����/���p�3f��s��#x|<�@�o{�!�#F$�r���[�����M�6��W^y%��wm�L�1�^��m��M�4�>}z�2y�����W���������PK�;g��!��n�-Y�7o^��gR�@��'p�.oO�w\U�8n�8K�;A��	<�,���������V��#xd����/�<��/���_����.-7�pC��2�<2��7b�����;$�����;��W�^���k�k������������y���G��N��	<�Q�F��y����W^yeh|���*���'��G}����I�`S�lx�>�lh����+�x5	rL2�x�����K����Fw��#xdY~��'Z��L��e��
z���vi��i��u��������L��w�q}��Y�h�W.����������f���;6�hs��#xL�;wn��qiii��1c��^�z���.���"�9sf����N�4�s~���_�������Nh�2e��5k���������I��c�{�>����]�,/���?���hu<2�G�e����_�xq�Q�0�G&�����7n�����v���}�A���5+�s��#xd{�����#��lH�e��M�6�����u�"3w<2����E����
�����w�����8���_Nv��
6��Fw����Cz/��R���n�-�!.������M�4�����]�&�C�	/���_���y��}���F�C��	<�*N�	<2�G&�������i�!�����&��r���&��Y��	&dZz��d��w��#G�<�������g��r�%�X�i��rK���.����;�Q�F��K�.?��������?~������C��{JKK=���B.**J{,��G&����#xd�L��	<����������,��Y�&��r��#xL���.������z��z�����^�?�|��y�����O;���e��-o��f:���}������+V�H67l��������g�N������7o�|��M_�z9��^/��C��=����#xd�L��	<2�G&����m.��?~�}��|e�$�����^��o�oY�lY~~��{����r��I�2�<Ol�����O�
j��!7�r�)�e��k��=����#xd�L��	<2�G&��^��l�R��H���RPU"��YU/o��M���k��E
�'�U'���N��w�y�������������g~�C�xd�L��	<2�G&����kJQQ��G�j��*�+�@z���[��G&��v.��'�|2�~�y����rX5��������������r��a�t�������'�=�]X���������#xd��M�6�u�YY^DI��	<2�W����L�5��g�
1�1��w\�hQ�-�}-�V��#xd;x�p���-[6n�x��%5>�\U����]{�����O�4������O?��y��m��)..N{,������x�d��J�5%�/�	<2�W���CIi��A6�u�)J�'�W���
%%�O<�n���������e�	<2�G�}��7o������_�b��)7�|s��M

����%Uz�_w�u��
{���|����;�9�\sMm�0�r��i��a������{�K��?�y�Q��������'�C����G�y�����%%%���3<�%K�|�[�Z�x�����������^}JJZ��8���������W�n��}�fK��!��Y���;6����[����F�c�<��S�N&�=�������0�#p�1�6mj��Y���w<���.]��Y�|kh��J�^}����B��.,,��3f����k��B�7�p���Fd�^'��SR���D���������.
�?����t�9s���jxd�,���L�:�w�yc��]�vm������������}��7�x�g�N8��5k��X�"�����Wv�:uj�y��gFX���!�WUQQ��������[{����~��'������7n���K�.��(���z���JII����R{���+W�l��i��Cm����o��_��:Fu<2�GV���>�G&p�
����5j�a��p��l�r�i�M�<�����G��_~y��q��������WRR��s������Eh���2�N~b��"������w��a>�`6wx5��?���������z������NI�OI�=J��;��3d~�w�=����#xd�L��	r��9s�7o^���5�����]����MK�,9��#�����={�LN����^%���;���2�������[�h���Z����'�y��II����]����_��g��Ca9��6l��z���DII�������_b��M;v�s�=W�X��Xv�L��	<2�G&p�
����w�}���S�N���i'g�Z��}���[�~�������~�����r�TIII���>nl����/���O����>��W�^!������;7������[��GM6?���A�e�N�DII����������z*~���=����#xd�L��	r�?������/��O9��dB�5jTH8��e�]�6���C5k����������dM��)..>����'vQQQ���M�Y�����
���z]�SR���D����������O�:u�x����k[�fM�=��#x���iSIII6=��aW���f���!��:P�=��o�L�]���j��q�����������}�����#*���z]�N��-[���r������������?�|�u5NI�II�OI�LI�o���o��S����O{ �����P�o���l:<2�G&���x��'gs@��	v-aB=|��F�%g����+V�^��r�V�z��!���������:tx�����-W�xr]XX��c�p��{�Nq�����u�����u����/��k�������c�)S��[�RR"PR�������7�����~��'�������/((fy@�5"�7A�G&�j������m��a��^#��=�-���C��6`���N;-��[�6mf���tp���Y^���Y�(/L���o:���3��r��&��Z���R�F������wi_YR������{�n�����������{o���d�n�=�\�re���*%�V)))RRR�����{���Y��+��:T�
6DX�y��g�? ���4iR�&M^}���������8��������=7n<��CZ�n��|��~���PZ[�l����C�������F�O�>�oQa��A���������)�v���K�:��v��}�;�)?Y������h�����~��9s�l.���X��=#F�HVG�,YRa����j�C=�|;MI�LII��R�����G���wYY���v�m��/��h�=U: �j���O[�j��I��nX�~������()�T����II��s�}�����i�2-+W�������Q������{&�
+/S��-[�<���]v�����L�>=i���������o����Z�b�^{�����>����?��M�6y���a����/����\SM���d��C�|�A�Q��m�����w��-���k�K�s��{����{nJ��JJ|JJLJJdJJ|����~��P(�{�=KJJ<���Q���:�? ��***:���W�Z�iy��G�br��7��^#����? ��RR ��r�)u�����<�/�0Ln����Y^u���,Yr�������G���m���Z(���M��a�}��G��m��,�u�Y��7����>*\x��!�z����L��W��R\\�t��t���AI����������c����a�'�|r�����
K�T��������Yr��[n���������O?=y���U�
��������z������< �*<xpH����J6�[aaaaur���|�W��S�(�/���A�%���< �*QR �l���BK����+z���_lkZ=s��<��W^�=���������-[�|����l�O������{��g��:��;�c��I��[�n��~������N�s�=���W���&�'NLc��6%%-_YRV�^}�I'%%�N�:�n\��i|����6%%-JJ*���By6lX�����K�jC
Z�hQ����3���/�����>��,��O?���k�)--����CI���~��z;MI�i�����zj�����}��;���w��|��r�dCI�\2z��3�<3��C������ks\q���<j��m����'�{z���F�#��q�dZ�.]��K�����o���N�:����o�m^k�,�'y���>�d�����[�9�>��]d����eSR�K`�����w��v���>��`s�����"%%2%%!�K.�$Y���o��pr����t�E��K�}���|��!���e�]�9kGx�[��CI���s�����4iR����G�V��
J
�����w�e;x��������'_�
��,�N�:afQ�l�c��
w��_����s��~b1bD�e{�/���.]��_�x��m�7o��k�U�����K��%%-JJLJJ4JJZ������]~��!�=����_L{,����	��������SO9P~����TC��^�
%��-Y�$$|���Vh_�p�����@�SR ��m�;���'����x��Ic�Q������K;��=_)L����<�^�x��u���?��]�v�/1�g��������3�9������()�()1))iQR�QR�{��w&M����/o��)�����'�K/����r��W_�}��G*����{���}���Gy�������J~����:�\�����/�x/�����f��]�~������%r@III����]�O����Z��������_&�_|y��c�=v�=��5kV���s��
�������|�n������cz�W\qE���g��n�Ys��MC���]������S�N�?�Q%JJZ��h������()�()1�x��y���M����g�Z��=���
����c�I�"�\sM������5h����.j��m�����]��Pw]JJZ�{���m��-���5jT������u��/'))���Y�;w=zt�-*O������'���,??�q���=�\�c�
eeex`���;����?��0�Kkx�a���%%%�S�<�i|��7�5k�|a���z�����[JJZ��������()()���B�h���5�\�8p`�@t���o��9�c���|������q��U�{�]wu���I�&:t�,+�����_y��z]r*�����r;MII�q���]y��o��4�r�{��|/����@�I�����Wyr�������������|�����
t��`����{/�����'u�a����!��u�����qWUTTt�����2�9uaaa�>}����Vx�����jRR�QRj����CI�FI�=JJ�B��sL(#���n�q����zE�<�h����3&9\;u��
�n����z���N[�xq�����<���W^�9��6���_|���n+_��%%u�b$���|��Y�f������NSR g�7�i���x���<�H�����5UU\\\�e��%=z�H��}��]�ti���Z*�?����k��
���k�p�x���
<8$y�UWeZV�^�d^�N�[o��B������*%%>%%]JJ�RR�SRR7}��������i��%�/����������1w�"s��7�gxH8<��z���}��a��P�~��%%���o?r����>���:�b����!���;S���^Gu()1m���?>��r�����}���;������SR g|������7�R�������Uyr=�����JEEE�:u����3-+V����C�<��#�4i��0I������/����������;:v�>��P%�m��k���"�v�����{��w�e
������*%%JJ���Z���BII�M7���|��J]�-^�8�����g
��	���^(2y_��;��� ��W_�Ix	�s�9II	e��^x��'�v��.L{���k��6��W_}��//~��}��px'�^W{��hvPR����xa34u�QO<���/������GM{��0%rC�Vx���7��������N�>�B���������;��z����PwQ�>�l�z�B���u��5o����_����a����~�%�	&����y����T-KEEE��//�RRRr�e�e����T2������e�*�=�\w��a���F�s���������NI�mJJLJJZ*�JJ����W��������?��Ob4�|��'�,�n����G�\�~����
���;��/��j��~�����LIi��a�K)�{w��'�=:�*O()�[�������0waJJZ����=�\��-���������OI�PVV��W�=����7��A�0�n��UR<�������07L�4����m���@o��)�
���8}��q�����KNk��?��S�N_����O�����?��\���?�9�hu()q()q()�SR�PR�PR���M�4y��WKJJ��-���k!�v��-\���9:��Y�6,�A���.��N�:�O~�r��.]�T|����F�0`���#�/z�m��e���f�:����y������^w���+)U���(�������y����s�������i�4()�K���?����>X�1��/�����>��������>|xx9���=��L���������O>)�w��k�*��s�1!����m�m��kv�������:%%%%%%-!�V�Z5i�$�Z�~��"F���C���_�����?�����+�����-[���#���3�SM�/���kr(<<�+_@a��u�%%EJJ4J
��������G}t�$'LK4m���kJ2�����f�,2L�k��u��������t))1))()iy��G��q��7g�����a���v��L��u����o�]����`s��-[�x���+u����i���z�*F�
4��w�������

f��Y��������BI�FI��3z������SO�5*��[x{z���/^<b���/�2��0sG��u��{n��&�5��:EJJdJJJJ����������l�RXX�,�%g����={v�^w��>���.|�����������_Nq�9�C�u��Y�`�6�����?�_�����q����vr��
62$��y��g�K����e���i�4())RR�PR ��Y��K�.����j�j��1�-�&z�����2�d&���zk����:�O�M���N�C�|�Aj��!JJ|JJJJZ��������n������/?���*��-Z��W�^y��h������9�]w]��[�n�<G�~�����	���
6Th)))�5k�-��r���f�������:5�����()5KI���y���7f6W�^��_�"�����w~���o�����_}�������g����������!�
�� L�?������AU�\;Z]JJLJJZ��h������()���u�6��B���SG�9l��{�����>Kq���P�{�����E����k�v��!Y
!�������O�~���.����s��<�@�%<uO9������y���]w]��;^��F()�MI�UJ
��+V�w�y��\�N��N:)SE�)���;,������0����.s��c��%%%��O���O��9JJdJJ������D���KI�m��|����������n�;��[������*������;����z
H�z��7o���
��z�z��o���k���������)$�����Kk�j
E��\C�R�����K���m���m��(m��*j�)E1�ABCF�����u?�='R�s��9y=�����w���}�{���T�l�/��b���###�.�n�\�����K�.����/Wq-�D��8��:�"Rl�H��8�3g����f������m���-���������Z�j���
F������e$��u�������mz�u����}����g���)y�b;D������H���W�JJ��#gg����k�L��v��%-��������]�~�b&m�N6�
*xzzJ�t�����Izx���jidd���V�Zu���X�b���>��#�����SSS327c�Q���c���o:_w��Q]ku,D�M)F!R�#�\�D	������w���������e�U�R%�{yyEDDW���������/�u\���k������+?ip��cG�S�cD����!RG���H�"�p�n��P�B��E�/_���b�%m�������e��
LHH0�Z{d�rjI	�e-�%�=<<L�����7t�PYG���BCC�|�)I�,Z���%))�M�6�O��&��|�m�
"���=)�c1b��x�m���l��U��6\KT�\����g����T��������m��I+h1V�Z�|���x���o��U�V�Mw��	������`��=e<ap�� RtF����):#Rl�H���o���q��a��G��>����6l��OO���^�}3���~�zXX���MW�7������\�x������k����+U�$�8k�,����v����u�n���bGD���H��8������Kk_���W�H��-[v��]
���7i�����?��{��I��k�.�����������v�ZN�>�1WW�l�2������������E���H�)"�pD����"R�u��I���#G�6�_��I�&NNN�-��
��i�e��i���={��J��6_W�Z���;�^��l�,�����-[V�`A�����������cD�n�})�c+Y����O�:%�O�8Q�h�_|Q��)))�k��_��������7o>n�8���?��OW��IJJ���#}��������>�>2d��U:�l���Z6r�
��?���fD�M)�#R�E����?"�@?����S�����-[��r��)#��|�������I��?�r�����:)z"R�A��_�~�q������*U���wO-Z�`��������V?�������)Rd��-�Z��w������GK���WO���9u��,�����:�,�OV+2��r���U:("�v��)"Rl�H1
�b���/;;;���
8�]�vj����_V�EEE.\X���2�6_W�h��/Z����M�2E��F��>��s#*u4D���})��JLLT>��c�������_~��������e��OEFF�H���������@ux`6���f��{			�-2\�6������VD���b"�@D�M)� R4g�5���#�m�J�&M������!Y������[�T���-��L�u������H���"p1112L~��7�wj�HF�����2{�����[��IJJ�^��tl�"E�;������-���;s��j����T��$��q��z���������������`L\GEE1��."EgD����):#RtF��/222""����Z��'����}����y���B�
u��E�JBB��i�Ze
W'�t�N{@:r��������(�A)z"RD�v�������C����6m*���/W_����{���T��X�t���[��m-���+[�������`���_�����9�0�`�&GY��e�����_���o��1x�`�=e��]���?"EOD����)z"Rtv�������<qqqy����yKx\\\�z�<==�^xVg��
�2�t����:_�x��:���3"�pD
`�6l���5m���������=b��/���IM�>}��5��_
.��tsOv�rl0p�@��ull�������Z�:u���o`���c���'RO\��\��I/�C.)� RtC���H1��"EO������������O�^�T'�g��:�s��ys����+W�u��������P�B��E��&-��m���G����|�>����|����3"%� R{t��)��8p@}�x��$����4i�����]�v��P�B���3�d�����x��Qdd��K�*�A���������X.Z�b��-��="�XD��):#R�E��������j�����;vL��V���m6_'����*^���M��+��M�<Y�����f��r&99y��)�U?��Y��}��7<�;���)�C����C5k�4m�v����Z|����������e�eD�� %%e���#F��7o^BB��������+��h���\\\�o�<
-��:7n���9$"EO[�n=z������H�)"EgD����)z�?�t���K���;wzzz�N���d��BXX��bbb���4n��D�OZz�����og�1_�)����_?�n[�n��|�$������,���cD����!RG����
0�\�rfw�e9�Fn\�pA�JO�>��������?�x��������pv$/�������c-��u���Y]�1u�T�ksD��>|��sg�k��L[J����"EgD������<**J}�����W�-v�����z��������(���:�z���lz�������J�z����W	��W��[�};w��z�������z��!+�k�Nk���.\�c���H��b;D
��d�,��&����u\[�����������O��z�j��B__�#G�h�h�k�X�b.\0�fG"�`NNN�c���-��.]Z�Vu���V�#Rt���*[��!C"""�z�-�X��-Z��C���bkD���c)�Q�
�3gNF�$�P�Q�F<��3f�P�v�5j��Y�~}���?[�n�;w���e��A�����/����?���,I�_�'��:m����9��e��{�9"%���"R�G���}�������o����.:���6{�X����{�����0^x��"E�DFF��������J��>��#��]�vT�#HNN�u�����#F�(��s���9#�n�O��!Rt6v�X�F���I�&e9_G�X��3"EgD���'o��-���)���g�tuZZ����������yS�U��,Y������j��}���O������������...��������:�,��d�L�����F6��"RA����M�gF���^�zY�E+2���7��rc������m�w�.\�p�%��v������u��7�Tw\���>��������]�J�������SRR��u��)_���
�.��)zz���l���5�Zd������ 5��� Rr�H1��'"EO�S�L)Y��������zc���5k�Ho/X�@kILL�������e��	���`u�����2R��|�����]�|�+u(III2����7��Swl=i�VG���b"p������&9Y�T)���:�|��'
��K�f������O��_����+44T��C���w������O?��aun�;w.((����m��������������C�22'�
�!J�.��E�C���l�������b�c��I��F�����V�VM���������Kv���#�y����j���3"�D�n��,�5����:�����W_e)6p����������^{���7]4r�H����Wk-�7ovvv����L���V���)���wo&�F������|RG���e����9&;��C�J�������y��:]]�C!R�G���H��
�3y{{_�x�t�k������0`@F�a��������FGGK��R'''��+WN�g�J���*U*S��v�����_~�e��%Jh��W�ZU�bE�;+_���,A��b��w�����!nJJJjjj�&M�����f��j��?���g�c��_D���C)�y��7d�^�b��*!�n 8��k��V�/*�W�N�>]�5k�n�x��A�Z�BCC����;w�P�B���W��4��;v�j�u����� ��k�X�]��~���d 9w����d�����S�p�O~w'r�H���'"p<�~����W��gO�E�m$--���?W�2�m�����������u�4�������;z��qe�=�C�����?k-�o��Q������[�V����������#R�x����x���'���y��;����[7�)Rd��e��h��C)� Rt !};j�(�E{���i��V&Rr/,,L�b��U���S���l��jiLL�zg���G�������Bn�>}:#�]���u�����;w.U�T��%���gD��g��i������=��B��H�
�8����^
�?��C�E���n��<�&7���{��
��3g�H�4���V�Z�7oV�
 7��icz���L���J����,#E�!Y�*UL[���{�I�����U�c"R�B���H���,���;��,'�>|hPu��������S����>|X�����������'���ZBCC�{-����S>>>��Y�b,"����Q}��wjp��G�-�!����/^��c��_o������toHH�����Er ��{��Z��?/;��Q��i���t����r�n�������v�2�F�E��N6���� ��ak-���*T��������)"Rl�H1�| ���c9���i�I�&Z��HJJJOO/^���k
?��C��:YA�"�-��7�RG ]��W_���6j�Hz811Q[d9_��#�E�����r����f�_y����{D����)��fp��u�VPP���W�����rR�x�������K��ruu��iSF��w
6��6W�Z������G���3:~��Y���_X�c#Rl!�H �2a���?�)!s��Y#�vD���[ R�v�Z������)))�W��������:��W��l�Rz�l��������3[�r��������[0��A���k�u�&M�q���/�����X�#�<y�tl�&M�|��������:�ksD���)�ccpmuaaa��S�����g�.T��������RC�-����z��������fy�9%���mpp���?��3��_~�����"���4RV�^�]�[�|�,���!RG�X�b �puz�B�
,����Ii;v�Q�9�[�nH7�F�&��5kfy�
�u�����V�ZIOJD��{W��R�J2����|�B�[Klll����K�y���]�v?~|��
M���gB���H1�8<�V�������t�R�F�s��u��-#s�6f�777i)W���9 �2Ln����I�������B>��W1S���aED�=M���+W��x===������)y�bED�����-[�8;;K�6o��l�.]���~���+u�������w�|^�j���w���nZ�+D��I�kw� ���'�8g������j�i6_�a�����b��}��gFT� N�8!��;vh����k�[�S�)))����={�e:"EgD��n���z���~����{��H�\�/:>>��Z�URRR��e�,�e������_�%H�,Y�Z�����x��S�v���L[��?����P��z:���Q��c��qqqq�(����*T������"%��5Rd�!��0��b_���#Rl��#E,\�P]���S��/fd�O����i���������K������7un�O�>��u�}����������j�����+U�$[��[��!7$dd��"�����Ej��Q�����s'#s�N]xt[n)� Rt#������	�z�Q�F�W-)��[�v-;��X�f����������3"9H�

�<Z@�d�S�re��?SSS�U�V�h���g�X��V�Z��t���O�����{��������U���OS�p���C����KD��)��H�%"�v�5R22��=M�L�2���������oIII�Z�


����n�N�����K��)j�(..�F��=�;w�����J��n�^�����G���[D��O�=�������g�u��A��o�!�#+,^�X=�MN��P�\9�<y�d��WD�Q�}$''��-���z�Z�`���������#]�A��������.�j��Y�������'�����=����~�������=j��������#={��P�BHH��.]�dT�@�)�C� "Rl'�r����#GJ�u���l�	�����
6,��v-��U0_g;�[��S��l���M�6E�=~��Z4u�T�	�wY�~����1�h4h������X�d��dW��c��5o�\u���7��b"E����t��h-QQQ�>P��"����f��q�K�w�.�$K�/�h�������7/,,�tirrr�������#Rl�HA>D���b����^x�@�k:�S�L1_g#.\x��aF�KC�{/^�-��qc�F���I�~������M��o�������}�F�����7s]�v�������� RA��@��B�
u��IkIKK����t��i��V&R ����M����/[�l```jj�Q��;mp-{����-ep
�D����|�H�"�X�
���
*��?�1[���������
)�<~�x��mK�,�<K��U+�y�7�|�����_�-�1M�8Q�V�E�r�?66��������[#R�s�N��I�&�����rx���
{�
��v�������7wuu���_����i������'3��C"Rl�HA>D���b,m��b����uG��5"9&]W�n���8w����A��x���5==�i��]�t1�X�2m�4������+Vl��a������!R���~�[u��W���S�v���vF\;;;�e$�s�N��r�������\�
��B��H�"��b;D�����C���{W�����w&ooo�D���7�dkW�I>|���{����m3�l��o�>�����3g�X>�'>>^�������bD��=zT�hQ9���wo����S��T�%5�vrr=z��=~���������^�gF��z8"����sD�u)y�uV7f����k���}�v���������|��y����?~��%;�NI�g�o��]��1����"���cM�0AE�����|�"E:t�`Tm`����f��it-�*::�o����svv��_��e�����pHDJ�%''O�2%00P�188x�����HA>D����71_g-���6m�=,ZIKK{��7���)r������\�\�j��-Z���z��l�aaa�����W���oU�������4h����������5k����8���/�k!Rt�e���K�F���}||���L������������(��6��5k����9������j�����_�D	��[1�F>D��FRRRhh����R�����5k��D
�!"%7���L��]�t��Z��l��Z�z��[�l�r�J��iii�aV����g��]���uk����W��x����Q�F�E�R�$m/^|���
6��S���u����"%���z�H����W��:�2e�����<x0,,LZ�N�j�������c�5jx{{o��]}�r���:��)96h� ��O?�T}�x���
D
�!"%���<����W�^5�
;v��-�o����
qqq�K��������<{��gO���CCC}}}��[';g�777Ya���j��s��%�??�M�6�/�w��\"Rl�Y#E����{�F���+�+�K����������/=���_f��6������)0��7o�tvv���G��)���� R���w�A��I�G��\a����g����)#����I��e�����|]zz�����~��^�z��5K�:����b;9�q���1c����s������3�np82�<x������#F������Y.����;\�n�W�!_!R�UDD�D�_|���h?)����gE� ����S�u�����_7[:o��l~��6_�c�	
��n�j9_�5"�v�@�g�*���{O�M_�������~~~%K�LKKS-���6/�������7K����'���C���w��H`�HA~���U�X�������5kz{{��s�����6_W�J���{�r���x��!Ry�w�}W�H�={�$%%u��a��u��}�vua���w-��L����e�$$$H�����,��1c�H�,\�P�b�uD
���y{{��'g����cG��
�����'���o�|���k��
����)�C�������%K�8ZvUnnnk��U�M�4�Shhhbb�����sgYt��
����=)R��'����o��Nu��7�|�{��:"�0��AAA%J�h���o��ft]�@�������(���:Y�y�-)�C���e����������.����S�w\�~�X�bu��5�Rv �HINNV�?~\kOKK�vww���oQ,���H2L���V�mt9�������m��b��N��w���kD�`�+�����sgdd��J�� )�j�J���-���C�/^\
�-Z$;���7�������{
�@��M���q��u����c����O�>z��k��&-���� �"R�6_W�r��7o]�]��L��-�a�����O���C��^bb��������:u�$%%e)�<i���?�����,�g���_�~������7�Zy\6�"�����i�,Xp���V �#R�6_W�J������W������z��=h�������(m)�u�����HIIi����^����y������+WjK�@�������:--m��Ur���c�	&p{ ����H2d�k���?��?G�5�Bv�H��r�E�������W_%U�V`����c�&M�~�3g��J������������k-�� {D
+"R�'����L�bt-v���S�c�F��~5m��e����H�9&)]���[��)]�r�y���Ny���_;[m:���k���?����3�^y�����O������[^n�'Y�f�D�����\z����;����~�n�x;'�"�Y��wO"���G�K���%R�]��A�"#e�>}����K��F>[�������_�l������c��7)��H�{�W�NMM�III�=�������z��������Y${a)iii������������1B"e��	:�	�";�j�����;vL��������rp=l�0u����<h\��."�)r�����������[�j��ukiLMM
������,����pY�`�����e)�[�n�={���_:$��v��o������=���K���;w��Y
�M�b��-��M;{����D
+"RX��o�-��������v�Z��|�rituu]�~�����,�����Rv �H9w������[>������>b��+����������������{yy�h�b��j|��w�������'N[*���H`ED
��s������F��M�S;��0WW����P�L�#���=)RV�X���$��
JNNV��?~��W,x��Q���w}������9s����g}}}5j����:c�u}]�5j��Y�~}����)��H`}��uss�������6_��������0i����f��Y�|y�M�6[3�<�I�"/^,"�+V_�pa�&M�����
,�����g��iiir�[�^������X������G�P����J�,y��qcK��)��H`�.]��a������|����/^�e����e�������9z�Z��)3f�0�Z4k��1{�Ubb���[||����X�C��""�U<i������W��9s�?����#+`G�)�����o�={�������
�������s���3~�x���9Rv[r���l�����������	�>)�H��V�0`��a�v��i��H�W�^���0{?H��uiiiF��)�����K!!!�mh...c����P��O��f���������U+44����]D
+JJJj��}:t�s��ZJ�x&���(X���'qqq�Rm��S�N>�/_�H9s�������]��P�j��-�j��������k�N��S�D	i�]����#CBB���:dt��""�u���Wbd��!k��=zt������.^��A�x�����5S�%�*j^�n��w���������-���]�d����X3�<�H��%K�*T����Z��?����%{�W_}U]�{��auF[�Y���3�^y���._�\�`�Y�fi-g���R���G�����H�����������7�W�n9_w����+J�����3�@C������={��������?�:tHF���=z�j����+-Zt��m�+`���u��-[��)S&==��=&&�F�)�7V��%R��S�N999���Wk�q����?�����%''8p��L)�������[�vqqi��U�^�,W����s��O�<�{u�����N���


�\*C���K�
,��4vi��y���W_o��]�j�r��8p�r��j�N�C�b���_|��zO�������-W:t�,>|����;D
+:x�������n����+�Y�F��SG�������ZB����|~��Q�
J�(q��i�z���6�K�n��������q���K�.U�u����\z��1Y��M�`��V�^�W�V-�qS������2�6�6v'...,,,66V>6������b�J����/����*�3��	�>);�l�25_��G�-��w������4�0��H`E��W�:t����b�())����j��F��N��u����k����
6��c���?����#"`�����G���������QQQ����)�H;��+�����w�yG�,Yb`m��;w������*U�]��������E�����2d��"K===w��aD��@jj�'�|"y���Y}"`/���5j��9s��9U�T)\�pDD����?D
+�N�(Qb���_~�e�����|6�4y��k���/_�D@@��}������<��T�[o�������`\������6m��F�������D
��h�u+V�������{����`��V�����
�������.
@��qc__���W��wo��
5k�T�u���W+�h�BZJ�*5b��������s�[3�<k���2��6mZLL���G�������uD
��h�u�f�2�v�H`E�)�.]����]�<���c��m�Z�v��N���WZbbb^x�5�'�*�L ��3K�3f899I���"`o��`ED
+��l$%%�7.""�b��f�?~��{wI��e���{W�l��q����N�2�Xv`���'O�tqq���c�H�C"���Y=[�H���X���8�I
�<()���f�499�a�����1c)�}����$1$O�-i�����e�F��_��|+"RX�d)66�^�z���/�\�����(88X���������WEJ�~�,Wx��Q���e��+W�/��S�u�
2���H`E�@��
��@��Au����-W(S��������G����HqrrZ�v��
��u��������`����UpD
+:u�T\\��U�s�S�?���#�o�������Y3�J`�S�����o7[Z�V�"E�������|G;P�\��;w�������P77����[���pww_�`���I�����J���~jt�@>��M�6���G��%}}}7n�hti��v
@T�\�W�^U�Vuvv����.
�w�S^^^�'O^�lo�c����?�������/_6�( ��NT�R����F���i����v��mt9@��)V��(R���={�.��8��8������gt9���)�C�]���S�
JOO7�vO�h���d��������`-�'�*FW�i��/��
endstream
endobj
16 0 obj
<</Type /XObject
/Subtype /Image
/Width 2048
/Height 987
/ColorSpace [/ICCBased 7 0 R]
/BitsPerComponent 8
/Filter /FlateDecode
/Length 46125>> stream
x���{l��?�K��Mw�R�m�l6RK+����h��b�JQ�J��V�E�_���ZU�����L���1����BH��r���\�HB�
�@�#��mc����o��G����k|#���(���93��\G�wf�\����?�����>TWW�}��o_����PPP��]�v
z#;v��7�f��k�7��������iR����������h#]]]C
�-�$������|��������~:{��x#�>��U���������3���o!�O�����3����:thx������y����<>[�������i|aaaww� ����[����#��B��+++���g�,���?��q�9u���W�u��Aw`�����6m�4����2�����#������=s�L��L�V5����W_�q�H�����y����s��9�uG�<�L�������#�����u���[��e��n�����8n[YY�x��A��3f��=����e����JT����<����l��eK`>��S�o/�.]�#�������e������������sg���U�dr���������o�~�V������Q����������������fUU���K�e�������|b����)S�D�����p��mQ�Gyd���q����pa���Wm�}���r����Z��Q�M:������q�+��r��R��;w����'��[��H&�;v�x������


�M�VYYYWW�������O?7�����'O�\�d���>�,[��o��?�x����g�.))�2eJ��9s��\�2�ka��[�ti\�������?^tE�������#�G���\__��SO���N�:5�����Ys����Z
t�Q�h/�������~8�^t�?�������=<x�`uuuyyy�����Y��s�����k������;n��k�
���m�-Z���J��G9�(���Ut���MMM������_��l���|���o��?�x������[�|{��M����?��L���2��a*����S�N�Y���������E�����k���������^{��-�Y�&���d�V��L2���ofl������/_m���<��G��������m}[�~}Tg���q����������������-�^j����'N�\�2�\WW�������j�f���2p�?�/!�M��_z�������:����3�.���;���>�l�p���q>_XXXUU�b���_=�Z��)S<����_��n����^H
�S���g������8�]�$: aR����?��@�=������L�<9�\SS�r��E�����6l��w�K�,	������yEuuuH�#�����6�vww�^����x��7�&�6�-�[�������?��KT9�---]�|��o��������x>�I�������Cw���A4O5����������3f���4D����pd��@���2-����/_�"���a���K�.���Y�v�������Pv����>��@/1,Z�(n��K�,���H���������"�V�pi#��~��9�����������XA����DM�M�W�:��v��
�����O�2e��Yi���8q"�"v������K]�p^�c�;_�t���*^
��4G��rJ�md��i9{�leee\����v�����9<5���|���3�a/,,�9��G�(n�`�����kp�<�QxJe��}�G?��lF�$>� �����]����a>�43f��g��pkz�[�����'��xW��o���M����/������=�X�{���_

���2vc���aiu�z����������o��G��:�l9Auuu\^RR�qt����GCCC��\���������������eK��0�OT!��K���sa�I���7o������@
%�g������W�~�qI����T���3g���g����.��\������uww�mj��g���u���B�\[[��*����������\3�07�7o^\m��U���������k����O�����|��'~������k�`��������V�2�0_Mt����5k���*++S�KKK��{����A�������������������.\�[?\�	���������?u��3fl��������K]]]���6lH���Kl�8x�`���^h���g��=Ln���x��� mZ�X4�po|�ba���x<5��;wP�n����,�(L�������r���,�'"a��Hx����%�`?:t�����d|�f��i=2
%��<���qI�s��L�TTT4���aF,�?�w�������������!�;w.��>y���'Oh����q����\U��.\��Z����GM-���9s26L
����O����)SR�b�td��%!�29}�t���?���������K/��V�����
Gd�����3�0�i\��G�������6��y�xBS������w�%iz";v��WE��P(�����?MMM�%�i�\Ux�@��=���/]�4K�pw}qqqjy�����26a������-�����4K�C�c�����������>g�Q����^�pa���^�H}�p�d2�
4�_�zu�p��mj��!�����}cO?�t\�:OQ����T"���2/JEEE������V�=�� v���;����iS\m�����!�>dl�}��A���O@����'�����W�����;u������
0������o��5�7�P,L�4�����q�s��
�a���GV�Z�\�2�={6���G��K*���_�>n�v�}v���~�*��c������������j������J��aF�H]]���d��?{������C���e��������?'O����L}QoE������z��k90������G��otQoC������f���UvC����qa�6���1��x���@�
1���eK��=����wq�?�p;
�uuu�j!�}���S���G�
����u=�YYY�j��������9���K���v��%���;::�.��>�{���B�,����;`@�x�b��Je1���r��U�w��Kf�����~'� ���������$�&�����O�t���/^�NC���s�e�������f���Z~�x<����� z���������|��aG---}��>S�f�������.�u6n�8�����7t;���U������hG�[�I��v�����C�����mA��]��������#�w��j[UU7�7o^�{<v�X�����\�C������>�l\��^H-�j<�L&

�:


��a��'��{�d�=���&.��J�������A���S�Z���U�>}:�`?u�������i����?������\��?:��#:_���+W���}��i[��y�1�w�g�����5�����9�1d����\�C��7�
��dH���[��*�x��g���,X� KO���8f�R����7��<\��v
����������0\8t����R��0�U�v����H-���}�����Y����/"�?|�p�A}��I�9��������G�M������������8p �����������u�L�r�����<��:��2�_�dI�:[�n
u���SW������_v���=o��8B��m[��������o>9q������:�O�������M�8�t�


�cW��FZ�\�����%�_�j��+�������/]�4n[\\|�������"������&���(�k�����/^���/f9z� �2���SR�IW^�{��������������s�]ggg;���d�?������]�6-'?|�pqqq\'���X.�x�����N��w�����p�~aa��s�R���?�aUUU�-�����N�������a���V�{������f����o�u�O��6�\Y�fM�Q]]]�S�����
�oca��H�SI{p����4:������^�,o�k��G���G��"�e,�?�w���---eeea����g������WUU��5+5��
3�����={�V/��������+W��3g��7��^���w�y���^|��p_}aaaSSSZ����g��&��V���aC��h����h_;w�Lk���s�._�|�����-��i����kjj��9������������k/^�q��-[����F��teb�C��#��������h�����qf��ul���uuuK�.M�a�g@�#��<�d��7�x#l�LD$�s8�9������f������>�WN�]��6��%�������G�*���|	AeZ���=�a����N����o��G�0�o�= �����g�����{%%%��<�x���#n��h���{����0��]]]��26�2e��M��6?u�T���T�<�H��'���:����@����b��p-��������g|R#�@���7�x#���O�_����=����+�_]]�K�����_��3��?���O�e�?����������V��7o^II��)S
}��������tw������A�9��+V��|%���cGTXVVVPP0m���s��]�6mR� �x<v���hG�D�x���m������I��������_�t���?^TTm!��|����&����R\\
*�3�<����>u��3g�TUU=��#���������S��|������\1c��g�}6Ekkk����f��%Q��N����?�����z�'�f���[����e��
�zA���������t��M[[[�
��AH��?����@v�y��0���`�����#���G�#�������O������;�����?����[��8qbT�Vm�����w����:v���n���?����{��a ��[�����m"���7�y�}���'?���[��_���<�m����o3f��	x�������n����!��2���;�Dyyyooo\r������
��_��;����nX�bEhX]]�7n\2��C��~���?����OOOj��5k�������kMMM���?�iZ����;*�����C�p��D"����_��_F_�����UVVF����o���@����><�������������0aB"�hllL�_WW��s�=��S '��{o��[n�e��i'O�����oG�Hk�}����;�������������y���Wu�-�]�t)^���=�H>|8���]�������������@&����8���#G���G?J$���������g�������e��@?�;v��n2imm;v��1cZZZ��?���DCCCZ���WG���{o.�<~����I[[���G�'N����_����o|��D��w��>��7��>/Z�(�NyyyT^PP0}r�y��D"q�m�uww��_�p��o�V}��'������������w�uWTmd�z\Mww�����D"1q������������
����9.I&����3f�������7/�����7]��e������I$�����������������o�y��m�Zcc����1c�L�0����w������w��<v���C�~��_��?������7���_�**L��o������+_����co����z����y�0#@O���]�t�L�������`���G���f�������bG����F���xO�?���`S�k��F��iow^�9���Ey�������<\����w�����#/����������ct.��^���������O�����|}�3����n����������t�����}�y\><���Qa�����������B^�ysK��;�3:���{�r�~���y������O�?�����������q��������[��>�|-��<s1Z�����K��Q�4���+�����3���_���E�?J�������@�?��.���h9zF��C'{f���Ke}g^�����@�?��>�<.��QB�?������a&��c�p��3T�})�������$?S���<����8~���]������9�������8�=:���y������N7��~/9:����b�����l�?\'��]�/�0:�9u�yPF��]��/������,���S�uI���<i��<{M��]Z;�}`�:u���S=�s9s�7��������}�.��b:�.�Wu��<_����|~��]�]��k�.��|��Z;.�l��K��f����>02���k��������q����#TA������k�z�R�?���?�gF&�?p�����A��&�����I�\s��z��0����}`d���������`=��0j��?\�$+�:G����d�?�Lz��;]�v��_�N>�~m{��\��o ����KKK����������>��q��M�8���i�v��}�}��z��c������~������7/�;}�������������'?�����/�����o��������
n���1c�L�0����}������y ��z(�H�}��mmmqI��{��^T8q�������w�q�
7��b������:�3n��d2��~��������}�RW�^~�;������D_��������������a�+�������w�y'�H����K�����e����*�ZeeeT����v8z	MAAA"�())��N�0!�����V���.*���{���544�x��w�qGkkk\��o;�H8p �����S�	>�jkko���[n�e������_�z"�8|�pZ�]�vE�����e����o�L:;;�e��_*//����������'�|���Y������r�����c��]������?�������S�N����~�jhhH+_�zuT~�����������4C���������D���������V��o~�]�hQZyyyyT^PP0,�r�L&���+++��S[[U����V~�]wE��7o��}���$�HL�81K�d29n��1c������p��y���������@���;w�M7%�{���g�����5���/�3f��	>��w���������{��w@�?�����R_��o������+_����co����z����y�<����p���q�������]HhAQ���&B�uL���H����o�����4Jh�
	c+QT*M�P��R�rZ����?��|�9�9�����u���<��9�����{�<�
@�^y��z��eee
>���M�v��g��[�|����s�=w��Y1	�h��\pAVVV����5�?~�����������_x�����}�J�>��������_�~���r��8��v��F��)Sf��1���#G���6m���o��/����>��3f��/�����G��O;��<��;w�c���)V 5���6l������^�B�O<�������W]uU�E���������	&�)���C�q�W�@�mk��y���|��9y�'M����iW�@�mk������|�M���S���-Z����a��%3�MA�5���E��<���m�T����w��2�_��5��1���?�0O��/��O8���
m[����C���>������
�7�pC\�����W^y%��x��y���m��{���
m[�����M�6���5jT����6���ys�a�����:���s�hJ?Q�d����	&T�\9;;�}��]t�����U���Y��?��5�\��m���K\���_�w�yu��)_�|�
z��1������\w���v���&��%��M�0����k���i�9����g�v�s��������S�M��{��>��1-9�������J��������-Z���K7��_+JO���������~�w�������i�g��}-]m~J�c���6dM�_]�Ys�������IC�����Kw��T}s}��'O���c������@�1����?d���y��@�1��'w��u�i�Z���I_o��������;����i��>���u��/_�^�z��{��Y��Pt���������n����^�
�W�T��?Lwh@Q�]��Q�Fe��3fL�p���YYYM�6���Mcl@��=:++���N�S��s�P>v���DG�^�����x��<���w_(�����P�������0aB���_=�w�qi�
(����gee��3'O��I�By�6m�P{��wVV�7�|��|�����E���Gz��u)��_,��m~A�-�����mS������<��C�0��/8��c���>���<�/��r(?���P�����}��<�w�uW(����P���JVV��'����m�������KKT@q���6m�4;;{��Q��|0�����i�
(�	&T�\9;;�}��]t������U�V�Y�f�;4��������;�N�:���o��A�=�����������o��9�Q�\�<~'NLw�=zt�r�.��b����������L�2O<�D��Y,[���+�l��A�*U�=���>�,�e>9������8���5k��Q�{��K�.MwD�o��|p����6m��s��;���a�������b9��#�=���2���o��%�z��m��B�r�I'}�����(��^��'�n�Z�j]~��+W�LwD�O�aG��o�[n�%�Q�DV�^��S���_�d'2k���?����o����n@�V��c#�1I�^�zH�%�xL�:�~��!�{��w���7a�1c��t����<~#F����)W��>������-Z���O��+�]y��!��>���w�e����:�e�0:��#C������q�V�Z�_�>�Ae89�_h@C��^b�?��5�R����'��e��?��c���dr;���{.�#���/�<$<�-��y��!�{���%�8
0 ;;�A���c#��;���j��]�BK�m���u��i����I���~��k���V��;��%��;vl��e�9�����~�����>!���sO�C�X��>����EK-1���{���!C�����@�c��w���[�j�������]��W_u��9�
9��t�������h���{��������;���k�IwhK�a��_�
*Dv����m�j��Y���5k�����[���/�r��3�4n��tt<�<~}���R��?��OK���3��\�r���a@F��WOcT�M�c�~��
4o�<yjn��Yap��[�4����o��
�z���7nLKH�m����<��3�����U��R����]x���+z����������p���i,Sm���I�&�2o��DaHu�r�������2�����K�.�z�K/�d	 ��C����������	&�T?����s�%�8��@��Q��tt<�<~O>�d�������k	���\��l����.z����&_�t��
�[���������>6lX���M�^r�%����/NK`l��5!�g�}vra���M�srrN9�[v���>��_��(Y�vm��U+���Q�O�>+V�Hc��G�c�q��0���<���v[H�/����2�G}r{���)���c(����Uf�s����W���.
�X�����C��z����%�x<���!��|��O?�d	 fa@q���o�:/�<6��Qi���}���!��=����w$/,_��Z@I�1cF�mg���Y�fm��i��Q�ww���sss�d�����Z:�V?����J����T��m�����>��3Oh����>��D���^���V�G��U?~|�b�4���Kr�[��7��M(�[�n��������Ok�E�c�t��(�y��y��P���O�#�7z����K/�4Oy�=By���9�Hh��V���?�9zi	 |�A����~���;��#�{]Z�S�Z�h}�<}�E�oL��9���
rrr���?D/K�������+����f���Vfgg��JTj��}����y���������>�i���3/%B��7~����Z�j��;7*Y�jU4M��s��o��K�.�L�<��P3I�6m��-�T���k!��{�������E��r�)�r�C�K��+B�����F�+���/���2z0e�����V�Zyh���y�B�X�F���?�0�|��1��ni��	
h�-�����#u(Yr;���J������/y[WK�-77w�������t�UW�1���k����� t�[�����n���#�L���B���z���i,�0 d�L�2={�-i����i�������~����
��j����m�����������������&M���G���{����P�,X� ��f����o!��	'�tR�����6m�-�u�Y��1��s�9!��f��^������]�lYt��_���tE�y�<f���?��S��Y�\��c��$�����*����w�������9��%B�a�V���)S�?���1}qe���x��?���+
.�T���s����-�<���!��&M�^�$�{���\�}�K���/$�j���6m�^._��Y�f���\��p��}���a�U�T�]���G�����������w^���0r����r������_?''g��y����y���D�y6l�U��>��C����%K�T��q�%e��9�*U
�����2���0 
��:uJKxI�K���K?������������
�����'����������,s�����/5s���d�w�����\~/�]v��/�G��%�z���_}�U�D�aG�g	`��)5j����O
P��,�n@vvv�����#��e�<K�I�vG9���ZF�>}z���?�ek�%�G���-=r��z(�v���[�N�G���Z�q��a��us���������������7�|~��zjZb�Tr�P����;��r�����y�����P�,]�����?�<���f��n���M��s���e�
,�>vj��e���&":����*�3���,����rJ�@B+U�t�m�m��}�5��kB{�(I��C�W������o��U��S�z�����+9�������3_���G	��r~����9s[W�9����������n��X���W4�ow����??��������W^u�N������9�P?��}$�K�.���+�3�=��3g���_�q��pK���;�����wK��4�m�I���,�4:�e��Q���h��h#���+'�����>�(�|���y��~��P>h����.3�y�R���u�]!�_|�E���o�9�O�8�t��X�f�Z���F4/��B�2eBb�<��<GZ���~��u����^X����6��D����.�[�f�
�g�}v���i�<fS�N�}��������[o-���/�8�/�%i����P�:�999���o4h}���w�)�������C��O���+-C�j��r^�z�����/^������%�b��!��������
-{h�?�����`��V�&M��l��������&����n��N:��l���QG�<�7o����_�1f9�_�
h�y����+�H����;VZ()6���M�����/�<��}���]��~(�03���/�N��>r~���'~���a���c��03��S'�~���9���GZ'�zz������o�=�H3D4����#�6o��)�*��;�Hl��~����k�=/,9�����4hP�j��������S�|�k�=z�$GCN��E�����Y�f���7n����BV?����g�}��LD����C�N?����]���;��n������%���p�]v)�N2S�L�u�]M�����C��|d��q��EzP!u��;14I^x�&�h�w�R���on��K/�4�$ODS4r���}��7���%!�4���QG����'����/=������Br�;-����Z�j����.�v�y��������A��{w�}��l�����B�n����}�����3h����?>�<��c�ajF����v�H<xp����E�o����n;�����'_���<f���y��3��W_
?�����G�/,0�_dm��
ux�I8���Cw����5k:�&��l��e�*Uj��y�V��0t�N>��D�!��������$��7�_4W^ye�y�;�n�n@ql��)���30o��D�TL.�R�J8l�8���������!��K�����M����Y�fE������q��z�����Z<Af9�Y���Q�FE�t��� ����/��=R4n�������y����������G�!�(��{��Q,�o�1�q����Gnx����;u���?a:l�����r��M���y���~��/��������������:���h�P(��)?��3��i���������s����s���1bDH��w����v���^{��
B�0��@���c��e���:uj*O�>��1��V�Z�5J���}���
(�0�MLh�S�>��&�8�O���:�i�����@���b*�%%�t��={��k������/�Dt��y�R��L�8��Ol��A�������;��1d�������_\~���q�������-�1��r�I'�l�r��=rk;#�P����?~��51��Q�<f���[�����%���]�v:tH������FoE�����}��!{���O.w{�5�:��}��'J�QG����r�-Q�Q��Qg���7��\8a������.�,z�L�2�s�H��CzM�:5�U�n@*�\�2T�&���������?yL�6�M�6��t�����'�X���3�t��U�T?��s�F�j���|��t��������D��D�y�
�i��������S'�2�%����.:�����S�����<f�g(B��(y��G���:�����b�R������l����0�_dk���Z�jvv���s�����B�srr�8��^�zETl��Yt\��9s�W�n"��>��������k���Q��U����PX�v��/������P�Bx��{��9�����g��|�����"77�y���+W�t\lBO �>�Z�J��%�*�H�W\��@v"r?
h�4����������w�I~��%���W'f9(�P����������N>m������7���/N����g��+Wn�]v;vlT�a��n���_��'��,Y���q8���N���^h��e�D�E����^����sT2}�t��q�i�M�81�2zz��3�\�jUT�����P����F%r��x��������_bl��"T���w^���D��Gy$���D��k��3g�Lw ;9��4~���y�tZ�+�����[�n}����7�LU�t��)Sj��=b�������<f7�x�����K,X���]�Z�t���V�^��W�<��G�J�t�I��*���5�\�����Y�!C��+* ���xx�����9�������b��Uu���}��=���'�nm���(=r?
h�4����������7���%�h�?�8p`)��y
��<��S�Lq�\a�y�
��d���/W��n��V��������~�P�)N�o���T��bZ�&M�T�Z����Ow,;�Y�f��m��>J�h��k��6���D�}_}��t����i@������O���}��7�tSa*�mhl�?u�e����[o�U��JLG7n��Dta��?�M�6�I�����(Z�^x��������%Uf?~|qs���+B���)���l���U�V���s��)�������.�(����B7�S�N)��5@O=�TiGEd��M������&�ET�\y�}���aC�c����W�3r?
h�4�%B���L��r�!+V,���}�����4�_(�}�]�*UZ�lY�'��8���p�����/�������?(�EV���g��]�v�3I>��_t��W���5�?�����)S���2D*�"7��7o��P[���P����?���t�����
<J�@?��C��5����z��b�`�?���;���/f��r�M��i��9��I!��\/�%%��E3
h��iI������{�����)���m��R7l��B��-h���c�-[���i�
�Sr^��|��
�2����_}���o��z������q��Z�bE�Z�7n���?����~�m�v�B-���/_z�����0���+�03J���c��1�?����#Gv��)�`x��4����s�>�����j;�|��ge��9��#c�*�x��v<����?��O1����8�[�n���>���{������zj���o�Kt���[o����v.
6�e�]�,Y[T����^
�����D�����rH��������S*�
h����O�%]�8������{/��M���?���{��U+d2�1]L��M+[�l��S�9/��s>l���$���+�YD�x�m����g�yfr���m[�����r�v��F�%��{���0� ���]��2qt�%����}��X��L�M�������+V�]��w^H�M7���q��
n����:''�E��9����I�B�����`���\6|��pY�^�b,#j	@��o����h�����^�9h���_�-A�tZ4�%B�%~:-in�
*�n�z��M�\������1���9���+S����m��LD���^r>f��T.���z�_}��p����a���Z�*��2Rh
C�X�J��?�l]�|��G�w���g���^3Zd�7�����w�y������w��	��$�]�v���a���gv-ZT�Z�F���Nqj4��k��#�;���������a���!�5j�He��~���#��F
#G�����>}�����y�a�V��$��K/���F@r^�������{��NJ�W\��?�-���h@K�NKi�i�����B&{��T.��/~:�_��]�r����5+��G�a"���,YR�z�&M���4�����
�s���7��������@v"�j@��X�n]�.]:v�x�<�������w���o��,�m����w�}����O?�2�>��G�Ox��/��\��.���x���$d8�Y��3�����?x��)F(P,�_���C7n���&L8����].|���z������ ����{������e�Y�f�F@��-�"tZ4����R�tZ~=V�ZU�n�:u����;�������}����;���=�������;������k���n��yl4����l��h��5j���3����-��2���s[�jU�l���>���/S�L*�i9/�M�6]t�E��w_�d��qM�4	��(�������{��2[��e�������G��srr5j����{�Kr^(�'O>��#��!{]�t����=���$��tZb����_��{	9���_������!����Z��Y�_�>�0��U[�hQ�c�Y�y�f��U�\��;l�����eg��_�+V�k�.�����L�:5��d��K��������������?��e�����Ga��N�4)|�a����3�<��h�b
�����s�9'��d���G[�DS@������[�[=��(�^xa��MQ��r����(&������O�%�B���u�P����%b���+W�o����������b������ND����O�����~:���,4��CX�z��G
�R|R�"�6h}����W�Zu��GM����7n�x�]vI�V�h:N�=�\�p����;���l���+r�!y�oy�����[(q����~���Y����������J����!�'�|r����_�>��nr��)J�1�����'�;������w�Y�|y��5����f�����~�6o��d���3h��}����J�h�8��������i����3�!��8�;v�]�KD�h��9�$�0h��tE���|�����.�,�[O<�D�Q(a�V�F�_\���_=��f��]Y�xq�
�NKtZb����q�i������[�d��n��w�q�,���O
6�u�]�.]Cll��y�P���7�Iw ;9/����Y�f��R?����2����J;*4����a��;��#��B�
��~���3����K�	'�������+��w7n���_�[����t��}�Z�b���1�0z��f����fgg�k�.y��@����O�9��Dt�P�GK7�xc��e��/4i����G�N��U����X�xq��+W����UW-_�<zK������O��W"��a���e��7�;��7�|��A�p���0|��pq���c�-��� ^r�%!��F�*�xH&��7`����������������=�PL�-J��!
(�J�]���c�
f�v��<��h ���?�xt��t�
y�����d:t�c�=��~x��e�����I�h����O�S4�y�9�D�� .��[(=��s�=Cn����������5k��R�J�`�������������y��'��m��9��,_�|��]O<��J�*����_��O>�.�i)U:-i���[o������&��j��a����B������;���e�N�6-��2R�oW�Z��>	���[�
��X�hQ�j�B%���?�a�;w��G��W_m�9/�_}�K���Z���3��!�L��-Z�������n��o`
(�t��=t��r�]���k���'N�
��KO�0<����c�9&$?����~�=���3���z�Gu�^{�u������Q��F���SN9��K.����{��'Cn��������������'.�PzF����+��yk�����W5|�^�[f5v�����]�v/��R���%�0������t�2b��4��	B���o�z��%�]�pa���C�k�����D������@�%~�&M�V�_c�������{�Z�
\�"E�Z�0aBvvv����-#�j$��U�V
-cNNNr��@w�}w���v�m�����v�����r^"
���p�{��C`����o9���C�
B-��O?m�b
(�]A������.Q�q�����w�04C�WF������7/�(3HH��Q����s������Q���3w�u���Pm&o
�ra���c��)����o�/_>��m��g������4�������;,yk����/a��[��CF��o	���F����w����/1��W�hW���>���=n��a:���2���SV��G\���-[�w[�d�P�r����'_��R"V�X1t���/�<T���ouZJ�NK��m<r���E�>}�/^����%QX�Z8��s��&L�'�0��SN9%���g�y&�RB_�<�F��k�P��_�%u!{a��������������f��F�]�t�'����������6l�>�_�f�T�6��Bz
<8�
������'�ya4�����!�L1w���:(y�������/�[}�Qh���_��0�����[�B+������x`5|��'���I�[�n��-F��#d2�4yJ?����w��e��A��E������7�*��s���z�B�>}-Z�?d��2e��|����z�n������k��y!�999!�W]uU�K�����/[�l"��'��:��#��bz��7v�m��NK������NK)�i���������C�6n�8�����w���Z.��������/OE��K�&���b�0�q�!��_}�24�]�t��m����1c��=����d��9����\�����#r^L��c�^�z5j�(�%��n�m��Y����M�F���U[�xqT��[oU�P!�[�����_��B������J2������_�hQ���}�D,\��a���k�~��'�8n�����7��u�]���o��Y�&M�D�g��e��999�O9R�'O�T��������N:i;��T�"�������:`�����={����S�Qf�[o�5d�����4i���~z��WF[*�s�9!�������B����0��aC������o����������*p	��K.IG�;��uK�B>�*=����~��^{�(w�c����|��o����3�����5k����G�������=��ce�
������N�����N8�����E<x��'��OR<�������O���������^v�e�/P��-k��u�v�X��'��d�W^y%��{���-��r�
74l�0�%
��'�|���/�����{��'F�����c��!��d�qt<�K/������
6��?t�g�u����[�*U��������[%�.V�^=p��}��'�_;v�dW1�]�6�9�������ok4��K���Z�xq�V��qD�bEg��No�r��W����������A���A&O���gz��+�wxr��/�k���7��������7�~��yV5y�K���3�(�;-!�!����+p��^x!������/��f�����x�����F�
]���NK��iI��1���sN�c�paP:-�=�\���w��}��-����>}�$6��y�%���X�"�WNNN��"JCh:+V���j������~���,�������o����M��*�<�H��<��3�x!4C�3���s���
��C\y6��1cF(�������3���C&{���(������0��w�}�'w�e�<��ok4mR�Bn���A�U�P!�����??dx����?��q����#�8"M!g��={�<'���s(��k���s���
�����+�.��HQ���Y�f�+W�L�2����6lX��7�|3M!g�#F�L�5*Q2q����&O�S�tZ�.:�(���)��s���p�	y�g��]�NK��o��Q�b	 -���B���sO�g����?���<�W_}�%����w���No&�`	~UBs}p>x���o��V����n�	��3���_�i?~|��-����?���W_=��Si�/�����.�U��F7��7����G���o�����K���h����h��<�A:4�?����6�u�Q�Olx�g�?�?��#����3��M��?�����n���Ml��P�E��NK�oa��=a$X�r�>[9m��2��;�D/�O��j?�.������W�;6T,�|�M�0�0h��4��������^|�������O�ct�;�8����~�!��f[K��ya��������P���������@hC���(q�~x�p�#���~�i�EK��OKl������j[K�N���r�N���u�:w��,���E[_���O?}���[���/���Pr����/��1u����v��m����
6l��I��(��{���.V�z�F'j�B#����h�{��i�3c�]t�l�G���x��Q���������O=���;{S!�!�o�������u{xw���i�1C���K!�!�[�V�����m�V���v-T�Pa�����4Cl����/�0�+Wn����
����#�8"�|���i�:C<��!�����R���W_}�T�����������AH�i������P���������];�GG�~��E��N�:%�<F1m	�b��a���A�=�����)
M�����?�����'��,����;/�F���W�R%����'ll�K�zhty�R�1H�i�V�i��C�)��9/��b���z��E�`�|��i8�l��)�gi���n�s�A�.A����DP��e��Yx���B�T�L�D7,!��o��v�5.����;F+�y�f��M��j��V�Z��k��Fv%��'�)m�����������3&���3��1����p��}���������.p	�g��i;����7�t�M�G��/F�����<'2Pd_�uh4C_%�����Y�bE�|�=�af�i���7�}�y��a�	C����GEX(U�,h�kXS�L	��~��W�B���7�|�<���%�hw� ��p)��������^�z���C�z�Qb��=m	�T�7.���O������8��c�
�|�B	����m��@t�r��m<c��E
�������������e����r�)�^����/N�<���Q5X�R�<�������^�z��,��G���<��W�u����&M��y�<j�
MS"�
��
E��[w����k��Q�F�������nw��X�p������'��a4�-'�tR���/���r����<,�x����80���]w�m���\��%�o�����������������-�_�NKHiT�����������W{�;0��_�W_}5��W\qE�d��UtP��=��@�	�L��Y��f&N�X�r��K���W_}��m��i����:�\X������}������o&���:*���<��S�������K�*z��a���^��;��{�����_�z^��68m��Eb�|�6�B%����7����&)Tw��D��x�Z�<%o��f�
Bz��-��w��>���h��%o���v�.�����b[��e8�����>�l��w�a���*E��K���x�����+���3�J����K~��������8����C
f������C�%K�$�9rd��O�>������ur�$���Dh�=~������@��i)m)vZ��Y��M�h4=e�����f��Y�f���"R���+��]��u�F�����E�%�<��P(�6mz����=��f���|����7�-�-^q����
���-[�/�L�l�����z#�uC�0Q�ok	�bz��7BVz��DI���n��@��xb�8B�B_�������G���\�2��_Dhm�;-�q��<�����7���������V�V�h:+�d����-\������zY����O?M��4=}�t�sVh�C�~��D�����U�Ti��U�;A�����W�	'������>8x��&M����8���&O�m��l�������zh�%~�����G���d_�K�G�NS�;����w�*1Mj���;.$�i���~��H�f��C�:u�M����Gy�{���V���c�D�(�y���O����+��=���P�tZJ[�:-��-���+_��\������z��ap�SE����v����,&J�O�O�4)���3�1��Y���N�v�j��-t��5����a�����w\W7pq�)��(�X{��(�v�{�
{�K��
c�^b���A
�({A[B,(�DDP��r�����.�e�]~�?�Y�����e8s���{y���u�8p 88��K�r��;w���
�����e���Q��*J������T���z���=**�?��PM;v�2
�t��0Bf���t�����>%�4:}�4���W�Z�!M�����<`����$�U�L��/}.iU%��<�\�r!�.]z��I� RJ����m�w���e������U�Esa~��g�4��X�b�:u����k��R������:F����YGC��������M�&^.�i��S��M4������B#���v����%$$H��___�q*Wo�Qtt��i�s�N:u7o����(
��J��n����^����c��k%''��qC���s�B@|&���K��2�P�t��&���@v����?133IK��-���L���+� i�
��5h�)�S�i������'����oP��h`���7m����J#��a^�J�*[�;fkk�Ob��yr�Z��k�n��U�G��*T����S'����(\H��e<-���Uo�S����������.P���i����/^=t��|�;�����Bs���{K����9F��tR��|F%��r�Z�7�������f���q���L���M!�MGFFR$��8�6������$���
��		�qV����o��&��i�������|�Ze���^��+R/��A��Nc:��v�T�zQ��k���{��]���� +-Z������S)�P�� ���L����X�3�����_���zi���4�k��-HZt�Ni:�y�-Z4{�lno��
���+�.���4b]�:tH��OMM����FJ]Dc||���O�������SA�KHXX��b�%�Q	�k����YD��*U�����4z...|c���4��K����P]�'!!��4H�N�Z�j�)SF��5�R�bE��'44�&M����/�������F5((��B��(Z�d������n���%��������&�#G��W�^��}�37����!C(
��h���i�={���]�6��P����Wy�����At��-[V:e�����M�Z�l��Y������i�m���];�z�W�3�4�Y3���kW�M� ��.ZE�����*�&�������{7�N ���E7Z�jE������5�CBB��8�k�7o���L�F���i�������B:��n���DEEU�V���&&&���W�B��9s��mgggGGG���Hnwuu��\u�;�W�������;4�3g�-aaa��+��m����e!M��>R��|9xr'f��;x�`��0++���y;iHx��dkk+�
H��%y�����������-[V����Q�d����1��u���~��V� ;$-:��E7P�Ktt���I�����S�N����E�v������N��4L7�����������_���o��GA��b��fff]�t�������?��5�t->|8���g�������A�������f��t(>>^���S�N���1�T���s�N�m���A��i�v�����i���v��I���C��V�����C��O�naaA?�h��}QQQc����*w7
�� r����G�ziJ2�y����B�X�n��m�7n�OL�8����������$�k�8�+U����{�/ ��
����E����J�����C���h�������o���`����m�V�90h� �-[��}��K-j�d��?�H�K^7�RD^��H�"�+�qHwtt�������?y��|��Y��9,<<������������

�]����16���G���&''�}���p{hHJ�.=`��ON�:E���Uw#�y������&�?			���"�-^�����EZKa�[�n-o'
�����������X�UC�-��'%%��_����'}��S�N��r���C����&�M!www�7�(���s��q����d�`jjJ�;�:kh���I�nd���Es�����k�.��'+W���jMz��-��
�����t��%���?��@�xb![T������=a��(2��Jx>GC�|���
��"##��(���'N��������F�k��j����%
!s�����&&&����Qd,jK�wa@g>~�(�/�y�f������e���[�'L�����y
JJJJ@@�������x�"��Bcbb0�����>|�1������Xf��A���N�:����aQ
EGG�]��b�����g��>J�D��4@�*�/E�n$-:��EFY/ i�.�#��~n/_�|����'O���:y���U���9#Z�w���?�O�.�&]d]]]mll�(f��g�*U��i�&�B���}{���7O���K�-���jK��	?~��A�(�`�YM<��N{�	)?��+W�syQ��?�0����-GO����Kk�����+�jjj���R�|y��p2/�.Qx0`����i�FlF����o�W�NY�+����� S���
*�������� ����G�O[[���j��m���s���o��r�
����?p;����l� g�����e�9v��5������g�����2.@v%''+�R�A����,�4iBB�W_}E-%K������N�0!�������dG��g������nJZG�K���[w��]��� �R�4�9v�����x�B���}�v^�~��ab��7n��j���� stV��]�&;aaa�1..N��r������ ""�t������Y�.��'Y�hQ��=�����W�V-J�j�&�?Nc^�P�e��=zt��7o��~�i����j�*y���f���I��(�R��s`��m����������l�E[�l��/�l��I�r�P���KvvvX&BHZtI�"��
�^�ZT�[�n-����_�fMZ�}�q����l�4�r�(��G�n���5�"L>��!o��i��9�:4h��_�r���)������x�#M���'>������}i	���k:���y��)�!|&+���qHZ������bm���!��"��������:88L�<�a����w��={��nt����{�������cTT�|�z������&[(��:K4�|����?��t�WHG���lmmy�m������j������+W��������c�u�<��.d���sl��
Y_�2�@�>}��&��[�w�'N�cJ��;R����,�����2Xww�L�E	 ��={Fgu��Q	����&���IK��V��Q	I��V�\�7����(�(}A�|�=4h`ll.KW��R�����������KKt����)]�4�;����O?��?�W(i��m���BD�������e���9�(E����x��E�
������CY�����P�T��#G���Q����Kuj��]��5k�~�:-=!�?�R	����]�v��&_�F���oJ���������
Mm���/���iS��+����J��K�-�Qw@�����6���S�Nq�%�MS����loo?`�����Y���R�P�:d��@����w�U����{i���-�y�����}���g�%�%Q4�suu7�i`[�l��E�bcc����������e��	�!~�����}�c�����X�&���Z�*
���3�&� N���@CHZtIK��b�&"6���:�n*���{+�!���u-�������:��!%�����7���I������h���!����+W��%������z	7E5���]�rE�����b���Y3,�*U��C��@�.](i)^����,<E���wJUw��L���Ci�*�P��?��2/ ���L�2-��.\���h��U�~�x6�tRx��9m�����uwwW{����K�w�����@W���J���g�/_��+%���J��+�o���LMM���011Y�|�x��^�>�E<�V�e��O���;�'�<yR���{�kX&%��7R`i��
����!i�=$-�*+IKXX���u��E�%�������e�����O�1�A�Y��(���s��e�< �8W����:u�����fT��R%~���l�@w������u`` ���+��e������=w��A�)�7� �D	�o��NNN�e�%�.��V���v���*�,�/N�L�|��m�_����d�������g�~������������INN�,�c#M���r4�&&&<P�'�-�aW��!�2�M��:JI���Km�����m���0�q���
����Ci������������ �N�:%>�<�C�Q�~\\\���i�!����y	�o������{��K���X^+���*$-��<i���
8x����o��
z���������Q0Y�z���
�F�����k��@\��@'p�f�T���-(���_~�n�p���V�Z�$�d��tU���,�J���W�!JZ���1b��Q�(���G�J���8..�m��������=��yd.&&����F��������5�v��n����@��Kz�r&��tF7�������=�>,,�>o�������}�����^�������S}5m�4����7^R>66�������?����C:��A�����?�s�&}���AC������%��%���Lif���������Wo���t��g�U�V��Dv����G�n.~8D�(�n�Z�}3$9(P>#GO
s�Babb2z�hwww�E�)�/*R�HI;�+rw���@����N�E	 44T��39+�}�V�.�������/_N��ZO�<I��������GGG��?��a��o"##�1!!�L�2�(��i�����[������������Zi6}����������B�w��E�7o.=��I������w;v���s���\�r[f��%�i~G-4����_��	e�4�@�KC��n��M������aC�7�A����6$-��(i������?h���/y����7�Z�Q�dd��U2�� e�i��g��U���7�&�U�X�"6���u����:��G)�[ZZ��7C����%K��k�"
e���t/66���C�����!�S�n������I�v�EGG��}������o��imm���'r�?^�re��+�&���x�sss�������py�g�)���=��k����`�3f����[[[,>�9~^1����C��'[V�X����5k�P��i��������?;v�H�hff�P(x�E	��`<p�uHZtI��e��|��Y��.���O�;v���������C�(���I8v�X###��!��L��kW��]���(�����K"�
e����,G
�qN�>}��	��U:v��y���/������W�^������e��)X�u���~���_K�-Z����Qx,]�t���x(}������g����P�|���G��Y�1l�0�z��)�Fr���R�JQ���q�����_�pa�hJ"c����hHG�AW���`����N=h���sE`����>yN:j�^�������*
�����H��:uR��}��i������������%��x�%�h�F��d��'O���ELL��q�h���h�Y i�1$-:���4j�(�D.��7���k����������Bw�6mD0�$000P������Lhh�x3�H�"��0Oa�n��t�cYNM������*���Z��z	t�a�����K�.]�bE��E�O���E��y�n
�+W�<|�0M�
*��5G�'O����i��q���fff|��Py��E{���]�FIl�.]��4�|����Dc��];�N�:���m�(
�d�E���[�h���1M����a��~Z:r��Q��"_����O������+�^�U��&������I�.!i�1:��7oNc���>q��b����:u��y�F�5�\�~=::z��i��"V����
#e�@����Z1D	@72)P����d]@@���I�R�(�p���z��mJ_�4�.���wvv�Ri9 �L�F�V�����={��
�J��y	���� ]�y;�����x[�����g��?�U#������Ge����h6������7=z$S��������{���$��1��:��;���d���J%�?������-Z`�]�����~��t�������999���o��(h��!i�$-:6l�0
,��o�cbb�W��Z8p��-�{��5T�������@��@�$''{{{g��N�#� �MDDD��KA���������Z��FT�ift��	��k Z�limm���(A	 �N�:���W2*����Z 3���5k���<{�Li6M<���q��Q������/{�����\�~�t�s�����'2u�-Z����&���(��7�5�u�����C��%K�(�����Y�f�$z���)))rt�@���N���g�?^��:���K��(h"55��g�O���gs����}��]B�"$-��U�a�������J�*q�����;`��&n�in��94�w��Q{�����n����&M255

�a����#�%�LJ���=���K�c&�@��G�PHk�+W���"-��s������������P$%%��g�{������m����.**�233��Kaaa[>}����C#�3��?9rd��
G���� ��ejg������D�����������+W������]U���9{�l��E�^w&L���]�*U�������!������8�6m��?(U-��hTiHEl�8q�4��	����cbbZ�n��cG{k`Z�lIc;g��C/^��9�����N�}3$HZtI���������i0�:�4�U�V�>,,����K<��������xzz���<yR�PBBB�F�j��!ZP�����H��%�@jj�7�|�k^�F�1n��U��5X��+Q����C
e����\��eKZ��Vi�1�1Jil�4i����={����$�F;�e���3i�3)������f�"'�������)��'���1f�����c{{{++��+W:t�Wp����!�#b#�W�.IZ���F���iS���7o���{wJ�-Z$K�������z����T��]��r�(����s�C�U[`y-


522��=r���Q���$�N�:x�^HZtI��������;i�iH��;������w���Oo
��Z�277���9@�y��)����������?�����}�b��t����5������9�2����#i�
�����i��%R�8q�D>��sg�--[�,Y�����e��^JNN�4iW�������v����;���O��o{AdR7�����s���@�:u*Z���.\���.�Oi��4�l�_�~����P~kaa�	@Zzf�{)��)8p �/\]]���O�:k �/QRb����n��I�Igx�n�t�ACs���>}�\�vm��u�
����n����{��E'N���<x����O��B�T�\9�
6��YA����K������:�4�arI��!i�=$-r��������'O��P(��WW�\�~����066��k�|��c���+
`�^��;F��Y�f����stt���S���J&�V������O�2���P�����W��
��P����.2�}��U�R��������r &&�F���"6�F�q����iT�/.*������-:���Q[�t������@.&&&�O555u��A�s:FW+�k�
������] ��=[�P![[[�#�z������[~��|�������<-�$miiI�5k��y�&���/�j��%K�4i"���|�r���UoD�/��5o��"��5���t���&��g4��c?~����	������H@�<��P(�~�-��������k�-[��hI��!i�1$-_��m(�K6lz��y�[I�u�z���Z�h!v�	��&5rE@���]=���U_
�l����M#)-P�=ztF7�!7�6��V

rss��s��)�#%�-6l�������7��2e�DDDH�����7��Y�����	&(�(Q)Y������{t������#G�����5
�C��h6
�[�v-
����?^�|�&tta�������?}�����W�Z�y���JDCJs
Jn�����b^����+ta����"/.J���i�{t���>��K�.]�x��������@s6���3�p�~�����=z��y����S`���_�5����O�7n��bW(�����i�7���#��h���
����rw\�!i��]B��{[�n�^�z�*UV�\)����|�{������������M��{�n�D����b����������������7���r�.��&M��Bi!'�J%���@C���������+7v�X~�H�w������;���U�}44���|z;;;K������U��[[[o���c���'���*U���_g������M��(�������(�)�P��t�:v����Q�����O�/.^�{��9%ft�f|4�vppPJ [���cnnN�����/S&F#��}{ny�����_*M:�
�4@4�pqq��,\����(���u�Rf{��=�<{�l
#����C�T�����|�����T���MWO1�III��M�������,&e��
����I�\�����[�hQ>���[���yC[[[������)��}�V��������+S�X�X1^HZ�K'��HQ�.��A����+c��
o��-)V���&'''&&�e93�4t��I�82GGG�������H�:�H��.�^^^2u�p����z���K�[VZ�������:h���H�����2vX�?~�������,��]���2�dt���A0@�f��'55u���|���D��^����3f����/_���|�4��w�����c�
M���6���f��oB����i���(����(��'Npv��������9z���_]�~}�B1i�$��&n��A'��3D��;o���J_�w�}O�j�Y i�$-:v��m###����M�[�hA-vvv����������W�>��O����?7o�T[��}���e�����i��y``��]5���5k���n�RZ��N�R�J��Y��������7��A��?!!!�=��)�W�P!..N�n����'O�����%���}�)�P���8e�<��	m�h:88Hk���O�<%�/���y6�d��Cb6M�;�,���7obbb�#""hxi�,m�U��o���+x��
,(}�Ru���r	���P�|y�] E	����t�`P��I����}����}���h9|�0�F�����i
����ix�jo�#��$-�ASf��IKnC��c�V��[��XU���'�i�(���r2�o[,X�@����J�E����<��������]4�177w�il;u��T���733���������+�h����i�G��zh���(|�~��'�M/[�L����f���y�����:t��+���}��=����G�q����%**���.]����&55U�PT�\�T�G������!��%�@c���%h4��?�������
�P#��S����{���b�����������y�f��6�-B�����?�K�R����&MH���*$-�D����G___OOOi;��R	������7m��;�C�|��������q�%K�$%%�C�%����O�����WWN�>�z����|�M�6XIL+���u�V��u������%�6[�n�_��&(1b
x��=������'Od��


�����z�.�_}�OQ��(��4h������4���4'���o��Gp=zDgcc�'N���#��a�r��a�m�]�6
8]w��A�+�GFF��C��y	4A���h��[��HF<��OA�o����{7}{�iK@@
o�F�(�U}������e���C��KN�>mbbbffV�V-^v��Y���%�!i�
___�z��\�Z�6m�(U-����k'�g�A��7�D	�K�.111�g�.Y�dBB��}6$�~�-���U�5j�����-!!!NNN4�4����)jK�!J�,(e,��oGE	�r���n�:|�0}���2v�������������G��SSS:JY%�i��w�/0��
666|�III����H��uk��O�4��)�[�n���iZ������[��}Q�������.I���*�r����)h8���#x�e
/���������N���]�Z���n��>�
��#'�#RZ����;�8g����G i���?:88��]�_&z�����#yN-�=A��������%Kh�*D�������@	@�(�h��-�k��UhNT�re^�Mm	�M�0A�>���_-Z�Fu����G���C�a��X�Ct)4Ngaa������(hWHH
8%-W�\�`B�7�'��m�%V�^=�m�E^^^4������R:Dg8�����:t��|�0�����?�Ui��]�F�{��\��}������g�����L����wG���k��������_��-�d�nv��U��C����<%�����R��t��������� ,X�7?�~�:/�����c��i��������CnV(4����Y�^��J*�	�I�v�;w���G�I���7�6o����E������W�h�������.]��P����n.J�[I�����a\�n�h�v���J%���H33����c�"M��}���C�0p$Wz8�2��e������M�R�vm:�i�Cc�p�B�t�/��e����`P�$Di�d����hJ�mnnN;�����

���_�2J@5jDc��������-[
.,G7 x6M�^�����������B�����U�;vp���{��}��:u�����=zT���+�$&&��?���-Zt�����(���%K�/_�������1� �B?~�����g�;V���O�z���o���@TT�t`����-[&-����e��"�*T�B
��u+M1��G����i�O���k���� �A���?����i�\�jU��������-HZ�I���B���g�>�b��"E��- i�\���ix����?�,�L�2���R	 -�
&G7
�������^���a7zxx�z�*-������)�������B�U(tY��")��f�j~���x"ZC?���R��f����y
m������c�p�����B��RGNZ:�_�|����M���e�2dI@@���������C�;���~�.I\*��("""
������B�
U�Re��=����)�xk;!!�����w�~q������.���h�\�n]>���V��?�������sl��a4z�;w%�Q�FQ0�:u��#Gz���/}qQ�t�QJt)���R�dI~(Z�����EsS�L��BV���8�+���/�������W�\��Ei{�%�\���i6�7����k��A������������F�z��g���1c�x,
r�.����VVV�g���a%3F(tsV������R`qssspp���~����c4�4�����P��������������w��i�#��7}�t��p�B~`��������)�h ������<S`�7o�p���k\���6i���
%6...
��T�Rb�e��}�v~4�y��jo��s/w���}�/A,f�t�����p������o_�L���������>z��M���9�R[[<x� ������f���[�D	Q��666���_���R	 &&���i��k�3g���w���,e��X��hG�������f���n���
��2���+-��@�j��]����ZI�������y�&����xQ�Y(kO���
+VL����;8�\�z�[�_�����cnii��5t�������	���,J�',,�B��������g)E6lz�������-...�{!�~���|��'���oyw�>}�pKJJ
�s�L%3x2����ws	`����G���G�(
�}���M�9s�g��7n���m`��VV�J�z��������]���7 J4����R��������G��s[�.����4��}����C&N��t%�����C.�����F���_�P��s�����i��/���E�p��	^�/_��Q����E(�\�r;Ci��)9W]�%��s�������j���*U�n��Q#??���[S`WZa��q��t�Kk(�3Eo��Z�G�����G�����4�+U�T�2e���<����rss;x���Q���P���������������7 �r]�t�V���P�$J�

��	�����+W���e�i�(,_�\����7o������W���m���Wzn��5j��&///^�������_��\.Qz{T�(�:t��U5���x����{���R�~��EyOOOic����>��E'�B�����z�����2���#J}���}R��������'O���wz�g�D��'��4*Q���=p���O�(C��][�j�����T���G��~%0H��/^�O����t���J��4��Ev��d��ax��}��������[p�������m�5k��
�e���������?����<y��}4d������`�_M�:K���1B\"il��]�v�/c�em��������O-Uo�ST��?����e�&�D������H�urr:}����2<��V[���Y�f��o�G�x���E��3S�S9777��[�,,,x[C� J�XM�R��C�V�����C�"�LJ���={��v��q���e����FFFK�.����$��W�\���5j�(6�
]�p���t�����$$$��A���A��y	r,<<�������K�.]

���3����J���"���oCCC����ys�{m8��iC��b�
���L�2���}V
 �����3gRb���'�{���/Q*����f�#G��MQ0<�P�R%��a�K�I��N����{�_�G�,--������V i����u���X~099y��Y\I���JK_������'�v�q�1���Nl�5�CBB�������[�@nh��q�j�����W�K�.�O&���S��K������q�P(j��o��y�b��>(������Y#w_����W��mkjjjff��c���hn�|6
`�D	���������;��Woo�2e��H�+W�����1���I�,,,��;'ww���/JZ�`������������7-�)�q��988T�V
��j��?��������^������������h��}+����X�fM:D�L��C�7j���T�!bc����Z�j� �����D-AAA�5������n�k�"����������i��q���\[������v������N��|�D	`���r�E/=z�4]��u)�m��	_�f��7�@�*UP��>�����C���G1���	%�!i��q	`��ErwD���,Yr��Q1T�~���t�[[[�����o���g���������S{{{��3f��C���\�|���?"""((�v��������2��9�7�m�V�!�?~���8a���E�>�\���/x���s���=�t�R����y����L�2���OK�`�����}�x�����,X@P:�SSSe�?����c����
�Q��i��<UW;�l�&�41f��U�V���]%��P����="5���'������t�+�}��tt��%���0`�^��E	����H�"G����n�:���)S�hddd����7��+v��	�����b
7
]�x��s>�w����FFF��������p�O�������_��u����~������+������w������|�z@���f���7����M���\����|	D	�Y�fr�E�����
���o���k�������|	D	���Z��Y������/���U��V������f��{��iSQ �9$$D|!88���\Z��H``����
�v����8y��������,e���?�/���W�^�}���"x#F�h�����~�����R	 &&f����<y2v���Wv��MC��@F���koo���_����L���m��a�k���;v�x��M�;�O�;F���-[�MLL�j��{�& ����U(cQ��dI��Phbb��t������RY�fD	���)44�b��J_�1W*��p	�}��)))JG{��I�<x K��(�d�w��J�^rr�j	@��r#v�(���??�G���^�B��G��5:@�t]��o�Qf;t�P���'�n���?Rh����z����}	$-���@�B���F�A�X�F�P�J�����~%0T����.}���l����}3\022rvv��s��Q� ��;��1�����KTT5.\�0���LMMt�S�Oh����/Z�h�������������������[�����'>�\�Z�^�z���?~�C����OC�y�(�3���k7o�4h���7O���=Q g��Q�J`�D	�b�����{������K�,Y�ti�M� ��[-Z�P=��*Jk����H���Hj|��%o4k�,�bkk�������>i����v��I#�����G{{{�I��������{u�S��~�-
WWWSSS�>�vxHZ %bggW�X�z��8p@�~Q������i�-����X�w �����Q�r�J�,9l��/^��/!J���%��+W��o`������g��������S�NMMM�����(GO@oDGG���P�h���h���q���X�ti��	d����Lu92����U�T�R�H������� Q���<w�����{����O��q�������CCC�.;��D	���Cu�=�����_L'�R�X	�������>@�@	���#��������[�*
jo�������<y���omm]�L���_��g��y{{��/��oZ���N�:�hnn���u���k��u���ZV�X!c���ljj������@$J(�XRR
���1����k���-*Q���'J9�~�z,E��{�.�g^�
��<���+
4P-�(Q"�D���y� �LP��7o��]���\i	�&����������������������}	����P����[�h�+N�:���i����(J�g������W=�Y����g�f���#=��%>>^m	������������������kY�{�n��t�����t�2a��k����=�G��@�yJ�X�x1
��u��GL�/�yJ9v��7�F>~��-��%������� �#H�����E7n�8v��_�%m���j���D	@���+�%J��'���@�V�t�1�/_j
Ehh��}�'&&&qqq�M�P����a��������!i	 &&�Z<���?��Y�O�<quu��B���y������5k��>�7�&����C&I�����-\������u@6t�]�be�rwD�����3�j�&$$t�����gi�%��}�b�_���R{���{�gj��egg�����3g>|�����/^���@^A�Jt������Y�jU�\�H�?��C|A�J�*5r�H33�n����a��EEE������:t��A��}V[����Nxx��}�/��&-�@Q�g������G�����C������ORSS,HQ%!!A��v(�,\�P��=����.����_��6m�d�T��c��P���u�C��v��E�������?~�����@�f��Y�J�*�y�F�.�������U+\��������]+++���}����8������_�YLZn��������g�����\�?��?�^���{��m�v��q{��})t0@������!
;��)�����+������3g�����_ZT}����O��%J��Y�h�loo_�re�L.}���+O��f�th��k���{���M�6Q��k�h9}�t��9�(�����l����:
�#[I��W�(c�(D�j��_����S�(V����I@@7FFF���S���s����%j����yO@o<y��"���i�-���jLNN�^�:o�o	��XYY��[W�����}��t�K�#�gcccJ�=<<x6}��e:t��U����57����?^�x�������P�<�r���$����@�����+���5�n�o�>###j3fLrr27R����c����]�&S@?L�2�N8y��h�{�n�����i����"[�l�*�\���S������y�������������)Q�533������i``����0t�P������<(R�H�������Ws>\�F��5k��__���~@��5l�0�Rx�pi	����@��^�b�+Vl�������,X c���Ey�%��8t������S�����Y�v��1h� ��E����u������C��84j��z����/�G�����g(����LMM���S��u��)#v�����i�]�B
,���yS���A�Z������ �i�R	���d�����^�Z������}{bb"e#�%�g��u��Q�[
��"@��U�V�R������9������{aaa2v�����)���y�hIJJ211IHH�����o�����eT���sHH����������e�!�
 jKi�Kn��i���w����{`��={�`��!C��]�6..N�'&&���f���/7m�t��E:�#�Jn���Q�FM�<�����C��O��r��!���o�)
��	�
I���O�;vLi"�%���T9:�����N�8���;����y�����[ZZ�w�
.��~>D����55�w�e��]����<%>|���S>���;�z����\��Z�7o��u'&&��U���M�.�@�Z���4j�������%>>^%�=zPz���cJZ"""d�0�����r��q`)R���?�,IK���;���1c����u��{�������=]�&M���x�b�}�MLLF�9`�J�)������6l������><s��B�
�fy���t466����Z�������;99��������k��!i�KJJj��9�www�[�V�:u��y#�#J�J����*^��_�%c���@		
,m���Bi��m��D	@�P�l�>��7O��2dH���E~K� ooo�&o��%i����3F<hG�qbb��]�/����)�]�v�hy��A�*U(��-[���W�\�����BS��G���_�HZ@���������111��WW-��s�b���/�*��EDD,X�^�z�_���%�9s�p&����%�@�=z����i�&�C~~~��|`` �����5~1
 �N�
.Y�$%������5jPli��	/�����}��Q���K�:�I���w�R�6l�h����T���J���aaa��z���P(({-���j	 -�������������_���vvv������W������D��DW��}��w�Q����#E��4�.Q�}a���:��+$-�K��_O�C_�|Y�jU���0ggg.�S
X���X�b4�?r��3g���/��l�B�>DIrOJJ��!C���m[�/|���v��t4  @��=u���"E�pl�x���>L�(���o����@.��s'����������7h��������i�oq�)Q�D�V����_�z%w@?�/_����7����y[4>��sg�--[�,Y�����e�)8����g����]K��/_������D����U�M���R�)R�M�e��)$-����=<<x����'+
���+W�_�>�cc�]�v��M�3�W���w/}x���������Xu��}U�T�����B���w����M������*�u<~��'Y������\��������>|�`iiY�jU��z
I��/^������G���aC�6��������c��&M�D�	�U�������(��:u
��n������t�LY���m���qI�%�6m��cul�����c��z
Ih"%%�����������F�)��H�E,����j@��U��J�9��Y�r��u��U)h�;D�E���������>@^'}��C�[�lY�hQ�"E*T�)w�@_������~���v�����Y����B�9�����}�|�������+W�p����3n>|������o��2�oo�|�k��1�
hwwwj�={6�x��KKK///��y�t6�����W����'$$��/�o�@����M���=+w�@�!i��3gN����.]{���n��q�%�h��~������tuu��������p'N��X��o���f��]�@ji��mRR}!$$�"����O�4����B�
qqqrw�(1����<w����!J�z�JII��;`��@v���(���z�j###�$��~���m��)������_u��������O�%44������=������8�899=x�@��������f��-(��!i�,Z�f��;w
(���*��i��Bq������O�����w���S�AAAG�quu��{�����/[ZZRl��������g[�n=x���t�Se�M@n@	�I���~���%!���7n�P���)S��7�}�@O=y����L�P�-[���G�G������������lrJ�uHZ s�>}6l��1b��/���D�t���'����m�����U�V��Ju�������C�}�
�M+��{���0\h�����o��$-�9Q(422
P�B��}�����u�7�_�w�������Q???�@_ ���������w������0(HZ s�P�`������j����x���]=&J���'N�H���K����6o�L?r��i��q��Urw��(�;611�:T�@�N�:��7�<B������A��V��P(�,Y"w�@�����m�~�\]]y�3Q��&�`���~~~�?��S��D	�}��6l�t���=�sD	�������rw�(�]�V���Q�`aaq��9��%���%�IK���rw�(l��I���Q\h��a||��}��{��%J��yS���]�?NLL��`h��{'w�t�����
endstream
endobj
17 0 obj
<</Filter /FlateDecode
/Length 1916>> stream
x��\���4~��"�Hu=��B��g�$xZ	Q������e���~��tC��n7;��f�o�x����Q�-��;�}R����=�P�~x=���==m�����<$;���vzs�>���S�g8�q2YL�nT`C(U�j�s�E_������.w��4w=~����?=�{6���p��D�9�O)f���M�+��������Z;��p��)kF����H����,�
�?���������
�
Y�b���b�V�
�����8��t2Ni�z�L��>b]`zP��^=(mXBiI?*��X�(��vE�S�[��V��N�f����#���d����QNg��H����{��Q���Ci������+���p\�B�PH�h�$}���O���q��0����.@�))�3SL��Q��BV�A�/VTcI�&����}�w�0Ad��`gGAR9����@{}�6-�`	)#��������a�-0�����`���������<���\��R��F�F��J&x�O�F���z������F2�����q18�C�Aj.9��������{	>�������=`���a;2�(����I���@''!��`���z�B�.:/��d����ek�	�K
�R��)��M��_��R����E��bP>��!��T��h�m�5���:G��zs������t�m����V�o;f���M���j���F�6���hB��FNos�S�o3&������.�]���\
�V��F��.�]{�^�����"$�uT&�F���]�dQ�G����H�w��k�y�UI����0C�E���c4�dQF�������G���dA�F�����pM�A������/������e��9r�$�\9�d�*�l������4z���*
N��eg/��4I�w�ML*.��+�S0�(E�#��C�[� �����	�vu!�b��Z�Lt
B#t}�P��.�j{��8����B�+o���I��2����D�:�_!�����6M����w��im��?2?�ga�����X����&q�Jr��nPF`��I`n�KF��_Xg8��&IF����:x�������5#�B�Oy���C���B��9��|�]
�J��B��F��u��5f�D����.nx��>�?�5�g��[�sVCd<[���s�: g��7�����M��O���'X&3���ls�i4Ts�Y����<>�W>�|�����?^#�|�T���y�r=f�p��{u}�I��u���yUx������Z�#j��I"���Si�Ox��qlWy�q�=��
�2�v�6Jc�Q@K�Q������[w��K:B5������� B��}��?iqP��Q��pP�f|i�9@���t��(�����R��)B��+ ���4qh��A�uw��0F�yww�Db�
�����(��n���C���J����@y|[���{��A�A�L�-BB��\?���n� �����{&OBK���JGuu�`,�p�������WL0K'F:����"��G7���q�`���9������4���)�I�H�m��!���J�@��t���)��
+���n��yo�������=f��L�uw�K(�����g�;[m���i��\4����t�2��W�)tF����Y1���z��?N?�����s��69��W
5�����0��R���J�+����J-o:/k�Rvq�����v��]k�D����Y�ye/*�@���K�Z[��&m�z�����w�dX�����&e8�����(f������<���"��G91/+�H
�J<�pV 5�JO�E���(&���`�����"����gz!�.E��U��N���"��SF���2y0�2��!X
�� �Z�#����������o�:��s��Bt�������Dg~��_�5Bb
endstream
endobj
19 0 obj
<</Type /XObject
/Subtype /Image
/Width 2048
/Height 987
/ColorSpace [/ICCBased 7 0 R]
/BitsPerComponent 8
/Filter /FlateDecode
/Length 36777>> stream
x���k�U�~0�=*.mCM�B����J�P�L�o�TMS<�R�$551��}�   �����
��P�#�@�� ����=�OX9���sas����/+�Y��?���3;|����s�4�,O���_~�T��`���v��yIOt9�������k7n\S]��c��k�<yrS]C�.�hr���KKK��Zaa��\��#B����������P�??6l��a��U�����b��9Q�g�y&��eee����:u���?>!��
��x���{��7�r�1�&W_I��o�i���w�}%y��W/�n�B��������
�=|��x����
<��O����+++k��f�����g�������:p��)g�q������k�F'Z�n���Y�w���&�f�R�!C�����9�=u���o��Q�����f���Q&L�={��i��wN�:���:c`������O?���/���%=��i�����^��L5y5;�%���s�i����1c�Dc�
����}�������������c��C�dr���!Itt���c�|�.g�q����;��S�����YF�q��������������W?��C\��>}zYY��m��������Qph�������G��s����CM>c����WGE�Y�f]���oZ�`��;��Z�W�'M�]@�C�gu���0d����kjjBO������v�1!���c���+W�j������%q�-[���?���}����Y>���s{�������S��1b���:t���-Z�g��:��w����j��i���[]]���J�y����g���kW������;6<���/�����+O�8Q���L��7/�	�B;�|Fh��������k���}���0���o����
2$���[����3TTTD�����4���#c��I��������^��
���?>���3n*�� ����OY���F}%��F��/�tg�����J�RK�,�_/S�W_}�v��nv��9QQQQee�o~��:s._�<��:����.�`��U���3g�+��n������6\����^�hQS���/���?�����g�Ey�}��sx����'O��d_��2eJY����������?��7<cUUU�'O�F�]VVv.���WP3J����z�_XXx�N}����
?�]��%K��;v��o���{��Z�*4^|�����I�2�~?���]�v��Y���/���/]�4�0 ��7��[�.48g���p��Q�F�o��F���oRz��W���y�����}��3f��_�fM����������O�y~�����������E+���w�9�pl��u��y���?t��(���>k ,�L���{��������3gFGG��������\��+�O�>=.��>������E���7/??��U�v�J&�r����w����?�?��-z�|����4(
��ys���n��7���'N��}�����8p N��+�80����q@uu������d�� ~M������_���G�I8t��������<=���������2�48v���	��^x���S
�j}F���x��<dY��������s�=E��R������j:thii���
��@}%��,[����^{�.#G���q�y�:�����������F��/f���Q�w��%�����o������k'\�hQ�����~iL��m���8�P\�
T�g�����^����������?��aC���5d��(���?�3��~�m4v��i�:��,������T�������%�����������%%%r/���J�c�����_��o�Y�!��J�R�>�lT�����~�'�|���_�/&$�����_������=Z{���[���^J=*_���^�o���S�N�b&M�T���jv��@�K50�Q��	���O|��8���eY�/))��+���uz���kOl�3��$///�eA�U}%�a����F��v�����S�NUUU<xp��5�u.\�����:;{��s��W_����c�9�=k���������kW�1�&M�2���^���o_}��������e����Y�n����N���8��u����{����O�8�p��-U���qg����/�wF�C�����W_I|��	���������?�����c�����������X����i`*�����;���W"8k���/#8�=v�X�1���V�J�����j���?�<>E�{o������80�o�L'O������������ ��s����;j;���Y�����x��������wo<W�WIh��+�g���4^�7�M�g�/��n6�����_<}�����O_�zuIII������|�����������y��W���1�������~�������������d��cG4j�����j@�������C��v�}���r#?����4s��h�����UQQ�z��������~��o��>�>|���K�\f������,��t����^Js�����K�/�\g�����g/��R�2�uZ�xq4j��-��j@�����|��������36r����>���s����h��+�gi�����g�}6�Q�}�Y4j��E�q�XYYYQQ��Y�����
4�v�����������O��7���^�?v�X.~UvJJJ����g}?KY��������=H��g��_����B|��1m����.#�����?���l���|��h��Z�5�J���w��U���K/����3=�i���F�j����NW{xz�?�H~No�����%���.V�,����#���zPYYOB��������?|�����{����e������~4|��aY���>|x2`���.�zv����s�EW5q���CM[����k����[���8~�x����<8�_�vm�sq������+g���W_}5�\�xqa�'L���Ox8i���(��g�@�%����}��m���������f���O�<9�38p 2u�������� �+���������{�R�����������<o�g�������b�������F�
�1i��eu~����d29a�������~!�p���$��;�����'O�7���,///�,,,���qyv����q�����|�M�\w}�W���M^�_�~}}�<}��(f��iu������4hP?���\�w�u�����S���d��}�?~����/.l��aQ�G}�~��;|�p����^{�B@�VgI|���q�;��S��T*��k�E1�����<c\'��o��^��'�����}�]}a�����������&���5�����C��5j�����Q�.++����e��,Y������������3��������9s���^z��[�ti0l��������`������R�7	��Q_I<�fGU�c���=x���i����K�fy��'OFU�a�����qex���%%%����?>��x7N������5kVF������CL�����U�X�"����g�:~CN�}��:/���*��\�:����C����L�:5���������t��KN78c������:??�C}%�����5*>��3��7n����f�����t���J��<��;�Q���o����=����3+�����+W�|����,Y2}���n<t�����6N�?\��E��>�������[�~�����!C���7m�����jvuuu��0#G��V�^�b��y������Gu�������Ge�������c���\K��|�����0{s��	���'x���j�������'�+	��sz3��H}%��g�K���S���\�2����,tg���4�;��&N�X�|]��6N����UUU�������n���i�fWWW/^�8~Pmyyy�W���������Q�Fe9�N#G�l��������d��m���dLWaaa����g�����/����s!�	p����������%K�L�<y��a4h���?��k��]�����\O7f���t��������;v,\�p����������
:t��	������uV����������]�v��7o������-*--�3�Y����#GV�\9e��#F��1r�������eee������~�.���tQ��AEE�����������{���'^�bE�M�f�>���������)-S6�h��E���h~����Q���G���h~���9Y�reNNN"���{wzUU�����t���]��m�v��u��I�����o���o�����U�V7�p��?\\\��e*��8r��
7��8#���L&{��:;t����v{���J���5k�\}��999����>�h�7�[�n]TTt���������[�n��s�����)SBOnnnyyy�SVV��{��9w���������n���+/^\�`A����S2��>p���1#�H�3�������G�l��==���(tv��=�����=�PF��={������S������m����J�2�����a���o�RSS��}����������<���5+#l��	������>p���d����������$�f��?����:k�������7�vnnnho��!#f����W�^��.��!C���y����������#�<R{����-_�<�o�����E6m�������S�w����W^����=���_=���������{�C����}����v��t��m��;w�>�Y����@s����*���u����t�M?��C��Q���m�������\������u��}����u�Z�dW�����>z�UW�wf��?������g����v�m��9�������H,]�4�?����:��~@���?fSC&����
Z�x��#GB�c��c��d��m�����������O��3fd��=:�����v�����3���Zn���D"��������_��;��#�l��%}lAAA����{��e����|0���u�����v�I\t��	���z��������������v[�\�|y��L&;u������[o�'O������&�T�EW���J����:;t���_��}��o�>�>���7l���M�������������#�\{�������
��j��O�������]�vm��M�v�z��1w���cw����_�����U�V;v|��������e*��UV�.=^�2�p��,��"y�����}�#�������-sk�	h���Y8i��xSm��P�h$���L��F������h���L��F����%����-�{����������m��j��+;q��������g.��;��|����Vmo�.>�U�FU��m�6K�4��F����;��[����#S����72��'{��L��en����������>�}yM��N*����SO�:�2��vU7��o���?�D���~�l�	h�6���wTE���}���O���	_���?@#Q�od��4o����y�en�h�Ox�w��f�h���/�����F��O������	_����'���-w�����3Rv����T���/�i�	�8y���T�������McS�od��4��F��@#��:���T���N4���L����en��M0�P����?V��-�j���K���'�U�2�u_&�z���P���G���h~����Q�.�S��G~�i��I��p9��Pj��S-s���TSO?47��l�_)��{_�<��@������?4?�������tou�����4��@c��Pj���-s���TSO?\�������h���sK��<��Q���U�-tKY�����?pm�����������~������O?�2��vV7��Cs�����?4?����|�C�W�����TSO?�����O��������\s������y��/��beeezLUU�����t���]��m�v��u��I�����o���o�����U�V7�p��?\\\��e*��M�:5'''�H�}���<��?��?�n�:�����b��d�^�Bg�>#4�n���S�T�j��5W_}u���������C;d+**�c�L������������k��Yw8p�/��/��o��L�2%�������G=eee��w�s���z*++o���+��b���q���N�:%���S���>����#Fd�?����D��g��v;w�v�o��STT:�w��������z(#U��=Caaa���K�W��U�@~iiih�|��1555������9~�x�}���C��Y�2�&L���z���S��'v���_��_�D�G����?����{�}����������7�vnnnho��!#f����W�^��.��m�&�����^y��x�����Gy������?Z�|yh�~����{����M�6��;��3�T����O�{���������-��2������_=����=�w���P~~~h�z���]RR��m�����s��S�Uyy���0'O�<��76m������Db������o�������=���[��S����[���8p�\+�d(,,L$]�t	�?�0�{��Y;�k�������C��{�	�������K���x �Tg�g��]�0G�9�rw��s��w�y����}F�����D�v�B;�ghw��1#&�L�m���+�����O>�d�1cFF����C^^^���1b��D"�/��/��W��V�v������e��������y���F���-�>�`F�n�������g�
�_}��UW]�����<x�K�.�D�?��?��9s���������,�9|��m��:�/_�$��N�:�To��V�j������kjj�O\��'&������_��W={�l��]�������G�F1�T�O�>��C�������o�����O<��j��
m������������=B���^[\\�d�
�@��������7�x�UW�m������������cR���/���k�6m��k��G�s����j����������Z�j��c��{l���1Y���������r�-�Z�j���w�1n��S�N��TUU�?�K�.���1]�v�4iRuuuF������������n����~���8#&�T�y���O��O�4�Ht���_��_{��u�5�����H�RQL2����C��a�w��qL�f�����:'''77��G
��v��������,S�����o��o���A����W_}�����s��EQ��)S�nnnnyyy�SVV��{��9w���������n���+/^�_�`A��B2��>p!���������n���I������D"�?��?�n���������c���Bg�����������Ce��g������0�T��;q�DF���#���B���4�o��������������?~<�>���!l��Ya&L�O=�T���K����N$k��
�>� ������aw�uW8�q������
�
6d��X�"����+�T�E7n��D"�O��O������#�<R;������/_���~{h���;#f��M���;��>p���><''���E�*��_=�H����v|������������[C���$#f��m��s����:��[�n��9p��9���������L$={�L��o�������=���[��S���={v��9r$��7�={�D���z���:���~})P{T��]����7��=���EEE1K�.
�<�@����k��o��u������}���#�D�c����d�m��W^yeEEE�}��'C��32�F������O\�����x�����[�~}}1w�qG"���eKzgAAA����{��e����|0cl�n�B�<�T������D"�h��b���b��������������v[�\�|y��L&;u������[o�'O������&�T��X�jU"�h���/���SOEa�T�O�>!�C�������o�����O<��m��
m������������=B���^[\\�d�
8o�g�N��s��qd*�z����v���M�v�����c��������_�~�]w]�V�:v���c����?#&�T��c�N��������.��1.DE�@p�h@�+b��=/1F��KR�cD�+D�
(q�%���~A1a@�a�a�Nq+]S3�
3s�4�S��}����on��������u���|��;��C^^^qqq�k��9r����i����=z�q��QU���1��SO�e�]


v�u��N;m���[�T@M��9�g�����
4���yy�1�6�m���
��p���N����t{��6l���#�<��s�����O�2eK�
���_�Q�F����<yr���7��?j���~��G���$-��/���gh;vl��f�������W��'��<��G
}�v�Z^^��S5��#����?\�lY����������3fTn�2eJh���grw�����~��*����h��g�*��V�Z���������:Ty����[�l������_����w^�6f��*�n����~�e�e�T@-����K/������?��C���S���Gyd����oV�3i���~�1�d�T@-�����q�B�g�Q�����	&�����O�={��*}����/�t�A�?P�6�������C�V��I'�M������s�p�?��O�>��O���w����Z�����������������}7����>8���Z����4�3����r��*6�����������W���G������
����nO�2�J���~:�w�q�?���������6����g���v��U�\^^^XXX�~��+W��^xa�v�}�U�v��7��_����?P�6��|�;�	���M��8q�����o���3�<���U{�����^{-��j�����������W����'-K�,���[h�0aB�R^^��k�����{,��;��39������*��~��_��������$w�?���OEE�������m��~����zj��-��.���S����M�4���?��#�z����>;�����33}�|*�&��lT��3�***����=z4i��i���z���c�?��~x�������������\��Y>�����_>�f�����W��g�;c������}�.~���������������Ja9z���7�WgZ����d�����d����x�����o��}�>~�s�T<<e���/�l���G+��jY���/���5��{^(Me�>��hr��w����O�����M�� �X���c�r���=�� �|^���O�m���\�v��m���#G�<���6mZXX��G�;��c��ui��J����sL^^^��mO� �wO:������Gl�Q�F���y��%%%I����{�����������{����3fTn�2eJh���gZ��������:t�P�}���-[�������/S��^z����������9���i����G���q�����8����6M�0!����x������Z}�I'�6�?>���������y��'j{���1~��������<�QG��3w�uWm�[S;^}��������W���G�������?*�&>������v��Ui////,,�_����+SP���w����M�V�q�����o��i�
�����?//�W�^��/OZ�,Y��[��8a��t�l����������m����O?��S[�l�^p�i
�zw�}w�=�4i��i�C=t���i
�����>� �QlG����PII�G��U�w�y'��l��#+//������g�F�}���?~|�#�q�L���]�v��:t(,,<�������G����#��|���;w.((8���&M����r��#8�����~��=��sid{!����i��6�@��#xL_|��w��������O�;vl���Y�L������~xx��8����������#5<	<???)�������W�xd�\r��Wq�F�,��!��_iiiAAA���-��!����u������~���'w����{�-,h��G&���>������#��_��Z�*��8�G&��***������+�.]�l���/�<�m�������]xd�s��7k��i4�L���o�����w���Z �C��	<����;$�,�f�~���Q�uA��	<������W���O���~��+V�2��&��Y���\_|����:���x����5�&�������I�&���/���
�<2��e��!��7�
�q<2��q�A�m�6�c�C=���?o���������5��$����	B����{2-k��	w�i����e��/���/�Hq�9F��	<���>:����r�k��/����F����!���5+s�Q�<2�����oi��3'���@���K/�=�\#��G�6m�7o^^^^�q��a����!�b/((4h�g�}��s��#xd�?�|H5��nii�GZv�e���;'g6�k�����Sf�xd��{��!�O?��r����C��!CRT.xd�\�������i���H���#xZ^y��������������e��{�����k�a�xd�#�.���_�i���������M�K.����.k��u���K��K��8��!���_|QPP��^{�[�.�>|x�
���?'[�y��}��'~����B��	<�O<1�y��7Vn��x�y��5�&��9���n�|a �uM��	<_~�e~~�UW]�iIH�� ��93���$�G&�8���z���T���n���3�<3�~���~���I�O?�t���.���t�����������[��_��y�#FT���s�=C�?��i�0�<2��4y��o}�[��A3�����W^���r��#8���.��3�g?�Y�3�R+�����d����;�7v���#�����;t���W�^���r.�w�}7l�m���a�xd�l����V7l�p��I!��'By���B{�~�R^�xd�S�>���r��L��5k���:ujH���o��><x���1F�CV�Z5}��E�eZ^���*�c����������%K�Znxd�`��A���kr;|$h���.�������ixd�f����q�tu�Q��{n��:u
��X�xd�%%%������?�1�-Z��_���U��\�2l����~�9E��	<�y���x��a��k���o~��M}m��g�	}~��LK�)q�v�2eJ��n�V�^�����I�&!������|����x�8����������,�^r�%��h��)�L��e�
7�^�xqfi49)Jr��=z��E���#����������4���s�1u0��$��_��#��mj���K/M����_����P�C����Z����L��M�>�m������
�u�]���<�@�:i���nfi��g����_���3����{r�!��QG�����9�C�8��s����z��-}`�@X�"�L��e���C�#G���4������=�G&���<�AZ�n��Q����r��a���_}���cNxd���{�I>�mj�4�}���'�r���***�����������k����M��	<�e���k��i���'ONZ����a���������|���p�jit�0 dx�M7%��3f���L�U��9c��Y��������=���Vxd�,��?���dn�r�5$��Y�5��K.	��i�/�������s�9���k���Q��G&���?��-Z�$7�@�r�-
4}�w�~�UW��7������^s�5���xd�i���!�x�r���_�}����{������4�u�/�T9��O?o�����^C��L(y����9#���� ��Y��u�Q�Fk��#xdY�z��C=49���y������WoS?�g3��#;������3{���] }��������_-[�5jT����G&���v�ZXXX^^^�����.((X�l���g�����E0e����Gmit���'?	�����?����8a�������_��|�Y����!�����v��}��Y^��������xd�,��W�Z5g��h��a�L��e_���Ys�u�u���C��
�:uj���G&��v�q�/�0��f�4�?��I�^|���+WFf�xd��u��U�-**���W����+{���+���l
7n-�n�����^z����7�tS�C�s�9����6mz�]w%�^C��^�y��NM3f�8���,����#xd[85'����#xd����l���������r���&��Y�����?�r�}�%���{������w�p���0s��.����V���B���sN�e���M�4	���u���~���$�1c�$^��S^^��>��rqqq�c�.<2�G&����#xd�L�1-\���?����������.	<2�������{���������
4�q��}���e������I��u��y��t���[�xqQQ��E����W��}�����3W��j��-B��Z�*++�J�5#p�I�=�\x��~��id{!����#xd�L��	<2��h��c���y��3_��	<2��t�UW�����[��������Y����������yb���{��W����!���p������o���@��L��	<2�G&����#x-Z�n����@:f����"�L��mi�����5h��u���8��W���#�<2��|�Am�'�	�73g��M|p��<�)�G&����#xd�L��	��t�A�}��=*�@����[�"�L��m]��?�x�������Q������6l�p�=��������*������.
oOc��M{ ��P?�����*�G&��^seee��rJ�Qxd�L�5��|�	�V<���!���?K8{����[��Z�"�L��mu���Y���iSXX8w��ZX��I�+V�8��#����W��U�����K[�j��n�����=�m���CC�c�=��X%��������kn�����4j�(��:��%��I�5���BI������_���3��QN�����#�>��k��p�	����'L�p���7o���� ��0�\�E{��W_=d��'�|��{����k��s��W��s��!�L�4i����W��L�;��#����_EU�Y�jU�>}�? ��9r��'�\^^^ZZ�������;�{����9s6�G�5w�Wd�^'��SR������D���7c��������7��X�	�G&���|��Qy�����/��B����=����	|�v���[#�0�rLYYY��-6l���^��t��-�
?���XC�5[t@�5��?�)�=x�������������,�Z4`������^��>����	�����()�()1))�6lX���'�����)S,����#xd�>a�������5j��+"�-'e�{���������N1b�=|�	r����-Z^��m�k;O�81�<���#,Wm�!�o����������������wr����������YSVV��[�lbx��~�N�[JII����Rw��o�%K�4o��s����|m��7���m�&��#����9�G&p�
��~�=�>|����;k��lr����?�����G�W^ye�����������WZZ��k������Eh���2�N~b��O"������w��!��{o6x
����?������,���=%%uJJ|JJ�QR�9~�����o������xd�L��	<2�C�6mZ�V��k�e��=�P6�fn�F��;���_�~�Vz��������������O9��Lh���a�=r����[g9�xM|���x`RR~���d��o�U�V�v�i!�PX�:����g�^'�-���KI�II�@I��(++���s�f�-Z��X��L��	<2�G&p�
3f��y�����K�.%%%i'g}��g:t�u�]�}��������w�}��0[�������7��]����<��55��_���+D��a�����=�\6`�����?�������4(�kw�E���()�()1))�{��'B���{n��^<2�G&����!7��_��e�]����c�M�!���������^��+���;P���_v����{��'�hrMII���������i'7%g���������u�NII�������
��O�z������id��|��,{
<2�G&�ZQVVVZZ�MO�G&p����x��0���d8�!��p�a��x��`j��~PF�����'������~��0sD���Y��������S[����~�}��G�o:������:%%&%%>%%2%�������W��G��@�a����,_{���txd�L�5>8��c�����#8l[��z���M�4I��{�e�-[�,��@�:���B��<�H�MI!
[;v�����[�����������c�=z���� �u�))���������y��W}��U��+����&L�?�\��D���EI�OI�&���~�~��������g�-((fy@��"�7A�G&������]��a��^+��=�g����c��6`����?>���n����[o%�;a����g�2*��:��zh����MM���m��A�&M���G�M���b���|��G���o���?����[G����5k�l��%������:���HII��R����V9�f�-
{u�<�W��6���SOe@�57n���M�������������8��������=k���{��w�u����,X���PZ��i����Cu���|�������'�-�l4h��~��+���)����y�N9���������<Y������x���'�x��i��l.���X��;��~�::w��*�����P����>���jJJdJJ���:���>Z'�+**6����n
�~���DX���C���K��m��i�����a��!���xmQR���C�!%r��w�^��&M��,Y�����v�&M^|���=�CEEE������u�{���/����&O��4�`[�h�
}���|��E��������Sl.X�`�n����_�7���������55�}II��:v���'��e��hIY�jU�=�_�}����d:�Y�a�v��g�4�\��������D���>i���?
�"����YZZ��S��Q���&�? �-U\\|��'~��g��|0)&�_��>\��BI�,�C�RJ
��c�=�~���������������?�8���S���s����Jz���\���7��2����I���#L�<��������SN9�U�V����G�s�=7$��A�p7�����mQI)))�7o^:��m��,^�8��x�f�F��z���?���3�-U�L�"JJ|JJ4JJ|JJd��n����N;-��O>������zT�*����k��a�z�JJ���<xpH��+�H�������$���_��!%%��Q0�?^p��
J���= �-��@�Y�~}����{�W�������z��)�:uz���b4�,X�`��wo���_���0�~��G��g��|�-^}���a����;wN
l����6lX��l�f��U�*�o���L������mJJZ���,[�����NJJ�z��n\s�5i|����5%%-JJ*���By2dH�Ww���z����=�k��a���K�����:(�Cdo���W^yeyyy�%DJ�O������jJJL�V�:�����������r������sH��&J
���#G�|������W_�\����./����o���?�x�z�}��7�1p������3gfZ����d�L�%%%#F����K��}�������R������v�)sv���7����u�N�\daK)))��������c>�������>���)
6()())RR"SRR2������?���i'g�Y�&LgZ�n]���y�����u��\|����v���z]JJ4g�qF~~��q�2-/��r��m�J
��?��O�e;x������
&_�
��,�^�zafQ�l��F�
��?����s��B���~�eS�/�������_�x�v�Z�j��oT�����K�o%%-JJLJJ4JJZ������]r�%!�v���^H{,��/�KH����}��'�x�!��p����TC��^�
%����;7$|�q�Ui�5k��;��@�SR ��m�;�������1"i7*����/�l��k�������g����9s��Yw�X�xq����_b&{��������36:�fK))iQR�QRbRR���D������7��W^)++�4&�ua'���R[���/�}���o���;���-]�����z]r��P�����TG�����{������[}�[o���a������%r@iii����]�O����Z>��s���5�\&�_m���a���;L�:5�Q������x{����&�S����w��9����.��U�VS�L	����y��!��{W?%c2����K�ol%%-JJ4JJLJJZ��h�������:�����m������j���$?�***���C9$��\y�����6�^��Q�a���k��C�+V�Hw��.%%-}�Q��M�6�{���E����r�����IJ
l��{V��]G���u�������:�IfAAAx;���/,,|��g�sn������S���[n������0�Kkx�a��5����S�=���i|���[�l�|a���z��Q��[JJZ��������()()���B�h����W^�8p`�@t��g�]�6�c���,]�49�5z���[o����>�i��;v�,+�����T^y��z]r*�dWwu��������O�����w�	����{�vH����QR �$oO3f��>��jC�<���:w���^{�w�y�|�Ij����9���>��}��G�:��q�*���s���C�����*..>��+O������O�>?�����o~rM
))�()uGI��PR�QR�������!����~�i;vl�^2�4Z��#w�}wr�v���U6�|�������6g���>8o�9�/������7�^���7�tS���QRR*Fr���'��:uj<������9#�aM�4i��<�@�����5[����J���s{��������;o���=��T(���_3�W�X:�����Q���<xpH��+���,[�,��^�z7�xc��&��KI�SJJ|JJ���:������n���!����+���KZ_r�%a���g��1w�"s����=<$��w�}7i2dH�+4l��rI	��:\x��)
6|���;v�$�7???���w�L���z5������2f�����E]T����w�}��6OI���`���~��I��D��M�l�>�~���+��kw�����o��,Z�h��w���h��irn�$������;/sz�;����[n���s�`��	oCW^ye��+V$?l��E�e
������)%%JJ���:���BII�u�]��|��J]���3'��_��W
��	}�Q(2yN�jxr�����e�'�%p�g$%%����{������{�C��5+��o�����PF^���6\��C�!��Nj���()�l��|���x�nh��w���c�������|����
SR 7�iu�N�
o������'O��!3�.**z�����c���{�2�m��O?��A�`fr&n�Z�z��7���� ����]v�%�dq�������y����T-K���.��RZZz��g����T2���������<<�\w��q��E�F�s���������NI�kJJLJJZ��JJ����W�����h���K/�=�������������������U�~���7j�(��Yg}�������o

2%�q���.�<�m�1�3r����PyBI��z�	'���0�aJJZ����<�L�6m�*�������OI�PQQ��W�f�����;��&�m��M�gx#{�����07�7����]�v�@����"Yer'O�<z���^z�i
��`��.]�|�[��<�N�>S�Htfr:W���\�5���������NI�CI�CIIK���6m�������80Y[~��7B�����5kV�st,_�<l2dHj��_|q�z�*��|��%��u���9s�>`��/�������u�^}���S��}��O=�T�M�Z�;����-���(�����_��w��3�<��^Hc��@I�\����-�f������a=l���:���N����:thx9W��=��L����������?��u��k�Tx�?��CB��'��1��'�l5%%%%%%uJJ4JJJJZB�m��m��iH�a���E���{����_��/��r�t����1����M��={f�n������9s�w��
�y�(lt������HI�FI��\}>3Y���O�9����i����;�bmI&����!���E��u�0�N�������.%%&%%%%->�`R4����L����=,�QV�X�i_�r�~��6��W�����K�M�V_�{��7�?�x����P1B�h��������w�=�^PP0e��*����%%JJ4J
���#G&��'�xb����U����#�<2g����??o�U��f��|���3������V�\�HI�LI�@II��������u����������Mo��V�^��S����/�f�z��g�������W^Iq�9�c������9s�F�����(�_���l���G�};9W����O=��l�V���=/Y��y���1�\���HI�CI���|��n��e�G��m����;��%[�D/4���?�A������o��5�\����i5�����'�|��ps�������%%>%%%%��������O����u�g����W^%�[��~�q���W_"����F�����8l�r�16c���UZJKK�N�z�
7\t�E������C�nf�N
�!%%-JJ�RR ��]�v��5����-���J�����*��y����k��k��>��Q^^��SO]w�uw�qG��h��U&�,�;��E�kG�kBI�III�������%%�����z]h�8q��^8d���o���/�Hq���P�~���������+Vt��1Y
!W�v��v��_�~i�t�T\\��k�{��'�v�c�=�a��'�|��W_]������JJ]SR���9l��Eg�uVx9��W�����T��
�u�}�
����h#�1!�0������siii�i��kjE��k������.%��))�))�RR�Z�����������?�|GtS�ul����*��������k������3f��q�Cc�^�>����1��GqDaa����c}���������|���z���\��������j��R������U�f�j��}�S���~�^�;��S��mYYY����3�������g�l.X�hQ<������~�'?�I����\G����	'�����iJJdJ�7��Rw�����o%����7/T�d��~��/��rfS����^{-���3����Jm���t� �^v���;7i�$�A������/���d����3W�,**<xp�-5j�Oz����������
�q�1S���_U�_y���w��:�����)%%-J
��P?;u���M����%%%'�|r�#wo��fx��{����Y�f�<�LzC���s�9���o���>&�[�����;�����&�'�x���m5%%>%��()�SR�SR�������w��y�w|�����][�J���F�
6�]�v:tX�bE*��U�8u��,g*v���7��^��_\r�%�Oh���������f)��1c�Tn)--=��c+��c3�:Y�s���PR��������?�yx����K��_|19~]yr�@�n�v�m���:+�[*�Byyyaa��6�!s��������/�5�m[�v�}�	����^��n��������������PR"SR����M��D���%����Nh����i����^�:���
�u�^ziRg�4i���3�0�m���,Xp�)�\w�u�;�2^e���
/��s�.[�,�x�Ueee{��w����o�4N�4)����/����y|M���q�AIH1D�4���Kk�j���-��*�5\�*U\ZZS���[��r�A���
��RE�1]1%$1$����Y�����DJr��9'��}����x|���{���tU����"ED
���U��}��{���W�������������s������7�c�t����������_�U}]�n'O�����k>�kV���WVx���T�k�"RtF���b8"EgD�M)�:z�����1cL��_��uk'''���#Gj�4����1c���'����i�u��������5k�V�s��j��%K�4������i�F���H��8�
*����c����#G��)���O�8���{�7��hoo��S��k�n���Fkf���^�������G����-������+}>b�]�t,���a�l������U�*��"R�G��H�)"ED�����;������:tP�V�TI6{�����E����4i��
��Y�u"R�D���H����:d�G�h����S����7��E�����]�|�l�����i�����WTTT��������}��q����5�>7�'���E�{�6�^�����A�jE������JE���b"�@D��)F!R�r��9ggg77��C�v��EMq<����6������KK�]�������)o��6_7m�4��s�����O����):#R�A��*--M}����/����?�������_?q��<*66VE��pO5���T�VM�
����a^jj��%K���
����9��)6E��H1�bSD�!���7OMk��Hh����ukooo�jsH���4�e��:u�poK!=�|��t��):#R�A� 11Q��/������-������{Wk�;wn�V��-�������__:���K��^>|�L�2���'N��+W���UK����a�s�='����������u\\�j�"RtF���H���3"EgD��bcc###/]���9r��/���{���/^,U�T��=�-�������1��}�����iHGa<�|]FF�:"EOD����������C�n�L/�j���4�\�R}MIIy����jP�b���nnn�>�������CU�T�vWWW�������r� Gl��(K��R�J?��sNNNBB����e���SvQxD���=):#R�G���H�������k�����������-������5����Nx�Q�<y288X�������?���U<�|
�H��b8"�_������3f����(W���#F?��Si�����3��]�����t��<M��d�/�C��\'%%I������5i�d��=�j��w�.{"��E�W_}������C)�!RtF��H�
�����OW�\���c������W�,�������|����k��-��=�/55�F�e���MZr{���111�+0_��|�����-����D���H)"��;vL�H��������K��r�����Zv^��N��*U��~0�d������{�nll���g
*�Adff������X.Z�j��-�(<"�XD��):#R�E��������z�����:tH��V���c6_'����*W���M��+��M�:U����~�g��
&##c��i�U?��y��}���<�����)�C�o���
64m�x����Z|���/������e�eD�����{+W�=z��RSS��<����7�LG������"}��ih����������!)z��e��q��P��%�D�M):#R�D���H�����3�/_��l�����Su�6_'���!�����Bbb�q�:�V�Z�/_�AK��={����?�����8���^}�U�n;u���|�$���}���<��P`D����!RGu��������2�j��fw��9�Fa�9sF�JO�>�����������������v$O=�����	,]�z���Y]�1}�t�ksD�������G�k��L[J����"EgD������<..N}��g���w����������233���d#7�T���Y3��M/|�>|�b�������*a~��}��o�N�Rocy�|]VVV��}e�.]�h��|����u,�1)�#Rl�H��e4]���_~i��kk9w�\���}||f���f���B??��j�h�k�l��g��1�fG"�`NNN�c����-����i����V`D��222���d�1bDdd�+��"+[��%K�u��!Rl�H��b,"E7�Ya������I9o���������Y�����A��
6o���b���-[����>GEE�*7���Y���igggIr�Jt8���i3u�o�QV�X��c�)�G����?"p<]�v-W���_�{�nu������{�rM�}��1�N���Oxyy���������<�L����}___��_~���bAFF���WM�=zt���}��	tk?
�H���	�M���L���|�bD����):���v����B��c�����YYY�����5�V�ZRR�Zt��e9,W�R�B���[�=z��7K�
����+6n�(�G�qqq�����
�W�P����-�A3u��?�� Rl�H1�8777����O�����r.Z����9�W��m+���n��cG�����/�g��=������/��������w��Q7n���������4:;;O�:���{j�&M�T�^]�
�.��)z�s��l�m���Zd������ 5���%R
�H1��'"EO���M�P�������+���]�Vz{��EZKZZ�$OJJJTT�.	���`u�����2R��|�����]�|�+u(���2��\���|��c�A3u�:"��C)�c�?����o��+V4������_~���4g���?�P}���_������$<�u���}���w������V��S����\]]�}��.]�xxxH���k�����'��
�!��o/?������[�.�^)�8t����l��kRRR�z�d;?}�tDD��dw��y��,X�@MV�`��)� Rt�����gi��e��=�Yww��?�<�H��.���>���������1c�H?�Y�Fk��y�������e:�����.HI��0;vlrrr��'u��__���^`��|�����@���M���|��.����)�#R�D��d��
���������.bpm;�����C���� ������3�W�\�t��NNN2��Z��v� ��k��U�R%�6�K�.=���������NU�^��f��jwV�zu�Y�("�7n�pqq�C�{��eff�n�Z:Y]A*6l�6o�Qd��;w[��"R�G��H��K/�$���U��W	�p�w�^�H�X�$��|Q���0�Rt������m[u�����5jf\�����S�J�����z��|��	T��,���[��������SO=%����gdd�6<o����K�x��;QD���=)������e�&����3[���F���>��u)���>���{��emi��M�
�����c����W���=�l�?����r���
H�n���l������Xn�/<"�K�.MII�~�a�?�������{�������+����)� RA��@"B�v���Z��*�3f��L�^xx�d����O�:���)�"_����D�����3&$$���]����8~�x��wAZ���}������b��*T�H;��P7���=�����7{j��H1��"pH�~��\���{f���u��MyMa��q#!!���������
3ml��������(���;��ei9S'�,���@�� �HrHV�N���_�����������:�D��H����>�@6���h�5���;w�T����6�:w���f�u������1{�2
�A�u����0�^�$?v����/�uVG��H�5"pT�|��\����f�d�����W���K��}�Y'''������+Wj��0@���>}Zvd���3�RG��];�^uo��L��]������CktXD���)����(�����Y�F�>���J
�b "�v����������?���W�\i����)S��A�������+W��5������|�� ���%K$����HW���aaa-[��NKK�Y��%%%��HkQG)��o�\�����Y�g�y��u��'"�(D
���\���^�$�����������!^FF�,={����\]]7m��{�����Phs�U�5Jz{��1y>��������}���:6"���!"-���N�����9y���E;
"�XD�-)Z�n���_���{��Y^�����~+t.\�����d�*U���v��m���|
�����:u*a�E��o	����L�������O?��s�H�N�*��u�<�0+�-���j�N����3"�@D
��\[]xxx��e��Aff���sK�*%=,�&u�����^�����5k��������9V@\\�l����������������g��+����HY�f�vo����|d

�H1�buD�������5j��x����G�q��	F���^�(�(��8j����56��YKvvv���'%�o��!�R�V������|�B�[KRRR�r��K�x�
���z��4iRhh���\�H��)�"R�����rrr\]]�/_n�({.�����{�����?���MZ�V��n@�a���v�:e���?us���+'''��/����""��&R�W_}���������0�RG@�MD�)z�3R�������o��kg�~��=eS?s����:�Q�F������K>�^��������nZ�+D��I�kw��,X �8o�<�%&&F�4���6l�\�l��?���J��#Gd��m����Sgl�N��w�z��s��5�L�A���H�YBB��5k~����7o�"pxjp-�)))F�b�����w�.Cf,[>�o��=�.A�l�2�"]�c���-Zd�r���j��i��k����N �crT����8qbrr�4�h�U�V�J���w�1���Rx�)2��H���H�/DJ�)6���"/^�.\|�����s��O<xp	�iXiii��?��S.���7unk�����u�1�)�������i���\�R�V-����r��!!#��)�+W^�d�Z��F�����_��?S'�.<��0�C)���{�����u����c������[��Va�]����IR�������I�Y- ���]�����������+S����sW�Z��Q#Yp������uo�����������4�K����4���x!R
�H�"�)�D����FJ���,iO��T���'t��I��O������;������7{'{��u($�[�5A�����A��O�:u����+J���_��c����-�d�'�>>>��������u������^����.]���&'��P�jU�<u�T��WD�Q�}ddd��-�����_�h���C����4i"]�K��������.�j��m�������G�����=���������w����������������Q�FHH��!C��=kT�@�)�C��"Rl�����0f����������M1����q#44����kY����:����S�&Mdc���;w.S������������H��e����Vj�d�m�������b��e��]-g:��];������LTD�Q�}������r��������@�^����2��'Z.����,�,��0�
�g���`����p��]�v5\��H�"��b;D��RSS�x���_����d��:9s���;wr��4D�w������7v��m��1�[�����+��m��I�v���Z��k�4h���iy3���8�~�b"E�m�*U��^�Z������+>c������6�6{S��[��T�R�Z���L�j�w��Z����7[���H�"��b;D��dV�u5j����c�T��]�r���@vv���[�-[fy��c�����o���/�����[�c�<y���v����RR�����+�a)�F�b�����S�LQ_-'��8������D\���K-���k������?]�}��!!!�oOfp
�D����b�H�"�X�|]��5-��<�kD
L��i��%� �q��)mi�-�q����kNNN�6mz��iP�e�����������-[v���������!R��g��[u��W�7i��q���vF\;;;�e$�}�v��r�������\�
��B��H�"��b;D�����C���qC����c�}>>>����7oV+���.�>p����7�"_�n�jl��a��������'N��|�OJJ�,����q:8"����{�L�2r��k��<���I924�:�Kjp���4n�89`���6�"�f�pE��������C��H�."��b]DJ��|���?�t����f�]���S'�a7775_'}��q�&&M�dh�E��SR������m�E�f�2����H�:"�X��������y//�n��U�)�����g]���r���A���-�������%**J��?��Rx��M�V��tcpp���sU;��b�H)<"�hb��Z��k�����h%++���^����:q�D����^�j�z��-Y���z��l����>>>�������U��3g�����[�h�����|����
����d��-.�k!Rt�g���K��-��}}}���L�4h�����;�(��6��3g����9������4hP�r���������5�!"�0�������4]�:u�'��]�-%RP)�A�ej�.((����F�b�d�����O>��C�����liVV�z����!����/v���t2���2�1��y���j�����)I��K��8qb��
M�4quu���6���x!R
�H��G�����f���.��M;|���}�����e������cp]0r��A�m�������7[��5�!"���
&���G�����f+)(���#R��[�n]�p��*����W�Gp���+�+$''����w�_���������aaa~~~?���t��y����d�Q�F���N�R��j���7m�d��A�C��bS�)�=0�4R\]]9\�B��f�lD>���[���>�,�����'�|�Oa�����|����s��}�_�HA1D��������-Z�PO�����\a����g����)#����I������0�����Y�~�k�����9s���cL�@A)�S�H�?~|�~�&M�t��)��#��������=z���N�<��R�=i�������x��"�QEFFJ�|���y.�}��v�3��b�HyTD
����d5_W�Z�K�.�-]�`A>��6_-Aa���-[,���F���(�,_���[o����/��\9))����B�
YYY�%##��%����y�f������z�������)L)(�����5k�^ �����aC����X�]��������c�Y��|�b;D
�(���o���v�������[�~�A�m��.�q���?Q�4}0(yFJjj�4����������?^"e������#Rm������?<y�dttthh�����?�htu�M�������
����)�C������
*�8ZvUnnn���S��[��SXXXZZ��?����,JHH��XE��"e�����+W�|M�����/���XE������������w�����~3�.G���I�Z�m���|�,MLL��<���!RE��+�����Z��3g����)��.]�T�l��M�Q);�g�ddd�[�>��geeI�����k��(@QG��&�uu���r����������[�jo1{w�������F�H�������������D
���r����Z�b�-���r���z��%����y�!���������Y�D�7m�T�=<<&O�|��������^Z"""�@�E�m��v���/_6��$��:�����CU������H)���4�WWW)M�4IOO�%RE���S���{�sY�O�<��y�&|||��_o`���|"E�_|�E�H)Y�����
�@G�m��N�:��=�.T�\���m����
�����2_�b�H)�{���o�^z�S�No��FHH�W_}�-%RESNNN��������W�qr����y�n�0)b��}#F�x������'&&��
�"P��+����{zz���G}�T1[��:CDJ�M�2E�m��y�+�(�bcc###/]����3���)��HD���6m�����c��I��;6�����:�S`8"���$  @�-�������?��];u������o����6\���/�r�����z��ziD
+"R�?���ay�)d���.�s��c��w������[�{����(V��Gu��M����y.MII�H�x�b.�0���+W����1p���������g����������T�R�Z���Tc�P4)��HPxk���������w����w����f����m���Y${a)YYY���~~~)))���=Z"��w���N�a��W������C�e���>>>����#G�K�d��o�>�JPt)��HPx���+Y�d��=o����c�N�:Icfff``�����n�O"""d��E�t/@Q�g����{Kn���������_���K�J��.\({����k-��o���D��ETT��3N�<iD������V��k�Ih�������[�N5�\�R]]]��_o��| �"##u���3RN�:���!���!��o���=Z�J�z��!{���8�u��=���������V��dff���9r��R}D
+"RX�������$4��i����������.^��t����J�*I�Q,���A��j�*'''i6lXFF�j���~���J�,cP���n����{�7o�|>y����_��-o��-_g�����k��A��
�7ont��:"�)�b��Annn�!={����������]�v�-�={v���]\\6m�dl���E�X�t�����Y3""b����[����&M2�`@1�s����Ggee��o�f��U�����]�|Y�h5j���U�
>ll��>"�)�����6l��������[�xq�r�J��J�*QQQV���?R���n��Z�xxx��5��j��]���-Wiiinnn)))r���h`m�����V����;w��Y�f����}����w
��yP����l��m���K�.�r����!9��?���'M�d���1c��nK�{����7;;;ggg�^&�@��",�^�z��!#G���}��""@\�p!22��� y��eeeQ {B����g����h�����L�0A�C��9S��m{��=�z���F����Z2���H`E���]�v-a�[�n��_WK��$--m��!%K���$99Y[������>����H9q���(���]��P�z���)�z��>}���w��E�����X�|yii����1cBBB������ot��""�u
4Hbd��k��7n\���������s��"--�m����DRE��5m�����:�|]�*U|||*T�p��%kPd){�l��R�J���Ok�������e��s��Kv8P�reuF[�Y?���q�(��Vt����%K��3Gk9y�d�:u$=�W��F�D
����'����V_���o9_w����5kJ�����3�@C�������;w�������?����_F���7n�j�u���U��,Yr��5�+`���e�����J�*�����'&&6h�@"�U�V�9�D
�?u��1''�A�i-			�?��:{h6_����w�^�0E������N�:���t������+������d��G���:v�H`]��OW�
Y.�!v@@���h�"�K`�,X ��p�B����ku���Z����{k������9D�!�O)�������������u�r��_]��5J���"�������O]D�g����]+��4i�m��_|!�����]>��{�E����?~��|=x��J����:xxxh/�<){�|�r5_����Z.=t��,�������GD
+���U��k���z�����???SR�������$�G����lzn�V�Z��7��quu����`��Y�b���{�������K����R{D������S��u�w������too��u�U;u��U77�^�z�6���FGG�������*�="RvA��7n�z���s���O>���gly�����S�<����Ny��7�q��e����~��k��V�V���O�<999Y[�~�zI�#Fh-����3::��J�����?�P�$$$d������D
�^h�u
4�={��y����S�t���H�K`�V��(_���I�>���N�:�W�lti���/V�^��������w��Py"���W^y���'55���]����;w6�9QK�����j����G�7�|���3F�^)�H;���.#�;v]�"�U�V~~~k���y���
6l�����_�Vh����T�Xq�����������7�fE��	d\3c�����������o�,�v��#�|��9s����#RX�v
�g�����F���:t�����[�����^�z�S�v������'�xB����
7�G��e�Rb��YNNN �!�H���X���8 ���'N����Y�������>}�HzT�R����e���.<v�����g�>z��������E�)�����bD
��0_���V�)2l�0��AI���,����������
)�}���o$1$O��)k���Q�d��-[�_��|+"RX��)))�Y�f�+W��\!&&F�_����=h� )�����
w��
�������<
O��
6��B8"��S������F��INNn����d7>>�r�J�*yzz�_{���3t�P�''�u��Y���woY�����_V�w�^��]A���c��%'']�"G;�����=��������m��5�4�G;����m�6���5����u�����v
�j����oW�)))aaannn{��1�<�E;����h�"uE����7����>����bD; ��i��o�
*���m���������]�v�����������{�]P�h�����N��b�
���L���������;gtQ@1���S������.�}�Nx{{�����r�b�S�H;����s�N���5N�"NE��)��7o]�fz
`���F�k���a�rrr����S�BCC%[��(�n����?k�<�T1�
�H�?��
endstream
endobj
20 0 obj
<</Type /XObject
/Subtype /Image
/Width 2048
/Height 987
/ColorSpace [/ICCBased 7 0 R]
/BitsPerComponent 8
/Filter /FlateDecode
/Length 45213>> stream
x���y�U��7��)Tmmbl]JMZ-m"�Ij���&F}[k��h~o"���1�5�0�#C����0��� � �P����R�Up��f��r�;��s�����m�~>9����g;���|����t	r�����/�������a��]�:������?���p��������9�a��I����*?z���+--��9�������_��\���m6l��a���m������7�;��������[���?{�l�c���'��s���m�3��T�����;&�?r�H�������l�@��6Qt���64���a����+6���+V��|�9s�����������a|:`��W�d���m���U���V�^}�gs�N��Y������!C�~��j[WW7����Em��G��������������������+����M�:5�����:������7A�|��V5����F�����/..nC�?|��pg��}��i���~���� ��u���t��)�7J]]]^^^����(���������h��<��=��_����i�*++�m����?z6t�������jP���Q��xeeea|ZTT�~�D�e�������'N'p����[�<y2�����K��-���q�����������ou������;��#�rY�Lz�#q/^���3��F_�pa8��-[Z��������S�L)((0`@����:a���Z+&��N�>=,��ys����1�y�����G�9k����w�7����;w��1c�
�~��W�-[v�����FWr���aI�U��tY�S\\|����s�$�?q�Dp)&O�L8//o��!A���u���������:��a��<yr����'�����MQ���o�a�u��E�,���)U$>o���|����7��1c�Q���3o����h��hy���O����T'e����555�'ON���~�v�V=z��s�]�|yxt�����[>7�d���'�>�oll\�`A�K���/:t(�k����>����Z����.���m����_�}��p?x_�4inn9rd�ee��3�Z5s��!U$�����4�����!&L�����-��=f�������G��/v^~������>�~��]�jUQQQ�3j���������e��������_�zu�3`��7�x#�0o��#FD�~����F+)���k���~���A�|���������+������'������Y�f�����+
t���V]�H��~�k����k������
�8q"U�}���u�O�~)���� 7����M�E��.�0S^^�`����g/_�|���


W3�����p����*��{0�pm�x��o8p`X���?�?��d�~���ND�s����>|8����^0`@P����Q����Y�f���������+W���
;v���'�+?~<��zx[!��Ki���kyyy	g8s�LaaaXa��Quuui�j*a�W\{������Y�&x}i"�W$B����>�,x�S� �����$<�x��h)�����qc���2�/��2�VQ�<b��TuV�ZT:t��E���S�l��|`��y-;\�`ATa������	����v��(
�_����m������%m����;w.����
�^�`�!C��u��[��N_�u�v����m�����������O4������[__I���T������f�-����-?�EMMM��.�
jll����M��q_~��Tu�kjjZ�g���>}�e��[�FJJJ�~T�e����j�2eJXg���I�'���c�w*��_�dIX���0U�T������m�j�����c��w��?�8<:���D���T�x~~~th����V�:z�h]]]}}��c�V�\_!��,�|���a�Y�f����={�qw�����W��S�S8p�@�v���I�L�81����|����Ts[�bEX'///�#��������W���0���D����?|�p�&u�������o���~����W	%� 7����]V\\�t���g��3&Jt�<�5�����myyy�655E�����3'�'\1�Ou3����Q�3g�$�}������Q��6�<�l�
q���������������`�������o_��	�7=|��K/����w�t��UUU��Q�',�HX9�����q�"�L=z4zo�J�W=_ �a��������}���u��M�VVVVQQ�&��b������1j{����u��9U�_PP����/D�����O��sx���l��f	v����3gN������?PTT�]�6��G}���S$�r\�H<C3g���?>�V���a�Q�F�a�K��~���oGw�
6���$�cvS�l����;7�p��������b���������DN���>}:���_�zLpR.[}��'��J�����?�<,|��W�+�Ea��oET(�r\�H<Ceeea���g����>[-X��
�F*++�������G	�8p`��:���;������������M ����TTT��@���UUU��J��������^z),��"}ob���=���w����u�2u#���n����?o��-5558p`���������k���j���G������	�k�<>��Un��>:u�T�y�'�����������|���a�{���l��5����qW���X�"l����a����a���x�A�555m4�]�vE��0aB�����yyyi�M�u��h��ulR=�w��Aa��U�R^��*//;_�d�������G�
�������_�:th�����@�K�WWW<xp���;w�L�<z$��I�2����a�)S��}�iEQs �Cv����'R�9�JJI�����z��T}���Y������{���&�`������������~�����@�K�����Q][[��meee^^^X���4��@����
�������m���	&�W�g�����L�#��M�L�:5i���?������|�"8\�TsN���1�P}�s����������_Z�lY�~��L�&�r\�H|���Q������aSS��3�:���?u�T�#F�l����.^��6?r�H�j�Z�yyy���Qy���#F$M��?��_��Nyyy��	�eeet)�<Fy��Ea�^\\��N�����93�&��V�p��<yrAAA�3v���=����*���0?s�L��c��M�:5�PRR��p���aj����f1�4�x��p����WTT��Lu���a���q���:4�YTT��Ceee4��N��T�`��%���.]����K�x��������N��������k3l��k��f���b��O@��9.U$~���#FDG���7n���3g�;6>}
���2n��a�w�y�m>}�t~~~4��	����l���>�h��E��M��$:thP9�����?���^�|�c��y�W�^�fMqq��!C��7o���m�����1�.����������.]:{���nS}�#���������3o� �=������gR	_I�����'�7����e�?��RE��..=Z�'�,[�,��?�I���=z4�DK&Lh_�:������___?g����������[v�&��t�������Z���+++�������1"�&I
><��`��=�������D7�R-R$�r\����C�-�4iR~~~�������m���V�:�|k�=zt8\�cy����y������0aB0����`nC�-,,,..��sg��;��vL���w��={��1c
\�`g��G�M�m��?t���e������y�
>|��iA����T�����O��2^@R�����VH�$h�?�*���"���G����:�?t>��|������ |�����_�����n�������O��o��0������x���o��k��w�q��O>�s���LHo������wb��O~��'�x�����������z��_~U[�re�n��t���w���~:���p�
���Y�<�������F������������
���?E%w�y�u�]�p������s�:=z�hhh��������~����z���)�|��%�X�W��U����8x����'4��������.p^}��X,��O�����>�,**J�VXX����>A S����'O�������}/Z��w���Xl��
	��.]�?���>S #�<�H���o�y���'N���s�=A���{�l��9(����:v�@��
��C�{�����7n���A����������X,VQQ��d��mAy��=3�����U�Lmm�5N�i����=�P,{������={����^�2��H�����8�&�����]�v�����s��x ����'T+))	�y��L�<r����LUU���s����/^\VV����w���>���`�����_���:#G�����:b�@f��Y�����������.t��-8��W_//^�?���	�{����t���+ill���~�����[__������'(����444����K�.���^�v��I������Y�:���u����o�b����������}���^�t�M�6m��m����o���K������s���un����;wfq�@*��������������}���=�\P�Pm��]O=��m����k����?��3�����?Bu��c��ss;S�����j�/8���[���d�s7��fDunn����Y���vm�u$G���e$��ec�3�lm�k\uV����\p�|����.�e��g�<������s�������E�6���i_c�/?tNM���k����?Z��%��x�r�3�_���[�����r��~�Y���9������7���~Ov������x����j�r��������h9t���@���w<�?�@����~�Y���9�������ek{���r�����>�.�_��[y6�-��;���L�����������gq�����������Y�}���z����7�?����o���A�������,-�N���w���x7����w<�?�@�������\v�\��M���-�4;�����������_�!��xs��?9�Bnn���f�����������M9�y�/�	���kN�����r��1�����-������5'���;r����9���b4��u��n����9�\@�.�\]��[um��h'�7�fDu�n�*���@�4jQm�����M\V�������K��l�����@��k���x����1�W�v&���;�����'��f���'�������>�otRysk�������}h����g���I�\s��=�������~�s�����h�:1��������5'�����N�����eu9�U�d�
�Nj����3�Bnno��A�8V�<��&g7���vR��u�������6d��W�������g?����_��o~�G�}��=~�xB����?����~{��]����'�|r���Y�0���S�z��������>��c��n����e����9U[�re�n��t���w���~:���p�
���Y�<��3�<��|������$���/���7,������;�����F
�������GCCC�
���{�X,�k������������_/����>�`P^ZZ�As2v������k��b�_����g�}6xYTT�P���0(��:b��������b�������{/7l��Pm���A��?���Z����[�nw�ygeeeXr�=��b��{�&���ys�2A������t�M7�|��-[�����+�UTT$T��m[P��g�Lz>�|$S[[{-�n����#�������;v��/���g������+��?�>|��n�TWW�����b���oN�<�p�����'������<�H&C��ZF�\����_����X�/�Kccc�
�?�|p���_O(9rdP����!�2���~����0U���}����^�z�k��i�9�����������NCCC�=�t���{�E��&M
�onnn�i�:{��
7���~��?&SUU���a��7���K���{�������Z�r�-;w���)	8K+���v�z���n����]�v����g�9t�P'�?����9�9]N��$���d�Ij"�q��	��w$��a�N���q����6.����&T5�R	�H��{���{��9��s�[��k���?�9�{��s>���|����~�y���F�*��3f�r�)�m�]��5���N;m���Y��W_}u��g��Ysc��&L(***,,����Yg���������k�e?``�����-Z��]{��}��-u����[��V���q�R��G�����k�z����|��>�l�}��5kV|}�9��:�?v��(?��������3�����X���^�z��U���������w�}��o���(�����(P.�����k�O�4�X�s�=��~x��lc�����{���3�X��)S��S�N�
(�������NQ���+�>}z�w��!����`#>�������4������&�����s&��\�;�p���R��?��C����^+V��SOE��G���2����/~��(�������p�
Q~�Wd+@��66����OG�QGU��s��Q��+�d+@��66��z��v���3&Ux�m�%���[�.�a���8�������~�d��E�e�&M�[�naaa��]�>��8 �l������s?P�%�\R�q���K]�����~����5�Y�f��-�=������.p������/]���[�6���2����?�b������s��c���o����Y���li.~hE���s�����I���P���g����������o����-��������o�W_��w��w�_V�}����K^������������5[�����I��4w��2����������u��J����c�����?�� �������Y���w��7�����&�w��9���7V�:��fo����r�v�mW�f�����v�i�g��uP@�M�0�������k��g�uV�7��S��k�������X�bE����U�6n��T����

��k�z�������c

�?��b�={�������$*�"���_PPp�}�+���[����.�IT@Et�����`��I���{��(?���sP���{AA��9s��O�2%�;u�������i��


>���b���O��:d�?����yP�'�x�
���:t�����;w����������`z��q������k���z��(?��#sP���/


����b�7�pC�_q�9�
����~�������*V��s�(��WrP�W�n��]aa��1cR���v[����u�rPn�&M�[�naaa��]�>��8����I�&�g��uh@�������~z�f�j����e�s�=w����
�������[��(�,r�}�'O�u�3v��5j����tt��y�
<�Z�j��w_��R,^���/l��e�z�;��7�|3��?9���3g�x���7n��Q�>}>���\G��~��}���n�����{��GsN�[�j��a���~��X<����sQ����[�hQ�����f��[�>��w�}7�����u�Qq�7i�d���K�,�uD�O�as1x��k��&�QlA�-[��G����o�d2{��8����o���D7�`��Y#�YIn��a$�@vL�>�E����v��v���E�5f��������g��?\TTT�F��w�9���y�����\���.����s������V[m���:�<���:(r��y�6m�t��q����*��y�E�Nz�I�<�k�U*��5k��|�=�����sW>�s�\<�����%��8p`$<���f��w�������i������-[�4�5r�}|p��Mk��e	����?�Y�fm���2eJ|���/z���z�7���-9�����W�^��C�����ox`��w���|���-oE�>����EK-Y��O����#����g��g���~��v���_�����+����={��`�}��uhy��_�4�W^ye������v�)r~�%��:��%������j���,�Y����;7h��@�,_����0��%�lz��'"�=�P�6mLGg��g��A���������@U;��������y�c���a�F���<�V�\��e��w�=}jn���1�>��crX~�u�][�jU�Y�e���Y�&'!���?�8���N:�Xy�X�.]������g�Yg�]����J��e�]������a`�j���m������y�R���5j4o�<wq�39��K�^���o�'�|�@vD%C��/������%���4iR����;��C-dS�������!��w���G��M�6~�xKUg��%��W/9w��_�z�M�����Z�*'��+9��g�y&���#G+o���9���z����$�<�|����)���^�x��Q^TTt������r%�����T��+bd��I�(o����A�����F��<���YC�u+����"��?�xN��o���z�����*V��{�(���/rU~�s��4o������/,d�{��I~���kK�q��wF�?���o���@�����3�X�a^:}::�9��QU��,{���"���s��
w�/|����*��Y�Jn;�����w���u�����C�Y�zu���3r�}QK���g���Q�����^�z��V�Z��/�U��'�����C9$Ur���&�v�����A�&L�]����_Lr~��w?����d���K�]�.��w~N��+r�e��y��b�=�P�����*��;6r{�y�+?��s�<�u*���f$���������M>Z�����������GKY��_�:n��.-dS�n�:t��|�>}��g��F���g��U�������'��Z���[��{�5jxp�R,_�<�������$%Q�<8���w�}��!g�uV��9�����R)�<�&L��l�����s���K�&�t={�����{����������m���S�N��WOf*�}��H��������`��c�=6Yp(pe�������e�]���.���h+�e���o$�vu���C�E��,��F�EJ_{����q��E�5���<�
h�-�����#u�\r��W6H}����rK������������h	 �.���S�X�"�����1�ml�J��o���>���R�%�Hx����������C#���U���_��]�vM��R�����u��M6|�m�yC��l��u�rH��UW]�����m���������~��� *��?�8����?��O�������>�{����Yk��M�N>�����oN=��Hi�����
6,���/NN���������g��!C�;�������s�=����>WQ��������.Vx�gD�K��B��s������oq�_�u���g�.�w�}��?�����P�@��_�~?�pnc�3>�`�y��)��H�i����E�����y�Eb����v�����_~��}�d���(��o�19��^�zM�6=��C�����zk|���O�U�yF��/:�1p�Q�Fd�E�EEEC�-vM2}�]w�$���j����>|����;j��b,Z�����,s���S�N���=�\d���31 ��=z�$��$�U���?��7S�+W�,������"�o��Vza���_e)��2w����~;U3�Jw���o����%�{9����z��l��_"���������*�s��[x��75j���7�\���PXX��M�q�:��Tl	 ��dw�#�<2�����3gFV�������$���{��i���g�����}����o��O���Z�q�U�����3g���~#�|��w?����]w�q9�-_�y�EM���_~9r��G��<`������K-������7n\���:u��; �/^\jy��E�*��W/�MDr.�^{�U��!9�����=���@"�u������6�����K��hOS%�QT���7����;vLpj����q�6v�����~Cjp���E�����Hu��}����w����r��r���.���[�������L���&s����v��?�Z����n��i27a����G��G���Wb{����w�UQ�����o�3g���Y�fM��H���^��)Mj[i2!�Y�a��2f������O�P��u�zlZ�
����9���;��������n��j��Or�}vZn������o�]���������'WMty+j����olD����W�V-{�A;�:�-Zl��v��*z ��o39O$\~����5{��(?��S�>�|#�Y6}��m��6�M�Q�^{m����7��/�>m����LF���������-[�L^�}���K�x��v�o����S�#�����e��q�����
l8=|����^,��+�^#F�(���L��U����O�:��?�,���j��m��-[V��J-h��*�����>�����s��|p�Dtb��y��zkU��o�<�2l@���q�\�>��?~��L2l@g����]w�5�<��:~M�6���/�8��"���a����n���q������n��w�^���f����o3]2�T��H��]O����(�����i�H��6~���u��9���~��_���[�rer��w��J����/�l��e���S[�G'����f�������{n$9r��/����QQ�o�>9�}��5�_~yd��(���w�9����r>|x���NH�������3J����R��s��h��p���*�N2o����[om���{��h���������k��|��+����$�u�Y������O���^��e��w^2I���|�<�2o@w�e��V�������>�?��O||�����o������9��;-����_�~\y���';�<�����5k��e�������#�{������|�m��k��v�A��t�MGqD|<�����25c��I�|O�><Yv�����W^y�u���G?��%O��{�y�]v�e��b;�]|��Q���o��>Y|����M��[����O�!)���Ot�K��}����7]n�/�S��������F���?�i�?"��C���Kv���GR{���/�/�0r^���Pk���v?:�����G4I��'���W/�>o��	�=0])�<�2l@���z���%�t�����v3��6l���g��N�yF��,�N��1c�i��or�����~�z��#{���?��U�g�}v���&/A'�0`��b9\y����%K���U����M���G���A���#�m~��,k��]����v�w�o��/�������K�d~���D�O>�d�����P2x/V~��'v��)��������g��v����|~��H��7�X��i���^z��U��sX�%P9�����{����O����3g�4�_A��7i��u�����6m��Q�c�hb������LMRE$o�����3fd'�-��g_�
��W����?��_�~;��c����r������2y����:�e��{���
7��a��bF�	O����%����_�����=����f^9�����c�����[��D�	�0a�����f^��,�f�mj��Yl,��.]�t��-�����o%��{����~���^��]��no����'����;'�=���S��k��&)4�/�uF�������I�&����� ��U��a*�r�5}�����n@&/Y�$*U��t���l���bf����S'��
:��"��.��=��C�{��$U���~��u�&M�|�����eK!��W��JQ��J!��W�N��?��Y�f���,PAg�}��'��|��t4$�Y��C�K�����Nf>�u���_�"���^�z3g�\�a����G&��m�����/,,�;wn��g?�Y$�����O�����b�����������aC�����3����;�[�.)Y�t�n���M�6�������^�V����O��9�����_�U>����dK�z���w��n�������	D���c��-�R�+�\pA����y�i@�L�}r�}:-Y���/�����e�R�TD�*���j��&���O[�"�<�^|���}����y��7k����V[�?>)Y�j�1�����:*)Y�h����6l��w����<���{�NX�`��;�����o���3g������?~�������'�t���K���v��������wR"��[.l��aT���&Q
�~���d�������\����K�u�y��\���,��f�4��<�tZr����_~���{80����R���x���M�>�����-_�y�]y����MK/����4h������e����_l���Y���>:WQ���^r�%�]H��1bD���>|x��wPu�8���������@�K�.m�����n�����<yrtkK��D������f�4��<�tZ*��5k�t}�@2��
VE����&��t�o��������+k���\��F��l�M%��%�H�������X@���W_��u@�D���m������g��eK1{��h�;w��U��I�]���Ks�$�w��g��u [9�2
h�i@�O��O���x��W]uUY*��lhl�?s�2s�1/��R�~*5��M�e5��N�:%'YgN�+�|9Oy���#�?���+7��6a���<�t�D�����J)���M�Y��c�����s�������H���>;��l����G���K�x���"�v��h����4@Yu���e�]V�Z��X6o���p�A��O�}�J���C��R���w���k�co���'Gv��/�O?��^�z{��G9�H?��#�&��������
0��?(��V�����{�i���g�~^-����/���3�?��c�U�Vm���2D*�r7����K�P[��P�n�
�N���@6cg�}v�G)���/�h��q�-�-[����X��#����6���k����4g�����Hf&��ye��n��f��R����NK����+���e�)��T�u�]�9rd�~�4q�a�U�^}��e�)9���s�j��������g�y����o��a��5��[V_}�U�&M��i����~��}�Q�.]�z����;����Gf��yUf^)S:~��=��#�G����G�`|tJd���s9�����������U;����U�)�(�M�����W��Bl�*���s����_G�o���M_�q�E�_x���D������!C�l����h���V[m�h���E��|��&d� ����W_�w�}�]}~���i@�)�N���tZ�O�%WN<����+�����&�+��o��~���4i���GLDW��3�W���{��D�+(���9� M�����A�;��#x�u�}��'�tRz�;w�\���Y�q�b����[���O�>Q�� ����{g2qt�9��e��_�T~*�hz������[����DW����	������i��U�Mo���u���"���2eJd�E���&.5jT\�������� �7k���+��o���F2o���M_��D�tZ4��B�%�tZr"n�Z�j����k��������'&�+��G�^x���\���_o��6&�+�������7.����Rd��g�y&.���>r���K�f!���a��������s��U�����O�>���{���4���y��g���7�9���<i������X�b���1^����4h��u��^���2���}��r�����0a�������;G�5���Q�L��������J2���a������3g������������J2�<���n$��m�������MvR
\p�����R�����:-UM����+��L�s�=�\����������K�5f�����?����
Z�hQ��
��m-i&��y��5�T���?��g���@� ej@������z����{�3�<��;���Gn�����Wu`yl��u'N���{���2Mu�Qc���Nxy�����[��V[m�p���$2�z�,y�~�����=��3�����B�
����6m�dr��I�>�`�FW�'�|����0 ���w	@���O�>�������d�}���F@����rtZ4���R�tZ~8�.]��v�5k�,R��X�����
�8��\������n>|x����y����;�O�g�~�/^��]��Q�~��e�#�W��������s;v�X�z�C9���V�Z&�i9/��k��}����rK���_l��mt���g2���
���{�mu����3�9�������Z�n��m��6�%9/�i��x���y��^�^�.������/�%	� ��,�i������D�/���\�9��3"��>�l��R�\�2j�
,X� ��l)�<�f��]�F������u��eK�������K�.��ZTT4}��\���>�������y��o��fR��[o������GYEV�L�_�Z�*���Ce>���"����l�z����%�
><��&����������V��,����_�vmR�,Y�$�%*H�%ktZ�O�%��b�{���z�d�%*��\�n�]w�5����'�x"*��}��:�-��g��A�"�>�`��Rh@a��l���:(�e��.��l���SO�.]���C1��
.l���V[m�����t6=�������_��X�����k������{����K�o	��%.?���RgX�&����i�2����'F�����:�����+3<�f��a����`�j�zh�-��M�u [9�,�0���_6n��E���/���Hh@�h��u�-J?�&5��y�����t�����|�/F���
�;����M�?�.��":Zq?����n���\E��^x��H����_�[��w_�Q&1vk����.�p�����i�y"�+.L_��i���,�i��8���#�/��R���E�}�1�~���,|��7�Z��z��?���,���
�sE����8��lA��RL�0�q��K}�m�Ee~�UWUuT�h@��c��U�������k��u�	'���;�������G���_�R�[I ���M�>� �����M<��;��]���a�rg;vl���#����]�tI���P��N���9�&��E%�,\y����-�mz	�m���<�H�=4h���X�pa��u��M�����������[:-UM�%�tZ~ ���Q�{��f��\������[�l7m�K�F�������[�
�9��93fL��C:9���C�F��d	`������[\�q�
Z�`A�'
i@�b���vXT�]�t9����U���������*yN����t��u�~����8 ����M���I�d������_�*��<��S�U�d�j�-T���w�a����~�����8qb�������?>�����-D^�������Y�3gN��5k�����QGU�N�Hi�-�N��\��R�tZrB�%����!C�l��d���#Gf'��ux�K�������W�>c��������]�~������c�9��n�,X��A�Q����Y�0���;��Cy���7q��W�_����/<���q�I'�����U��:t��^�:r��M��P�!���Ot�R�r�X���K/M��'ON
���NT�{��g���C����	'�p��7Gsfy�"��{���������/�������c�=��s�)�������#��
J��?����L����S�Y�:c����Fz�~��b��9sf��
����%'������+K�.]�|��Ty�K1�����z������(�|9�u�]�7o�:���O>���gd�i����OtZ��NK��d��)S���M�_����n��I�R���P��&M�TXX��{���������~���2��XJu��7�o�����Nx��w���l�)���LKQ������J�W�_}��[�n�j��Z��o����P��A�����_�*Y�f��~��(�f(��d4��M�y��e;�<�3f��A�.�����>)|��w��z��yT���B�P.Fy��sO���/��B��5SO��=��{�%���h�
Z�zu����������bw�1��2�����ZPA1��>��n����,P����]�{�����{��U�\��?�2���GA��GK]���-[�w[�h��~���u�N�0!�J��J��W_�q��*:���NK��i����G�]��3g~��w�yg�QeU�%��N;-��4iRvb����?��c��Mx����*%�������q���)��K�"{1��m��2y�\�+K�K�f��h�^��X~�����c���U��w�7n����P�������������N���b4��G� �|1w�����+}�h�����w�[���z������=�\�b|���{G���X�zu�/��s�5L�:�K�.�����.I�z�������O����OB :`�1��t�M��E����}��uQ��z���_4h��"�#F��V���W_���7oqKGo���y��EJ���"�]tQ�KU��#��^�z*�%'�c�z�H������m��&����O�d|��REtZ��o�[$��;�h��M&���`���Z.�H�c�=6p���QD��5�W\�����'����/�|�f�W�^I�������0n���c�Vq��,n��y����<��;��3���
��"�����o��u�K�]w�����^�1cF�(4h�p������^�U�VR�$m����lJ7�d����Vr���]�v�&Z����OZ�j��i����?�q�G��}��#�[o��?������h��mRV�^=�[TT���#�0m��:u�|��g����}���Mg�����X&N���X�����~�z����(����^�>��S�L������/L�T:��S#�q{_~������%�#�V��u����I�����/&�[��p�9��"��^���[�n���J/9���k�����^��1��Y��>��������5�w��]���#���d�������}��sO�
���?~���s�|���G��.�������&���&C_|���!C�������������~�KT������{��vT,1��u8������{�v���k����V�Ze�@�������j���y����3y���q�L���1bD�'��B�����Ol8�m��U%����C��b����sL�z����?������.�-[6l���w�9�����{���V�XC�}��7�p���M�������.\��c�d]��L�����Q�a���}�Y�����G?j��e���#��M���^����O�y��z�����:��L�I4�k��9����5y�K��77�(�R;-����e�]V��?�?�x|�����]�yb���-Z��s�=���M�]���NK��i���1���zj�c�s1��N���>�*y�����v[KU$R:h���F@�����5_}�U�WQQQ��"�B4��k��l/]�4)���o�<�LKU'���?�)�q���������?�O<1��%������;���C\�6��5kV��W��Q����O>�L0 U��-��1��e�]�'��j�b��ol4mR�"����M7�T�V��%�g�qFdx��v*9��f���������J�~�"���>n��*n��1p��<n���o���b��P��!C�vZf��]�F�j��E��d:r����^x!G!���~829f��T�����1M������\rQ���S>s���y�����{��f��Y�
�N*K9�E��a���U'���:uj���/��@U���Oc�����,�J4�������O����K�����b?������i�0aBd��k�I>������x�����_����� z��
��W����4�����=������������d��b�A�q�Q����"�|s��G��������u�]�I�i�yb���GqDrK'7|�rS�t���@9l����[X���0�,Y��N[���C�F�_~���c�����S���tZ�o��e�������?L��n����������Ez���[�[S�NM��9����Z�����d��-$;��8�d�C9����Q�L�81�>�Z�64�=�Jw�D�K������,D���������[������f����������g�������\��e��p�	s��]�a}�y�E������������#�]�tY��'�[�j��m���W����>�D+�^��$mS4R�.K�������8�F���g�=J���|�=�L���Y��?�!.>���J��M9D&#��?��������=�;j�����'�|��Ho$y��*}��v��v����i��@�Z��y��\D�'6�i��������5j:4�+Q��x������'�4�<����>2<d����M�����N��D:-Y��?�19�:D��?�����%�*����'r��i���.�������G������M/��];��-[��~��K����h";������E����/��%��v������"�p��z���w��=�����6���~�%�G�2�A�+Z�v���1��s�x���3���7O������sp>Y�vm������K��g����.A����DP�����Y���{�a�V�Z����������9���{�bXl	`��Y�4ih��I�
����{�U����?R��}�����%��7n\|����a��!����O9��TIj@��>����]�
�D�e��uW]uU��b��5c�7�����@�}���hF_%�����|��W��s�=7��������+�W�G��Hy�������\`	�J%����a���Q������j�r�{}������[Hv
Q�;��"��������a�!C�D���$�q�'OA[�R/��br��9��w��q������e������o|	 9�`�6�Y��%
�������O/���=���M�6�{��WEDb��p��T�_�����S�N���y�������Ys39<��s��y��W���\rI��m�=[��M����q�olC������[o���K����v���?�����'����[�
�V��\R�}��������o�5J���D�8��b��a����{���_w�u���^��6�i�F��?�yT����K4����,��_�NK�4�X"��v-~���<z5Ys3���C��3���{��J�.]��^{��'�Z�:Q�$����mf���u�������@+�������s����_�Z.,u	`��}�o������?9�7D��~�EG%}��x ���6mZRb	�J%���j�*��"���~��7?��sV�+b�����:tH�����@T21�5j�Q?dY4IQ�
6,�k�J���(Z�b%/��B��-#���W0`@j�dv4�c��q��c����j��J�VlL��I���N�����n�m��9�UJMW�O>������
7��z���b�h��%�~�m�>}�6Nf���P�;�������[�E���=zt\<h������K��:9Uwu2��O~��b�[�t:-U-�N����;u�����x�����g�n��q��~��i������v�m�,,&J���H��2B��]���8�����o����4��F�����\��VW���c����/^��M��7��Iw1z��:cKT���?Y����S%�n�������������E_e�=��^��!C�c��,Y%����6�����+�6�=�X�������[���&M�$�Y�'s��d�'�|r��'���;������V�����3�QV��G�����J&N�C�z��u��1���k��I�+z���z��q�m�
>�m��EEE��)�i��%q�{��w�3g��o��K�F����;�L�(�f_�Kc���Q����+W�Aj�"j��?<��]�d���7R���sh��Y�����_~�]w���'n�����Ot��"�C�-y���^�������%�J��R���iY�xqr�^��5�<������_6l�0��**+�����I���,�JJN�O�2%��Y�fe;�<�|��#�<2��
�N[���w�����#G&�����c��y�����RlWXAW^y��[o�t��N�����GV�U�P�����Hi����������?�:~��x�����Uw��I55�����[,H���d�����D%��Q��w��h�"�,Y�����+VD_���.*�pW���%��G����QC�x��/��Br@d��h�W�^�<��;���[�������p�r_2�����;���>�$�Go��f�6m�u����?'3u��������{��������^�z�,5�N�;MI���8|�"�J�z����_c����_�7�������L�N�81W�n����[�6~���������~��(q��zE��q�%�{%��8���Z�r������}��Pr'��S'}�4��c��>���,(k�%�z�#�k�NuZ;��b��	S�N-V���%����G=��Yr������UK&���Hl��5���?�Y�&2?n��d;����'u��O?��i��4W]uU����~��#F�H}���m��[8���s�f,���7m��(y������[o�uT/��5������>���>����6����o��������(�1�)���^�D_1��B�L�<9���������@��P�����K�
��UR�����6~f
��L
%��9s�DM
}���v�������G%?�
��������b�@&�����g����WA�>�l���6��_�^��z�z��V�6�;��i��v���;j��Gy�]�"���b�V=����3E%�Rs��b@����r�i��rtZ/^�������[o�(������#���zk�D�%;���;<���a������'?�<����o���$�4�����x��bw��5kN>��(��K�p��%7�|s�������������HS���X{��(���`y��7b��Xb�����hxQ�;
�^���(��.���=��H��8���G��}�����Y��s���/,,L��^�@"##)��,�O��u�&���C4��Z����M�����7���;G#\�l����e�������e���]�v�r��{[��!�+W�N|"""h�����h����$9zj hTCCCi*D�������-,\�P�}���K������F�8�1�~��}�����H��Li��E{��M[XX���Ku�J�����%�/]�����|6
��3�|���)��w�6l���U����/[�LlM�e�������y#Nc�5����v���rK��UL����hI�.!i���;w����HZt�u��4��n��3�1<<���S���-(�Tj�<�,�F���������t��%..�z��\7117n�������Stn���9;;;99���r���'��k�s�Y�r��5(7o����>}�h����,]��?h���/i���Y��<����;1;���
�i�������������A��������K[P�WRR
����h��o_����/Z�9R�qSlY�f���ziJ�C��cHZt%��������Z�J�>e�)�^��c�j���ou�M�Dq���(%%%S��
/}���q���}4�+W�lff��kW^a�������J?CH��a��q9}��h�w��O6l(}:����U��z�J���'N�O�6�������};�6�u��l���F�F�m����e;w����?����+V�U���S�N�����t��gO\\�������!C���ADn��Y�(R/mA	@F4����Q(k����eK�&M���	&\�r%""�t���$��b-�q�*U��}���^Z��������@	@~~~�z(ym�^4}8���7���G��v����� H#�i�&�O�s�Em�������r���Q��+��(QBu%=�����|V��'��S(k3�:�EEE���B�
AAA111���u��166��PZq��}���4�O�����$c
I��e�������'h��y��nD<]�h����Orr����H}K�.�v�Z��R���6m���I���i333�7�8����r�PnK4��������J���������Y�fQ���G�	qS���K�M!J�(�=zT�}3$�-�����N��$-�@���- i��9s����Cu�������Z�^�z��j@Caaa4�666]�v-����s�F<��+��PX������?~�h��Jx>GC�
��aC�@ll,?%�t���c2v�������v��M��?����!dO5�P`�����$11Q4��Em	@�.���������/_��7o��a�6mRzv��	����s����%===88x�������i���MHH�<Z+r^�w��\C@��z�VS`�6m
��/;w�lnn��E5�z�j�-���+����\(��w���@)2u�@ i�1$-2�y	I�v����s{��e�4ivo�����W�Xq��)���{w��9u�T�/�"���acc�D1�?~\�J�
6��:����$h��9�g_my����������7n���s���&�<yB�=���rKtt���1��n�SC�~~~r�T_-Y��f����?-������+VT�
'�������S@)n��m�f4j�~��F�����Y

2LQ��T����ai��y	�l��=4�����������l�B��={�n�f�(w-R���-?���ci��U	�I��!i�]�K�g�/_�X���1s�L^>��%����4�[�4��;w������&MNN���/����^l����1~��BX�'����kddD�i��]�8W�����U(h].�����i��{wq>�y@�B����#G����k���[��r�C�[-\�z��H��U�n�����N�:4�����III��}��)��>111e�����V�Zt���%K�T��s	�����k����h���'4���[�t�����~��5�0����K+V���{�n����tQl�L�r-��=���-[FQ���S�i�^D�U�V�����
�.W%���`gg�e"4��E���|&�/ i����+E��M�6�z��U�Vef��;v,A�J�)�P�=z��Q����F�I��d���/_�h���:6l��o�
*�)������x�#M���'>�g����{i	����:���y���!|&+���pqHZHHH�����cm���!��"��DEE���:99M�4�Q�F��w��]�v�nt����{�����s\\�|�z�����&[(��:K4�|������t�W�B���lmmy�m�����Z�?�������+e����G�����`��A��;w.��`6�g�������*���o�kb��5|q�a<v�?��T����e\�W@���v���R�����S�(����������?U�F���	$-�@���r��|���EC��/��������j�~ F�G�
6466�������K)JDFFJ�R�{�n���%�h����-[���RH�������+��l��E�B!�C����D	`���J�K��c�M<}��R�J����v���[u�dQptt1b���E!Y���T�6����U���/2���s�*������[7Jl
e�aDI�M����W��X��M�
�B@��5kFc[�r�?��S��s	`��:�.H�����M�d����eIg��?���988������{2u�@���+V�c�����x���������k�`���4h����>_}����={���h��(��yxx��4��Z���"J���^^^vvvu����i��?����O��c�����X�&���V�
������%� N���@CHZtIK��a�)"6���:�n*�^�z)�!�U����b�����w��@xx����===�Gy�pi	@�����Ciii���JQ�����Q���pSTC��Ytt�R���o����W��7��R�J�X=��(t�������K+m��S$i	�Px�Qu[���m����%��#� ��9�\��+G�R|=w����E��������i����#n�iKRR�������W�^-[������r��U�Md?�~��]�(7�P�.^�����5##������d��e�-�{�����Zu���5���"�P�|��q��N���a����_O��m���%�C��{HZ�UN����Hkk��%K&''sJ�E����)?,��N�JcN�\�V-Q|�����K�+x@nq�bii9e��	&(�T	rKm����sUM��y����!!!tn�_e/�&M��h��m�6��R}�rH��������ZFQ[��R�o]=�������t���P���7n������;MF����.Qz��7�xxx��;W������4�r96��N,+G�nbbr��]�?�`�v�|r.��4�����tI����];�������9����
S(���e��u���D�9w��	��aXX�a<x�������/N�
��
���K|��f�o��\055���Z��%_!i�E�I��/R�������|so�k�����|������+mll�o�������
���Kt7o�\�(J����~����
��_o��5O������Z�Yh�(�i�v)B��%�5|���#GR�K��*U������$>�q�F���P��(j�}����+++����;;;7n���y_�z����IW.��S��O��?u���I���Zq��}:�###���M�h�����Dl7n��=�W_�5O���/)���������W����������w��|����?�s�&}���AC�������SI��n�3�]�!��
F�_�~�1c���O�i�W�X�oQ����iP�@��%���M������@��=5@�
�����Q�����/�Ni~Q��EJ�)]���E�4h�vR/J�����[	�����u�_����a��e�S�B�����R2w����xy�����[�����Sll,7&''�+W�s��4
8������Y�������_*��:D������][��.Y�d�-���6mz���o��v��m�tN���V�P�c��3D;�����������L�&�pi�r�-[�(����5j���?h�����E�JZ|}}?u�����g��_@��K-�(o2�b�
{h���4������W��@�*T�\�j��5kx�	��������---����R�X������o�	��r[�������H������]����;�S�n������iS�v������}nnn����]�fmm���'r�<y���J�vE�D`` �ann��t6%o�RHH��3g�|M�F�?m�4����nkk���5��+RY�y��!�d�������U�VQ��_-GO
�����S'F333�B��/J���s�C��{HZt/������j�t
=z����#7n�-L8@�FuM�1c�I�Eg��;�u����I��?�g_9h(�%���49:h h�s���c��I�����}��s��)��fL������������e���X�����{���O�Z@l����Xt��c��e������x��]�v������+�5J����C�:99��__)6�+W�8::R���q�N����W�xq�hJ"c����y�hH�NW���`����N=h����E`����>yN:j�Q����(
�����X��;wV��}��a��	��A'��A���K����K��4���������ir���0v�X�5�.���EHZtI������9R<�K�%�
7w��A�~��a:�������m[�)			G�/����y!��-Q�D�+�S��W���X�S���4�"�xxx�����@+r^k�������%K�����%K�?IwwwQ��5�)�._�����4�+V��f�M4>|�66ff��Q�F����e�B����e����|�2%�]�v�6����"���Chh(�m������:w�\��U�4����-[9rd�����4��������;��������V��v0�:u*��D�n�(�������{��4��EHZt	I������E[//�	&�*U�>��[�������_��+W������k��?"V�<����a������U+�(�F6%��U�w��611qtt����.�-[�(���H��=z����H��� Wh0)�V�Zdd����w��%6�b(�F�%�' 
�tq��83���m����K�M���W�`���������S�������^�z��}��f8.\H#�{�n�v:��iF�������S�N��%Y�h�R	��?��{w�e���Gk��J�Y[�]�rE�F
�Azz:M�\\\T����Ol��I������:t(��[������5j�� bK�^�p
���3g
��:�j��7iii~~~9�Sm�H!qF111t�R�~��������(��s�;vL���V�ZY[[+�'JP��'N�|��O���������Z�jI[?~�4�&���������c)Z��MA��]�v����]�V��������C��i�,X@�Kj�C��������R�:u�t��i�����J����3h�q����t9�i ���C����3��=+mW��Q�%]}4���A��������������s���o�
I�.!i��]�����CEKBBB�*U8�KK�w����?�7�47k�,��7o�=����������'��������wzo����n6%�aF�u�����C#�74�Q(������9�HKt��>}������_bb�<}5���4����@i�t/�v�������������,�@dd$��>df�����'OF���Q��#G:99�gt���4h���{�4�a�r��8*b���+e�����%�����e-����3~�x~�������g���!��w���'�8�5k��?(U-��hTiHEl�0a�4��	��E���i��S'{k`Z�jEc;k�,�CO�>�9��o��V�}3$HZtI��������ki0�:�4���U�>22����K<�QQQ���������?~\�Prrr���k��)ZP�����X���S%�������?���h����u�Y�U�T�2e���j(c���M�2���JK�A�QHc��iS�Gw��ell,&�4��-��O�N#�M	�.����439���,@�h�Lim!	�W�1���888XYY-_������+������Y���qI�"OOO�f������q�����S�`�Y�f0���/
,5j�P}�%��M�;v�H�����2d����kQDD���
��C�T����&�u�����@��{HZd��Eg�o�NCMC����9���������|zS0o�����9�,����'O��<��=�����{��gD����+W���e����� n�Kw�a�1V�XI�V���W�^��z-���	&��.]�pli��������Se��^JKK�8q"W�������v����;D��o{AdS7�����s���@�;w.Y���}���;��.�Oi��L�l�o������P~kaa�	@fVf�{)��)0`�/<<<���O�:k RRR�/QRb����i��IIg�W_}�����h���{_�|y��5�������WzR7SR��{��C����4h���'O��B�Z�B�u����YA����3������:�1114�a�I��!i�=$-ry�����/�=i�$�B!������A��all�c�����~��W@oo�#G���r���Y������}��)���I:��4������O��g��j���+�q�O(o������={�V�J�Y������ !!�F���"6���s���iTK�.-*��;w��-:���Q[�p������@.&&&��jFF���U�t��V4��3
/���@�>}�X�b���jG^�~)�
�'����s����YC�yfVI����k��u��5�q`` ^t����7m�T<�u���������?�3�k��E1kHOO���;M�)���C�������&|��G��"��|�B�P|��7�����O���S�|y>�	$-:��E���|&(nS��x.ml��QDD���gUo%A�y{{��	-[�;�����u��" �{������@��HR�����(b�5�S7�!?�6��V

�����s��	�#%�+����������7��r�����H���7��Y��������+�(Q���W{�t�.�_}���C������5
����l4�z�j������^�x�&tta�������?y����oW�X�y������JDCJs
Jn�����b^�5::�.L��]��E�s��mq�Nt��3y��%�-��_�t)�h�&�p�������������=kbbB#��_?
,���+b��RSS���&M�Pl�*���13�������2-[�� _�H���]���1$-rA��KHZto���5j��Z������#R(k������E�FDD��M��s�N�D����b�w��///�{��ef-���W/j��+�
]@'N�H���BN�J������9���_V�Pa��1�>���I��={������hh�����vss�n����T�vmj�����e�����[YYU�R'�&N�>��C���J%Q�����*�P�Sz���|u����#G��G��.]Z�����J��(��h~�����0@���y�����/1�/^�L�F�C�����s:�y�T�t:i�&h���N�Y�xq�*Q�W����������y���F�������baaA���e�d����s���bxSSS���k���Hn����y�bR�|���0��k���I�� i���h���x
��1�����6���������!HOOwuu�\�T�R���@�N~i��
]:�_}�={���w4��Z��X������"����v���������9;;K�<����FJ��+E~��.\�P��� RR�~�BY{�JK�^����#�u�\��������we���;z�(��M�4��Y._��Ge�0�h��}<������!���OFF������']��/.�<��[w���E��X�"EQ��i�w�N�-?5�x���++m"FY�����<��q�f�xQ�%�Q�?�������3r���/���A�
�b���yM\�z�N�i����w��%K�~|��m�=���
$-�@��3HZt���FFF>>>w��
�w+����l��Z���|}}=<<�s@@��}6�=����]���@g��q���/occ��E����j��U�VI�_���h������j�:�|TTT�&M�mP��Oxx�x��rr
��*UJJJ��� 55�������j	 3k�q
)��8;;O�<O,h�F�.�NNN��8e��&MB	����~�M/^�X���M��7�4����������^�8Kk����o��
���E�J��T�G���|Bsg.T�XQuHQ���,�3�i���g�>}hx�>}*Z<H#�Y[�����h��e4�b	�7�[�	���)�ti��%�!i��+V��WO�*���C�4\�9���-���'k
��J�E����<���[����]4�177w�il;w��T

233���������+�h���'i�G��zh��Q(|�~��'�M/]�T���3f���y�����:v��+���}��]������q��A�%..��.\����&##C�P����W�yt``���2�|"J4�jKX�FC?����ijj:p�@
5�P��u�]� ��
�z������'O�4o�\i��"$-�������+�-�����IK�B��K4����������h+�(�=zt��
��;������G
)M�4Y�xqjj�8�Z�?z�H��~u��������������m������������WO�����Z�h�y�f�+@T��!�������4Q[x���L�4@4��U����/��)*^��e3�M<}�����&�4������?��Gp���Ogcc�c��ef�#��Q�
*`�m�S�
8]w��A�+������C��}	4A���d��[��HF<��OAw�����s'�{�iKpp0
o���)�U}�����e���C��ON�<ibbbffV�vm^v��Y���%�!i�����z��\�z��m�*U-��RRR��o/�g�a���7�D	�k��			3g����ONN������o���Y��"U�fM~]���Jxx����$
)p�z��h���E���B���[�QQpuu�~�������������������4���W=��/�����Q�*����{�������ccc����t��m���Z������z��/^���j�����y3�U�|���7]�0��W(��7nP�0`��G���^����R��{���n;;���k���j�}��yGN�G������7�q��Yru��@��u���wrr�S��L����#F��Z,{��%_!i����� +V���sQ�w��Q���];
��)�������jS[`���������%K��Q�2e�����{S�o��V��]
��XXX�9��i5J�NNIKtt4J�9?��e���(�����m-Z�p!�j��������N�y@@@��1��'�������tU��c����^�/��O����x���<�y7?Sys���#Ft��m�����3���n+$Y��]�t��}��!2u�A	@�����V�*]p;==�_�~4�E���O�\���xp��F�o~��K�q����w����

�t�n���MWR�K�?HZ����3tV��_�H'?�a�q��L$-Z��E��?N�8h�����g��u�������Fu�pQ��J�<X�v-
��5kD�����$W*���������
6{i���t}�"�188�#���	�I�/_���_�n�:u���L�����eQ}�V�(3����b8%!J�&��T�@�Pmsss��1��dhh�/��"�Q���qcsggg�=,6m�T�xq9�	���i����&��{G��{�-Z��JG��?���m���[h�o���7�s������������b%^�$%%%3�	F^��d����o��E�����W�X�����0� �B=z����3g�3F�������-WQ�������y���K���_�j�J�b��Q��C�7o�)5���#>>>3�)#~^z�����<HZ����_~�%���U��z��v��}�bbb�IKn!i�P�>}������gVl^�D	�%$-��Q�
�x���'���+W�QP*dfU�������V��888������F����gf��4he2�|VX��
��.���RD###���R�o��ODk���V��W�Z�S�#����
6X[[s����;S(�P��I����/^��������]�	��y:x� _zhrG�>��%�K���ALLL�,b6W�X��U����+  �7Eom'''��|���/�\�2�]]��<D�!�>��W�Oc:�U��?�����y�<:t(�^�.]D	`�����L�r���=z�Z\�&|�]�o9�����C�b��
$-��<y2���]�d��x^1���|�=jmm�|���-[J��/���/N�!�������5k��266����������Q������M�&����K���������3��[G��
����:�X<==�����7�|#w���9M�}}}+U��4����?U���������_�W^=o����y������E���9C�S��@���=�_y��2g���|����NLLl��)GJl���
�����v��m���
m�����������7u�7�K��4]��/����.�z���:�+W��/�X�p!t}����
p������~:�������[�n�)SF�h�����h*�THHH���s�v�����S2� �(K>|8�,���iokk���$-���}�B����x��J������o_�N�V�g:�����]������[^��o������S�Fa�a���J��.,�m�6�<�.]��+W�xxx��[ZZ�uE
]�|�t��|�n,�@�������v�Z�|��iJQ�����}kee%b������^��_���������k�]�w������N�\<E�����f���\�;w����}��!J�t�1� f��N���������G�w*�������G�����{�u��M��Q�1��L��
��w��`�<5j��jw�tpp����;f0���N�2a��C(��{��q�e���4�AAA���.]�L�:�N�_~�E�.�c����J�Xx��Y��5)��>.B'::;Ci��)9W]�%��s�������Z�jU�T�n��q����6m�P`WZar�I�&t�Kk(�3Eo��Z�+]@U�( D	@iwB��9::�+WN�A
y��i+++OO����+�l�(����=��~II�\}3b*��k������%0H�P�X���0�!���\�O�>r��0 i�]6�����e�d����v�������w�9N�v�hx��6��q��:��aZ�p!
�x	Q����/p_.�(�=�t�K;v����HII9t������Z)m?�<�������b��j�d����V�PH��S����E�z��%���{�>)�_cc������;���i"^���l�(���������������[�FaQCb*GI����U�$�[�-��Cir]�lYGGG�a@HZd�}	 88X�^��o���������Yz�����H�J��y��X�P[�,Y"��W������I�&��GC�}	����/6��DXX���������%�����o/�1�X��,��������R��?E����x�B�n|FD	�.X����_��'O��/��ia��~1��1c����D	��,(Y��������1��
1����Tz��q	�����50����8::����[+=qy��Ev��@={��Q�����q���/O�����,Y�GyI:�������F�I_�����s���x�-[6&&Fu����d::p�@�:h��/@�EEE���988P`����B��Avss�7�_�|I�8�P�y��uDD�-�h�B�^��m���~���j���<y2U��@��%����O�����r�H�I_�T�YO	��G����`xD	�J�*4��������}��wx��(XZZ���@��YA	@�x�y��`ZZ��3���p�����O����Bjw�<��}��V]�?<<��\�R��(��&M�T�^]<a��p��l���d�����n����O,hG�B�v��-Z�*UJ��R�x`��Ur�E�]�t�]�v���fff�:u������g��J�������o����(q���+W��d�
����S9(�D	������3rwG�!i�l��EIII������������3��B;v���S�����&���O++�5j�������W�T)��������)))�j��C�1���y�Q`����"6�`��=�]�6
2��������qc;;���{���&(2������4����L�����{�J�c�j���o��)��N�V�^-w_�����M���W����M��E�a6
�(T�Z%�<x�����'���1�(}��AqS9(�P�����,X wG�
������#)b������<���NLL�}�������o/}���G�7)�M�������@�LPPPLLLhhh�:u���#""d�?(p8ol���4�Cn=x����y���%K�|������O��"c�g���{`��%J��9s�HK�r���������!CxI7�p���7n��7�.�t�gdd����C	 �����+V�fM�2��y��v��4L(hb���4t+V����]%(�P����="5���������t�+�C�tt���������?�^���E	����D�����f�������hlll�&M�7�J�*u��1��
�{��a
7
�?��s>�w����FFF����<�s���p'O���}�������_����N_i��%�|�r333il����?��#���%��!{c����|LLL�?����h�t�s J��7��/�����V(������(�����c�Q�����BN i���o�KT���:w�����7o�4k�L�}?377���o$$$d��q\�zuRR�<]���+W�}�����?�����.]�}���"x��o������{����R	 !!a��e�4iv���Wv��IC������W����SG��WJ�3����k����y��U�N��]�&wG���#G(���i���)))�]�[�n��BAC�
e,j���l i��C
MLLT�n�q�?V*K��(���DDDT�\Y�4�J%�@�.t��!==]�h��=����we��%�����K)�KKKS-h]n��3�������P��P(z��!Z�F�����~��7�l�����d�����+������'O����@��(+V,$$Dzh�����%h4!JU�V�X���PC%J^^^�����[�h��M���7�%###77����+E	���1cxs�8������Q����?��prr��������{
z��	��y���9�>�~�����R���H�?B����y�f]������W�������~����;�}�6I<�`dd4z����/_�vm����2g��{��D	��:uJ�(��%���+�������{�����/[����]�[�-��-[�E	���\�vvv�	rll,5>{����1c�����uqq�yO@��n��bH�����d�������Au�v�Z:�{�n����7�|C������������(�D	�����*U�~�������_B�h~��>c����hbb����D	����B�
���C�}�����2�@���QQX�|���o��a<}8}��h<x� o�<e�������r��F||���	��V�Z�FJk�4iB�e�����@A�����T�#��_�jU�!%J�HNN�HZ�%KK�3g�������x����W��W���U�v�1}'J>>>�k�A��}��|����v�Jh��g���
Jh�����?/$m��Y�PP{�&M�=������ kk�r���x�B�>���������ff�����K����.�s������v�J-������_XX���)^HB��(XXX��g���4����[����w���`�D	�g��(����kmll8��,Y���[��}	 ?P�;h������
��BCC��)SH������E�9s��������hB��_?i`��,\�P���^����"##���R	I@(h����-[���L�����w�^q%(�D	@�R9�����U����y���G��E	����+�%���_�]��W�^>>>���o�����;UK���&L�������/_�,W�@}���(�P���E�h���Y�_i0�~�X(���S�h�(y��=����@���CCCi� ]&�S%��z���#G���/i��J9�6i�}	A��{����q+S�M���(�n�Z7�L��V�PDDD��}���cbb������D	�[�������k���qC���e���?���|�����C,����3G���(�Z����{�n���4������IZ�%~�n���w�������k���O����'III����������u{��qfV	�O�>��
 �����O�^����k����=D�z�����?����E�t�5((�rC�n��u}}}�U�F�K�(���������#������+;����8ss�!C�8�7���jK=z�� C������������E�(�����>�����a�l8p��z�����o�CFFF��E)�$''�������������G?~|��9�������m�O=���:��E��
�;v��f��a�����{������ys~��J�*/_�������yt����/~��n�t���J��g�333�-2��C��k��999q`����|�����
.�������v���o������C�����$**�Q��mO@��d��^9z�(MN�:E����������>|���)SF��@�@�gWWW�L.}���O��f�th��m�W��{���
6P��c�h9y�d��E9�(�n���t����p:
�#WI����)c�(D�j����q��Q�(U����Ipp07������S�����~��j����yO@o<|��"���i��-���jLKK�Q�o�o	��XYY��WO�����q��t�K�#�gcccJ�}||x6}��E:t��%����57n���_��?oiiI	pDDW
D�njj�t�n�l i�z�����	E����K7
��g�����=:--�)�t���p���/_����&O��'?~\4��u�x�����Y3�W�-]�k@�z��]k���x��q��QN��~���?��)S�����u�����4$$D���~2dE�5k����w��(Q�I�&)))�u������Y�V�Z
4�������v
:������4\Z

*R��W�\������y��_~I_���'c���Gy�%��8]�tij����1c��m�H_[�l)�?Z7l�0^�;88�.=���C#G��_�>?�2j�(��z�]__����>��W�\�rb������&��*U��B	��k���*�$-�E���

��+�(��M�������+e�-���[����P6�Zx��q�N�D`��e���J+����k;::J���>}���o��)c�@<x�2��7����T���������D��Ih��J?~���

z����=�CDm	 3kI�
6�_�����ru�������7x����W'%%�����0��UK��f��-X�@�}=C���?�<r��I�&�<yRzh���[8 Z~��7�B�9�_!i������#G�(�@�����!G@�P��y��c���y#��0�|u��QKKK��Y��������(�����F�
������*��P������;���������������E��^wJJJ���===e�2�$-�u���#G�,\���X^�z%��@�=(�y��%-1112v�BDDD�
8��(Q�����%����Z�M�6e��:�����t�qss���i��|yZ�h��>�W�#F����cJ}��3|��jdd4a���N�>�X�b�Y^||<MLL�����/��b���...fffQQQr�>kHZ@�RSS[�hA��������_�n��/_���������U������/�����`JH(hP`i��-JK�l�"~ J
��fC�a��92v����+V�(�[�����6y�/��z
m����A;J�SRRd�2|�<x@�����E���w�V�J1�|��<e���vpp��BS�����_�HZ@�����[������5j��n��Y�re~�o@�bbb�-Z�~�/^p�������Y�8�����@�u������sww��a�����@�t>$$�[��������'N������SB+mOLL�Y�&���M����o����g����=������@~�u�E��C������*U�p
Q����)mP�W�^
���������2���r�����_����lggW�~��� ���?��M�Jtu�;�W�~�-��N�:Q�P=Js�2e��6n������B��d���=Da���g��Usrr���tss�?��U
 �J�*E���C��Y���i�&j�w�J�������v�������u�����������.�(Q�c����Up��A:D�E�}=�������)tt���>�}��a�����w����z���N�2eZ�nmnn���s����b��=�^�J���������.]�pli��������Se�)8����k��V�^M��-[������D����]�6M���R�)Q�M�e��)$-�^�z����tO�4I�PH�^puum���cc�;v��M�3+W���{7}x���������Xu��=U�V�����B���7����M���EDD(�u<~��'Y�����k\�����������{giiY�Z5��z
I���O�������[���Q#�6g�������c��&N�H�	�U�BCC===)��8q��n������t�LY������+.I����m[~��M�2��m�&c�@O!iM�����w_|������#�w�CBB(��:2�^
(Z��j�@��C��7o^�B�n��)
~�H������=<<t�G(����w��q��M,(Q�D�J�bcc���+Q����7o�?���}{�J����+$-�7���:t($annN�	����������2l�0++���_��e�~~~��������^^^�2s�L�z��MKK����_(���iwwwoo�e��%''��/�o�@����M�O�>-w�@�!i�<�5kV����,Y���x���������x,�e�������������>��g��;v�bE�>}d�9sf�"E��]�v�������p�<����5q�Dkk�J�*%%%��q(��l������3rw�(x{{�����0HZ �lll��@\�r���E�@_�5k�E����uE�W��u�������h�������0B�x���� 333�-...w�������l����i��@���@�Z�����E����?�m�����B�8w�}������G����[r��Fhh��C�<<<v���t�������[���;ny������������;��@f��P�C�����~�(AI������WU0y�d�A�&Mt�7�S>433S(������W���C�8?y�������0����h������+o>\�o��-S�}�����zj��-���j��n�R]�v����m�}�r�g�
�b���r��5j���k��IdO
������U��O:z��E��
����;�����z400P��g�����H�{����[�^���`P��@�D	�h�����JGk��maa���9�zL�T��O�0��Uh�(���m����r��_M�+V������D	`��1)))�x���"E�t��Y���@���X�Z5�B�x�b��zL�lmm�������[��r�7�^c��	|������'J:tX�n����@�#J����O���;` D	`���r���%�3g���0(�%�(�NZ�����;` D	`��
r����@�F�^�z%w_�p����L�2��]��#���SRR���7o��������9G�
endstream
endobj
21 0 obj
<</Filter /FlateDecode
/Length 1924>> stream
x��\�n�6}���s�0�����s[�{�(�M�(o�V2��c��6�
�+)���)j� ����C����N��R:�O�j��?���ON/������,��J�>�~z�1�A+�VS���Ob����������/�-zS��Vaen���E�����onO/������g�}R�9�h�bHj����P$�O7Mz��6|+���
���fJ����lc����x�������N_ZxI1�ww������	�E_M!�+��@�kx�X`8(�
���s(����>S��eG��`1���]S�7E@":%�T��5#x`��M�Teer������{�)Qa��}n���e]�
8���9(�"
��R�	o9A������5�������.@�)1
�3St,�A�}R�N@�Tc��ML#u'��c���	�Q�z3XQ��R���������H�:�A[��K��0���k�,�#�s��`\���e".�w)��2��������JD���QS\~��D���yF�A�2�����q�[2Cs/5o9�^�����s	�z�!�����d��1FH����N�4��E?X��1'!h9�1��5'��Y�G�&0hZ6��DY��t�@�"���f��
<�����% 89��`��B�h�{ZdX�Hf����&@�������}��}����V+NA�6N_���g0�]��.'B�J\�����Tx�gD�F��6a�'�������Q������O�#^k�����iG%V����FM��d������U']Z����A���B�7]bE5�����H��#��jv�����G� l�[7�	x|�\"P�����Q"�]��,�O��>���U~=J��Kq�%X�����<�]�V(�-U<J���i�Y�##Qj��,9|n��M#����5���g_�����m")���lb��&[���'��q�J������	l|�Xn��r/��5M�������\����ch6?F����b�;� 8#�_m��������������N^�aIrn�1PB`�H9`j�KB��7��-!Mj	�z��)!`�����8�gI6��
�������#�]����N��ch6~�7rpvY�9#]c��t}���/�/~�P��3�������`=e���s�3r��9���=����R���d��	��fKf����\�y�Y����<�O���1[K>��������hi�'�����1K��������#�����r����W��BA
i��qs�g<��j��c���3�
i�.�` FY���Fi��%���(W����*�F5Gww�ug���j�w7A�����Eo��bV��R
�r��<�j^9h�79��gJ���rB��
x-�t����BP9���f�Db�6:��Wo�5AHtxw���A^9����@��7����&5rZo�n�w��A(���W�4|�����6r:����Jr!h�ttw�.9����tw���O9� dr:����]�����@9�TM�FG<�����i�M����?<�>A(���W�4|�_�Z��i_wox���A#�+s�HN��#9})�n���������Lp'���_O���Hh���P�l�p�'/��2!������b��=r����O�V���T<��������O��?�dcH��J�+���-J�o:�k7����g����RS���6���vg���]Si�T<�����H������Z�S�e��Ve��r��HcWg�U�u��O�U�dX�O�U����
Z
��J4�pV�jxU�+�]7y"����w�
R3�t�����f�3y9���M��U������,o��h�g�'"��4sa���T���@}h~y������wB)��>Xz�i����<�����"AGE
endstream
endobj
2 0 obj
<</Type /Page
/Resources <</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]
/ExtGState <</G3 3 0 R
/G5 5 0 R>>
/XObject <</X6 6 0 R
/X8 8 0 R>>
/Font <</F4 4 0 R>>>>
/MediaBox [0 0 596 842]
/Contents 9 0 R
/StructParents 0
/Parent 22 0 R>>
endobj
10 0 obj
<</Type /Page
/Resources <</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]
/ExtGState <</G3 3 0 R
/G5 5 0 R>>
/XObject <</X11 11 0 R
/X12 12 0 R>>
/Font <</F4 4 0 R>>>>
/MediaBox [0 0 596 842]
/Contents 13 0 R
/StructParents 1
/Parent 22 0 R>>
endobj
14 0 obj
<</Type /Page
/Resources <</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]
/ExtGState <</G3 3 0 R
/G5 5 0 R>>
/XObject <</X15 15 0 R
/X16 16 0 R>>
/Font <</F4 4 0 R>>>>
/MediaBox [0 0 596 842]
/Contents 17 0 R
/StructParents 2
/Parent 22 0 R>>
endobj
18 0 obj
<</Type /Page
/Resources <</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]
/ExtGState <</G3 3 0 R
/G5 5 0 R>>
/XObject <</X19 19 0 R
/X20 20 0 R>>
/Font <</F4 4 0 R>>>>
/MediaBox [0 0 596 842]
/Contents 21 0 R
/StructParents 3
/Parent 22 0 R>>
endobj
22 0 obj
<</Type /Pages
/Count 4
/Kids [2 0 R 10 0 R 14 0 R 18 0 R]>>
endobj
23 0 obj
<</Type /Catalog
/Pages 22 0 R>>
endobj
24 0 obj
<</Length1 31664
/Filter /FlateDecode
/Length 17974>> stream
x���	xE�?�������g2�L��d&!C$��d	���I�T����9DA���B����*�+�����'�x�F�eY�d�oU�����y��}�}~��O������U�=rD�;��n8=IO��:k��q����d����#&M����	�$0�w�����g�X������c���e��
�Xn�yI�b�������{g^�,�����H���/�s�kW��
`�`��9�-��Z��
��s^q����?0h@����.Y���W�a�4����<���%��`{0`.&X��!�c!�%�Vl�oH��0�i������j"{��K�W,V�2�b�h�/m�d�����*�j/jY�,���^��/��8�����A��0M
P�I&�fc9
��*�$L�����=�eU��V�/x�4�{,���?\)���4���>x���6_��W,]�9Kg/����-����e�B�L��r�}����4�\�/�W������]_?x�;����1`T�iQ��-�k��nUV�U����bj���^-Rv�|��1����8�v���H�4�����<�Q�sl$��X;��-L���l,!|��x(�B�"<	�
�J<	��I`8�D����Ix���h�w�������x�cK�����:�q��a6��Ka1,�����}1��'���0b�R����W��?������9[�Jn�6a�x��b�����~:�~g���!;�[M2������[�����y/�=;uX�v���v����������������R��������
�q~c#�x;��hM�h����b�lL���Q�&��R�
.�����i*L�G���%`InF�-�Z�O��Z#1>:�.LI�#/+����\�a$����JLE�B�Vb�VQa:�����M��/K��_��hy�0E�YeT��R
���]�\3yh!���6�-�����G^������,e���i�1�\���p����bgj�D,5�#���=cg�=�%K��~x�sy�?om��"������m.L�7[��y-��[��\�8�������$��J��h��`8��
�T�T��&���T�jj�+C�������VW����8���cA�����a���W��H�0*+oy��$~ }��IX������c����q�W�7��1p�Q��������=/�9�gW�%���
��v2��~x����v�^h�?�����n������
8���k�V�F9)�����X�|�g�A\�/`5�^����%��#��HF'���8&^��:�iS�����)yK�ax�
����t���p�+����!G7�mp#�hw�D��r�W�y�n�Q$�9��!�� "�&hk�
�Y)�ZJ&����7��}�?AC�����ap`+����
�����w�Au2�p�$��7J�j�?�Bw���j6�8J�P�����;x��0�=]�2�JUq���7P#����1��S�oz5��������(�k�f6����xH	G��^t�_X�Z�7��Y(K�N��#{���T�vO�pF�p��'F|� i!��7��t�A��	��O�����/Dn���+H&��\���#7���ar�|Nk�d��~-�������#^��^u����i������di�z��+a
��6��l/���<��A"S�Ux^Mn$����[9J>"_�o����%US/
�<<�t)���J��G�<J�A��B��UB��{�N���n�C�#�8����U[U���R��:�6H�h@��Ouu}�
���o�n�nO~����<��z_Po5��^�~�#�������!d4��2�,!+p$�#w�Gx��!��(�E��>�����O��qx^Hg�%t����7��$��`��B�0[X&\!�.$���������Ox&E����G�3�����g�g����O�:�%����o��i�4Aj�6K{�74M��/�nx6[�����N�
7�2�M�D���<f	c(r*}����H;�W�P���X8)Fq�_�[�i:XCF�I0��SjS��'�R%�����l��W�
�j���mh�+��?}���*�##���+���t���������AH����U����{��f��X�:&�R����1�\T!|���7�D9^w�Y��	��J�E����T]���W�<q#�!�@�'��*I>T6��4
w���o�u;"���i����0F<��H�����aIr
\��&����L��x��J�T�u5j��i{P�����`�9g4���w�y'�	9h������������L�j�W�'����pWr\���Q�K���O`3<N�v_�v�����N���'��F�6�Do�9�8���/�|#C�O�(��^gurS������.BKr��+la�p��������b|�c0!�X2@t07�����I�R�8A���{��������p6�(�q�����6erM�z�9U�U��_^V��oI�����^��H~8/�s}^���t�m9V�l6
z�V#�U�@	��o
&�M	19�����������b���e�&^,��dK^|V��R2�)I�`T��������`�>a�7�����NN���N����`�knm0A��u�����X�T�������������:=�z������9�p�:��Do���Jx��u	w��� !D��g%�O�VW�
���{'������0�x��I��%$�Lp{�!������:d��)f����0-!4��6,1l�6�����L+���.;�+l�s��������m�e����cx/�o�8����8jR[�k��%�Zl2���=��|��u,�i~0�

��8�	���1��y<������n�<-JT{������6�8��]�x��3���N���N�9E����L�xqF���Y�z>"���L�3
d0{ l�9��QO���,��y	����� ���O�"r8��_���G���T�:"���$�j����X�����4��8����������� ^p�`<�ms���P�M�
q�#��	��x.��A�$V��M,�@:�>����s2�7������mOh��?�����;(A�C�l%����	���66��v��1%`&/E%r�M�4EQ��s�)2�Yd�!!F�O��zV��A��)$8<!7�T�^
��7u$O�����m�n&�z������a��FS9j���u=�����M]��a��PpX��dF��#y` ��D�l+���$��=
zSt=�;�{GE�q��pp���������A9�q/}���qq]S�q:��n�&�o����K�PP�3L�O�'�'M��W��<��:�ih��|���7�����D	��"��mT��{��Zy��x|f��I���A�49�F1MT��<�L��<-�{�H�s�������%��#��e$5d��U/���,h0�Z0��^�a�R�H����X�i$���$P��V(�Y��H�^wv�����Z�Z�.�����@:�n\������V���g��>d��i���/�au1*
�-
������#��g��%q(������e���J��������'u��Z^7{"5�;G6��n}�H�a�&#��J��fuJ:VV��2<�N��Q������9��m6AvIS��
�,�W���X��G�t��g���e��4��E���R��Y�a��=����&\Yj�6^��������#���c�Y��l�5s�������8�����\����u�3G*
{l�gV�������������2Fuf�;�u�U7r�5s����N��;s`SY�a���aeu{����6!o��V7>�����3��Yl�5�n+�-Xw$�;�n���#���cr�J����a�;����`��+*����Yu#w93G*
��� �U������	vV�����5��%�D�g�m6�'s��8x��*`����'+�auG=5;�%K�g�m1�/s�����!(�*�Me=����;k(�a��FqP�����f�g�T�� ��JaSY��/+���5�b��Ev���Yu����4�qQg����#��l���/���\d�a��g����H�H�a�}��<�>nVS�ce#L6+#u��d��xV�n;e�T�?�e�*-��NA��-B�T�w+�(���C�����>�#�VPU5Y�*�Yb��E�l�5����W�,�0����(���s��#�J�S��G�ae�P~lc�0��,9k�(�y�|00s����c�J
���@(ee�pL��P)��^�,���G�z�qT���
�
�����x��e���k�� �F%���0���_`��f~�~q5�V;0��p*_D����V�Y��+�����@p��n�������� @��830l�����c)�0����I��m��a��m7����Ky�Y�64��������	���\�� �X�r%��P�Z�[�Z#����3��q|Hv|1"��L��m���N�����h����D��YHH��RZ��I�5*���v*9�s��R���<�����@?��C�!�����#Vc��a?�#������<���0���C5��b���k}Q���uGFWc��=D�����.�����;����m��{9+I�H�pzS��Q�A���}/��(�4r�sB�2!�-�/�!����:����������
H``�����0C���H������a�m��eAz�k�����c���m�L=��q�?�����a�G~}������?��+x���}���=��#�U�k	����w�[���c@,�P�a�6cP��4�mV���<��Q�6��_�5��G�!D������(�Go���7����u��b�r
R�/C�At�|�D��@�At�d�:����*�- �3�G�r��q�.�^�N�^d}����G��x�WQ�ui}��N$������j����V��Ik���H����I�sd E+����V�]��i�NZ[Hk��FHk>i
��x
��[�/u����	^����LC8�!������G0$y,���yJa��]�vU+�>�J���/��/�4��0�8A/"�������1��p����X�������X����1|�A���5
�R]��;V���8�/��^�h(�+���<R��#f?�O�i8��f�h,�������mm���D7���[R��m��:��m��5vr�E�:R	Q��@h������k9��Sx-m�M���m���}������w"����"�����[�����)O�	���x��C�)�G;^�y�������x�5�qw[�jv�X�X�����[07&F�Fb}�����sO��wa�J)����'��S�"�l/o4��N�� s�����i�8i�T*��BR@����Mc��������WT�KB[G�x<������c��_�sZ��_�����h(��a5i(�80F]L��� �	���P����Q��&�FuH�������4��i;	��St}���:H�%������@�e��^v-\{c}=���U���C,��k�R;s�z����GM��x2�>Q��dn���o��^�-9YW��|�.���
C��uY�0���~T���A�|���c���4h�Y9j�J���r�������k���h���HX��-�u�;��ygZx�g0�����DxG+�e9ZY��^���"~/B���E|���L=S�$UdC����@���)e���e���L�?=f������3��pS�n6���
��u%Z/
w��O�G�.�9�]�g'���k3�����~!��e�������v6�g��
��7���1���G[2m���������Y[#*~!��e�`mU��*X[#�#x[�y|���Z?�A���z�k�7T?�!/��wp�u�wz+��>V�0��&�XVqMq
�B�bY&� ���zp���<���1�
�e�[���n^����&-[�\�X���W��7��,�UB�h��D����vJ�6�GJJ���u�JbL�!S��U�4�6U����<u����>����d��	���U���V�>���yh��l!1���#��X�8�gN�e�STj,�����xKKzH2�Xf��a��@ �P	��f�T����4I�E��fN�.�5��K�#��h#���L�2�-�?�jA�+".���?�l��Gt!��k'�p#���c.x��K~��/C\N"����� �F�W�!D\"F��k�0b!�#��(b�$OCo(D,���1��!��b�~����`�2(A,���S�����Xe��<�O��8�#�X��
�!0�*��B!��`��P�8���s�`�p�N��G	5���P��8��a���qO~�6��`�x�8�M~9N��'��d'L�1�S9�c����?��#NG��`�
0	�&#^�qLI��`*b3��x��0�g�t��p������p��������0��^�q!4#^a��0q��0+�,���Kab�e07�),�y���|��?���
��J��*�+a�*X�x5,I���[�q
,C��'�������.O~��
�up�z�q\��6�J�`�lB�n��o����a
���p3\�x\���.yn�x�E��!��1�N�cpl@�6&?�{��{a�}�����f�m�����A��!��a�
�#pk�=xnK��������Op|�D|
�B|�A����q�����w"�m�qlCl��o�nx(�7���Yx�A��"���<��<<�|~O"���~x
�<��{���<��"�H�	!�����+���ehC�#�J��@;�!���*�A|
�E<����G8�}�����M��#����!��#�	���8�
^@|^D|"���=������r�(�x^I���G�*��O�k���a�O�O�������s�_�����$���u�p��7��7������I��������	� ���/x/�*����
 ~�x��c�?�q��C��8v���W�N &���������o��u���c������/~��?�����t����N?���K{���E��u��?��q��Q�N������N�(K��3�~����\��/��o�����_���:��N�������:����������Y����:��%�	��*d	Y"�'`?�?�UXAP<���kH�O/������t�@��1��0P�j1p��ot���'�O�dLg����4���kh/��{7�e�:�)"q������N������t������P�U��/��;|�0����g�Eu�J.5��f��0t�������H~����������R��RJa�T�a4��S34J2���}"�y����7�Z���l�Sw�HY��R�a0 X��b������������t
kR��>m79�U����Y�2K�``��2U���]t�����6��5���9y<>VT��������TZI��u9�����y'�4������9��M�+�����W�����n�_q�C�T�����t����$���aC����
��E���j	he-��J�!���-���eX4,����y �[���Q�%@�J/[�/����1�����%�L
i\�&�I@0dm�C,�#[��:V�L����h��(+`���<I=e���.k[6t���q��{�X���'�^y^#}�����g��N�������;�%�u���I2���j���c�!���\��w��:��u�	��Ny
�B�h)_ ����]�i�hA���VE������Q��P�Ho�ed����qg/g/g/����1O�C8�x*�r����R��*��*�~�"kA�%�8�#Uc�����YI,�l<�1F��P��VK��(�?���>���J��W
Yxf����*Q�Q�S�^�P2�h�1��KLV�S�P!k��r�H��"]99�)F�3'��ke)�M�g�d�~����0�o`O�����
T�t���`�b�,y�0��P�X$V��`)?�i�`�R�`\k��t;��zk����4VwV�<e���8�_j�I$k������~N�_������t���0���0�t����
����x>��������^�'��~Y�;t�$_
^�8��N����|�����<��O0�����qb� ���	�uy�]ZPuiA�1A��L��|��	+y��AGY&���j:�.���H��|��;��5��DF��O)�V�UU���x�be�����'fZ%�r�ep 4���)I��C�
���������L$�6�,���*�3���_?~�U��K��|���O�|������T�<p��O.^��{7�y�����|������NM~*:��b�}���J�#��������nW�M����F���+�Cka��t��~����S�2�����5(3iJQ^'��0�{���`����;�N����������X)l�UF���x�Q���o��+Lt,���f9���]o�h��}��S�tz��$J�%lN������F#��c]�����s�Z��
�i������bkF[[fi��D$�*��J��R����j;J *G)>��g�]�-��2���:�G���3:zK�rK�;b��?R��T�1���N0���9�(�����YR��KN���b�RE�L�c�!���S��-X���Ue�mV}K����m����|f����fK��o�>I�u��.q��l���f^s�u��/�i�5��>���t��_�2o��>�U�C�m$����������q�
Ws�*�����s5G���9J��8J�pi4J:`
GG5G-G�,X���6<ax��-�6�*
Vo0�I������ �A�@
FQ������l���'�����gU*]<7P�K��Up�+�^�:HE�(����Rk����L�0���r�2
R����=H������Md��0���)&�U��27����U�J6������D�f����z4&?h�V��}#�/���+17��UQ���e�6C\_ih_i�G+
y>�Wr�QO~��6���O�,e��E�z{�u�����R{w2�a�O�=������0=�����Q����99|:��\ip'E��3J$�dT��W���B�bTw��.>�����Zh/m#^�3��v���L��,�~��D@r����%'��b��i&U(R]Q�0%�������(��so�y,�E���w�m��T��}U}�����i�����s�d��rl&��M<�u$n�f�&�9n'�N=k��L�y�[X�,3�E�jy�,�����J�E�%��+�T\[���I0��P���v��r	�T.=�K#r�>|-P�X��S!�7A���%��:g�M��A%���T4`�I�F���~��k��o:S�7����w���f�����EZ��7|���q������5t����7�ge���P.Qa/��'��X:RD0=Z�4Q�f�p��B�����3/�5�Tt���p���$@f�x�q#1������6��O "����D�;e�SNn��|y�L�%�qX�C��;�������I����k������Y�,�|���2�r�Z���75o8,R�Ml��3��a��1*�3$�QC,��z9�H��^�:�;�IK��0��#�!��9+���H��9K&����������F�60���R�����U���T����3�������/��|�v���z�����b���b��Y�S1j���0���e-[K���H���PK��Y����\���e����.W�sL��r�y~N{��G�����}>��~W����.}����|R�d��wL�!_�7������y5EV�'~��?���d}��w���#�����z��8n:h$"�Q��E��M_JD���"�
�8��	�c��h����fP�/��j\�M)a+�j\R5�T�X�4[-�8���T*�
[��APK�VkE��{Sw�����5�� ��}�m���;��N�$/���&���Qj�������K/�=\
K����R�x��cq�������3���>�K�/��x����zU�3�����qM���=<�+������.�Q�5�n��3��n�S�����jU��j�3��o����
bf�#�l��
F�L�K`����RBF��|�����\��g�zn>�Jgeef�Y�u�#j�#'�^�9m�S��4$~���D�,������?���K7�m��T��������q������/���}�*XEV��4K�K
��W:o��d�x�f��:�����Y^�����h�=���Kq0�t��W�~������N�Z����J���_K�����
���b]k1���k�����;��qw��+W0.�`\-	�tN���3�yf>��o���A{�N�[����m���
�S�������|�G��5��5.]K��)R��/O����3`J�-K�d+ 2��O��r�%�n�>�����o���s�n�x��A�n�������~L���s��w�m���^��>	���{2y�u��������c��{���'O��1���=���(*a6v���r+��.�e��}p�e���f��b&�K��CNo����`�9���<k��Y}���]����]�����x!cp��s��o�X\��1}��l
������	�I�lQO!�?�ckp6yc���J���C�g�(3K��2Y�8������g�B�+��l���J�����v��8�_,,t\��������s��n���=_:>
��������!�5KM��F�r���`��is
}�I��x�l��N�2H�O ���G*A����af��t��YkKO7qKo����pv�p9�h�o���%n��-�r��:%C)	�8�iK
�KH�/~<�x�Ch��f��
(>V�.�.$v.=��;V6OZ5~��%{~"�K�;�����~�����mO�\��$_y���[lpM]@4;F���?������]�����s��Mh����JU��P	L4�-
�Ko����Z�|���P�i'����ZTV��B?(��Q3���q�e��x
�� ���yz����x=�&^?�%N�Y���o�S�w\b(���nTK����\m��^�"��zI}@>)�5�z2������?
�4���
�Q4	z�V%��I��$��A"���|�3(l�E���Y�
6�K�W�4~������Z���SB�>�G5��[
A�-	��G�c��E$b!q�x���A�b ������Z%*����[.������)wz�rg'���<��'��N�[�����c]�r)���:��A����T��pTB?iT�?a��v�,h�}�������f=Y��+�~�I	!!'$D��@��L���T�=�M��kx��L�������Z:�����o`Z�~����_f�%��5 �4�\?��E��A��Hv�l?�t<���������6�<����p�6�|�=�\����-��%W���`j��4�n�Hm\���g�#��v�u���H5�7�2[��U]1���D�lAb��w���W��5*���n��E�z�Ag�	j����qj���	�����Cg	1=c?�\C�,�R��*��NM4	��6*���O�j����Z�^y����;I�����s�����_S�������������h.�>�_��~��"�+��g�����v����H"|������Y�l-�&�uA#�y���*��wtl"���X����fR������_�}�XzX��qEg�q��g�f����J�����b?�U�N�o{w�������K�����^��xm^;m* jr�U�����I#������C���7	��i	�D�������|�}|e�� 
4�������ImL����k�2V7]�Z@
r���������
��0����������1������Sc"�Aa�����c�qe����s��j������}���#�h ����p�e�
����������<U$D|zd>���
� _@���#�UrUF�;B#����p^>Z"k~Y��pJ}(!��v�*�!����%���n�[���]d��[	�%�#t��Ek_�<4p�7_}r�~�t_���\��7IK���[�.n3��q��������X��X�k���K��
R6:�6�|����.���=�i���&�i��&���s�l�Q���La��",�HA��7L8W�[��^0I��r�/��c
��g��&"i"�&
�D��RX!"i"�&
�
gT�1�O����sy�6RW2=85<%�P?���t�m��
���+�����-�����
�������Fn1�n���O��*E���G�E��<V��_f�6_�������X�/�����b���K���w��b�e�
��K#�5/�TNo�8�o2�U!T�^���&��<LC
�-���Tl�O����YY�L�d<i"���F+7�&Y�����i7N��Dmf���B/��y�&e��S�����4�8�\�B�K� QkG���5���n��t��_J����,L����c��Z����	��(X�lT*	����{��Y�dG�Ur*��D���|I��(8����9���`@/?���q�W-zr�����'��s���>����}��O$�H���z��?��r�?�"o���x�����9ags�����~?k�kkL7����qee
��l���e_0���v`��>���\AI�w���k�=w���+{jSZG������c��(����g���eWP�i�U	-a�QBv��[d\	q��I��o����
�)m1��K�F����
1�����2��l��Ssf���<�4�;W���U�o���������m����z����/�R����[�?p��d��1�[eX�m��b�/�S��_*�=_�c�*���3�u�T�����"�)��~�UE@�4:Pi5*BU%��R�������ty��%*R�BDWb�kh2l�l�n10�4����*R����Zb@c�UVWs���i�A������9
R��R���"��v�����R��r���j�h0�����+gP��n���KP5^E���T[TT'U*U]�K���+�f�+{������D#�qw���\����V�/��_�f\{|���v����~��;�c�B,6��e;����wg�}f�`}V�s@^hM��BV�	��M/u�����[��W�{�0��y��E�8
��>��5j��FOQ/cQQ�q���;����Fcc�|����������q��	��P11|�s���G�O�q?Wx�}��/��5������z��zf�����cT�p�z�W����G�����]���������{��1KE���rI~��4ds������+1U�6����&�V����D�,�L�{ �Q&|&�������Lj��`�2�4�=\a��d���B�����I��:��J}��W���5�W�L���	H��PGB�L���?�| %2��g.�:�W$M�����@��+?��;�qSA��F�FwDU���\��1}3M�MD��U�?��+T�m���}4_��v�e�3��+������.�%���G�4��VS��������JK5��T��#���'C5��Us�N�o`�����(��,�	Qg�	���E��O��9�����P�����D1������h��,�0���J?��(o��Pnhv���G�d����f�����-#�/xg)�[���������?9^�:���9/:�����ys��^;e�Sk��k3=������/q-�aT���>+N�������B�\8�dd�����Y�����N�&��^p� ����@j9�9�-�,�WnZm&f=��xX�V�^r�D=1�%
�j����w���t�|����b�6�������|�r�9'�Lr6�49���w��4F�n>�'�W-7,6�5�����6��
S��7�����,�	��h_`�j�nm�mpN�]1��p��>�z��13�a�����4\�����JK�W�5\����!��I�C��v#�-�n����H��0�W2V#9�g�|l�|l�|l�?"��T-Q��n�t�6�kI������y�f����g�qi������c��Slgkizab�,�O�w�P��0q*o���Gow���P�3��g�����/6l/���z��'�n�Md���#$���&t�������/\��y8��1���%��+uT4F���Z������|:Y7�6�7��R����5��P�5�}�'9���v���I��@2�b�*G�g�gq`K3��>�A��q�3���;_7�8����3���I&v����8���Q����F<�����|~�,�����.��	
8Dd���������jq�������T���Y�e,j����aa5��<ZLl-�3
����bD���2��I��u�k��]
�;�������D��$A�s���L�+r�y���y��/��tg�.�����m��*�B���������K��MV#�,X��j,�3,e��J`������|��6�^��+����y��\���J��j������������k���(��~�4v�������t���j�N���ig�5vflRCu">�Q�>�������i���:���Wc���M�6�'����x�}+�+���i�b6:��M����3o���T�E�O'�>�$�n����O��}[�g�|��V��r�q������d��`��7���E�	#1z��������H��Ln�P�(��N�9_�����Z�zE�����]�>>��u4����-�Xc�����4���|�3&����vwU��*�hZ��q2��4�d(+�M
�@$�_S�����j��_�{%&������37u�C'N���	2��P;	�Ha����������6�Qfs�l��Fn�*�����MsD�/�	��"O�;��N��`�	�n�}*�����kH���Id5CD/P���Z������-�B�6&�Z��X��$�q�VN���\��6�|]��O`��<~z���`���|@y�q�A;�9��CtP�N�@�`[��Oue��I�O��}�/����>�q'�������?�fy��.�n�+����]�&`I,�����XiO��`2na/�S�R&�I���/1j�^l{i
����e(��u������nY�~������|���T�������{�f��]5��U]����g����y,�������z��K�_J��?�?�R�	I._�)XqTs�8��]i���~���~����D�������(q�-��|
�J��A|c�q�-�m�������$�7^���V��T�qmR�h��D*h���b����*��SK�[�mbB< ���"1(���^���3�/��u�}���_T�P���:�
�X��L���`�SS�,(���f�x�<r��������������.F|�I��l6�\Lf�e��S����c��O1����(�pq�
�����[�]���k�~�5/�|�AUaVT[U�T�8��*!�Z�jU%U"���
����������or}@�-{�����,���|�A�F>k�#�Lo|����=���[*�Y���?q&]���70)]���U���BNJ��Y_�*�%M�����&�i��&r��}i��&<i���H1�	S�0��e�'������o��M�QT��&�i��&�����4���o�1zcyD<!��~��$����t�:5����
j!����>������;!["�"4�tzL�-b�3���_�rg��_��>�C�r���]2�^��_zd9f�1�wi�������l�/o��i����E��5�����}wL�VL��������^�B!��0�>��D���p��*4�0�'�E�J�/�e�wB�7)��S{�=O�m�@(,�m(��#d��c���S�����9!g%*c��w���]��\?TUU�>�v�,���&�-'j3X��j���G���5e����;�N��	�.|��mg(}t�ew�>t����
C��>m��5���mcg\4m��=]���3��p��m���w���v���%�Av�sT�:�>.w����N��E��+Y�
��)uw%]bPc3�V�*��a�MS�iMi�3�v���wqO���
=�'����g�	=W#�<^"�N]���\��~-g=�'��q���s�EO�O?���Vo�[�N��b�6W�u�%�Zfwp�qprp�qp}w��bI���E�Bw�Ka�r)��v;�����u�/%2��d��nF����)��E��<�g8��N��t�Z��r�K�:k�a��%�s,�������u.�������h������;��)]��B�����[^�z��,�u�C8�V�����r�|�<J��� 
{����������[��A�A����y�5�
����y�%����m������?a;�?La1&����A�p�<y���������b����i&����;�,��r��|��,w�Q�uq]��U'9�����?���r��Rq��,����.��?Sg��;�e$��������QYDF��l#	r��RM���]*�
���u	��1�� 	c�_��rg��-Om�s���p�����F��S'��3�����&���j������;�6��L�E�ZO�{x�-s�����U�7��<z���[���{���'L������o=��G���_�����b�s-N�K8�� >�$��"	���0q�x��LTk-�Fk��h� h��O���[4D��!94�����������[��K����FV\v5�/���[G�%����xj�	����2���_YgZu�
�R���2zN�o�d�}p���.2t��m~1�����+Q����
�su�sa'�L_u�S1h���+W�h�g�����"�&��D(M�������g��=O[�?5ov�J�M����y���Q����}G�~����)���D�j�4ht
�C�q�f�v�n�~�a��=�^`f/��{
��������*\^�������[
��}[��uO*x�pW�QGa���K�4��&R��N?�:�P��c����A�����)�t�'���>������������q���#n��p/rs��f7u�9���W?��
+.�8�29J(��ov��|�A6Y�	����0������������i���xc#��G�O�;��*/e��gJ��R�I�����dw���.7��v����s��^R��=|)�_���U-"E�MvQ���E���jF|�������Z�<���������������
�|p)�
���2�T�5����[�sa0��������13��8�X���U���3s�1 �?������h\2�T��Ae�\:6�}�-a�Y�M'���^.����Cgo��%���S�\��bXe���V9G�y���������6��La/���M/��hu�������l�������YYj����$���[A���_��/:�e4�~����V��7\�rE��o^�k\����'���tK��2o�|���{��;��{i����9�Kg��vEJ�]3v��������&6L��rst�e5+�o=�i�[����"�]�$��������������(�:M�����Z�%��hu�*�`��6f����f9�����)f�@���N[�$-�Z�-�RP�&%��QI-1������F������-E�
3�!�?-9�L-R\)K���H����E����u������SU|����5KY��
[���F��N�%���R�c�?���gt�E{_w����sb����Cf?Hgn"���7u�fLo��Fab�
endstream
endobj
25 0 obj
<</Type /FontDescriptor
/FontName /AAAAAA+ArialMT
/Flags 4
/Ascent 905.27344
/Descent -211.91406
/StemV 45.898438
/CapHeight 715.82031
/ItalicAngle 0
/FontBBox [-664.55078 -324.70703 2000 1005.85938]
/FontFile2 24 0 R>>
endobj
26 0 obj
<</Type /Font
/FontDescriptor 25 0 R
/BaseFont /AAAAAA+ArialMT
/Subtype /CIDFontType2
/CIDToGIDMap /Identity
/CIDSystemInfo <</Registry (Adobe)
/Ordering (Identity)
/Supplement 0>>
/W [0 [750] 16 [333.00781 277.83203] 19 28 556.15234 36 [666.99219 0 0 722.16797 666.99219 0 777.83203] 54 [666.99219 610.83984 0 666.99219] 68 [556.15234] 71 75 556.15234 76 79 222.16797 80 [833.00781 556.15234 0 556.15234 0 333.00781] 87 [277.83203]]
/DW 500>>
endobj
27 0 obj
<</Filter /FlateDecode
/Length 321>> stream
x�]R�n�0��+|L��H%��E���J�`/��b,����]�J������{�����y��&����6��<����U&����]��eQ���al�0���<z�����Nj���E�N����w�up{��F0������!Tz��K7�P�oT�k�������X�	bAn��`����+�2���%���Q����A~une'i`�q**D'B��#�,G�3'fv@T��e�w��~7#b�	�GrF� ���8��� ���� '
�BO4B����|� ��������59�(H5�d�Y^_l��}��\��G�>�6p�C�dW���+��<
endstream
endobj
4 0 obj
<</Type /Font
/Subtype /Type0
/BaseFont /AAAAAA+ArialMT
/Encoding /Identity-H
/DescendantFonts [26 0 R]
/ToUnicode 27 0 R>>
endobj
xref
0 28
0000000000 65535 f 
0000000015 00000 n 
0000376539 00000 n 
0000000104 00000 n 
0000396841 00000 n 
0000000141 00000 n 
0000000542 00000 n 
0000000227 00000 n 
0000053780 00000 n 
0000101749 00000 n 
0000376791 00000 n 
0000103623 00000 n 
0000156542 00000 n 
0000204214 00000 n 
0000377049 00000 n 
0000206087 00000 n 
0000243906 00000 n 
0000290209 00000 n 
0000377307 00000 n 
0000292197 00000 n 
0000329152 00000 n 
0000374543 00000 n 
0000377565 00000 n 
0000377642 00000 n 
0000377691 00000 n 
0000395753 00000 n 
0000395989 00000 n 
0000396449 00000 n 
trailer
<</Size 28
/Root 23 0 R
/Info 1 0 R>>
startxref
396980
%%EOF
results-pgbench.pdfapplication/pdf; name=results-pgbench.pdfDownload
%PDF-1.4
%����
1 0 obj
<</Title (pgbench results)
/Producer (Skia/PDF m122 Google Docs Renderer)>>
endobj
3 0 obj
<</ca 1
/BM /Normal>>
endobj
5 0 obj
<</CA 1
/ca 1
/LC 0
/LJ 0
/LW 1.33333337
/ML 10
/SA true
/BM /Normal>>
endobj
7 0 obj
<</N 3
/Filter /FlateDecode
/Length 240>> stream
x�c``<�,�y%EA�N
�Q
����p��o� j/��Q�p��'�@,S�h$�-�a+��I�	�]^RPd{��E!A�@v�����NBb'����6�9��w3����C�2 C���,�200O@�%�d`���� q!�����h���1DX$%��X��)-����r�H�\����&�y2��@�����
�d�cHf����[=�
endstream
endobj
6 0 obj
<</Type /XObject
/Subtype /Image
/Width 2019
/Height 1058
/ColorSpace [/ICCBased 7 0 R]
/BitsPerComponent 8
/Filter /FlateDecode
/Length 51923>> stream
x���y�U��8�f\�H���Qc�`�f(""�T�X�\*N�r��1�LM%5q�d�dDQd��R�������U��FY�Yz�w�;���{���n!�O���=�{�9���?�w��'H��_�����[W�c�Bu��%��'N�X�c�'u���(U��M�����J���-[�,J�>���BE���t'N�R�s�����P�$�*]�n��T���[+{,T4�z���{��(O��S�����M��r����Q�v����=*�D=@�z���<���+{,T�z��<����..�.-�������"�%�������/Z�h��1�{����c�6m�u�6d��7�|s��]�����p������������u�'�x"O�81����.�>}z4��]�TNN�/���W��m�v��!�3y��/��|h9��������g����3f��Jv����k�
0�s����=��s.,q��W^y%ja���Q��%K
�1��7/�����U�VM�2�_�~a>�������?m��u�����&m��9\���K�0�pyhd����������K����#������8�(���k���Z�j��]�Wm��-�9LK�g�O�>���_�ti&C=v��;��3l����p�a�s��9x�` Q���[��j���Y�1c�D1�[���m[z��e��v��]����I��;V�HV�Zg�KjW�^]��3g��b���N���Jk��7�<�I���7F�����t��G5u��p:{��x�S���{����-��1#
x������9s�W�'���"����C�����,�6r���g�}��1&L(������c�����w��=.IO�����G��QOQ��O>Iv��[�ti��u�z�\���q*r��
�k���J�r��=;��������?���/>��S�������9R����dd���y��Q�F
><��!f��%�����[q����=z��N�u�6p��^�z�n�:9����3��0Q#�'O>�k�`�k���`�����q�����s�O?�4���'��}���6m�$/II��/�]�vqm��|�=z��a�����;��h���������R��}������������+VL�2%yIJ�>�w��qm�����#F������|{���w'���m���
-$gl���q&_�(���������);������?����=Nl���3e7�C�M�81�0aB��n�'�;u��d��d�6��h��:Dm����gOJ���n��E��G��{��8 ///�4&�����!C�F� �/n<xp���[�j5s��0�8 e��Q�RZ�	S��k�e�\�>w���-,_�<���g�}OZ��m.\��������=4���_��
���;6�=&�k��A��|�Az�/8����~8�����t���>�(<qX���`�M���U���x�����5����6lX������=W��y�����u����7@���}{��}����U�����:???^���{�C����K/��?7m��R�jC[�l)��u���-�92�����������I�����>|x���}�����=z4����iRv�Y�xqz��#Gz��������$��w��u��a�m(��6��?�V�Xw4{��rm��x�X�[���:u����Of���Ck+W�,�^���#������?^��!�v���e<c�E�%�D�(G�f��r�m�����{���7W)1���[��A=q�=�q26eQ��m��^~��2F8r��8���0;N�g�\T�+�����a}�Q}�&\]>`��3�<����[�8S���;
_����Kl!777{��W���#��=z�����G�s����
<�g�����ni-$7�I.b�$��y���Jl!�<~�Av�?�D���c���S��2��ON�D=P�����=�G���4hP���'k����)�M�E�k�.������=�;������#�{���b���w����#[�pa}����_�.�>}�\���~�����9r$^���dU�N��WZ�����aq�����w�z��w����l�L���z��iSi�F�����s��IV��h��w��[�����]�����+��x����8��9�H����V����<�- 4Uv�����q��MKV%���m�r����q���s�p������]{�'S���W7��_�(�[�n������M$���G�e)///n����+��f(�&��m)��3Y���o3n��w�&�od=zt\����0~��2.O��#Q��x��'E����+1x��}q�r���e��{��8x��eqy�^���z���k��]���x2}]�n0'���:\r��R�y�6m���z5q�;�m���>?Ark�������w�b�y��S�*~������w�IEEE�X�b�������V����3I�?����
`��	QL�V�J�����c�F��{��w�����7�(��dJ_�(wEEE��Nx���K[��e���3��;�����
-���I=z���S�:�L_����K&��
�3�~�(N}��W�I�&�C������wz����.o���|//��b��6����S��/)([��������3��:�-$7�I>�eO�D=p6l��=����cGi����;��hvb�}rqr;���|��(8e��I��+�K|�n&���)S�����_�������#���g�������6X�jU���3C��W^y��2��n9�j��5q�)�_��OD����0}��d&���������>}�<��8ZPP�0v��S�-N�'7-9Q!�����8=�e����6�y�;~km�W�gr�EEEqL���3�^�N�Z����sg�U�C�������=v�X��4�,Y������WK��a�����[g~�Ax�V�^�y��c����Y�e��V�Ze���K��m[3��3�1N����7)��T@�>���;�r����������L&yG�i��=�Y={���i��=����|�>�$?���i��aC<�Sn}��$Q������}�F�q���;��������������s�e����u�ZH�v>]qqq�7��#�U����5j�i]���S��I���/F�)oG��N�W�<����5��G��	�A��qy�
�3N�')������Oe?��#%���oz��S�C'�[|����%^�!��Wn��m��]�+�?���8A�����D���>]�`����0)N}�j����������G�}��I�gx��F��b:t�P�����h�n���l�7�K&��}�������gv_&3na���eD&w|���Qr����G����~��\�~}�U#F������g����3�.>���2"-ZG�X�"Yu�������{�����q�;��aCia������������4V������]�6�|��e�]�����'����0g�������]�F-��3f����]r����C�����������c)&w/����/6l��9sR<���'na��Ie��0�}��)#9���u��EWu��=���%S��'O.-,''��Y��N�}P�[z���7`��������)����h?����|��y�]Z�N��ysJ@&�������+~P������(<H�I[�b���G�U������c��/�S�|�D=P��Mo��m�������{w�)�2eJ������;w�j;v��g���m�{��l/><�j����M�Jla���qv4}���������N)��7�e�������~���1L�fx�'�W
rrrJ�9~�x<��:uJy��m^^^|���>[��y��P��\�2%&�D}0�����S���\�rG���������e�+���� Q����7�����m��o�g&��]�R�Lov��y���������|�A��o��u��{�����;v\�lYr�����o�t��-///�����8p`t����3�*]�������m;u���������	e��$N�\T��C�x�����/..^�fM2�����m�G���L}�/=Z���k��n�&LHi$�D}x���3f��}��%v���9
Hi!�Z�w%�'����������al�'����O�(F�����������w���83��[���pr������2��g����_�v��U�-*q999�>��'��=���Q������S�N�[��8����U���������~�����O<�j���a��_L���{��O�5k�$�?�p@���o�4��L�81}����
�1=z�x��x	}�r7m����	B�c����qc�H���'���7���g;�64��{�d��J���i�]�g���/��n��xf�V8]��.�Z���ukia7nL&u��.]���;]�����YS�H��[��w�2Z:thi[���D}�{���3��4q������s��I����\�;�D}����J��]��s������m�p����
�D������Sj?����*�D}p�����G�q�a0�N��>i����:u*m��?���R����N)���+��Rvp����V�J���_�x���c{����c��r��|��	&�����V?E�Y�|�������Zh��u�����~��2.<���I�&E����k^R�8����g�����80�i�6m�u������iL�0�t���'w�Y�z���S�����O�Ym��]��=G���{��/�/��Fv��z�i�7���k�#F,X� ���0�Y�f���#��C@�*�:�D}d����������C_mN
�<����3���{���s��[o
2$��pmh*�8p 
������*HO}��[��S:�R���h�������5Z8�s+�}n�N��J}�[��S:�R���h�������5Z8�s+�}n������������+���z��u��m�����C

R��9��[�o����.���K�6m:d����������e�z����U�[��Vvv�����n���?��������.���;����7�H�������_~y��54h��_�j��5g4%PA�z��*U�dee�l���������{�����o�����q���������Z�j5o��Y�f��W�w�}waaa���z(��6�4ir�m���S'�^s�5�w�N��X��n�����_����F�e���O�dX�����U�V��
�o��A8�]���y����@9X�fM�j��T�������;w�l��aVVV������~8�4o�|��=Q�������P8`��8l�������.[�lYT�����s�=���{���
o���P�������G�3g��U�VL|m����5jT�Zu��1QIQQQ���+�9R���W�^�����~�������Nw��]�z�j��m��9��[o��������8*i��q(;vl2l����*�x#��S���n�!eU|�B�<p����O
%?�p���h�"�>�tf*H��m���|������'�����>:9rd8���;�[���+C��E����M��=j�;���$��	=��.]����]�6���S'Zf�a�A�'���O	>|x(����N5P	F����u�-������7�>:����n�:��h[�a�����:�f�������?T���?�N���%�:6��~������o��h������e��E[��9
P9���.�����������;w���7�
g����u�]�t����-<��c�����}��	�?������L������G��k���V�J���w���O��y��-
����O����r��:�d@%X�bE�n�[n������}��w����S'Z�i��y7n\������7���y����Y�f��k��6���G������GF}E��g�o�x������m��e8!P�����|���u�f%����^�bEs��7����'�_��K�P��_�2���
��>�hz����CU�
���C��^����y�w��#Fd��k���5jT�
V�R%��_�>����t����n�)++�7���G}����u������k_�U�V����V�G��O��>Z���������dE}�}@������w����_u�UG�
�?������O?������P���}�����O�6i��P��i����/�+W�L������f���y��/��^ziz��={�D������������I���DY��_~9������.U���/������;�U�=�\8�6mZ���I�z�
U���/��&M��o�M***�r��q�������7������/L��������a�}�k_���z��7��.����j��q���[oM�)((�W�^����������q��5���R"����P5h�����G	����O	[�lY�6���(�~��}��g�N����(��O~��|@������G���
6Dk���[N?���.��J�*k��M�E�\��qI��M���������Q�Z�j[�l�Jf����������'#�
m~���E�������\�)**j��q(?~���
T�dee��[7��	��6����?��]hn���;vD%999W\qE(=zt�~S�^��F%�����v[���8���8z��C=m�L�0�j��5j�X�~���jk��
�?q�5�����|~AAA9M��������/++�j��-Z�x������������/�|���qd^^�~��hg�f���t�MU�T	�?�pJ�Qz<h���-��������<x0�n����z��������h�F�J�e������W��6l��������������y������^���_��I�v������D?~�W�^�7�]�v�:un����c�����I�Z�lY�n���Q��]�����v����c�}����Y�f���������Y�K�,����/����`��
���o���4���.��Q�����Y�+{8��E�*�D=T"�z�D�P�$� R|����+��a��;z�>s��p�he�;�TT|"^������iqeO<�/�z�D�P�$��I�@%���J$Q�H�*�D=��������-E�=�\%Qg&�������^�+{8��J���D=P.$���H��B���D=P.$���H��B������kwU�g�������^�+����{�c��z��f�����?Cg��Y��D=��z�%Q�����Q��>;>;��W�8GI����'��w�����Y'Q��$��W���G���'N�y��?s�����##�T���I��o$�27uq~�l|z�d�Y!Q�$��3&Q_$����D=p�$�+�D�y�����D}��?�?���gK�o�-~��������~������������+x�%�2����o]a�'u+���ay<���F��H�P��
 Q@i$�+�D=������F��H�P��
 Q@i$�+�D=������F��|~���C�����8���u��{���*x��U��������{���=J%Q^��8WH���$����%�z�s�D�yI��\!Q���\}>�RT�c�T�P�$��I�@%���J$Q�H�*�D=T�M{���u��?�����������_���){��8Q�dcae���_~�G?�Q�z�.���o��g����yJ��#G�u�j/���K.��i��C�)**Jom��1-[����U�[��Vvv�����n���?��������.���;����7�H�������_~y��54h��_�j��5g4p������<++�J�*7�|s���k��N[�h������:x��w���P^�V���Y��������������z����&M��v�mu��	��\s�����a+V��[�n���������Q�FY'���'�y�/��B��U��n���
��p/���;s��z�j�8qbVV�UW]��������q����o��q��?J�7o�g���d����]w](0`@6v��Pr�e�-[�,*��������Px����a���7�pC(|��G���og��3g��U�J�*����
k��Q�j�1c�D%EEE��waW\q��#G�i��&Q_A����^{mVV������,������K/E��w��^�z�j�6o��{����$h'*�2�c��M�������/��F4S�N
�7�pC���:��x�t�
�
%?�p�
�h�"�>�4'�C����dee�x��e��92��q��UW^ye�Z�hQ8��iS�G��c�R�x����6>�`8���KJ���kCy�:u�e��4l�0���??%l��������*����D=|���'++����������n�:�*��f��a'��N�Y�f�a���U?�����h�}������_�zu�����/��>��~d��e�V<e� �3�����_�����0k��������/��f����/��������q�]w������c�=�B���������M�2%T}����N����Z�*=�;��N��>}z��.Z�(��_?=,777��:t(�	������z�x���Yqe�_w�ygVVV�V�.���o|���sO�-�,�u�]���y���d��q�-�k�.�>:~��G��f�������p���%��o����r�a�Q�a��aq_��m�|Z�bD�Z�V�Zvvv�-|�a��o������|���t����-t��%T�������_����>�6��P��A�p|���(y�w����;��#T�1"�~_{��p��Q���J�*�v����T��-[F/�-**J���;7J�8p�D+��U��\Q-z�dE}�W��f������-�4e�}�4w�}wVV�������U+T���{���?�q8~����[��������q��}��O����I�&���M�F�^xa8]�rezd�������x��p|��������'J�>|����?��8�{2��R�?����N�)6l�f��������onM�r��s���i��%����W�P��_�":m��I�������(����g�����K{c���������S�T��c�fee�h�"�����F��j����t��q���[oM	+((�W�^����������q��5���R"����P5h�����G	����O	[�lY�6>��'�~����.���=;%�����'?�I�S���>����T�����,���_r�%�f?���(l�����hC����>.i��i��=�}��5jT�Vm��-Q��3B��W_}���dd����~���4�~����+�#EEE�7����?���
����gee5i�$~���
����P��U�8,�����o��cGT���s�W����G�aQ��^�z.�Jrsso���P����&+..����B�C=t����p��	U�V�Q�����O��P[�v�P8|���������6�����

�o��<=z���o����U�V8h��y���m������������6��5�����T�R���Qz<h���-��������<x0�n�����GY�-Z\{����j���F�J�e������W��6l�����������t�M]t��^���w������������q���k��S�����:v���4iR��-���"5j��k�d�?�k���{����f��5����}�������%K�����]vYh�a�������m�v���?��J��\x��
��"J2b��(�"���F�'���C1h��M�S1
�"q{����%��InE��0�0+�{,���
8��.����=����t��NQS�u�-��^y�����D"�����l***���8����7m��G���~{EEE��L�2��#�h��E^^����;v��/��2���|�y��o��A��Z�0`������U��g�2d�{�Q�~�v���1������4@���:v���ZJ�����:��C<//�W�^={��[�nX=�������9rd����t���o����5���������v{��7�7o6�l���#����s��	&��~�����#���~���k�.,7l����_��y�q���&���[��G���z�Z�fMY�dIAAA�r�-�nS�N
�6m�,X� �l��a���!x��'&����w��)�?�����(����������$���
�z�����N�2%�TTT�7.tk��mQQ��J����g��������SNI)��^��n��u��Y�ti�y��C�������2�t��%D�N�Z���u��4i���h{�����S����������a��w�^xa��5*�����O�O�<y�r�QTT����6l���>H/����!�����s�=���s����>�(��f��M)��
VuZ�3�8#�^w�u)�-Z���5�n���~�����:s���n�'O��V?�y��7�d2����~�+��2��im&M���_�����3�������N;-Z�n����c�9��}�������>�����qcJ�DS�T/
���r�WE�\���&����wEE��-�"w�yg��^p�a���_�'L�����-�Z�t��G�
6�.L������M�<�L��;w��hj��nk���j�����F&���/+���pWk����;��U��&���{��"��MK�����:99|�|��g�w{����:������x�b�������Y������

��%��|��j$ �)�|�\v�e�Db����Hz��{��!��#����u�]6�~����:�������93lj��]X^�~}T<���O�{���?l���{�����~:,w��y��`NNN��x��m���v3f�{�<�����N<d��T_��W_}577�W�^��7���>���[���nz����������Q��}���p�q
��NW��+[T\\��S���''�����?�����;�_d���a���c��M7��O=���n?�p���G�h�Q�Fa��w�I���~��M�>�l��;o�����U��nk���
����[��.��7��&MJ${���)�[�v�B������v[�y��'���b��a��w���x���O��j���a�������]�&�[UEEET��>;��~��[��'���3'���k��M@�R��������&�~��ia�w��)�PVV��E������
�+V�������qcJ����MQ�?8�����5�\��m������T<��oPPPVg����s���!~��'�X���B=�w_��7��y�
rrr-ZT�g4�M����=z$otOZ�bE�z�����l��(�����n���/))��3����s�����;�������.]����>�y�Jk7T����n'�Z��	��S~[������wv�VU�[R��������)�����3���VYw����B���B��{��+WF�7�x�m��!��$�E���h���W_�"k�����o�u�Y�n�����u��#GG��z(77�^�z�/�����
6���'����cd�������9Y��?��M��G����u2g����7v�a��6={����[NNNX5jT��G���K�.�~xT??��������������[GU�>}�t��!,��������>��#u��
�����&_<9=�5��n[,�%%%������K��
�5k��w��S�n�~��#�8�y���g��������m�U�Z���.�{�������u��N:)y���w���C�i��Mx����s�=w��������B=�H�b�P1R��)�@�� F��+����2���Sq�q�6����=��,�;�����+�x�$���?m��c�Q���L���������'�^�|�n�M+�;��
�z��B=�H�b�P1R��������e�����'��M;��L���?o�;�q�2�����Q{���qv-���t���Q{����������k+�p;�w��o����o�����������������H;iba�Y�o(�@�� F
�#�z��B=�H�v��������Eq���a�(�;�B=�a���[����������!jC[�����������
�d��]�������eqg�	��
�@-�����O�1����9C~:�(�{��bI�Yg�S���qOlJ_zG���@�����*�tjq�^�gy��!(�@�� F
�#�z��B=�)�.���J��X2A����A7����q(�+��5O�^v�EnG�jC��i��w��>���'Y������%�u3��?�)�I^�y��5�l��Y������{_Q��Za�sP[)�g�7�U$�K��=�J�>+���2�����e��.�z��B=�H�b�P1R��)�@�� Fs���BI��q��]6�uz����;eqg�4���7��=����q�K���X��j���#G�����W�^�f�=��[n����4�[QQ�
7�p�4n��i��=z�����+**�_p��)GqD�-�����w��c�~�����>�����;�}��
4h�����O�������={��!C��c�����k�n�������2��Gm��A"�h���!���}������S\\����W_x��!�����W��={��[7��p�	���U_p���!�����k��}���
���������v{��7�7o6�l���#����s��	&T�V���w�}����������]����a��_~��;��e�5j�H$��STTg����q������=G�"�z�Z�fMY�dIAAA�r�-�nS�N
�6m�,X� �l��a���!x��'&����w��)�?������?�|^^^NNN�g����W�^nn��)S�HEE��q�B��m�&5�N��/�H$9�����������!��w�hu���u���S����K�v{��C����+��]�t	��S�V��n��&M��xr"��{,�v��)���h���
���^x��!2j���_�O�>!>y���Ld��������'�|2%���D���X����+����a���s��G}�Q�i���n��
�:��g�V�����n�-�&��n���~�����:s���n�'O��~[&�;$�o���7Z��W���+�{F��L�4i����={�L�6q������N�V������hN�w�}����������7n���m���T<��� ^����vX"������������w�����.�.����<a���<t���n�>�h�t��G�
6�.L������M�<�L��;w�����u��nk���j������������D���KJJ�H�^�Bd��i������������g�����^�:t��KKK����+�{F��f���~�/((H������������~������-[.Z�(���{"�x��G��_w�ua�����/����|����w�9sf���]���~���x����������t�=�T�O?�t���������/���q)++;������{����oW���w�Gw����M����>�W5�[�;����t`;U����Z�n�1��H$����K��l=�����;��#�G�6�;6,�t�Ma��SOM�����M=z��V5jV�y�������_�����V������Z�J��f���P_XX��D�>�j��T_��u��u��5�H0����J�p��'���"�H�t��w��'�x��c�?~|�4|��h5�]����***��|P����o���s��	�����[����qc������g�YVV��>��MB��x���E������
�+V��������s���a�m���Fs�\s�5)�,X�_QQQ��au��)='N��'�|ruR�7b��D"q�i�E��-����4h���S�	���5�M����=z$otOZ�bE�z�����l��(�����n���/))��3����s�����;�����u��%�|����2,zk~~��N��B��{��+WF�7�x�m��!��$�E���h���W_�"k�����o�u�Y�n�����u��#GG��z(77�^�z�/�����
6���'����cd������M�����H$Z�n}�V,_�<��q���;,���g����u���	��F�Jy��<t��������tP������~�oT����O��rnn���������Gy�n������/���k>���6U�����d���]�ti��a�f�z��=u��-���?|�G4o�<�������_��m��U�V]p�{��w���[�n}�I'%�������?��!C��i^0??��s�M~��j~�|��S���dME���������/�p��[
��qC�.�Z���O~�$���7^ZXv����T;������P��)����������Q[��2����B=����V,Y�������A���W����V\w���A���0�7�Zn����;��N�POvP�j)�z��B=PK)����ZJ����P�R_V�����Q�/J�W�������fR���VU���<j���M6*)�����D����q'�����Rr�o7f�
�uc��{��
3���2���B=[s���b/�f���?%N�B=[�P�
�l�B}��g�������{��2?�����R��J_V&���t��9�w�B=�H�b�P1R����o..�h��h��/�Dm����=�����@�d]�k��w��������xxN�Q7�R�g��uv�����WWd��]R��7��6gqy�P�'�

�d�����W�o����;��N�POP�j/����G�/�]�K���g���P�^
�p��������e2�
�@��P�
�5M�����{��3�~8��m�o2������$+��4�z�A���)��
�5M��mP��i��7���2��+*^ZX��>���*�����lsq����+�N:�.i���C��c�=�����]�#F���{q
v	��w_nnn"��g�}�����]����a��_~9��@�[�dI�z�rss�L�E***���H$��m[TT�� �]x���Db��Q)�>}������c�"�������3S��'O���2*�|��g��m��1e��B�M�6�vs��M$�[�N��v�����~���v/��B"�(((H�TZZ��/_���������N$�;w�������u����y���N;��K�T�;�W�XQ����p�}vv���g��y�D�U�V����Y�3?0��[�nkO��3gN����^�v�Db��)��'���'���`1v��D"1|�������.]����>��`W�r���
&���'WVVn��1�c��	��;����=@�r�<�H��u�D~~~�>}Z�n�[�h��[o�=4�%��?��!m���_�~~~�����|�����w�}�����{Y���^����{�,�w���q�`������[�����Z}��6mZ�:u�?�|��;z����|0��d�5k�\t�E{��w����>���^{-�e��_��SOm��M8-�1b���q�(��O:��#w�m�p0_s�5%%%q�(�,Y�d��a!��7>����j�#�B��_�������g�yfiii�#�6����������_�^�}�����o�{DYh��M����o���6mz�!�<���q�(�Z�*\!�k�.��
.3�Qz���{����Y����q��9![���o�v�iEEEq$�M�6�����{�,\!�3�����{ Y��s�I|M���t��1J�Z}
Y�re�a����+��j�*d�A�Q��������5�qe�;���n��!�yyyQ��;���W�=���;�q�!�999���|�q�UTT�=��1k��f��Eg���!��d������
�p2�_|q�#�6���C�M^W��x����m>���n��%��_��q�+�����-[V�p��x��g�W��F��r}����)6l���u�p�8�����k����������gq�%k�����jAj�5��;�yn���Z}�9��Ssss6l�V_sZ�j�j�;������q�=��#��G����{��R���_�sg�������;��V_z��=��3DN?�����=�Rz�Yg�]�6���4iR�z�B��{��{hYb����T���w������|������M�>=''g���~������E�����T�	�����K�,	��z���G�m��_�����$:���^�?~t~f�����D8n��q�*��/~.-f����{���-Z���=�,}���>��s������_]W�7.���-���J��<�����$����c�9&y��Z}��={vH�UW]��C��r��7���v�mj�5��c�m��M�j������l���k���?���d0��+((�^�`A�c�~�a^^^���7l�������^��McX6	��p����U�w�uW<8�Qe�K/�4�3d5��d�n�����F��Q��Y��A�}��g���q�%k]r�%�\�����j��?�q���g\��2�z��d$�]�t	�{��7��e�'�|2$�k��UnS�L�ne�q`�w��w�N��zkTR��	C��}����_������[�p�	���Z}�*,,��~��-_�\���<��sQ����^R��!W\qEH�{������w���z*���?�iJ���n
�����2�,�7���?���?�����2����[��u��[��j����i���
�kTY�����I)o���+#G�<��#�
�����5����_D�iU�����!C�<����;�i��(�!�W^ye���
&L������c����kV�X���@III�&M������CVC�

�X6y��WC2?�����i�B�����eTY�����|���S�����@U?��O����&+Bj�;������o���V_C>���h��p$����N�:�C:,l�V�����:�l�j����C�����r�������L�8�^�_�n�OFvL8o���+���m��w�y��A��Yz��Ieee��0�+���?�0%~���0��k�=��c��^�����������}/%��������KF���_��.������e��a�}�	y��iS2r��W�L��/��2�A�j��-9���W2�~���WP#999!�����x ������}�����WMr�&M<�t��|�v��1}�n����Y��)������s�9'%���o���'����L�6mB2�gx�������^�����S�N��Z}M��@>��s�U�������?�q���]����a���C:���j��2�e��o��F�c����mN��r�Z}YY������{���<�^�-
)���+�����O?�������k�	&�L����j�g��e���rrr��#�#x���;�w���C������g�y&z^d2�����B�5j�������Qb�%�~\�<�8k��b��/D���rKX���[8����_=��W�^U��T_�$Gr^^^����N:)���SN	g���zj��!��|�e��;��+�E6�i�_|��}�z���;v����M���O>�d�C��>����d.�R6���~��7�eTY����I>���S�k��	�p��eTY&???$3�:1z���������u�HK����t�������~�����t+V����C��6���f���&k����������w�Y`����T\^^�&��Q�O<��p��;������q���{l2���G7��?>���^���~T�<��3�o���?�c������^{����i�����;///a��u�}�Ee��n�-����>�`�&Mv�}��S���<�3&���8qb����F����e�p�
����W]uU�p��f�
9�z�T��u���;7���J��~{���������Y�>}�T����3'SnWf��r�)!��]w]X�����D��d�$�U?1a��K�=��#$0z\�/��p1\��Gt�E���n��Y�&���V�|�\�K���{.e���������K�EE�V�>�����?�0�A;��Q����,�w�_�vq)��m��/^���e�������6j���;&d�j�r���7�\��]�[�����.	�����k���8����B>�&3J{��������W�^�[�����k�$��G?�kTY��;��n�n�������(�S�N��'z���������a��E	o��o+4k�,�y��T�����Y�v���k;w�%y����.�:����$�S�a�fZ�VXX]<�u�]���>� ������o�����v����C����x��pi��B����G���o~����s���C��8���S:��|����
7��k�g�y&}f� ���v��o�>�����+��z��K�,I	��;7�_|qJ|���Z�X�l��7����&��%��?�8#�j�-���z�����o����b�����j�����3cX��b�>\������`��U���Z�vm�?Wh��I��	���I}����i��E������X����.���D��7E3�$���l����_~y��!�����CCV�?���>!R=y���/;�w�}�����������4ir�M7�t(..�}��C�-Z�k����k���G��zh��29o���>!�m���e�Y����������v��m�O�N�B�9s�dxlY��s��>o:��3�k��������������i��r���0�1�����>��q����.���]w�5|��3�8#\o�������_����7z��C�~�����_����m#���sH��7�X5�x���}�{�d���
,���KN9�����z�_6?��C����UW]��y��� k�Sh�C��#�VU�4h�����&Y�������Z}���p!�t��c�����Z}t�]'�'y����py���0���7����%E5O��WM/����U��'�x����S�-K�j~��{o��3�<��J�~������%]5��j���u�n�#����S�L��C���x{���B&�����)���&7emM�/�.����������C������e�/��2\*lmk4@���6l���a��A���Y�jr���#�<��������\Hr��}��'��\]������w�������p���M�FI��/~��!�j��-l��y�R��;d�����-v�������7z��������{2�����}����U?{���!�_��_o�SVVv�E%�a���M��E���)�S+
A��G���;���Z}���U��!�	��S��_M�Z}��i'��y����UA�7��U�Z}�8'o[3m������:�$���Byyy�J�*�W6��o����>�?!����.���Z��&w����\��P-6o��b������V��M��y��A5<������Y�f�L^x��������u��\��X�m��[8�C�{����g�}��Q���;����v]���qnnn�Yw����'�50�,N�F[{0S�}�?����R��?|{��g������vO<�D�:u��������6\6DI~���S�����*�Ce�������py�����g����H�6��$AP��`�FA��F���kX�5�����iE�u���E]u"+APQ$�wu�:�M�{������c�Lu�{�{)��z������b��
Zx��Bn��	�,P�!C��[��O�>d�N�6Mf�0E]z6�_�������+Wq���3�S�@��D
{��
)��1,+���K2fnn.�u~PX�����#HY //Tny����^=��
x�����^�*U`�����W����@�G�J��z�8yS����!E0%+�'�:�~o��c���=eN���uk;;;	��p���
y��
H)H7h��KOC��{�x���Vq�������j�*h�4i��b7��b��M�L777��YPP��[7h?~��:#1�&od�=d�f���o��/��,(����tW�<�����]�t!}��C�"����8y�dC��w'�S���|�T�l\��u+}�$##����O�8�c������$Y�WN�*W�\��e����sSSS|6-��?B�����g������W�������	���g��[� ������A�*6LK�I+�7o��G�-B����
X�egg������C��5kd�����^�z�3��Rv8v��%~�oX2q�DH���s��-
2`�F��_�|��oq�����X_�R����DU�n�e�	�2Qi�Q'� 3gi�Q{�(*>�2lee������;�/�U�V(�
`�������Z�G����@��'O:v�-S�NU�"�������/��z�����/^�Y���������{���*>�[�W��@jX[[2d��	nnn�����B15j�h��1)?�����-Q�V�Zc��=z49��B1�����kW�C�$���%2t'M���CCC]]]|l���^��R������<�4!!~��O\�������1##C[[[^Q��;w�O�����g?����w����o_K�Y�+V,BSA���u��aN�B��=p�Y��L�8��=W�^�\��W������p���@�������`�.�r���7o���K�������.���
�n5j� ����.����#�5������^A�\�\���g����4y#c��dSSSt�J�<�������L2�r�J��-�y=ztNN���-�{�<y2)?������{HH������
x�Yt��ru��I�C�dv�����3���h�a��o�"�S�N�(P�������������r�|
�u vvv��c�������'Q����������$�/_�}�6��HDD�3�.=bbb Km���h'u O�>
*}����O�2�zzz������)� e�hkk����\���S��sb��������c�t����W/����[Y��)4N�8spp���y�����0�HII�'*
�� ��{]z�`����!���V���;v���5�=<<����G!��������]�v566611�����7Y�i�v��q����666#F���`ZA>�������c��A�_�~�K��&**
R�s�������/*�����w���.�3S6,\��J��a�������aaa7n�����l��U+������pS���g����tXZZ:t�v U�p�����|��RFF����3�>|�pH5If�:uh����L��]�q�D��__�}���+V���/=a�s���[r500�4�)� e�Q�F�?�%K����t���?H��k�X�$88�F�(��y����������������p�������0������h2\�
W�@���P+���7�}���i����G�s��]###����W�pb��-�d����W��g��I�m;��8rt��������q�����/^$}��[�.={4h�Z�bmy��-y����|���#F� ������sRr��lx��y�q��-�����5j�3fL��=a���DRbcc�W��#H�t�����������F-��;wT�����^AL2W�M����X1�����+��7'o�
���� #\����V��
Pb���'77���3�^}~~>��i�.]���#��������!��[�W��X	`�6l��9\���U|����I���P�N�m��m��c�����u�F9��J��.]�|���4&&&V�RE��\o�����]�v	�=z���������c���T�����FZN�8�.=��YV�\	�0d���d|}}!��w�:����Ovvvzzz��=:����[���svv��+�Y��V�j�V�N�xF�W_�V-6��#%"���>}����D�jD9dz��l������81����^^^�������mmm�ybb"��i
��CCC���%�<x��a�52MAbC����y�f�n�G���� XG��
���o�:���������*U����#$$�<�:Mf��A���� ��XP�y��P+�
j���$����xrX!zR�^==�R^=q��k�N���5A��?�\�@4�-d�,t �����!�:A~�=
���E��d&L���7�Jaaa��
!����:�q������[Y���nP+x��P+x'oJ������p%~H��1c��� �������\����N,�,�����Y�Fb7,�^����LW��ZA��[�\9|"������	��g���
I�PZ+�>��a�UE� ��!S�p� �aaa,��fddT�P����������r���...XR}�z� t b��V� ��
@�P���O3�J+�B���M9rss���j����3I�zt�p��=��^R�]z��cI�o���o�W�.�J�E��+���H��0)�V��y���P�\�7n�00M�4ZA�z����.�s���Ra`������kkk��!�����_A���,��
6@�^�z�;��L��=!�7n:�$��DC�XDW�@A��
u�Z�aaa��n��)K���p����e��)����xr���
(((pqq�,)g����o���Hbb������
����/_�4i�]���yyy!!!�������}{��n���Z�=|�0�|�������������E�Zq���;w���v��mll����o�"H���
n���8%����;��+����C��u���+WxOc`����	_�|	w�
*�s�N�����P�m���!���V� +Lwi)i�
uSXXXb�Q+�r��]KKKH{��B	8iN��#==����|��iii�~H����.����C�<<<���G�u���/����@N��u���/�ZA�}SSS'''2����R�IJ���V��%%"����[!\�	�A8iE\\���9`�����V%��� e��o�:::��7��np�466.e�2W�-<<:7h�����7o��������y����7���T��?��~2~�x^�(Xj�f��A��9�K\�W�@A����_---[�j��������U����?��Z�4p���k�N���J���G���Z��7�X�r%�m��a��.=W|}}!]{��e�t�9���';;;}}}�,�.=W�k���E��7@�
�.]�{���^+222���K�\�V��G�������=����E�@1>|�C���8�;������999�{�X�O��
W����+M�2��y����6m�����]���fqqq��1����������aW�@A���i� c�7655ecA�V(��C� �5j�x������J���G��
W�(���R�����Y�������wCt�����S��U�\9;;�M���?����K������������������gW��u�������������4�Z����7n����&�U+@��]����k�F� ��F~~>,�z���i6-�.	�i�p����q8�oO�<�������x����A��3����<��Z�j�2a�����qjS������!���'8i
�b���~����C0�W[[t���j���m����������Z���z�
��D+p��G��<{zz��Ill����H&L�I�5k�������s����T�x�"�����K�	%��
W�@���V R�������w�
����d��:~�xhh�Z�$���f������X�o,���d���[�jU�W���]K�#5pJ��xf:K�����d�sp-�ZfQN+P���_?���������$���E��#�\A�P�BHH���=���Vp������I�z��E3��B*��"��)����9,,L�@4���+++CC���D�c�X�^�
�������@�X4�
u�Z���(&--�V�Z �*U�����G�x����%���
6f��*U����y\�t�G��](������^�v-�����G��Z�nP+�Arrr��������k��}��!333N���������CnMLL`H�y�F��4
X;�kkk������A���zD�������_�D�`���0����#t �yx,t j�V�j� �IOO�_�>Y�<xP�p4������Y�>����[`` �o*���#��'���~�^��@�P�<p��u����bbb�S�����d��=Z�p4
��j�244d�1�������W�*P+a��Q��E�	�������%t,���/
���333��EcA�P7�<�Z� H�|���T��������Gs���3d�����[�n�t^$"�
6@;u���]�^��@�P����������Wg��E�M}6�x��v�:�a��U��H���u�������Z!o���$���������e����s0�5j��'W�9��&M:��BiP+~(P+�q���d���o+VdyfR"����R��n.[��8c��E�Mi.]�ddd�������{��@a��*h��@�P��&99�f���F6���7
S�Hk��utt���/`l�D�n� �g�������G�z<RAiP+d���a����-Z�`�x�����s�N�FU�������-����O��EcA�P������_��V��
A(�=�����Ax���G�AF���rH�����K��o�����S���Q�F%%%
<�|��X-�= c��!�@1���cbb�%�
��Z�%�o��5����M�@:��9#`��B�V�W�r��={���, Z����/S+
j�P���B�!�TC�|��������4O�<������������+�����(���B���V(��?��i��Z����Ki�\OOOX�������S��o�%  ��5�	�����>������1�����/`������NNN������m���WGG��[@�P-��P��Fpwwg*	����z�r��H���)=�������O@�4i��XW�
�������s��)�v���(�J����������z�C�i���;6�!--�����z�����������oXz��F�Z�&�X��Vp�A�<z��n���O�<!-�?��Y>_�r�4���B^�|I\����K_MMM���=x�`��u��@D1���s����i��~y^���������+7t�P��	������I���'O������r��/&��*�B��
y����~��,������Z�^�
)((puu�d��N�)�<��w)��@(�O~���0b���*�I�������g��m�ghh(?�i\�z��U�P����9�@�`�fggY�Ncc���_+�	���/R��4���B}p]��Vp�A�����zzz��?�-��'k������S
wpp��B��.��m�6bY���oO�>������=�-���mmm�&H/���al�+{�X�t)�q�����]�vA������t��Z�4��F�V�������3�����?|���@��t�������]�-$j��zfz��C�`��s�LMM�V����[��^B�P!]�v577g��F��������/_xL3���o��:�������H���I200`��g��������QcA�P+\�z�
��V R@��F��m[�"�����7o������������\w��Ka�]�J�
���4��Qc��Q�Hwr���N��____���L���Z��
(Q+�o{8i������o�"FA��S�N�ZXu��I!�_�~���u<��=���������>|���Q�3f���g����o��Y}��e���#G�/����������z��1v�X~��F��2'�III��n�'?&$$�4�#cj��~��{��B���X��\xyy���.=�<xp��9�'��=%��7oY�U�P�|��qp4<**J������[�f������l��Y__�z�bmm
Y������[�n�t����A��6Z��[�A�P%�?s�,����o��S�Nuvv����-6rq��o�����4yI�z�#�����/��w��I�-���v����2�l�����d����u��Ub7���7�����c���x�Bmaj��fks��177gj��B���'--�
=�033�l)|������>|��5�
�	Z��,������+k�SS�c��	�(�M��������*&l��]����jC�����������7Xj��F�)D����gX�����������3��Z���z��E����7�G�2�z�
%�q���������'t8Ejjj�j�`�*?y�d��n3.
���}�6�LN�NLL�������'�
aj��������Vq��W�^�y�f��M*T`_�	j� ,�E���4Z<�����[�n2+����=�v���-f�������������5k������e��c����j��%��Y�W�d��#��-�������a���woz���H��2�X�i�:����A�P7JhErrr@@�}��
�a_�4����f������T�dgg�>}���k�F�
		��,��G�PZA�N�:X�_����z��f�������^}���W�
��e�S+�j��+�N��lLJJ"�����Z� �b���� ��]��&���7�����+���0��v�?������^����K�M�6It���!%3
Ho��-!��vtfff�J�H���7����u��"d�Z�nP+�j�p*��p���K���d��<�w���}dz�Hi�z�)R"III�OWWW�K�o�&G$c�K��	 �5��S+�������;���������W_zP+)�~���������K�,!��F�b.��yS�Z5��a�M�(Q�a��;���u7j��,�aq
�n��)���[�&���/����HR�&�o��������;w��#G����A�P+����O��G����###Ho�&M`AMJIlH&�W�47o�2d�;i;�o��	�tvv�y����D�!�X�[irss�v������+*�e�`P�F��Z�����|���J_JHH033#^=���4��(&--�N�:dn&����(��={bccw��Y�jU��G�
�x�������p��-!��5::�����)]H��o~~~B+JH"���������amm�b������'O����'O*f��Z�>P+�
j�`����O�G�oH&������S���Z�jX��%��}:t�X_L�:��B�M�|���<'�t����������qc���KJ������nff���s9C�<��ysH���@��-#++�;w�����Z� �k���o�>y/������;c�
��=+T�b����y������@����T��u�����a�X�@�`7w�\�[J�o�o��O��GG�1D��Z�P+x��g���:������;��w��E�|�B����T�W�g�|��% ������A�EDD�9s�o��DZ�nM����R��Y�zu����;���_�re���/��Hy�������{��o���d���uK�x�j���L��}��7oJ_�i���	�Z,]����D
L!.]�D�P+Qy�FAQ,�����O�>�z�Z�r%�bL`F�t���i������_$V����fff���0t%�+�����{�������<���o��iX^�=�:��})���BXP+���V`��� S+���C����Cll,�R�^=�XP@.\�l$'�����{�62�7|fZ^�~M\h����O�$�n������-�K��U�V����I�h�Xy�����O�2��@��Z�?����Z��*~�Qz�B\JJJ
$<1r��E�/��S'Pc��Z� �H:th��9{���72<�Bi�����.��q�Fccc"�}���O��������'l������{����O�+=W�\Y�`�`�����/_�H4FFF:88Yh��!�k�Z�4���Z�B8i�W�Zq��usss����?A������T�^>��{��YZZB�cbb$����L��HJJ�����vV�f��}�FEE��K�.����`��rrr`
��C��% D`JFd�c��_�~%W��o'P+�
���������0��o�>�5(55�j��Z���%�<b�###�����:::���dd����*j� �
P	2���z�*�$�����E)V@VV,���W�W�j�*������$����tJ����#99�}������;�����+���7�A������X�d	�$�KLL�+���c%���~�:��IecP�A��?���Z�3��E	�����!O+@l��L��:!���[�^���i�������3���?DJ����I���C����cd8��������
�dD��ECvv�������������C�@
 ����C�^��V������G�����Y3rV/d��0��?���o��{7i�$h��
��Y�%g����q�[���DEE����/_~��{��	

��@�z[[���/GFFZXX����D+
`�K���'$$������	����������Cg�L�_��\Y�����&L� ���o�7Rc����7oj��Y�����o���+%�M���y�f��5l��I�&B���^����������*U"�a�6j�H��A�`ONN�t#j��A�P9�i�g��UZ�h���g�����93s�'�b���Y�|�v�222\\\`"-\�brhhhrA*�����G{��7'zr��;;;�����S��]L����1=��7o���)��#""
V��V��>@b���CBB`��mn��-���������S�a�&����XY�FFF��_��&��G�@���-����-�i�z,,,�� 2�������lll���h���82%fz�X��
0O�R����'��7n�055�^��L������������Cq^������M���Nq�A��Q���b$���s�|��L;|���l�e�o�l /7��1���Z�nP+��rZ�����^+�_�U�V2�zH5� S��u���������
I��C���bsi]]]a�-��...����d��$o<1��y���]�_�}HH�@!���������QC��ay^}�j�P+�Z�3����O3I�M�y70�X�~=�naa(�I7"���LP];;�W�^1�x��R���?-TH�8q���)S�-[F�n���w/W�\�����qyP�g������5j�D�^=R"d������aR�fM��`��!���m����ME�;����3k����h�Sh�jX��M�x�T|P�������30������gi�
)��������V��
��Z�&8i�b�)2��]�v-Sr���_���d��NMM��:;)�+W�h��jW��6l���S������(`���666��������J�]$���!�{�"��O`p5j����k�.�K�JO���������P�*U*V�(]�T�W�Z� e
�Vd'''f#��W���0m���,�*��<����q��#GJw@�^	���{���^=������������?�����!6((�^��L-��T�P��BB�	��)��5k����
��Z�&8iz��!33�VY����/+}��&��}��=�7n�������+n6o�y[�|9�*������}��p1���i���e����A�����8�[�N�h��K�����a)��7���H����2�zA��������w���s�T�<<<f������U|����%������=*��+z��C|�������*��!�)S��ws��yx�	���Y��o��^=��V��
5�^=o�=��Z�d��/_V�T	�!� [�
�.]J$�,���H�.]�����N�������(y��
,C`����_�~dT�^�Z�3��g�������7��VVV�=�v���o``-��)V���#�����>}Z�x19%�g�����=�W�"H���2�������>���|��qr5//�V�Z�/l���:?��9m�^=V�����������{7�H����VqY��� �v�����c�a�5���i0�H
����BN(���V(j�V�	����X�y�&�2��&&&��@�5:w�\�Z5���M�O�>	�xIII����T_�pAf��k��A#���A���G��dff���S����n�:��111����w��
�!����3G^����}P���KFF$���+����czzz���O�^}�.]�.=��e`)�5�����cv���#���d�
��_%���������7N(�����`��f����v��I``���W�aCx$W@�34��"���h���'o\����V��
u�Z�\���
b���o�>XXt���rrr���keeE�����YJ3|�pH#��)]�~�����a���������~���m�����J\�6m���
j�������r�H��< ���
�&i�7o�X;���yzz�b���K�?q���A��������_��s��������(m ?z�������1@�s��IX5�|X__���������D�Q�^=f�=2�"##���������l'''�!����������24h�&l��D�
QN�j{`
q���K�.1W��*��gP+���K,�+*����"�2��#++����������I#�1����(����jggW�bE�/� pSu�p������R�J�����B�^%�V��Z�����^��w������?�����I� o��wg6N�<Y��������W��^�~�����?@l��y��RR��������xR�,X��<������:99�{��^E�^p�����999]�t����m�-H�nddI�2L�����7�U���'�
)X���l�$�����(��Z����Z�rv��M��`Z=
�7Daaa���/�%11��O�U�������C���IPPPVV,C������A�Ad�� �.]*��w
4 y>u������/
����V|���Y� #�������8k�,���K�.�|���s��������<O�2E�W��#Hd�j��Z�u�z��e``����RRR��`�"���jgg���{��a�b������|���xV��� ��zuP�W?r�H�,�����������H�3q�DA#������666�533S��D�MM(��P+�������?k��>p���+�gcc���/K�D�P�
A�Pyyy�i##������W�������4i��b
��6p��)P]���L�~�����&L		i����QC�Y�f������G����8�����+������
j�����_Q�3��
���V|�����"���H�
�P�x��-��SXXH������I��z�'&#��������������_�����U�T���@��,�������,>`���������+��^=`�N�>�}~x�Xk�%�����;�5�x,\�P��E���!o������������1c�p��<�
��#F� ����m�����Q+Jj�
A�
��
6��)��4���V�Z�{�������������C�H���BXeH�o�k��-[������"�����5��
$,���hSS�y����W���{�������i����Q+��Z�r��
&r~~~�++++___�A�E�V�����S�S�N�^=��e��t��	ggg|SA���/e���XV��Mf�oaaa�*��5�(^Q�>H����� �����a�������666l�e��{��I��(��G��^+bcc������1x��{��	�X�I�����4���V�s��Yl�I�V������u�����l\�r%�*��G�(
�*��V��c���/^� _Q+J��]�������gf������z�{��1FQ���?~<o�����K��8q�����)+��];��D�����Z�A�P��C�VDEE�W�8y�x���A5j�@6�A�A�����^���������V��%''�{���*U�"|��Y�b�6�dee�3�Iz����`�fnn.oJ�l�2mmm�\���{��Bl�KkE�o���MBCCi��m�@�A1HuScc�K�.�K�HZiP+T������c����mD�(
�j�������m�����{�qB1f�:���m��u+�(^1A�7��M�4IfU1��� **���T�[�t�^=��
��Z�&�iL����)k8;;�&PA �7�^���x�B������[a�~��:V�DGG�d>y��������d2ON����r���g|q�=��z��yzz~����S�~��E���	�V�����+V���s�&M �7n���n����#<E)~�o��������7�y���Q� u����r��G����T�^���_�x���;fX1���X+�Kogg'Qt�B9rss!o0��aaLO�$s<�D�8���`
��C�}�S��y�B��V�	��Q����]�����y����
}}}��F8q��p�����\!�a5`���c�����5d�-<Q�#��z�[Q�WOK�#�@�P-+V��*.�M��h��������A2+����[O��<�M�VG�����`������?u�|~�����d�fr���L��<y�����
���
\zj�r899AV������v���hB���O�>���{��Y�Qkkk�x�"����Y�v ��m��������^���/W��V��
5��W���#H�}�L�g���~��Y�m���������U6=XQ���O
@]MLL�U�F�4ONN677��%��WO������=^q#����c��
Q�
�����k�Xe�8w�i��zxx@�����G�$~5�|��y�f��72�7�
5�g����p�344d�F�p�������k[�l	��)#�LP+�D�V�����yy.=�4g������={�0�^���@;�D	��fmmM���f���LmA���W���*
j�V�	%�z��� HY�����\�vMziL��J�%0|�p���/�q3��������������?4�i���@E����C�5jD����w����[��Q���'�v�
Uq��2z{���lOJJ"e�---��dB\\���4�\��`�
�a??�z����U�d����V�yZ���SHx��m��ptt�1:M��k������W7o�9r��!C����������5jXYY��<�@��������h�"�-id�)���BJ������@��4�V��
>����}�V�H���Dr$�����UjhgZm�?����9s&������t���@KV�1XGk�g:x���k����kkkC��]H����v��r��OH��;�����z�4�b���$��v�b^E�P	��:u����B~��w����xGGG�'���CPPP``�������b����!�p��e]XXX�����7�4(����H��c��������E�#1�<�Z����k�����+�J�?}�t�,]����4�W�^��l(W�^%���o�p���\�~�W�^...����D��Q+��Z�?��zA�YYY�,HX�5044d��:{�,4������E�'�v��
�-��S#
���1b��/HQzi��I�"S`a�f���.�-�����z��/�h�S���&��5k��Z�*-Zt�����`��L�H��*�n�o���lB�yonn.m��^����S���0�4���.��w��X��Z�VP+����_�w�������+��@.f��	������^����W�^t`��![�lMX�`��oj�D�>44T��DylJ�>���Z��BQ�W?r�H�CD.\���s����b}����*���<���w���O*�HT�@�SPP ��/*�%K�@z����XfOff������=�|��z,����Z�G��777w��Y$��d�"�
U#��={�v�Z�+�B��p��kC�?fkff��[�a���/'��*$E��o�/�+
j�:@�P+0a���3�q��A������W�������/_f�LHHh���������[�����_�~��={�(���K`�������w�r����q���H����'S�K0��V��
�*��t�R��u�.=��A|||��G�R���ggg���������u��$A�W�(��;w �0s�y��Dc��E�^i`���O?1H�!���V�i�(R��!�Af�2�n������&�����K�h�l�2�i����z�����{���D#j��A�P+k������o����/����W?x�`"��Og���(���0P[�j��'���@�	��`�����o��!���o�`�=���:::�4H��G�P�
�^+���_���>}����_��{�2�ez�E��N�����)��������������%�WO����mKKK(Xqy�<�����W!�...d�6j�(�]��b`�����u��a��I\����VpE�V���.]�t��5!"��������N=z4�
ww����c;\�"==���sx'{��?b�r����#�?P+Tj����������%��G�d���W�����
<�+7o��dJ2����c��%�!���7��X���3���������Ky��r8��[�hB����V0�z�
�A�P!,�

522��j��q^�~��S'X����8;;O�0A��<�a���g����*U�����m�!�d��s���7O[[{����,j�����K�|��f��j�����A|��=�������08���W�~}�>2�7�=%jE#�}����m���U�F��
X�,X�@��|����������Bb�'��
HHH ��ZZZ�(%��+�}P+Tj��HJJ��U�R��z�k�.�0n?}���Y3���9s.���_�(�D������%�={��Z��������722����
���bJ��A\z��A�����6d�������V!�����[�nzz:L<��p�������o�Ua���A��65�BCCutt��6�P+�J[�zu-0������^}i���������������Po�������d�����"}�DX9'&��1c������A�g��]�t)��������i����/��7�a�����I���ceH��������������OW�O����3z�h|��%�<������d``	�����$6P+Tj����_��g��kxx���N�N��������O��������w�����[�j��������#G���f����9s���U��������
V�(��������(777�5�dbLj�'%%U�T�j��)))E��3|&Z���3j�7K��{�2]zj��M&L���c���_��2X[[��8;;K��^����A����BWWWccc�&�|��l�������n��F����������7���os&�z�j2U3f�D}�.]�4m���0����G���gee��s�A�dGGGKw��[DD���NZ�;w��^^^���dgg�>}z�����_���I��f��I��V�Z#_8�j�g����&i��<i��B	P+xf����.����+V�+�A...:t �{�����)H�����W/��60�����������W/\��o��F��6q�Dy.=ko*���7o�L>�k�N__������������ihh��5R"��!O+���oy.=�A� ����?>�����*U�����[W�W�c,A���W�B>@[`
���faa��E���������@�d`�F��S�N%������eQ��9s&��^�Z�����	����WXA��B���2�/X���Ej����g����
gggRH8v���5j\�r�4?~����k����,JP+�MNN����N,�X�\�N�:���N�V�Z��	I��}��1�7o~�����7&&���
��q��d���y�G�Z��6�O���M$�����Y����������{������^�zu<u����
2m1b�q�������uDD����
~P����5k����#R�����oHHH��-o�������G��w�^H���7�J�111�~���/_���Wa�����A�a�M����Ab!�m��Y�x��Q�`�@�	:�g��e���fxxx������m��?a�k���i����W�\�l���C8�Z�V.\	trr�={���S�����M#n����-,,H#��\]]�^���d�c
��@��XZZ���#G�������g��a������7��r�B����N�4	�n���0\%�e����|^�z��dgg���:t��HE�r�v�JF)�kA/�n�4�\���'�X���u��	�����}�U���Y_H�o2�{#�Q�D�%����CN6�V�j� ,9q��XYH?�C�^���{2��c���X�����������9���R�Jo��6`1y�dH��%Kh������c��������(��P�\�A�a�������08��'q�7�Z�>N�<	I��HNNi��������&�����?�}�������������
*T�^���W�u�������g��p�#�Y:::�&{P+�Maaa�.]��3GGGf��w�NL!�2c�H>f�����#G�433���`T<��	�����)S�������������Q�re-��E"�)Q+��[�u���	i�93h��]�
Y��V��
A8�}�vR�i���/��W�BBBB��m�)]�x1��Bcc�i��������)2^�~�����];f��{�,--a!�r4���9����_������!�Z��S���J\E�M��V�	WWW��?������
�M�V:�����={7!+jo�����������'p+���#����;,�mll �x�&'P+�
�{���t��i�����=������C�q���g<R	`)����L�
���hmmmX�������{���A{�?�l�%s����S	%j��G��c��������>fEX�Z�>P+Q��;w�^z�[���
�a�\\\����'��!������W�����8��H�K���'Dt����w���3���L����DJ	j�
INN��������j�J@���_��I+�5j��~yu}y�V�@���}}}����4777	�m���m����xJoiP���[��] ,y��	����]�Rzz���3�o���V�<y��Y�J��={&P��j��A�@D9�W����K_����Y�&������^�z��V�^}���)))����K�L����C����)D��V�����@�U������}��� �b�(��&s�F�7����bP+xR��$K;o����G��%�p1j��F����V�jkk��wo�s�Z�n
�>{�,mIMM���=v�����
����(L���.��?~������s����x�%aaa0��3g���2����,!��>|�M��0��#�a�������Xjdx���M�6���5!�
����'GDD0�Q+Tj� J�����C����$��Q$N��^�:4�D�|MKKspph���@���6$�r���p����������jQ���V���O�}�F6\�P��ttt�U�&\��j��x��5�pE����1c}�q�����R�r���cllLOiA��Z�&


�/_�����C��m�2��d�o'���7nL�BWWw��
��k����b\]]����
X���B �[�l����
�$��"
@�������3��
bN�P+Tj� �A�W�����7VVV����������I1=H��5kH����)n������������o��!l�"����F��-u�u����8�U�b�
aj�������+��tvv�Vq�7���HP+T��������e��?~��9�J��O�>dY���C�-��];00�A��y���B.VP+TNAA���/����g�/F@��4$''�DB[[;  `��:t �^�|9���,�������,\�2ill,�����P�k//�j�������'FP+xf�������y��m������O�W�ZQzP+)
����������dff�[!�}�v�8{�l�g�����@���gDDDBBm�'����J���wo��G���J	j�������sss�Lis��MZ���^D%�V��A�`)M[
i��A��j�'N�011�����S�Yd�V�@PP$m���g��7n���������0����A�# ��7���>z�(m�2e�L����;Z����]���`5�o����666�?���h�"������_�A���i��A�&O�L[@7`-���V�
�
AJ	������ciii������#���+q	�w��u�����������;g��e���Qz2����>�f������t'!��=w�\�����4�V�Z��D%0�7,��
��I+��?OV"�5b�rW�^522�Y�&:���B9���#""BCC+U�$=�W�\IF8];���@����o���{�"�B@�4i�������&%y!���7<��G��b��+*�����N���|��Ii��,��n����E�anV�J��������i��������_�~�+VP+�
,C������O����4A��G��
j� jb������������:u��/_���g����}���iS�����K$++�����2sE\w{{{2�puu���:o�<�hgg7e�X��k�N����������
g��A�P-Jh������cCC��C�Bg]]]��s��Z�����FX�>}`�'���I���6tx#�@����7��w�h�� �8qB��FN[@�3f�H�����W�����-[��^�dIQ���������p�y��Z����_���g��U�Fv6���3��m�\�2H
��
~�d�5������\�r8v������srr�����Z� �Z��n8��.]�)���c0!!����~�:���'��:���3��-[�4������K�2���^=���G�&�D}�Vp�B�(���h���///|aA��Vp�T4%<z�H�C~~������V��'���Iwss�������C81~�x�$��������+V��-Z� �������������CCCGGG�	655500�����7���cQ�.��;2�&rX��=��A�����/(((*�9���k��$���O'���
������:d��Z� �������W/��s����fpu��M<�&Fh	&��

�������`�`gg'���)�����]�c����DaBG��V����w�^pp���i�!��X�z5��6m�0�R�����{��?6��Z�?������d3�YP�SQQQ?��9��������3�^
		��N�"�W*\�"V...��������S�NZ�����I��<��C��|�����7>~����H���b����Q�F���/^���Z��=��
A��6�
�������x/Q]SO�<y��y�Sykj��A�P-���f��^7n����R�=��SXX8l�02����'�����|������j��Y[[3K�DDD4m����;�f����,Dr������������p��R�Z��}^��O��6  �����?_�h��={�'{P+A~X��		�����0m���`n�BC���79r�t\S#"�B��V ��'L��t'�s��m����'.P+���o���2_�'��a����_��=�g���	�G���B�;v��l��e���.�l��Y�q�L�-::_�Q	�*'''g���}��:t��#G��;|655���g���	���'a	j� �����&������i����:`�!t�"���a�,�� \S#"�B��V ��[�n
*-���������BG'2P+��D������G%R._�L+�4���O����������>�����������p!�����C>�t�R$�y;u���?^�05�
+WWW�V������a<���C��k��OF�iff�����A�����b���>��S�6U��<x��W�����_�?<Q�
��Z�h0���VXYY�I��Z�?%�o�={fffV�B�l���]�vD���G������[�NHHHMM��������B�.JRRRttt@..\� ����k��q����a�V����������;vlHH��!C�)�������y�ooo����?��?�N�6M��E
j� ����

7n��E�8QP�*q�tXS�������D�V��
��@����G?~��1'@��Q+������333��e��=0 O���-�����7�7NHl'>|8���������_�6l�7F
���l��M��w[�jU�����JJJ�\�2S+Z�jE+�#%�Z� ":�������I��
���M��=�������c�^��AD
j�r�V e��O�>]�XD��G�������@4h@��V��oJ�������y��E�"##���!�m��%�XDEE5l���w��q�������5j�,4n����K�2_�fM2h��������
�X�"*�rP+��?~5jT���%.%''��U�jccC
��z�
��0�
7n��rp�4�����7�ppp&S�
AQ��W,X@j����������{G����TP+��Z��Y�W?c��c���FFF�.X ������7o����C���
�hHKK�S�N�>}�5k��_Iw�qN�q2m���cYYY]�t������/fn-�������?nooO�"��A.������!�XVHM�V(,(z�����:|�p���^�zE�c���6���1��G(�/���~c��DDD���($��Q+AD�o�9x��V�17/_�,*��%$$H��55���V��)��W����xSSSXV��������>��SXX��s���d�<���'��3g�Rn�q��1�<��^���W!�M�4�y����Ia`��u�Crrr�f���O����������|P+�������H��~��2��
��dz�,"�}���j6����D�
lmm����/f��I�}��!^=j� �(`�og��:�XV888XYY��
�55���V��A�^��Y�����e�������F�@~|�\�bjjJ�g���/_H4�J����4�����_�N���l�t`���^}aa!hE��-����T�2l�0�������k��&�9�z���<�&:�k����m�����G�hH���.��G�@����{��������<np����:�-����3YS{{{�y7���ZQ"�BX�f
�
>,t ?.VVV
:��w�|@�@~|������a�O�>IwpuuE��%L������Z���e�D��'Jx�"
����Woaa!Q��0n�84�Y�������9s����W��Kx�� �(������������[pw����y5''�{���*U���#-g������"O�V(�A(���B��CcdddnnN�@�e��ikk��z�������i#��'&&���999�[!,�^���C���e�X�^="R�W_�r���8�%Xh��������H�P�^__�O�>����t��AQs����|��o_FF|���#��ttt���/��/_��4�}W�\�5VA��A6DGG���|���|����4i"q�&�n��������(������[���������������x��Ea���d�oE��#������X�yr����q��y�F'2�W���|�^=� "^������]��| � ����,�_
2��9,Rv@�@�
���Z�
755m��YDo�������=���w��	&�/��
����O;v�hhhX�B��g�
���^���~ll��>����".�W899u���b������/:4����7l� ���qj� �����L;;;r�����o�'''���Cc�-����m��%�w��`P+aI�N��VT�V�V+((����F[[[��o��������7�,��������^������D	����f����y������={���^�:(�"}��4�����V1EAD������Z�q��s���������y�&�
IAN�EDPP+a����V�h���X&%%U�R�---O�:E�����������B�� ��z���������������#F�P�����������v� ?8���������������i�����}����-#������TzADt��y��k���c�� �:������:x���k����kkk�����7R�@�@�
�?����Z����������������C������@�	��'N6������x�b�'h�f
=6^=�����r��92� ����zl�zA������[pp�L����GM�6�b��Q�����ED(P+a����������^��Hd�`gg�pF��^={�l��U|����a��`����Df��
�z���{����B�
�w�~����;$NA�A�`��oE�K�%K���??<<\�����P+a�<�x�����kg������z6�{��T�f��?*��^=���W���M�������?
��W� �h)))G��t��D�6�� e���?�>}��������v�
A���
^=�h$�����C�M�w�MX�~�������)bx��
�1@������?~\�X~P���=����K���Y�&�4� ������I�&������k���hf��A��������kB� �P�������hE���CBB�WQ+!(�
�WO6��Y�f��u� jn����	�.]
��u�V�W�}���o�)S���>|�i:o�F���v��i���q�q�hE�~��uX�z����\XX8}��������AD�����������V�X>_�|����om���V�*fAa��y�o���������[�|9�j� l��z�NNN�M[[�s��B� o��s��JC_�=p��A���e�����p����!H�!--�����3����_���!==]�'���722������VQ�K��ViDd+`��A�( E�.@B�4�1�FqA4h���%!&� @��%DYET�B@�M(�;q�M���}y�������{�������y��9g^RY�~���*
��}��u����^����������n�-�z�xL�6-j����7|�r������tV��X�bE�:u���M��+��J����#5j����Z�|�\��8��?z��R�eE�*@:��������i���;w�l�������;t���{����rw�������g'�V���\�2���u�Vt���^���K��W�^=x��	&�<y2��q:t�P�Z����_t���?��|�����d���6+v��1|��g�y��:������CC�i��r��
6L�J1r��0^�\�w�}��W��D���;/z�H����P�^����ggg��G��g�}�"L=��%���g�0.<�[,�=Nd��OO����}�����s��_�xq4Ul�Y }��3'B���#�W��V�Z~~������d�-Y���#G5j����[�/,,���[���3fL��L�81��y��I/�S����+�q��������6���k���������P��sO8�=�����w�}7##�G��R��_����lvv��Q��{���/������b��!
Z�n]�n���f��M�6��k��?�]��s���N����n�w�@dpf��/�V����N�W��Wr�t�Mu��u���k��y���������_PPc�@����3///
�h
�����
���5k6e��/��r����k�q�h���j��Q���R�J�������:t8v�X4��K/eff��O���X 6?��c����~����G7i��N�:��m�fW�ZU�\�h���+�8~�x��������?�y�����^��t�^}���&R"�d���1�$����b��i_|q���)S�T�R�hVT�T������`���<yr�����������	�����v����W_���+�M�e!!�m��!����W��;1����ggg��3�K�.w�u�/��S�@�dpf�+�+V�(�W�[������������p'r����*�e������^��]�F���k�N�:
:t��1U
g���Ck��-ykNy��NpEg��y�E%�: U�_�>��[Q�"9++��BX!@�o����� +��v�^=@�z��������Np��u���o�K�.�^,=u�Tb��nh��}�q�:uj��u�wH��������
����o�D�dy�
����b���)q�UWM�4���F����?�<�J�8�!+J���^��&z��s\�=�u���999o��Vt���{��08h��h�^x��������������rss��>�������mF:v�����q���!=����X��MVe�`��b�H�v�mE��H����k�i���c��H���c�H����D��n��K�,Y�ti����c�pv^��pF��������-[��U���7z����_|1����5k�����u�!��]�633��+�������m��u��=J��={F���)_�|�Q��e�]V�\�����];�<�(�����u���9s���~����fee�X����K��G.���c���X6�de��D�>R�z��[��X6��p�{���}w����7�tSt��:uj48r��
*D���z��"!�<����
��6#F��b�_�~���y����n�:�'5�&d��������_�F�-[�$�|��(�����[���=W��O?�Q/��*+���w�-�ddd��|��'q�go��q+W�����>}z��'ND���+&�y��{�G}�q���W
�i����zx�����/9�x�&�����G/^��_D�eiBVe4v����F�J�����U�V��U�^�)�;�G.�e1;��8p�@���a��YQ�Q�F���/y�����gWn�������m��U�\9DA�$���W�����/P�~��G�&�< E�
�������'N�>�����K.	�b����gG{[�x�����o_�m��Z .��4��k��m������/�.��
HO#G���"\������]�v8`����/H�(�'�x"D�]w�u��7y;u�T�B���G�}����$$F�:u7nmo�Y@�8~�����Zl��b��.��]�6��)��W^���{�����=(;f�����Y����[���������{XL�0!1;k�����
��Z�j�Y�&�J�8�
���'�^}�r�f��]l������~VV��b)H�����K����;L}���/H)�(��~��J�*M�4)�������:�h��={��X�"di"������4iR���^��{���6 �$�o�'["+V��P�B��-c,H�(�����'������?�r���S��-Y��s���#F�h��Erk�'+�t�^}p�M7��7���>�������;>|8��T����j�j����W�~���+U�����i����R��"K�,�V��������������*�dggo��!����k��}��w�W2Y	E{��V,��5{����?wi@jI��rrr6l��A�{�����#�t&+���7W�Z�f���<���������(Z�n]PP8u�T�6m�H�z�&O�<c���.��b�������v yd���ggg��;7�r�����=���q��.Yi�O�>U�VM<����999!���~����l����x��B�
%w���d��������9s�.H]����a���H]����}�N�:��i�g�}�����K+V�b�S�N'O�#�w�4hP�v�z���f��8��!+����2J��{���kR���t�s������o��]�v�f�*y����333C,���k�/H���^=PF�o@Y�
H+.������x��GJ=f��������S�N%�< E�
(����u���]����7�x#�Z��%+ �|����+W��+V����Jp�����-[�$�< E�
(��W?p���R�+����C��~�-�B��&+ �,[�,j�]z��,y@�V�4�YeQXXw	�?��'�.���V���;��}������o����,Y�N����E�U�VE�?��C~~~ff��E��-H���D�-##�m��]�v����Y���y��.
H!���D�-77w���3g��]P���s'����k�9w9@��p���e!+����BV��������s'����Wo���q��.Y����~�q����R�������]��
endstream
endobj
8 0 obj
<</Type /XObject
/Subtype /Image
/Width 2019
/Height 1058
/ColorSpace [/ICCBased 7 0 R]
/BitsPerComponent 8
/Filter /FlateDecode
/Length 50495>> stream
x���{�U��(�����"j���2!$FS52U3��+&���t�E��Tr�T�h�wC����yH#��F��`&  ���A�y4��]�}���9����t��:E���o���:�~g�����j�����m����;vl����������������_l��pf���s���weee�(Q����(�\RR�0=J�@l���Q����^j�W�Z��qk��m�?[�|�����m���c93H��Y��sg�p���MMMc�� Q�g��C�p~��'{,g�z>+S�L����-k���1$��=zt��Q�..�+��O>���o.	��9rd���3f�>|x�~�z��=d��q�����|�A6����Z�j����92��W�^��g���������-t7�z��)S�������0�3w��������x*v��}-�y^�t��i��D��������`��a�?���%K���_�Uc���:�<yrJ��?U=��sQ��]�����7�n?t��SO}�����BG�-z����$�/�����������k�}���q�����������<�9������B�;v����,�555����=ztXx8f��������
���m���={F����g�6c��(�W�^��oO(//<xp~Bs��9|�p���[�n��au�����~��k.\��=:����'���/�P�I�+�7o��:t�I\�l��������O�W^y%}����I�&EUeee�t����w���w�0��%o��VAAA�����}���9rd��������>�l��i|���2L��	R~n8<���q"���6l���]�xq2�ZTT����O�6���Jf�y����:�7�x#��_�I�&M�>���$'��+W�L���_��
v����C�F�C�y�����{�������Oz��D���;������G8n��G}4������y���-DUs��Y�vm<���#F$�-,,���;�D���O������;R���
�o�>|����o���F�9rdJ���Oi������%;C
��O<1q��dy������3p:���3fL�9rd�3G����c��M��O�S�D6lX��$����={v0k���l��-N������������-_�<^���w�]�v����K/E�C���O�:u���q@EE�3�<#Zxr��5R�l�����`�����p����������3�63$�CIT5m�����9c����O>�3���(**
���/9r$����|��g��)S��t�n������$���C%����B�=������9Q����_q��e��%������+q������8k���#���$Q��! }%see����������W�����8I�������[��.R����7�-L�:5����_�������o�D���={2LH]:������������}EE��!C��$��I����9L��?4/J���|������ z�����$x�������"���_=�)--MVeN����
��k��5k��-,^����3��E����q��?��4�u���������k�����#G��]R�o��=n�����0��S����}��%��D}��E��B�+V������?g��.�����c����x#�d[�f�/�&6�]�$��g�y��f���?�Q�1K�,�cR���$�����TWWG1��gH����;����_�����:���b�\���>�`J*8�2���NYb����0qZVV�o�M=��sq�6})x���������D}�w�����q��e�2�U���~:�<}��7����g}W��:Q_�����_���������_�>�I���d�~��Q���B������3$���8����w�n��%C$����>����Y�&N���-|PSS�+>{����'�����o�����}���-���%�����6N9v|#�8��W^�<�Z���o�����&���'O�o�>�D}AAA]s����~��ukF��J&�3/zO~�������x���C�fh���=|�F�������u�q�����Zk��={�����3��s��8���<.4hPT��C�px�F�%%%��dz���u]~���8,\r��R�y���{���LkjjF����p��yo��v]���&Q?b���.������z�@�/���U�D}2��n��q�s�=�gH�E��&M��r$~'���sOp����~��G���_�"���zy����F�����"6���C��|0Y�L�<x�������xC�l��������-�ca&L��p��0��� �D}�;�������e�>�*E�����!Q��O��>B��i�2���\�_������O"���X~_YY��9��c5jT\\\�,o�D}iiitm������C�����?
H1d��09!&���'Q�as�c=�s�����J�WUUe���8��KNs���O�C�y���"7m���1bR���=z4n�����c����O�7@����f����[�n����:�r��3f���/==x���kX#�O�~���n-9���i�J�WWW����)�7o^�a���n���g���q]������1K�,9�����k����t$������_uuu��� 4�e�����7.9����~�a2��I���g6Er���kg3l}��o��������GG��Lg����2l��Z_x�w��8������\�C��ZH�v>]MMM��yJ���q��O������{��i����1#Y{�$��|��w��:)�������E������2�Y/��������7fy���k�$D��B?���Q�W�'�j��&� Q����F.]��^�KMM��I����������'Q��/d��?��Oq��U��������G����^�pvKnz�b�����7�����6mJ�*NVVV�D�.��H��=i���q��5k�U�:Qn-^���#�g.y������O�D���3���qd�M����/�3p�Jnz3i������f��	Q���C��+W��S��+bk�j���'���K;v�H����+na��9Z�Ga}��M��N�o��1����(������SVV6~���B]y�Hyyy���'Q��g��>������w������������N�0�a�����;�TUUe�8�������g������;w��{}���R.���8p`T��_�]�v��~h3��>=�\RRU�����w����U�V����}xNu�>���?%d����R��I1u��(l������'QL�6��=j��2�|M���V�^]���9?*������	g�-[��9��^z)=��^���6lH�M�I>p��7�|3��������c�����W���c����������<�7{h���_��RQQ����N�?����U�M��k��Yq�O>�d�:{��I����+���'Q��#���x���{��555��/((�b�����=v�D��\XX?$��K~���������[8�o
hH�Mo��S�v"!f��q�<=��g>��~����{��GG�gn#��/�u�W����W6p���{l���&L�7��?��z��-����D}�������)..N���A��D������8�L�4)����O�~��
���|��i��=���)������x�D}�~������p;�1�0 ������s8k������s��mu�m��9�&Mx��7��m������_�a$7n>|x�&L�P��:�4Q�z����1c�dyI]���?e���%�����=�r����������3z��������&�����P������,=p�Hnz��3�d�;wn�/]�n]z@ee��+JKK���_��raa��Q�f���z��l^�bV�Z���O�1"���W���;6�m��M.<���9s�D�<���Y^������{��I�&��������C��0��?����N�D���g��0����>}�D������~L�&Q��.7��y���=z���S4l���S����������d������D=4"�zhD���$��I�@#���F$Q@������������SO�T<xp��!_��W�;������;w7n\uuuz#3f����[�n��y�+��2??��O>I��m�����.���s����n�����>=,�~�.]z���_t�E��5k���]w��~����h���+r�KI�����k_�Z(o��y��]�t���I�p���|���*y�=�����������nh��e8�����s��d��5kZ�j����/|�[����c���#N��)S�D?1��n����m���-Z������<�)����&''�M�6���=z���]����+*��ys���C���c�����Pr�����G%�~�����
�����aUUU:t���eeeT�p����������f�o(l��i^^��3��������v��<x���"8E�.]���w�M7}���OI�����I�&��s��-[������!��K.����J:u�JJKK�a{��=���Cy���y��i�RV���;���������%=z�H�����>�������@�8x���W^��E�w�y'=Q?u��P��{�����/�������w�}7������)aw�ygr[����;�4(%l��
��e���2�,�
��kN�,Y�VRR�o�����^��M��Lz�>Z���W���mm&N�x�/���t��6f��Pu�wD����Z_�i���og���={���+**R������x��h��7��u���>V[���[n	%&LH���U�������#�������Z���7���h�"��[�.=�+_�J��?~��._�<�Z?=l���Q���Y�4���7QIz��k���d��������G���{oz��E�B���_�+++����;�#���]���7j�}���aq_��o�b2���������3fL\������kB���s�/4hP����7u�����-Y�$T�m�6���?J��������wU�'O���g�}6w�������
��6m�8
��-[�����k�h���I���V��pE}��=��Q_Y�����Z��Ft���:�w�y��7��D�����P2~���F~��_�����p<r��p��� =l��9��s�����>��p�v����/���j�����b��p|������+J�8p�����������R��'���\z����km��
��^{m8~���C�������)n���P��c�������c����C��~����������T]]������w���u�1��7���\rI�s���3��'�,�F��s"�&�3g����uKi�����[�Uo��V8��cG8n��YEEEJ�������p������}������Gk���x��7h��}8]�xqJ��1cB�������"hx�[�|��G��{nnn��
����6W\qE\��s�x�{l��M�6=��s�n��,X� �]v�eG�IFF��w�}��7???�b?R]]��S�P���O��<@�HO���.4�\s������^����/�O<�D�~��u�e��E%�w����B�O~��8����������s��C���Y�f���5m�t��M��7��h�"���������~��(�����p~���5Q_QQq���F;�t���������
�=z�H�<J��:u�����������}��%�6n���M�(����_~���8//o���'����s�4i���k�����3B������#����:uj��E��-�u�VZZZks�����[�j";v�8x��x�|�|��\z����5k���m����?�~W�\y���_x����v����g?��}{=���d}�oJE�����=��2oE�?
=}�/:����FSs���EG���g�������6��V�4����U]s,^�������D=��zhD�p�Vo��>om�n��g*�z89�U�����h��g*�z��U�*�4������NE������=|�-g�z��n����?i�Y>�g�������j���z��J��l�?�P|�+7����H�g(�������O9�����:����}��X��������%��3�D}x}cU��r��X��3|L�8cI�7�� Q��j�g8������4������h�||@���~$��#Q��y+*�d��Eg�Q��H�do������>e++{8��D}���.�
@���H�7�z�"Q�$���D}��@���������C+��?�h�������c�3�D�Y���X|��R|���@�j�'u���'uz ������{?Z���� Vo��>om���a���OG��v$���qMc������o����.��I�&�Z�����~��������2��_��y������s��������Nop��7�xc����7o~��W�����'�a��m���~�e��{��\p��7�������e����Ko���p#��5k���]w��~����h 9�]t�E���7/�����[�n��������}-�7o��k��]�ti��I8��w�SUU�l��{�	����W]u�
7���e�p��/}i�����5k��j�*T}�_������c���#F$���w��)yyyQ_7�tS��m�q�-^}��S0m�X�xqNN�9��3m�����������C��#{��J�v��k���d�������c����JKKC��^X^^�|�����zk(��w��UUUu��!�������6o�<777�6�~Ca��M���f���TWW���/�8���>����-''����eJy�>}B���_�����I�&��s��-[�a/��b���K�$�N�BIiii2l�����~(�7��7o^8���C������P~��w���p��G�)7n!�����gV���]�����KI���M������st:u��p��{�����/�������w�}7������)aw�ygr[����;�4(%l��
��e���2�,�
��kN�,Y�VRR�o�����F~�������w�}�i�^�W�^����6'N<��u�]�tI3fL����;��h�}�����������w��=���)a����V<��;4����6,77�u���J�[n�%''g��	��<�@����~�G������=��S����Ft��E�p�n�����|�+�j������|��p��M�����wG9�p_Y�4�;vt����K.�����������{���qm��]srrf���~aAAA�9|t|�����-Z�(T]~������2J��N�#���]���7j�}���aq_��o�r*�����{9q��q�����5�\�����~��A�B����p����6����aK�,	Um��=v|�~���~���{�P5y����}��g�q��k�����P�i��l����~��?��W�^-Z�h����3���l�V��pE}��=��Q_Y�����Z�J�&��M����^��U���o���t��������/BU~~~89rd8��~�6g��P��s���s��\8]�vmz�����P�`����]�bE���a�v������Pc?�g�l���WMMM��-srr^{��p��_�:~sk��o�9T=��c����,�������P���(:�����7�&UWWG9�w�y'�~���[�c�x��P~�%��w�T������;o�����������7���y�������3�q�n�R��=��u�P��[o;�F�p��Y������[o�5T=��������N����V^^������}���t���)�c��	�������h8�:u���)((H)_�lY�F}�������>:��ssss7l���6����+����;��c;v�h���9���u���d��!���.;r�H22�������N��7???�b?R]]���O>Y�Y��������4i�d���555Q�[o��������{��qd��5�\����G%�W�����C�O<�E���n�z��eQ����o���P����$}]}�����{�9t�PT8k������M�n�������-Z������F*++��_E���G�~vs����������i������?��?�����������w�����k��6���K�.W_}unnn8���GJ�Qz<����u�]���������/�q���c������/���p��>}z2,�~�����I�P��]��`�x�=�������_���/l��������W������?N	;r�Hqqq�N�Z�h��e�n���������9sn���V�Z���;<8^6���<���^zi�f���is�m����O���+W�~���FB�������~m����;�����3����,�$#�Q����,*.QD4��>\������F�4*�&�<MP��<��AD���"�A@AT�eV��X�~��l��i����T��=u�gq����o���w�=��3����5k������o.//O��q��_����������6m��w��n����*�N�<���n��EQQ����;v�����*���|����o��A��Z�:����O��Z-����={���{��G�����k7b����{o�B���7h� �5k��W�^����}����6m�W[�v����������O�����y���VVV&��3�8#����u��m������:�\�2��o���y���e���rH������p�
���?��I�����cz������
6�9sf-�
v��K�6j�(��3f���Q��37n
'L��9r��P��o�U�VE%�/.))	�7�|s���)SBI�6m�����_�~��!������W������S(<������?��sEEEyyy����PXXX���?y��������k�
���mk�/�W��U,���Wuuub�/~��P��_�hs������[�dIb�^x!T�k���/���k(�2eJb�5k�4i�$��'�y��G�f�N������;|���=�\JF�������'N�����L�>}��q�����(����}/���������S���{�v��;7���G�5�7oN�6|���imN;���y��W'U[�pa4	Ot�}��
������Y���M�81�4��"�B�������~��/�<�f4���w�����~�>}R��t�Ma��'�mF7�o������,H����y4���
����??��'���U]]}���b��n�-*4hP����;R+���a���^�o����>l���j?�p���g�h�a��a��w�M���K������J��s��
��[�N��z��(��n��4�>d�u�]��:w�\VV����7�L�:5���W^�>Z?���R�=���aW���zyyy�<_�|yj��X�,�i7��%%%����Z�lY��l�������Z�l�p��xa�=b��C=�Z�����N=���~�%�����;/���Y���v����u��E���>�,������{��'��>����7[}G�����-J������N��tTTT�u�Y�Xl�=�|���w}����]��zG}t�{:w�G�J����Q��c����P���}�[�Y���#���b]�tY�dI��c�9&�����S_8z���k���a}��	a���NJ�6m����w���f�F���;���Zs�����y����������V�Z�V[�jU��/--�v [��Y��[�X,v�QG�]�6��E]rk����������=�X�c�?>�:��S���p�cUUUE9�>� ��������9s�������[�Y�a��~���b��O?���b�u�N�*�jI��~�-��7�|3l._�<���_?����C�	�n���h3�c����J�6���������������3f$�����B�	'��N( �F���N>��(7�U_|�E�
����0���	m��g�xI����7��-_�����^�zK�.�J�y��P�}��eee�5�	m�>���=���c����w��k�P���
���1�����:�{4M�=V�X�����m��
����Z4�M�-^~���d����g�yf�Zuuu���C�g��i��������/,,\�h��7�m��a(�8qb��[�~���1c�|~M��UTmY��jW[��v��y���X�u��=k�l�����
<��hf�>}�t��=///l�92�oF���k��tP�?�����4������e������c�������?�!�Z��}���


��������8+��>���]m��.�_U��=c��xs{YY�����v���a�f�����o��)[����M;����7ojv����k���6���O?=�����{�����n���������(����7o���m��	���x��Q�/�H�@I��V��^��j�Z�n�v���A�>�}Q��[�����*3�-[.�����W^�[�� �A�>�Gy��r��K�ne��Z%Q�Q��V3�tW[�$�ky����"Q�&�����&� Q@M$�3��i����t�Z���D=@Z�~�b�����r��L'�j����:eS����*���������R����{7
��4Z�{bs����?���Lx�����TFK�����o�����U�nPW������Jw����J��L|����
e�nM.zc�����x��l7��$�3����O�uC������BX������1#��
�����o,��2�����r���3|������J@.����{^,�����2����O����w��e����
� Q��@%Q�� Q�Q� Q��@%Q�� Q�Q� Q��@%Q�� Q�Q�d)Q?��%��������H�g`��v���m�'��N�'%�3@� }KVW���2Z�,��vsj�D}\��M�v��L.'�v�a��F���)����������*��R�9���7v��,��e���w�{��X���F]<ec�����f���oe�����������heU��YPYYy�5��b���{o�u6n���_�z���o��q��M{��}�m�UUU���<y����E����}��w���_}�Uj��?���s�m��}�
Z�ju�QGM�>��9�������{��_�]�v#F��������>��_�~�ol5��v��8 �-**���o�>}�����[YY�X��3��yyy��u0`@�f��f�V�\�X��7�h��y���e�C9�s����o���;��I�����cz������
6�9s���d�<�H�f�


����
���9rd���o�U�VE%�/.))	�7�|s���)SBI�6m�����_�~��!������W������S(<����������{���(///����
���'O��TUU]{���Z��m7n���
j���_\\<{���^S�~������[�dIb�/�����^���QI��]C��)S��Y��I�&���G	��:uJ�+���E(>|����.%#G�Ljy���C����3*�!w�}��_~��������B���S_���{�]s�����:�5�7oN�6|���imN;���y��W'U[�pa(o��Yt�}��
������Y���M�81�4����WS�>�_���/O}I4���w����������Z���n
�N>��h3��~������_�`A���������7l��Tm����T<��� �jJ�4(��q��/9�����K/�4��p�
a}��a��~����g���f��
������Z�K�.a�SO=��q����[�n�Zm���Q��u�~��u5%������N����+��2>9|�~�Yg�V{������;�����(y�|�������Y��<n��KJJR����l��o}��]5%�{���z����\}��a�����/����~�y��V�5kV���]���n��(y��g���8p`�u�=���'�|2�w��y�o*///�]�h���;d��Q�E��w�G7��sG}t�4����[=V�����������sL(����S_2z���k���a}��	a���NJ�6m����w���f�F���;���Zs�����y����������V�Z�V[�jU��/--��{�d�t�{�������]tQ���I�:���������=�X�c�?>�:��S��n��������*�����w��55=1v��9�|���J��@v����:uj(���_RyEEE�-��7�|3l._�<���_��
I5�v�r�-��Yg�6�����j���������J��AIII��1cFR��n�)��p�	����D�_|v���-\�0�<��f�}������;~�{��������t�����g�	���o_VV�X3����������;6���HUUU��]C�<�]q���)Q���Yhz���b������_o��m(��������oZ�h���/G%�W�0`@(<��3������w�
�8��M�6E�>�`~~~aa��E����ao��
C�������cd����+**vJ|`����{&�����b]�t���
Q�
6x����6}�����{Ty���I3J�]�v=�����������k�&V{���[�ne������c�������?�!�Z��}���


�������<>=��y���c�*�+����?�k��
6l��Y�~��L���?;m���>�y���f��������m��>�����?����_�~����?���}���?��y����M�����G��l��
���,��:���+n}�,Z^_Z����\[�������-�[Y�<8�<���Fy����Jw���{6f8��=�9��:���-�p���3�|�����W-}V���A�>$�3`�f�]gxygyU���������z����������(������z����������(������z�����������w�W]���/?�y��kK�����2|��_�tY�>$�������~����O�G�~S��t��=,_m�t��z���y��\n���wm��+�����������2�A3T\���/�����I���tj��>ifY�������.����O�Tg2��`+�V�jKUFc��is���t�Z~>mS��|���Y�^��_��o,��������u2��$�3@���I�u�D}H��6�z��������&Q�]� Q_�$���K�>$�k�D=Pw������2�\�����-�?���?�FFs����m:���L.�'����Y��MF-�3�M�[N��!���wn��m��r��>zX�,���E��={���{��G�����k7b����{/���]��I����c�X�=��v�����
��93�M��x����������'G%UUU�^{m,k�������<�m\pA,9rdRy���C�����*�E�b�Y�f%�O�81�4(+��]������
�v��??��i�&+
�]���sc�X���Sw�^�:���[�.�
�]���?��JJJRw���G��e��e�a�+x��'c�X�����7///�]�hQ:�'�i�f|�����~������l��u��N�R������X�U�V��V�Z%�KKK3�0��Y���'���3'����^Yi�"JJJb���3��o���P~�	'd�U��;vl,;��S����v��x��l5v+V�h��a,�8qbuu���#;f��P��>�TTTd����z�����X,V\\�����[��-Z�����n����7t��6m���_���x��Q��-�v������]��V��W^y���:���e!�s���v+��[o���u�>}������S���W�������%!��G�A~�������j��/�p���n�������+�d�E9���^;�����i��#F�X�"�-�A�>��!���n�������*++�v�r�����"��q����a3�-�A/�����ZTT���O?���<�-�5a\�_��_]�t),,�����7�������7�?~���k��i�^�~��l�(}���a���]��'<83���4m���}�6k������k��![��[o�|��7n�vCr���S����l�"����1c�|��l7$��}��������}��'
�\}-Y�bEa��Z�����U�V!�
4�B]�~�_|1���)��~{AAA�mQQQ�pe�r��l�+w�k��N;-6///��Q���VUUe�i����^j��Y������K�b����~��x�/���l�(�TVV6,>��}������\��'�t��=������v�rJ��l�21�a���3�d�]�#|��1"�4>���}�I��_��u��Ev�ar��d�������?�y����~���D� ��Zu����87i�D����t�I���
6���=�Z��Nc������^k���{�.����h��~���P������Y�����~��w��_���=��3��z���nZ�8��SBH�<����W���;�����0��s�=�nZ�X�bE�������������>���Bv�����������3g��.��iS��k��]t)�x�������of�E�f��u]�t	A6l�+��2o���^z��l�.G��6�������eZ��1�G�!�-Z���v�rD�������.X���k����^{m���k�����:O�����7d��Zr�G������=�g�A���+:v�(W_K�����[n�E���y��m���B-W�UTT���~�5z���������$�z���Yl[�������:w��~��xa���{M�6�b�rI��������P8d��l�*����?
�Q�vCrY�������o��
�V�j��A�6l�������/�8���sNb�O~��P������jU��~�����K�)��k�Px���f�a9�������[b�m�����,Yl�/��;���o��(#$W_�
����_��r���u���{l�|���U�������?���e���k���>�.���������.�,�����zf�����'�����~�T>a��P>o����*�D����~:���c�i��qV��{�w�^PP�f��������M�<8[��1���^^^Rz����g�q��>���s�������h��XXUU>��z�!��{����R8KC�/���������p�
G}�Gq�UW-_�<[��eeeM�4	wI�u�������d�a����_�<������N���:����*����?�|������)O�@�s�9�^�z�0�������w����Z��'�D�3Y���u��)��ae���/��"����~�i����\}ee�oF�y���7�����Y�������|u�e��m���;�<xp�����������0�E��~�T�������7n�Gq�)��f�IS89�������$���������/=z���z�����[Yian���C������%�_~y������������:m���!�}�����[�.��H^^^���v����0&>�l�����Or�&M<�t��x����>��v�m�f��e�I�'��B��>����7�x#�w�qYiU�i��Mf�o?���B�����e]�N��u�����<j��hS��6Dw ������}r��j�����'���\}��l����_�v���m���9ZO��WTT�z��=z�H�����p����.�,�L����g����O~���������B$���Y�ti�x�����{D�t��x�4(p��q��O=�T���x��g���5j�(0�	�?�����F�}������?[��������?m�|��a�{�����^zi���}�&&�I_�3���(�e���Bz��'���'�:tht&_r�%�mj��"�6��/�l��}aa���cg����h���3?����mj��GE�m�%��o���7o��V�����/�g��I��V�
����J�rLqqqfjvb������3��7��M��7��w����!C��z������n���;v���&W_��D������x�>�7//���$�d��9`��A�+����6�=s���;.���ma]WUU��q�#�<2^��G7��?>�������(�y�i�E�R�7o�>�����?n��/��b���w�}wQQQ�\�;j��IQ���[n	gruu�<��I��w�}��)!�!�c���F7�tS��['�1"D�e����
��6m���+B������K/���S=�CIAA���s���:���n��������5k�������9sBa���l�O<1�������_c)S�E��&~c�v	C�=��#0z\��~��0N���n�v�m�U�Ve��uU�o��EZ<���I������*�,Y�$*Z�j��'�$����1�IF��������L��%u���/Z�(�M�eeeI��m����;&D81u��\��
�!l�p)���%!��EJ�����Yl[�����`Fa����[�S����u���%W]uU�����jU�������7n���~7
��)S�DO��S�S]]=|��(���:��B�f���Me�����eh�^��s��Q���{�h`���?q���x����a����������>�>����:�>�h(o�����v��y�B���^��0�'sj�}�w���g��9�?��?c_����0�8��S�*�����3�������uO=�T���A���u��T.�>�����+�����]�xqR���s�y{�E%�/_����*SM�K�.���S���I������?�H��:c���'�x�~��[�^�[��_q��5�5kV�3�����pV���|����m^��z����}���w�M��l�������:uj�YYY��e:�������%<�)��&>��g��3f��9t��p�<l���c�9&�N(��8qb���&M�4p������=�I�&&LH��i���w�=y���Yia]WZZ:n����{��?y!����jR�P���m����|0�]~������j�N�:�:s���p�r��Q����N?�����o��.�-v����8�����>:���sOj���8GuT��W��+������SN9����`x�d��CH����0�����0����k�-\Pl�aO?�t�u�]�X�h���|�;�3�cl����/���O<��+�����{��>�
���������:��������#)We�4h���������.Dx>��r�����@z��%���:o��I��h������Ui9���FY����p��lY���!G?5���K�$d��;�����'=[�Ti�~��{o��SO=�%!K?~���g��*� ���[��?zj����wv�rD���Gy$Dr��y��Bov�)�&��.�������o��)D�{����nZN�����P����la >���_�Za�����K/�T�m��z���~�F��\���Z'�������y�����[k�e������i�(����/S+D?m���m{��W���;t������V���O����^:~�������3v�aFs�'~�e�C���d��uOEE��^��-��c4��V'}O-)9/*F���;��x��G����.@��p������G���!�����
���_�}��\}�8'���L�:�K�.�L�B:����x�>�U ��>�����V���{���C�0�t�Y�hr��g}E�C���=}�������'f��]Q�<x��Znl]�~_��K/�H^p�����fAA��+j��u�v
��9���#�$�����5���s-40l��-������������oNk��9"t�F5=�)T�~�\x��I{���{��;p�������W�^���)Wz�0l����?�9io���%<���&��C���,���N�-R�G�z��1O[��9s�������~�������
���_~�V��������,}:n���(o�:a���sR��O��4d��UUU�I'�B���e��q���5o������#\��7e�aWP^^z����c���s���������k�.�v���\�y�/�O8��xm<Wo��m��vZQ�}k�0����N}zlX��=�����>���m�&e�#3g��W�$��"�4t��OH��G���?�+j�~_��;���������N,���C��_\km���������C0�v�������<���C���?^�-���k�]w�~�����V�������iS�Y��7�x#~WaM���7{��Q�s�=7������s�	��\rI�\���G?����\�G}z�����'�K���_���+�?��lr���E�(����O�>=�Wy���J�e��7�/o�����k�v�����������7o���>-X� �3f�Y����;7Dx�=��?v0�<��X�OZ���;��G}t�,}z�'V�������$����u�7�|�V_��M�8 Z���]�c�=u;�Z3�����.
A7n��V���p�����/n�k
���|��p}.%�u^��W�����{$I�C�z��,=��]}E4rN���m��[�~ho�p��-���?UTT�^�:�/q��:�mH�������7o��Q����J(y����<��P2v���oi���-�8��O>y������3f����c�z��XO����?�������C���Z�ju����3�k��a�����m���C��=�����_�jU�3�������G�=�W_�m�_}���!CR��d��y�����������������������}}������V�~��>�t����%��
s���h�0�H,���/���k��i��I�%w�q�,}:������{�����~��gI���m���I!��D^?��v�J�>}�3.t�a�r��Br�f��bu�TVV��*���r��W�X�������_��Y��f�<g������������'���; ��"�n:t�����A��:5�����^r^^�/~��4�N���[t�'�I�&2o�*�bn���If���3g���/1��F���iS&\������\rI4���s������{o�4����������6�9��8���'�Lz��V+�O�+���Y�f� ��_����6��9���C�B�T~���������<��C.�B��m[z�����[XX�4�*��_�g?�Y�I^|��W_}5�k�^x!�g@�>���J�����T����O�^z��g����H�6��$A��`�#��b^#fQ���k�YQk�����0�E]E���JQ$�w��y��73=�L�=��{f�k�s�K�t�����^}��%����+\2d�BR�x�����&����u��;�.�\l��
�u�����.�����2�k�.��a
��7������kii={�LvO�i$%%q���^�>|�.�b��
X�q���^+�>L�4���V�...���� ��-::�W�^���FFF���x�&K����>}���������cq�����V��l�z >>���S����Nb6����������� �^}���{�������\���L��|�r�*9���W_,���_�|�����O��o/��;==nj����R�
�ss�c����j.��PPP@^Y���`�_�p����&��W�-W���I�X�K_* ��������=�r���
�'����rK�����F4��2~�x���j�*��###a�.={�����I�u���l���f��(��y�����������������Cq�&��a��[7�Qg�dD^��
DP+8�B�(0yC�b��A0
�_Yz�{>|h``@:������s'$��4f��#��1cy����"�]������5y�d2�����WI���7�K��&M�@���[G[��O��1551b���cI%=�����.=>|�@�k��w�6FDD���@c��5'N���_?�d�=����(���R>611166f�;E��Q�3�.]�m������dy�3g��<���4'o���M��/���-
2"/�j�������!�����p��E�W_PP�ah�CXX�����W�^=��V���2�z�
�i����:y�d
�a
�����LY�W���{�n\�������{�����@%�}��=?}�D����V��!:���|������D,@&L��|�r�5..�<�X�p!U�������3g��K� ������ �9��@�OOOHr@@���-���666:::�^��;����{*Tptt��+�Y��Vpj�VpN�8F�W[�N6��#�R�W?w�\///�"��bH����Xk���76!"vbltt���[zz:�1))ISSr�ip������� ooo��wG�%eX8�L]���I�&���C���	pj� ��0g�5������Emy��������-�|T���#O��D�>|8$�����@�d@���
U�Z�8y�1�>66�V������WO���3����WO\z���{w|sAE�z��_��;�r�<��:�g�H���C�A����'O�&�m���@��i��a�M�RTT��iSH������Em�E��������VD�� ��
@���
����DGG���(�C��O�8���X�$�9���(���^=���e�K����6m�
��W����%�e��VP`�V�P���
����bZ������a��_?e��f(�L��I��u���BD��)h8��	���`��K322*U�������[UVn�q�c'''��:`�I����;!!�V� ��
@�P����3�J��B���M1���lllj����3I�zt�e���#---��^R�]z��cI�����o�W�.������<<<��CE��E+iii���*T�s��S'����7ojkk�?���,%� ��y�����&(0R���~�
�����u+������+������m�6�Q[@"@(@.@4��E0��(��Z�jP+ 88V��Z�b���VpN������f�~K�C�^���NNN�%���)S��K_*���zzzVVV���R�~���eKt�KE^������o��%$$t������[/JB���?~�|�}�v�5���/VY��G��y����E���CCCmmm|�A�lVp����)�\����B�
��7�?��_���q����f�J=�����p��T�=��6Z��S�N�����(�
�]ZJ�B���d�
yy�����9$��W�Z�riN�#==����b�����r�����Q]*�/_�D����e�@���K_*$W���r����G��T��
b�;88������OR�ri�^R"��������"�?�r�\Zcjj
2laa?�U	}8� Hy�����j�Z�dI���.ihhX�
f�
y�������I�2V0+?��{2�����g����gff����?�:u*'�,��z���!�'N��$.u@^�@A��o������o����/��U���e��Ba���W������P+@^��B^�
��)����!o�G�f�t������u��!�?A�^.���mlltuuap��	����^+@�W�XA��*U��z�j�K��Z���1b�mmm��:u��<y����\Z���3WWWZ�
#::�� �y�4i�����_rsse�\�n�4-/��o��^Y*��+ �m����u����������0�����&H���VDFF���U�.@�#�V� ���9s c��7766fcA�V(��c� �5k�|������
 �W�Z!/�jE1N�"//�v�����~6@t�����K��U�R%''�M�/_�4h�]z���o�����b����'&&&���G^��u����=z�������y����Ow���_�:0uB^��u�VJJ�J�B�g����x}����4��p���4h�����s���^�xvvv�&6�=|�p��������~�j�J5�	{�����'OVY����Z6������\Z��,����_��i5��������`�?�Z��v��e$����l��V(�\^=j�l��8yS��'OB�]]]��$**Ju��%��M�$/X��e���tt������T�z�*�����K/
h"/�j"/
h� �����4i�d����Lf����O�40u�����6m��9-����l�2|�I*yyy��U{������Fj��
�%}||��t�(��������,j�E1�@A��������GDD��������V�r�J����ggg��'�r�����k�����'���W�Z!�hE1N����
��w jKFF������~||<���-7o��a��A���B�cQ[P+T
j�V "����:u��P���6l���p���W�����Zo���'N�Z�*{�
)�����}�2w�,]��������lEf��#�A�P5�� 11�K�.�m�!!!u��=v�����\������>}�@n���`H������kgaMMM///��5i���W��j�<y��4��"��m�����:C�n����@��
@���
Ad�����qc��;z�(����?600�]�6}$���w___�����'�cOI���z�Z�:P+8������#�EFF���"@�������0a���0V�������|c����222B�^Y�V�����!�+V��;�����$9<<��X���o����YZZfff����Z�jP+8�A�R�����+��������G����7��w��%�y�HIl�����{w��z��Uj��@�P5w��166�Q�s�,�o����h�����?p����6l��.[�L����{fff����
�x��=$���())��X�-���.]�a��Y3�?A���C=c��Q[P+����A1`Ov
��V�re�gf!�bjj
)�z���5k��1i�$��&,,�����W������C��0�U�
�/�Z�
P+TMbbb���!�l��;w������
��kii>|�������{CJ/^�(y)<<\GG�x�x����V���u� ����|"$�����m������$y���*��<���mmm
j���K�cQ[P+ ::������
�B��V By��Y���a��khh8v�X�0�7�C�L���J^���G����������������?>!!a��+V�j��A�8q")�����I/�V(�
(�k��5L����O��.�������+�a��A>.\(���e��V������
�Z�yyy�y�*�D6�?�����U�/^hkk[[[ggg�:�r���{������w jj����/r��P+8�A�b��X���uuu�E�1�����;G:���\|||�[c0�����������}xjC�^=a���<),��}���Ik��q�N�Hz���h��
��Z�
��o�-Z0��A�Z�^�r9r�$�����g����/�' MZ�l�o�+j�����2d��K�dw;q�y�O�Y���Csss��z�C�9s��:6�!55�����z�����������oXzs�Z�Z�"X��V�j� ����3X�9::�x���<��nd�|��
����y��-q-��#y599Y[[�������g.�DEE-Z���?�d��_�W��qKK�
*�5
&~|�+<�~�
c���������������+I#j�A�PR��$�
�p��
������`���+���BgggH&����r0��1�R]�����]#6..���Z�D ��4�����{v��	zq� �W��J�*���1<"HL�lll�_�^�^=CC����?��5�E@���f6�V�y�n���Z� �����/:::�_��-?~� k�a������S
�����Br!Y�������2e������C{ff&�`��+�&ykkk�	�K%y�0���=�X�z5�1  ��x���|��
���i#j���V�ZQ��dddp��a�L�>::��@��d������]��m�j��zfz�N�B�`��K�����V���n���^B�P"�z�255e��F���������_9L=�����u+t���/�	�P1������1h�~����-[T���Z�R���Q+d�Z� HYM�Y�N�hKI.=���M��������K��O�>�X����U�6i�����Gpp0��f��������'w@����d��������2_@���P+���J�
�����x�K�.�6F#����s�H-��������o��u���:������Xcc��+�3����(��y�h��������,X0h� �?7n�B.PPPp��u�^=���4i7�	X#Cf��������rZ��������`�������`x�y���W�Z!�
A���@.����WI�Z�=�h�"�����R��/Y����*U�z>y�d�
�o���A��[�&srr��g]]]������%d�n��t�����A��V����h�oe�Bu�Z�������F��A���=�����Y�������)S@l�R��$�^�����Mp�c������AJ�v�����2�l����8�d�������Kl7���;�����a���y�Fea���fk�-255ej���$P+aOjj*z.aff&�R���&u/��O�`}
�B~�2,���>}�J�*�������S�E-H`GDD��0zam"�������	��[��g:#����)u,�@��#,A���ZA��q����`@�����cbb�&p�?�|��$��^�b�e����T��B���C�!MM�G���Z���\�zu��n��T"66v�����=�f\`}��}����
7�
���!�A�P0y�����|��]ZZ���Y�R%�5p��V �XtAHMMurr��c���@+z��-��
�����O�B�}��o��>|��?���i���X��:u*&&�N�:b��ex��V��<R��f�mm���&o���.[���
��*��E���(Q�
U��V$&&�����7�A�����AC�\��`��[<y���@KNN����o��5~��}���]��}�T��Bah�z��ay%�
�������]#n'z�e�_M�4an�E�M��V�2��={6�1!!�f���j� �			!�P�n]��8w�����$��$���������[����7��y������u(�CJffff��v��Ai����L[[[�sI�
����~����Y��V��
��Z�1r�G�%,,�����[�'0@��T�)��v��JBB����Y���������22m�4H�X
j��T
j�* /�}��A�����NNN����
AJe���d�c�f��U�H��������������ko��������WCT��Y�fd��kX��uC�Mav��E4��_e�_�~�T/�I����i{AAA�=�����+lP+T
j��A��y��#�y�������e����&%��6$��W��w�����9������7���d:::J�z��q"��m,��0yyy�z��������d&T�6�VpF��!���������LLL�W���)j� �IMM�W���I>�����q���������W�VMKK����|�,\����(**���];H2|������&�BJR������
R���k��z��ibbXZZ�[�.22����d?���3��Y��V��
U�Z�1X�_u8������g��
���###z
��W�^+0������F��`����g��A��)�/_����aaaR;�����B���%w�",)�3553f������=��xU@�VpL�6m �%mZ�f
�+XXX<x������
Ad_�n�����^���������w�J�*]�x�����Wp����#�3..�6���V�Z���/���������\�"n�����������O��Q���c��j�*@���
����� ##���07>p�m���+Qfccc�^����mS���zzzB2�z���A�A���y�Z���R!Vg�5�z>{��m��q�*U����]��}x%--�������2��-Z�Anhhx��=>����2
���w����
�f###2�X�z5��	�B����G��
Ad@^��Q�s��8p`�����_�;����Q0!,�_���~��W�UpDD�������a������!�B���1�������92b�//�9s�`y=�@�`$3���V��
~A�P�Z�����T� o��9�k��QQQ�K�z�K`Ai\�|9���`hjj���C������iYHII!.�n�:;;[���;����������a�������1���-���e��Y�f��P+�����}����%�*��������`^�"W�^%/���w5&���0����c�-Zt��!z#�,&''���b���m344$�<p�@����+9O�y�f�(��0��������~��[��q���e�`�C�������P|��U��������D�6mJ�Z�V(j/�V(����+�T��}����)����������STTdeeU�F
�@=zdnn�����O�7z25R*IIIS�N��Y���
N�����V���0�t�������+O�
�0%#���[�o����%�o�\�V��k��m��c����dkPrrr�j�4D����<v�X�����ZZZ���dd���7�*j� �
P	2���y�&�$�����B)�AVV,���7�W�a�
Q�i;;;�jggg:%���������KIsr��������|b����� t��]��Z��^������c�e�s��Ib����}V���1(� D��
�@���
���V`��(I+@l��L��:!���[�^�=h�������+���?DJ���+�I��Q�F���Sd8��:���
�d���CNN������������c�@
 ��;wF�^��V���999G�����ukrV/d��0�X�t����?|�0c�h�����Y�%g�>~��q�[������U�Xq��y

�@�zkk�k��]�~�����?��%ZA3^��P�>..�w�@&FL�-,,��,��:�er��m��z�����0m�4������
U/������Y���\�~������v�����M��l����~`�+V?����V�Z����� �f����?������lD�P5�JG1�����a���B��m�|�"��z�0gfn�D�@����k����[FF���L���Q�@���A.H���d___�h�M�6DOn��acc����={6��	�b�'|��]^}hh(O�
�
����'H�����}�`��mn������],:EfkbZ���������������+u�J��Q+��b�kmm�<�B�333�!�T��C�z???++���,�!&&�L��^=�g��V�z��Yf��;w���k��!�����%�w`�7j�(�W�����U�V���]~��o�n!���<x�a<����d,�C�`y�i��y�F�
U�Z�"�
,���ZA�
������C���l6o�L�600������H��c��I�bsimmm{{{~�,��NNN����D��$o<1������]�_���}�x
Yx�]4��f��b�`���W�^�B6�����=�<��T�d�w��-[��M�fff���R�t#R�������y���]�W�Z� ��!C�� �B�P�3g���5k��5T(����O�
*T�R�Y)	����9s��%���� ��GJ��"tuu�^=,@j��M��7�=�w���8��X��h��E,��� -0����"���O�#��quu�p�L}�:|��E�CJ�����f�o���Bu�V���B�W��
�������3%w�������Dj����d
���R�q�����v������GkH;�����0������
���qcmmm����K��aHs��@�����5c68p���������c��s�)+T�j���+K,-��G�@��H+����D��������|VV�d_�$����y�q��Iv@�^


����^=����/����$���������!����^��L-��T�P��BL�	��)��M�����
��Z�"��
���Bff&�����N_V���L�I����~5y�dh����8�W������v�Z�U�Kq��}�b0p/���H��*.��GJ��Kbbb o��w�-�.}||<���w��!�vS ����J��)o��x��|}����	�����?���UCt����%������=*��+z��C|�����6�����3����g��E�����M�\P�����S��9�B��V���9c��	$�b'��}�����!�G�![����V�^M$�,$/�m��={����;wZ�N��k��$--
�!�X�qB1x�`2�7n�(��z�.�>T��Z��M�K��?~����^�*�5�{�������+W�SB���WPP ��z��-��� �����#��Y�V-rttt<}�4����_�Nh����7NAC��#FH�6P�+d��^��={��W����jkkk���������F����{������L��GZP������b^=j�b�Vpj��P��:t(�
��w���)��h||<)��Y�G���W��;v����+f���������r����7�n��F�e�('O�����-�g�&Cw�����###��W<��=�CN�_�hQIo`R�A��.��7n��S�N���@����z�={����R�������z���������u��Z��A��U�lY��111���8y��zL����?��n�0�������*9l����M��H�� �C���������V��
U�Z�
�z�M�6�$�K`` ,,:��o����/��� 33��K�b�,�3f��l���K�e�h��u+_���deeI>V���������G===�.��3G�W��j����_��
"$]�'O��M�|�����;v��RSS]]]A1LMM���9sF�W� Hy����������III������g�`���sg<g���U3��uuu����?N�K��������G�Vddd�~�Z�q������3d�~"X///P�&M��������!�!���Z��B�8q",,��:F�P"��Z�:�\����b���0���$���`����z{{?~��4���k:�bY���666�+W��b75PW1�����E��hkk���,�+���j�J��@��}��{x777�`=���1c��O�>���3gj�����Hn|E�A %%���]�����������P�V-==�'O�p��Y�lymmm
�upp�����^�*���GJE^�������'���{7gA
���H,�a�����K����"����R�E1,L�FM��ydd����
�Z��J'  ���B��zd�o�����>}�l���'��rA�����vvv�hdd����������pGGGp>����WK�{��]�&MH���;'�+���j�r�K+�}�F�,�T��������OOOh\�`�BXX��.]��l,,,1b���Y�$�^=��s@f�U��!����===����������6������ mm�������8z�(d�E�o��-��������W�
J�����cx���V���ONN�~������>}:/���Xccc++���P����)io���"d�o��������_4D'�6�r���������kb=Q+��GP+�E~~>9E����F��5������f���C����q����;����K�7�	7n�XSSs��i���k����QC�u��������'O�����0�����;������M�j��|������W�fj��Q@+��N�e���$o��T�V�����)**"��@����%E�z��Q{rss4h������������U�J�o �T�a�w��y�B0U��������e�D��
0D����>?2�z�5��Z���R��L<�/_�S��d��a������������&N�(W~J��P+�b���dcy?=##�c���^=jEY@�P"�|A����G�c7�V���['�a��
�G*�KL�����;v�t(**�U�����i�����)L��/"��)���n�*fGDD/Y�����������/%�w�������Z��
���V0�����_YXXxzz2BE(R�"55�^�z��w���a>,���3g�8::��zR�X�v-(�������h2�Ui�����/�O�
��A2���K�M��&ox��T`mee��Y��g��A��%y�{�kETT��A�\\\F����#��*0����������o��Wg��B��=��?�����7�=�����yxx0��_O����Q+�j�a�0�X�p��7o�W��2r����^@������={�C�p� a�o��?_�dI�.]��L�>]�CJ������3����#�����Z�A�P��C�V����W������)�4k�d�:l �����K������������V��%77�O�>���T�/^��[,d������,r����/iA����Vp��LMMK���Y�FSS�>�{��n������ZQ��[� k��� ��{�nmPR����0,,�\�G�
�Z�D�h��&M�}\\\h#jEY�S�������_iL-:D�#��'��pTTh��]��O�
	���m��R���������������������V��
Q�V�X�A�����#h�~����E�r����
���J%""�&������E�.$�yr:fU�T�<��c����S�������/��z�+V��6^u�B�����[��~��� �[�l	���m��_����<�(J�#�+I+���������7y?~<�n��)�kpp0�u��}�OP�F
��������-Z�����dku�mll��N�V(F^^�
&�t7,L��)�d�����p���A�v�*��o
�^=��V��
�^=� 
7��u��~�>���KlW���'��g���/Ra���A���+�;���!:V/++K�W#G������$�^��V,��i�uD.P+���u�4DE�I���m��a�g��;Hj%���
<QHNJ��dkp��	|�I>\�b�s����'O����A�i&��_����3g��@�����B�KO@�P���!C����^�zMh���������.^�3jMM�RxBJ��o0a.i;���n��qx�Ea�����<�+|P+T
j��P��������>r&�3�H��
�u�������=Xe��E�|�ROO�����z���M���DSSS^XbKz��������6R���{��p��A�P.0+�[�.�UP�K�.�v�����[[[?{�L�WK�.�K;v��<^a#�C�P��x����<}}}fi�+W��������k��3SF��Vp�T�x��)d�$�Q�.�j��������[/<<<���	�����$�EJ2}�t�� lP����c��P+T�^=�DB�<��###o��%�4&[d������3f��S�N���nj:::���A�Z�������cG�,0����k��9XV��?p�:oeFihhhvv�X;j��8q�����c�'$$������d[2!&&���a.�y�B����W�F����C����P+�BIZ���KHx�N���G��U����� [+._��.�*�{���q�F�y�����\�%����Y�������d��+V@nI#�����7�,�ry�����
��Z�%�z�����)RAx >>�	�2$22�y���V��/_�������y���������Va�������LG����������	y�w!Y�����gO����!�{��m����W���B6�d���������J�V�^=��V������[�V-�'����������������b���+!�p��e]pp��$�7�,������k���f*���g��m9�T��Vpjv������qqq���;w.�	V�^�Al���w��[6��7o�Kl�7D������}���NNN����D��Q+���{���)?dee�� aAG�@__��������+�����N8���7,[$��Fd���;v��7o�����^=��TE������!��/_N[����+z�J��_��S���$�]�`��Z�,V�Xq������K��`�<l�0zH����)�m��	��yyy��z+VD�MY��
�0� c�����c��
��Z�j�}���O�����T��r1�|�����G��$==�F��#G���s'h��e���S�z�AAA<�'8�cS���������
�Z��z�����1<Axa���ZZZG�)������h_7��
R�
h��1�("V�aOaaaI^}�H�W�Z�
		Ac�=���:::vvv��aB���W_v`pj�� �o^^��Hb�������$�
x�����?�`��EZ���kC�?febb��[�a�k��%��*$E�t��/�+j�*@�P)0a����q���������7��������]c����k����	��:t���g����������K`�������w��9<�y����_�!:d�2����jEY@�P"���������c]z)�xxxL�<�~�62�����!�
���07-#��b�I�l�Q�@>a� �*��&M��^���$�a���Rk��o�eAR+�e�o�b���������555��&y�7�6Z�Y�fD.����2{���?|� ��Z�tP+T��M� �S�L�-_�~%�����#F�����;w.�D6�>}����}{6=��foo��T���6�$�LKK#�K����4{������\\\�	>|��W�Z�0�J��V)))�j� ���lP���:t��.��/�;
		��T@��t�B�����?���^=����;55��`�
�
��7o�H^�l;99������%w�#���BNN��]�F�-vI���Z!/2��X��v��->"U������N�0a��-Zdddp���W+���/]��gq�����c��%����U�����Bu�L�������y�#`�QS���Y\dd$h�,/w���dJ
2�����&M"�!�m����X%g6{��GgggG�$%�oK�� ����- +V$Z���Q+�B���
 ((����n�R�III���;������M�&��$�a���������������� D�����x��%K�hjj��9��������������6m�^�����������������Q�F�7��#�C�S�V3�<h����w[XX4k�������e�4D���>}����b[=��Vp@\\9���F)1(��[���Z�DP+TGBB��j��������q�����uk��_�p.�����(�T


rrr�_�z��V�����?~400����
���lJ��A\z
�� �g��9r$w����G���������_?==&�V�t�RH�����*�����Vp�AAAAZZZ�M���R���Q���	����uC��,DEE�����������#���k'�2/$���899I�7�@���9q�D���j�����W�^�}l�`^^^����K�D�MaXj�c�Ri�8�XRa>�looitqq����
�����	&�+�,A�����,==�}��A��~�
7;����
e�Z�:`��x��|
		������{~~>|}��%=5���s�?=#F�h����/_


��G�J����kC-Z$�W��u���O��6X#�+��'���7h�kM+����			�����UKJJ*y���hE�Z�`F��f��Vp�l�^�KO@�@����i�@������7PKKKGGG��B��711�7��STT���lhh����o����b��7o���Y���c�����;v,00�9��q#��M�8Q��M��=[�j�y���������YYY<h��	������}�E.�.]�Sk777����lrrr��?p��m*��i�����m��
0���S�@����������$���'���V(j���;��e���c���a%�<�����k��dx�3��0��������|��4|���<r����������+W�
V����M�>�$����7����;v� �;w����M����o�������|XP��!��Z�%i�?��S�KO@�@�rH�F��.]J��z��j��  ��������K�����7!�C��-�i�����Y��m��o{���}}}��I�9���=�4v��������1<�|h��q#���i���������&������=��}��e�8P��V���ZXXP�ptt$��S�N�Y���7H�������z���_���B����0���"n��a*T����T���
�A+�8!)1�ll����'�>}�U��r��ys2�a�����o_
Q�M���b��deeU�bE<��=��_�����BBBj����������L����l�7o���SSRRBCC��&6�Vp������]�vI.=� �
��A�����]�v���g^������#�r��!H���;�J�122�}����_5jWa��������c�M����Cb!�;v\�r����a�@�	:�g��5���f��������N�:�?~����0
�;w������0�e�o�\�V�����C.\8{�l�r��9s��y��e333��?ggg�.11���j7�*+���t���q��e��-��d�������'O�"�r�Z�j���f��w7}}}�b����;C>o��I[rrrLLL�;�y�f��z�"������@7`L.y{{�},qqqdK������Z`DDD�>�*�A�d}!��I����G�V�{�B9E��Z�������3D"`e!���z%���C�d�n�
a�������M�J�p��[[���4~3g����Z�������C�����k�����E3�B�
������IJJ"�?`pN�<Y�*�oJ�Bu�={�+���\�����	&M��)���d�������7�E-0P+8���*U�Q���w�����k!�.$W��G������M��V������={2og�j�bf�O�>��-�����c��"**
t`��q&&&����#F�?���)�0k�,cp#���upp�uW@=�T��!��H�=�j������^�z0� -0g�8p�O!�
U�Z� �\�����m����e��+�}������R�r�Jz	n����s��100�E7�+�S`������t�������#sss�EH�
��.���s��p��}����|���d����)�
���lff���g������iS�	�J������/�&d@�����'==>�x�n���uc^m��,���� �x��\�V�R����'!!������;;;���g%����'O��x"��R��a���f�zzz�����s!������u����~���K������J�
X	�=�X�N����322��}����Bu�V ����'^����b�W+<�B)899�
.;;���g�prr2��$/����#o�Kp������N�x��!��`z&Y������HA�P"����:�"�yC�P
���o�A>iuB�f�>\R]_�$P+8�O�>����kjjj�
���y��1������)�eA��V,��LO�@X����g�-$/���;::��Vv�h���g�o�����z���x��
��Z� �bP������[�vm<=�=111�����Q����S����%���������c��133��`�
��!u������K��K�.~~~���VP�M����o�����Vp��9I�t�rrr&L�KB�bT+P+������W�V���z��b�
u��R}��E�������}��)�#<����%V�"==]�;}�������������4K
���aF�h�"�3L��oYYY|��DGGC2A��>����i��=y������Z6lX�V�`�cMH�DDD�"z�������v�
��Z� �����q�{�_�N^����~U�F
h������joo��uk��6�mHf�*U`�,u/���W�ui�"�C�`j�|���l����?:hiiU�^���
�
e���B6\Q455���G�s5jy����zxx�SZ��V������k��h��k���:ubVu#H���HHHh��9
mm��[�2;P��]�v�D8;;o�����
9(��s�N�����M��*"�
����7s^1|�p���B��V Rd{����,,,����;3���RL�i�&�g��=D�;w�<s�L]]�;w���@)**�Y�&yK]j]zr�&i�"�C��Z�=�$����K�5����!*��Wxj	j�Rpuu���Y�f����/]�_�28�,������\�n]__�&M����7��PA�P:������LS������������	MMM��{�v����z����n�3���i�Y�|9d���P�)AAA �nnn��W�����O��Vp����!{�������A1@�����T�����V R��/#+W������1m���$�B`��=�q���$�D�������������8�BO����<=v��p	�,T:����
U#�III���$����������E�jE��d���������>|8�{��###�l��=���j���A��
v�����'�����99�	�����%Z!���MMM��'O��Y�fI��<x`oo�!z7�����`�������VVV��?��b�
''������^�"�0g�����3i���%�z�
e�Z� H�^���w,B"55���7n��A��.���w���R�6���-Z�f�<JO*999�G�l�������$���/^L����F��
�Q�/�(����c��Z�\�����/��H�f������7
j���N�*@�P��������� [[[�A�~�z2���9))	.\x��=���<��e�!C������)�9/��3,�����Zy����0�����z�g������������_��Cb���I;���V�
����v�����YZZ<��x�
j���e���n���i����=�&�y����Z� ����?,C��&������W�b��c��������V�Z��^*YYY���~���+�������������3L6��%K��F�Y�f�z�s����z�6�����C�7�!��B�(����'����G��������A:���C�j���7�k=�}f��A����)	�
���c��G���F�
��3gd�o���='N�d>|�|�qN*8��������U�V����~���`���+W�[6d�@�}�W_�zU�zu��x���.\��{w�*U@:�hH��VpCpp0$s����e���*T:t��S�����W�����f'/���|�F.`���gO"� �Rw������o��>Ba��Z]SC�`���];�����������,sMM���8a�2�@Tj�\�V(���:t�`����/,��
y!M	��=��PPP���D�7D��p��
�9�
4

��*�C�b����I���������+��m��%�������������H}}�Z�j�M���������l�������E���u���
��a�B��Vpy��������Xts�%s�^�Hb���K0�!F�����w���A�g#??���Do-Z$��.�����qlB��`"kj???++���,��
666bkj�r\�z������������ 2A�P.�i�������o���VB����7����#�-u
�a�:`��c��SPP���M�0���7e��aCr
�?��)�8q"��o�>��/�AAA�E*0`e���dnn���HA@�w��!*�N�N�g������5J��U�$P+8�����j�"OC`�lll��Y3�b��7o����ck�����
j� ��	L��s�c��Iv����`�������g���d���BIkj��A�P.���i�&�^�<y���#G��R�=��STT4z�h2�%;0�7�O���w�`�Q�zuKKKfI����V�Z=x�`����_�-Dr��
�����?��s��2�Z��}^��O��6  ����_�^�b����'{P+A~Z��	1�����0m633cn�BdC����77n�d\S#�B��V j���M��t'�s�N����<�',P+���o���R_�'��a���������4A�����(Hu�n���;w�,��D6;v��`�+�y�����m�j�������m���G�u��	������uuu��_�x�g�	GX�Z� �3C�7��-!!�X4mvrr�YL0�P`�55,���kjD��V(�
D��^}�@%���}����?�����j�����|������k��a�����ggg���o��������
4����/ds��a�g��=�Kp���;-S�N�5L��B��������-Z��gI�x�����[�n���7����)j� �O������|�W��m�tM=b�����5�o���}x�0���Qc�W������,��{J��6�z�����R�J��-��sg����&4j������w2t;t�������_CBB��]�$%%iii�\\�rEj�[�nA��Q�xR�@�P
����7��;i��}���9��RannA����vvv7o�������K���9s��\��V ���P�M__��m���X�M.
E��bg�I��5���7,O8�A�jEA�@����0a����q�s� j���Vv�bbb���<x��)����%$$������&b����9$&�d��-[�@���[��Q�A�(;�w�����]EEEU�V�<�'%��T��������
�H��V �������={��p��U�Vp������?������F��Z��H9�z�s���;����3///P�&M���b������ddd�(utt\�b������BV;u�D��o��)���m�6>�$AAA5k�Yh��yXXi����]���2�'''C�+W���
)�
��e��������K�K���u����ZYY��n�����#��AC&O�,�"ITTT�6m@+����o�N��� ��7yY�l�bmm
�upp�����kjD]A���
��B��y����		100�t�YGG>��{�^E����-_���XCjjj�z���u����[��s���i����r�����������O��+W�dn-������^�~mggG�"�����A.���!�XVHE�V(,(���<f������{G�c���6���3��G(�/}��)����P�e��adw=j� � @��=G��s����b��...N���u��=�H9�z����Y���fffFFF��A�����"<0].�\�B���X�>}��>�-"��q����c��;����yr��e��w�FGG�������I������[S�<��?���'������V�KBBB�Z��V4n�Xj�!��L�EJ"00�T��^=L$*U�dmm
����y3�|2�8p ��Q+A��p������������������u��
�R���,X�w,?/��
��z<7j��s��
cccb�H>��~�J:��V*�>}"���W?d��z�������S�N�����@+��kgjjZ�j���GK�C �$''��[�����`�}�9�{���86�A_��^��������={F�@�����^=j� �  ������/���'��p����.����<yB>�5���;�w�����Z� �M�6������|��baaaoo/���G���
��'<<�X�M�6���������F=K�^���/��o�s�N�>��O��D�������L��a���h����������-4h�Xh��AA���������{������!�jnnn�>}lmm���I������a����A�@Jll,�!�����R5c��5�����j��C���;�y����:::�VK�Wooo��C�'��W���W�R%&&�y	NNN�����$R*�����8p��)S$��W� ��������s```FF|���3�����?~,���_��4�}7n��4VA��A6DDDxxx|���|���[�l)v�&���{���K�r(������_���������k��!��^��ox��z��T���zD�0����0O2d4.Y������[��C��GA������~��w���:��;���$5r�H���� H��A69r���o�>$$����Y�fd�g�R��Z�L���i�8�A��������u����T�����MxP�^WW7**Jj������z��Q�remm��+W���`z�[�n���z�8�@A�Eff���
������7�MMM��m����[�N�����{��1����{��D+�W�N�����@���5��7���K���;8A�
�����6n�x���F	��g�J2}�t�<A������.\�w��w����P�<[V���������"� �c��	dA-�����K:::���A�a�p+$9�A^A�@�
G�%Z��m[�c���P�jUh777?w�m���111��O�>�/����w�����o|�#�����B���TTTT���/�����^�����7o�G0$%%��3�]�tY�f
9��W���#� ������^�P����������#F���{{{kjjZYY��7R�@�@�
_�|����V����	�����ccck��El��]�������BOXe�9s������W//+W��y���`��c��#�@A�^^.]�Df###ZC��W� � �#00������o���={��U�V�5k�W���j� l�z����)�������a���lll`�c����g���;5DA^�|���-���gv@�Qc��g���
*U������{����^=� ��������V�Z�tiHH����)?�V ����z���W���,

������^=>|�Y�]�����etC�Qc��gI�V�ttt���_}��GA�����'N�����m���!R���������=����lG�@�IIZ!��G��x�666h��D@@h��-[J��������b�W?|�pD. ^����������'%>>�����WF��_�3����k�I�� ������1c���y��f����fv��t�!���n��+`A�b������D+*V��o�>�U�
A������
��6m��y3O�"���[!�huD���W� ���K�����4h��Y���O�`���������?��(~^���Z1x���:l������|.**�;w����Ut� ����~��r`��a�*W��


�]���F��N"���
��A^X�d	�����2d(����]���Z� ��^���t������_#�<�����x�9j��M�?�x�"\533�zR~HMM}��%�L�"%%������?������t�]AA~f��KJU������;J��������M���)^A�!00����>}����R�7�
)������H+++r���f <�� G|������������V������H%��7J�!�
�*�����mll^�|������@�]]]A
z��-��������'8�AA���{��F����l\�~=Y5Kz�QQQ3g���kWQQ��"�'999�������Z�w���������V H�D^�HNN^�h��e����#����3��y�������W�U)��Y�������b?������V� Hy $$4����n��zzz�.]"��o���K�'O��U�~��L<�
AA����3�FD[v��]�B��������>,,�\;dA�����gA��G[���LMM6l8c�1�
�A�-������o5k�$����Oi{aa����kiim�����={�@��#8A><x0�9������j�*��@��&DGG������N!AD��?npS�L!_���+T���o_�*���F�pUOOo��u+W�l��EAA�#��5h�����x��R�J���iii����B��C���]���7|�� �V "���R��'M���^�������[�s��=|�p���������)))<�� ������W�����:w�\r�N�:������_�re���W��3� ��XPW�X������'zzz�����'W��_�����?f���k�����w�ttt�.]Z,ZG;88XYY�}��\�����&9Ch��U~~>��"����&$$�n����#�I�y��	3f��*A%y���1#�=�������
4���8p�b��L�022:u�_#� H�)**z�����m[}}}Xb��W�\qss���o��,��,$��gbbb��y���L���R^^������g�t�2j���?�#� ��Z� �l�+����R�z����S�N���C���a%���7�"E�O�V����_{w�U������X��|Ae&�1��1z`��E%iZ�Yb����IY�eYYb{1����d���&B�L�ea�Dk��������}�������u�]��+���/���{�������[�~��}555S�N���~��G~����*�����������8������>X[[;~��,V$Eww�����#��_�

�7�jmm
d��=Y,HY��S��"����*�S^�hQQQQp������������h���1|����'�������8���j��Q�F�������]�6�
""����o�m�<��FV���g����������W�\�~�q�^�_|S�@�N�'��o���!z���k��7����S��������=�.\�0<��g��{�:�����/��T*�$���6����F���<|lhh����n��j �d�������G��[nI?�"��WVV���s���A�����1�d��fE��5j�����h��k����+�W����?|�������,��-]�4\��s��#��w����\{��������������W���7��{�������0s����� @�6��K/0`��1cZ[[���Yd"������#G���~����/.((b���n:i�>t�������1�
dY�Y��CC�mii��l8=������.������i����U�V��K�,),,g��e�H�5?�p�
��1555a,��;7�������<yrt&5�#d���[��c�6l��]���o�fB����m����������8���?eE[[��3�������'��Q/��W_}u�������W��5�����KJJ�}����������#��q���O���������{��Fo�D��9r�����/�7�r��2�|�� 
���h���eeeC�	_���;~���2���FV:t(�)D8#����}���?��}tvv�����1#��	�{��A�Q|%�={�I���;7X0f��#G�d�< !d�����;H�7�x#�x����/�8��M�6�Y�&<���o���hkkn[����� G�����'��9������g��i��%aV������wA{{��#�����~y@B�
 CO<�Dw�u��o�VWW644��s��	�$H��#G^p���@�����G���5������`���9����l��0+�O�~����e_z����$��2���2o���������x�����������q�����s���[����� �tuu����Y�����c���[PPp���X��#��-X�������L���{�/HYd����g�}��	��[�~}yyyGG��
8cy@B�
rD��/((X�re�Tx�=o���j%��EO��6m�TXXx�Euww�X��H������O��9����ys�TSSS��\sM�`MM��I��[#?Y��z��i����������w_�������3�����oeee�W���e�/�p�Yg�R��;w�]��m��q��!�Js�w�����_�u0RTT�����#{��1b��w�_�@dD�{��Q,'N|��g�=wi@�D�����s�=w��q��{�I�r��������>����^�b��)S�X�<yrkkk�������.FF���[o�������/))��}{���#+���W_TT�n�����+��=���q�$���7g����GO��y����� JKK����'�L�R�3����}O���d��������k�.H��������]�\�rS[[[OO��^�x��^S���%%%A,TWW;v,�����+++g���u��8��!+����E���{,�Z����k~������[o����������>� ???���_~9��	!+�o���2!+ �|��G�s�yyy=��I�<��S��T*������������^��m��.H��������]�\�r��<h���O�����~�����3\�k����$���L����]�t��-����>w!@��
�)MMMa{��K.ioo�����L�
�������K�]]]q��d����VUU������?8p��	��d����6i�����*����������7l�oy@B�
�?Q�-//���b�������������4 Ad�����J��.]Z[[��
�/Y�'��M�2��?��� �d��7 �����	Y�G�
�������F����w-@r�
�?�}���;��H:Y�G�k���
endstream
endobj
9 0 obj
<</Filter /FlateDecode
/Length 2061>> stream
x������4���)r�T������B{
l	���(���>NvL�n��L���4^���gy���2b���3�����~��sa�����X(����7S������o����K���'!��>�~yw�1~����Q�9n]��af�9��s��/�Lu�r���HsLjo��1���c������������g�{w�P�VV�t�>����;�D�����o97������Lp�U���Ef�cZH�����>~��CO�2�C�����m��e�jn����:$V���lxE<!������82$=����M�PGo���"��u��sqo(*�r���y5��1J-<���'�OYb�U��B��C`����v��S��V�="����)��A�P�Z_�?h�t��O|����A[�5�C%����Z�8L�cM�nJ�ZM6��	^��7���Gi}�=*�,�S�B�~um\&�3RZe��1�y���]��y)�	�N��0�����K�`)� �L�ZeL��,���T���~�2���l 5{��.�h�]�uB�AH�
���g�)h���A	S��� NH�LjFNuR�.6`�dk�4H$�>zV��L
jV��3���NH������Ej�QZ�g�5:O���F�F�PD?�"��W����X�y�^�=A�����@���uVU����|�_fdV�%
���uV5�E�|1�{����@�#�ysR�.d��t��q�{���3���l��&[#�Q����������=�U&�NL2H�$U&����ICb�����a�`�r����L�=T6&{^�d��Y��#���YE������S:3�~��Y�?p���q]�oL�V�d���i8p7d����2� ���\�I:�kL����d��c!�Z��BU�T:1� �Iz!�2�q+�-6v�r)�+4�&5z�f&~Q�p�e�����
:�+�	�n��������odX�N�r���<��>E����=�XAE+�2�{�'[8��!9�u.�r�{�^HN��s}����0��/��c����g�T�+�DOr��-����
�D���u���)�Bzf�4X�Tae����F�������	�u�*�`JgX�/32�HiH�q��IP�*�����3-�W�K��g�L�
+��`^��fX�LK��S���c P�F1��-���/���������b	���V�)	�Vf�I �&�U��4��|o�z=�����b�����@�*��k>0���v���d����8��N�����	n���0��7�4�����TN��H�%������05+�
�j�$\?��ih5������G����TW#%�������*(h�w�G]j���h�������!�n8p�o��eP��� ���������U"E�D0����}�v���Y�`'�5��Z�X�����N������
���q�_����)".�:8A������	3n�~W����c����'�a���9��n�o�!�g�m��F�d,FwM\h�������r�1\?�=�7 �n|y�I2/�D������0dp������X��5NXCw,2����
�l�!B9`L�L6<��b�	kAP��(�l����� ��*Ma����Id�4#���F�uB|�?*��9)��S��3vB��4\����2v�J��_|$�x!�'hc��Ls2�+�F#���C�x�L�����d�1l�W�@�3^����4�3VC<@�*x����bpF�_��u��q�{���t�5$�dkH2�{�;!x|�n5�U:!�����_���BY�r2�=��&)�l�)���i,��>�+�Nf�����|q�(f����eua��b*XV�R���e��xY]q^���>w�k�tW�Z�����������u������v��>/�G'c��H}���w]��>Nj�U�����}�n���bw�v����b~i���]�9��u�^A��].���
j���;Z��u���_���iV5�K
��K��������~�N��J�XM�&q�T6��9���1�-7�!��b��_����-e�4���y����L���o������
endstream
endobj
11 0 obj
<</Type /XObject
/Subtype /Image
/Width 1965
/Height 1058
/ColorSpace [/ICCBased 7 0 R]
/BitsPerComponent 8
/Filter /FlateDecode
/Length 57051>> stream
x���	�U��?z@@��e)j��BB�hZ��6�D|�Zc�b�?�)��h����<�pA�l��<C�Nl� 2�E�w��������p.p����S�R{���{���i���v�#G8�>������'���t�<8������{.dU�~��?�SO=U�sr�W*?p�@4�n�������d�218�	�c�=ztN��a��s2+W��.5z����'18�	{��y�/8�<TQQ�~~Bb���z*������R�t��@�f90`@t��[���[�$"�l���q��f��CGs��yDc�������D�'18�e��m�c�,����oDcM�2%�c�$����>�c���wgz�	&Dc-[�,�c�$2��>���O>�$y�����<x0��(//�����E��
�N�7o^�SPP��/:�o����u0`���c�-[VVVV�����N+**B��<~����{��	&T?���r��5O?�����y���]���������_�>�lg��Ue)��l/^<|�����0�p�'�|��W^���Q�}��-�NG���_����G��+?�����o�������~?�����o����z���]�t���G�g��E��3f���a�P�|xJ���z:?�C���Q�F�Q�?J���������"_�|y|���<����iS4����z�����s���v_}��.]�t��c�=����V����k��C���t��5���o���?��?j"2r���>����>���QM~~~4t�W��W�U�V�v����3fL�93g��S������f��5����{���/��b���k(Lu��E)�F�qr��0��+BM����18p����,Y�w��=��x�����f��]�s�x����3f,]�4��������8\�������?�r��7���������T����[��G�d<z��)S��5*���cG��>���QA������u��>��#C�}��G�C��X�fM��80Y���?�KU������TYY�^�������K'������j"��4iR��&��uj��iAAA2�?���&O��|b�w��bp�J���t���3=����Gc�x��6�����
���g�.]���_TTTyy{���U��y�����o���w�����V�^����&���{����+�s�-[�|O���l��E����=�Xiii��^x���h�j�p��>}��]���}����1#����_$Y0m��*�������'��������C�_�_�xq�n������X�����_�|y������/5z��*o����#��H�s#�F��f��]RR
���k��'~cE2!E/�������m����'�x�O�>]�v}��G����?_��cPRR�����u=���$o��v�����������q|h��!}���m}����0��7�X�z���j���j��s��M�������
��S��5K�.M
�(~\�OP�z5EEE���T/���p��j�gP��l��5�����k���4~!�w��U�a��aC|��'�8Jr�18pb���g������O�2�s�&L�p<����P9t��c8=��9�����~��t:�x�vV�^]�v���<���)�4n���l���UR�d��g������g��8�=zt����~:q��a��
4��7��m��N�/`G��X�������"�o�{����,���>g���P��G�D18p���'N�Xc���{���������g�����g��.2w��c8=����������3fL�P2�0`@��g����qY��
��+�l��<������s_��u����Q����@�������K�$�������9sf�����7.���6R��������LH�'�t������S��[-yQYY��g�-X� ^y���_N���u:{���
���pz2����H�0 ����Sd���(L=������o��f�P2�m)�H�(MP�"-)$�~��m[��q��^�+����LR��x�I����_a��)N��c���1���c|����M�j<}��������,YR�	�+D�v����R�8?��<���'��N���-�����������Qg��o��x�����d^�%���0������XSQQQPP�z��e����/HH�c�"?~|mH.�]�B���K�������:w��w���K)NO�bp�J����� ���Q_��.�Z���k��a#u��Y���-**���1���+k;=^!�N&M���H2��5�*�y��������r��/��3gN�m�R��UR���^{��7��}{t���7�����z��M>^18pL�>=�H�7���6mZt���m�8?j��\f��/����1x��9R^^~l�p�Y%c���M.0�b����5k����3�9����{���&���/�-����]�6�\�lY��}��G�J18p��<�z��~������q�y���������X���������]QQ������i�3gN�:��'�Q���O��9r��U�v��}�����=�/��������&���/�Wx��'����O~����{��'�	���/�Vyo9�m��Eg��������F�c�a����L.����f:1x��=q��c������S����������������~l1xrq�x��:��qc|��.�/�#N�����{�E����O�W��<y��
}$�?����+'M�Uv��%����4(�1b�1�6�'f����_�+�eFJJJ����'�Lq����3_�bE|����������+��D�����J18p��<�-��?�8�����t��c�H"���Kyyy��!C�D������4c���'G5�z�J.?R'�|��
)*�{���r���Q���[����S��\���b�;v�WX�dI���W����f����2<
18�	����������?��W�^�e�k��?�1�B�n�R/��*�w��X�k&�1x��[��:t(~�z��I�Ci�����'%c������6lXT��w��s��u�����(**���1��=z�������-�����GWH����y���@&��'���")=���?�?>����_����w�7��1����k+[�jU\V�s�i��{�����M��bJ{��:t���s?���*/�'c�����VD��o_�.]�������/^���	���9a��-U
����$VS���sg��g�}v��I��VY�e���4v��Q��eeeqZ.N��b�d2��K���W�xzAAA2���ys�C����Y����1x��]k\�%�������x��H�1x0q���r��U5�>|x���QM�>}�n�h2�\�b#���w��������1c��xn��x|�5�T�1x�
��_.E~������Y��U�jI�?n���I.�"N�k�'�����qYYY8TYYYPP��K/���3.x����4�O<���?��xn!�����{�>}��Z�*����}������g��r��c��{����+������/�\\\
�e����X����q��G���w��e����x���4���*���Q���.L��kW��u��������9��4����|��w|��C�V�7���?�84hP��<�!���
�'O�������w�s�N����'\�OdVyu9�o��36q���������0>����sq�<~��E�E��<���1c�L�2|���l{�����*WH?��]�����0<L`�������g��SOU�9~���w��eK4��=r��0�0���Y���(7nL����'})~�;��y��0t��}����N��i���"��������&�k���Rx��r���\�|��������4��'�����v���_�>�;V��Y�<x��w�iju�{�~���j\�"�x��!C��-��i���VO�#O<�D�U�X�b�`������5�����E�j|&q��k�#_~��O�>5^$<�����8�e���v�yyy�����j����*���G�|�{��y�onV7b���9
O����*�����S��P'G���|����+�O���������K�.�{��i��-[�����������/��5�����k���s�x���}�v��m��������k�e]c�#_������3g����<�H��]{��1h���'�����_8�U����.Y�d��a�a��j��
[�pa��;w������q�����?n���K����&'��+�80�G
��\�)����o��Ec��
������O>����n�����.X�`����%L8�f�	��
�L�M�NZ�y�c���8���K}�����& ����abpr��& ����+�������7n�����kk������u���]�f��5o���������]�v%k�v���^xa�n����������N=��s�9��nx�����[\\<`��K/����O?��3�������WTTT�\�t����~�y�5m��U�V���/j��>6o�|�5��yu��q�l��U8��i�K/��]�vQf~���o��1.����Bg���P�����������<��P|��g���?�F���O�������.���5����UW]�{�-����'+'L���Q�p���/������6o�|���'�ip2�3gN�-7n<h��SO=�������K/
��������G�6l���KB��7�W���?=�&MJ=hyyy��mC�<PZZu��?�Y�f
6\�re\��S�P��C����M�6�i�&t:4.�M�4i�����S�9���EA}qq�1<r�m����u��K����b�E���pt����������9��7�z�y������3'��m�����z�
�w�qG�[PP.~�)�l�����\pAeee�����&�t����@�^{m�=z�Q�9i���{����k��?����������={�D+�l��5���������Sz��w��~��U�_�n]�o��E������n���_����f8�|��h�u��aw��%U�F��o����������6Qj��I���������n�Y�bE���o�j� f�-��?���_�����k��[o�55j��D_TTT�l������s�M���au���v������9��^�^�z��1c����o���;�1b���'6o�<��Y���5�������o����=r���e>�`8�����������-[V/��{w��W�_Cu��/^��I��N;m���qg�o�s�9
��y����[oE5���Qg����:�C��M���O�^��G��b����J�n��M��x�m���sS���c�����q��5�={v�g����0o��|���/���e�]:�>�����P����>����;v��7.l_q�a;9D�_�~��]w��_x�����]����a�pt��
�=rV�1��q�7n��I��3g&�+**��R�����}�����.\�W�^G�{<z��o��{��G�{����Z9j^YY��s�Ps��g.X� �+���;����(�=�����|P��{��^84o���}��7��#FT/���������~;Z��z��]�����0�y���I?���R�������sO(�������fd��	��K/�4�����3���"J�?��������6�f7�pC84v�����_�����z+�_p�i����U�)�%��1��~��p���/��kWmW(,,��h�>}��;v�v�������g�*e+W����������O��\sM�������:+z��w��6m���W_}�J��!CB��~��Z����1x�:w��m?����N?~|��������������R'}���z���U>|8Y-u��_�*�
c�)5l�p��u��Y�f��o��qO�T��w��,���h��}��1cFZ�@N�-��gO�-5j�z���Ge�
w�u�_|u<x�S�N�������~uVVV^~�����{�)))�:g���h����
�kF��\q�;v��zV�Zu�����)S��e�h���C�������|��?��CQZ^VVv\���������a�
\r�%qO(e���5�A-�{����a�i������N�:t��7�vO?��_|19����[�l�u�Y�^{��������Q���''��������p(\���������Iv�������=�q���P���������u����7H)���~8u��q��kn�����j��}�-�5k���|����iS��w��]x��M�6m���m���l���e�~��G��7o�y�5�L�6���y��wn���s�=7\�u����w��m�N���5���~`a���^Z���I@������0189L�!��+�l�9%�=��)1x���j��{e�Ve���u�������}(�C��~Y}?��u�pM���Gm�����N����8>����!����3H�I��%q�������N��s��1x��,����Wn�����;��,�Z��%�:���l>Z���^�r�����~�Yk�����A���������kbp8���s���3���p���^�g�����#��&�\��q*�_y���l��<z����i��xV���tI6��<C��@�>���������O�g���3���p����#�18�>1x���3D����b������\��<s��"���)�����=��&�1x���!518@�<s��"����Ib���g�������{?]�����~�����:���V#�r���#�18'�y�������6����~�U��3G�!bpN.bp��%�1x���9�����<s��"�
;���>w�,���d��~��3G�!b�� ����1����7�$j�vU��t�t��3G�!b��`{���\��6����E�gC��9thY|�b�����������bp8i��3g��C��^�4��c^a��v6����l>�U[�_[S��6j���'��I��:�Ce�{�������}������`�������&g����_���?es�1g��@����IK��aNy=�_����������\�	��3D�!�wV���f�=�����L��1x���s���3���jbp8b��!�1xN61x��<CM�C�3��"��&�P�g����x��s�<C��9���jb�5181x��s���"�18�&1x��s���"�18�&1x����r���������p��g�G;+&�~8��'��~���q��:���Td�����4.;g��i���������fi6��X��|N:b���O������d����5�$����\��I�\��9C�{M'18|5��s��$������,�f���������lhV�����~�@����I�=�X����V�j%�{��}��F��t����?��i%Q��K�J�����@��`e�bm�s�= wLX������m��r���?��_c<�'�)bpr��l�����/�Z��������~4{�F����7���1����9�r8_�iE|���X\�����}^�jKy�v����d�<7���:���8T|���
O���B��<'[6c����������g�tX��)����m�<���	����#�>�8��_�,�8�`�����l=��C�|�b��{�P��o���*��d �W���/k���*����g�H�<s��"�'�1x�������3G�!bp }b���g�H�<s��"�'�1x�������3G�!bp }b���PP��������^?�(j=g����UTf��������s���\���y��{:$�'�b��lbp��/��?�-�����;1x��s�r����m���5J�N����*�ynEi6������L�gJ�9�����ysLX|��_��v����+��M���:�M�d����~
{�p��<�Ni}O�b���/����{:�|>�S9��C�l?~������l��6�s��s�Vl.���u������&��$���M+���;�����Abp������~��'���t2H�3�������<'���Z����S����R���x0�C������=X1x�*;����l��'�w�?�P6�^�6{�X�UO�UZ�!j��s+��}^1x��-�����Z{��	����3D�!bp�N��"�18P'b��g��1x���3D��<C��"�D�!b��u"�1x����:�g�<C��@���3������Ud��9����EQ{���l�coe���1x������N������d��1x���^�������^8��i%Q+���UJ�l_���/�f�_�
;���
�eu��O/���
'�Ce��������x���*����.����I(��C��IY����Ji��8Q�����=8:18�>18'�io������������������7n��A�k�������x���^z����~�g\y��������^9u����Gg�uV�f�����t��y��}���n�z���_t�E��z�9��s�
7���K�3���Ko�����;�i���Z���/~Q�����y��k����_�������.G�5k��C����*��o������d�=���6l�����?�a�-���_\PP�,[�z��g��}��?�����k����l�N�0�Q�F�X�]w]�V��v���/^|�'�9s��h��q���
:��Sk��;u�u��a��]Q��M���i:��M�6-��{��+W��z<x���������qYyyy��mC�<PZZu��?�Y�f
6��M����I�F�M�:5�������e��~qq��?(NF��v[����.]�k��

7n|�)�l��%��`��P�TVVF=���=��MK�}�����7�W�3gN�m��m�7�{�������������&�t����������?z��:>r���c���m��O�81�w��������7������rq�h��C�U)���;���}��a�_�~U���[�[�h�"���A������%K���=:��t�MG{���b��]��]�V?%Z�d��QG����UW]U�l��!������E��K�5~3ZK��?L�={�D��U)[�re�H�Q���W[~�M7���#GV?���~���������_��z��O?��?�v�7ov��YS���K.	���������/�-[��^�{��(!?p�@�{ ���w��!�O�>��)=z����������e���J8��o}+l���F������WFcE���9nt�6m�T/����m�Qo��V[~�W����gW?�_�~��]w�������x�z��%K��V�Z��D��g�}V��c�����q����^�������6l�n��!������m��
���
�������Xi�����5�U�
���t�M�T[~��7��#FT?����u8��s�����������^6k��p��+��vO;�����T�������7/�q�~���}�9�T/��kW����H}���J'�$M������o��QVq�
7�Cc��
��>�l�;�I�>�h8t��wF�������`&UTTD	�G}���_|�Em��|���B�\�����j���O������*�eeeg�uV8������������M�U����[��'�|2����{�n��=���\�2z����"�q�6m���W_}�J��!CB��~���������?�6l�n��d����������+��_��m���I�&��r�'�|���7/�]t�E�NVFK���W�����;wN�m���h��}��1cF��9����_�'���+v����Z������S�L���uQ�:��e��E=�w���:��_�e����_~y����{JJJ���3g6j��I�&6l����h���C�������|�q��z(J����N�����q��$4l��A��\rI�
��������:Z�����������N�:U�f>�������(���������'���_��e�(3���k���o��F�M�<9Y����g�n��q8��u�p�����)|�����
R
q����}�����7o��E��\s��i�j���Y�~���y����]�v����_�N��s��>x��6m��e����v[�yR�����;��~����.��u����o��m��`r\��=�4n����k����\x��U.�u��������.:��S�9��n����^�>zqq��.����O?��3����+�^QQQ�r�����~�y����i�V�Z���X�v��~��Q�F��g�yf�
�N�U�w�}a�u���+o����5W�^�{��g���?n��]�����'�����e���f��u������j��q����[�����&Lh��Q8t��_w�u�Z�
���7_�xq��9i�����v��_\\\����?o����I�R�X^^��m�P�����F����o��Y��
W�\Wv��)�u��a��]Q��M���i:����&M�4j�(�+**���B����O������A�/��b�s��7��g�y&��s��	em����Fw�^�B�w��4n���SN��eK�l�����.����z~�����N�:U��k�
��G�>��kk��Y
4������W_}u�\�pa�s����P��_�*�����-Z��^�8qb����c�+|�����/_��n�:�.Y��J����C�M7�T�[�k�����/l����������w4h�b�����o�>���A�-Z�C~��������k��e��zk84j����g��h]����*e+W����{n��������
����{���%���W�3�����������#F8p Y��y�P�f���W���K���s����n�)l�9�z��>=���a{���a�e����v��%�U&�9x��9����y����*��|;m���;����z+�)--�:�o�^��:t��M�oO�>�zY�=�?�����L�MHB!!���TX���VEG���`�RD�� �(S�Z:>'��c������_�"e|H�(� ���g��;�"
�pM��V���o��}?/���s�O|1������������s�^��_5���S��b��/�8)�s�����y�6o��a����~�K�.!��i�h�<����>�,u�}��
]��M���u�s��MM�4iR�:th�~����v���:������r��|�
*++���c����K��***��Zt���M�6q��!�]w�WU�<��o^
>r����v5�^��<����X���d�u����G���'j6h� 4�~������>:t��7/l0 l�y���i�G�]�������j�KjZYYY4
�u�����/�1U���ZD�����k��Q��O����s�<��c���LTQQ�����{�y��������_�~���{�	�7n���`.Z�(�[�jU�q����l�&c9pGyd,{������u��������������5G��&LHJ[�tit]wEEEh��934{�����{��&M���7�x#�D��,X� )s��)!~�9�������n�����/��"���{�
]m����gOb|��]�R''N�"����2���3��N�7���aC���322�/_��6g�����}�xd��q!2d�����������5k��h�>�l,;������������C�n��1
n��e��!�����'�D�����]������w��g���������r���>�uQ�u��v��(��k��l�2|��xZ�������������{;vl4[�{����uPt�w�.]�)������	9
48��c{������
6|��'3W�XQXX��4i��w�h�����x 1m��m'�pB�
����G��]322Bs��IO=w������UTTv�y|���h����{�#����;vlIIIAAAnn�QG5f��U�V�f~�����M�6999���g�}�+����V^^~��7�����}���k��{}�%K�4�y��a�EEE�F�Z�z��{�@���G��7�������z�O�>M�4���=������i���}~���?�����m[�~�f���������JM��}��7���s��
6j��������;***R3.\8h��-Z����n�z��a��-��W@��C�X,��S�cS����L�>|x����8��cN<������l����u��^�������M��t�I;v�&�o�����/���K�.!�����g�=zdee���g��g�������gffF�u��'�n�:l������5W��-Z�b�>�`�i3f�i��7_�ti��e���C���������'�W���Kv���y���������c�#F���={���E�U�V����S�i!��������CE������'���-[n���@_?uZnnn,���/��VRR�f�����qc~~~���(y���C�C�IWt_w�u!>x����n�����z��}����i�>�lHk��Ueee���KCd��I����w��������R^^�X�4k������V/��sgR����<���Cs��IIi��/���������/4�����\�~x�Z�xq�,**
�_|1)���4����_��
�!g��u�X,??�i�5�=z�H��2eJ�:����ft��^o��%����~�?�x�?>5-Zh�������y4K�m�����K�F��T�Up�Z�bE,k������o���s�=w��#G����~�x}�-����;���=���u���F�����|��wR3;u���x�������}�]w���3&t]u�Ua{���a���05m����������K�����|-������������9rd������<����k����k��I����g|u�h{����i�sE��G;/..NM�?������e�<�L4�<x��%K����s�����Oo��Y���;J���+C��K.I���/�]O�7o�����>K����o��6mZ����[��;wnj��I�B���C����?�;v����gdd���+WV����;�*s����7���[+V�H�/^��^�z�X��g���
W�GlW�j��
��y5x�\U�|���*�og�dU�����x���Xl���a����u������6g���u�q�E�hq���~;5����]�����w�ygj����C��q��������5k��VVVM�o���^%��a���b��.�,l?������Lt��7��!C�D�c�9&~�D��{����_~y�>�I����������q��o���E�B�U�V�B��6l����_�������&M����Y�srr�m���6p���u�m�E��#G���	���.]]�]QQ�3g��^�z%�����I�&���7��"�����`����)S���9���m^3��.� ���&�W�\Y�~����?�)�w�q������Y���]�^��>�(���7/��m����<13Z����/��6l����X�|ybZ��J�����q��%^m���())	�Y�f}�@]��2##c����w���}�Q4���{����(����I�W^y%��_�>Z?���.��0�w��5��c��(8{���������+W�3�uQ�u��v��(��k��l�2|��xZ��������h0�v�;vl4[3���������5k��g��]�fee���G��$fF��AII���hv�?�A��*+V�(,,���{����333x����m���p�	�Z+=z������#F�H���s�!��w_8�a�����~���sss����w�~�M7�u��9s�����q��yyy;v�����|'���O����M���������>;~
y�����o����$�����W�^3f����,Y2h�������5j�������l�������Y��2����z�����M[�������z���Gv������s����s��zUY�A+�i�����+g�8D~����VX�������O�����L������i�������s����VX��L����5�48�_L����5�48�_L����5�48�_L����W���{��u_V��������/{`�A�����?������i��S��5_��Zj��U�>[~������t���6l�p�5�t��1777//������W^YVV��3~���7h��M�?�������m���_�~�f������SO�>����o�����;7l��Q�F�w�w�QQQ���p��A��h�"''�u����
[�lY��:k��e�[���b999�;w���cVVVh�l����k<m��Q!XTTtl��&����_o��qHn���I'�v���r�-�i_~�e�.]B<77�g��=z�����3���gOb����333CW�v�N>��h�yyy/��B�V������s���X���O^�fM\�re�N�Bp�������'!r����{�{�����C����Kv���y���������K��3G��z����|��U���!8u��xZfgggff>��C�1O�<9����}�����������b���_�~}b��g�
�����<����"�<���w�����:$]�}�u���������u����������>o�V�*++����^"#F�Hz���{�xii�~�b!o���������|����J&�q9��B������/����6i�������C��� �D������}������]�/��EEE����/&�����x�����B�E�����;v��"����C�/���XRR��zC���������~�?�x�?>5m���������*a6~��mIiK�.
�����W�!n����X��s��G���_������C�=����r��wn��9��yyy!��w�I�g���O<�����������1c������*l/^�8l���_�>�!O��/������A�+V����v�f�b�W�--Z����+
�����g���k�����3g��]{������������S����z��jy�
�y��F�eff��;7��9w��}��y�7o��a��O?��K�l����u�BZ�Gi�}�Y�������M���u���"n��I�k���a����;v��P322B���+���P�M�6-+++;;{������������2n��MGqD,������������j��#G~U�����\���S��M�Kee��q�b�X����}���?��������O�l��Ah������G}t��7o^�0`@����;S�F���`���������VVVM�o���*�L�� Y�gb9@�������b���[�l�~=v������;w���sL�>��***����{/4/����}0����/t�s�=a{����t�E��x�V��k��~��_�b��]����}S���[��;q�����}�F��#G���	���.]]�]QQ�3g��^�z%�����I�&���7��"�����`����)S���9���?/�CNt9w�6l��M9��{o�i����={��v���:�8qb�7o^�Y^^��-ur��G��\������X�|yb��9sBZ�����h��!C�$�UTT������Y����������dff����3-�
:t���Qp��-#F�����O>�$
VVVv��5��c��(8{������+W���3Z�[�nk���"���Z��-C���������,--
;������c�F���w���bP��t�M�X,77��o��c�E�a#'''$7h� �{������
6|��'��b��������I���{y��a;33��HL��m�	'���n{����k�����1bD� ������������;�/�{u�UW��i��i�������%%%���Gu��1cV�Z���O?�4t�i�&''�������~��WR����o����������^�z��1c��\�d��A��7ovXTT4j����WWW8�.\8h��-Z����n�z��a��-K���L�>=333��k����On��u����{���=48 �V�������|����HEE����c�X��-�o���������Kc���#���{�������
�EQQQ,{�������!�����
������m����.]���7O����-^�8��v�_�>�!��y�������b������]�vE���W�>�������b��;��7###��\��*�:�;�Z�S���r5��5k���t���U��*��������5k��UVVM�o���������>��-
�V�Z�e`P-���c�����S�L	�s�9'-��j1n��X,6d���`EEEIII���5+]��v�����X,VZZZYY���7�;vl��o�~���� ��s�fee�b������{��&M�����T�%K�4�y��999EEE�F�Z�zu����M��-[��Q�A����/N�(� ��n��M=z�(,,|����=�:���r�������5kV��R�(l�y��GN:���}�{m���0aByyy�GTG�����������#��a���]���
[CV�Z5x��p(h���i����Q�e������u���������SO=���������m�N������kw����{Du��9sz��YPPP\\<y��]�v�{Du��%K�>���M��l��g?�YYYY�GTG|����kB8����3�8#�'�{D�w���3����t��R����o�����oO�@��Y�f��f&�z�]�6*�	����5!|����CU322rrr�
�v�i�Z�w��wfee�z���F�
����[��q�z
[C^z���������{w_���O?���c(ifff8�6n���?L����={��w�y����G}4����?�a�����SN9����q��{5�������/���i����3�y���{\@�-\�0:�����K��R�(l
��eKaaa(�?��?�	�vo��v�m~~���j��Y���&l���V�!C��z^t�E����p��������6mZ��V��s�=��=z�G��|���?��:th��V�)l
Y�vm8�����{������}��k��Eeee�^��[��+���q��;�/_��A��kW�a��U��o��F�GTGD������O>�����p�
�������=��m�����M�6����V�X1c��������������n��~�v�\����`����u�m�������=: ���W�d&l������_~9^X3��n��=yyyg�u�����W���G�����n2a[��zE��&��?�3�a!]���������v��q��-�`�������Q�4��S����_�"�����=����C(��������5eee���o����m��=�:�����c�9&�k�C=]�����vk��m��a��Z�bE<�l���
�ni[m��k�P���g�#��PRR���{o|�w�y�v��������^
[C����P����7yyyf�k�����E���r3�������'��a��muQ���8deem��11�g���5��3�H����hF���cR|���oZ�T7(l����sFFF����/�<|��>}�<����}��V�]v�e�M���|p��W�����3�������~�

;~�����-[n����O?��SO�0a��5k�5�����N�}��g�����q%�����Y��#G����3�2�:��W^	���%
�P���
��8���N<�����8l���(l
���~V�^������{�LxM5jT��'�|����
6�wx�����/KH����qceeeZX[)l5��{wff�G����/���������G�|���]v��o����^��`�w������8q����:d����\�MakN�v��a���������E��iSY]t�E�t����G~���G��qGyd��U�����%����w�m��mba�������q��Q�LG��H�����n;��������o���G�O�:5-������P��/�8)������Yg���Q�[�n
���F���&l��������C������PZZJ���O�����?���M�4�����=�Zi�����W_}u�L������:w�����4�#���UVV6h� �O�Sb������O��]��������k��Q���C�&N��|��'222b_�&/>Ks�%���M�)l�9��Sgk�N��]�v
G������[����3q���)Z81>[N�B%�7o~�m��3�P�-ZD�^�V�J�Pk�h������_|�E��m������`����-�=�Xz�Z���=���I���G��k����Q����W^yeR|��9��>�eTu�}��
x���&����B����N�����]�v
8���o�GL�V��9����
o�	�v�/������f�Lx���4hj���R
6���~��'l�K�n���4��R��5l����wk��������k�	���;���K���+V������
��t����n����y�m��7m���Y����;��3f���s��
c���N�L�����
[s����P��}�~�������;q�{��E!�t�-�[o����_|�Eh�t�I��������[��K����W��
����gO��^x!4��_�5###q�v���C�
	��������7�Zf��{�g~��,a}��T�/n������%�@8����f��}��'���^
�
��t
��(//_�zubd�>��NakNR��1�r���;�� ��^�z��w^<���[p��u��Nt#&L�
����$]����_��c��Q���i]��l��9��s��N8���������G�
_��6m6


��=�V�>���v������.
[s�n�M*����������{/)��G	�F��a��y���n��������MKJ�������C�K/����R�������}����
�����{l�����2��(�o����x��8I7	>����2�Z/���j�]o���P�G}4)�G���z���oR��&�����/O��Y�����`

������5�\��A�_|1������u&��CNN�^O���N�:�����7n�u�1�@�3&�p/�h����n�x �zm��u����w�������W_M�	�o��eZFX{M�>�o��]�v=zt~~������;vv�a����/O�k)��!�g�EgS���o���^s:t�r-Zt��V����{�,�u�]������6�{������s���B��O?=|���~�����H�~���j��K�^q���{���^�tMW������CR0|�
�RO�za���.\�_l���_ZZZ���}���
7�p�y�]r�%��+�?�����	��#�8b����M��d�����u��m�7�m��I���C\�j��qU����+l�Lx4��~���d-���_V%��.�����/Ds�
4x���R��I��������'��*a�6|�M��#�*~~)��������^��a����;Bm�������V�U�����\�dIjW�=B����T�0�����o���[�F�!���p��e����3�8�E�{�i�������z�����u��[o��E�{����~�7��;����Q����_}jB8>��SN9���Y�������.�n�)((��Z�EEEI���v�����������������45^�P�}\�����h<��_��C8���D�[<6>a���O�D�l�������x�����6>��[7�
�f����S���=��)S����9��T-�Nx��v��7�|3�AU�>VK�.���&N�F]�a��3�����&U��R���_'��rJfff(lR�����}}�����yGUutm���ElXcAc
`o����
���b���J�5,��[,��"Q��,��f���v.�^�������5�v������;�V���0]a�-[�������������U����
k,��r���I���S���o_�S8��Rp�!c���=U��V&�P�BBB��i��M-$%J�8�S^+�$�8;;kf��3g�'�����O��7�e
*'j��1$"������N����VR`�&M�����/�#k���={6�S:t(�SZr���{����u+}d
�a2*�o���9s�<y4�N)A��������2KK�K�.���lX]���B	gWA:Z�`�C��g���5kb"�]�~}zS}����{�zX�eR-�a�i�1F����5
���:v�(m|��Y���e��k����7�-^��T<LLLl���w����#U��/6����5�<R=J���o)�5����X:>}���G44��CV�/_�(�����>���k����)S��e9c�&���d4=JxXX���;��c�D��+W�u����j�����W�V-..�ZbbbJ�*��3fh����k��%�o��u���h�O��.k��8{�,<.777ql{}���-tW�Y�`�n��-�5p������?�1c�������a��������lX=����*����G���GGG�����+�/d8���e����:d�3���R-����(����e���������������t)f_3������S��3g������u��A������*C����5���;����U/�g�H��s����c�~��/^��[~������-��4T���YCy�a���4�v�����������v"3V�*�����c�o��uk[[[kkk~#&?aGv>���������
�s`����}��xz��ul�@��d�Dcbb,--u�<Z�|9�2�|��&����/\c���f�^0������� )3,�
;v,��wo�=�4i��r�=
��,Y211QO���R�B��_lX�0�1�u������:88�����WXX�8���2e5j�	�F��_lX�(]�t�2eD�3=J88r�H�*U�B��=5�y0I��������U�JDDD�������m���}%���}0KeU��v~����#�g�.[�P����v�*���30N���e���G����>|x��AY����<����V)3,6,<m��9�����3~��3g������������C����^�	��
��3�����s�Ko������T��+W�XZZ(P@y��UB
�k�.v�0���q�����'"��/�fT�f�����������M0�����
kF9;v�(_�������k��]y���Q����W4h`oo�5k��u�r�A=(���������#����'I��W�Add�����,<y��T#U5k������(�I�/(����i��7n�d������9y%JxR�����o�����S�+|���0c�R�d����+W��-Ey�z���z������P#��H�aw��M������R�����K�.p�������]���0�g
�a��P�����~��	�_�?����h���;;q�D����
1��g��quueW� ���;[�Ns$�q��=8��iccc�=�E
�/F	l������Q�_iN\\�����G�\	g��e���@�Q��d���vvv���B%����/H<{��h<~�x�������W�^M�6���W'��?�b
\)3lBB���;k��������L�"Z�={V�@����:t���+%I�1�K�����0_XE��/W�����~%eU5�6��f�����A��6����G�J��>����:t�W
KR�1J`��)�������<|�������~%��������%���#m����a�B�
X���UN��=��'>FDD��8j�(a���0u7l�@-;w�d
\?)3��78`�������Q�F��(�I�x���_�|I����y���H.�L-o��Y�b�yF�0�9�[�.��+W�{ ��S���;v4�@2l�t�����2e���A�f��d(^�~����9s���o�{,
���	6l:��W:���	������������Gf�������{�p��J�l3�������������;6� M����{��~X�`��[��=yw3
6l�!;���}{Y�����S����a�/�[�nY[[{xx�y���c�P ^���F\v��9s�%C��M?��k�`��i�HFc��et���h���N�a�	�����L��.������{t�F����{���q�T"S�I���� ���,Y�Vm������`��w���as��m��0c6����Y���m�����+W6�@2l�t���G��������?7�X2�>}*]�4&�����=���_�6���+����X�^�f���J��a��
�&����/N����W/��9Q��V����Q�{�.�G�R>�<c���dc���;g���U�`��u>L��
����_R��Y�6m�4���0�������#��{���{,_:p6l��<c*�[��uT_!l�t1��GsD�E�
r������3R�-��lX���{�����3�_��_�y��������W
�@����5i���������S�]����Ij+�p��5�5k��d����=�,)\^��K����Rs��
����_���O===3e�t�����0�b��9��5kf��|�����0�W�~��eKKK��\�<ma���'�
�������7r%�\	o��)V��s�����Bx�J'��
��aB�o��F���W:���Q���?�I�&����7of
\���#�5��{�.��c
\��6>>�B�
��k%22�eWWW�/s�=z�������r�J{{{kkk��(������S���ab�����l[����'(���3&��0�ABB��?~,Z�(�#G��fH*e����2e2J	���;�J�$<q�����y��)���O+��������W7��T���/)��r%���{4r��!*�3�@ �R����v���/:;;�P��p��b�c���r�?�={�l��EEE�E��5p]T�T	�p���F}K���A)3����.�
����(�|��
GGG�����...�FLh�������>���W"�a�c����B��9s��t+D�lgF�L�:��������-,,k���*��ex�U��={�����>���2<�&M�����eB����w��E6������A��� �Qfu��1��n�j����(�C�A��}����T���o����V�����������������������#��XlX������c���l��sg�_a
\	g��E�P�p�>(�
k�JH�aYW����������<4������{`��W��`�*�n�������
�d����+&&�C��%��X@�m�f�2cF�<ybeeegg���yppp*��}%��O�2��<$**���	�T�*UlX���q#������?���y�����r��c�pnnn��7n�0������Ca��e�:88�����k�$�����y�=�`O6�B�U�y�RB
������{ooo����+�S�N��+�]�v��3f�P������`
� ����+��gg
� ��-�a6l��?�'N<y�$]G��u�����s���)���U���B�S�N��#��0�����?6�E�)���M,���K��e�R��P#"�m��y��	

;v���^��h�B��
���g����TX]�m������x1V	_�t):����cS�����K���o�zyy�P��
O��������Y����Z�R��
���p����z� ��/c��ml��bb��K��uH�G����;99�x�B�W��?��C�����"X7��O���=x���������;r�Hs$�a���0�������g�>{����s+��D ��8�����1cv4*��P	��c�;��P\�~���
�;|�0���g2)]�V��a�*a���9r�X�lY��y~����T������!Cz���9sf�J8�=zp�w)�Z���������@�eGQ����� QQQ������o�����K~�
k�����Y�f����5�y�D	��KFZ9�E�5`�
6�{ 
��0,<s$���M'�=
�/^<11��c�P���������FFF�{,
����1}�t
����A<��������sg8`y��Q��32~��W���w���3�M�6F��~>}���qc�4k����O�>5��2o��m���8p`pp0]Q�'�<|��V�Z���aaaE���qc����R�� ���}��1�p2lK�(aii��aC������pF;����+�����3X6�1
�	���VVV�1ma���&w����HFc���0���o��d4x�bF�E��2S�d�����{8�����vvv����e.���V�S���7m�D$%_���7m�I��oO�g���NF�u��0����E��s��8��JN�<Iz8�g��a%<m9{����Ljooa���L������J/��Y�&k�����vLI���e;�&����0l�Z��=��6��w����M��9_�ze��d(�����a�;v��c�h���0�&"�u�N�X�M%����%�=*k�X	O�]y����E#�i��O�:w�LJ��+�=us��y��F�������*U���s��)�
HO������%K���<����~�%e���$�X	O���g��a���5��G��=�Jy��+b����#���u��M'�F���=u�|5��o[�L�� �1���<|�P�bT1GF���0���o5M�4��~���l,���+Y�`�������;�K*
%������7������3a�!C�h>z��i�|�X	O���D�%���Sf���t�*����Q�F0���{5;v�������X�101S�L�a��oo��|���\�re�N�/Da���Zn���M'^�~��������[���Nhh(V�NTpp0���������Bx�b���]�v�(QB�7n����Jx�@�����5��5k�$������l,���}�t��*T0�0����/{��EW����,�#V����K�Z�.MN5�@��9/_�l����Jx�����7���={�8TU��1`%<Mh��-l8j�(�O���;�����)y��=�^���a`�B��('�V��S�����B���y�u��5�@�h�8��7���y�&v.77���_����*x�b����X�k�����C�C��E���CX	O==z���LZ������`wC����O��x|Z?���+T�U�T�������Q�&����z<x@�t]�1  �^C8;;�N�21�����{������c�1`%<��[�tppEC��y��0�*T������A�p����u�J�S�l���^5r���8Q������={�,���j���j��A���7U�6 \m���~�	��j=����l`j$NT��}�����=6�3k�����k���������/��
Y�r%~�
4g�v������FWW��/_R#+�����{$*v��E����������__�hQ���WN||���G�u��qi�������#m��7o����*`XL��Y�����-R�O�0�Y	O=={�$������O�w���������_~1�������G����4k�.%���kt��.�_��B����T���X�X1���_�}||0��2������S�K�o�>|���7������S�vm�]�v{V�^=CCCM0*��'
��w��-���j"""g���>|���������'����5�7o����l�2�=�9B���H1�c�(x_9r�����������D�B��_�U�����H�"��111�K���)�����.kg���,22R�,^����>}��^%l����^��W��I��D��C����&%���� d��+WJW�X�_}�%�?.�A�V!��!�����p��0������X�/��^
2~�x�����|�#]JxR�g���
���h���#U�e._�L��+W�,�������3o���W���������x���x��A*��-[�����
����2o����	�^�U�aOX�����L0<���QVEE�Z���Q���
k��a[8�J:7m��g�����R;�*�s��A�&M��`l*���;R����W����*�����|U ��� =s�+�%�/_�w��������m����v�*�6������u�������o�!��>�(Q����
�V�V-i�Q]/c�R�Je��F-Z5p��8>�l]�����Ggk�m�&��9�;v�0�����
`(//����{zzR�+.2$�U��� ��S6�~��]�*A���-
������]�������:�aa�J�*u���,�5����1H?~l����%K�U��p�B������
Q����+W�CCC�v����?������R����TY���Ua�F6����:������J���|i� Xi>�\	G�
����*�z�*~�AAAR��.��~��)�����0_����� �j�����&L�&X�SI�	C��C���I�urrB�K����#G�b�{��S�m��3���|�l�{�����l����5k�d%<����3K�,����~����m����Dv����tZP�z�a��}����;88�mk����W�X�N������#L`V�S;i���{�����G#���-[<�V�I�&�w�_>O�>����O�Sc�������Jxj�\�t�^�+�/^�.502��[W�`A����J�p���A��4h ;��Z<����(�lX%PJj__�#G�(��tf4Ax��Mz	.V%2,f,;]R:�Jz�����0&"�a�$EI���a2(.\�p���;v`q@���T�q/��i����g���xW~����+��+<X5w���/������o��a��I�j�����wZ�p8�w��5�0�t>~�x��	��p���
ME���������GIve<j�����A8��W~������.%�w1��c`�]�q�F����R��1�|�V
�v�D�-��_]J8;��?>mO�d\\�������\�K�.���XK�:[I����;GS������p�(T�� X��J{S����=���������ogg�e.v�A��Er>����?/4pZ
��]���)T���`�}�����j��x�?�/_>J����"����Z�<>|O{��i�������.s��t�����3E���e��/�w��!3f��+���v�y�b�
�"M����S�rM1�L�4���z��-pk�7o.j��;��L`Nj��Bg�����1j�aTv�k��M�8q�����&��@��}��7n.\Xv�H���G���	;�Ay�89r$V�+W��z�j&��c�������+{�K	g��X�-[FB�V���a*9y�$�Y�rei������-[�������K����9"���K���;Xr��=��C�9::��f��)���J8�|�:+@��e���/n�O�2E=����G7n4�x����/---�W�.Zti��r0QK�.MS���&O�<�u�t)��V/899Y[[W�R�B����WtVhj������E�5�������%L�>�n���=o�<Y]J8�vL�Qe%`��_��K.r�t)���,_��4�~�������kW�q�����O�>�n������_?XO�'���4G(��vy��������|t��9�c����G�Q~9Y�pV��kQ���m^�R �������}-[�L���G�f������%\% 
�k��A55p��_�~���f�����+R�l�I�+W.�y�����p�X�h�E�����������g��������C���[M>XU�����~�.]j�\R�L�2��������+�F���	0��c����K�A@@��+rV������!!!;v�8qbdd�hJ��?��Jx�i��l�U?|���6ZrCCCM?6U��>�V�~�������X�]�y��j�.]z��
�_l�B	�W6�������������7o�}
���6�?������R��9�v�����d`�?N�]��������C�����k��3g��7����+'QT��W������O����%V`Dm�����eii�a���d��[�n4Kg������p�����&���\(dI��"}�c���1N�2V���?����A��5f�����D^c1)�:�3777���W3K�P�6lh���	vL�]H[�_�s�����.\��.�`_�T��6c�sV5�{��S�N���,dV�S����i����j��KI��G� �pGG�.]� L�����,�.�=
�K����@OY	O=���������C`` Y�l��/^�0����A%�z2����~3�8�1
aaaE���q#���>|��K�����Q��Qvk����\(����_��#Tf����>}�t��A�NW���Y�4�'��~.��1c��T����;w�t)@Q��QgWNC�FGG�\�����y��Ac��E�*���M�|�a��p��4�6,�4pb����3g�
���{�J8�����u��������ge���UU�Y	O%X9�������v��7/�CIg8����O������c��G	/W��g{{��g��c�����#Y�d��d��'N �"_�����>���z�X�@�/e�.]Z�T���s���:t���S���1W���.%�Z$Wl���9��0���@�������;#G�l��Q��mW�^�����������_�pA��>}����VW�|��,,��+�|�_4���"wA��K�.=p�@����pF	���f5�p��u��u���a��08�U4����.=�����%66�E�"=5�5�������e��+��B�1H[4.��4����W...�����'{�_	g�3u�T�n��q�F*����x��E�(���|���t���9J��������M���_��p��������WLEQyA�{��=���~��(�.^�~�I�7o^�����:��}{�(U�e��'O�����X�"�.{���X�b��Y�Odd$���w�t+����4h��E��U#�dl���.\8f������F=/�	\���xY����===i�-]��(�4q�Dj�����$���O������ y�r�_�NG
aO�[a�G#�Z����b%<e9rd����`aj���3Z�\0�\u�����e���yV�]�XZ�jEw��s��%��bX.d_a%<e�c�z�r���Qhu���h������skj��������@�RM���K������RU�X�|�����3��
j�����I�&Q�_�LJw��x�bi��k���s�d���0�u���N�:�*�.%�Q<.��q��5�'AJ���6��G����n���w��-�;F���'9����z�			���]������������$���]�v���p�a2<�����IE���S��4�/8?����^���'�se��	�?k��J������U���?�"_�|��m�63���r���_��Yctt4�K���NKV��������?������#�Jxdd$���\�z���]z�\X�\��K"gW6����UK3�Z�t))�u������J���c�zR�p����|���c��4uaC�o�����%Z45p�	�o��<yb�Q���o�6m�������s�OJv(�"h�����7����-[�����{�_4�6����	��q�F*oQ�fMV�SUF�J�j�w�����&K_�2�8pk)��QX�N�h�n����5 �X�z5���������c��A<_k��uI�q.e���J�a%�a�Bf��a���r��������dE�[�b�[�n��7��={�2�/���H�t��^l������r� �><1��Y�����BB�9���k��'_�_ h��i�����KD0������������~��U�<}��p���u�o�~���S�N��YR%|����`�
*�k�_,���\��V�BK����2`���HB������4O�<)���M�~��ivJ��?�����c�&��1��1�Ho�o��Y�� �p��=����M55���??�*U��o�j�U�&M`R80�+��0 �`�<h$%��`���/bN�>M{�.%��>0J 1l�
|��������:L��U3��6y��qHHE�*U"����#�������������"�����%\�������5  @����x�r����2M.^�(
x/\����������L�4�}����3����f��M�:�����%�?~��w�y���%E�P��!hU�G��'=����G�[8]��(��A�9R4��
T�~���@i�M�6��/�qD������X�����K��b--P��V%|�������w�v����/��c����1��zP��uXW.��;w�?�V�f�����k�/�=�*�����B��L���i�A�
��5U,�X{e���{w�����%KD
<0�`�'8X3���d������s��DEE��Q�6 �-^��3f,Y�$6}��P��g��YS]�n~~~XQ>|(����\�a_�x����a���<��&��0E[�j��J��_	��b�0L�B�|�r��EW�X4��0`����&��k�J�(AG��5#E�{������ux���f��h�����;o������1��3�Y�x��F����5�G�9r������0>�&3o�<��TH��m��}����)�V%��
�G�z���������J8�v�v���J8��=z��9s�L�B:f�|��=��|��?������������j��h=)Y��b��d�WWW��R�J�W/+4��[	��zdvvv�>���kooO�cbb�.3�/M
t���G�1����d��I��$ZO�Qp�����X k��p�4���R����g��2cN�:���n�D��w��N�J���B�
�2yI��9F�&D�[�lYXO������*R�+�&������=z$Z���/�	�����MO��!p0�HU�P`lll�+����p�P�V��v�v��V�S��W������@q�����E���U�V����wo�����������N|����&,Y��L�S%�Q-�����kv���3��4i���^-��>>>2����{��eC;g�P��`���'�G�������;g�1����hzA#����,��K	g&�s��1�gccc��"@ =����a��#G����X��=R�!^��5;p��V�M)����OJ>���GJ^�����O?�n��Vi�+� B�
4����p��n�1H'�1HCX	Ooz��I����w�����1���[GD`a�|PP�nT���,v���$����-��[9�.�>}�%K���LQx�Z��	<}�t��B	5j����.<x@e40
6����qc����������
|	s�W}�m����'���w�����}��u�j����K��}�v����FK.<YO��cAx���YF�0�����B]�f���h/�]����W�CDD���U�<y�;N5"�%J���jvo���A�~�*"eJx����rV�\I����&U���i��i��T�	N�y��:�J��4�B	�bmI��g����A���A�b%����f��8}�4MB�o###���Er�z�����o�������������Er�s��i���U8a�B�m�3J��<�f��Y�4���-Z��z	�����6�G�&O�Lgf��z2�3g����*���G����8p@k.�'N�Q��.J�,)��}��m���a��E�*�]�t�
b��q��
�#����0���?����6���������9e��4�#�m��5��J0V	�T��h�2b�c1oCBBd��'N�h�1#}�Y1S�������s�k��!��)P����B��]�es���Z�����1c���������`X>x`w�����!�@S������k�\��u����X�����^��������+{4t�P=J8�����������c����c����O��U����.]��R������g�}��9���	R��_�e����-��*�!s��]=J8�0�W�w����?����aqx���f�E�Yh��������6lhgg�x�������n0�e�cT���r
r���M�6������f�e����
*�P���~��M�>��X���u�3�J�pF9F)�������c�7oF�+�1H=��v���K	OJ���_�_�K7����7�Q����3��H��HN�&��G��vLcs�����X3e�6�V�\94zxx+VL�[��������z�pz��M�Fat���k@@@���/_�L���}�����L{��1�+W.�7��Z�m��x
���,��������}��p��jY�|�(q�-[�e����N�����L3B��8V�&�9sf�}��i���4���������@qrq����&			���G����l�j1ZPP�Er��D��iS������3��nU�pa����e�>}�+Z�(����AZ�r�J�����%�N�G	gd���N�6M��e��q��//�0
��z��g���_�zE��~�-���������2��]�4��J�����]�v�����;v�(��+���
6\�vM�I>*�@Vw������Y�b
��,������Av)�!o_�z��%Kh��s�Y���p��
A�_���[���E�wQ�X_��������aqvuu��x������C����#�W���$x��/6�J��������Y�ft'�P�B�=��<u�����>��
}���o���)�����7�x����o�J;����W��u�f�����{�������5j��F�d��
��pv����A*�O�
ac5(P�@��%e��P�@gD��k��\e$&&V�XV�����i�&����-Z�h��QY�f��0s���:L�/�O��yY��0�$�(������yS�[B	��m���Z�;F{S�<y�g�*}*U�o�����g��i��_����k\�\�r	%&*U�~����[�lY��Ueog���B��M���=OZ�����^CU�z����-��c���S��Y�v-�4�d����U	o���xG	����;f�jh��-lu��a��8��"�a���^��GW�;u�T�����������x���W��)�.\�<���q���}��Q���{����!66�W�^F�����=zp>p���u+k������w����3g�T��10vROhh�Q+$;��4p�M�2Qk�o��S!<���o��|�_:B�J8�������3����*�XT�g���/{��X
�-[���f�3g�������dU�H	�uPy���������WW����'�X
������KLZOOOY9!FLH��o��7n�H��*!S���5�J�*�-�3��f������u������?6o�\�*��Lw�����f��a2<p�r�����!�~��)�v�J8V�	&T�Z����3�4d5�����_O�K�.�����_z�����:	z@P�����^F?dm�������
�R U���?��eK�n:ts�����saC�^�:�%���P���k��J)cP���0`���*��A���S���=�����	g� �c�JN�<i��A%A1�'���A�X�b���3o����+_�d�x?��ys�QMH�"�z������v�q�����_�W��A�`��5kJ��i���<4J	���y��=����_�~]��+�s$�?N)������gM;Ru U�aR��Z�j�����_��3�����%�d�"����S���+�\��a��V������;::�(Qb��2%��������k9�4i�+W��GD���V���r����""��%*r����)�	�nm�v����/��3�>LJ���QL�2��j}�����Y3���zy�@�����X*�"Y	7�{~��%::^�_��L8��;�D����W��s@7q<��P�pa''���x���^��|3�]�z�ghA4h��E|\YB�1b65�1$��p�;v���AS	�������a��u0�����������|��G��v�	�g�����(5
�1!d
0@kzIV���a�Er&���*�~%�a�"�%K�$�����9r������xM�6��{�^,#8hn���wLL�]�BXo���Z���Q#�M4JubP	'
���ZV��^��j��?|�y��-����M�>=)Y���I=�R��U�~���u�_.�-��83�w�^X/_�|ZK^�t	�<7>���J�������_	��^Jx��1�ekkK/������/oooO���c;o��	��X4)���p��0@����Q��6��;�8�}��Qp�4��{w��Su���$���+��p�0|�p�m�������C��Bb5��5+1
1!���][kV��J8�0���~���)����+T������{����s�,--����7��J�:��U����o�������%K�����+W��S�
�G	�����8t�����z�)R�R�.Z�Hv��n����|\Y+�\\\(��9s&�O*���j��i�F�A�������]�R��h����[9��r
.��A�d�V�0��O�����'�����Za� ]������	v�q,��u�5k�`M�_}��ew����`���p��>DGG�{�*C(0�j��zx^������VR�����1.-g���/?~<%����2d��G���!L@��#������p���}�>g�O]�X	�46�x�1'��������],#p�:u��^�.��{G7ma1QX!11�|��h���������/�H_�3z��������3�E�sam%J����1bDHHH�~���#�T,,t�XH���
���G��#j���wuu5�x��V%|���z4p�Xn��E�����a�~�A��r����-C�t��e3��K���F�NEH�j������Gd�����V��na���h�#�)@(0�z���~��p.���(�lX����c�j��R����uk��x��Yzef�A�����SW
����K	F)P��������������?5#/_������'O�\<x���T+[�n%��i���vX��*;;;���K�����=;�|�~[u������l��da����S���7���_�~-k����[�=z��?�	G�bJ�(ZZZ����G�n��yll,5"��me1�L��
�,Y�p�����P�W�X�x����j�
v��P����Yc���v��W�^�9�B�
+V�d�R%<!!a����aF������u�������eep?}�������"}i�h���Gs��1b����� ���Q��R�B�R�cbb�������I��>\�P&�9s�Y��"�l���a6�?�+5*)����b����s�a�q��A�������zx_�����h�:u*"�/�h���7���Xl����{�n�����k��6mZHHB]��%\����/[�l���3f���`gg��I`��5��NNN+V��>�o�v����������#Ut,��%j&�Jx��9���������t��#2�L�0l�2eV�^�a�����k*�L
����R����sh���a� ��������a[M�2��)����(a���5k�,V�������
�����&���+�(�N+T����3zx��A�^�J�(Q�jU��g�����H R�x��PtL ��*Q����3���x����-�����X���/-yIe��Rb�?���[�ha�!��������o���Z^lmm��Y�I�8����-[6OOO*�F��u������T���E����9s��9r�xJ��VP�����F�a�j=,��������+"����kU��o�N���M�60���
�TmPP����E��]��D��:C��iL���,�'&0
Q;i��O����������F��7n�Jxjx��-�P���x��a]��1b�t�Q������Sa�����o�'O�R����Mb%<M1������qx�`����\	�7o�g��~����7�e�������
����c���;v��+�i�A%����7/���?����+������d����W���n���s�2e{xx�=c��&%���9s���#����}������K�,��GGGS�	vR~��%������������>���*U����B#G
c����p�}���c��AD��_�k�*�\�r�$�o�r��������b:��������`oooeen�Q�v����w��CY��O���k�Jx������������=�(�"�����hDDD��U{��Iy��U���~�_��9	WJ�)YV���5��(�AAA|�N?��{x�����{������:@��
eJ8�4���5��9s�,Y6m�d�1��2�j�*=}X	������z��b���[��J����V�4���w��]�dI.yc�������QN���aC���?~L�,���W��~l�f��)%J��zb�
%<..��5�v��qf�j�=������Q����Vk ��~:���7��m\cQ��
�,���HC	F+>|x������4a��i�l���r�XYY��O��1c�Er�f�O%dJx�h)���6l��z������\���J8W���m��d*�p��>}J�R�9��~�������Yz�`��e���*��o��sK�*u��93
Y5�|��j��U��$�������HA���_�����(�C��K�|
�z�
?vwwwi��$oBB����O����U
��]�U����Zx�/�z��	s�T����0 b.�O��_O������K�L<6��X ..n��E�;w�=�T������������
\�I�&�1�HN�>v�X�s%U�o����|�n���|�(�-
���z��I�A�r�bbbL<6�b�c��Anxx8g��Ottt��])	p������1H6n�z{{k��������---���c����������/1W���L	��q���}��qW����eV�iL�X�|ypp0_R`LN�w��I!j��q���3z�7o,6e������b��9::��q��w���/�i�*����0�f�%8y�$�0���R�J|\Y��5k���!�\����p�a20�N�����?O�<X�m�&��5�e�}q����Ao��f�*�:*��-[.^�����L�2��9z�(�Z/�#��#G�B�������������gkk{�\�J����U	g���������F�I%�����s��E���=1�;v�Er6{q�C��K��c5�hd���A:AU/���1!i5��	I���������	3f��
6$��������&�y���BUX�bf)�����+V�HJ��={�h��M��QTYIF���a@l�Z�B���gD�������p����
��w���t�U3]�t����������
��9�u�V������u��������0�������^�|��^����������h�`�(���a���Q��s���� ����BB�%4�p�k,����Vs�<y2)��s�*U4����m}��9���4j���{_�~]����������gO����	
6��_�fOe%�X���{r�`���k�IJ^fK�,)�����D����|���_��=�"�G.\�j������A:[�P!�e��a)������Yx���������3g�+�u��i>���3��	&�9:�`�fI�����0++��� ��n��%������+W�y�_$thy��-�����}��!�f���0�����w��#�������Uz�p]8q��1�e&(��u��))Y9�^�:V������=Liooo���8�U�V}��
���[7����J�G���[u����;v�v��C��U'H	�BW�5P�dI��G��~��Z,M�6���D�`����O�>+V���^���w��/M%���5j�={���U7n�X�f����E�/^xyyQ!�$x��9�#^3�HU��m�`+�	���.\@�Es��fg��s<�������K�v�Ja�L	�?��o_,��O� qqq�w�^�r���'�E�M�*V�(����o�a���g%�c�N���L�$&&RAM%��h:����������������:�#U1��(9Ottt�\�|||��Z���j��M3�K�.��
V��y�bN�������������k}��G�+W6��U�.%���k��	�.�����G����7Nv�a��M���y���H����PtA����	dq)n��w��&������*�����sG�N�R�0_111X�9"Z�o�NR����5��_�>�.7e�h���hA�P�xq'''��Z�p� � &����{w�^z�����s�a/^L[|�
���JSY2����_�5�G����"R���v���c��5��
�QZHh���h�]���3��V�Z���"V���$��������c��
�o����t;����4����m�"L��I�J8c=����o�&�G�bll,�afq� ��Z�Q���k�J+U��u��k���9s�TT%��hNzxxH�M������[,����?��q?��{�N�4�6,���@��D��D
��e+T��������K�(w��A�2���k��ei51b��Q�&M,��8K_�'%'GT�K_A2Z����b+	%�|]8�0����������;::����SO��(��7b����J�.�5k��'O���S���������o��'Q4��������M�6&Lh��1]G#�����*.��;w���������<d�����
6u�Ti;��~%�Q]U8}�4}��-��7��v�Z���}����s��*��H��G��F�5x��|����J^.�0��-Z�X1:�I����A�Biy������n���e���I�"C�y��y������A:05���e�X�b�������#�=�/����0^���-f��G�Y�&lx��Q��n����#UX`i-��J�Q;v��lTpb��_���,�,@Olsz*?2I�g3��"�B�%��7�R��R�J�7%��q��1�K��$%{h�i�1���4h@����G���W�N���o�����[!t�n��Y��
x��]�=�������R%��1����A�H���*;u��o��x�"�W�N���D,����pb��g�	�/��O�>�/_��H=��=���
~����B�i(��t(y��Q�l�h���[�����/q��)��Y���0�����V���0�*ny�����'3e�$n�����t����9y�A�1HW`�9r(P�����8y�ds��Q������������+c�Q���K�����a���{������`�����q�����k���X~y�UB�f����Oog4�p�������X0]������7�5`U0u�T�������I����i�hE�U1�Q�VY����Y<�|�2MT1?S����K�(����0]�n����L	�g3
�;::�?������#����G��
o���Z����0��Cbb�X]������e������8a���������C��""�>h�a����7k*�+V�@�U�D	�\w����G��*x
9w��R�'���c�SV�S	~�.\HJ>~P�`AWWWi������m��,Y���
���3H�b�����QmLLL����,X�@����{�T�B�1Ho�l�B���7a�:u�H��+Wf����+�(�����������`4���=z�x����������.��$%z����;v�h�Q����lLXl��i�U	���2d�{��3'���R������b9-R�����O^W�LF	�H���<<<���I�-���������)����������wx��p�_�n�����w�&%'D���x�5k��������4����$�����RDM+V������sg��*6l�� �~���~x???XXZ����?�z
����2a��._qJ
��B���J8�cdR��M�`���K
��{�$�����������E���A�a��4 �
EB{�L�2��t%dfd�c�N4n��n���cTT���*����
�����G	'�U�B��JHH���S�N��zV�S����s��%-Q(�X�2�� K�,[�n5�xU�%<)�1c�V!-[��w����h��Y|&�aB��|0�>>>\�J?7n�h��Y�\�
(��o�G��G�0�n���7nD#�pb���E����������2)C(�Z}0R�����ME���'   G�%K��2e
�&�3�"9������_���M>L���6,W�}������z����qc��Q��c�&`r���/_>77�����;wN��Z�j����{E����a�����|�j��t�a���*0���c���u�b��:u*���ODD��q�z���f����K	���5�0���9s`C,�Z�.Z����
*p�e�.]�&k�j���a���+Vl��%��~�6l�������e[�*��K��Ma�y��i}��U+Z
)��0_9^>K����;88HO���(P����cTT���'�3�W������a�F��t\y9r$:�-�T�_	��� ������R�H�+W���U�VY$��[�`��	h�*��y��e�Dt��8:XYY����|c��c�J�<y���#]
,--�.�u���(��2�388����Sv(��4$11q�������]�v����y��J8���3gJ�+c��f��*����{R����E��R��d��W�j>��[�paa�/^�~������M�4������7"\���J8��P3v��9�B	�R���d�+k�k�jd��0����������TG�"9�'�d���/���O�������m��q�-J���0�Y�d	��5k�4h���;��S�N�w������VVV�a������<x0�����\#�0�W�=8p��B�
G��y���q��f�J���������������S
��
�{�*��W-ZTk>���8
u�5�;�!   s���&M�s���}���������� \�z�^�)R$$$���O�>��W�����u�������7��#�Jx
;v,,���;s�L�Mu�
*$�7*�p��j��^9#�Q �"�@���n��a;��
��A����?)��SW�+������|��YZZ���c����k�&��J6%�9���2F� G�0 U�����:_pf&���2a�[[���/��W�^����m��%�8j�(����=[� 0����O?�D������������wrrb�6M`%<e��-\��T:�~�:�+,�-[6�(z��R�	|ESj`�`E
���-�="%A�l8o�<��-I��vR��'`����XR�Rn���f;w��7e��j�	;���i�`��m�����w����6l�PS��*�111f���=�������[�n���[���O��~~~O�>5����?��G��\��f�Z�j�����*k��y����������+��]Kw���YB	�:u����.�T�T���r��m�Q�_2%���T!����`�C�g-�o���p�p,�6m��~����a��|�DEE���_��uk������5jKf��Y��x�����'M���h��<�R�
�_p�������HN��@�k���o��	�.\h��gh�J8��4~�����j5'��'O�K����)���/]�t���[�n��t���8Mk��;���^�Y=����}
�e���*���������Y�J+�10��?������zxxh���S���=z���F��� c�101*Th�����e�*��UW�����P�D�,Y��
-�O�&�VS	W�\��k����o��E�b�Gv��1j�y���/��`R4.Z��L�U{���
�]�F��������z'N���?�|///V
��B�5)��s���c��u��u��Tel��>"�o��f��I�2�*2l��m�+jHHo��a��2��B/������S___�����]�v�����;,���������Pwww�n�/^P*u��2e�4{�lzW�^=��J�,�K2E������D���pu
���a�R���]��!""�.�
8���Sp\�`�J�S�u��y����X�bQQQ�t���t�����S�N���}{kkk,)��CL*a�@!�j�7oN������>���R����vL��.]�OUh����;�(�Zs�22)��>>>�����������9��LJ8���}�6J8p�]��I� �k��p	,���a��o��?��%K��'�~�%�b��o�Y���v�Q��%�
��^�z������N��.\H�,�8qbR��u���V�'O�0����;w���p�0b�j�?;����]�v�Y��;r�a�L��>{��������Oy}i��z\6""�2�<y��#��ILL,W���+W.����g�b����C�a�Y�f�o���o�,
��s��5����������7h����>p})����ZA�EWk��ZYYU�R��BD�...��?�~x���j��YH@���m�v2n�81���o�?~���/#�S�s�N�U����t }�G	gM��[����v`V,X�<�}���\E#6>ggg>�l�3g��������������P��J�*Q.�s��IS�OOO~9�l�T�NW@@���A%�1H��}�����q��)I��x���i�b�����.|��111����C��-��a��U�����z��"E�0�>|���Y3ZTG���b<�7o����^�|Y�tii�����_������,��_���y������_/�$0��@,���KUSLHJ1���t)cX�|�T	�6m��������7���eJ8�t��������+2P1���DK���~��fLW=��vL�����oO��z@���TR�NJ����:{���o�O===)O8(U����Obb���������E#���� ����@�			��`�J�*
:���f��8s�����Er�)������c���(Q���m�������x�l�2x��B�phh��F���[g�QQ3�stt�d��F�Q�JL`D
T��a�I

H	���q�F�=z�����b4������7�<~�X�Gk��0_p�������Q�pa<�%e�%|��A?��s���et)��E1c���z������7����10"�?���K��k}���A��Z�t�8�)��}���s'O���,r��rD����i�J5p&���@X~5��K��S�N�e���V��?���?g����^����|���F�y��a�
Q=T�^���R�����K��2
�a�I'�.��C<{�������@#��x����h�	9�e�|��;w�+W�H�����);�56� ���e�v��M�+��*Jx�~���!���cG�1���|�10�2�[�l��@J8
1����;t���e�y�����S�zi�D����C��F+,��T���?~������W�ZU��)�\(� O�<5jT��M���_�?��S���q������0Zquu���55p��%K��it�0_B	��]<HJ�����S |0�U�x�����������J�����i�^�~��l�����������g�������k�$�J8�
�^�Z5�hy��!e�2d��G��10�p�W������<��TXX��P�N4N�0A�����E&�1z�+���O������-}��5�0U�A%\�������CT�U��];q�����toT��{��]�������7d����3^�p!I�9p�um�12�d|�Jx�L��f��?|}}�f�rD��-[���/k�C���-W�c�X�N��+��d����C��)C(�?������0
J8 ��/�Q;&�����g��0]PP��%K�
F9�---���Cf��M�F�����m�������o�����<��k}�x�d���5UI!���S��������1%h��Z%�^Ej*U���-�������ZCt�%TD�PM�y�=�^����9Gh9�=9��?����Y��u�~�������aW.?����b��`��mv�B��w�4>��3&��������U������.]���-[��q���U���S����s��=��#����nj���w\������v�B������k�h�.s�E����v�7��N,��1��_|q��-���#t%�~��7n�]�����?Z��i{���G�"
'��n�����~���|co��)���1iiir�1b�n�p��Z�H��^���� ���[7##���+	��Yccc�����m
���5�[�����4(  �����U���0��������d������/�r� �'�\���>>>j4����x$9�Y��J���wRR����4���3�v����j����Y�t�M'���3V�O�<iv8.MF�v��I*+#g�=���{�~�J8P)�J��I��������J������f���������

�
H��o�����������KK�^����o����7��M�6;v�P��.]j����~~�������;,C�1U*���|9%S


�1c�����???���*����[]��K�h�"3��4d>5p�@� ���������o~����]�G�~+N�>-��������7������J���>}�ZK�n���o��M��}�J8����O�<��X\��������x�cqu			5j��:ujDD�������]�� //O5�����._����[u��3g������kI�8qB��j���s���Kn�{����P����KU�5j��~���?<<��Gm������mO�o�z��X������W�3����;wN�~����{���������K�.�_����Tc�����%8���FFFJ2�p�B����~ju^�*��[�n��q���>�y�Lo�������@%�$.������oJ��111�6������m��F�v�{����+��C�Zu�]�v���m�����;|��Z9�x_����������U��q}_����?��?��W_}��7�m�6���|u��g����LHe�����V�~tt�����9s222V�\��]h�����/Z�H�9#d(�A>������+��W�6e����'f��Zd. ��_������=+��m$Yn�
j��}������=�J��)S������2*,,������#G��{N||�}��'�[ea��
~��5u�\���kU	/))���C���������_�j{p��;w����;2v��999��'N8?�J�*�?~��|^�b�>����S�+���1bD��
��k'��$8�EU�e�>v�����u���|U�q2�(������g���N�`����F2���`��!7:A��o��V}V�q�=x������===7l�`v �����~�E�P����'Hg�^>c%<--�c��K�.�:g��qV�p�����[���|��U��7oN�|��c������_�=j[	���y��V��=��u���G�m�V�zu�r����v�rbt�C\�p��d(��������}�J�j_b������Np�~���\�*/]	������5|�p9d�BMW�4h��S'���R	�������;[U�322d�h��)o5�OW��|��-Z��@%������k���4�Y���K/��K�v+!!Amu��@8�LZ'L��>'&&^�tI>\�r����b�|��7�������?�IF��;w:5VSTT4h� U�����-STj����1e����|��:H������f���t%\�3��9T���t%�Y�fT��O�V�_�n{[����e��M%������V�*������p??���Li?v������w������9��eK���QF�!�z��	���K�O<��Jb/_�l�[O?��e�+�m�h����s��u���b$1@e�+��N�:�{����=�]�[�+�������v���pr�,]	W��v������V�Z�7o6;�JCW�e\���������b��1{�l�����l��E�?����h�Xd"l�+;w��C�=��s#�@����JV��zm��g�J��>h[	�����D���p�/��B�m��i�t;�*;c%<66v��%7���Fne�q��	��Jx�������v�Zn��^�>j��U����.c���9s���K�_AAAju����[�n���7�xC�+*B�������>3)d������@\\��]�W5J�h������5k�����#IgW	�q`�]	���NJJ2;W���:t��|��GY�z�z��V*�z��e�Jxtttnn����4����?�G�;v?~��S�T����=�n%������pr9���	

��Wpp��~��5�%��������9sf�&M��_|���T�}���B��f��(������T�����JHH2d���GPP������Xdd�����i����
P	�E���RH�qy�[����J���T��{���`�����M+���������_�xQ=�eU	/..�X����)o����p�������%K������w���3���[�NOO7+Z����z�jI��V�p�*�7�t�Ru;l����L�>]�����=P	/�������,����*C�'�|�`��s��*�U�EVV�\��L��x���g��!��Q%���d��7��6mZrr2�.��nT	/#1@�G%��������&M�\�R�iT��������_���\��?�J8�������~��
V�u�S	�����7m������o�����pKG�Y�~��C����T���NW�Y�����+��b���VZZ���Wf��<��LU�e
|��I�cq-�5�S��������AU�}||�)p)���S/2{xx�3�����~��Qi9p��L�e�`^�B����@5T�^}�����>~����d��w�^��� ���=z����t���������~�zi�t�RLL���������Z���(\��Y���/[����������^P?�����'H�*�������x{{��hJJJ�z�t>����o���Y�ps�7o����Z�j�>}d��&��<���Jx```lll@@@�
$�51l���_�n^�n�A�5k�L�V��Jx����[o�eV�����
6����s����������M����O�]	�a������^^^����a�����V�

���k�J������&�h�5X�pEEE�Y��{�z|�F���m�����'E	�����V�Z�z���7���['3Y������O�����8`R�"11Q������	&���/_����S0`�I�p����-Z�������%O�[	����O�/Z����T�����5kv��1;;{��=
6������o���J�7o��_

��<$����g������$��+�j��W���u�]v���%K����c�,�$&&F�S����-?��s����>����`��^xA-��m\�v�N�:!!!������uS���������/[����TF����|qq��j(����?�0...99���p��]�6m���5jt��i�>{�l�|����/�_�d@���U��p��x8����k�������C����MS��.]
�����_�z���.\(�f����x����/K*+SZ���� �_�L�zR�	��$%%I6l�nIMM
�a���V�pF���n�Z���u���<X��3�g��-���Hp������&7�+..�����[,��e������SO9=X�l�25x�����)))����~��3gt{vvvXX�����'�,7q��9�x�����nNN��������g��q�����~��V�Z����6;d�f���-[�TOw;v�V�Z���jS�~����`��a���?�4ir��I�C������+�����2_~���b����/C������L
@����Z�D��Q��k��=��C�P���7n�(����S===CBB233M@�Rk����VG1����}}}��3g�<t���M���t��8�&,,�����oe>�������W*((�Y����
��_��f~��G///���$�i��AAA�N�RG<(���S�k���\w2|��{��G=���8q�>��W/��3p���2|����pI���S�\��c�L�@����������S������}��I�722L�2�������4�����[��5j�(��|p�����������oL��3�5�'O�,������������z��g����2)Fw��y�G�������i\���W^�8qb\\\TT�q��N������������#G��;�S�N2GHHH���5)R��InT	���[�|y�>}:t�0l����T�"����������������s�NccXX�?��O'F�I$��������,Y��{���L�K�p7J���V�6�1"66���0S9�p��r*��&�����G�����;j��_�U���������m���,��^�n]5DFF&%%�C���U����u��9s,�zn������_�vc�;;;;((��W^1#X�������?""���NII1�[	���/L���%&&FGG7o�\���t�n����q��y�"������4i"��:u��TVmq�_\z����%88X-�p������z���0�fT+#�^��������m�VZ:w��F��c������*��&�7o����a�����h���G�������T��3g����s��5��+����OKK[�x����'��0G�������q����@�}1c%��w�9~�x�V�d�`^�����������{iiiQQ��U�j��)�0�]�v�	/^l��������w�}~~~2���}����H�����C��~�I~<u��~�_�~j!���w{yy��q[�n������iv�*�M��gO5>�{��AAA�k�������I�n��MJJ��#G
�z��o�i<MW��,����3�
WRR��wo�������%�Y�������g���t%\c����r������3�����jg���@�d���'[�j�.gu��1���=L�81((�j����x����Z6o��WMi����������bbp��5�u��������x8Djj��b�������
<�n%���#�������g�:=X4�|��c���-999aaa������)S��^�x�b3�����"�H>|X�_��O�����������DGii����o�.W=3��({��Y�b���#�
f{T��j��7�����c��}�$�un���&��~HNN�p�����X��~����������y��v+����K����I�_�n��5kJ���,Y"��
�*�e���N����=Z.[M�4���=v���	G�����s�~�m���9N�:�zz����q��:TN		1&���������~��	��W_}U�F�f��]�x1..NU��M�������F�A��9#��^�z��U����_�J�5\�z�}����vX�~=�����

UI�������m����c�L�g�VC������:%�U�{l�����pZ����Z���z,$$�a���=���"��������j��O?����p������B�����%&&���P~LKK���FDD��+W�49bn 333<<\m�l|�Q;{���U���c�Lj�?��O����z |�����
���P��[��;�����������GG����+B���/_�lR�n��I{���YYYw�yghhhvv�>��[75����5/Ln������s�Z�K�������
�M�
�3�J����m����6m����8��]�vw�V&O�<v����������������h���hl|��>���#G��������uz�[�n]������/����]����8����1�����������&��9H��Mff������_���8�7A�����O�>��=j�(���>�����z���_�x��k������h�k�.�"'|��N�?NOx������g���[�����V��t%�y���W�NMM}����U�V�~���4���$$�����>��`���W�^UG�~�mi	���Q-[�l�R�����o^�*^AA���CAppprr�>�o���8d��2y�d
N�<iF��qz�+6lX�v��m�rc�
�J���o�F����7|�p�[gpc$�������j��>}���K��.��e����������KK�v�>����s�V�VM���<�cP��}�Y��111��/�4iR�5�G�7PRR���i����{N>�C.����
pK���J�+��bv,LCb��A�=zT��Z�J�}���Uv������
		9~��y!�xiiiU�T1b�n�p�B�.]T�_�x�j�<y��q������\�B��KOx��������J��I����iHwu���������3fXJII�������K���i���o�|��v���;��7����f�����[��

�� ��oW��q�^�������c�K���	/EW�'O�lv,LCb�������>�h�����_o{Brr��b���h�"���ij��1u������]�vU9K!�^
�pe$����m�z��J�*����{�k���z}ii�������111j(����x���9�X�vm9����s~�8���6n�8??��p�FW��}�]�c`�����S�}������n{BNN�:�����s���Oe�#G��{N||�}��'�N#�-Zl����@�l���QQQ���f�L$����{�*t�j������'4o��28����������	OLL�=A.���nO.�f��%0(c(����w������������iSE����K����=|�p9d�B�>]	o�����U����###-���~jnx�CW�=<<�L��6�,--U$FGG�#��Jx�*U��m��{w__�Z�jm�����8����:u����;,,L>0��P��Jx�������v�Z�^�m�X	���]�dIjj��ACW����sss��9t%���;))��p��D%@�p�5*������Q	PF%nMU����O�<iv,L�+�/�����l�����3;
&+**Z�j��Q`���[��
endstream
endobj
12 0 obj
<</Type /XObject
/Subtype /Image
/Width 1965
/Height 1058
/ColorSpace [/ICCBased 7 0 R]
/BitsPerComponent 8
/Filter /FlateDecode
/Length 48050>> stream
x���	�U��/���4�P�)�T��bP���u_��}UI,c�3�-E+y���Fd�QFE�-"Q��"E�DTfAP�e�����r��{���=�����U��k��Z���J�cg��*�~k�������������G7�q��,,��/D�=���YX.F���'�x�D��I����:�����YXQP������uO���?�of���T&L��S�IP������8t�P�PEEE����?��s�T����W�*M[�l�~���K����Np|
�����?�j��m_�O�W 8>{���#��k��2_q7��;wFk=��C���_�������g���q�����x��h��S�fz��Dp|6m���{����rO?�t���e�2�V}"���5k�����?Nz�������g�6���{���U"����7�|s����������G^^�#�<��SO-Y����?c/��B���>Xm�����^z���g��]s��6lX��������Y�v���|UX���_5jT�>}��(((��ys����������)++[�bE��A��%z����������N^YY�v��p���7��g��~x��a��7�v@=PG�|��x���<���e��h������-�������_���}���R��#?~|44g��p���o���#u�p���k�K�}�����o`�����������w���5^��;wn�[�i�m����Fc�����u��K�,�3�L�����f��y�����G~����G?���>��C=Tw]Gf��f��?���{�i��<m~~~aa��M���<<��_s&���jK$?����<8:�����a��Zm��s�����c�
6$'��V'L�0u��q��%�����'���8�����t�~�2}�G���Z�j�1]XXX���];|��j?���b����+�=z���kWrA1�������'�'��C�{F��s�(`0`@��=/^\RR��������q��O?]m��k���&L�5jTrZ~���W_}5L���(u������_�Oi��e�o�������k����6f�O�������:4�n��=�D�X����O�>���^�v�q(..��),,<�k����mS�������G5���KJ'�~��m�R��_���������	X"N�#�����d���Q���t��������h1x���p{��O�z��x�W^y���SW1���>�2d����k���O�oh�����<#G�<�k.\]��O�:�V�^�`�����o��=�?�<��_�R���&M�k��k��e�j��W��SwM�TTT4(����+++K�-��gO<s��5�\��8����N]u���o������E0`����w�?�|4I�{_�m��E������M���c������_��,]��������5~�a�Pr>l��:�3ys��>�(y����W^�/��?��/un����J�SN1��q���=zL�6m��
G�
C����w�^�hQ�7(�~|�K�������!����5	O'�������������	O5�	w�<������{��W���[�C�����(�c��/vw��0�UG���O����a��l�R�����2dH<��%K���q})zee���������={��u���T�-�<���.�����:Tc�'�|��KJ���������#�|�����j����?���#?�pT<s��/-8����i���={�L���T��/O?����}����c�����p�������:�|��Q�]��G���J3�6TM����9s��j��sss����'�q������O�'��{�1][PP]�h���[=(..�3gN^^^��n���.\jR/<yb���7����3f$�����G��+�e���k���7�S���UVV����+�+..~����M���w����_�~�>.Yu2���m;I����[Rc^QQ�?�����6{��:n���������|��w��p����U�{����8��S���n���+��=:9	���������W�zf5���T��fm�����+��4iR3�o_K��{��������_�x����)S���_j��=�'O�oo��i��'O^�_$"s����C����<�H�?f��:f����<N����G���ODW������t:*++��-���������/X������
+W�L�-�2eJ����_�GB���b��+WN�8q��a����{�8d~��KKK�\:T���F��5�U������O�|��qu���y���0a�Pm1�q��@}R[�������6��f���q�SO=���7n��0`������{���3f��0Cm)td��5��'O��G�}���8Cee��a���~��U{���<y;�����~B��q���s����iSyyy����b����~���	����k�|���qY��������s��f��q|7���po�$a�:*'M��
<8��������'��{Ir�����W�-O����U�j�����	&D5=�P8���������w�Ii�{���>���������w��9��^�z��f�:��}����j�]�g�}6��g�y&us��{�&����k��'O�����N�:���?��s�)���E5������:b�������G�={�\�`��#G�'_�~}|y���pB�������dyyy�;��I�&�~�������u�0��A����o���G��0aB�g���������}���)��aC�^���>:y����z��������������S�(�O>�d�g�>}�'���|I�������~���N
�c�{�^�x��&��V��.1b�W�	�z������(��3gN�*{��'�������;|������{���c�`��m���5�������z�Kc��/��~��w�O�>t����{���#�s�����-+..>�ug��-���/~�_��m�����^?~�����{��5p����zj����������*��bK��+W�{4hPnnn~~��a��M�����{������O�Z�g�>|x�>}z���#�<2i���K��v!�����.
'?18���zL@=&��P��������'K�.���~��6j��y�����;vlYYY��#G��������j����g���M���GWTT�N8m���;�h�"''���/�����R��m�v�=�\|���7>��s;w�<�������jF���A�D"��c�����7�|�Yg�N����e����CNNN�v���m��Q�pz�M7���'Ox��w��0g���;t���Y�pz�%����3�l�����7C��s�
7�p��W&�0d�������j��_��a�
���Kq���~���|'�H0 ����k�i����]���-[��l�2t�92.+((=����+����w��%t�|��qYyy�W\:�u�VZZu.\�0'''�L|m��@�A�E/~W�>|x������t����5j�����[��-Z�.��������U�V���� ����?��0_�~}�3{��pz�WT{�;???��v�m��.����M$w�qG���3g���.�,:�4iR8���S�^xaZ�|y8�����K�=Z����nK��$�N���[�l��
��Y�f�+�i�5�2eJ"�������:4�;:�����i��=Sg�6<7n\�?��n��mj��#������F/���A�h/�u����.������.H$�<�L�����~����.�z~������c���p�}���x 2$����L-�5kV���~�6i�$��]�6��?�A�;wn��@mV�^}q������o{�-��u�Y��5K~��]�v�`�����������]���w�}wj��/��.���p\ZZ����;R+������\jSTT4l�����'���7�Y�zu\s������3g�^��o�0��_�:��O
���uK-[�dI�����:��{����N�:���'��.�����\sM"�����������m��M�0���FNNN�3IUoeGo����-[��J�m�h�4�����g��y��������.*..�?������1cRg���{�P������a�_���e3f�Cm���N�<��p�f�������ah��y�����8e���R�(s~��������7n�8EO��Cm�����sz��'���9s����l��Aa���o�N[�n3YEEE��o��)�u����C
p��IA��7���D"�`�����M��C��O��_}�����-Z��w�}7����#�q�EEE�*�t��{���������z��V�b������VTT��.�(������o��9��{����t��}�7n����
����N.�����M�6�/i������Oo�������7/�]|��%%%���V'���������T#G�L$��7O~����C����V�U�����k����O��U�V}����S�N���}QZ�h�l���g��=:t����UVVF�����;����g�}���N;���?���c]R����r�-�D���Nk���w�q�M7�w�y���.X�n]\YTT���8���m���\sM�
�i��]������>z��U�V�]w]�&M�����&�m��1Z�E�a�K/�4��)S�$���.����|��g:w�|�y�5j�����j��u^^��={�U���4�U�VM�4i�����__PPP��3f����c���C��W^��_����d�}��}�����~��3���r�-�;���.�	���eS^/�����'�v�����x���l�_�=r����M{�4�K�m}��~�d��%%q(]��-#
O���AEeUiyV��W�i`a�>�U����*��l�������e��izq�c���<�K�z��������_�)����g���*=�?9k����=@=�����x��-Z�8�������Gy�����j�9���0��i���>�M�6�G�������i��u��1����s���w������e��m���{.������{���;w�?~jY�������#�1x}����U[��v �������O?��f{���n���6���,�^�;���x �H4h���k�m��]�&M�i���������<x��W�����P��m�F����n������_�w�yg4[���;t���Y�pz�%����3�l�����7C��s�
7�p��W&�0d������8���3G�9b��Y������������x��[Ffu��J���l_][v��8e��;,�/��s�%��.�h��UQ�g�}��U��9t����k����]�v�v��z�l���e��9r������ ����+V��z>��K��y��7�e���W\qE����[iii��p�����
����.�IN�9b���g����ZQmqi���<s6|Z�;�8�-�J����v�EY^}��b�/*++/���D"��+�$�������������t����5j�����[��-ZE�a��'��

��>�����:+��_�>��={v8���+�������o���c]�$'�1x���3G�9b��y����{��������[o��H$������&M��:u��:t���������?�0��������n����
O����p��o�je6l���5�^Os]���<s���#�1x���3G�)j��!�D���c�e��(���g�P����q�����w��mS�F��n����4zi��bF{��[�.�uN~b���g�<s���#�18�����7�Db��	������~u��q�����x��}���e?��OC���cSg�����P���G���_�2�l��Ya�G?�Qt}�s�����?������s�_��'�������A��l7��O
��#Y]�����l���#�1x���8Eu��9�H����i�������t���}�(�n��e�U�v��������������v��}���e/��r���K�qiii�;v�H����vOs]����>�w��������D�N��3G�9b���p�j��}"�h��a���������7���O�T���^Ng���:C��}�����p��?�)w��-�l��%a�[��V8>t�P����;��S�Nah�����p���'?�X��<jE%'�n2I�9b���g��ST���OdVT���l���Z�8p�*����7���m��-[V��6x�V��~�w�������_�_��{'�v8%-��;�����lw�����6}VW_�"��v���'<��f[�|e�����O���f[�tU�����N���f����z'�tRPjs�M7%�������_YY�����.]N�����1c���p�����������C���_���e3f�Cm���N�<��p�f�����E�y������:�H��[_����f�����~�?/Z�����l�����%�g������1{�6�/[���������g�����>��l����i@a����{����o���g��e������v��]7,�Z�q{���+Y|�dY:)(����_�����w�����������G�.���O��9s�$3��A��������n�:�f����(!��iS���VRV��`e6������R������zy?������g�m���5����z�+?*�������u�2�m�����Gm��J������=Z�~�D�}�������O?��0�r��p:}��p|���W++++k��Ez��w���;��g�QTT}W�.]����{,:�����i�^����X�"��{���&-i�p��g�<sv�<��7���
�{�|������q�
�Z�*�?z���������o���l��
�e�V'�]vY���M����w��q���7l����?�z����.�������X����~���4�uNQb���g��S�<�H$Z�n�r����\rI����G\�Or���~��'Q��U����o���S��eQ~��E�e��E={�����C����������k��&t�y�����Q���>{�i��~��|����p��g�<s���Z������$����p��]�h;�:�uPTT���8���m���\sM�
j�W<�o<h���u�]��I�p��������e7n<������}���^zi8>����L��\����"1x���3G�)���l����\sM��M�<��p0|���G�V++))4hP�V��4i��Y���������	g����c������+���_�~��z���>���������q���w�-���C~|��r���#�18�&1x���3G�I�9b���i*.���YE6��+�F�t4j]U���������U��)�f����	G�6��%Y^}ae����zL@=V^Q�����l�V��7�8jO�V������b��������Gm���};�g��U�_<����iG:
(���c�������s��}_���K��hM�����Pq���u��w�WTV�7�H6�o�up8j]�fy���/���
�x����k�^�i`a�����l.���l�>�gNE����}����=���CN�O�Z+X��g��<s��%�!�1xF���t��3G�Qbp b���g�H�<s��%�!�1xF���t��W���,�m�_KnX�{'gy���*��l��%8�**��o��l��>Y�i����2�0�����<��w���=����Z1nQI�f�U���C;R��Gp����r��%Q[�&{���MK�.=������Y��
9r���W]uU��M�>��6m��=���"u�i��u���E�999�_~y���8�Z�m��{�����/n��������s��������.����#�]vY��b��^}���?''�]�vm��m��Q8��������+�������A���[w���Y�f���K.��sgr�����7o��9��n���+���2d���u����H$�;����k����]�v�v��z�l���e��9r������ ����+V��z>��K��y��7�e���W\qE����[iii��p�����
����.�?��<����$�-@�����`�V)V��B)(j��nk��R�O�U�U�Zm�Zi-�j�ZA�FQ�"�,J�dI ���y��@2	��&�^O�;����������;�����^���>�������)��Y�&''�^�z+V�(��?�����a�VRR�t��5���1�t�
64m�4�����Q�o~����S�Ne�����B��#*��P�m��u���q�����nj��-�O<��C������{/Z�d��e��1���'�G�'M�T����KC{^^^t�x�����C��I-�_r�%�e����O�<�>}���^���_��n��~{�5|���at��o��%�d���_�-�2`������{*�2$�L�6-��&L������=e���=l���n���]�w\��q�������S{v��%�z����]�����D-�e�����2s����_��a��1c��c��M���3��]����EEE���Z�*�g�Z���i�.��UW]�H$n���dKj�W�^����O}��I���Q�F%�w����n�?�|�u�������7Ge�u����,((������_�B�������7���?��������P"U�<�������o�;�����J�u+��7)@��Se��o���S�&M�$�C����O;���r�=��������]�\sM��:uj���7���m��YaW�>}��������E�R{v��9��;wn����O��H$�:����_�~xh��������B��/�|o��<xp�u�}���'�|��}0K�<yr�5r���a�=���,���8��G��4_R��'?IT$Z|{���a{��e~���;[�hv���[���U��v�
�n�Z����C�����;6<����_��k���[�l-����@�REY�~}��
����.]Z�g��I��-}��I�H{��U����W��|���;7t;���K���:7n\e_��Z����Iz����GE-o��F���C��?������E���Q�'�|2h���x�$�������34�����o�{��������/[����i�c|��������<���_��=�����1c��y�e�]-���k���?�q��a��c���iS�n���N�V��������k������_V�u {,�����'O���k������0c��=��Y�f�p�	��7=�9���o�9y�wi�W��0a�QG��A�V�Z}�k_K^C^���7-^�����?��#��������o�;������L�m���r�-��uk��I�f����s��w���Gy��Nh��E�F�:v�x�5�l��1����+/�����>�a��-[�<x��y�R����P����6l�H$���z��}��G'>7p�����'�m���{����Q�F���������	O?��]�v�����~h��������A���
��m�f�����|������]t�����c�9&z�)S������@|�Annn"������m�5>���M�4	�S�NM�3fLh���_�vm��|�������;��#�m������~�����-[�:44�q��n�v����Sh��w�����O�S�F������M�u �~��D"��w������7�pCh0`@�p��5999���[�bE�n���C��;,���]���3f���a���M�����~;j��o~v��������1�������w�M7��3�L{T����=|���������p����],����^�z��;�t1bD�OF�N�4�L��K�F��D�����P)��{o"�4hP���K.	'N���3Z�d�����[<���_j��o�=�>|x�0�h|�7���_�dI���+))���"�������!C�����MK�<a��������S�L	���
K�6{��������6n�8<\�xqj�.]��]O=�T������[��1�SXX�������3g�v������1c�$�������g�	���k�����[�jUj�������|]H�m�����u�A-]�4���W�D"�������4iR�5j���}�UW���|�;�����������7o������K�YPPv�����.Th���c��M$�z���K������
�
�o�������^+����?j�t��Th��
_����D�.]V�XQf�i��v�s�=�O?~|�u�5����S���o|���f��v���'z���.Z�(�g������s������������R�
6���#�H<x��M�.������2<%��������O>Y�>��M�<9�9rd�0z��>��G�w�}7������u����y���s��=��9sf���i�[�hv���[���U��v�
��,�s���a�]w�=�V_����_��k���[�lY\\������{���Db���Q�y���_��a�����������N:t��l���O�E��V��_�~�z�>����e������G]XXX�g����q�*���*�s��G��g���3Z��W�^}�Q���o�n�:4>����n��(-Z���?��|��'�
�\pA�[III��=C�����}����������_���e�*�����SNI$�Z�:n/>�������[����y��_��={fee��c��)�3/������v�z���7n�8l{��eV��w��F5���k�.lggg����,�-���2�;��D�J_�]XX8y���]�6n�8//o��3f�����5k�	'���y����c�������|��z��	&u�Q
4h��������5�����PY�;wo/�_����l����m��������]��m�O���d��u�w�~����'�����������G�^�����v�S;2�������F��:F<>���Q��e��(�iR��2x|���4)��G<>������[����F��P��x�h�ow�'��GQMf��+E��������B�fU�m��[n��[�nM�4i��Y�>}�������L����M��w��H$5j�����_��������O��kW�G�d��1�D"??���Q������o������
���5krrr����b���������a�VRR����>z���DAAA��C=4�Z�`A��
��%�\�H$&N���k���a����k~TP-��H$�M���k��	a��W_]���j����H$f�����������S���j��W�D"�������4iR�5j��t~�q�VuW^�R���c��M��d�M
Pu�]y��i���H$�����]���������T��/�|o��<xp�u�}�����Z��93�H0�L���;[�hv���[�����7l�0++k�����g���H$:t����@���E����G}�����[��?�pf��h������O$
4���_��=�����1c�dzhP
'O���k������
0`���T�%K�l��)����d��7�������n����Z�����jm��m|6n��
���_���X���k�^z��GuT���O>�����gzDu�l�#��,_�|��p@�&MN=���0�#�;�l�r���~��
6�����y�2=��C����c����;w���Y���{��=;�#�;d�Y�f�������o��G?�QQQQ�G�n����_}�GQ7-\�p�����m��@� ��j��q����V;����G��U	�^/��b��-C�
6�n���_���L��.�m|d�^x!///DZ�^����{�V7�.�W�>��cB����YYY��7_�bE�UG�6>�q��=���7���q���O��:��s�d{��'�D�����^��`����ez,u��-[Z�j�=���Tk��l�v�=��x�6m�Z[�d�E�%�U	�.���z�&M9���s����,[�l��!�6m�gzt��l�#��|��G-[�l���<PXX�n�����A����Q����
6l��}����T!��l���K�.!�a����?��W_9rdTQ|��2=��M��=ztH�{��O?���%Kn����������G���;����Jx�z������V/�����^
�^w�u���S��^����]�7n|�g:T%�Z����s�������'e���	���k[m'���6VW^ye���?�y�R��w��><���d�+��"d{���n�����9��L��n�m|���b���G�J�#�<��<��6l��<���nS	�v��M��y���7V��^���g�}�����o~��?T��^��U��}9����B��j�
�����i�:ujh��W32��A���m��u�����u����/�������	'�1��'����j�K/�4�E�,X����_u�U��~��~�3G�U#���#��M�6h�`�����W�Zo��}�V�6V��zj��O�S��:��rFF���;4(l��W�/��^�z���/��jm��m
���S�����������j7�����.
y~���{�����n�����<P���k�m����i��������O��s�������m|d��m�fgg���#�2q��2k�<x���d-u����y��d�O<�&���E�ep���lc�d��]�Rwp�yyy5?�:C��:���C���z�y������_�����E%^t�E�C�����o�N�:E����K�5`��a~����j����:��7�x#�c��d�{��7����O���*��������h������k�)S��

JJJ��|�Ax�������N���?��
6dp���l�#�X}��_.]N���;���={>��������n��Ah���/]*'�b��_}�0|l�0>�����+���9���Cm����j�#�����{���D�n��2�:w���y����n�m��<������2���������***:t��~��d�Jx5���|��g'��V#�������K/E�����YYY���-�a�%��,X� $y���FKW���Bnnn�.2;����w����=z���;����j����o�������������k��Q����xk��G��������2��M�6���
8�t����_��K���_��W������~�K_:���V�X���f������>��0k%�����$��)7���#>��Q�
����1c��9u�9������P
��[����
*�Lb�Tk�-[V�C��d�g�y&�9m��dK�+�Ke���/^����v��O�����
K��������s�=����{��.�m��I�6m�$g��Q�Ot�!�!�,��G��������0�Fg���n�>���oC{�f�\�PY��~z�n��;v�������L�>��i����/����^���SO=���rN�z��Q�q����~�i���.�m|���O~����!C��I ��b+W���q���J�u�]�������gp`u�������4h��y����z}��'!��c�&[�O����M���/d�.]���m�����7oe���U��s��}����k��a��u;���R��������[����d����������'~��{���S�����_����v���nT��������x-Gt���'���j5����[����?9r����g��]z��2>�����)��R���4-L����B�s��3f��������2�!.M���~�A�����[�����.�M���+q�6�������Q�~���QGU��cT-�2���N��a�?���q���m����q��w\��i��oNiS��H�l��f&��sN�3�@�xnn��y�R��IR���^�:''g�X�����#�T��j=��G����qc�x������a�
�][�lI����~�U�{S~�3f����B�{\�+����[n�%�1�V���+��r��G'J9��������9Z�z��Q���N����nP��u�N<����v��yok$��R*�����/��]�0�]JJJ���T���d%���~�S�K��jm�^��iS�6V3g�������;+�9t����]��u���!Z�:������xk��'�lo��������G���u��N��xk���
��/����]����������b`-&��,\���#�H�fv�����
�$�~���!��xp�������C=4|�U���:��lw��~�A��}�o�^f��g��(u�R�d��_~9Pegg�w�y?��O�
�8q��=����JO������O:v��9��C��]vYt���f�c�����-Z����[��8�:EEE���XU[�0Y	���j�MVk�iS�6V�G���u�]�����B����:���a��S�6>�g����5�7n\�=1��_�9�Z)�l-Z��|��2W�G��]q������m||����Yg�UaO�V��o���pno�m��E�-_|q�k����^xah����jp��F:�7�|s�g���|�A���G	G�w\��F�[��6&�6m:�������9s���$����4��%K���.�l�:mE��4�$[�;�Y�f����B���l�����{�h[
j�'�|2���p�	Ux�_���K���(�l��j��&M��h�������
A�:-{#������
�l�������
���C�t�����;w~��'W^yeh4h���T��Oqqq�^�B>��_+�,��z���C>���7��(�0C���-Z�ly�y�]v�e]�v�
����4���yU6Z�:��y��W]u��������CI�{�!��$�����_^���c�
���!���a���������g��o1����+�H�e])���
�m��i���n�0����q����z�_�tT-[u�t�6>�&M
�N�0��n���o���:m��6>if�u�Yj���~����m��Q�!'''�2d�f�l��������w��k���{����?l�����������0`@�*���E]����Je�|��o}�[���K��K_�Li���W����O�M/�~��'���������_����V���;v�SA����i����8�����L�-���g?���E�=����W�N��m���m0p����09(�A���[oegg}��������
�>��S����m|�m���M�p�>�������Z��fFU7�6>�g[XX��k�����������B����o��e��������_�r�_�&"�X}��_����{o�=e[)'�tRx�F��T�����'��3g��\#c���������s�>���K�,��1�V����A�B���t��u�rss�>���;,��E��f�Jv���w��N[�o�1�J�����o���?>�aNN�u�]����m:���w����])j�q�����[o�5����Mk���_�tT6����|������m|}����)������A���l�#���6>���^��
[�j�q��L��N��7�9x����4+��C���mL�E$��l��kW��r�z��8��	&�k�.z����F}~�����Vh��9�_J_�5e������_�K/�4�u��n�)� �tT-�W_}5''G
���k����5m�4�+4J��r�6>�����>����gz u�l�#���6>�������X�
���[�������;kph��l�#���������g��d��	B�;v\�pa��m��SN9%4~��_Lv��/~�N[��>�����O?�l�={vVVV8�}��'��7�pC��~��+W��Zd[�*g����N
���S��_���;/���d��g���H�C���!�c�kd��G���m|6o���u�p��;�dz,u�+���-���c:7*����l�E��.\����`��u�W�Z����~���ktp�\�l7n�x�)���?�L���;�lz��\-'[���3�v�����W^y%�c�kd����s�	������L��m|d��G��y��B���~z�R���(.[���#����u��l�#������fz u���#C���w_�R��������<???���d��g��U�����7/s9�N���m|d������g���P�O�S��Rk,\�p��yUxb��x��G������>�ZM����q�/~��*<Q��r�I+V����:���w��U]���=��1��}���M�BCD�@�


���c�=������6m��fg��G��	g!�/�0��*5'�6>���l+%�4��_�J��l���s��l�9��������u��m���������Zb*����3����Y�xq�+���K��?�i��!CB�S�L������mp���&��]J�����o������M�m��ez,��~��_��W�_�~iV�d��'D�
���3=��u��d��G��[�dI���Y	�m��>��p&{��wgz ���^��<yr��l������%��l���c��p\����|��������N�V�\y��'���t�I���
��_��W}�Q���e��W^�~�a�}��������-�}��
��;�@:^{��-Z����z�6}���_Ln�����_�U��f���=��k`<�Z�����s�l�������4�6M������H�.�Jy������o�{���
x����K�����[�����Y���WW���u����lcu��������?T�Y�MG�������i����gee�������2���T��>�h�\�~�v��5j�(l�i�f_.x��d��p�p�A���,����k��Ynn��yU��U/��o���999���ov����o|����v��e[!�/|�?����VRR����>��'jd\�Xe�����s�l����x���_��W����l�W�J�l����/�������}��ww�q6l(�)�^{mx���^Z#���N�������Zb�d�deeu�����(���6M�g'n������������\^�J�o�|���m�F���_?���50�ZJ��?���s�u���+�9e���s���50����U/��i���p@NN���<.�me�?>$v���V�=�������/|�U[�r�R�9A�i��� ���5kV�6�����.��l�W�J�l�TRR]���/})��s��m����C	���%Kjf��Zaaa�v�������g�Oy���B��
�6V��sN�����4��6}��6�_���+���z����U*����pD���/����V��C�����B�-F��N�pl���iBe����T�K�{3s��I�&�n���{�?�><�� �����3�W�:���m������Q�����g�=�:���p�����	�e[��������������l�W�J�l�h����L�t�;�>�CVGyd:�����?a����Y�����
q
80���������.�m|V�Z���{�|��'i>E�i�B��I���-�oV�^��/~��s�=��������3g���3cXPXX��#�\q�_�����L:U/��Z�xq�z�B������h��(�h%�t~�l�e{����t�M�F�J�Y~���W^Y�������	�MU]s�l�t��wx��<��G��Sd��g�}��k���������f%\����z��G��&Hx�&�+Z�B���^x���ci]SPP��������A����I�B�a���@� ��G���-�W����M����C=��K.��p�����[�n���g�qF8�:��c��z����n+}n�c�����t�M#G��T��
�^��c�������N�aN�^��S\\|��g�T�4i��E�5k�dzDu��m������O���&,�;fR�_�����:����a����w��f%�Jy�����Z����>��'L�m���W����3=��F���m|d��p��!77w����N]�e���;6j���g�M6>��#M�4Q��G;w�|��������v�R��v������GT����~��������j@H��s�����.�(���#���o�<o���d�+����];��}��OD����
�;m�4����7��;��"��<���!��O>9���d��G���I�U��{w_�w?��OB�e���]�/�^USRR�{��� �����Z�yyyo��f��S��bbN�1���\pAT	��3=�Z��W_
I�iO�R%��~����������2\%<>k��
�
M�4Y�jU��R;��4����U�����0g��L��m��?'��m�du��M�������He��F9�����$�~���]�����?C���P��v[T�����������9��wm�����b�c�����-[�-�Jx�z�}����������kSw�Y�&Z���[5��_7n�N%���0�fh�u��)SB���{n�R�������P��g���aNh��]�
2=��F����� �����E������b���c��I^`�^]F�b�����7�C���
jxlu@�U�������;={����o��Yk�3'��WsB��	�+��_|����=af<xp8/�v��W����?�8p��=�}�����t��-}�
*���7n����G�n������]aaa�v�B������>���Be���l����H$�4UvN�-�8���y�������p���O��\��x����*�����6m�����O��e��pvU���[��A)���d=�
U8'��WsB��	�����k��}��G�'�xbTKgg�%}T�����+��[�{2������>���^Pa%<r���fp��BQQ�����?����w{��'B����/))����RU�Be��^xa��!��������^~�0��������]��FX�9'�6MU�d����W,]�4��n'T�B�h��pJ��C���~;jY�xq�R�u�{���Q%|�����K�.!�c�=v���
��sO���+<�`���?���o���p4[�}�U�p ������B�5=��&�9A%|���QII��O>���}o��Y���"��}���&��������O?M.	���(jT	�]tQ��y��.L�;n���/���SO��X�c�]�6'��>{���-[fee���EEE�rm~�C��Cj�����<��C��3g���j�*L��MSt���A������i�^�zU���0����;�fFX�?'�6MU�d������#���[��o������������B]N��������&[��A4��5���C�>|��L���I]C��7��N����������"�����B!�p���jk�����d�X���y%��^�HNHV���iS�?{cN�I���OO�	�{�^�rer�9aE>��C�|�����n���[�.�X��m�U\�����Z:�0?t��1dx�!���0t������_nN�P�s��*��n����o�3t������X�����c.;;��#�Sn
�V���;�������T@���"M��%*���c/�-��k�X���Q�D�+1b����AQ�(**���{�=�9���a���������9���gf�;����^h[M�����G���Y
���t����������w��Y��]����SM@�jBU-Z��`aa��v#�-�/^����Y3Q���b�^�Z�N]�O-9T��W~��J�*7o���w���l��D�(�%55�F��o�v���cG~��E�����&�dKN5��7j�{�����P�RRW0`7�������Eh��P�V-sss��X�8�K6�U���e���*U�{&5�X������'����'3f���C���!��&hr�A�����=N��G�:�d���x�TG^�|��_?�]/��*			�&����k`` �m�������u!������j�V��mffF
koo��Q�m@�����t�7o�����]TB���3g��`R�d�C����E��B�^�0L�4��6/Z�H��
�����^�������������@�hB�gjj:r�H�J�]�Jj�r���	�������������~��E�Q��-���o��-������l��VU�9;u����H�����q!����S===�����7[t�8�������X�A��'��y�����N@�]�v���R����������U���'���]�o����������H�E'���������;M@��B�4m���&�����*]��.N8��#66V���5�W�^�� �dP��������P��<A :�P�}�6��������O�/jCb��E-Z��������V�N�;22R�aiii������
4!��&�7.\������|��Y���59��M���v���n����+�*C�1(��3gKkjj��e�x���eK�CjL�+=����);tAwMN8�+��_�U�X1j4�l�:�y�iKM����C���!8j!w<~�X�]|���A%b���t��@�UM���
		��p�a����wwlll��UE������$�yH%hD�T��<A ��P���<q���3�����?��;PC�������;F���o_����p???�����E�LMM��������[��r94!o�&��J�.�~�z�r��.ir��	Z��	�!�%]\\V�X�6
oT���Q��5������-^�x�b�D�$���,�6m
z��0��&�<y�ZX�a<�����+�|�R�p������6n�X�{*99�G�p�>���P���[@���������j�p
0�����R�J��.\�`bb��Ts�=z���
&G�I�r�����b���e��U=�N�4kkkkjj��I����������=��wo����V�Uhr��&4i��W�8U��"��R�}�����e�*U�� 3f���3gD�&�4A����?�A�QK���O�<##�W�^p�rMff&����Nx~M�C�	��&M�@�g���@X�~��|��\>d��W���dee�31u'�9TA�$&&V�T��'
["�����Uk�	�)6l����������@�j1���I�	��cp�r�&M8}�4[�������D9u�v��QyPP���5T�u�F-v��Y����?~���������-D��\�pa�������[���+:t�@����z��}��u��B��\@r��,hq����X�b����EjHPK����	S�L!}������h��~���,��w��b0Dbcc+W��K��\��M�Kt�o������[�l)_�<	�����A�<g��u&&&�w��Rl�<x0�U��<����8���#508�7&gB�^�&���<���[�b�G���~?��#u`*���:Y�ZZ���!�]:diiI�����,YBb{���7>~�x�b6D��K�6f��,
������M�'�����_I�9��I����p���q5m�T��.p��d���~�sl�l��
*������]�v2�i(�Z���YRY�v�������<���d����l�������/^��1T�U�R�;vhz�c�������A���>�+`9T�Z��j��������O�2����m4�E�_]�e�����Y��ErU���'@���RG��d��9|����5�W_}���Rz
�%[M�t��x�.�rq�+���g�)wl��Qm.���gS���@�"4,�	�Dzzz��m�
���r��QNKK|����^��jp�>������������P�\9�[�i�F���Z���C=Vz��'����{���;�Zg�wC7�����93i�$>e�l�����\���@��������?}�T�hq������P�H��/�/ /�����G��X�b-|}}���0��������+W���P�s�������:u��7n���J��;�@GXh�����&������={Vl��&�ZO���W4#���_�D	��U�liw���d�	4�������;v$FE]P�����5Am>��
R�K�k ��wh����7o���M0��W�^�R�K�td�����_~����Y�T��{��y����;��D���n��U\��z����9�� �����������i#����9�7o�����W,]���_�����cE���	���V��0a�F"t�������_~�E�$N�)4�$%%)�>}�����Zu���1!�jN�u�V�B��e��Da\\\�j�������U���\s�����O��%Z\/�	�c����9Gaoo/��@rJJJJ����$�4f)���;kB�2eT}-�^���'��	111���Pi���E��|��Qz
�@�&�j[������}�Z�re�K�����{w�-���hJ@�{BBB�b>���m�H;�q�Fi�;vP���)S��B�R����Xxg��!�jr������R�=x�@��|����������@t���K�u]]]i�K�?�04!OX�n����I.kB�V��	b�
$4����-O*�c����_�|�U233�
��b�������i�'Qe��b<B���p�B��R||<�M�����T'<�����M��g����Z�+**
�:�@�y��
Q���s�DQ:88)R�>�>�Z���Br���'�t����%##c���{�U�+�@���j���w�*�XZ��Q�y�Ip��*�}i�H�+JT=p�����H4A�u��]Y
8�Q�L����,�����7��^�z��s'))���~*\�p�:uh1"w�;���3R�@wzJJ
o�%�M�&������-[�hQ�U�~��-����/�6���XZ/�X���������#>>������������N8��PemmM���m�T�ZNx�R�N�:u��i[[���'������R�����������|d3I�p��CUTW�4w��w������y���7�	�	��G��7V�'..�b��4������;����fPR��������o���\�PCq���%K
������,��KB��o_�g4�]P��	�����o���c���S�,\/���@���iBll,�"����n��K>>�	��6���U��_�|Y�j�&M����A���Kj�q��Q��h=z������;wf�;��H�a����r�o,Y��F��Ql��ul0jr�q:y�([�,�[ttt��W�^��U_������b��{��)���o�7������	����CJ�\�p�����C0hh���j�R�D��'�������E���+W��g���7o���N����	prr�v9��v����q����P8��r�|���83[�����*TH5���z	�A-�[
�����J��3F���&hGU���W)�Ru�4��8|��?����
hB��;M�Rd�1bD������'O�;�������e�9rDZM�[�7�7�?�����&��{��Q��&l������m���O�9i�$i!-��������~k��1�����������������
6�(]���{{{#��ZBCC}||8�}&�r~�a��a�r�xyy�o�����(�����i.A^���&���&$$�:���E���&'�����W/����;'-��,-&L��h�"�3�@��sg��2e�H��%����q��Qwww�
4[Pu��&h���������^|�RN�p�-7n4R9�*K��|���3f���.�����Z*X�v��#5D�,U���;w
*�z��Z��E�&�<y�p��9u�@�@�hB�3t�Pj+Z�K�phB���<n�8����f���666j��S�����5�#d������Dz��\�Y�|�Rs��Zi���46Q���Y�V�Z�u�:�111��4��l�6mz��1Z���[����:u��/ggg���+V�H���d9�6<���C�)���Z��&���M�����mIhJ���3�
j�ph��h�P�Bi��D�p�h��R�;!!	��E8����Sj^Nx�����T��p���ukj=��^��7o�,[�L\MJJ�����[:99�(QB��tp�tG�&����	�4!oIKK�C�����^����I�^�w��U�R���m����#FP�������booO�V|U��i�i�&��3Hh���cG�����(��	Z���X&M�,t����������H
>�U�iJ��A��W��dM\�4a��!���:���V
�
�%�+W���4h0}�t�������N8A�U+�	�p���[��Rl�:t���	�8::N�0����qW@D�$�/_��\/���7�	�4!o�����[���G�������TNS�]�v��jd��Q�c���f$Z�ei�^�^=��G�]8p���"GGBB5l����k�"E��LR�����&4n����0$���5�����3�x��1kkk��=�\��
�!C���j���d�*���GS�?~��gO-�1�������0�����|������C|555�b��T)o���p�k��A�.�
�	�^�:-��a�;'����s��?������fjjj�8��^�y�������������_W[�]/����v�o��%S�	4!��&�-�v��	�p�����I(��0QQQ|�#�����];'''��������b6D���;#E�K�.�����eK� �y�3z����������}_�v"�[�n���z�P�����+_�<��M�6�:����cA&>��3���u���
��#v��m�8O��Mm.�����{h���������&M����D�{����@��F+���.��J��Z�jEb��+	�%33�Va���������{��������	o�������Og��z����%�W,X`���r��A���x��L�VGr����3G�`
hB�M�?r��Ctg���zb������<k��%J�������[r��{�,,,�*����2������g�?~��R�����A��N����'-OJJ������?h+��*9�����yOaff��o_�����Bw=�uI�����]�[@��>ZTwh���6k�,00�m��J��L����(������s��������?y��JT�X�y�&�|������Bm��cGZd��T�v���sy�N8�9r���.��qc�����������S=`%11�B�
��Eg��/^�9�
GGG���<[��N��ph�.�� ((�P�_A>h�~��M�������,E���u�z2�h�j�
6�h��}���U\b��U<���������3gR�P�DFF�~ZZZJ��XfmmM����0b����	�@�z�'<K�7���k�'���':w�L����_�(5/uoj^�q�|L�~�B�Z�j%G�/4������<m�����gM�V������P��p��xkbbBk1����hWWW���GoA(����������3���
'<o������m����+..NK���dZ�Q��7�-H����...�V�((Z����
�W��#'h�fc������l��Q	h��@�I��p�����O��,u�8�@����={�HKRRR|||�$4H�R*��f��]�x133���W\���)}�d)�C���[N,�����S�_�	��V�-i�@m�v�ZQ��	J$$$,[�L�Q��y�����A�����/:t��qvv

JU�m�6���K�������Q�p�Bj+����?����������P�������N��9�;vTr�I�i�@�jjj�o�>�b6"##i�����Th����	�[�;�4I@6�l�YA���y=����3�
*<y�D��_�Ek���O�d���3F��
��5j�a����
����:p���l�p�d� HIIi��5�U�*U���C=�Hq���S��jBr
4A�d��C���-��K-���\�fMq�#���c�f*���/�DUh�E�5)���;E��������k���?0�[������5kx�'�	�lbooo�#�BC����')H�`����	����r�Jnnn��w���^�:��QW�X;Q�|���P��	��w/�T�Zu��
��=?1�)�H#s���2e��&�+��J j)���t�D�j�N8��S��| ""���l��bahff����8%�?����o���!��Oj���Ok�'\4�:uj���\/???�P��������������K���I"T��+W�pN`#�[$����)dCb�������K;R� [�8�,���
�������������N84!@��h��{-N84A����o�1�Y���L}X�t��#����
'�,�����:;v�`i�:����:t(AH���~�	)��$$$��I���������L�.ev�qF�.l����(�v#�� �pZP���<�]�vz����e��p�iiFm��������R�J)9�����V�V����&�3g���R�%W�^���644���J�1�n�.]:""B��3e���K�E�6m�6�nQ������\%'|���T��/��8q"���%J8::j�p��5���0'''�7Pb���:.��bV������+J���I
X�N����{��A������������4U�y�&�.O�,,,T�u��9�|!�:�����������\s��Ej7i���k��	�&�h�����k{{{��sj�j�&'d���[���z�����T��6m���u���
	�x��ikk���$i��{��:�@����w��i����C�T�#'y�u���;46��][������'''��aaa,�����R.k N��#HTMLLBCC�n��]�ti%'ha����\^^^R'|��e�s��C�0hHT+T� J���k��acc�x�b�'����<�\P�p�b��i�A-Z���_�W�v��R�*������Z>)RD�I���;���K�&�nZ�����J���#��?~�8K1�	b9��}^�xQ��'N��w��5��:���g��a��wN-�����C��M��p�����q#��H��q��'O�%Lr
4!OP�;���&�	�+V������$������H���;�S�����!6l�^e-�q�_.�U��j8�9b���nI�p��S'd���C����?/-<w�
p�����h������Og��9w�\~�hB�k��O����\p�suH+++U'\�	b�:����!�	��E�
����6���=<<h�ER��~�C�H��g��%��x���aCj@��U�S�N�.�)J�%['�=p�|��zYXX�8qB_�<������f����/�R,���r�����g���G��5��Z���S����{\>y�dj@___����������a��.���c�J��	�`��!��#G����w��uY�.]���_�~���l�8v�������_��&6l� S�n�����B��I���?�1X&%%���L�2b���3g��b�' H7������f������g���8�z�Q�F�t�o������o��]�4�Z�j�Z�S��F7������8��b��4���g��&&&��K4O���^F�|����	Z�)���T�r����l��M�1F���?��3]���Z�pM8C�C��h�Z�R%�m7l�@m>q�Dq�m��B!@	�#A��W�^u�����>����;w�(��7��***�.��YS��Z�pM~M�)��������+}���,,,<<<�VO???�&�?^�`?^h�U�D	^L����;v,���hr��kBZZ�8�B�
�1{���}�vv�z�����o�v�)����x�#50��F��;Wm��
���k'o6������������	����a���o���5����<xP�H
1��h�B�-/u��;�@�v����_���cE=~�8����
�^m���O?������M���������{~��X�b4��9Uzzz�
��T�R7o�T���9s���.@-j�pjyWWWM8������58�j��!��9}���'�=���c��=��i0�5A��N1�)@�~r�����{w�Fj�hr��lb�~���w����4+�����aq���������7i����T.����5Az�4!Q��C���G���������m���8���
�;b\311�����N8^&��\8�h��B�>��)Z����3���y����� [����w�����N8�m��\8�h[�\����������={�]O.ia���o���
��� V��]�J����9�2M�x7C���
���=X�VR�]�v�z����NxTT�$�-��[���C����4`���������K����-[��E��D�SN���������3f4l���/��F�:����Xj}w��			y���RyDD��J��]�v����1:��F�|�K�@>�6m����I-&�_N84!��p�������/�H���R�-\\\J�(��b�p���E���9���C��D��/DV%�9r�cbb����y������{���t�R�=��3�����%6����'�W��>}��-[�0��/<x�Vwr���|�m����)�b��aaa���v�r��}��%*AU]��j������y�7n��jdd���+�<-u�-[6q�D�������Z[[�.]�&��\c��-\��Qv'f]��	4�r��M�����&fz�� ����f�R����D�,GT�Zu��y���wss���&M�1f������;�-�i��%K�Q��3�.�Z��-akk�u�V����O)��.���m��qc�Gj�l��Yh�R�Ih�������}{#E�����S;��__�	�f��^^^��U������?u�Tj���!6�&99���F���K:�
t'GN8�����}}}i�"���A������'�n�:�C3x���$�!��t9	�N��p������'������H#�ts2�D�2>�����T�l��8�BG~���A�[�N�����>}��SB��1����������|�+Q�re8�H��@�V^�q�����N�:QVM��r�������������:����t�H�"Bh��x�b6222j��mjjz��IQ������;�1�p�w�n���egg��r���*
d�<�q:5^, ���DEE
4(::�z���N84!��5Jj!f)����	�@��{��*(V�����}���T�y��8�Q;�Vl�zzz�]�v��I]�t������9�:�����1<C��)�z�>/[�LK��� �?~�� 
???^�-]��F�&M�H��Yp���l�pM���-h�k�.������m���mnn~���@�������_�>
XT?$$D��
MNx�"������3HTq
�.L�8�Zr��MJ�����j9��\��&d�zO�V�Z��9�%�MNx��'���4�V�X ��o��F-��wo������}��1�h9`�8�9---%%����c@�2.tvv�X�����&�>�)$�j��,hB�y�����Y�r�T���^pr�g�v���HZ�����g���c�@P���������[>%��/�|���\a
�9���K8����������	��V8�w�z�N�>M��^�zq{*=��&%�2d�l^�lY���j"��i�%��N�vr�	Z��6m� 
������#�WZ����[����>AH���I�0��������+jq�A�������y��)�%K��l��.������fff��v@j5A�r��e�4IkZZ/�h������5j�����X&u-ZD*��������-����=SzX��	9���+��4}U{U<�6l������#EIRR?�Rr�Ef��S�������Q�V-jF�#��:���*������l]/�).�N8�������6h�@��%'|���b�x���ccc����3f5��UGM'��)��&�| ..�?kr�!44�z��}��=��i�Z��4���K!!!4��#XC">>~��A������GT�p����O9"5`h�JmH+,�Wy�U�D�k���96�%G���Hn��11[���	�N85)Nm�){���6tssS��������&&&��m�x
M�7l���7�(]R��?{�����s��~�4<���-ZT�dI#E���s�JWUR'�3##c����&�#bcc���-�6�5x��Uy�0d�-;o�j�R�J/^\z�%��=Pr���i�#M����CC������111]�taC��p�UV%<<��(�F��;cR�K���[�n�h/^%t�[[[�&(9�4�=z����#R���������Gj����t@<��e����*+��&dff6�\�rb���	"4�j��
��-���>z�h�
�\/�-<�S/Il�yy�_�d���pz���q��%J��[W��
��g����6?u��>��B�
T�f��X�f4!��E�NR�}����k.\�rMkmmm�
g����B��Y�m�S"[RRRH,--IfIEk���ZG��%99���H�rV��:u�>�N�����
87;�7�4o��H��Z���+V899���Q�����?<C$::�S�-�[�n%�	��7o���v��=J�������KY���y���j��������
6��b�^d����W��^��S��K�	����������{����k���|�J�*4��D��s��9������V8�����q��U�,�%[M`\��N���. ����wvv6�@����H�jp�r��*T�`aa��O?��&%%}��w�������������E�"�u.�����V�V���e����~������aM�?t����0vq���5����t�3�+Ak��c���?gg���;�/j3��	�_}���"{grr25������6Wr�k��)�_��O@�/_655��#�U���/���];88x������@�Q�\���w�'>*T�M�6�u#""�y��c�&�n�������h���\��N�5k�v���*�ez��0��zi���+V �o�h��	5&�jM�|��|�cZZ}fMpuu-\�0�DM��e~&:r�H6�i������W�C����t��2}�k�h�M8s�������R��=z4-
6o�����}������-����*�������������e�QBm���^���{��M�7o.}�h������o�+��>�����'������K���VgrDjx@��iBddd�.]��������	����������4��2e��0R�LNHH�r�
-�����T+'gg�g������p��A�	JN8��Q�F��Yy�u����w���5�����m���;%_�}����{��FN�_�dI�-H���U��l���|����������y`��j��-[^���X�W4��K��O�{��Z�����Z<p������@��������\��~��������F�w����)����r���v���VVVNNN<����_h�����<�K�7�#d�C��	��z�4C��S�<rw��-[�,��U�TQ�z�${�t!99�p���EI0���cll��?��^@h�b2fffC����"##��)�����y���������^��h��O@�	-����;>
�=z4�h���i�+w��5]������o�rr	Z��=�b��us���c���xy������e��j��]��8q"7 ���%��&M��-ZpBZ��O�N%��/�5p��F.�Ye���6��c���Q�FAAA7n��W�����c�g�,H��Z����*=��������r�k`�� 88x��E�R�k���Z<p�-���S��r��A��i���5*&&&$${��s��!���{�IN�9u�g��I��?P9�`��E�;�����m(x�<�G�?��S�&M.]�$����:���##E�_q�������f�Y��^�'O��k������?vrr*T�P��������sgN&C�<TEEE�S���)��ASSS��6[�	�
4!?�V��}}}�m��������>c��c7����gN�:���OZ�����	:�/1]�p��n������[�n���;v��~��ukR�5k��<	@���������4a��!t�)N

�:��e� ��yB�r��y'p��vRRR��[�hQKKKR�D�^^^J�lbb"���={��A�x�b��K�.��Q�E��������C�R	�z2�kH�[��F+�:u���sR�������7S�%Em�����7������j��P�}���--f�N�8t����9�vi���k���T�|��Z�}4�O�������}������ph0��������(g��~���|�����#C�S�N�����A�UZ|�<yR^�x�����\���4q�D~J���C�hB~M�st����_�q�����u���'�:88�1B�*��<�C��!�A-/x����������y����a0~�xj�����>��x��"��s�h��
kll��o���D�B6Ho���)R���_T������f��6m�������o���Z�n����:�+W�d��U�&	��F5+P������]�v���Y
wk��e<��t:��%K�H5A���P�����+���Kh�#M�#]���%Y���N8-J�*�-O�����������rl(@����i'���]��F�^�V����;whm��U+�����O�0����f�83H������T��q�5�^
�!��?�8{�,^��hB~M�[r�	iii���?~�8�����K�8k������O���	�p._�|���,�fWWW����s���}���Y�f�B���\��������]�n\�X1��7n�8z�hTT��B4XhT2R������������r��	����#l�����*�1�>��;�y��1MYi������u�w���q�B�
K�.E��ly��!iB�J���4�t:���MLL�4iN2��Y3jOsss��@�L�n��.[��h����@�J��z���8�I�	����<y���#]���#�U��U�	�-[������+K�z��S���V������D��uw���)�"P��FH�U���"�@�	���'@���� ���R'�_s�c������&M��?~��!Yx9Wg8���%KD�Z��:w���m[�566��Z�>m�4��P���'<K������&N��z�����
�p�r���+����KKK�����N��::88��{W��
-N8��^�MdI\�q���^���tssC^�ly����1c��/_�T�n��)�V���/�����E���Oi ;x���#5`�w�N���o��WU�����������hB�M��� ���M�jr�����ddd���W�Z���>���TJ�<k�,#���B�L2��0
����K���8
a-Z�X�l�|1*;vTJe �Z�~����m�zxx�����M�<x�`��y#F���}���R�������)�W��f�i���6l`{�a��|�6��+V���_Z"�Z���?�������?5jT\\���4A���� G�4�hw��g&[bbb����`LLL�M�&��~����`�s�Q����)R������gS3v��)KC��3fPd��p�	4A?@��v'��-����j���k�N����m3R$���������S	�9����O)�ILLT���?�@���~�x������l��Y�f�'�*�u�������t����4���	�~�:�-�����{w6DH�9W�J���+������#48���<==i��W/R��j�p�#�5A�����3K���J�*X;�h@�������033[�h��{�h�J_Y<���+6Hf���J�*M�8�v���y���rn`DFF��@4�R��w��It����rEX��&|��M�'��p�~"����/]�����U��"799������1c��Y�;v�;p��...�t>>>j��=z�������m�V���\�r�2�	�s��5R����O���)2~?y�D�mK3
j^�@J"c�������\��f��7�P�z{{�8�lY�p���(���;t���F�C�����%��M�z��?���m�����Va";b��}333�����E�����@-��_W:�r��	����U��������lmm������M�?�	�'<w$''[YY���KZx��NAY�zu~����{��3-[�T��>		���5��������[7��]ua��e�V}��	1b�:v��j�H���/_��aAM�B����%e��Qu��os5~��cYr��������7n����E���������-�.]"h����C�Hlll�����U�)u������&P��9R<IG��\MH��RvJ�Z��+  ����}-)~~~<B���s	
aT����Kt�����In@{{�pyjj*�MTX�P!jX��)))]�t���Q��t�	9��W@>Z�N8������=zD-v���Kg��a'��d)��l��y��)AAA��)��	�><x0�Ps��!'Z'���'����K��G�����i��������������������Q����yLL�(�p��2j]��'O�={V�H
�K�.u������Z�j�F�z���;v�{o���>|(�����T�a���50h-���.D����e���]���p����iB�"�:�^�A�-��.l���e�E�-4���"Z�����3v�X�P�H���.]�����������F�������sW�Z�W��k����5k�QP�R%�J
.�?� M�hB^M��a'~�.�\��7�ZZZ>~�X������E�-����&p*T&33�C��n��������G������y�'L��x�b~	�I�&b�������]�V�n�s��I���jq����-qqq���������+���U�F��^�=�Kw���1�����{)A�+6:t��R���
�_4�%�077��F����������?~��y����H�N8<p]�&����HD-�L@��|��M�
�F�Z�*]]�`���3h�T�~}j��%K
�������j��������}���F^�r�����K�#r���Y#�?��M�h��M0�	:r��1~pC�]�Vm�!C���V�Z�96b��q���p��D�#F$''gdd,_����D������8O8C���[�/���08|�0Kh���CBBT�jq��.���������,���4�����������c�p�������D]�g�$�����R�P�jF�s��%i�)���Q�=���'O�����6n�����W���	�M��	�O���5���Sm��u����n���?6C���u����^4�Z�p����1c�\/���7����?A`` 'V@v�	4$��=K���������n������P -���o�N8-f����u���kjj�d�����������7o�������^�~�X`��3p�?�V�Z���e)�z�xgccs��]q����s�j����l������q��|
9Cs���K�_�^&''�]����Q�FS�L�+����?��Z�
�p�?hB�M�|e��<*�1B���]����!C��!\�R�J��s���O�>U�����#���@@A���s��7l�P5#GLL����

T�:������Ha�:� ��&v���ZA�����\ V��y35��%K�W=<<<�f�����0b]�3g5��#GD���/i��w�A�4x�`��R'�����x�4!o�&@~#\���GK���Y�fT~���3�����T�D	�s@�^�P�&|8�P�Nx��Mi-&���9��;W����ZXXT�V-  @����B�6�����U+��3t�������������k�������%��j�>Mt����1,,����]����m�kb�p����z��p���W�^>|x��]g��-�M��	������_^�|�J?~��K*�<y�����"�/_��\/`(@>h(H'���)(((---11����.k����	� ����C�u����:���h��k>;[P�t�c���
�Z����������*�x���*|���e��4���0aU ��/��v'��������:*�!caa���'N��&�	����"�-J�-Q���#��Z��emm}��u�u���������h�&|8�P�N8�XSSSss�a����F��:�[�lQ[G8��A��0�u��v���[j�6m�l��i������F��ZW�^�V�ZE%fff�����G��������{�n#�y"�n�R��`���Ta��mrEX�����)R�����U�X�����{skhB�M�!\/��������Hw�������I�~��w}E@��&�h(�'�I�&/^LHH�;"�@�	�'f��w��y���+����\all<t�PQ���~&������%�.^�T)������35c�J�X����w�����c�Nx��N���HsZ�������������-4!�H���&�>����S���c���#G�,Q�5�
.\(��u�0�	�C3�������Qs+Vl���lB@AB8���}�����|�h�]�p�W�	�����3���������_LLLBBB�$99y����	T��m[�]�IMM�>}z����7v���������0KKKj�
*(��p��	�V�Z�o�NxN!Mx��)�Xhh��%???^)��5+��s\\\�C��W����\M}"\�i��������i��V����|���p�@A��)))m���V277����]�v�B@AN�.h�8��D�6�����������Y��V��z�:v����1��+'"Q��%�����o���kQ����� (^��8L���CT�����`��m$��K�V:�|8��{{{s6����PZ�.X����g���V�>}:g" 4A�����U�7��������'p��CcP�5h�_�zu��?��C�\/P��&d�P0`���o����g��Ah(H�	��l5N�>��>|���Q��566655UkyQ!��y�f�GhP3r���?�\8����cM���		�Z�*}%!���?���3g��)��-s�������;��S
2���H����%Y8x��jXOOO���O��g(4Hi@j��
^�p!<<�c����bs4��p�f��!w,4����={��jp�@A����w����4o�<33SK5h(HH�pl�RBGM�>BRSS�v��#�w�}��;��{��sl���W�/.u����+*$$$4i�D�	��9s�T�V����R�J3g�|���<�$,]��5�f��j�������)SF��
���^�zU�\Y�Z�	��Q���ph��+V������O�@>:|}}ixz����
7o���w���c���M�Y��4a��-�*�<z�(�
���;V�@>:t�����;W�����4�����C��`�g�p�5j���k���������N8'b?����U�>�6x�H������M�����Ju������'���r��1���Cc����^=q����5-��+�wg���ct�#��,Y��4����jTTT���}}}�+4$���/w#9���!�	733S}�=d����!R���u��%K���+U����?^�]��;wR��A����PN�����_~���f8��"66�y���y���\>y�d��V	���Y3�
�iii�z��)+}��a������/_��x�Q��k�������qh(�'���d��| &�p�����������N8������w������\x��)[[[Q� �pb���j��	 <(\�p���O�>]�r�"E����P��;whE@���U����/ IMM�^����i```�n��N�=�iii����7���vrr��/_��{��|�
6�	'�����k�'?Ro��_�.'���M�]/u�9]-�	���l��E�F��3
�xcTw�nnn~��e�u�~��=��Sf��E<YXX�����|���|��|�~r�����{w�F
������1���9sD��#G��%����wE�����{��|�
6R'|�������d�-����;�R
��E8�k��	����;(C��LU��������{=��S&::����F(Z�rv&55�e�������k�4��[�.��:uJ���HZZZ�����Wz�y����(���[BBfff:�
g��-C��|�
<�	777?r����$]�vm��q�~�BCC�0['<%%E�a�{�>u�T�c1._�<h� ���;�S]�p$O�g���-,,���i�*]���	OLL��2��U���7o���nnn�u��I2��?�
�5j�MMM5�^vvv&LX�|���'���^
$��)'\G��{��S'#	�{�W�u�0 �>m�4�c���?>�Se�T�"������$***$$���g��K�	OOO�q�H�"b\���X�x�����������ia���:x�`��e���IIIr�W�	�N�.����������aaa3f�P��
'$��g��?�����?~����s�FEEI+�	�q��	'����l�B��k�>~�X��D��Ek����Y�f-^������+B�>�&��p�;v������^
N8(H�	��������������p��KFF��s�������V�(���t���W�\�jq��'O��<yR���
<�	G@U@-��?�h� ^N������;�H����?�L-�j�*M233����$Nx��}� �u����+�Cm��#GJO��:��o����/������Gbbb���E6���������R�k���T����6m�����2 �Y���c*�����&�B@��&���m�;�����[���i�����i�������W�.Y�D�����������rG���p�B��
6������=zL�0���x��fx�@�[ZZ.\�S�N��7�n���:���8p������#
[2�
�'>|X�|y��===}}}-,,�s�
�<y"������g�����fff����1l@>����NW�*U���S�dI�\�H�S�N�:�
<g����+!C�����j2y�d�JK}��/W�\�&������F���Ipp0]�������S�������E��-[V��
���Z'�~��l�������2��G����W�.�t���|���>p�@�c|��52��_
D���q����R�����T��C(�\�p�u�>�����W���W�9$$��i�@Tu��->)O����w��/^�i��o��


-_�<����`eeE7�����������bCYh��

C�W����?�{����j��	&pj@�c���t��EIzz:Ik��N�=���cz��.^�H���������O<�:�Y�
(����5�7������"�gQ+Y���!<<�.�n�Z����)S��
^�^=+++''��r��E�8������~���aggW�pa~������*T� J���k��acc�x�b�'�_q���(���[�n|�u�d�o��T2g��'����Y�D�x��������%7n466&e�DjE�9y�$_�T���7LMM��/_�<�p����899Q������g�?�\I[�n�{��|���w�}���D�Z���B���C��
Z�z��'�6m������=X ����4YZZ�������AZ������U�V�^/��{���Sg���r��_�����7�����[�W�^����+��/����s�����w�Bw���#���������t�B����_;;;�U�%K���?�~��8>�������z��Qw���SEh������;w��?����;�xyyedd�3 �

��'gG�[�h��Z�j�����:b��Y���1112�
�S�b��:t�1�g��&&&��K)))��g�����E'@Ae��!�*U�w�}��a��'NW��m+4�r(�������������������������0~�xY��#s��������766Vu�cbbZ�je������y�F�����c�h��g�U'<55u���,�
*��sG��|�DDD�������4l�0�������O���m���~��L1�Gll,z���++�5jHs�M�>}����G�����I�|a�M�����iV`ii���#q�����7���o����9s����
�����S��������#A�����}����?����0�Nx�"���Q�����6m��l���w2E
�����W�z��I#��3g��+V��}���M��[����#-:t����@�$&&�&���+�GDD�&4k�LZ�k�.WWW=F�(���>A�8��,����:u���,--�
���q��}����.]��'N�, ���	�g��r��MsZ{{�����, �IKK�<y��������>>>7o�WO�>��3K��m��m�������?���[�j�����H/�:�)))W�^�!J����	j�����K�(|���������<<�9w�/_�
������K��}��>|�����l������������`>��_jNJJ���-x���������K���-Z�T)������
/^���lyq:��������7 ��?�4�/}^�l���p����kk���8��+�j�p���������k�R��G��0�O�������t��-��MKK��m[���i����:{�,Ux�����#�XXX��_�H�"�

		�;p@���&>>><��U�����j�@�a��ut�>�S$�;w�Z�j���/�:�/�gg��+��-Z 8�%K��=^�^���O��q�W�^|��H�	'�5j�\�5A8�L�������~x������?� -|��A�
hl*V�o���~�:ux����;r��L��5!11�O
 ������'S��|��-[��&<IJJj��=+����h�"sss.���E�O
$�/_.T�P�
�G����W���o�>Z8���x��I�4���5j��=��?�{�>]���f��N���'O�����������U��SZZ�^�t)$$��r��_r�	Ddd��c���3����_�x�r��J�H1�	/R�HDD>{�����s���#��n����O� J������K�,���JOO��������j���K��d
>�F%777KKK�+���o[YYQ��+W�?<���&�����]n��Q�BRR������������+���������]����R���g�F�����9sx�]�7Z@~M`<z�������'����>��������������S'���
J�����������W��!@�4i����m������h�����Kdiii��E����p���9\@>M`(���T�\������?���}���c�h@Jjj�����i�J�������p=����������g///sss��?|�pKKK���u�&$$�&@O@����*U�Q�d���U&ADD�,Kl�MHIKKc'���$((H�jFFF�2eLMM���S������
�N�6m��Q111!!!�$��4�A \�R�J����rZ�v����w��%cx=MHN���������V�XA�C��+6@�r������w��u�������K���������B//�a���7F���&(����l��Q������1KK�`@��"�p�}����������-}���LJJ�;@@��l�2ccc��������O�r�J*�\��P�����o��U���4@�A�^D���K�(��a�={��@�	)R'�d�����+V\�`Ajj�������@���T��z�j???�������7��111VVVT����<xp��eE���Crr����h��p����/w8��&�'�����_�;@~���NC�:u�$55u����z���###�
�9Bj ��:88��{W���4@�D�^������&�'����V�r��{����>}J�yhh��%???v�f���%���O�>}>���Q�F����=X@�MP����MH�@&44���f��t�?{�L�������/T������@�@x�z�@R��PP�?>��466>x��j���OOO���O���3����rqqy�����d��"u�o��!w8�<c����z��YS�������e���l�M�)[�z�}��������N���c����X��]����^}��9,/>)�	>h�+w��h@Jzz��!��z�?>33Szi���T>h� �b�h(x��c��O�>��S�N���:88��'4<��eii��E�F������GFF�@�	��!\/�5k�gdd�@6�	��!\��S��@~�	��!\�i���@~�	��� �
p�R�	�_;vl�@p1f?�D�D�n��\���^���-�<��>�YU��/l\��F
endstream
endobj
13 0 obj
<</Filter /FlateDecode
/Length 2141>> stream
x���]��4���W�5R]H�-���Jp�� ������d��l�6�Y/eV������������:���L�_���/�O�Dp5u����������������9���T�!��R��?�vz{�>�AE'�;;���>�lV�l*��M�d�������T���sVXW��K�j��n���~ywz�:_�S?���'57GX�U��Zw�$��2H�r��~=-�����~?��)���%Y��� ��6818_
^xo��n6�j0"H�J�.����\5|w�+��Z�A�tJM��Hf������pR���58)mXJi��,��-��R�T�,Y�Oq.���H^�$�lx���wl��]oT��G�}�e���7���l2����-N�����4^��6])n�t�aO�O���g)B�:R|���zR�~WM1��Gc
y����.�X%�&fo�Q��g�a�U�;7���n�����FZ��X|��?g�������!0�&�x�`�������D1	�l�Gq$%�,��'i��Bnlt���F��j0u	j���s���i�i��]���������Z+�6T�sh�8���s�.�S����Y�e���	o�R�t\;Y�_��t�6
(
����
�NH�����K�!LM��1\�5����&G�`�L�3��=��F��YH��������Q�c������3��L"Z�~����J��h�[�?���
����m��^X�3��KQ������m��>�U"�.Dp��:
m�7����q�����["$V@Ek�0�{����N�>�P�F��'�j[}�P6��'������j+�6�@���1�{���bn���I�/�n���$����B7a���L���d��W���YX��!�$���I���<����qZ[���JC�1�����n�S]����L�qS'd{!+�~�M&�����bx'd=���x�������/n������~�A�k�^�"�Q�B����B'���O`�Gx6��b�r���G��4�
�l���/|Q���7����x�_�#�_a�:�LxJCx1��k��-l`:^����?��8^<]'dK���:!��t���:!+>��#*^x#���Ax��0��	^���M'��Dx��M��X��S�s�>�6����x�_�#FvVK<���E�!��	Y_;�!���Q�Lg���:!�R��O���#�8^���>�_��,u�P��c����l����m���9Rh���2)�{��f�!�B���}���������Fc�XDc����}�9A���#�X_g��l'`�n ��
����~1m���~OX��W�3jB(PB�'�R�n�cT%LM�'�R�"&�D�����{k%��,�3�K���]�usR
Y<�����Q7�b�n�z��^�O�]hx��#U����%T��@|��e���B����_���it{�k���l�{7c�7����AQ�����n��fxL_R���C�n�p���HT����E�.�q3'Zs
���������������A=k��/�o���Q����������������p�g�����3��]
Gr\��M��Q=K�������K�7^$��-Y�$�R)4��K�I���t�=;J����X���zV �/�`]���0P�'�j>�_���I@0�������' ����`tW���n�$ �,@0���OC��1B���d
.�K�7L�M" ���C���
��gB���A=+��������u& �! ����&�M]
���= �����WS"*LxW������g�1F5�Q��7(J%]*rD���1���f����)�Z������)G{w~��S���p����)���_��S�����|�x�Ck[/rH����|W���F�V��Y��.7U�.�}���m�������Viq���EnO�Z�:�.s��&��B*���:���jI�a>nv��I2e\k���������}>n�[����fWZ/3\%P�U�J�A�=e��=��Z��~9&
�Hwm��'������tL� Iu�_�����u���b�M�F��k�
{��;aK�CI>�H�S�)%_���������]_�H+��kx1g����t����9
endstream
endobj
2 0 obj
<</Type /Page
/Resources <</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]
/ExtGState <</G3 3 0 R
/G5 5 0 R>>
/XObject <</X6 6 0 R
/X8 8 0 R>>
/Font <</F4 4 0 R>>>>
/MediaBox [0 0 596 842]
/Contents 9 0 R
/StructParents 0
/Parent 14 0 R>>
endobj
10 0 obj
<</Type /Page
/Resources <</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]
/ExtGState <</G3 3 0 R
/G5 5 0 R>>
/XObject <</X11 11 0 R
/X12 12 0 R>>
/Font <</F4 4 0 R>>>>
/MediaBox [0 0 596 842]
/Contents 13 0 R
/StructParents 1
/Parent 14 0 R>>
endobj
14 0 obj
<</Type /Pages
/Count 2
/Kids [2 0 R 10 0 R]>>
endobj
15 0 obj
<</Type /Catalog
/Pages 14 0 R>>
endobj
16 0 obj
<</Length1 32192
/Filter /FlateDecode
/Length 18313>> stream
x���	tTE�?�T��}{����^�KB$����Pd_$�HDvY��Td�q�iB����(��00������D�apM�{�nwhP�w�������?����>��nU��g����D�3��f8����1����N�r���11���1q�P����$��}�N,.Yy2��W�}����S��4����Xn���q��\�������g^�,t���/$|^=�����ri��&�/��������+1�<{��n���7g����"���@�����YG��cy�(��?#���0�c!:g���{�8��q
�l�8�z8���[6�X��il��s�>tQ��&WC��T��^��yY�nE��-^��8���}y~��0N
P�I��f}9��J�H/C1L��{���^~�X��r�����10L���x��cN;����S���q�f^�t�f/m��9M3�BhA��� t�LPy�\��EM7W�[����{?*(b���
������2h����I�s�M�������
��Q<	@!b��C9b���$0F"��s��D��p/[����+���R,��\������QQ�Z��y/����I��T�u�'��`��d������b#"o���=32v������c���!P#`�R#4�\X�`+	������:����9�����G�q���x�y8��s�5��H��q��B���;����~����v��d<O��)�g�Z��~�v������N���N7u�N�]�!��ygj�|5����>��P��sZO��8��y?���>E��`~�R����rY>�DxPJS��8� W�c�
c��U�7,�M�SF���!���F����w`^'����J��L�<�a$�s1u^Y�)x�P�9*0`��(~0�q��:�!�(4�2/��L�	
- fh1'�
��K��Hr�R��F��������c��~��}��1��,��y�	����?�^�B����	�k6,G�cO�;���Y�5��3�-����em��n)�1^iao^��L}s��9���������������������Z{-6�dG0Tb��������Dv�_�������_��US�^F�+�_�_�\����Bk����}��+�8��c��������H_�~��x�����O���U�/Q�^�`���Gk	�O1|��]s���tv�_�����0l#sa��g�q|j;��6��P��+�f�I���X�c:9�n&��b�9�8�y�C��N�N�`��>�mC>r�8��������)��W�����������oH����=�_p4�(3�<��J������up�G�M�](Q������<u�P/�������0\�m�g��4��7���MV
����������z��;a/�GF���.=:}�X�
,�h��x���mbPO��>��R�
���d�������
2�R�;g�{�	^��$B�L��URuY�u�L}�5{���|G��s���8<=e~
��z������d
�A������zrI����n���'	���!�>�1�'u^���	G$�G_����o"��*������������#��R#������c���d<9��!+�Zr#��$��gt�D����9����P<Qv��U���S�5��@����K�������������f{������������0�L.��Jr=��<L!mX�a�!��|K�M~��(���h����K�%�fz=��a�O�������O�j�E����f<w	�^����~.Q����zX����q�A�J�W~������.�Z�ukWkW[����)?���z�u�
��@>������&�b�L'���{�r'y���	�4����kl���y�{�~t(����.���M���A$A/��P$���&a�p�p��^�>N
?��ubP��bB!N��w������T/�>V��������H����8i�T/m�vK�k�;��]�d�!G��B��n��������y:�FS�T�0YG� m4�Z�D�1p\�c_?O���t�0��"a���������R|:������%�P���k�Z��W`��	}���2�-!�x�#���t���q���BX����+`�A7�'�F��1uL"%�{�b:��\����8�@9^��Y�l�J�J�D����H]�v��\q��6��#�v$J��!������[h��:x_x[�>!���&�9(W���$�.UM_%�A S &E��R(�x]�Z�u�n������1���s.��d�w�y;�	9h.��y���
m�I�f�L�j���&����pGz6\��	z�>X�^�%>�&x�����h%�}r�j8=���E7���Dz�����#n��'�f0���7���JoL����Bw��$��-��F
���k��.,��=����Ds���~�T�(%p�S�U|����NH/���b?l�^Hbo-G��>9l��!���gUX1��_YiI�>��{�L�(,�����p(�����������l2�:�FR�D��Y�J�Rb<2rd/vi������T����'j��B��Lb����Tr&�s9T	��z�j"����H��L?���#��T�Gsz3��H���@��=�:�"
������l�i���v�u�"��t�z��I=R)Wd��L8A]5w��j�F������'R�Z�b5��R��O�������z�����)�M�<�����R�&4��
\��s����2�hHfEf5�MM	���K��N�.;�>u��[�M]���6�������
kC���������b�,�
o�0����8jbk�kj����2������~M��0/��F�F�l���C����	��[�����Q���6L�	��|���j�;l�p�NO2�9=�W��E��&s�0s���4N���5��g	kQ�ld�Thf[25��4�A��0sf����S�Y8"sS�a
��,�=�R��Hh��9 ����c31���o`$��nV��,�J$REE�E�a8������_����Hd��v���m�X�����=	3�&�2~�r��VH'jS������8&���lJ��
��6�q;R�x�?������"��"�II512j�����

��5��;%}@wZ�J��M|4CQ��S�)��3������j����%
r%�!��)�a����p�?|�=}�=�/��4350q�����Ok�a��
FS9j��
t��!�)��� �������LF�������,��RI��a,����=-�/C�����W����6l	
�����=�2#�#��g�3�4d�=��:_j��Z��9d 
��;"d��I�n���{d���IS[)������b��=!�$��,�E����Q_��jx~��$@Oy���N��i�qf�S%N��Q���$�c�1�&M��.�����c��uz�������#�y$5��<�V
<�����a���3�hX��}dK�jN��i$�N�I�fy%,P���DF��3�Y6���BnN��[���e�$�l��Q�JM�q�llCnN�6�l
��V���*
�-
p��ek��L��u������J���e#����g��V�)������fe�d�/��w�8��dsN.|��F�@����@Qf�Z�B�(�g���e�>N�m6AnN�ie�9�W�be��%=���n=�l�.c����[d������y
#L��T�u7M�1 ����3�FF6w�8�����ee+���L,�����=�5!��y�g�����}d����rr�l��!�����{�c:3����(9��}d���.6�;u`U9�a���aee��H�ed��/���*���������������S��,;��Q�A��#��c�rry\��a�������VTE��e#w���L��C8'���y�8X^����Lvd����e����>2qA�� Dsr�l�����������1�Y��0~F����L�8���\XU�k��������B�������W�3���!�}d���Q(���U��F|,o6��+I��}`��g�m�!�}d���E�+'V��!�cyC����1[�����3�v� �}d���>��,'�nNU1�gycL6+�c�|��QU�(�����#���/��9�JzAN�� ��!�[��c�8�����(�����G&������*/c���7���Q��#�c�"d���5g��Bi���;`�Y02'�Y,2{�Bo����>�=��,9k�(8��a@���0r���5l0������j�9�=.A������qw���B8��
=Zy�=B���:(�l";����^B}�b�!�E�c�'�oQ���v��
C���a8��/"K
aX�a��,E�����<�@����������� @��X�1l�����c1�0����q��\�7�b�]�����yJ�m�r[W�ow�W�\G�W��g+�*���)���*�����+iaW��d�����tb�#z���j�*8 ��
�LLR����K��D ��`z�@Z���!:��_�=��h��B;v�,%[��C?���a��x~@?�U�(�s�*[0��p����(�G�|��f�c��0��0|�A��!��]6����*���(�w���A4���z���M{����d'�"�._��:K����?�@���H#G=%��`(�[c}�����rn��~�3�n���)��}k~B�ah����7�zZ0l��C
r��!D_��
�7��$�q4�p+V�N����8�_�hU�� ���B�����s��"^x}�>��=�>#�U�k1����wF�����}D,�P�a,��6aP�}4�uV���</�����9�>�j 9/��C1�<)�-�-q���z�2��pR��lD�A���H1�/�)�Y��b�6)����Bh�w?-���OBC����K��.�^�Dz	;������EE�cw&=��-{I���ei���4��+I�j�RIZ. -	��'-��$-O��-$�v�mE�MZ^"-�HK3i���i���)O��p����R�/;�0���Y�Q��i{4�<F����4�Kb�P���`���EU�}��%���������0<G0�8@�"=��<���0L��������}�����X��
�t�0|�A���5
�2M��V�i�XvG���}(�p2O��	y���O�26��rp2�j�X��q�w���3�v���@7����3�M�?��������C�6��u��$�������_��e�������?3��{�{jw������v��g���o��E��;�<�;��}���v
�<o'x��Y���������;[�W�������~���$\��wIspB|Zp$�W��L6c���U���J�~����>���Bac{�y��/pry;���)�*M��J������R�����F��4���8��P����G�	�
���M�"� �i����?�S��p�l�(:j�P2*�&��J��i'���R��P����Q���$F�K�	�����4���;��cSt];�IS�I�E�����=@�e��>v-\s}m-��W����-��2�8u�O��R���85�h^m�����Q����=�[r��z��]j���ok&�xapum��v2�����!�|��i�0�|��|w*�b�<������j���i�<�HX������(��
A3���
��y)�yb1���/�</9[X��`����,?�B���Y����L9��8�e}w���&����W��f��b��z4
M$��A�3���pC��	CC�����S-3B�3k3����3��kcS�6�T����T�+�u,yP�z��L���.�T�:(9�&�X]�s������Z�]W��_)l+���5��W��Y�VW9����5"9�����M���������N��!�6���C�����y��W�����0��)Cdh���%��kKB�bI&� ���rP���<�I�1�
�e�����fn����Z��u�����:0�&�l�n^���T��Q�������$�m`������k������9�E
BwFW����L�_����u����N��e�\+��&QT�2K�{��b���_��$Hs��L�	P���s6,[��2}�,sU��G��]�}��Jt��2,��*A �L�������&����]l�)������=��F0"�8���(����3��DXqJ��@�	�`G��8��G������ix�����t}�t1����!���8�
#��1���A#��E�q�"�	(H���P���#N��!��z!�E�7�{#�B1b�I��~�C_�r(Ee�A���q�J��x�#��UP���0qB
�����j8�#���qI��0�l�x�Q0�\�F
��_����X�8F"����_����I0*��a4������06�O��q��;�|�tLD��I�p���_BLAl��g ~3�qLCl��/����0���G��?�y���|��q!����`&�"��aV�SXM�Ka6b3�e0'�	,����<�K?�0�RX�x\�x9����
X�x%,I�U[�q5,C�
���������.I��
��p)�:�q=\��6�J���
����\W"��7�j���G�F�
�&��wpM����X�x+�E�
�a���G�X�x'lH���������x7���6!n���� �������M����������pK�xnE|nC|���p;�cp���{�m�����Sp7����� ����mpo�-�����9>	�#���{�A�������G�o��Q�?q��!�������'����7��������_�V�������"�!��_����������������o�4�����k����:�	����
��������[�,��p����s���������p��Qx1}>��?��?�x^A�"~E���
�q������>_�k�����#~o�_���M���� ~o!��F<����n�e8	�!~�#~���G���?��?s����/BCL��������������_��:�������B��:��_��O��~�[�/=M��:�#��?��N����st��\��u��9:��_���\��:���@����!�����������t��t?��N�-?�u����_����@�S��D<A`;����%��~
�sH��sR����l�yi���B��3�YLt4M)���c���zwb�|�^��Gw��KH��_�1�� ��v�R�"��� �t�J����(��������U��vwB>Y_�UXDi�R����_NN*ZT����Qs�h6C'�
z������gI�W���$3��X=��\x"�4�N���
%�����%u�����F�n3��dF$=F#R0�p���D� �Al/k�o���%������O��FN|����jV��b@6���"O���yd{�x+
����������>�#���u�u�M*��w����s<�|�lu�:��|i�~�m�c���w)�D}��2�Z����������7������e�e=���m����>ig��j�&���>ZZYK������,�vs����bb	
��4�d�O����=�<hX�9`s������K�':Y����N �K���C�9$6�������:d����m�����E�G�%����m��u��y�����7�yd��G�r�9��5"�����+�vWW���n��������9d�Ws�e{Y�'�:����)-���ou�[p�FK�|q�D�����Dj�*b��%�
�E l�B{�h�,##���HZ8{�9{�8{��'=�y����kP���XY&V���TIUy�{I%Y� .Q��xS9����\�R���DIG,j�����R�S���&��a�2���+�O�xi:��@����$��d>��F�.T�;�\)����F����ld<c�p���V��
�U�A.�!`��	S���v�T�@u.W(([(
-����2<��EU�0����V�+Lj����hRo���;�ce�b��P���L������D��Xm��d�A�A��T��OI/h^�Kgj
�L�
�L�Y/���>m��������O����d��'d���]�P|5x��{:Y�V�����~����x��1 ���w��K;q�bo��;	5�����
��	*�f�f�k��LX�St5:�2�4XvU��t]EE��F!H6��bW��R>��[egeUGg�1���
�ZS���
�� �@V@=�_����#/G���_J�Z*��D�aG����s9u��������������{�������.�m������<����w������6����_���I���'�y/A�vn���3���9�[�q'����@�l$xCzDth-����#�=���������d&m!)�����b�|��UUr����������B>�(a�
~���4��5�5��,��	��<�,�r���k���}u����No0�D�`���)���a�k4�~�2����:'��V���Fkv���!�v�bk����
����Z�lV)�U��*5������q�oz�I�T|s/w;��y��%����:zs�vrS�;�?2��D��[-wcr�!sfQx5r*����[���b�Ry7��� C�����o��j��W��k������7w��-��+^����6w}�����j�kSW���~7]q�����&���������;���w���-x��_�^��F������|���Q���p5G���9��:Ws�*�����
���
�F����pTqTs�rT��u�a��N�#�
�s�s�7���jAR������h|I�� 
F��(	O����� [�:���`��tb;��I�J������C�x�����vR�4J��H���'m6S&z���LCT��a��v�g�.S;������3�q��u������|��d���
rE���	���l�������[��m_O�K+��^���W���Ef�<I�!��0���0$��|?^{Up�QK~��6$��GJ-���E�zk�5��{����~d�����y��Te�t�gz���a�� ?'m6>�V�z�4���g�)%�t1���C+G��uh�)�e���������e��}��{�����M�����2�7�b�o4��h��s�	���qa�I�T��2L���r#h�8�{i���[m��5�ax������"��������E@M#�t�����l7��&��M���4m5Q���t�L��4��5����$-�y���"y��I��F���Rqp�n��*����i�������]��\��+���K=r�>��-P[���P!�7A���%��:g�M��A%c;�*p�%������c�Um�6������[�O�����D����$-����{g��*'�������N���[�2�2���v(�������o,�"��-M�(��Q���������3��5�Tt���p���$H���
I#1�����v�.@ &����D�d�S.n�\|z���%�~P~.�[���z�[��{H��tT{�C���B��Y�,�<���2�r����74�;-R�
l��3��e��1*�$�P���,��Z9�H��>����I���0��b�.�e9+��Y�f�s�L�(���'��+o���m@��R��9�Ul��T$��\�]�\�\��O�\�]N����Z�j�������b�rY�C1j��a7e��ee-WK���H�>�PK��Y����\��������Nw���O2y�����K_�A��?��l�{��co���{/��Qq�i^��}������^��q%EV�G���3?�W�hm���o��=�����z��8i:`$"��Q���)�>��Z��Y(��������i�~	c���S�
/��*�yLa#��_R9�D��$�-�����T(�
���APK��Vky��kcW����=�U�Z/��m�-]������F� /���&��xPj\�>��=��N��\
K���db��}1�^Y?�G������g��\����^~�#+x�x��*�	q����q��&�w�{�}��f��s���'����|�|�������N����U��1�<
�ppb7_7H���`�i�N4��n�%2K.ds	�2-D���Ktp�v�Z8}���P:**�� ��
Qg�Vr��E���?S?�C��d>�d��'��8���z�leX)�4 �Z)��$=�g;��b���J��\W���2��R�r�e��`�(^�Y���p��z�+��m�|T����]B�bv��3���2@�
l���$���j$�U#�F�
4���^:�L�l�D��I4��!�5ff�L����������+7W0���@�v:;����(O���h�#;9�������m��/h���o������w"��2������K`I��:E�A��~e��U�y���stN�"�/�d��/�/\{}�����:y��k��Y�������y����]��!����y[�>����z�<���4�����9�\=}��k~N��<����}8��$;��p�0��DXw8�
r�1�H:��p�(;e����<F9�lp�(f��d�n�v�����S	�2��1���,:<��s��kr���[���8�,d��p������3�/�MA�X�`2�a!|"i�-����G�l��@���[�>~��Lefi�{�{!"��<�dw�,\�����:������e��:�����E.8zgG.�^���.p�����/���N�lg9�vns
{�R��-FP����:Tk��\C?���6N1�m�����������
�g����Y�>��g��r����'��.t8;���4���t��%i������-uF�2��$f-5�/!���yV�
�~e�J�P|��\'\H\zos�l�x�����Sw�L��7u\~�7�>�6}��e+ZYy�=d�|�E����b�{�|���"���Q��]�v�|b�P���������E��T�8��D���������m�i������vr��o�Ee�����"5C�Y
~O��v?�K��K��/R�4=���t��Z/�����,�Y��m�{.1��[��	7*��ry�f��A^'l�_T=��/��U-�B��s�)�_��e���(��N�E���QK�i�� ��f���vL����,N�;>�
�T��ZP���I-h�')�t/����'��4I��q�!��(l��NHR?��_:b6����f��DWI-�~g~�M7�����!wx=rG��*�U�*���V�;������n~�R�S��������+2���~��T`���m�Y�H{��q��=��Z���W~���R��-,���@K�F���X���y�|s��|�j�����]�t�u�%�_�����_�����G<Ik(H�i�y��0�������z��d>���!-	�3m�y Z����1l���{�y2�S�[V�K��������I��8�Y�����h{��6�t���H�������+;l�A��?���o�a�&�>I���4�FT{�^7U�u�Q'�N����>�&V�[���fz"�~�����Z�%��+��NM4�d*���M~xl������\v��5];H����}��1��^Q�u��;�������i,���o��~�]������������C�
h4���:_�
�A#1}V,[��I�9!]�Hu^����������?�i��1j��@�S
���>|"���y��3_?���S}�
�Rf]���g��b�������Q���U�x�q�ha�S��k#c�^����
���X�h�V��.{Mk!jW�$��%$^�f�/���(�>>3��!DC
|=�g�y2So�w�����M����<�yy���x���C:�:�-�q;���gf��~4���r��L���S����g�>�{e����s��������{����c�x0����H�m���lcf�-$�]�*&~=2�������vzdB�R��s��PO��,j1�EKd����N����RKh��"�r�p.]�����tmi�I���������3v/Z��%�k	�����i�������=���A��f���gq�����]��@��-��������_���}ndlt<k�����}]��y8z9��!K���?K���g�ZB�	���L�YX&���~B��p�tn^M�::�`�P+���W��f���g��,�Y"��C���,����3�����P�o.�T�j����D&�����.�7�/�_f��|��<��V��_o�`�^^�:v��V���@�;V�p���{��$��kK�����U�^�����/�4�
�HL�T1�U�e��6p
���e�
��K=_5/�PN_�W,j2�UaT�>���&�h>������&�Tl�o�zq������8�@��D�>V*i���dUc���f�8mV��S%mz��C5�(���HY�=�%a�i���^��[������Y%e����IL�y�fd�~�1����p��;:g�E��Ocp�����z�� Y�����S���C[y���(Z<Z��D���K�+���)�������'���r��G'����`���W~{�}?\��k��H������-�]��^����M�����\]3;�jL�����������t�
��[Z:�p����j^�9��>h�r���G���Q-q'L��f?�~G����&�V1�%q������?%-�R��>�?��m��;C�O��:Dh1����d�"�L�[M�t|��fm��Y���]:`%jv��k�q��4���i,e���S��������<qC�Oe����a�Z�B���-�#iS��/�E_tg�we�F�d�t/-c��J����)��_�e�I�P&{:>s�>Q��2�u�L��$��"Q��cf=��"�A
������p*u�RZ��\�W�|�h��A����5���
�
�
��a���T��������c�UU�5��uZmH��k4*tNCTe�T���>�@�m��&��e
+�iH�f���=5�da�tJ6�-�Rc	���hU�j�j���J�j��v�v'<�ue��Yp���h���t^����X�����v�K[��s�oZ�V�.;���u�Z�V���c�=l�~@m-�wq��g���gu��������������^d��������f��+�?G�xN�3�/�B(�'{j��"��[��XTTa��(�
,:���X_4�8������=�t�����Q������m�A����=O�*|��^���I�Z[BTO�ZOMQ������
���D���
�������S4��5s�^4�`�!a)/3Q.���J�v���z��bS�i�i�)mRm1m7}�S��I���21e�gbM�=
&��`R�eS�q�����[p��G�F7�-v�_���CM���/�{4����PCvf����N@J��:�2E�1��d����$?�\*�tU$M��w��@��+�U	�vz~�T�d_�C�>��qU�&��hL��l=��|E$�����tk�`����Y�.>Mu�����Zs�Q�e�8�O}HM��*5U����+�L��4��T�%N�����/}2Tc*�P5���}tokajk�bO��B1�[�:�Np��-����DUGg�������%�)�~�>G���`I�YnW�����@��4�rC�t8�NW$.�%U�0�P9k���O�h�o���Ii��U����^���q������5������s����z�����Y=�n2z�1�E���]�^r��d�9�W�i�Y�{�~�pt������u	�8���	(M^��=��9@>�����r4s�9Z49�����L�z��q��~����zbrH6���N��t������b�����������l�\m]
������;����{
�G7�����[�viw�vN�����`��n^d^e���D��F5`�6�V8
�����z8�F?6=��������}Q���[����Yi�*��PT����$M	�
In7��B���9���$��|&�e%�����������!��*�J&���c�I\�H��B�[��+;�m^6=���K3��/P��KO���������X�?���+�z8���K��T�7�u�;����y_?�v�wK?_����v��i����y7�5�'�<�{�������_��ko<sj���KG�v[ ��K��Q�3����~�~���$��D�l:K���io�������=�����_���|�w4�:�����Y��]���L���9��3��5��������g?V����0���v^6���:j=wv2��'�|)�o������Ng��1Y>l!�%ii��X�`�q���a�2i�j�i������sXX	z6�G�F�����_�H6pAZfU�t(�87X�w5�}���C�)-��?�J������P���7����'P6.g��<]�#w�X��%�����k�1��A%�
eOV=�,X��j,�3,���I`@��U_>���n-��z|��<|��{��{�O�m!���C�������K~��W���Qh��i�w']A�;�d�^U���o��i��36��:����<?�hl}K����W�k���b��o��L�7Zz�+�+'�I�Nb6�\��
��N��7o���T�E�_'�^�(�n������}�
��+�
��M��\��8{}�����#3�����(mAQY�H�� �������If��$�d&��c(U�if%���������X+R�h�P�����+���G��f�^��d��O�5�c�<p��xFw/vc���]����;���>Nf��f���%`�Ka����gj�p���_����kb���D~�L��f�����x��)�W>B���k#A")�z��9�}�r����<�l�Z��v��-{��]�p���m�4��~B���(�(��S��X��������z�!+���(�D�^3�����ei-��%N.��$_�,�hg�e>��/NrG�e��l��Xkg\���|[���'w�u�1N6�=�������t�s�3�L;E'�����������+c���?���_�Ko�u��.�,��a����p�4'��K�[G��k�c�8w�	X���}"u"q��g�q0����u)��$�Lj��5f���l'o)J�����pyW;,k��������w}�jo��7��W�tz���'�pE�S(�������*�DJz(�p �r>"�2���������Q
!2!���6e�G5G�#>��5���������@4<l�4G5G�#�93�SU��5�k�Y���n�n�����G����x
jk[�[2QG�i�.�EO@��Ul�{�Z�$�V�E�Z��@�"nS�~����/)�!�0����~�{�E>����/��������d��S�XA�9�	�V�
v8�	����9�~i������_�C��^���&~y��O1���LJ�F(g�IF�d2g,O?e��;Z����#w<Ne��=����,����,��\��U��1e�zU�YTmQQ�c����j��E�V�([:*(��J�b�(�W��~�i��}J��rd�w>��
���e�t:���#�>l�T����.�e�3����}���Bu�b�~�lm&���UK���v�?K���7K�e?	���/Kx��!��b��,a�6e�'�������j�f�(�X��,a����rM�@M���h��,&�i?p}R�]u2D]�PD�����	��?�D��G������1s����f���ssG��Z�3f��3����%3p���W-��9��O�����Y���>����+��
|lR`a����q�c���3��|�����P�4���p3�f"#����

B�E��JQ�R��sY���Mg�.���a�I;7
Kr
�h����f��s"�?��9���He3����15M��,��Cee%���lE�����a2�mq���#V�#k>��o)�������n]��#���S����o^�������
^|s��Y��(�o3}����ww�?,�>���;o��+V������2^�'(IN�#iS	j}Xn�?>�N��"����,w�Ln�����n1����N+zD�4��&�)������2��HE���ps�B��	=�'������}>������\l��l��3���l�C�O���e����fj�'�-���t�{�;����-u89�8999�8��;�f�d����K�;�����bF��OZ�tQ���N��Cq2Np7�������/�"�t��3�j�V��I:A-�q��#f�5�0���9�p��,��p��{���p�8Y�V4d�Cb���5�G�\��L��h���^�|��,�qfQ�#o�����`Sv���i�%���	VI�1�P��LQ�jf��j4e�@�@g?w�<�:�Y��S�i'���z��B�B�,y�u�s�����U���I�I��
�&U�n�A�����=�1�����Hw�>>�q����%��cfm��=�k����XeC��LK8�S�h���D@��NN���{����M:�6qv1�C��Q0�����+�4~�|Z��\[��
I��)&
|B����	}�l����].'����d���t�����0�F~�D�D���H�k�GN��
�-������_��;�y������������k��R)����:~y	�+/����^~	��k�F��B���\f�{�g��d�*�
�`��!�W�(���8�9���;�u��Vs���U����o�+/t����f������1����P:���	9��'���������_�u�z�	��~f��~�L�,Cx��ad����Y��5�Ztb��E(����'I=c�;s�|��?�`c���T�x��R���JiifQAYNP�b�	�L��9N� �"cqf�m� �0�[����u��
_�bY����pT�l=�Q�&�sN�����'����b����gz!���ya�-k�;�>U`rF|��o������G.�������W<����]sU�0~�����u�t��;�?x���������Z�*�yw��]l#�H"b�8L�(^(.�Z�F��m�
����p��h�C6b�����T��o���=�������Bu��V&rj.Ue"gq��&r���K���H�e�����Z�X.e[Q��sI|)���{��:���C�����,9���U
K;_�6W�?v`���B�7���ca��
"����Dv��BD�D~�g	����*>#��������N�o�_��A{M�A�c=��Z����3��.��N�T.!:w��N[�������4���t�����m��3�4��?:MW���U�,�,����.�M��������G��_�3�\�Y��4��D$KD�D�}��WPg_J�}M5s��OZ�41�N���Q�;��V��==�����3�3���s��6{��E�#1�����?"8����~�cg�e�$T&�	"��e��Y���d�����uy�h��!��>G�$;�$icl$�{��^��z�6wY	{�S��L�=����{�bOy�w_5b�8�{�� ����'��",h���p)bu����?`/Rv�����"�-��R��-�5��/�U%-%��-�E������CJ�S�7.�]�[��m!�����k!3o�9���3�%����X��o��|�9��5S������/}"����Nt,����H,aka9o[)O���.��t����%`��
=.��I�
DT��q�l�m���7�|�-�|D�!`���)������������N�}�����l���]������!G��{����~�X/�M���]gglQ�3@��j5��|��~��=��!�n�x��YR���+�9���k��6e��Wz����������;Vr��1#.-&F^>�=�nBy��g�EK���������n����E�;�E����]����������Ru��16�����K&"��!@F�)kf�LAo��!�O3c:��HZ��hk��R��Y���RJ�/����L
K�m��v�J��3_FU�d��b�)u��R�Fi/�n���g����udV�����k�����YJK���?�5�R��-�~��r��C�����s+g,�y�5;w��%
�l�7�Kgn$����7v�ntO����l
endstream
endobj
17 0 obj
<</Type /FontDescriptor
/FontName /AAAAAA+ArialMT
/Flags 4
/Ascent 905.27344
/Descent -211.91406
/StemV 45.898438
/CapHeight 715.82031
/ItalicAngle 0
/FontBBox [-664.55078 -324.70703 2000 1005.85938]
/FontFile2 16 0 R>>
endobj
18 0 obj
<</Type /Font
/FontDescriptor 17 0 R
/BaseFont /AAAAAA+ArialMT
/Subtype /CIDFontType2
/CIDToGIDMap /Identity
/CIDSystemInfo <</Registry (Adobe)
/Ordering (Identity)
/Supplement 0>>
/W [0 [750] 16 [333.00781 277.83203] 19 28 556.15234 36 [666.99219 0 0 722.16797 666.99219 0 777.83203] 54 [666.99219 610.83984 0 666.99219] 68 [556.15234] 71 75 556.15234 76 79 222.16797 80 [833.00781] 81 83 556.15234 85 [333.00781] 87 [277.83203]]
/DW 500>>
endobj
19 0 obj
<</Filter /FlateDecode
/Length 314>> stream
x�]R�n�0��+|L�WR	!�D�8���|���R1�q�}�.I�Zkfgf���n����Gn�-x�k�L��I��j�D���~E��CgY��<y���,9�>Cu�n���/���w��is��s��������1�*��I��}�����
u��m��)�f<A,�4rT0�N���X�U��V�����\�^~wnQ'YP�q&*DB;D�3��@�����&��y��"F��%G�����4�f;���gF=�P-O�5�)��|!�2�=�����<'�2w��t�eF�]>.@������/������Z�_2��
endstream
endobj
4 0 obj
<</Type /Font
/Subtype /Type0
/BaseFont /AAAAAA+ArialMT
/Encoding /Identity-H
/DescendantFonts [18 0 R]
/ToUnicode 19 0 R>>
endobj
xref
0 20
0000000000 65535 f 
0000000015 00000 n 
0000213122 00000 n 
0000000106 00000 n 
0000233223 00000 n 
0000000143 00000 n 
0000000544 00000 n 
0000000229 00000 n 
0000052645 00000 n 
0000103318 00000 n 
0000213374 00000 n 
0000105450 00000 n 
0000162680 00000 n 
0000210909 00000 n 
0000213632 00000 n 
0000213695 00000 n 
0000213744 00000 n 
0000232145 00000 n 
0000232381 00000 n 
0000232838 00000 n 
trailer
<</Size 20
/Root 15 0 R
/Info 1 0 R>>
startxref
233362
%%EOF
scripts.tgzapplication/x-compressed-tar; name=scripts.tgzDownload
xeon-count.tgzapplication/x-compressed-tar; name=xeon-count.tgzDownload
���[�4Mr��ZEo@��_�CH
����`S�,�2��W�nVu�0����	z������������?��?��FK����/���������h��������s��o���������[k�oO���A�������������������o�������?����������\����������_��������5�4����I�$Mn���k��j��Qs�+4��y�R�_^��Z�QF�s}4�6s�V�����dN��G��%��OQ|���c�$^���u=r.��������V^����������?�������K���4��0�Jm(��=*�>j+%�/����H��������>��k�������N�S�����[��U����5�{��b��6A����*��f�C�������)��OV�>���}��?���e'&	������^�T�~���V����'S��������.���H�]^�������,z�P��:�S�>�2w��E��Y3���4��Nv�k���y�O3��D����k��E���]LX���{mA���~�w����?MD��Z�O���O��l���"?��>����g��������Ok
�4��J������v��P���vz�G�-<�o����Oi���f�?
��T��S���>��:F.�E�Z%����T�}�U�x�����^��h�'��e���}��Tl��g���{y�j{���}�{v)�g��?�<w�y�Oi������������(�';}v���\o�dQB�i��������0s�?�}����F���'�/xv��Y�\�%�+�=�w�^�D�B.�lL�v4S�"��e��%s:]���>�aAd�[���x�L3;��c��O�����O���$������/�"zv�!.W���=�Yn����W����3���z�������Z�|�����v����3B�����i��������������Q�,(M-O�q����Z�.:�Q��YS;(����K��J�/{�-��}jY}�7}�v����o���s/>�
�gwL���,����k
*��Ls*�?{d>����Q��T�vF}Bh:�)���\�v>+��?
��G��Q�����%��?��,�7�.B_%���?b��������;����r�?���Y�4���S	Iq�������j��U�Z�j�w��O�Y�rsQ\�wh��hcP����LD�,z���S��D��8O����}J{��D�'3����e�Q��%s��i�`�<y�C���GL�(�V/�	ndZ^�?�{���!���d����*|,�.�E���Sk����r�a�W�ro������O�g�����	�a�(x���&����O����Y�X<3�kr�7�d����E����gN���>����9/%����~�����R��E��t�������@6���;����4Q}���L����~�VHYW������G��,�!�G�V\���}��\����	Jw�<;�L[����7��gA��%��g!�Z3��U��,z[�f*�����l3%};CD���V��QR/��g���w�����������(z�RA��#V����n��E}o�_��^�=;(�2h���m�����3+m��p�U�>�X��(tuw�����5������B�����O�d�_<�}J��.a>
�]2?6��~�GX��,zu'*���Q��1o����o��=�����D��%��x���>���/�K]g1��E��RBR�D_�'�Oe�"C�wj�������#����V�O�Zl(�U��uaV\lF�ohf���vN�A�l����v��G���YNV����{�����?�/�#;W��\2H�^����|���v���~�=�o6o%���~�id���B�;�	�`��Ha�D�g�D�+V����j�d�5$�l�i��+��-Nl����,�9���B�����k��{�?D����xQ��c�]V5�l1��f��������&��Wm9�&��Z��]��X�7g�rN�~icI���3���Z=�k�������MQ��1���H���b��$��F��O�U]��	|b';�5
���	�M���E����oHEjc��}�����>�o���Y�[k�]��r���O��by��?����Ha�K?���rRX������G��,u!����������g��������a1q����� y�W��xt�S�F��E�T�,�.�;9+}��~����gc�8������-���b��E�����%];������n���3����8S`���x��u���������R�=�����'�j��s������Y�d_�����+F�w
��+,��-��s���A���j��1���+K��������j���YL"�7Y��e!����Hf��}~W�&�G���8@
�������pR��Y&���A-��cy��]a-�Ye�q�E6��>����-��,���Y�-L���?��c���H��q)~���y�$�\t���2�g��g���������1T�_�����/�X%Y<c�~|��ul��O!�V�0?�zI���>��O8�^L3H�l}x1����^D�,���&wId�M��
��/,k�a����/��������9�i���,%�R���W{��	�i�������� �s����*Ga�py�	#W�V����0�(N�9�1��C)��$F�]��^K�����{07�b�^�i��z�7��S��|����2���'p��g�����|lK�?���c��}\������l�z
��c2�����}PPF�
v���3��GgKy�ve����/��ii{�K�����(X��?�X��<'B3P^m$��86(`w��#8����������3,K��k]���=,&��~�^��h�����9���}�u�>
�����
�(�Y��4P6'��5�(�a�4e��(L��Z����mNc�P��@��pa]J�9�@jX4���c��X��)3U��h�G�����Cp���X17��2�F5f6���u�W�������j4Gl�	<�z��������PF��6j�{�A��M����
����
/J�2K,���X1�����a�k�5�X
��-\��A7v������M6=�<�>s�0f���F�����~L�7�������o����rp�bFa_.8)!�r�\�'CD�<�}��axrq,������P�_����8��w���({�����K>�Q���3���s�,s������Ev��0��}9s�������(�cm@�����Q-�����s�����t����������h��O2�#�3G�o6%�c5��!���X�/�����=c�u�}�U������|JA���s��0��SV/�z
�!��_d�:6viB��1�n���Bwt�V�(�cW��|{��w ��t�B�aYE����&Y��=�x�i��^-~u?V��7�GC�y���(?����&�b%�>����n'J�yX�T�%��������J�y��/@�T�����%�<�+<����|��a[�2��p���6_3����7���6^���Q��m����Wg
O@k��L�������R��k�
V�=�D6����}kgEW[A�c��!�1T��o�c��t��"�O��������8�N���a��4I�,Np��\\
�z�9}�7^�%��u;CH���U=��������^tl��}�^���:6��y�e�����dw��X�#w+���7�g����P��9]s�5����,�r��B�2,����m���1{8���%���e�c����o��8�������;��HP����`�����S�#�G���� y��ul��|�+���^�c����yX*�@���/���
N�%D�t����"��7��.���#��9����	��/�c
��m�=�{s|��Q�c�eV��X����~�q�8����������<��L���������|�������@>6���	����O��Hp��f�P�=���B�Q.b����A���R�f(�����zs�h���
H&W9/�a���SvLQ��������4R}�U����#e8���K�&{�X��U8�F�/�����s?���@�f���I~,#���M�`p��FD�<�?��y����\��g�cC��D��1���[%���M�������4{��"�y3�^�(����+���Wz�y�r�Ro:����E��X��{]���(��(��T��#�y\i$��13�%�#������~3�����W{��5���J�Ke���ppT]���:�����O�	������C��+��U�/��"�>�P|�#}K�y��;�K�����u2���-�__dO}���\8�c<����e�-���$��n\<�J������Q�b���7�
�Q�9��X�������cyy�p�8������J��	O�������M&��#UoJ#�c�x�<�c<:�?^�yt���>K��c��Bpe<,R>�8��R��)
�����o�'w.���P�G���g��M���f��i!84�d4�|=1G"�JbE�fH�=����-e���[���
���
�
�����9��c��:*��`��/%h�G��O�D��%O�����b��~�"��e�P�8�������#W�*����;h�*}��p���2=�W���j�n�~��A[���y��(|~��m���p3�s!J�aO�z�U��f2��c9��}��q�?S��ko��f�>|���Z��yX`3��>{��uN�y��Dg��	����]�%��1������������r@�����]����;�����Xh��B�M������({jSs&_Z������~U�<|���v��[�����3J1��,�{��2'���]y�~��MKo�����<6�����%���]�5����D�G��x���*��0������GoW��?b�QZ�>� 8�|PB��|��DOgW/�Jy��H�d�k(�Q���g]�
��<�7�Y(�����^:��+�[zJ���fv�xBd��	.=���Bq�k
5H��@oK#���cvV-��|�X-^>StE�d�'�_��	W����|<������7,U���|�<~�2R��T������Y���4O��p�q3���nE�{�,������<z��'���65v����aY^���#:6lL8��R�!�����X�8xr���c}\����D{f�u�3����]����L��x�zI
�1��)	��_���+����0�r7�x�oJ�aN��"J
0�r7e��$![(<���am����� ���`��o�k�y��D�,`a�(��>S�_)�������({��2<?F�(�����_�<r������9�fo������������Y���}g��ls���^�*��!�"���I
�y1S�^};#��Ul��������<K||V���\��Q���g�{�,u���P�hD�xN����-/�z��H��Y��E������?�By�T�� ��X���(�x��9\?���k�T)�����l8���������d�a�!��cR6�If�f85B�Z����~�x�/��@��E��Js?Q�v�����1���|�*���3����R5L��oc��lo`8�G���|����<�d��u��,�[)��I�I_dO6�1����f�x�q"�~�T����U%,w���������}'����pFD���J��%��H�]��t��e�����ha��3m�9�rz����{����$
Sw9���\��0��+@6�>K�*UM����*&i��|~�Q���V�u�,4����M�����>��(;^�"��+Z
������4[�BD���7�	Q�����E�+���R9��B�1|��M�mK6����
\��)�?��e��~U��t)���AZqe�=V�H��MV�����5�<pm��8U�y�� �?7��b���O
�������J�<,�Y��[�({bE���^��@PV����<r*��X�z�&X����s���E�(��[����������A�F�vz?�P4���n�q�S��E�]%��*T���RJ�@�)+��q'��Y��YP^?����>�&�Vv��*�Gy`��P�����o�9��';�J����������'���7W��a�;J�������������+<,��=�,��QW�]><�����}�R6���Md����?����mP���U�����o��
�q��/��%����ov�������E�iC���<R���$O����F&�<P�h;P�;���N�<*z����D�{��`���+b�[�kF�g�O"c���S�ye�l��g*Gy ��������>��tA�����*��E����Q,������������By�����J������4e�����"���`��<����>K�:��$w�\	��:s��7r�G��s�U���,��e)���`���:�@g�V��<
�N�(��g3�""z��@)X)�G�o��_"{�}�C���+Kv}}W�<�=���6�3k��"�q����1g��V���y�w��!a�@��%d����y���/�����s�~h1GyX~�|PQ�,T���<q6�[�~�
u_p/��>R�G��������1:6y�I�=����
��c�1���"V�a�4Ey�,����GMe����������-'��������]���A�<�-~�fU(38��A�1l���Q�c��4��a�1c�@E|zF� y�Tk���Q(��[�� �����j���D���^e?��Q�Gk���.������	]e�@��f/&j�����]��=��h���W��F�<Lz��@d�:�R�~�?:f�mt>c���.#^�����>lG@�.wa�"�S�%���`zvK8��"����~p�|�<Rqu�F�<,C�|����+��6��a� R����`�����6����D ����|��Eq
l��5s��D���^���Bk$?���������_���Q]�y�Mg2R�`�&�<F�D	����O�o�J�7+6Pt�Y L����z��Fp�\�������6z��Fpf����$o?f)��~��<�>�O���~�ZP�yt��������<��,o����XK�_mG��c�����<����_5�����k�]���
���m�7��@]��$H6�]<��	6�
&��9������
�V�<�;��_��X���y��,�X	�'�7�.�&#�����y,��}Hpd��#s����mT�ntjKA�xkM=������B��~,=�W��b���H�P�Gi���D��-|-�c��.��{�����c5:��t��:]��=�G�~�Tl�&�����8}?XSS[�����9������	�#_����������K�f	Q�,���{��q�Z��>��8�j�7�����u�$K�<�7�����<@��}So�=��,�_5��k����u����Q|��p�r)p�+����@#�}��jD��Y�k�`����n���e�Y�|I�)6�,!�@H�G��'�Q6T���� xb�Q]��E�F��n����SW�\�o��US��+�y\�w��l�a��u��#{���+{�O�8K'p_��|�:��xQR������b�(9XX��(�+���������2����	a-�S�ux�v��X�|n�G`��6�Q�~=�=� ��=~`L��:������3uP�F�����{�+p� �B��1�na���i��$^1������3����Tjj�Y���!��'�16��X����D4������<2nZr�aT�~��f��<�o����D]��-�o�b�5}�>�������MMmM����(,�����j���O�������<�c�B%����w�6����R�����uh.OK���*����w:����7���������}�0|+z]G,�J�G�c<��r�[4����������;��<����D���'`4��������3�t����\
��Hc�'Ge�?~l�+�����ex��8���4�Fp�����
����`��#]���1H��0v@��;��ET��<��:�6�����+���vG��c��e��f�K(�J�G�4��@����
D�h��oP8�c�DS}"qc����y�?��)<>g��_��h�^�wMzj��6��E��N�W��N"8�k2R�fS[�=?<'z�LO�G�����8���|��{���Fq3,��B��g�r�
���<Z�������3L�n������� ��9
�'�a~�aq]�_���y1�������T_{�S[Z��1����{8(�NK5�Dh����������w�����dA��� xb���G'l��Om8�$�]��{���-�+m4�����-i���^��X��K��E���]�B�M�09zz
�({�XF7�%����[xXU��=���<J������_�l��/]�yX<��G�:f���;�y$�����i�*}�
Q��u�6J	�\��T�W�8��m��� xtl����G�H|>$�u����;�y�����"$���	w5�N��L��3rF�SWl�����<���]��
�G����(�+����,�W)�u�][?��y$���9�c�����l�k��n�S���|���K�:6������������I��q�o�3Ip�j	w�U��mT[�#�#�G�+2�g�<�A�8��aC`H�%�5��{;�y����_e��������0���-����$R>�+���D��1�
���|�b~��V����b�f<��}�+����,���������,c6�����ka���O��7��b-��&�<6Zv��I�<��]�lj��Cd����"���L��%��������<�������c@_!�k��zX_�=:��y��R,����o��>5r
@t�������c�B�&e��c��f�����f�=~\���n�|�����'sL����"���~A��e�'�<.�9�Q�,xj=���X�q�&y��N��	��'Xf��$o?V�f�B��������sUP���y�K�({l�}0����-hgN�&z���>��8��+�.�d�u��}4A�<6������`��:�y�E�p�{=��Q��#Fu���>\P�cj��^'8�x�o4�?�����djK���o�?9t���Mm����[2H�������S>��
����yX�������~������i�re�8�.��t%�#-��P�����y������IR�e��E�=|�M�<v�Z�
W1x�#����W�$�]Mm����W��}4���#�c_	���c�+���-�,������L�~ntg8��.w�<$��~����)����<�M�����+�7?���B�Z���	�y�_���!!D���b)�g��zYN�Fx1��r^��)����'���� ;��^,���l/�W�+ZZ���
���v���3�/����-hvo��1���g�3��CXu��A2=�{0Y'|��^[����<P�uk����-R�/����5|i@Mm�?����L����Qj,�K�G�S[:�y�?�-gOd�����a8�]�}[���&{b�	��}��x��]���,���_OmA��W_�����u����C��SW���z�y�(��� y�F-N!�+�G���o��c��H��<�(k_q8�<�����1������7,X����<�A/$�7�t�
{��Nqu��y���3�#���Op���hF�<�xx�d8��� qNxS|	d�!s�S[,{	�Cp�8�"���b��L��]���9�T[��G�P-Pd��_)t=v:��)f�"{��^�_�S��������-������U���YE]q-�t)�nE�h��)>���Gfw���,�����w��9���1�0';�a+����F�<.��6|b��<�D:�A���"��^� xl��aD�Gx����A2���f���|�a3��� �N�������<��d��Id���+@��YW�GsW���R����Xq��)���3VlI�����
���l������;C3(�G_�������%����R?��~>|3�T�#�|���!W5�\�q>��rlw�� x�������<p�ir���c����/=�	����rA��W��l0����z1���l��^�J��c�O�)e�s�����q�7��W)��zp�G�8�\LGdO�8z�/�j�1�oaoy�����~���b�U�wML�����V
;L0`7[������#���~t ��OL�>h�I"��`�O�����j �o|�H�����uEFf�B�u���������)�C�yXZ�7�+�kp����<�
*�"K��icx/R�����h=|YQ��
�����	�o�0%���	��=C�<L#����J��"�o)��c��jT+z&�A�<pa��g8�/��Ru��[�%�������yd��	�����V=���s[��@yz��(�G���P8�]u"��x�RFP��Y-'�*z��bE���$+�7�{	?����8�.Z
�����M��b�Gn�������e��),�}�<��L����Q/R5w?O�}=�G|������k���F�y`l��\��~�;�h�-�B�u�
?��oQ���n��jnK���V���1�|�'pe�T�N	�����+P��G
��G���A�<��&K�|���<�����!�<��My��9��@M ������`�g���tS��y+|��q�N������w�� �.���}6Bp����A��-7}1��%�����PQ��<v�l*��<��'?9:��x�6?�d���K�<MO����L�������%�����qP����D��3����o8������|%/��.�{��-�~��av��8�����;� xb����� |����|��q��OX�y�}��c�a��m��[��h�}�Fx�8�TA�)D�����u��K�}pBqC?=u'=:�|'��8p��y�����P�/�p��}��=���X�����#W���|�w��o�_����1�o�b�g��?qc������t0���~"���x4}�<u�jI^�/�-�]W���g�����Aqf���g�P��B��cc���odL����v�������tx���o��\�!��?�{�������-���"�q��4�/��-�>:xF��:f�}(�p �����-��]��<��\�O����g|�RFL�{�������w����t8��9��y$����+T
����!�gJX:������s@�1���LH��G.)��"~���(����10!��
���3�bg(#�������R�G������i&}�h4R�����,V�������d�1.u���Y���Ddn����w����,��8�A�c��cA���������<����G�G�t��9$��Q��c�c�"��7�'�qqM�F"z��������@��9����_ K�zCq�����M��x?��k������a��6����i�5P[(�i>�b��9�dn��ke4wv�����c�Ipf�Z�z(H����V��[]����.���_yX6����t}�V����l�z[L�9>)�����OK��'V�������=;������I�<R��0���8������uKJ�E�����g���v��c�4��7�.}l#|��j�a���"�������i�����yX�H
�G��3	��|�\?�1H�X�.�Ipw��_����m���z��;���{�����A�79�X*���"{��D�.<-�c ��U��hzb��}��jf���_e�~��gGO��@���j>����^�%V�����O�y1Q����z��+�L���b��*f��<&r��Y�YW\�6��-�~����;�t���83�<,�F7�g��������9_�X.��9�������xy���s[@�����|,m?'n2����+����+�c�w%�"`�
���d��7?!uR>�];{�"{tt���Q��Nx}H�������G)�E1�g>����g�y��a�?�|,`"&��@w��~r^�<�bj>����7�^�T��^��d�z��*t�����H9�e��y	�����i��~l�����h:5��H����-��a�4H:�#�����[Maoy�#��4�+���������������y�G��sq3���Z���q������iN��1���9H�{�v]�
;	�fNY��M�yTK�}�J�<�~��|_G�=~�Wo8���~O��ul����&�y���x���<,�����mA��%��g���2�@�Iq����q����G��'�������7{�~CG��i�W�	��_������=G�ylp���� xt,�����(���W�M����������<P�BW����q��4��rU��|P�����fO6:9��x`��W]����^4�1��G�!�8���R�
]�����d��-7�y�(&��j�[��L����^�Z��;yd&}�{`�4)������`��^��o��������:bnK��Ip��5�Z��Ag\��K��	���g�S�@��|�+����;f�l:�c�HM���{�=�Q����~�ds[��j���������\������N��c���N������`��h ����vm1
j���O�H��8�M��t�u��9��J�p�9���u�O�����b:�E��I��|�+^�:�$O>��A�z�w>�}��p�������k��/.+�G���v2����YG�����Q������dO��TE;)�c"	������{6Z�=�c�����U�����74����!�*}�n7?�o�.�z������|\G�<6�����
���u*6�%�)�l[�m����^�%������ �����p���8�
`�',���9�O@���c���������g�M���8UF�O���������a����� ���f�����5K�l}�D�<,q����y�� hy��80�8�qs���=�s�?����a��L�"�q�������i!}�L�����<,o6�� l|�Mg���!���4����'�fQ+V���' ��`�g|�c
h����U8���o�tn��6��WO)q}��qi>�Y��V�_����c6���cs��O&}��5?�q�GBa�����3K.7^dnK��R��g��cv�z�d�qP1����������y����n!���$��Q}�~�>�#x�}mN�y�+�8����S�r
_��A_����O�����y,��o#)���|�X���+����_e�?��m�i��Gvx�j��
��bEDq��QA���8��_p����$����p��q�L�m�*_$O��%?eq��-<�5G�s��yQW�Ga�8����o-Z��pE����~���,���X��EdO�37�G`��f����*����G|/��@#4:�=)9�>y4����9^��
�~���]{��8�4�`� xt�yl�"8L2�m�h-H�=���������;����uz6�Eq�Yd�<�Z�=�3�\�g�����5�"{la�/����54��?FDO�Q�_���{����}��p�������6W� �?����\��������^�������������y�ke&�����9'|����|�1�0��0�sw�$��X�K��/"���A��c����zQ>L#'g�"{b�2�|Tw?f�>{C��<��z.pJ~U`�f���6�rR"��Q���b8�n!��X"�&x�^�%�<,N
��(f����y�;�����!�L���.!r�8��\�h
�����k]��c��k��>K�g?���@�<�JZV�]1�������������=�b����w5sy�V���c�W���me/����n}Q>��0�w��S��l�^��������D��������K��1G3�h`��Xq�Q(K�y���*}�c���w���XfB@�0?��&���#=�m A��Xn����y���k���y��vMw��(�G�j������+���v�z��D�g]������m��H�������V����m���g�
�Q��������#���=V,y�L��<0tS�B�J�<p��v�7^��h>����q{._�#|��ov��|��&.��@mu��_K�<F������j��]�+��Z��K]���6�`eO}�<�����e��Ke�>��1��05"�G���[�������s��?J�e_��0J�����y�������<��\<��I����#�PX�<@2��_����B�x-�<|���R1����q�=,����A�����o����X��,wW$�5������<Z�!����y�����y��<5j�}��%X��X��Nq����Y�����D���Q)��<�D�P��C+�GKJ�_��aZ�9�����G��,��@�2-r ��{��8���q�;�,x��_S�8�k6�%��:H�'����C�y����=�2H����O�^�������
�QM��s[�m��|�
{f�E�<�}��:������y$�B#y���<��)����~�K�_�<|x��>�j^�v_��8��p�T���\���}���SV�y�m�7m�	��~��<�5��w��[�&�������w���y�}��a�y�[��RE�s���y,���(�"{�i������� �o�D��b�(�y��_���8�:�m�y4Pcd��JdO�j���8�cO����U���g��,��H�1�����R��N��8`��}��Y��c���Mp�l�x
����>/g�7��R��]|$�|,��q9��<����v�eoy�|��X�\0��>������6�y�g)dxX�c������E�-�Hd��5�cI�?��7��]���ks����I�7y1�{�F������l�����tz��
�!��/�x� x��R�}��8����f�
��3�{���|3��xL������c�\���A'L���Q��+��^*�<�'����>�;���4� 0�*z�nu��[d_f�W�D��c��v�����O��S�J�3�o��@@g��������n��Qk�vg��>�������@�\Y�,�����w7�y�#?�>�U��!8x�l&��<6���^�=�;�Y�Q�����6�y�����M6=�<�_��c9.O����-��W,�E�������cc�������6}�p
�+����:Sb�kB��W��c�G������Z&}�X��]��m1�3\� �}�~��&806�{����<��u����� JI�]����It9�f8���� X�"�����
��8�
���U6=9�<�&8�����^s%��R�����@{������@�����y
b&���eY~���8�b�������������i���f���L���}.W����P�������s�g��<@=\�U�Y����:��8������m�y\7�z�W^��F�W�<:���u<����E��X�]�%�":��'�#�'V4W��1pB%�IdO]q��c{��a'��g�nW�yT3v�R?�!Q����o�^��ck�����l����c�����8�Xl�>!8;�Y�0D��9Ow$�������|c��)��,y������n����\�Y=��10����z[L}{Q?���n��������|��������|W��LbxXq��H�L0�_����=+s����y���=�~]&}��������Xq������pc���;�<������Y�<�g����l�*�w�g�SW�_^l2��x iK�%O]q��Mq���:���({����9�#����BD���PE�^��133S,��>k�g��1����D��X����}���)�w(D�������-�<��m��4e�������e�8��[
��j�)
>�@�%O����c�W_�%|�ZPc�����=���{[�������P��n�����[�X�E���6����B5J���;��1rQ���Y=${��-W�~���1#@q���h��>�k_��|uE;�����g�H��R?��Z^=~^�W�y�����@U�]�L�i����#�c�cz��D�<z����10�{��q��e�>��Y0�����<2���B�uES�4�|����}���<�5��3��c������y����O& �G�V��Kq����u��<�������8�r]�W���-����������y�M&}�[�3��������w�����Y�v�y�����?�yX��O9�y�`��>���7��0��Z�>83���Q�G��b���(��c����Q��A��E6=����`	�uE�qS���<���8�i��L�GdO�l��&:�e������rK�	���:��^~l������z�T|`��x�I�����7��+ud	{_$��-?��E���e�1^�y��Q<3����cX~����� ��o���a�z�D��E��I��F��=����6������:������q�_�9�|Qc���'
������{7��L8�u�����I�E{��|���������|�~����X��~�����X������������������?c�8�_YJ�_����c��h��O3o���E�)�-��{��!��Y>�G�����c������/������_��?�����?��������w��9'h,p�Y�|\��-j[k*�4���c�p�)���?��A�
?70�~�<U����_��;f������������/��rYd�\�KY|��(��Tq�����L�3^]��1�H5�o@��v
��4�e��I����/;&��3qD���3wa�\�����U��l�?���\��O�_C����?K��o���M~�"k!J?�O%x�$�|���y�/�'C�y���h,��1�?�����i��/���h�,F$�/��P�O��M�����+��-�=:f�n�:6/���M��vx�AYw@���H�b���Rxi�7���M����n�bL���3�U������c����_�M������A�������&��@k�
�J��1	�|A�4�
�V>K�:f�xYUH�p���t��%�������^�nW����@cM��C�����Y�L��:fv����HK${��\��P�`�b�@����Bca�c���b�B��������u�p6�W{�����:�~�����3"������
J���}`�X�����#Ac]������d�����+���B�mV����.NI���}{��XT�f���"{��BkJ��:�e�������\n/JJ%����#P���k!���;7�){}T�;���-7Ec�?Z���J��Bl���)+�Y�2���B�����&��o5��BP+�������4����������������:8�s���t���t+$����������I�����/��[�I1���������344���1����aH��c}oe(������G�L)��2?��@�3�S�?��v�o��k�����e��L����2e����Dc�x�p����������Y����d������\�(�[����?0��[Y��>K�{f?���/7l�9Y6��g�t�������B����A������^uK��ch�^P0.?�O){��1�.^���M�W��D����c/�����Q��Uh,�U�OJk/4Lb��7��g�H�=�:V�.��}�"Yw��I��[�������B�?���/'Xwp�Y��� ���|,����W�G�����c'!�Y}������Z��e���=Mu���u�2� �+���z}�=�Fj�gI>������V�;�LR��/uE{��~�����_����}Cc�T����u����Sq�p��=B���N��@'�o:f�I����Y\��7����<I�,xj(���y,���5��~H!����9]���7�?=��eh,K����P�h,���ah,�<J�?
'R�YW,�����$����D�A������M��g_�Th���
���X�����,���G��^���1: M�h�n�I��[>��\}`��X���y��X��\������S�/��x�L�V�������#�j�Ae����c��J���!NJ�zeh,�3|
���:B���4FV�X���0n�d���h���8�7 :&�bz�U��<Z���&�/��(��������\>Dh�$��I[�O>��!�7h��<�P}���X��1G���h��yy�^��W����c�;���"�h:��u�(4�E��ClD���L��(2Ccm��3<�5,EcUZS����No�[eh�+jD"d)��$�>�����V��G�<���r�g�g�TdF��A3{��"|bG�|
;s4V����=<O�B19s4���r@TH4�jy�<)���q�|	+H�����L�.]C���v8��Vj�a�r
����~�w��@(�eA��zi]>�L���M��#�6�����"�yZQ�^�]���v"�����2����n�0�Yy��*�)d�G/-����Ts���c�]T�(��h3��������}�����d�'V)�&�<�J)�L8"���n$�"�(���A4v�2��h�04i��n=����d�|#�'��.�$)Q����[���
��
,�W~:�)]��|1�����&_��r�vz��z�,-�%��c6G����,��p
��{-H�>����A\�.-h����k:��q4?�s��R��`:��<�B����Qa��0��3�L���E,V��!���=�!�����zmbC��E��c���r��S�z�k����O�b�R`�����{�3U�l�J#�bkJ�#�Z�S��T���/��t��r-@#�K�^=Y����&��f�5�q�-�nQr����X�
�����Z��!�Z��~�8v���}�+G���[J����V�,S2�r-%�6��������*��K�w
Ab&>�U!�I�J�}$�T�Z���'�n����H2�sk��eN�S��7C,�X}p=����ky��B5A�o������
���
�`�A~7��e&3i/_%��3�����\\��b'���]F-��W���.��N�#JVAYT��+Q:zg
�F1%�J;�;�LA%
{�c�+P%��G+��xaJ|��B������9���� >�>��?z����������������lP�
T&~�������X�P��/�;��!�7�"�}����=D��pTJ�����3��Y��@�m������+�d3��j��.��L*����M.�_��w��,��z@�RXL�� �F)n��C�/�����
%�?��F(�r����]3b��b-Y�G������������b9d�tbAV�g
�I
��a'��G/%�� z����P����5+lfUn�<�,xQ=��-��?�~	�	��C�B�'HH�;�<L�O��E�.�x�5b�����<?������K>�U�-v������*���)#^:��O�7Z
�M�P���h�{�U���I��Y�(���#�#Q��9.Q�@��S�qf ����H�(���h�1VH�)���i�;��Q�����C)+��a���'����;
I������KL��!?�4����U8��n=W����22^�g�/��r`
8�:���z�-H�P@SL���3�������� ��S*��;.H>�]���
plA1��`�E��� �K��
��/h��P�2���JP�J����sR1C�z
�$P*���`��p(��������w{CA�*����75�Rl�?����_��'D�BN/�w��9�Qf�8���k55�k!��x�������*��Y��;�^��r{a�A�������V�},��n��/����oLC�o��W��� ,�����}�W��_������'��g��D��c�9��!����PZ.�b�V� �w�^m����Q&<�%��u^�U�L�����Fa�����Y���;h��������j�1�g"&�m�����}~$������|����>������x��7fw)z����������bXK�z'�*���q���d�`L����w������b��.��_eO=sd��(���d���^*�
n><\�P��@G�-ZD��;Lx&B�&��&${�mJ��cx�%�D��K�
�G?��W�f�,G��B�<z7���(�������;4�_}���@���*%2m��R�������(|�]Y!�(���>{����R����2�8�A����2�5��@�d��~��m����KMeU�����jtI���E�f�]���2��^Q�`��)���Q��iS^����
�����|�w��H[$xMj��B�*��f��������C�faxL�s�~���EU�x�����|`�BS�W��@���"D�����
/��K��|CP��*;�c��_p���S
e#"|�*m�4E�U2����8~����AZ�WI�U0J(82v�b�q���T�^��������p���l�s�WA_w��
�w�	�Y#��]S��E�[��FC.��*����A�W�X�Z\�W1w�KrD��wv�?�����X3L����/����U,���B��@�Ovn�/80�W�<���C((�*�I����WI��u�xL�U&��~�#^e�+d�{� y��W)�r�����?����?�eT�>k�f�WY-�uzW��}�2
�8�o�8	J~��G���*��?��;�	�w|`g������.ct9{;�w������l���I~�UF��*|4U�&��}�m���k`�x3Ec�����O��ZAl��X�]����s�J����D��5����D�(7$W�e]�x��� z�h�C=��Up���,o//��)\��W�\h������1��G�3�������Fi4\89�z��J0��V�7�����|���J��GAd
h��Pp�����pb�,UQx;��.�wW������U��h1ax�7+��{�f�W�3���g�y`T)�b�]�����z�+�b������R����� ���Z�*�tv*�%�5�W1������wc{-�WY��N�Ul�zP%�W�m�`;�*|�^��*D+|�UB���D������$oq&"'\<|?�����D��D~�c���*��J��.�,���I7���gJX�J���/�r�p��,+L:
�3������%��R�|���U�	�<��Ae�wP��53z���W�8)�l�rQGH>;W����#����VBn��Z!X
����?��������o�/
��z��h&~�p�{i2���h�B���*�����X�C�KL��)��W�����A�Wi��H��U��(���k��@�Z(^��z�dx�Yk�J�b�����@d��C��*�N0.�=����]G�A�(^����n(��}��29^���a�G	��dW��>�E�R17;P'0�{Q,��j��U6���i��UP	�l��r���O�h:3V� ��*�|{.�������"�5��`��J��7
��+ss~����������w������1
F�z�s���B���iWE5�����J���V�W�P�ND�^7���{v&�bx�-�>,�������7�U���~���Y>s��+^������Q��Z�Uj�p�d��e���Y�+�* V��kt��������X��y+���
�L���������*�1��T"
�{~�%�L�`F��"{������t�NE!�v�|L�O]%�Z��CI[h�$���jc���*�*�F
���'���`PK��UP)�;��O]��@�T^81�F�5.H�z�-��B�*��eqPp7|�(�|��~��{�2|j�3xf�U��22�-��?���k��0#�r��5+:�:�w��~���d�=������T�W-������:��S�`�172�����V�D�� �2��@���O�����wx�>k��c��.Z��.j��Xr3-Xsh8^�����Rz�0>
�'�,% kj����-��}�D��u�`M(^���z<{�w-Y�B<��e�a��WY��} q&�K�O���so�C�O�*h��������K
W������������{h���~�q&�w�fg���/���t�a�?�h�4X92���<<�%H��J�7X	^%!��S�h:sCZxS�p�R����Uzj-L��x��t�bG���[��7R�
h��l�:%
WR�ZU:���9L�#�'��(!~_����)}���)=�v���8`��p:������_�?�w��Sq���U����g�5&���A�s�F�
�#-g
���WI)Xo�W�<��	�`q����p�[#^eV���� z"��sH'(^����3
�83��6p~�}���-�*�p�)�J~��GHH)^\=�-*��\3��D""|�;H�O������B��f�����r��5���Wa��m9K�����_��O���'���W��MY��;H�3>{�Wi m)��3�����*�Z#^e�������q�Jo%����U�@�f����g�82�r�J�X
-'��pW�(�e^8h��b���*e�G�+ ���;P�x���|=����_�N�Y������@~�m���G,�
���8$!�|*�3�d����t��A�Y�Mu��U�����'�U��!$�}@3S�r�������#�WY�S�)�H�U���+�W���^��-�U,����R��=��Q�$^�u�%W��K�,+���3�,�C�R~�t����qw]Px[!�*�\7[��u�X���*��.@4^�u��~;���~�<zg��������������y�l��|�������*o�<R�R�
R\�	��*�U��D���U�
�XN���7ET�W�������w���]#z7����#���w�
�������i���W)��7���~X�FP1�����p	#�*f0v����3K���8�W)�����U����#x�W��P��, ^4�U�
LR��������TK�{�/Q��54Y�qA��U������4g�c�*�����@6n��d���|>�.����]�2
C����wf(&9i�����=B�bc�w��0G4x�w!�b-^EK~��q�~�r�d����{�� y�]�CK��O�xt�� ��<�)���x�3+�%?��UVk���Q���a���Hl=(���f�w	��< ���C��J{�R��2�=��i���M�*��r � ��������F�UF��9�Wx��9p�#s������Vq�x�>�[�9Yq���Yz]�5����
�.HgA�?��_����a�:����1%�R��FF��*�I�����Uf�ma�BN�/�.�j����H���3�K��(>7?��[�v
$��U6
��)>;�r��&��U��q^�����J�e[��]��h-4^����~�gb�����I���2^����������wu���E�J��H)�h:<�;��R�x`���n=zg��3���*������1
���k����<��p����'�����B7�����������k)�9k����5_ ����5������)��M�;V���zf�4� �U�\����]Pb�
W8�UZp���;�fA���
���8��~��ca.���%��[���]EZ3|�D��,o&��	:�����p���]�����oq�(��*�U����F��a���)����|��U���#C����/�v�W1#l9�%b�~��a����|��*�� P~1��w0�}(��%����L��b�������m���A����n�	^���K�����V
g��U�����z��Y�=|]�Q�
P�����M���8��Tt��bx���[
�9��d`�y`Y�������G�����z�v�Gh��pb+�/#�g��������*�f._6f�w]e���+��dY��^�U0���W���n��)H>�]��^�o[{�w�����E	^��~�G�;�W�;<��1�
�?�����jP�;�48^%=,�
�IQ���n��Q��z���������ro�<����#�K�WI��|~���H!�T�*��������|\D �*s��k�M�U�������]�h�s��j�����w}�p�	^e�B8�G���0�Q��q}�f['_�}.	����2�
��pa�/&���w���|x.1m���3#_��\�3�p�Ddo��q�l�x��,tL)��
�2��� ����iTR�WY���YQ�����1����8���&�*p�i5����U���F�U�5-���<u�h,����J2D���(�4��R����p}�=$j����@����O]�����d����x����vj����`t$^�Fk��*�{u�/,����	�Q~������W�����y@����q(�i~�
���W)�,-Ltc�����4�u�W���3�d:x�,2��LL��9��'^���*����
�b����q�
��{������aS���6�(|vl��;(���������W�3�>�����<X(�s�
"�m;�������C-Z�UR�9��<�	�J�#>��3�L���4��b������������U��\��Ri&���&#6�WA�����X��U�}����bA��wy_D��n�p�F�%��3��G�;�D��#��W�X<�w�tqF�3~�!�
���c�A�Y`�S|TD�d���h����t��J*�UF�����
Xa�r��U�J!��*@�0kL�T�J�g��W�(�6�G��[��S6:������|bD��-\L*�7�C1��?����#Dm��Uv�j��]�6\�/Xu�W����Q�d��$a��< ���v��g]e��c��
]�A)>��5��~���oh[��"|�^����o|bf�w	L��AnB�~WxD�;�����D:i���m}�lp�J�a�zg������1����vV�bs�v���kA���<��z�G��t��V�*��	�fo�.��#�1��'�l3����U��A"{�Cg��K����#y"|�����=t'xLy��}���z�+��(^���?3��W�W����� ������N��`���\M��3�y@m��c�x�2�^�L���%I�����W�;��� z���hX�V/z7����C�(|�������)^�,;?q�u>���p��<�9g��[�j�u�W���z,n�S��=�e����-$>D����� �^e�G��~���w;��Jx�l{������l��#�IS����;D�b�Ee���< �F�8� z�s��E�u��g	���U(��-t�x������Q��w3����ru������#�<��y@�M� ��*{������*e��<�W1g6(�6���Gn��������^I�<�N�n?�����0���*H�0]��gN��]��_��A��!��4�)������/��z�l!Z!���5�'��������[��U,?(-�dG�{��j���9^e=�&�;�11�g1
��Nl8b�x0/�}���d�^I)���U���@������.�*3��-`��x��W���]�*te{�'?z���r��b_��+���KR��U
�iJ��[�,x��D�����9X�W������U�j���_>��ykz����*O����1;lD��#L�od�*!�gxQ�������%��s��eTJ��
�w%����*��-�P����:f{g��� �M�����������UJ*=�d�W�]����>.��=��[�����d2��1b��w���S:�WI�|X�!ox�lO����]�c�H�Uv]���3��+���D�����v:�B������`�`(sQ�Jr0�������C������h��z�R���2.��P��x�Q�;C�*$�9���R�`�x�4`mK��q�
�3|�����Z	v�w��l
eG�W�g��[o���w��+��ou�ya���� K�;��3$K��s�R(�
��f��I����`�)��������t�#0�+�U�zX�=�m??u�z�~��U�,���su����%x���)��q�
��K���$��j�^�y@��w����,�F�Do7v�����*s�4�,
�zf�P���[L����s��(�UR�Q�$�J
����U�o��%����W1s&�u���v��c,����(!��*��t�H�k��W���A#]�U��^����]�5PNt�W�����9^�����W���i;��n*�JK!�$���7���X����������4���~Q�����t��U�k�kV�&�PPx��K!�=z7��N�U���:�l"������X�9Um�e���v(?}�|��7�vSO��n��5]�U�5�=DN��Z(�2(�q��
�G�V�_
�W���|�?�>�����
�W�#TB�Do���-@������JNg��-����0nU����g�0�1Y�wp��=
�����0,g�
�0���3I�O~g�'��U���Z��N"|�`��x�
�Y������0�a�Jf���1�g�`����W������~"H�z��o��o|b�]_�������q����agb��5��MA�|��8�2i=)�W��vl�W�0���;
?#�T<e~�����y��y�>(^edS��}�F��s��55�,�l�z-C'���U�3?<�[]����!���8s�@`7^@3EA�$^��X>�b*b�J��YA���m��?�f�M���UP���$l~��7������J��~���ymsx\tNO���S����4C���J��#X5�W�a�Y�D6�X
���UP���B��u��<<kP�J��X3&����ppC�U�����.�������k���U2����i0�g��B�w�y@��x����r7}��U&��� z��
�!�R�5 �(�WA�����Wi�_�F�{�����UL�g�S�����\�\���U��8�+!����p�C���2%"|�`{�1(�J����	D��]�a��x�Z�P}0?��e
��9^��Q�������1r��_���X>���U��wC�*a�K�y@�Vi=�
\c���/����XX����U�����S��T�R�o����gl��.7<���x�u�Jd�u������U0���P�m�D���5�2�c��Cn��*���$�WIHw��Og�Z��'�
��J	
�L����!��E�
��b��?������A�*���?A���5F	v���\a����4;���qP~�z���8S�U,�����U����D�gfdk��z7k)!�Sx�5s8�����sp�
�2K�u��2*��1Q�*�a`�P���c�X?����f)��vq������<����2;ZTCkx�<����4�J��D��x�����x:�����D��[�|���A�Up����N�y@�!����L�F
=8Q8^�:&�TA�;���=z��<���*nj�������q�y@
�}%D@�_�N*�w�z���;�����w�~�!�*5��B �����A�*��@�����U0m���W�8�v$�����9z���
,�����*����
�W=��C~��5K����Uf���.)����jP~��� Odo�����X���9��[�,�1��Lx���o;!�G�zD[
�W;EKm��C���������%w��J�
8��x�h�x�z
��\����>8^s<�-���
���x�4����t3�
��j
7@�_�L�5Y��WY�?����]yK���)��,aB�`�*�%`������j����Lh`C�o�3���g��L\�/��U��v�r~���f�?��7����x�J�����?���!j	x{����x���[I���*�"� z�X�C�G�U�_}=u�Ax��U��T{�7��V.Q�(^�w�~+��b��3���z7��_�;�}f-\WQ��y��j��~�7�q���x\�r���U2�
�Y�x��1Z�'��o����I�_�k���*�dp�dR�Jey�V��w����8	^���>��O���!��O���i3D���o{7^�O���p����������U�4R��E�{��R
��N��2��a�,���O�/<L��q������<�C�����
'��9�������*i��d��,&~�`�6i�����+��3�c={l��t��M���U?��/�we��]c=u^}�p�J��'���y@h���������~>�~W~�7�k�����N��4�K����C�*�_�M�W��j�� ����L�(><�&z'[��'�w~��x����&`�-�k����rj���������qL���n��|3�U������/����>��!�*��a��x��<�c�y@�n��-�Y������*}�k>v0��ba�������r���.���PJ�����&fu���^�����UF�����*��;�!L�W�(��0������_~������R0?����'�S�U���Ky&���@:��#^e�G��&y���*��x��"��a,H=u������_��tup5��=+��F����u����u�w�b�p��
�.1~�|q��Y�D��������;tZY�����\M��0�
����so�^���>F���>�B��������0�}
�
�r`��/��]���`�	�
����6<H�CW��|�?t����["�* �-�U��y��}0�
�E+����0�0�W4Q��@{p��U�8�n����'���#�������8���G���`R�

6�k�3��*C��7f�]5/����O�����M�WY�\�0v���8s�@�=^}�-t�2���r�K0^q�l%`l���w3����*�;��e���8^�n�]+�?z�o��w����#����!��0�3����@ST��U*j%=N��'��%�yM�WI�#��7qf����UpScy99\��y����_�b�Q�%>�������:�@��>=�{�Y�l�����e� �~��~�0�v����*�$o�����7F����e���{e��m2�W�C-:��;�aN��R~��q�-�&D�S�\��(Y��`����(|vla&H��qf���c���3�1)�����|���;� oU^�"�y]�R	�� K�D����l�b�3�t�WQ��D5x~` Xq���],%������� y*c�7Q�/�hb/}=�nX�*��e��=@�}D�8s���[)�W1{��{+/�U��1��x;?����Qx��j8�����~������xF|9�w������\��Y�P���*���p|9^�49��N1���j�P��x��x��Tx0�����������N:�l�
!��d���������!Y�xK�lgF�
`���
�'�[-����U�����9Db�2G�*�2 S>�����RG��;D3;�^�t��X��BZ��>z�9�|��F/1s���jYA5����=����
�R���q&���0�����>a���_�n�b�W��0�c��(KUB�J���}��W�t
<���+�U�
e&�4��W�p>������y@�*Z+Tw�J�&���3�����W����:h_��0���83��I2^e��)��
�<Ltr��,����b�x:.Z�����^v�-�x�;t���^���,�/�'���"^���*��]5}\J���v�oG=����|�W�c���7���,�'sQ�JO�C?
��J����,����%o�b"{��,P|��w�B?B�Q4N7��j!#]��NK�l3�w����%�*(��a������v��������/|o'M��w}1/H�8s�.�E�*��$�� z�.�����< ��L�D�A�G�����@�o��?��������8�
���o����.�W��8]�KdO]'^����	43���*��������N���D���b����X��F�0���3�����K����2���L������h��U�/0B	+H��|�E�U0`��<�����R���x`�����V�����*8���GE�gZ��?���]�e_�!�����-��,KH[�.�[�Z�,���������\D���y��-�WY@~T$�w���b��<����~���,��A�xk-DS���t��F��E�5��a�}�|����h~;p���C� �c
<����l\y����A����&�q^�b0�����p:�L4�(�7�F��|*��;f��!��k7��M'�������}Q�J�p�F���s�o��.�W�m3?��t�#��[��x��a�:-�*v�Pd)~��@sz�rP�u�^e��/�k���3{���^H����/�g�rO��o~�~��8�SW� ��_������W��<�U-����]i��O�U��5�[�B{�0���8�R����l����
>u3��0�^����w�{�Zka��x���M��������VB`��*��%�x���ON�U���<H������W1�Z�p�DO~�v��Y�_��R.�~=qfKa.�bx�Ig^)�j�*�qq~�JF�|G�c)�`;F�*�w�j(RH~��k���._��!?Px��I���K]�*��c����g���JGy	3����g�3��R�G���������&���lX*��pA���T��/�WY @,a,H=zgEH��<�������L��y+E�*(���c����<�m|�5�/>z�{����b�c�W&�'�k���3���U�g�%�����y4�b�*�h^�&D�d	����K���t�Z�p^������w���X���S��f9�U&8F���G�F5R���-I=p��{��<� ��UZy�����(���^���*%V�^��5���x�en?�@F��c�b��c��-��!7Px�`CbE�*�j�
�D��;`��� ��XT
s�������>����;@/z
���4M�<�c)�JiR�S1�g���mE�
��{�� ����p�^��J����y@��Qd���!���*fc����*��G5�#��]��)Wg�_�]�c��<�p�;����#w�_����G)^�������;���eR~`kG=D��������^�0Y���O��}��t%
�w�5�������wu����4�W�w��z���'�$_����N�DO��j���UDw�f�W�=������:m!��*#�����d�����(|��i]��%�5�^�4^e�f�v�|���> 0��oL�.]���u��W)y�iN��U@[_A#�����������=�f���Y~�E��W�������������< ���m�E4=�pU_^��_����2A����G�����.�{y��O~WS�6����f�E��w��c���n�A~�KdO~��W���U�8�,����t�U�.��{3���]MK��kD��3���A#��U�>��O��qb}���x����x���:V�H��*�v=���d:s��g���2�u�N2�W����v���~{�>A��]�D�o3��,�oy��G>��4��l�W�����G�Q��������_��
LD��]
|���� ������H��0�qS�J	Rd$�G�Z	�@��W�h�����g
�FERx������0L�d9�i��j8t�GA2\tH�6�W����z�-�*+V�7�W�1@���C�Ul�}��^�\���D�{��z���x���U��x����&x�����p����o����*���H�3��*�t�n�W���=�v�WI�?����m��Z&~����ZK��;��������q���7/�_e
;����'����������?����U�i�O�w�������G�A��g���)fx�a���)����'�u�?�_3-l�g����3gx���5|-���� ���M�*���yqF���L�$��;\?��BX��U�Y������?��M�L���t4F|xG�����F�s�JB�B�I�g���*��U&����DO�������tM��U� z�]o)��7����%;�61����WI�.��L�W���9pm�WA-���������6�� ��������P���_�l���U�)�n�������_�����Z���pb����������)l���0d��jp�L?�h��y@�>\_��=���[�Q�D_0~�zT9D��[����M�*9�i3�8<�8
�8��a����n�9�Mx|�DS���F��WA�F�5�4�n$�F�]O��)��E����Gv8�Z���x�4�5W&���Rg���b�

���S/���[���WIy*-�^
�'�����*�ZA��S=�����M�*
_<~=��n��}3���z�����(|���������U0g��(���J
��U�����!pb��N�*�v��<��W��Q~�`���L�UJ��Kh~�d��F��;j��$ozwUJK:?QK3/��)^���k�SWI���<�~M$q��WI#��n�W��=zrD�Aa��|��{s{�x�^eX<2W�W����n_�U���{�M�*��������z�*���y@���+���;�AB����,������Y���9a�< ��87���gP
�����?S�f�'���4xj���\��/����0veG�JE�kAt(^���9|�W��f�s
�~�WA�u�f�W���w��XQ��5LB%|�W� ���"�����_X��I�_e����-������o(^e��<�^�Z���
��1���c���
����W��T�t<���aV�����z����E~������5$Oe���=6h=���F��U0�:�x�y@�I�C���*�3���u[Za$j>u����9^���^�5
?���p�^<~h���+����q~����
������3�
���0\����5�W�FS�
�XW��N��@���s�J���3���,}����stx�a#��������9^D_F:�(��N�M������)���e��J0w���������UB"}�+���)�}�%�@"C���y�a/��
���z 9a��`5��y���sb��qf����pC�A���R�r�I=��.�������h����Q��
�E��\ ��0���'������������������������3.u-�f���?����������������3���fI��K3��7K�f*�{��z�O���?��_�������������S�}�����U��C��D[���^!~|�j����P`��Q�
��?q-X��G�?�yt���������I�����Y��Yr2>?��\�����W;/]�*U+��_��_,�W#{�M� �������%����j��L�ipy�\�Bc�A~��\qj�M��^�%0�hlB%X�yf����K^�2n�VoYE�s�P>�g"���B��C���o�%�K���[���������,��,���$�R�RS����CN�p��B��=�t����#��W�FU��Q��� z���~��[��o��S�����5 �J��+�n�\*�2�6�Z�0�
7g����%/�J�}MH�����+���`o�����NM�������2��j�� 
!~��X����P���!������y?^���\\���`a����Sap�����R�g�gV`��6C��]���A=j�����/���z����.�����oQ����3��D�Ph�o��o�0S���k���!qF�n�1���|�\o�
������x�f��~���:s��#���"��~���q�������y�u`L��q4�������B���7~���������������V�G����v�~f�\pt;��q��:���\q������-^v�=F+�YS���=�I���S��?�F�9~�b���U�t��}�����S���U��%DV���L�3���r7���_�n	X����|8b�R
O�^�&�,t�����n��m�H��gm���E��l7��� B�6f��]���"|����k��1�D-q�����,b/���v
�����@Y��-*z������a<�N��fv*i5O���oL��fZ��J��o��	qZX`�f�~�c���A���A'���'�����'M��#�)�j��o�Y��]<Z�/N�@*�������������Baqs��/�d_�b��b�DL��'��+�@���^�eV8F�
��p��4���[����M��_l�%o~��U�1z������%��
����A3G9���uy�7�;!u�J����-���A���������������/;]�D��A�8�4�����!Q'�X0~����j�34D�=8��h(� �;��#N�UAS8y�KN�3C���x������m����^�r����U����5�N^�0�:i��\Y��$~�`:=�m���V�G��K�3F��CB���=���.f���{���K�1xF�G�
�SK�L�r�D���}��Vs������-�%����y�B��o]�Y@�m3���#����m?".x���"��~[�����&�b�i}�E�������$/�����9�HH���6x��1���1W���{.���X�������rpv��}W���\�L*~��q�%5����/�|��}���?1yK��&��W��������yzY����v
f����O�(�t�I��)���������E��f7����
�%���pO�������{�t��l/`��^s��6=�R\���@�15;���C��L���jS�	��G5&��9���S������ ��5 7s<���������s	���93����o�7�E������q�&V���N.n��u#+�o��)�N`I��2��S5�T�{�L!��e���z������b��_�t$r	���]�N������Pu7#?V�=�;�}��k���y����G���aPk��X���V9V���1��$��fQ��UQf��Q�(<��K��c6��.���-9YYW�Lak�2?M������&R��v�4~�C���^������cvr��QO/�w>�������������?�C�X,��J���I�Ec��5��������RK�~)�{)�_�g6i�J��g�a��������Ll�L�g��H����4^-�����Z#W�c����^R �(t����3	�3��5bD�LV����n�8���X�yrA�������uR����]��C�gCg#��`�C!O�N�
��������-��lY��{�W����,e��,�E�����	c�@��L,j�����Jj��6N�*���3�<t~P��C0�0�@.����G��T� 7F����u�}��?+H<E��z����iD�����v
�W"���	�C!nE��EZ�1n��]��V��_�}as���?,:��a���x��1~�C��0�:���nhK�@BD8b���G�#��Z`{#

|�b���SO�,B}������Z5~P�
s-�3�L��Fl97s�[�x.�������:E�3S���S���'/~Y�g�;�j)�B�Y�'Po���P%��2�x�,�(�,��j����%j��������o����H�[^����<�����}�S�	�
�p#���{������*��v����8;�S�"����-�!j��.>a�))��!�H
n��E�Lap��G[�fNV����~}/��/J�-���b�15T���ypy�{y�
����������	>0�[l��>8dO�	����D��qc�/F q����8*',8�<���,xkB'�����U������i���K���������x>?@�*��}/K�^
���f���+n}^�m�K��t��r�����+��&R�%.os�j�E<o����W���0���.:��V���YA����L?�����`����"���
?YQ��������09���1��/j���3F!^��R��}aK9Rn��yG�;�3^��d�&	��E����-)S���Y������������������i���+2��0[�N�����!�Z%���j{�P�$]�R�S���������=$j�""��9lc��%Q����T�&��d����XrB�-��:g�m�KA`�j��LX	s��+�����<������C�Q9.���c0��?���=�I������=���^�g�":W:���~JYs2�RT�U������Lat{_����qs��4NP�&�*��������k��u�1F��-�-zft+�K�t.����G%��<Em����[]����5�~
^�wsYuxk���wLlY/�����C������,��
������krIzv�������������o+��x{,4��J��P�[ �3���p�r�_.�w��Y��`���	#a������������!P��n��$��ZFS��.�l�^��v*�������?{����9���^�<s���+hl������l��`��T�wc:���� B��o�:`�g��K���2��)��1��hl��O}��U(�9��Ab��u���������i�B9�����m���F�����}�d�>���������'�a[������(_�M�[�����n������)�*a�3�_M�����-��� ���������ud���>�;�*�v~���x]:I���%'��=sPO�M��-��@����+��%��a��P+���$T���tz���xU�,9�:0�}�����r��a����:)���J�v����B;BwMR*�#)���������&���2K'���x���?q��$m�*t����'
��B�u�������<+6M4�����"z������l�������W<#:??��x����hb!KNT7V���B'��Z����B�{�E�5@P��������U�����Do��0����\C�u�M�7A�����2��[����\}�.=0'W�{���q�|-��s\o����I��>SO�8*|]�M�9��C����S/.�w�R�)�0)�����W��P����%���$.}����0�,y���eI�i�C��������� ��]t��m�g�'k���n�W��l���)���-�fu��_7�saTr�aa���W����DGG!dr������g�-����a�FB�W,����iz%0���]gu~�}/C�|�{X��"��[��x�BI����8p%��w��^�D���	3j���c,Q!���dA�#,�jH|��������mg�l���GQ	B.�����vQ|��7��]���cA(<��@|Y�R���/x�������l����ykP�~��>nU~;\8�nc���Y)|��������9ao9��[k��v��;�01i��c���a)���z�v����-����
����3�n������ZXt�{*���5/zOIi���U#��K���/��uU�����s>��!f�:�#�%8�	�zUk���]��������F���nI���������^F*�y������l�'��)���=e���aVT�7�$��f]LL(_�D�+�J���@� �.'����v����z��o��r|��&�? ������d�/W/���c�^� �N�{�3_��#�$������GC,
!�kAt�B���:|IS5J6�w^w2�	�%�u��O����&�
���do{)�H'����y�\����#�|]A�`,EN�<��t�D�<'S*x��8�,������.,5�
S��u�.���M����%p�l�����C.���Bh
�����V�Y�%�� �	��S����,���Pt�M��������0z�e��,C�X����d}����ea�$��l��)_����
�F����Q9"�P��u1�
DYr������(�4E��������K}aZ��h%UYF���5�(�)�:W6G���y�M�����>�5�W�G���r�E&����n"��_�(D��uX���������a��(�P|&[R"l���U�
��������{��S����)���4o�!+���e���7<m���J�(����
���/���P��,���������Y�������	����(|���Y1����x��B1�������)�������'��}_�[�%����|���F|��@o���j���[r�c���u�uy|}��?+n�+��ajM-�e>.9�m),��*���~�-F���b32��J�u��-����{�-�����R��V@�"f�%��[�+��U��
f�����-JO|�
O�8~���B_�������\����F����?���P����Y:Ps�n���s�u�������1|Xp��.�7�W����^��'.��;���)Q���������[4'������?�sW���J�ui#�V���;���Y����/(�0�����'S����J�m��W�|k��\�=��{����������_�<�<��_���!W�_leS
<a���M��6F|��WI����[�{[�r�2|]��z-j�����D���8|]I�c����-��T����_�j�!+���,�5������\r�����m�K<�@d�Dp��u��@p��]�Q��d��'�|>�����w��)�uf%�F|�������ur��$�u�����������Z��U�J�u�[��7����0�OqP)��x���<����G�|(���1�T��mt�����^#+��o����J��
��p���X���@����,���m������D��R|]Z��������x^��
8����;`�*�CdPk5u��_f�g�.�*������`����S�-K�V6��ax�&���%����3��l1DO���K\r��,}pn����)8 e���S���G��w�GU�)|�ZbvS���kD�������U��U���`R���,�w��Q���n$��U���������r|�TB�������0�����G��^����n�������
f�Y��
��e�i�SE|xJWST�a���[����_��,JM�c��S��ITh+����e�Ex����������=��!$����'��^LC�����W��[�q_��|�uW��T��uIW�_g�<f��z������"A��s�c#)����B��2R�,�y�G�K������~���8�n�-��+��
�Z	�7������jL�_��U�����x�UU������f�����>DbB�u��4��d��w�������H�q��R�:X#��b�+�rV^�Dj�:���?(�:��)<-[t���n1��y����D�@��z���������

�|O"�n����/��&�Ou���u;AR�8�
_7��R�_7.���P�K�/C����n��l���������
d��vV1��,9�:�w9R�2|��i������u�)� ��{4��$Xl�����S�b�+`�mo�������)��_���N]�
���C��_�Q��[$_W@��w���~������zO�\�nW�41�>.y��-�������a���o�o_M��<-n����Y�+��R���Q�d���gY�7�2|��L�)*Cjl6�)rE�_��/(Q�;O��(���uvdlsD��g�.��1��:�������:6���_�3|�:]��u���t
�,"c��u%��Q������F�\E�J��Y
�e#\����U�]����V:��*W��������������V��J-��%o���%��F���~�"�!T����]���qh�=�����u�JP&�E���%�����s�I�?����F�u�-��bxX���Y����,F��a�a����$:�����.e��..9�|��������,l�� .9�y�LTo��u+m=�������������.9Vc��9d�|`pO]��{�+J������#����-:���`��5��M���l�9�����-v���s|��T���b;AL���&,8��4�`�F���$M4A���n/^|k_�^�Q�h��K��cp\a��:��1����C�\�:���A,�[�m*�74����"o��(|��M���}��l4% K��cf����^g�N��b�n}O���8}�@u
#��u�+�K���m������w��i�����0�������N�|�����_-xVm��ol>,F��!��=q�����yL���m�U�U`���u7�k_g�71���8���#������Kn�)��
nU�|�k�HHm����{YC��:`/,L��v���|j
��!���a����c����u�����2����7���������Y�5_��������+,8Y�S~5�(�.����P\r��������)�io\r�����}(]��s�#Yq��.�o���lG,#�,�����vN0��1�-��_�,����,������	�M���a0��h���]-���X����-��P�5�"�3����p�F�u��W�P�����|����/qX����s��|����"�K4�������E���8�j>l�Sd�����,�B��]S��_����U�
_�=���F�u����<���������vg.���(`H|��w{(�:$�j�([�����m�����\�������9��Z#���@�$ �a���K���|�jv���n�V~��D�D�����5�(�
|�epU(��m�3P��%�u������>?�\4��U�a1���S�_W���,����Y*��5��3����_�����������.��W)[���HWS���h��W�����T6�_���&0=A�X�9yW#�u���@M9�27$�2�����*�	|��@��:���hzA����kT��a;��2����]��_w�{f5���H?�&����a�bb�Y�����
\_W�E��;��5a�e'��>+������s_����[�����u��1���_��B��������p�u� hg����6ev�F��2^�
�������	��F�ue^w?"$�:j�%��uW�e���q�����r��K�Mq#�u��_W��h����}W�u pQ�k{r5b}�+��BWm"��u��i�&�����zUj��Cu����uD�&����_g>����4�?�{a������������N=��?����eq�:���(�R|� �M��W��������u}t�]*�:�������]���D,�u�~[�R���������uu	����u�&���}W����������@�E��'���������nb+[t�{�I�_7-��Y].r|�^��|]�����5��UKbE�u��Tt�|y�w+�����(��K������6�*����y�s�%?���g��.g��2���u��T��������,���H������5/q���uuA���|X�q���'{���Z�a���aU\�l���^������jCp��{�1P�:����,��h�������D�=��VR}��a���\z;��a6��U���%����p�s|��`�?q���w*��3|�B����W���W�N�u�j����%���&��:�[��]�`�$����9��S|]���h���S�k��*�������9�l�3����u����pk~��o}oI0,t�_72Hv�LX��U^<��d>lkKOa��tP��I��`���9���k;����}��:K{�Q��%���vcJ�u������8�|�6������p)�����v��N��!-���t�YYR&����d�-Rd�(�~�"�������#g���E���D�E�D|������e����LA]�	����[�����jA���_g��a1������D��w~���a6KP
�%�^W�r�_g�|CS���z�mK|�|u��-g��$+N}^��v��+�j�!���!�������'��T��%����T4+�u�����+1l���u����u�U1��-:Y��.��]��^y)5��l�/�������}D�a���-XV����p~}��]�(�t~U��n08$1�5.����Q����:����L�j���v���ZA���EO���b���N�u���S4q�%�>����u�_7�c�%�d���l���z�n�=�������80�+5Q�yL��E>���wL������5��x!*����_"�"����5^�	��7�-�{��!%Iy�K�������������k��������.�������>Sp
�%���^&/w�_���?n�$��N��_g��M$�_��@�v>�<&������}�$��:��2��d�n}o��������5�Ug��07��tM���O�#~� �ucs|~��:�j+8��r1|��r4L���=�=3����O��~y��=�����gz�����t����QFQ�1�2Q��_�Z�~���{W����4#	.n�����,N�9��+�&_��>o�&o����n���

���w�J�F�9�������##��|���|�}5S)�����S���N�uR���
�?�8P����.<o3	N}~�^��;���W�����uI�-u>�_xJ>h<.IO|]���N���s��%Yq��R)��"�<G�/B�=o;�@=~[����B���������������>�'�H|]��7�u�_7��tu���u�D�\9>�����C��_7-������0Da���w�n7��9���-��|{�w|�XM�Q����X�1"��%�>o�I�))����H{���'UUh��uk#�]NV��>-R'���J0*�7��%?�|y(��U����`x�����qn�:L�KE�z����%Oy��7[<��y�����N'��x�����g�.����
��%��MaA:�qM�;���C+��;,8U�V;�F�t>l��~�*�S|f��-n�)��y�o/����D>���&�*����Z<'�����^���eQ��aq�����%��W{.Q���a������M�!�A�_�jo"��r]ST$��r�C�_��I6W���+�������a-�Y�	��_�����|�ey�8�_���<�k���-���To�~y�$	���^��s�a�����L����7�_W7�_TE[��,X���u3��t.��j>,8EEL��e���H������jm�_76�h����=����[_��
�>���S�C��g�[��U������rj ���&&���jA:x�,�6����A���r���aa���x�w�#hm��"n�M�9|���%A?BV������yP|��4�vIzN
e���&��1!��K��]Y<�����`���h�^�j�a����3k��������Km��:$'k��c� ��<�_�������������%��D��yn��n&(q`���a�-�2|y���Q�*r|��
J��������E���w���t:"w���������,����e!:7�_�2�������t��1
{P|��r��3��[�1C[x9��`�W.B�����n�������_�U=|��n�W�z]C���z��[��|�SXp��}���m��mT�����[�-�������]����Y�����{S�Yd����x=e0|]�R�Yr����s����:TH�N"R�:`z����a��\����E�����������L�-J���b������})�� v���Kl��������`��$��l��C�H�� ���^�tP|��t�[���-��[$,��+D����q���%�>>��P����c�s�
���ma�}2"K�}7Wg����n3M��>��}�*��zP|��!r�*�Vl���wW�E������:��E���%n����Fu�ypA��}S���`+1�s������ge� ��_��,%��K���n��#�q���n��������J3�_���n[��?.����hE�
��>�����u������*4��k����}}���M1w�����<�e��I��5N���u�iP\�����5�d>����(��
������,�������a���(Ur���u��t�D	����%1�������^M�|X�'6��������"]�]��_��XnA�HV�z�b�t>�B��"���u=	�A�u���e��s�b*N�3]�_��z����[` ����� ��6O��Yv&��t>ln%	��a� �|>lE4��'�OI�r_����W~��$��}y���<0|���q��ws������Z�c����|�I�Mw0�:���'��d����h��sP|]YH*E�=Yr��(V����fi����u��!���m��6qe��s�>�!5�n�ZC�����*r@������ �{�MI�M �������;�_����������a���ql��������8(����".F)������G��o;���(��Vu,Yq������+�����
_gi��G���xz5�����������>.�qC��_g:�9i�P�u��U�R��J*M�e2�_����o}����}a�:KJ1Y��9��Cp.���e.���Ba���
F}y�W>j���$��-���`����v������s���^����� �'+����_7������+|]2u�,���D����_y�g����f��e�D�J��J�r|�Zh�V��|]���"����$�1�t��UM���5K�n8�x>�-�q������;��'�/k
G��,v\e�1�q���Z�?���a-�����3[$�����!��C���f����:t,�-�R��t��S��_$W/�O�}oks������������.:��������Mc�EG�Q���|]~L����8�?�u�p5#�������
����!����en�}&Tv��
�����v|���������q����e�'��!���* .IO�2�5>)���U�,FV�x�^��I�u �1�������������
�����������M���u��k���-:��R=�S���A��9�-J��d��b���Y�5-������,���I�u��MUP*���Q1@z���	�;|�j�m�wE}��;��t�RP���|�l�|Y�T�:��E�[\r���:�XA�=��@*d����(�M��+u_���Z�>����[`��a_���"���kVH��'��m�@	�V�]�~�&aX8�������O����q��$����u�x>�}�o�����F}�$\x_������/��6@�q@^Xp���4��&������:x�..9��4���C��w�%vH��R����&��Y<��e�"�~��3�I���U��B�.�Qy]a2|��xw���d����3��`o����xQ������p���.a6���B���5#���de]�:5	���GsM�u���|�iVO�p�QXp��-U^�t>lf�������|�����6�*L�����(�n��])���1L���?��	���\r��Fj�m�������TT��l��m=�|XD�E�=���/�����q;1_������g����j��&� �u{
�E��:��	?���1��w2�U\cxlXp���Cp�N�_W�1,��n���m?_6����Y���|��:r����V��d���,8�&������S�_��i��%o}�eG$K���"�S��M���#X��[��V_7������,�T��|���0������R�"�����������!Jc_W�E�����'_M��M��-`������[���ta�9��/q}�;��n�����C�>�X�c�x^!�&����[D*��n%q0�n�+�3���{�-�Z��k
�:,Z�
��u������0���������3���D<zg����3�'���@�&5��[j �$�a�3�U���������m��1���!�!H���[��#"�_��5*������D�K�I����5�G��l���"��':���z���}r�d��	��K~���7�_����UK�Qx����W�+|�B�Dp��EG�1s����;���A��{k�����Z�Q,�����:P���qr|�Fk����?��3}y���w���)� ��3�+��O>v��[��|Xt��Q��Er6��K����(�����OD���n��y�&����y43CFA�}�\\X;�_W�=*$��a����u|�0S�����3�"*�_g[3���
�'��Y���+i�����/sns|����_^���-}�H�����%��%>�0F�u�"�����������b�����7QC����!(��c�WY���,����n&����s��#���t��g���)�����)�Z���]���������o����-J���&?��3�e�����u�Ai|]�P#�����/39bwF|p7+���Q��)��������P�����:��D�(�u�.>)g���
&U� �uv�����u(t}},��i�����=�N+�/�%��oWl���_�u�Y���_WR���u82{��������<�Xq>�.�e�������k]+��j���%&m�'��&�e����jms���nnT��\��nO3�hC������*o-�����.���%'_�oE�����fn����t"����#�	&�_.9Q]�"$X_>+s��g�,9����<�\_�1�t�� [���"� ���u���d_2��X�p_��D<�!
�G�����"�:���3�������1���a��+��A����r/�/��Co��i#$����x^E\_w7b��H\�N�L�����o��z�����u�F�E����,m�C������v��|X�V��H���nf�������o�/�-J�V�,[
_Ui���9��>� �E������ �{YU�a������"�u���z|]b�5^��]_h���^�'rLW\r�y4�y�7��`EQ7.9�\6O�����z��m�����]�X_W0���qT�.���r�E����Mo�}�d��^7���_w�r�7E_��������v1�-���7�Y�G�:��b�=���[��J����()������{���E��Z<��N�50|��z�y)m1|]�48���������y�����Vx!8.9��:���(�3	��@EV�����
mQ�:;�vH��,9�0O��O[�s�	�%��cP(�+,�����N��%j����b��x���c�����s7;�,����W����w����je�;���gd���	����^�V~��9	��5����/.�w|�*�������'1�3.9�2~�X�>n<�R5A�"=�A����	Z�.0�d����W*�_�'�R�x^������.ow���>	�[t�}�,�w����^�K�-z�����-��+���o�����K��
.�k�>�u�"�nZ��f)������V��_Wa���q�K~�w�`�8�n �D�q���V��W_����8YYq�]M4Xt>,��:���r��^Wm���u������%���4��N+�:���C��_�-&���� ��3�=�h#f�N������K�9G���+*D_��&��bW���yh?_d>,�a-B���u�|�0�_�0v�v��Kn}O�X�B8���[�C���K���"Z��% �GgJ����E�u��]D
��u��X������Q8��,IO���G����c-�t�qQ�q��f��\��c�)�Pl������	 ��2g�S8��X��?2��-�%�
��_�=��:;W��J���u��Y?|X���aT�MP	�%��/�.y������ ���|��Dq���
�0���d�O��������>��/����%d�����
�k��E�`�����������Y�d�������6����
f�����������a8#�
_�.�8]F'�����c������u-U v�����,������y����������n.��CQwL��|X��P����������������6]����[�-*-�������?Nu�[��������.ZF��[�g^M$�j>����z�����&|D��	���B�9���&�q���������^������F|�}U��M�����|�_���^w��*�6�%�>o�W��_����/��eo+�������= ����c�)W+��+y!���{79vO�^��nc4�h'K����,n<�nT���&����ew�P��}OO��n���6��+��y��o}�88������4@��<���cq��&�a{����������_<��_waz���[r�;����wS|��4�����g���M�u������Y�����{�o+^0��������x~�������u���w�����9��u��������w����h+����37^Ke�����v��p�Y�y�?��&j
���PE�w�)SX�_�������apl{Xp�:�P�q��u8�S���%�^�����)��������?��=��U[���	s�Yq����gS|�%����%O��*���t>�@_��= KN<_����)������������$��
_��B_����Di��	���^*Q~,9��hp�	�n%�J�Wa����������.��U\A�g�-�x�����"b��U\r��fa��?��_W�u�3��u�w3�r|�����|�
Yq��-&l�����*2:��Y����gS|���Ue(��uy����
O�`O���u���G[��US�H�:�j���m�_�/l��9���m�3�������->�@^s�_�-[�2���QV�V�+n���@�,����z������n{����%�Z��h��_��R��,��8;�����;�h�#K�������;��Z�;T�u����v7��M�������n}��O��*�:�Z��-�O���-�����L��R��)�H��v@Z������y��/�n2h�����_��S�9�z������%��������u�����'������|����"\�sQ���.�����I|�����?�~!�MK����:�u+/o�_7k7���EG��,"T��:{�Fq{����������M*���u��^�M�u5]DE��}7��7�_��&����^�F�4������j
�KN�nA�)��������8q�����������H~$����M�u3?0�J����e]���u�:]W��2d����%�B��u{Zl>�@�E'/����������
�����!j�_W/�'|
��Y�,
�_g�w�.�b�_Wg��M�u�
:�4��2��H��n_S�h3�K��������a�f�
��c�s����]�wh�/W���H��w���
�?E@���g��/a����(�PS���"hK6��>�mQ�pq_W-v�����u�����vQ:�	�%��f�������������@�<������/��/��h19&,8��hM$�t>l����^��i-������E?l���K���196i����M�S*_wuqd�P|]���S\�*|����}�L�Td�@���d��������������?���������������u�SE�A�u���/��u�`��B�uWKfi�j�]��e��|]7�U��p�:;�K(/�����U	G\r��^������|o�"��uxG�u�QG��d���7u�)��5����p��u[�9����V�_�3dI:���#�������n���JW��v!O����u��7�.o�_gI�������0!_7�%=�+1�TA��	��t�af?]���X�����9�A��..�w|����F8�M���{�����$��N����u�
�H����fi��I��&���H�ny5J��d	|���~}�[�2�{��+}7�(.�4����-�������P�����'�N��������C��e\�����yY����(n�K�+���#�x�����W3{q-G��;��1<�yY��n��+���5g���s���_�I�'�l����`\z[�rAsM���
����>���ok��i,���.�5�9)x��������x�_��U�9�-���-z�3���������1s�O���_����������������_����������������_����������������_������������������.:1�`
xeon-pgbench.tgzapplication/x-compressed-tar; name=xeon-pgbench.tgzDownload
���[�-In$��EN@�~��.�
h]*���5c�s���s����rC����X���F���������g��5���������	�5�gN��3��ro���{9��K��6�=���������_���������������Dv���������������~���������W�?y�Y^}����\m��c��^�����{.y���-���Fy��w�
y
��>�V���>�UrE������o��_���V�L����%�j��6{��T;�����X��Wje��s�^��{�z���o�om��^}�%��|���U'Fe�m0�����Oh��m8�����x��������_��6�����g)�Uw�������.�&}�����W����0�/���8��~�xkY����8����^X�IVl��>2v����_0��b���V~��s��/��/u�v�V+w+[�X	���\{�����1�k���~��R7�W_]����~[��A�-|������������
��GJ��������1�+������U_s�����������6v�2���k
LB`�>v����$Vn�/L�jk�Y�����h���Ff�����\��H��1�����
������^����?��	��������_�z��
o�Y8������Q-��X�g~��5FB_�9������
�y~��7��t�>����'��������Q��Tj�c����-��H�'?������0�YN��1��6��]�����{a��%����8�c`�hZr�7�X}GX�2���|�(���o��s+�H}�Z��_�V����E
OP�|s6N��";[�8�k�4��`�����5�m��l�E���m���4�*>i��e|x��D�?x�s�4|T���X�cgL\E��Yq����pd^��S�U1z�N��M��Z�[m��S�����/��9������'�>��k99v����F��5x�3���P����V6������C��������M��]���.���K��r�����H��!�K
w&|�
~��2p1�������n�u�m���_�9�m8��~�~m�2|8��
.���s�/��8-�\D�����Q6Sde���<�y�B���b��n%4��N���3%�`�3��%v��I�����&a�������`�G������j��kG�3�W$\�2��e����JU��)��q�qw�f��?+��s	���pE`�*�J���U����1�~VJ�GQ�����%Ov���GP�:���t��Xu�7{�g�/~@���+`�	NPW3wa\q��.6�4�]�F��&{���:a�U�b���f���������p�`�Wq�����'���Z8�Cn���/<�� ����=����h]g����	$����c��������~�]Z8j�������������Lj���q�Z7
x$�����:<���C��'H������o7��y����g�f6
��+����w(x��{g�f���y��	���w_8�&���_k��`��rhhs�@����|}B���.M�����}a���� ���0F���tD����N������v.�z8�S����p�p�p60��qp��� �7
�Z���n:�M���s�)��x$�^xoK@w�~���G�'*���Nx?90�4��8h@({\u`7�-��i��d a�����qxq_V
�v=�vMNV��!q��@/�k- Z��j��@��dl+Ix%��=��*���s�^p2f�$Ln{������}���+�}(�=Dn��l����sVym���%63��0��;�����Q��_k��a�f���
-0�#C���'P�S0^�2^���������-a��F��������,��`LG��4w7���z�>���^�p�� x���T��2
����pnV�}n�������A�a�
n��ae6��ke���8m2��}��T�:
��=kO<R�B���C)��#��=p.��,L�ou�������
��W2��Z����=�M�d�+���F�%l�|����D���\�p���=��!��^�\��N��1���;/u�!���v�i=8�pk{?Mv�W�L���n/d����h��tH���'�8b�����v��VG�X<����y�(�Rg@����\����~��;�8��V4�]�xJ	p�3���=�k��N�]��{��id�^�y�O�q����g7
�J`dw����.�3`]v���G����e��p�����j`�����yp�z�>~�;����z�l\���b����	��(�+|9lD�#��+����0
x)|��Jhdy�G@>���}�iX/��f�=��XE�+�n(�A.���i����suN
�A�x�:��S�<���Wu�4������JU�^upQ>Q4���%V��p�^����}6
�&����wp������w��!����`L�c�J*��������F�ZK-�*|5�%94�4��p+���7�D��W0
}f=�>Q4.���3�C�m�X-E��i�7���[��[����{����5��8��EP4������+��^��]B{EQ4cD/�d�

���`��?������`�	��F��8�X�����8�������� 3���{70�p�%5�\Cz1�v�H�6VR���G���b+�+8�t��T;_�K�1F�
>Po/��W�S5	����UH��0P�)U��:��#(�pj�����^eF'��E�X�/@$M�I5O����8"���n��~�/^�3�����8��|��t�L�C���/\�E�q�E�L�L|��P4���EK?LP4]d�eE{��y����#Nr���[����y�n���u�&��*�c����-����w�h�^���\��,w7�i�8�O�p�3}�I��Ptfp\c�Er���D���=���%V���n7�o���=�=��g@����� �j��U����<���h�N�����k|���+1���n��z�D���wC�~����=W4|�v�EOR?�"�U��n�yb�b�Os���2Y�-����������?����V8��s*/��h�w�$��:�1lzN����%�Cl��L6M?��E��-�����Z����x�����{)�#n�PcY�c<��^��
Ol��;�T�������r������������p�4����~)`�:#5���_L^���3��4@�z�}3��*y����E����'�M����^�k�yWql���f�8e�54�i�����@X?Q4����f�W?Qt_L��4��S�����a�+�����e	R8UP��d�v%�V��q��F��4����)3�{t����y�9�f�A
����4��p�<"��h��peF$�`"^�+�8B@����}���-�����B��o���L�[��[B3�R���Bhg��^;CK������&�|����+O���(q(zd��FF���x*���������V�k�(z���c�r�U���R�y�j�vC����??�M����c�vv(a;���Y�_k��E3���h(NN�J��
��
���K��P4��������C�p�+��M�g���,��:��n���7�TE������q���#�\E����R
�Ec��b�ru�E[T����Bw(:aSO��=02O���r���C��l��H���\��
yk�z��+N��K�O����M#�h�<��4
W�
�.8d^�IB��G.:qib��cL$
�g�QYV=i{���hh�~�h\��� 2�+z����SP4N{\�u�)�Qt��-��y����L�w�f�^�Uq��G���I2)c���~�'�	���
�����P[u���������Pt��
��J`d���A���n���;���n����C%(�b�
3�54�$�($��H�������]��)% ��q�Zh��'�\Vs#���r�8/�_.��>Q43�������$�����[�Cu)`t(�41f��5sw���P
��n�3�p�/g�R%�s��7�A����+����J.3�"UTPs(�X����E�����mYJ���w��!����h����wf�@���ES�Mr�$p�\��f����R�7o���U�-�jG.��b�p�/~Ptf�� ��r��+���#��mD�>{��gh:N0YMP��1��fo*�j�>����s���2�k�\HM��f��3��h���t����a[EK_����0Y8�3��n�D�����V���O���f�Fv(�ix���Z�)(�����%�~�(���@�qMr���6|��#}0^�d����'/8��{?B�op�q)"�������������D����	�r���E�n��j��y�N��uajU38R�J`��
�m7]m��I����$��$�o��!Y��9��T���9hrEO���V7�������P�Z�D��,5[[���h:��hyZ���J+�Z5z��������
����B�Z�t�<��/F��8TMr����v��&�����5����(:��/�J|jG�3�dV:f��n,t���{�����sZ��������}?�������X+)i��Q4�
k;r�MP�`��q>�OV%�*4A�x+KC�mZ����mY�������&���\���+xfD14j��C�,X�tf����%x�i6E�Mj�{�V��g�G�)���E�j�Pt�KI������i�QY�z���
���H�W�E�eq�����!����?�/t���M]�#���)����Mi����]M�U�9��h�X`oM5��nJR%�E�5�7����9��L�c��a]���C�)���L�V��\.:��{uW� �O
/sE�vFv7Pg�U87)z�3
��X�}��a���zJEW��,,K��0���W'�e�v��n|sL��"��(�>����+k����<;%����L�q�=����b`a�B'0���)-E�����1j~��TOi�EwR�T<��J�U��z��3���H��C�(z�j��QM�6�E/+�j9��M����y���E�5���M�����������F�$()IkY��hV�`G(|�Eg��4T�C��I�^E��������<g\�#�{���IM��]s���8�Z��E��o�$��>��Z��]]t���;�.T�(�23��C�+��eRp�%�%�������{J@�c�#�f��%�+8��v�eaS^K��~��q��T�9pa�4l2db�6�F!�Y����Q��E'�pj�K�(�U�:�^���hRT�=�I�.(zq�6�V�%�1���/�����PKa89~�C�����l��h�NBL�.��z���;��%&%(�}]t�������=:18+y��i`������������R����1�c�����h��W�R��Ks�s0�M&��+�N�g�"����4����nwu�TfjX�z7xF7����Q�G=�!m�����Q4�Ga-`�M��n8�x����t�am���:j��+x���\G]4NB���CC�
,���7S�����X[����*A��b�FO��7i��H�\4�����Gfo�6+C�M(]��Yz1p�����lS�N���t�������+���+�m�V�t����.�{�]�P4#��_�T��
��S��/a�������	u}H.:3�:[���J2���SF7�A�����f�kd��B����Pji+���h*'$f��?�>�b������z{�<@��SK=������=�;�^	�`�������iK��E3-A�]m��3E/q���y�h��9%H�=�fz�R������Sjdi�����-�.������4����##L�f�3Fo����!w<���|�(z�9�t�$���p�Kp��\4�Z�����]���� [H�;]����N%,�%W4��7������Uf��EW}��~2�c:�E3��
����X!a�E'��$l����`��p:TIv�������f�B�zE7��U�����2cS��.������`U��pJ��T�x$?
pX�$���]1�GH�a��h���m�r1�.z��tSw80�q7�^;�������	�f�}�&:�E�B��J?�y�?�)A\��r*��o�����4�0\.�o��4U����FD�T�ix1mO��G�{3�I��EN��P4��$�E�CP4�h�g��Y=%�TX�q��M���R���c<�����J�q0�3�E��N�O
�I�5%�0�;a�
�-��
����<��W��� 7s�%��!�b�������atSl�������eCwI������;�U�Z���>����HLet���&��:M�sliU5N]��Y*<T�.��"����g��6���+0{p��?h��f!;xi=4{��$�q]%8�G�d���C����h�M�R:��CQ������D�s8u�Y($R��:>Q4C�2%|��5�:���}o�[��6�3�������Z���&y�)F����6YR�qe&at3rN���,<���cb��-�e(�V:�{I{�\4'��5�3���gh�o8]���H4�w������W����q�����5��g�����A����s��'xJQ9�-��f����r�?I��,� �q(���@�b����[e�����I6
$��DE��}���R���a|���S������F��t�5A��k�-]#��f��E�I=��,�P�K����7��7<�6������s��^E�atS�q�1�n��
`���K]���i��������aRB3c������(��p�@��;	��r(��{bJO�
NlYv���)��-�O[n7,j�������I��,���7,�|��!��st�^�ets���Sx!(@� �c0<��tI������#%�F�@CP4=s�����Nl~R(xk��?R�j`��5���!��MP49�d����(�x�U�c��}A&<��=%����;�n�\t#�'?~��h8�{O���'�KxC���(�r��$2U���h"F�$��t(�%V
�J���L�F����,mi�p2�.��F��0���`��'M�O�E'V��
�o����O6��C�u*�&_���7q�W���#vF������M���s��(��Y=z�O�X0���>m�����:�\0c�'��|��h��L�kq��\t��f"/~�����O��<E�\��������2;Wrd����Z�*FO]tb�iA��\4���l�3E��+IU��h:,�i������Qa�j/�)��5��������DXS�fE�SPtc���Vi�����:��O�D�cg�)�/��h��D�E��^=E���}��]������SZ���9�W!���vO��T�x��#����jCQ�T�n�����\�^]loR��>���bP�1X1��Pb����������������^L�@(��h�1l����)(:���-5~�EX��nP��<������e�(�X�$���.M9Y�*v0�Fw&m�
;0�84n�F@�t�E~su��,��7��#��Q4{�1��
�SPt%�b`P�E�g���V��w	"U�o�����x�/6q�a�D�l�D���)�'��D���{��h6���w����Eo+�������(07�c�u��X��K�a�V���x����p�_�$A�.zh��)(�-(����.�b�N�j].��L�N����y*
H6}J.��V���"
���xe�NA��-j�A#���;��kV�[P���U���9P4�U`5��at�qF��.�3���������&��GEt��hL����}������Mud�������7������pX�(�fWM�
-u��e~X�*:���F�8��]qX���1��v:����8ZW`DJ@��|;��L�����G�"aj]4or�7I�N����)
R�a��o�]J���/IP������vv(Q��)�s��a���(M�OSPt{8�DS���E�f<�]30���l�����lx�����\��mk��!��Q�������>��%���r,��E�#�(�r����]Jt�_/et?�-8��)���6�v���O=���R��>Q4�����+��h[���.A��E�p�t���3O��|�a��>��C���=�o�0��8��\t#%����1~7TF�vh�H��V6?�5�P49��mUY���f�pG�v
���C�lK���1T��gy�(�nU�������
9	���'�P3k�B;�e���?�NyJ��T*��6
�qx�E�#�����o�"�'�@�����Pt��*Ta�����
���8$J`���I�8�/KPt1���54{��v\Y�xKr�����2~��� ��O��Z����:�����n��;��#+3!�at�-�.����K�
���dZ{CR���h@�NFl��;�n��g&��������fKs��*��5�������R���TP����FqIo�P4��e����M�iG��Z��](�
�.����hJ�d6����;�F}���fI.�pk�09>���X��%�9�%(zd���[G�P��b��]��dCuTy��EO]��6	�����4�hF`d�����9��}O0��Pe��
�����M�\Q�F7�]�^�u<MbJ���������N�F��c�dh��V:~��&}/8V*8��f��V��|�hRI�tp��O�����KX�KP4��6����(��S� ��6���"N8�����=�s`��(�bJXJ3~���X�<;����Hho!�T*o���'�<50������e�Ew��',����SJ���j��w0�XK��]�!zY����^���-���F�"lI.z3poY;�.etfL\����84[,��4�\]�-��}
����l!Hzd`�P��N�d���Eg�e�����Q4{Z�H������M0����B�'����,*��E�/F?N���@��I�}tj[����s��'��v�n��E�wF�p�0bP4A�=��e
�d����h6���R���a�&aD��`tw6hT���(��6�����'k�'~�;�G]Os8���;a/��
�c��h�QIdd�=
�9��'������[Q�J��M����a����\����ip	�3�V�f�}/-}�������*�C]0�U��f�[Q4#r/��%�]]t&��W�#J�,�7&�Z�gt��a���-kE��l-z�/J�Q���E�"��O��jtoK�6��U]������������{��k��X�ZC�_^��Zu�]�#�k���Fof���'���n#������ZX�<��[�����I����Z(�����t�R��U[�t8�E��5),���.t�Y�&n��\��Y��=R�P�������q�Q�����h��V�������Z*�Pm�M&;��������CJ�kE��l�?Us����w�>����5i���������u��h/V ����5����w[��Y�������l||��
�Jg_^UkT�G���� �����}r)f�#�@����ek���P4�)��cGF&�@+0^��G% �"g�h������g]C[P4���'�Znat��9�4�-(:ik3���!#2���_��a�����19�b��Re�l������(i;M���w`d����l�"��[5��)1T�������z>��|�!��:*�E����[l���*��C�����=I�G�w�6g�-��?�v�n��O�P������<�B�-�b�)lp&Y�-�h�ajkA��(��:o��f�����<�[r�lF���(m�yg��}���.�n��/�xJ$�Q)D�C����^�$���n,�����/���Q��~��*�'������9���0�t1����%T�-(�����jm��n�E\mi�b�b�	�-��J������mrr��bh
�����+h��&y�FV������-m)�I�K�(��7/�G}6������Dcf�`�v��p2��z":��qe����_�����	��|�q]���Q�����������_��o��_������q\�����}�	��f��fq���/����v�	���4�o���g�������������������������?��v�{����8lYo��9�ad2[��l����Fx�-�p��Y�i��5�503N-������
�e�	'�:�^I�Gp�b���1)���"%^�(H���=�3��l���}���G#����������ws'���o30z'�[� ;F��M������PY.?)���'�U��(����_fnQ8<�=B3L{�z�$�j���:b��J��bm�A�8�cL�4P�X�'��a��"��%��,�����XV�Or�aD��M;z�M���,�6s`f��`xa.�0s�k2��N>3��Y�)[��z��i�����~������O������f��1�1.����h%02)�L}'�^�'7��m���}�4,�`R��k�Pj�d��T5s�!Y���SJ�bf�U�&bm�nh����O������n`UVK�c��n`;��! ����[tLjb�,0�W���k�=_�a�Y=�����M�����5'5s�P��z��g���v����%��iH�Q>�������
�O-f2b���O��I"���b\��dU�����j�,��p�adw����,?E���4��z7��~OT�1=��G|�(CT���C��f�XEOL����p"J*�k���Dg�8�>N��&��WTX)|�#��~��Ww`d�@�D�G�����L����&w1.�����1/5s�a�����������n�\��=M6�����
�6�J	�����:m6y���c\�i`�Y
�[b���gIC�T���g���M��������'�9={�L��=��)����(������M�i��'<�����b����r���Y�P��m\7w��T�J:��)�^������i}m�/�rE�A�e��=�����z�iD�o�^�.:[�JtD�j)��4������0����
sY���,�bhw3$lS���.��b�mGvd��2o��IvdV��S�R}
*c_�8������Y���tOdl�_��]$����VP�c\��2Eu��VG�7����3[~6��Y����+H�8DGa�8���-�N������y������@7Y05W� �*|��8����]��g�P�����=�?�xE%r�Kl�	���$�_*�7��dZC������X��c�L�t���JQzX���6K��H%|����C
���{=�����%�u'	�����N'�sH�����Mf�+T��}��){��M��KdB��jL�/��&���1W�)�'��d�/>0�z���OE=��2���qB���8;������z2Ib�1��G�K���"V+z/d���������ks�F�/���nxrMqYV�
 EG3�c��+Db{9v��7X���%il$n�3��z�#�#n�MS��p�������po��>��PY��#�����1���rn�C��'���7?����=���,mBRa���KS���'���f�"N]�N���,NNz�y��Y�D����K��XG���,v[���aY�w7�Z�������������c��?d:����'��5bKN@��7�b�Z�S��[�����+�l��� R���������3��* Y1|�[��N5�(�8��Rs�z,�l��t��,H|1 ����!�P0�����j����y.W�����������vWk��p|��15���,����Ix@�rT�����S��1�c=$'[����h]L���v��_<���N������a�66������V�f+�z8��R�i���K86�������BX�������P\���z�5���O������Y��'�Pt�hE�����	����n���K�a�#��H(�JB����!d��A�����C_�i���-;dP������sd�0��{.������_j_7;��*�
~�����bk����|}���li^�:!�|�V@��j�W��n�)�O�/�ce��8�8����Ucj�#��va�����x�NE���RE�:K
��Y�7E�:���h�0�a���Z�:��C���I����!��x.�d����H{^���X��o��a�+QRoT�'Q��]��[KV���G(��Y�^(,u��sB&;A.���?�_�8�_��_<����2{I��%RS�G��Rg���T�%]^����c�������(8���I/�����������cW<R7���0Ph��J�5�I��)>��e�G��R�
v�l�>�v�M����^���4�!�	/1���^�+.���D������c�'G�����f��$�@2���������H�z�v�A�v.t���`��gA��[i�a�3,H}Ok�;���E��)�5E�--�BZv�)M�C��D>��O(�HT�;����P��m����O6��,��c������B�8+uHv��A0�?��ov6!�VR1F)@E�����z��q9��U�0;����8$��|�Y#'��U����8���C9n��\��3���n�oR$K�(��H����EY�x�x���d���b��(�?)r-��+�?��R��i5H�E:!��3��^d~��[Rg.������l�������~"�G!|�+A�t������C��]��C����`8�������T�����!N4�5�2�"��20��"H�����e�s^|i�b��B�iEEg�H�<^iw�#�B��	9�� uJ<��9(ZER�����/-�;w�`9q�g��A��i��q}}��w��������"���Wg:��G>n/V�������5V ���,�Na��A�>�_uh�R�yQ����G�8���q�{�>I>h�W�����R�$��>6��L�Z�p��c^��������&�:%���dLq�tzYm��8wH��v4=P��&��M)H}S�����voi�����><U^��
O�XU��#�<��wx/��kG
�l�CX���.�V���lX��������1���6���b]�����%��P��z�^����������v����W��������>���z�z�WA�N����L�������foE���<R�����������C����xNy�"h��o�>t�U���M9;�jx�Jc�Z�&c��@�����/�����I� �NF|���z��:1��]�����+�1
������'�,����H�y�y����az��1�E�,���T8P%���O��i�.uk�N���Y���vR.G�A�^)[HV���"�E�u6T��E��p�S��f
��O�>(�������m=��:������x��|�i��.�i�Y&���R����/5j�����Is�%�|3�|�]��������V��a\U�G�}��	W���]�=�%�������w)E^�C�!�<�i�&��VA�|)Q����������O;�C�<1�{,|A���W{��R��So�w�/�l^��qY&fFw�"�6r���Q���:��������f����!�D��DEF�� �����������B��S�y����O�2��Y6r�Z~���=��FI�X���������joTo�(Z�i�s�����L���i�_bPP��%90,3��D�H�j��f����]����I�:��)�9VW�R�mQ�p�^� ��N���#�Tz;.�Wf�/����PWx2��.�N�4���80.� ���}{{
��������:\S�����w�jj���������U�:?��r����I��v�3w����_���--k>J:�'R���C�q;�}�z�t\��'z���,���g�����	�n
K�%Bi���J�*��	�9��XXKvHYK+� ���P��8V��L����q�;��>�p��Q���q�XC��A����5z�QsY�g*�'��z��~���t�*H�J�,~��DU�N]�5R���L95���Oj��^:� �<I�2�zs6�Sj]����>�:�
��m>�n+���r���d���G�X;r�,����a�bY8d�hp~���o�>���&H[}Q�Z]��9u�Wyu��Ms�������<RNB��o�D���O*�����L-�������:���kU����r���,<�aQ���_J*_�=)\F5�I�oRU���R[;r��}*��VM7�'AE�.�����}"�Iwb3��c��:���R��a��O��E���JVj�y������Mr�y?ez�7A�vl�����K������j���W�(����9u�r2,|��jN�6���I��w:�,5����UX�v �V/��Z���i�ye�������~�d���(�IN�U�l����&Hj��(��pB�	�Y���H}��������&9�doi��K,R�������H}����t�O+������:���GCw�Ev?���pv\~��!����H�4��'�t\a�b4���i���\�&V��)Rg�����A�s��^stu���P@5��r;��G�$�����i��Y��eZv5��'���N�G���E�����<R/k�9��
,H�x1m�����w.���:v� u2�	��:^�
��s����v�p:G�8�<R���~�+�o��
vatB���Lx�;���NyGv��s�>X]����!8������7���E���SA+��k��h����������;���e�����)�c����K}�"\���6��)�NI�$M����`}���	��
�3�
��"���U4���$}S���_"�7�G(�������S�E��>��<�zd���/�-GVF��F%=�M�:s���_HN�]�X~xc^}1�N����#k�B�{MKN� ���
����v u�V�)��	RO������������G���N�!���Z�H�%#���]�P��bO���~g������	��%��i��'I�k�#q����;�G�������~�0P;�����)�������N1�G	FwZ���`�����s���L�V/|��Cv�u��3��eX(Qw>�%���v��4d�5����e'%����zf(�6J?��k1�9���9u���FZ:���n7M9*��'R'��������/�+��������J������cY$_����H��SPP�Y�:���j����z���m�>��nT/���#u�
\�T^�\w9u
}N3zL�O��S��.�Q��=��BE/�.9u�vp�s9&�!u���96������i�<n�s��B����E�,�e�� _?����g�DW���;��A���Ayj�5�����	�y�K��S�i������
qq�kU�N��Z��t�}N}Q�+�(+����N���:�g�:��y�V����$U/��u����=h5 �=�����Z��p�q(�u�Sg&�Q�����:E�p"�v�!7�������SG����9u8Z���c9�:�Em��VS�N�=���?��[���,*��[	����Q��?�z{R��HY����:�d�� u������*�X�]��g��:f�
	�.H�4���/H��J2w�x���� d��zW����jB�b������<�$���)��KS3E���
�������!��������C��w��	��`}�ckN}��8�?bCS������O|v�7�3���'
S�pW�c:�g���u�����D�the����;�M�A�T1�����������a����+#7���������E��S���CIQ��"���%����}�v������9�����g
����nu�S�2#��T�������i�|�
�M���.������X-�Y��Y>�H�����S��m���~����N�H/�����Mf<�q���C�	c�K���C�g�j��G�|R�JZ��R6}�cE+RO��xpv�G��Oyd�j�}�{B'X��s%HN�n��S�Py?�:�

^�"�F�K� &�(�f����`g|"�M��%�Q�5a��{-2bT�S�����Kj��'��
�g~5������-8Z?C�:��B���
���-�V>ja��Sg��a- b��&ujD�KC����v)��������j�zd�e
���5��W���Osj�]C���c�V�%]��I�f�#��C�:�3��#.1�N�4�p�jr9u���-:����k��@_�����b�����,L.�QS`8\N�$�n������&V�l��;�\�g���v��/V���H�M��g:���3�vx�PH:���\��7�wF��������������m�v�)Mi8�^�=�a��
R'�=�4��3D�'*��hA��wW^G,k�x;yRMK��#u�3�6IS��q��/�-�T:!Z��p`������h~B2����k��z��b=���!���+0���=�N}���Y�G�}P���t�!�wr�2y��O�^�����!�wFk��^���~V�i���VU�=���I9:/�S��Cj������U�I~���Y���:�2�E������~���N+��Yh	*�GjBsh��sW�C�uhN��E�L
�e�����X	�s��w;?��{��O��E��$cFV�9�^���H�pH�r�/V���9TQn0,b�Sg�x�S�E�sF^��n�J�1!$ku���z�m����~��ks���8��$����H�~m�}4�)��(C%�'R�w&y�gg��+�&,�!�n������c
7���!u������Ml��3t2����:pM���b'�����q�n.�����P�����g�6=�V����?������g������3;������s�8�%�F�(f�x\
��;w���q�J�z�`����l����(�[>G�
��c�;�NI�6���T�,:�w��-v�r������c�t,T��{}�"�9��u�����p��CQ�v�-��)�����%s�jU�[�M���-����S������6�N���������Y��y������l}�E�)�w����#3}N���X1M����:US0q� $NA�O� x�
��h�S6��2grj����bK�����)�����N�S�v���B���[g��!j8��C��V������Y�V�����t>�Wt���G_�p�����M��i�t
�=�@��K���<�z�PRe������v�M��e������Q��<R��yQ<�h��r��1R���0��^L/���s��=�X��.�E���)m��S�z�G��)�
��6a}�S�:�}R���E���q�uH$O�S'��t���[�)v�1m���������/;���Gd��6��:��S��U��4�8U�=m�z�VwlJN�g��.�a�#�����y�o�	�d�v��������ua���:�o�o,�M#H�]���.������Ev�K}�2j�-����n`����^L��"�S�z��X�+�^�<��u�<��99������Lj��t�r����"�����{K��1�S2�":���n�8/��d�*_���<�:��SSl����&:�������;Gq�T���I��/�2�u���>��C��H}N��H`L��>��^/�C�,&uf9��!G{S�n?�6��)`�A��PS��(G);z��
�C�<�po���~/����y��wS_�b�X�:���i4c8����v�R���9�B�����g� u�h��c�z���c��
q���YBm�c�iN���
����M�:�#���4�?�{"�$���rjN=7lO��RK�(�Hr 
D?�!u6<�����Q�#7o�C�qJN��2��C0u
Rg�&%�}4=R����k9�A�&!
�x�A��D����Y�y�����s���T�>qyP�<N�C��.5��#��S�Z�"QX�C�����>�}�� �!t�	R�l	��d�)��I�<���y��(��z�#�1=R�;;�!��z�i.f&�����@��zB���x}"���)�A��v�c�s�3��C��S���t��Kr��jT�����~�d�W&u;?!���~��.A��|�z9h,K�:���JG	�:���G�����������+���9I����#+S�[T�%DVO>���D	pK���#&<K���(�5������V�;=�2�A�H�*V.�t�
����W;J�������R��C�������������������K�iuz�2-_����2�������4�v����)�F������.��cq]��S�8=p��
o	Ro�1�6�:�� W�9�~��;.��@o9����ZN���r�����;z�-�~��QN�d)���'��x�{�T8_��v��V��c�R���w��%9����Z�Us�K�:W�+�q�_.Q��l����q[�):F?+�'R���b���>�����R�K�:c�������w����=:����5��X��gj�G���H���p��Ks��=N5��x�Sb�r*�z,�~g���z�:u��^����������:!Z��+����{Z������,y���G��h}�6����[&�<T5�"���!��4��N�������Q������w�rH�T�e�C�o9���V��jd��eujy���V�;�a�G�w��:i���q��.���v�e�}L����7P�ki~`)��tq��Z�SOs�.\���R�wV������+�g�������'Ue���iy�>�\y=|A�$R\3��#u<����(_|��;��\N�C�z�S���<R����y��"u`�	����K�:�8�����:���:�.m���5w��	����Q���/F��</BA�B2�uYG�:����vs��7[����:�����]��u����F��:���*{d@��!uk���v3����8����K�]��=Z�:#���,Q���\����q>���x?���NU:�{�����I�vT-�S��+{���"�<�0������z��5��YY�O����h'�ea������-9�2����Y[����:�5���w��h���e�^l��-AE�o2��6��S��Yn�K�!�������.����oV��R���u4�����Ey��[s�8�6��Rdg2�7�H�x��.m���{�����z^�c�.�&d���Z_=�]���w
���s+ULt�SK�!��?�� y��j�h��Z���s�=R��l���G���.�����Sn��'M{nA��}k��{/����5�����G��T�~�Na��hi;�n�8S�;���y�����a�:u��+��l���d�O�1���.m0c'�cR�8Q)������z�r]\�:z��3�����V����ei����|"��B:����?��|2��*m�~'m�e��Q�;;,3��?�#u zJ�c#��u2�*&�����C����8����b
������:�Sl����'������m�r��rbw�'z�wk,I����bYL�8�S��[���8uS�G����>OJ�����~3�(H}���C�n��F���5��5���d��sB�'������S/,���^�H�0�0V>�/���g2b9<��$����M��-H�P
��u����21�|8���{c��������&��"+�kH������Ps���K��C�n��:��6�AX��N�?a�q��+���r���������0���E0\d{���nBXx	0��"H�:#t�N2[������+�w�6�,�9��:|mR^�y���:ebW9��)�1���Z���s��A<:�q�R/Fya�:�D*)��5o�����;���q���r��_MQ���:K������#����|���7Q���^,ST�?��N�=g�A����^�T���lB*�\j=P��H�E�����['�]NU�-9u����w�RA�T
��/�,��������DvS�8���Fyj!�zF9y�{z4o������Y���r0�?��,�k�*C{�'A�8��&U�3�o3#X��*
}"�G�������b��Df�W�|��3err����O��ac�����s���;�@��������������������k��c��\^������AQ����+���*�R�-�N���{��=d��O���������������������_�������C�>���~wtj�|�����L�m����������Lm�����Xe�VU�C��x���_��,��TN���46�Cp��w��f����T����C�{l*�N��Ns��Xl
����h�M����|mjl�nU6J�US?tF�7�_������[.<5~�#
^PU{
�4���2Vz1,�����v���"~|Zs
��@+[����)$5{�g-�}�;�]���\Ws_C�m�~�����a��)M[M
�����J�W��������~xQ�'�����#|d\�|��BJ�-v~
��s
Ga���8��!�O�Yl���ws
{�6x�Vz^�����,J�u������7����H?���wZ������bq�s���%6l��,�8�i�RJ�,2(��pS����R[M�}���p�Wc?�1���B�����:��&��E���c�SHb��@���-Y�v_G��SLQ3�y�����-����2�D+�K��������<����]ozJll�C�2
���<H'b;�i.�]�x ��;����z�
c���a3"�T��:�l k.���S�����?����]Hi�2���~����I����nY_��+���M��Oc�B�n����rZsZ �����.,V��k���?��-�S���q�d>m��P�������^:j�������Q�:���Suj�d������?��A:��YeAOc�����=�9��J�v@8�~
k���k���<R6&#/3�?C��u�D����:�Q]����6}TP)���������:Tb��a�u�z�<��/�B�,�k��}c�)��w����(/�Bj���uz]�K���(�?��F�����r?:���=)�����'�j"����x_.����b�����(�$8}Q��)\�:4h��OcG�s� q
>�S3X�<��:�>.:6�4&�]��� ��3����U.�&u&��R�?`��=��t�z����B��xU��a�4�f�4��H�Q����L>���d	�R@������v{��'��o��<���*F����n�u�����n�o1ta%����;{�� N��~���6�e���H
E2(S����G�����luB����E���=^$�\(�wM���v���s��U�l���������W��k������[�l�d	�����p�r����zs.\
�=�����L=D�����pT���Dm77�m��'RouY�U%�;7��gQq��5w&�H�:Y�i\�
3`c9�}2�C�U��ASr���]v0�}���.x�3�xI�>����9��$'�k[CX�qS����o����)����:�(���uO����nw��%�3��g%�������������a� ���Ff^����Q��
C��~�f��R�}���}�>�E�R/���U���,�Y�����
HC������D���Yc9�����/ay���S9k�������u.T���-T�wS�I/��[X�I����;����!���}Ft���x;��tJe��r�����%��C��OMT�HmwpJT'5�z�J{�Xe�������W�����wF_.�,k��{��Ev&�WNP����)���}:M���1�����>�,�r}��Fw�8�tue�����ly@��,
L�_��d�xZe{������IN�U}�-�L�,��m��7[,��x�wA�����x���{�I�[�N�O��=\1���q�Fbj#����x&�XatSb�/k7��2%�"����LS�KE�/�������F�O�j�nj��t�7]���Z��l���������/�xk�]�Y�A����dE� }+]Q�-H��|m�L&=B�_�?��L�v�<e	�0����G�B�Z��sp��e��m�|���'�q��,Nz�J����vn�pT�����,�lut_T>��L����|������c�#4���Y7H���#�~2Y��t�h8�d.V�p��o���c����#G���w89���8,�AR�o���LU��
������za/�{��k�R��
�x�o�����)��]Z��/>�'{��w�lM�&��ZXs1J�������Y�z�L�R}�~E���,P�+czv��S�&�s,\h��P)������.�����?Z�:��1�Ye��'�W�����>��G�������=�Tk�3�d��Zb)c�#�� ��,e�������6��a�k��Je���m
g��e�A�������?�h��x�AU����w
���rQ�� ����B���;s�|�q���.b�*�)�-O�+=����Xtg.�f�o���.47��{8�T?���U����w�a{���
w�����'�3��KE"@l�nP�j������QF�>�3@���00}�g�,�����f�����]u.�O��0��vp���w&Y 9��M�1y�!����+^y���r��,��ag#vBNp��]ZT6
�=!kR�2k���5'����C(M�L��.*py��7�n�����}o6<�D}�������"��t����j����L���lc��Pa�
{���x��2�}2�7��)L�{�#�+�����f�_������ VA��l���D��|�Q�!�|O�1�C����7�;������+���w��H�����D��~y���uD-Y�����U��������3�dv��r���q���{��lN��op�f���=�S�B�T(��A����zF���x�\qC|���D�_��m-��;�b�x����3�X���5�;k�f%��?�D��;�A-l�M.�x�wRN�PbY��z����Vc��[[Lf���������.	.������OePlV�;�hb���BE��E���w��5N�
3��G���~�,RO{�3��S���-�&�l���8{���=���)��>#@@^�di��ak;�*�ly���*"��He�������
��-w&+�M9�;k;f|������� x�@2�S�T_9"@#��eG��D�I�d�$��"@�!��}g�;�fi
��{���{n��t�o����TV����k��r�����dK�:�b��_�sz���dg���T���-�m����w�b�/���� bT�?f�����7[?#@�!�#p�����~*e��� �J���QE�xb2'N�`
��������G��87kPgV}hJ�S��~V�Q��z.�5��(�D�o-�N|��l�R�����8@���c�L�a���Tt8Z����
�rj��}X?w����)��W�-B���e�������	�����4�j� R��I'T�����p��{�^�RhS��Z�~m�;���6���q�>�X�8r����j3%6 ��k��~v��w�f�G�(�D]�����
�\��T%d����{O�U�Q�b�*�~��L��p��:��t2L|_X�9@�������]��=����Nug_�o>���O
M*�D�v��d7.�RpJ�������D�:I)l�w`���+S��o��F�k�{����`e�\;�\���u��k��A������D�{'�y}m��f���.*�������*�mX��) v���	�t�"$4���P�=EP��L�Dq��{,�j��I�@��u�1A�6�o���������_�> <�C4�b��q�{��J�9���}�����l��C�Y�7K9�
D\�C�Y���S�Hhh��r�Q�R�P��U�p����8@a_�`\\�X����7�������nP�h*��mH�����>r98zD�j6�e��Vk#t�f�@*~{17�,;�n\��H="@��T<D�
������E�����|F�X�B���H� ���q[UU�f�V��w�D�6�v��O��}Q��b6�g����Y�3p�%��bT���|="@<U����@�}T��u2�f���������Q-:��N5CK��{g_T�e�������Mfc�$-xW��8h�qfI��&��O�Qi���b� n��:Q-���y����?TK�Xv���E��F�-���}F�V���++P&p�N�p������#�����M8@����}�6�����������Y�����&����y�u�N�r�Zf�2�S�|`j��j��5�P����(���<��[����x�E�
����B���O>�+�G;�����l�Xl�{4�G�z�<C���I�?����~�
��+��Z��5�������q?����g�p�
o>�����3/���P_���w������f�`k��|	����&��s���]*.�vg(�����)�	x8o5��6��AH����S��Q0�����wU`�=TX?t�^���:
x���D��4��{-U�nZ��l�v_(^��������~�L
9Xc���MCd������ �5/]�_�IuK����������~�����qU`lC�?��W���-������	�32a�I|�p�r��w�P%<��~gmw&�����D����o3��~��F���T�7����?�ErU`i�%u�;�u��8N�`�;�(^T����(�P�j�����c�l����^8@kT6Shwo�I�=$�[gn�Y�N�d�;��Q�|�x�w��Q6�
&�E�2��#�������	!�|s� �cFJ��@������`�2���g�;��0j��D�X��z�q�qi���:�����yp��i$����������T�3D����y�Q��}�}�Q����o�2����w���4kK3�,U�U`,%���Ot���	���.1�D�����i����Xl�)-���#/������������.��e�;���������?��,Z@�hb	�ZPp�D��Uwm�g�P"@�+�����U`&�QqI}���j���~d4�2���o��n����J&�z����xC��32�3�n��Iy����U`�.����^8@��^{�l���R��=�S-q�I�.A�Q��`��Pn������X����1K%������L��y�A��F�(hKvG����8@������e�"�O��������}H�D�x�������:@�����h]9@DI����H�Po���eu���Q�.l����Y����\������"@�!oJ�]������y���{�����g�r�x���=�a���
�� }�%��<��I
���5<�@���n�|Zuk����X���`m�����^n|�����,�P�b��"@�A�9��lw���{� �%���;������M���.�9r�����V�eV�P��[��i�����{
�U`�G����a?����b�0�/E_6��df����c���u���<3��t���%�]����b�l>J@:����)v��.��)���6����L��fz��5��/�t����r�u�I�s��%<{[�����5 0��������d��:��z�.��M�1�Eu�Q�P4��Y�XF	�k�G�z�/$�M�!_�-kBgl/�M�`+�k?����������������U�I�{X�; �S1wt����d]�7�@�AY�T�w�JL���"��A�5�p��u*����D���O���h+�X�����d��sf���F�r�� L[cR{�k���l/����s�c�d
{�7�
��	�{�E�XoWY���u�u.+�1�w��T��2X�%d���hT�U�=+^�|�9v���+�������6�E����u�����zrv������{T��T-qZ�����T�X=H;u���d����zZ/�H�S�]9@����s�������=}�U��RaaR@+�>�;�7X���Zl�q_�.Dr��q�`KN��A#�.:@��h��R�2x��r�v��a^f��3$J7��{����!�<MMP������p��E����1D���d�*��XR�����]�����r��,�m����s����k8� n(�p��r�#���`]�Pf�iR��hO!h��^�o��@;p=�������y$���E��%�q�\w��U`X&�9��C8@���3�^	�H.�������xpe����m2%c�{s��8~aH���Z��z�R�8��~2��a�A���vf�Re�^����3uj�-h�Pk�����#4N�������#�;#�-��3��d�+�����J���c�;,�l���Q��[�p^%��4���$�)�W����t���F����p ��J]��mm2����7�0
X����d�PZ�;3�~3|��[����0�VX{Hh���TS�#�P���{hb�����k�WV�	�$���e�UG �>���<��;������v���D�I$����rgR��.�}�(��u���}�9@�4�H�]�cU`��/$GE�"�,<{���?�W�Q�����^	:�!S�3}�������G�7��7�~"@L��D���Z�L�A>w�h��PF���J�F5�t�5k������P |�L@z��������&+�������V����#���^�s�3qC�{�D�*��h/�wG����]��sW�D��e���v�gX�����Q�J�@H���AA�p�d�	�w|F�����==����n�c�#@��H���>��T(�*��� ,�k������������*��b[ �}��C#@I��Ny�����������"@V?2{��7�T��MwO�
b����w���PoP����;h��N"E�(AS��0	z_��`TMQ�� �	��,�Q}�-�,��^�yH�w�!��������	��}�:�~����D�:3�l���G<A�:^9�ug�
U��BW�A���"@p���O��Qt`��R%h�b��{��P%h�is�@�lh��o�l�����(lr@��>A�����9c���p4�J�sH�����������\)���B�I�{���;�'���6r����r�������x�88@��5�k24���
��8�^��p��o�.��#�rq_����jZ=��{*�>u�m���A)���������e��&S"@��!��b�S"@p
'�J��Q9@���{��y��P2G�y�##J��dU�U��G�z������S�8f�+pJ�����G ����Xf���9��>�7��*0~�)���):@��.�3���G(��Q�=�65O	������1�����cv~F����_�N���
�=�yE. �Fv�;����}RU�*t���9�g7�,��� X�f�S{�=t;p���u
���M�Q�����|�A.P������N	��Y��|�T�W�Y�j�|���<k���A�):@��)�>?=&�aS@���tn/���+����Q��L�a^*y��" Yl�V�j��{�aqc�����x+l/,:@`��X�+U`B�,��,U`T�h@&����<��!������7K�p2(�q���I��R�~�@���=�N��Pn�vX�L�v^���}�9 ��~g��A�@.����D���1�HTlJ�56c�&����wf�7[�]�tJ�M��*�8���������?;�S4�����9���<���)A3hP&n���q&�}��1=���V�0M��'���
N������U`X��5�gM�V��e�'-�+>�b����,kg+�o����7��b������9(:�w�L�j���|O�)A����n��& ����-XS.�M\���J"@t�=�4��R}�x�'��p���d����|�Q������/I���rG��Y�s��a��,�~_$>��N��- ��5Y�1�#@����$�p�:�9��Su�:Fd��Y�c#n8�A��yT�������>%�N� ����{ 8�����t��Ja�� h�"@�Y���v�D���������#��=���&���eK���TgJ�[m�q����mNf����F�29���yS"@�2�+h8�|����=��\/���R8n��d�*���m���������E�V���'�����dR������% ��C��=~�4�i������e;'�h���w�����A$m}F��uZ`��BY.������.��#@$�J�K9@d��hC��
�,�
�S�#@�$J��[�'kR�k�{m������d:@��t\��x��P�V�E���E������y��.��,��5��Wq����h��#��LM�����eF/n��[�T	��|e���;�o
��7�D�L4��w��:8@�ZRa��]Z�9������]X��9[��[�M&~&[\k�E�2��n����������)�%�����'S"@8:�����{I��{�W�V��K���7����
�H��j���[`6��O��V�z %��l���b�A����2��Y��Y-�����>��*���R@�_�J�����`��m��;S8@�B��2���<"@���L�V��ai��?�~g.��h��U�VY�t{Y^	���j|X"4aE�}�}�[���`U	hX��-m���:�t���#�����{uT�����-���F�3�&�q�*�Zm�����4�t����"@�N������*���Dn�7�~�FV�g�	t�+A���<E�$�D�
�C(���Z�Z���{J�X��Q/w���M�����;%����������`�Je��w�n�8�z��B���p����&p�q���M`-�<�����������*����K"@�:y����$�r;z+��ZVL����~���w�����|F���`}M��"@��~������D���k��.Q�fLgR"�wgv�R��]��Q�-��N�^�MU,��
���
���D��}�U�IN�TC/����>�q���(P��5�z�Yq���Z-S�7���TM2�������MMjR��~�3S��6���P`�b��rgR.c���/�������H��Y{��Mq}���U�������
�r���@VlK���Z������{���G��t�'_���["@�2}Q���
�*A�TbN�k��[l2�uZ["@��������d:������G�r0�.T�b�B����^��}�y����m��;iK7�AC��[{�m�D�wu��o���m�m��<"@$������b=��$����hQiA��������4��8@������}2�X"�mG{��1{���Mg������;��G���������,�'� 5��o�d�����z���*�L���������8���;��G�p3����[�����7�dM8����Y�]�dv�a���=�����t��@fk<&xW+�>��*��p^tv���pbML��_��f�I��{z�������"@���?�>�.��^R�3�F��Lt��E�(���]����"@�sk��p��d���x([����P����
��	����["@��A������z��3C����^`�_�gn��V��m��1~+Ac�c~�G�� �3P��I��3��}���7B��$����tk�GX&��G<�-�lZ���_��8@�$%��������E�6�1����Yv����-/�i����	��U&� ����,������`�q`�~W��Z]b9g�s����r ����L���;^���z��R�����V�;P��R�^S;�~qK7x`����-�*0�����^���<��q�}���3Y}�T�R6����Y����j����/_9@�Mjp���?pU`�^J��x_�6�>%�~������<F ��%4L~ym���.�����G�2,Y��t�F��^~������"oS#@�/�����r��u���A��q�����(��34X?��k_�Z��x��
n*DS�^G�=hru[_��xk7x
�bE��q�$�$]�[s��� ���.{k+�!�H�m��d���8T]����@�w��a�[3S����;c�����D�9?���lYX�0�>��2%�|?Sh��g*��7�^���&
�Ec+�p�%O�c�����s�Y����?�����"����������������������������������������������
i5-count.tgzapplication/x-compressed-tar; name=i5-count.tgzDownload
i5-pgbench.tgzapplication/x-compressed-tar; name=i5-pgbench.tgzDownload
#56Aleksander Alekseev
aleksander@timescale.com
In reply to: Tomas Vondra (#55)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

Hi,

I took a closer look at this patch over the last couple days, and I did
a bunch of benchmarks to see how expensive the accounting is. The good
news is that I haven't observed any overhead - I did two simple tests,
that I think would be particularly sensitive to this:

[...]

Just wanted to let you know that v20231226 doesn't apply. The patch
needs love from somebody interested in it.

Best regards,
Aleksander Alekseev (wearing a co-CFM hat)

#57Anton A. Melnikov
a.melnikov@postgrespro.ru
In reply to: Aleksander Alekseev (#56)
3 attachment(s)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On 12.03.2024 16:30, Aleksander Alekseev wrote:

Just wanted to let you know that v20231226 doesn't apply. The patch
needs love from somebody interested in it.

Thanks for pointing to this!
Here is a version updated for the current master.

With the best regards,

--
Anton A. Melnikov
Postgres Professional: http://www.postgrespro.com
The Russian Postgres Company

Attachments:

v20140313-0001-Add-tracking-of-backend-memory-allocated.patchtext/x-patch; charset=UTF-8; name=v20140313-0001-Add-tracking-of-backend-memory-allocated.patchDownload
From e31012217fb63f57fe16d7232fec27bb6cd45597 Mon Sep 17 00:00:00 2001
From: Tomas Vondra <tomas@2ndquadrant.com>
Date: Tue, 26 Dec 2023 17:54:40 +0100
Subject: [PATCH 1/3] Add tracking of backend memory allocated

Add tracking of backend memory allocated in total and by allocation
type (aset, dsm, generation, slab) by process.

allocated_bytes tracks the current bytes of memory allocated to the
backend process. aset_allocated_bytes, dsm_allocated_bytes,
generation_allocated_bytes and slab_allocated_bytes track the
allocation by type for the backend process. They are updated for the
process as memory is malloc'd/freed.  Memory allocated to items on
the freelist is included.  Dynamic shared memory allocations are
included only in the value displayed for the backend that created
them, they are not included in the value for backends that are
attached to them to avoid double counting. DSM allocations that are
not destroyed by the creating process prior to it's exit are
considered long lived and are tracked in a global counter
global_dsm_allocated_bytes. We limit the floor of allocation
counters to zero. Created views pg_stat_global_memory_allocation and
pg_stat_memory_allocation for access to these trackers.
---
 doc/src/sgml/monitoring.sgml                | 246 ++++++++++++++++++++
 src/backend/catalog/system_views.sql        |  34 +++
 src/backend/storage/ipc/dsm.c               |  11 +-
 src/backend/storage/ipc/dsm_impl.c          |  78 +++++++
 src/backend/storage/lmgr/proc.c             |   1 +
 src/backend/utils/activity/backend_status.c | 114 +++++++++
 src/backend/utils/adt/pgstatfuncs.c         |  84 +++++++
 src/backend/utils/init/miscinit.c           |   3 +
 src/backend/utils/mmgr/aset.c               |  17 ++
 src/backend/utils/mmgr/generation.c         |  14 ++
 src/backend/utils/mmgr/slab.c               |  22 ++
 src/include/catalog/pg_proc.dat             |  17 ++
 src/include/storage/proc.h                  |   2 +
 src/include/utils/backend_status.h          | 144 +++++++++++-
 src/test/regress/expected/rules.out         |  27 +++
 src/test/regress/expected/stats.out         |  36 +++
 src/test/regress/sql/stats.sql              |  20 ++
 17 files changed, 868 insertions(+), 2 deletions(-)

diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 8aca08140e..5f827fe0b0 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -4598,6 +4598,252 @@ description | Waiting for a newly initialized WAL file to reach durable storage
 
  </sect2>
 
+ <sect2 id="monitoring-pg-stat-memory-allocation-view">
+  <title><structname>pg_stat_memory_allocation</structname></title>
+
+  <indexterm>
+   <primary>pg_stat_memory_allocation</primary>
+  </indexterm>
+
+  <para>
+   The <structname>pg_stat_memory_allocation</structname> view will have one
+   row per server process, showing information related to the current memory
+   allocation of that process in total and by allocator type. Due to the
+   dynamic nature of memory allocations the allocated bytes values may not be
+   exact but should be sufficient for the intended purposes. Dynamic shared
+   memory allocations are included only in the value displayed for the backend
+   that created them, they are not included in the value for backends that are
+   attached to them to avoid double counting.  Use
+   <function>pg_size_pretty</function> described in
+   <xref linkend="functions-admin-dbsize"/> to make these values more easily
+   readable.
+  </para>
+
+  <table id="pg-stat-memory-allocation-view" xreflabel="pg_stat_memory_allocation">
+   <title><structname>pg_stat_memory_allocation</structname> View</title>
+   <tgroup cols="1">
+    <thead>
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       Column Type
+      </para>
+      <para>
+       Description
+      </para></entry>
+     </row>
+    </thead>
+
+    <tbody>
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>datid</structfield> <type>oid</type>
+      </para>
+      <para>
+       OID of the database this backend is connected to
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>pid</structfield> <type>integer</type>
+      </para>
+      <para>
+       Process ID of this backend
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>allocated_bytes</structfield> <type>bigint</type>
+      </para>
+     <para>
+      Memory currently allocated to this backend in bytes. This is the balance
+      of bytes allocated and freed by this backend. Dynamic shared memory
+      allocations are included only in the value displayed for the backend that
+      created them, they are not included in the value for backends that are
+      attached to them to avoid double counting.
+     </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>aset_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Memory currently allocated to this backend in bytes via the allocation
+       set allocator.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>dsm_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Memory currently allocated to this backend in bytes via the dynamic
+       shared memory allocator. Upon process exit, dsm allocations that have
+       not been freed are considered long lived and added to
+       <structfield>global_dsm_allocated_bytes</structfield> found in the
+       <link linkend="monitoring-pg-stat-global-memory-allocation-view">
+       <structname>pg_stat_global_memory_allocation</structname></link> view.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>generation_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Memory currently allocated to this backend in bytes via the generation
+       allocator.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>slab_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Memory currently allocated to this backend in bytes via the slab
+       allocator.
+      </para></entry>
+     </row>
+
+    </tbody>
+   </tgroup>
+  </table>
+
+ </sect2>
+
+ <sect2 id="monitoring-pg-stat-global-memory-allocation-view">
+  <title><structname>pg_stat_global_memory_allocation</structname></title>
+
+  <indexterm>
+   <primary>pg_stat_global-memory_allocation</primary>
+  </indexterm>
+
+  <para>
+   The <structname>pg_stat_global_memory_allocation</structname> view will
+   have one row showing information related to current shared memory
+   allocations. Due to the dynamic nature of memory allocations the allocated
+   bytes values may not be exact but should be sufficient for the intended
+   purposes. Use <function>pg_size_pretty</function> described in
+   <xref linkend="functions-admin-dbsize"/> to make the byte populated values
+   more easily readable.
+  </para>
+
+  <table id="pg-stat-global-memory-allocation-view" xreflabel="pg_stat_global_memory_allocation">
+   <title><structname>pg_stat_global_memory_allocation</structname> View</title>
+   <tgroup cols="1">
+    <thead>
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       Column Type
+      </para>
+      <para>
+       Description
+      </para></entry>
+     </row>
+    </thead>
+
+    <tbody>
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>datid</structfield> <type>oid</type>
+      </para>
+      <para>
+       OID of the database this backend is connected to
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>shared_memory_size_mb</structfield> <type>integer</type>
+      </para>
+      <para>
+       Reports the size of the main shared memory area, rounded up to the
+       nearest megabyte. See <xref linkend="guc-shared-memory-size"/>.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>shared_memory_size_in_huge_pages</structfield> <type>bigint</type>
+      </para>
+     <para>
+      Reports the number of huge pages that are needed for the main shared
+      memory area based on the specified huge_page_size. If huge pages are not
+      supported, this will be -1. See
+      <xref linkend="guc-shared-memory-size-in-huge-pages"/>.
+     </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>global_dsm_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Long lived dynamically allocated memory currently allocated to the
+       database. Upon process exit, dsm allocations that have not been freed
+       are considered long lived and added to
+       <structfield>global_dsm_allocated_bytes</structfield>.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>total_aset_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Sum total of <structfield>aset_allocated_bytes</structfield> for all
+       backend processes from
+       <link linkend="monitoring-pg-stat-memory-allocation-view">
+       <structname>pg_stat_memory_allocation</structname></link> view.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>total_dsm_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Sum total of <structfield>dsm_allocated_bytes</structfield> for all
+       backend processes from
+       <link linkend="monitoring-pg-stat-memory-allocation-view">
+       <structname>pg_stat_memory_allocation</structname></link> view.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>total_generation_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Sum total of <structfield>generation_allocated_bytes</structfield> for
+       all backend processes from
+       <link linkend="monitoring-pg-stat-memory-allocation-view">
+       <structname>pg_stat_memory_allocation</structname></link> view.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>total_slab_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Sum total of <structfield>slab_allocated_bytes</structfield> for all
+       backend processes from
+       <link linkend="monitoring-pg-stat-memory-allocation-view">
+       <structname>pg_stat_memory_allocation</structname></link> view.
+      </para></entry>
+     </row>
+
+    </tbody>
+   </tgroup>
+  </table>
+
+ </sect2>
+
  <sect2 id="monitoring-stats-functions">
   <title>Statistics Functions</title>
 
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 04227a72d1..61ff4a59b6 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -1375,3 +1375,37 @@ CREATE VIEW pg_stat_subscription_stats AS
 
 CREATE VIEW pg_wait_events AS
     SELECT * FROM pg_get_wait_events();
+
+CREATE VIEW pg_stat_memory_allocation AS
+    SELECT
+        S.datid AS datid,
+        S.pid,
+        S.allocated_bytes,
+        S.aset_allocated_bytes,
+        S.dsm_allocated_bytes,
+        S.generation_allocated_bytes,
+        S.slab_allocated_bytes
+    FROM pg_stat_get_memory_allocation(NULL) AS S
+        LEFT JOIN pg_database AS D ON (S.datid = D.oid);
+
+CREATE VIEW pg_stat_global_memory_allocation AS
+WITH sums AS (
+    SELECT
+        SUM(aset_allocated_bytes) AS total_aset_allocated_bytes,
+        SUM(dsm_allocated_bytes) AS total_dsm_allocated_bytes,
+        SUM(generation_allocated_bytes) AS total_generation_allocated_bytes,
+        SUM(slab_allocated_bytes) AS total_slab_allocated_bytes
+    FROM
+        pg_stat_memory_allocation
+)
+SELECT
+        S.datid AS datid,
+        current_setting('shared_memory_size', true) as shared_memory_size,
+        (current_setting('shared_memory_size_in_huge_pages', true))::integer as shared_memory_size_in_huge_pages,
+        S.global_dsm_allocated_bytes,
+        sums.total_aset_allocated_bytes,
+        sums.total_dsm_allocated_bytes,
+        sums.total_generation_allocated_bytes,
+        sums.total_slab_allocated_bytes
+    FROM sums, pg_stat_get_global_memory_allocation() AS S
+        LEFT JOIN pg_database AS D ON (S.datid = D.oid);
diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c
index c2e33a7e43..b950640643 100644
--- a/src/backend/storage/ipc/dsm.c
+++ b/src/backend/storage/ipc/dsm.c
@@ -802,6 +802,15 @@ dsm_detach_all(void)
 void
 dsm_detach(dsm_segment *seg)
 {
+	/*
+	 * Retain mapped_size to pass into destroy call in cases where the detach
+	 * is the last reference. mapped_size is zeroed as part of the detach
+	 * process, but is needed later in these cases for dsm_allocated_bytes
+	 * accounting.
+	 */
+	Size		local_seg_mapped_size = seg->mapped_size;
+	Size	   *ptr_local_seg_mapped_size = &local_seg_mapped_size;
+
 	/*
 	 * Invoke registered callbacks.  Just in case one of those callbacks
 	 * throws a further error that brings us back here, pop the callback
@@ -882,7 +891,7 @@ dsm_detach(dsm_segment *seg)
 			 */
 			if (is_main_region_dsm_handle(seg->handle) ||
 				dsm_impl_op(DSM_OP_DESTROY, seg->handle, 0, &seg->impl_private,
-							&seg->mapped_address, &seg->mapped_size, WARNING))
+							&seg->mapped_address, ptr_local_seg_mapped_size, WARNING))
 			{
 				LWLockAcquire(DynamicSharedMemoryControlLock, LW_EXCLUSIVE);
 				if (is_main_region_dsm_handle(seg->handle))
diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c
index 8dd669e0ce..af67e55bdf 100644
--- a/src/backend/storage/ipc/dsm_impl.c
+++ b/src/backend/storage/ipc/dsm_impl.c
@@ -66,6 +66,7 @@
 #include "postmaster/postmaster.h"
 #include "storage/dsm_impl.h"
 #include "storage/fd.h"
+#include "utils/backend_status.h"
 #include "utils/guc.h"
 #include "utils/memutils.h"
 
@@ -232,6 +233,14 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_allocated_bytes_decrease(*mapped_size, PG_ALLOC_DSM);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && shm_unlink(name) != 0)
@@ -332,6 +341,33 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+	{
+		/*
+		 * Posix creation calls dsm_impl_posix_resize implying that resizing
+		 * occurs or may be added in the future. As implemented
+		 * dsm_impl_posix_resize utilizes fallocate or truncate, passing the
+		 * whole new size as input, growing the allocation as needed (only
+		 * truncate supports shrinking). We update by replacing the old
+		 * allocation with the new.
+		 */
+#if defined(HAVE_POSIX_FALLOCATE) && defined(__linux__)
+		/*
+		 * posix_fallocate does not shrink allocations, adjust only on
+		 * allocation increase.
+		 */
+		if (request_size > *mapped_size)
+			pgstat_report_allocated_bytes_increase(request_size - *mapped_size, PG_ALLOC_DSM);
+#else
+		pgstat_report_allocated_bytes_decrease(*mapped_size, PG_ALLOC_DSM);
+		pgstat_report_allocated_bytes_increase(request_size, PG_ALLOC_DSM);
+#endif
+	}
 	*mapped_address = address;
 	*mapped_size = request_size;
 	close(fd);
@@ -538,6 +574,14 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_allocated_bytes_decrease(*mapped_size, PG_ALLOC_DSM);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && shmctl(ident, IPC_RMID, NULL) < 0)
@@ -585,6 +629,13 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_allocated_bytes_increase(request_size, PG_ALLOC_DSM);
 	*mapped_address = address;
 	*mapped_size = request_size;
 
@@ -653,6 +704,13 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 			return false;
 		}
 
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_allocated_bytes_decrease(*mapped_size, PG_ALLOC_DSM);
 		*impl_private = NULL;
 		*mapped_address = NULL;
 		*mapped_size = 0;
@@ -769,6 +827,12 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 		return false;
 	}
 
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_allocated_bytes_increase(info.RegionSize, PG_ALLOC_DSM);
 	*mapped_address = address;
 	*mapped_size = info.RegionSize;
 	*impl_private = hmap;
@@ -813,6 +877,13 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		pgstat_report_allocated_bytes_decrease(*mapped_size, PG_ALLOC_DSM);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && unlink(name) != 0)
@@ -934,6 +1005,13 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_allocated_bytes_increase(request_size, PG_ALLOC_DSM);
 	*mapped_address = address;
 	*mapped_size = request_size;
 
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index f3e20038f4..1959b5f4e6 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -180,6 +180,7 @@ InitProcGlobal(void)
 	ProcGlobal->checkpointerLatch = NULL;
 	pg_atomic_init_u32(&ProcGlobal->procArrayGroupFirst, INVALID_PROC_NUMBER);
 	pg_atomic_init_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER);
+	pg_atomic_init_u64(&ProcGlobal->global_dsm_allocation, 0);
 
 	/*
 	 * Create and initialize all the PGPROC structures we'll need.  There are
diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c
index 1ccf4c6d83..25b545441b 100644
--- a/src/backend/utils/activity/backend_status.c
+++ b/src/backend/utils/activity/backend_status.c
@@ -48,6 +48,24 @@ int			pgstat_track_activity_query_size = 1024;
 /* exposed so that backend_progress.c can access it */
 PgBackendStatus *MyBEEntry = NULL;
 
+/*
+ * Memory allocated to this backend prior to pgstats initialization. Migrated to
+ * shared memory on pgstats initialization.
+ */
+uint64		local_my_allocated_bytes = 0;
+uint64	   *my_allocated_bytes = &local_my_allocated_bytes;
+
+/* Memory allocated to this backend by type prior to pgstats initialization.
+ * Migrated to shared memory on pgstats initialization
+ */
+uint64		local_my_aset_allocated_bytes = 0;
+uint64	   *my_aset_allocated_bytes = &local_my_aset_allocated_bytes;
+uint64		local_my_dsm_allocated_bytes = 0;
+uint64	   *my_dsm_allocated_bytes = &local_my_dsm_allocated_bytes;
+uint64		local_my_generation_allocated_bytes = 0;
+uint64	   *my_generation_allocated_bytes = &local_my_generation_allocated_bytes;
+uint64		local_my_slab_allocated_bytes = 0;
+uint64	   *my_slab_allocated_bytes = &local_my_slab_allocated_bytes;
 
 static PgBackendStatus *BackendStatusArray = NULL;
 static char *BackendAppnameBuffer = NULL;
@@ -382,6 +400,32 @@ pgstat_bestart(void)
 	lbeentry.st_progress_command_target = InvalidOid;
 	lbeentry.st_query_id = UINT64CONST(0);
 
+	/* Alter allocation reporting from local storage to shared memory */
+	pgstat_set_allocated_bytes_storage(&MyBEEntry->allocated_bytes,
+									   &MyBEEntry->aset_allocated_bytes,
+									   &MyBEEntry->dsm_allocated_bytes,
+									   &MyBEEntry->generation_allocated_bytes,
+									   &MyBEEntry->slab_allocated_bytes);
+
+	/*
+	 * Populate sum of memory allocated prior to pgstats initialization to
+	 * pgstats and zero the local variable. This is a += assignment because
+	 * InitPostgres allocates memory after pgstat_beinit but prior to
+	 * pgstat_bestart so we have allocations to both local and shared memory
+	 * to combine.
+	 */
+	lbeentry.allocated_bytes += local_my_allocated_bytes;
+	local_my_allocated_bytes = 0;
+	lbeentry.aset_allocated_bytes += local_my_aset_allocated_bytes;
+	local_my_aset_allocated_bytes = 0;
+
+	lbeentry.dsm_allocated_bytes += local_my_dsm_allocated_bytes;
+	local_my_dsm_allocated_bytes = 0;
+	lbeentry.generation_allocated_bytes += local_my_generation_allocated_bytes;
+	local_my_generation_allocated_bytes = 0;
+	lbeentry.slab_allocated_bytes += local_my_slab_allocated_bytes;
+	local_my_slab_allocated_bytes = 0;
+
 	/*
 	 * we don't zero st_progress_param here to save cycles; nobody should
 	 * examine it until st_progress_command has been set to something other
@@ -441,6 +485,9 @@ pgstat_beshutdown_hook(int code, Datum arg)
 {
 	volatile PgBackendStatus *beentry = MyBEEntry;
 
+	/* Stop reporting memory allocation changes to shared memory */
+	pgstat_reset_allocated_bytes_storage();
+
 	/*
 	 * Clear my status entry, following the protocol of bumping st_changecount
 	 * before and after.  We use a volatile pointer here to ensure the
@@ -1195,3 +1242,70 @@ pgstat_clip_activity(const char *raw_activity)
 
 	return activity;
 }
+
+/*
+ * Configure bytes allocated reporting to report allocated bytes to
+ * shared memory.
+ *
+ * Expected to be called during backend startup (in pgstat_bestart), to point
+ * allocated bytes accounting into shared memory.
+ */
+void
+pgstat_set_allocated_bytes_storage(uint64 *allocated_bytes,
+								   uint64 *aset_allocated_bytes,
+								   uint64 *dsm_allocated_bytes,
+								   uint64 *generation_allocated_bytes,
+								   uint64 *slab_allocated_bytes)
+{
+	/* Map allocations to shared memory */
+	my_allocated_bytes = allocated_bytes;
+	*allocated_bytes = local_my_allocated_bytes;
+
+	my_aset_allocated_bytes = aset_allocated_bytes;
+	*aset_allocated_bytes = local_my_aset_allocated_bytes;
+
+	my_dsm_allocated_bytes = dsm_allocated_bytes;
+	*dsm_allocated_bytes = local_my_dsm_allocated_bytes;
+
+	my_generation_allocated_bytes = generation_allocated_bytes;
+	*generation_allocated_bytes = local_my_generation_allocated_bytes;
+
+	my_slab_allocated_bytes = slab_allocated_bytes;
+	*slab_allocated_bytes = local_my_slab_allocated_bytes;
+}
+
+/*
+ * Reset allocated bytes storage location.
+ *
+ * Expected to be called during backend shutdown, before the locations set up
+ * by pgstat_set_allocated_bytes_storage become invalid.
+ */
+void
+pgstat_reset_allocated_bytes_storage(void)
+{
+	if (ProcGlobal)
+	{
+		volatile PROC_HDR *procglobal = ProcGlobal;
+
+		/*
+		 * Add dsm allocations that have not been freed to global dsm
+		 * accounting
+		 */
+		pg_atomic_add_fetch_u64(&procglobal->global_dsm_allocation,
+								*my_dsm_allocated_bytes);
+	}
+
+	/* Reset memory allocation variables */
+	*my_allocated_bytes = local_my_allocated_bytes = 0;
+	*my_aset_allocated_bytes = local_my_aset_allocated_bytes = 0;
+	*my_dsm_allocated_bytes = local_my_dsm_allocated_bytes = 0;
+	*my_generation_allocated_bytes = local_my_generation_allocated_bytes = 0;
+	*my_slab_allocated_bytes = local_my_slab_allocated_bytes = 0;
+
+	/* Point my_{*_}allocated_bytes from shared memory back to local */
+	my_allocated_bytes = &local_my_allocated_bytes;
+	my_aset_allocated_bytes = &local_my_aset_allocated_bytes;
+	my_dsm_allocated_bytes = &local_my_dsm_allocated_bytes;
+	my_generation_allocated_bytes = &local_my_generation_allocated_bytes;
+	my_slab_allocated_bytes = &local_my_slab_allocated_bytes;
+}
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 3876339ee1..fec7ae2d5f 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -2032,3 +2032,87 @@ pg_stat_have_stats(PG_FUNCTION_ARGS)
 
 	PG_RETURN_BOOL(pgstat_have_entry(kind, dboid, objoid));
 }
+
+/*
+ * Get the memory allocation of PG backends.
+ */
+Datum
+pg_stat_get_memory_allocation(PG_FUNCTION_ARGS)
+{
+#define PG_STAT_GET_MEMORY_ALLOCATION_COLS	7
+	int			num_backends = pgstat_fetch_stat_numbackends();
+	int			curr_backend;
+	int			pid = PG_ARGISNULL(0) ? -1 : PG_GETARG_INT32(0);
+	ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
+
+	InitMaterializedSRF(fcinfo, 0);
+
+	/* 1-based index */
+	for (curr_backend = 1; curr_backend <= num_backends; curr_backend++)
+	{
+		/* for each row */
+		Datum		values[PG_STAT_GET_MEMORY_ALLOCATION_COLS] = {0};
+		bool		nulls[PG_STAT_GET_MEMORY_ALLOCATION_COLS] = {0};
+		LocalPgBackendStatus *local_beentry;
+		PgBackendStatus *beentry;
+
+		/* Get the next one in the list */
+		local_beentry = pgstat_fetch_stat_local_beentry(curr_backend);
+		beentry = &local_beentry->backendStatus;
+
+		/* If looking for specific PID, ignore all the others */
+		if (pid != -1 && beentry->st_procpid != pid)
+			continue;
+
+		/* Values available to all callers */
+		if (beentry->st_databaseid != InvalidOid)
+			values[0] = ObjectIdGetDatum(beentry->st_databaseid);
+		else
+			nulls[0] = true;
+
+		values[1] = Int32GetDatum(beentry->st_procpid);
+		values[2] = UInt64GetDatum(beentry->allocated_bytes);
+		values[3] = UInt64GetDatum(beentry->aset_allocated_bytes);
+		values[4] = UInt64GetDatum(beentry->dsm_allocated_bytes);
+		values[5] = UInt64GetDatum(beentry->generation_allocated_bytes);
+		values[6] = UInt64GetDatum(beentry->slab_allocated_bytes);
+
+		tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
+
+		/* If only a single backend was requested, and we found it, break. */
+		if (pid != -1)
+			break;
+	}
+
+	return (Datum) 0;
+}
+
+/*
+ * Get the global memory allocation statistics.
+ */
+Datum
+pg_stat_get_global_memory_allocation(PG_FUNCTION_ARGS)
+{
+#define PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS	2
+	TupleDesc	tupdesc;
+	Datum		values[PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS] = {0};
+	bool		nulls[PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS] = {0};
+	volatile PROC_HDR *procglobal = ProcGlobal;
+
+	/* Initialise attributes information in the tuple descriptor */
+	tupdesc = CreateTemplateTupleDesc(PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS);
+	TupleDescInitEntry(tupdesc, (AttrNumber) 1, "datid",
+					   OIDOID, -1, 0);
+	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "global_dsm_allocated_bytes",
+					   INT8OID, -1, 0);
+	BlessTupleDesc(tupdesc);
+
+	/* datid */
+	values[0] = ObjectIdGetDatum(MyDatabaseId);
+
+	/* get global_dsm_allocated_bytes */
+	values[1] = Int64GetDatum(pg_atomic_read_u64(&procglobal->global_dsm_allocation));
+
+	/* Returns the record as Datum */
+	PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls)));
+}
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index 537d92c0cf..9b47450813 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -170,6 +170,9 @@ InitPostmasterChild(void)
 				(errcode_for_socket_access(),
 				 errmsg_internal("could not set postmaster death monitoring pipe to FD_CLOEXEC mode: %m")));
 #endif
+
+	/* Init allocated bytes to avoid double counting parent allocation */
+	pgstat_init_allocated_bytes();
 }
 
 /*
diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index d2dcf526d6..a599a3a6e4 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -47,6 +47,7 @@
 #include "postgres.h"
 
 #include "port/pg_bitutils.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -517,6 +518,7 @@ AllocSetContextCreateInternal(MemoryContext parent,
 						name);
 
 	((MemoryContext) set)->mem_allocated = firstBlockSize;
+	pgstat_report_allocated_bytes_increase(firstBlockSize, PG_ALLOC_ASET);
 
 	return (MemoryContext) set;
 }
@@ -539,6 +541,7 @@ AllocSetReset(MemoryContext context)
 	AllocSet	set = (AllocSet) context;
 	AllocBlock	block;
 	Size		keepersize PG_USED_FOR_ASSERTS_ONLY;
+	uint64		deallocation = 0;
 
 	Assert(AllocSetIsValid(set));
 
@@ -581,6 +584,7 @@ AllocSetReset(MemoryContext context)
 		{
 			/* Normal case, release the block */
 			context->mem_allocated -= block->endptr - ((char *) block);
+			deallocation += block->endptr - ((char *) block);
 
 #ifdef CLOBBER_FREED_MEMORY
 			wipe_mem(block, block->freeptr - ((char *) block));
@@ -591,6 +595,7 @@ AllocSetReset(MemoryContext context)
 	}
 
 	Assert(context->mem_allocated == keepersize);
+	pgstat_report_allocated_bytes_decrease(deallocation, PG_ALLOC_ASET);
 
 	/* Reset block size allocation sequence, too */
 	set->nextBlockSize = set->initBlockSize;
@@ -609,6 +614,7 @@ AllocSetDelete(MemoryContext context)
 	AllocSet	set = (AllocSet) context;
 	AllocBlock	block = set->blocks;
 	Size		keepersize PG_USED_FOR_ASSERTS_ONLY;
+	uint64		deallocation = 0;
 
 	Assert(AllocSetIsValid(set));
 
@@ -647,11 +653,13 @@ AllocSetDelete(MemoryContext context)
 
 				freelist->first_free = (AllocSetContext *) oldset->header.nextchild;
 				freelist->num_free--;
+				deallocation += oldset->header.mem_allocated;
 
 				/* All that remains is to free the header/initial block */
 				free(oldset);
 			}
 			Assert(freelist->num_free == 0);
+			pgstat_report_allocated_bytes_decrease(deallocation, PG_ALLOC_ASET);
 		}
 
 		/* Now add the just-deleted context to the freelist. */
@@ -668,7 +676,10 @@ AllocSetDelete(MemoryContext context)
 		AllocBlock	next = block->next;
 
 		if (!IsKeeperBlock(set, block))
+		{
 			context->mem_allocated -= block->endptr - ((char *) block);
+			deallocation += block->endptr - ((char *) block);
+		}
 
 #ifdef CLOBBER_FREED_MEMORY
 		wipe_mem(block, block->freeptr - ((char *) block));
@@ -681,6 +692,7 @@ AllocSetDelete(MemoryContext context)
 	}
 
 	Assert(context->mem_allocated == keepersize);
+	pgstat_report_allocated_bytes_decrease(deallocation + context->mem_allocated, PG_ALLOC_ASET);
 
 	/* Finally, free the context header, including the keeper block */
 	free(set);
@@ -717,6 +729,7 @@ AllocSetAllocLarge(MemoryContext context, Size size, int flags)
 		return MemoryContextAllocationFailure(context, size, flags);
 
 	context->mem_allocated += blksize;
+	pgstat_report_allocated_bytes_increase(blksize, PG_ALLOC_ASET);
 
 	block->aset = set;
 	block->freeptr = block->endptr = ((char *) block) + blksize;
@@ -923,6 +936,7 @@ AllocSetAllocFromNewBlock(MemoryContext context, Size size, int flags,
 		return MemoryContextAllocationFailure(context, size, flags);
 
 	context->mem_allocated += blksize;
+	pgstat_report_allocated_bytes_increase(blksize, PG_ALLOC_ASET);
 
 	block->aset = set;
 	block->freeptr = ((char *) block) + ALLOC_BLOCKHDRSZ;
@@ -1100,6 +1114,7 @@ AllocSetFree(void *pointer)
 			block->next->prev = block->prev;
 
 		set->header.mem_allocated -= block->endptr - ((char *) block);
+		pgstat_report_allocated_bytes_decrease(block->endptr - ((char *) block), PG_ALLOC_ASET);
 
 #ifdef CLOBBER_FREED_MEMORY
 		wipe_mem(block, block->freeptr - ((char *) block));
@@ -1233,7 +1248,9 @@ AllocSetRealloc(void *pointer, Size size, int flags)
 
 		/* updated separately, not to underflow when (oldblksize > blksize) */
 		set->header.mem_allocated -= oldblksize;
+		pgstat_report_allocated_bytes_decrease(oldblksize, PG_ALLOC_ASET);
 		set->header.mem_allocated += blksize;
+		pgstat_report_allocated_bytes_increase(blksize, PG_ALLOC_ASET);
 
 		block->freeptr = block->endptr = ((char *) block) + blksize;
 
diff --git a/src/backend/utils/mmgr/generation.c b/src/backend/utils/mmgr/generation.c
index 9124d9b952..d511b67b08 100644
--- a/src/backend/utils/mmgr/generation.c
+++ b/src/backend/utils/mmgr/generation.c
@@ -37,6 +37,7 @@
 
 #include "lib/ilist.h"
 #include "port/pg_bitutils.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -266,6 +267,7 @@ GenerationContextCreate(MemoryContext parent,
 						name);
 
 	((MemoryContext) set)->mem_allocated = firstBlockSize;
+	pgstat_report_allocated_bytes_increase(firstBlockSize, PG_ALLOC_GENERATION);
 
 	return (MemoryContext) set;
 }
@@ -284,6 +286,7 @@ GenerationReset(MemoryContext context)
 {
 	GenerationContext *set = (GenerationContext *) context;
 	dlist_mutable_iter miter;
+	uint64		deallocation = 0;
 
 	Assert(GenerationIsValid(set));
 
@@ -306,9 +309,14 @@ GenerationReset(MemoryContext context)
 		if (IsKeeperBlock(set, block))
 			GenerationBlockMarkEmpty(block);
 		else
+		{
+			deallocation += block->blksize;
 			GenerationBlockFree(set, block);
+		}
 	}
 
+	pgstat_report_allocated_bytes_decrease(deallocation, PG_ALLOC_GENERATION);
+
 	/* set it so new allocations to make use of the keeper block */
 	set->block = KeeperBlock(set);
 
@@ -329,6 +337,9 @@ GenerationDelete(MemoryContext context)
 {
 	/* Reset to release all releasable GenerationBlocks */
 	GenerationReset(context);
+
+	pgstat_report_allocated_bytes_decrease(context->mem_allocated, PG_ALLOC_GENERATION);
+
 	/* And free the context header and keeper block */
 	free(context);
 }
@@ -366,6 +377,7 @@ GenerationAllocLarge(MemoryContext context, Size size, int flags)
 		return MemoryContextAllocationFailure(context, size, flags);
 
 	context->mem_allocated += blksize;
+	pgstat_report_allocated_bytes_increase(blksize, PG_ALLOC_GENERATION);
 
 	/* block with a single (used) chunk */
 	block->context = set;
@@ -488,6 +500,7 @@ GenerationAllocFromNewBlock(MemoryContext context, Size size, int flags,
 		return MemoryContextAllocationFailure(context, size, flags);
 
 	context->mem_allocated += blksize;
+	pgstat_report_allocated_bytes_increase(blksize, PG_ALLOC_GENERATION);
 
 	/* initialize the new block */
 	GenerationBlockInit(set, block, blksize);
@@ -672,6 +685,7 @@ GenerationBlockFree(GenerationContext *set, GenerationBlock *block)
 	dlist_delete(&block->node);
 
 	((MemoryContext) set)->mem_allocated -= block->blksize;
+	pgstat_report_allocated_bytes_decrease(block->blksize, PG_ALLOC_GENERATION);
 
 #ifdef CLOBBER_FREED_MEMORY
 	wipe_mem(block, block->blksize);
diff --git a/src/backend/utils/mmgr/slab.c b/src/backend/utils/mmgr/slab.c
index 516e1c95aa..98a8bbaf91 100644
--- a/src/backend/utils/mmgr/slab.c
+++ b/src/backend/utils/mmgr/slab.c
@@ -69,6 +69,7 @@
 #include "postgres.h"
 
 #include "lib/ilist.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_memorychunk.h"
@@ -417,6 +418,13 @@ SlabContextCreate(MemoryContext parent,
 						parent,
 						name);
 
+	/*
+	 * If SlabContextCreate is updated to add context header size to
+	 * context->mem_allocated, then update here and SlabDelete appropriately
+	 */
+	pgstat_report_allocated_bytes_increase(Slab_CONTEXT_HDRSZ(slab->chunksPerBlock),
+										   PG_ALLOC_SLAB);
+
 	return (MemoryContext) slab;
 }
 
@@ -433,6 +441,7 @@ SlabReset(MemoryContext context)
 	SlabContext *slab = (SlabContext *) context;
 	dlist_mutable_iter miter;
 	int			i;
+	uint64		deallocation = 0;
 
 	Assert(SlabIsValid(slab));
 
@@ -453,6 +462,7 @@ SlabReset(MemoryContext context)
 #endif
 		free(block);
 		context->mem_allocated -= slab->blockSize;
+		deallocation += slab->blockSize;
 	}
 
 	/* walk over blocklist and free the blocks */
@@ -469,9 +479,11 @@ SlabReset(MemoryContext context)
 #endif
 			free(block);
 			context->mem_allocated -= slab->blockSize;
+			deallocation += slab->blockSize;
 		}
 	}
 
+	pgstat_report_allocated_bytes_decrease(deallocation, PG_ALLOC_SLAB);
 	slab->curBlocklistIndex = 0;
 
 	Assert(context->mem_allocated == 0);
@@ -486,6 +498,14 @@ SlabDelete(MemoryContext context)
 {
 	/* Reset to release all the SlabBlocks */
 	SlabReset(context);
+
+	/*
+	 * Until context header allocation is included in context->mem_allocated,
+	 * cast to slab and decrement the header allocation
+	 */
+	pgstat_report_allocated_bytes_decrease(Slab_CONTEXT_HDRSZ(((SlabContext *) context)->chunksPerBlock),
+										   PG_ALLOC_SLAB);
+
 	/* And free the context header */
 	free(context);
 }
@@ -569,6 +589,7 @@ SlabAllocFromNewBlock(MemoryContext context, Size size, int flags)
 
 		block->slab = slab;
 		context->mem_allocated += slab->blockSize;
+		pgstat_report_allocated_bytes_increase(slab->blockSize, PG_ALLOC_SLAB);
 
 		/* use the first chunk in the new block */
 		chunk = SlabBlockGetChunk(slab, block, 0);
@@ -797,6 +818,7 @@ SlabFree(void *pointer)
 #endif
 			free(block);
 			slab->header.mem_allocated -= slab->blockSize;
+			pgstat_report_allocated_bytes_decrease(slab->blockSize, PG_ALLOC_SLAB);
 		}
 
 		/*
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 291ed876fc..47903e755e 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -5435,6 +5435,23 @@
   proname => 'pg_stat_get_backend_idset', prorows => '100', proretset => 't',
   provolatile => 's', proparallel => 'r', prorettype => 'int4',
   proargtypes => '', prosrc => 'pg_stat_get_backend_idset' },
+{ oid => '9890',
+  descr => 'statistics: memory allocation information for backends',
+  proname => 'pg_stat_get_memory_allocation', prorows => '100', proisstrict => 'f',
+  proretset => 't', provolatile => 's', proparallel => 'r',
+  prorettype => 'record', proargtypes => 'int4',
+  proallargtypes => '{int4,oid,int4,int8,int8,int8,int8,int8}',
+  proargmodes => '{i,o,o,o,o,o,o,o}',
+  proargnames => '{pid,datid,pid,allocated_bytes,aset_allocated_bytes,dsm_allocated_bytes,generation_allocated_bytes,slab_allocated_bytes}',
+  prosrc => 'pg_stat_get_memory_allocation' },
+{ oid => '9891',
+  descr => 'statistics: global memory allocation information',
+  proname => 'pg_stat_get_global_memory_allocation', proisstrict => 'f',
+  provolatile => 's', proparallel => 'r', prorettype => 'record',
+  proargtypes => '', proallargtypes => '{oid,int8}',
+  proargmodes => '{o,o}',
+  proargnames => '{datid,global_dsm_allocated_bytes}',
+  prosrc =>'pg_stat_get_global_memory_allocation' },
 { oid => '2022',
   descr => 'statistics: information about currently active backends',
   proname => 'pg_stat_get_activity', prorows => '100', proisstrict => 'f',
diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h
index 1095aefddf..a350f455cd 100644
--- a/src/include/storage/proc.h
+++ b/src/include/storage/proc.h
@@ -422,6 +422,8 @@ typedef struct PROC_HDR
 	int			spins_per_delay;
 	/* Buffer id of the buffer that Startup process waits for pin on, or -1 */
 	int			startupBufferPinWaitBufId;
+	/* Global dsm allocations */
+	pg_atomic_uint64 global_dsm_allocation;
 } PROC_HDR;
 
 extern PGDLLIMPORT PROC_HDR *ProcGlobal;
diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h
index 7b7f6f59d0..cbf801884d 100644
--- a/src/include/utils/backend_status.h
+++ b/src/include/utils/backend_status.h
@@ -10,6 +10,7 @@
 #ifndef BACKEND_STATUS_H
 #define BACKEND_STATUS_H
 
+#include "common/int.h"
 #include "datatype/timestamp.h"
 #include "libpq/pqcomm.h"
 #include "miscadmin.h"			/* for BackendType */
@@ -32,6 +33,14 @@ typedef enum BackendState
 	STATE_DISABLED,
 } BackendState;
 
+/* Enum helper for reporting memory allocator type */
+enum pg_allocator_type
+{
+	PG_ALLOC_ASET = 1,
+	PG_ALLOC_DSM,
+	PG_ALLOC_GENERATION,
+	PG_ALLOC_SLAB
+};
 
 /* ----------
  * Shared-memory data structures
@@ -170,6 +179,15 @@ typedef struct PgBackendStatus
 
 	/* query identifier, optionally computed using post_parse_analyze_hook */
 	uint64		st_query_id;
+
+	/* Current memory allocated to this backend */
+	uint64		allocated_bytes;
+
+	/* Current memory allocated to this backend by type */
+	uint64		aset_allocated_bytes;
+	uint64		dsm_allocated_bytes;
+	uint64		generation_allocated_bytes;
+	uint64		slab_allocated_bytes;
 } PgBackendStatus;
 
 
@@ -292,6 +310,11 @@ extern PGDLLIMPORT int pgstat_track_activity_query_size;
  * ----------
  */
 extern PGDLLIMPORT PgBackendStatus *MyBEEntry;
+extern PGDLLIMPORT uint64 *my_allocated_bytes;
+extern PGDLLIMPORT uint64 *my_aset_allocated_bytes;
+extern PGDLLIMPORT uint64 *my_dsm_allocated_bytes;
+extern PGDLLIMPORT uint64 *my_generation_allocated_bytes;
+extern PGDLLIMPORT uint64 *my_slab_allocated_bytes;
 
 
 /* ----------
@@ -323,7 +346,12 @@ extern const char *pgstat_get_backend_current_activity(int pid, bool checkUser);
 extern const char *pgstat_get_crashed_backend_activity(int pid, char *buffer,
 													   int buflen);
 extern uint64 pgstat_get_my_query_id(void);
-
+extern void pgstat_set_allocated_bytes_storage(uint64 *allocated_bytes,
+											   uint64 *aset_allocated_bytes,
+											   uint64 *dsm_allocated_bytes,
+											   uint64 *generation_allocated_bytes,
+											   uint64 *slab_allocated_bytes);
+extern void pgstat_reset_allocated_bytes_storage(void);
 
 /* ----------
  * Support functions for the SQL-callable functions to
@@ -336,5 +364,119 @@ extern LocalPgBackendStatus *pgstat_get_local_beentry_by_proc_number(ProcNumber
 extern LocalPgBackendStatus *pgstat_get_local_beentry_by_index(int idx);
 extern char *pgstat_clip_activity(const char *raw_activity);
 
+/* ----------
+ * pgstat_report_allocated_bytes_decrease() -
+ *  Called to report decrease in memory allocated for this backend.
+ *
+ * my_{*_}allocated_bytes initially points to local memory, making it safe to
+ * call this before pgstats has been initialized.
+ * ----------
+ */
+static inline void
+pgstat_report_allocated_bytes_decrease(int64 proc_allocated_bytes,
+									   int pg_allocator_type)
+{
+	uint64		temp;
+
+	/* Avoid allocated_bytes unsigned integer overflow on decrease */
+	if (pg_sub_u64_overflow(*my_allocated_bytes, proc_allocated_bytes, &temp))
+	{
+		/* On overflow, set allocated bytes and allocator type bytes to zero */
+		*my_allocated_bytes = 0;
+		*my_aset_allocated_bytes = 0;
+		*my_dsm_allocated_bytes = 0;
+		*my_generation_allocated_bytes = 0;
+		*my_slab_allocated_bytes = 0;
+	}
+	else
+	{
+		/* decrease allocation */
+		*my_allocated_bytes -= proc_allocated_bytes;
+
+		/* Decrease allocator type allocated bytes. */
+		switch (pg_allocator_type)
+		{
+			case PG_ALLOC_ASET:
+				*my_aset_allocated_bytes -= proc_allocated_bytes;
+				break;
+			case PG_ALLOC_DSM:
+
+				/*
+				 * Some dsm allocations live beyond process exit. These are
+				 * accounted for in a global counter in
+				 * pgstat_reset_allocated_bytes_storage at process exit.
+				 */
+				*my_dsm_allocated_bytes -= proc_allocated_bytes;
+				break;
+			case PG_ALLOC_GENERATION:
+				*my_generation_allocated_bytes -= proc_allocated_bytes;
+				break;
+			case PG_ALLOC_SLAB:
+				*my_slab_allocated_bytes -= proc_allocated_bytes;
+				break;
+		}
+	}
+
+	return;
+}
+
+/* ----------
+ * pgstat_report_allocated_bytes_increase() -
+ *  Called to report increase in memory allocated for this backend.
+ *
+ * my_allocated_bytes initially points to local memory, making it safe to call
+ * this before pgstats has been initialized.
+ * ----------
+ */
+static inline void
+pgstat_report_allocated_bytes_increase(int64 proc_allocated_bytes,
+									   int pg_allocator_type)
+{
+	*my_allocated_bytes += proc_allocated_bytes;
+
+	/* Increase allocator type allocated bytes */
+	switch (pg_allocator_type)
+	{
+		case PG_ALLOC_ASET:
+			*my_aset_allocated_bytes += proc_allocated_bytes;
+			break;
+		case PG_ALLOC_DSM:
+
+			/*
+			 * Some dsm allocations live beyond process exit. These are
+			 * accounted for in a global counter in
+			 * pgstat_reset_allocated_bytes_storage at process exit.
+			 */
+			*my_dsm_allocated_bytes += proc_allocated_bytes;
+			break;
+		case PG_ALLOC_GENERATION:
+			*my_generation_allocated_bytes += proc_allocated_bytes;
+			break;
+		case PG_ALLOC_SLAB:
+			*my_slab_allocated_bytes += proc_allocated_bytes;
+			break;
+	}
+
+	return;
+}
+
+/* ---------
+ * pgstat_init_allocated_bytes() -
+ *
+ * Called to initialize allocated bytes variables after fork and to
+ * avoid double counting allocations.
+ * ---------
+ */
+static inline void
+pgstat_init_allocated_bytes(void)
+{
+	*my_allocated_bytes = 0;
+	*my_aset_allocated_bytes = 0;
+	*my_dsm_allocated_bytes = 0;
+	*my_generation_allocated_bytes = 0;
+	*my_slab_allocated_bytes = 0;
+
+	return;
+}
 
 #endif							/* BACKEND_STATUS_H */
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index 0cd2c64fca..2f62f5e4ea 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1877,6 +1877,24 @@ pg_stat_database_conflicts| SELECT oid AS datid,
     pg_stat_get_db_conflict_startup_deadlock(oid) AS confl_deadlock,
     pg_stat_get_db_conflict_logicalslot(oid) AS confl_active_logicalslot
    FROM pg_database d;
+pg_stat_global_memory_allocation| WITH sums AS (
+         SELECT sum(pg_stat_memory_allocation.aset_allocated_bytes) AS total_aset_allocated_bytes,
+            sum(pg_stat_memory_allocation.dsm_allocated_bytes) AS total_dsm_allocated_bytes,
+            sum(pg_stat_memory_allocation.generation_allocated_bytes) AS total_generation_allocated_bytes,
+            sum(pg_stat_memory_allocation.slab_allocated_bytes) AS total_slab_allocated_bytes
+           FROM pg_stat_memory_allocation
+        )
+ SELECT s.datid,
+    current_setting('shared_memory_size'::text, true) AS shared_memory_size,
+    (current_setting('shared_memory_size_in_huge_pages'::text, true))::integer AS shared_memory_size_in_huge_pages,
+    s.global_dsm_allocated_bytes,
+    sums.total_aset_allocated_bytes,
+    sums.total_dsm_allocated_bytes,
+    sums.total_generation_allocated_bytes,
+    sums.total_slab_allocated_bytes
+   FROM sums,
+    (pg_stat_get_global_memory_allocation() s(datid, global_dsm_allocated_bytes)
+     LEFT JOIN pg_database d ON ((s.datid = d.oid)));
 pg_stat_gssapi| SELECT pid,
     gss_auth AS gss_authenticated,
     gss_princ AS principal,
@@ -1903,6 +1921,15 @@ pg_stat_io| SELECT backend_type,
     fsync_time,
     stats_reset
    FROM pg_stat_get_io() b(backend_type, object, context, reads, read_time, writes, write_time, writebacks, writeback_time, extends, extend_time, op_bytes, hits, evictions, reuses, fsyncs, fsync_time, stats_reset);
+pg_stat_memory_allocation| SELECT s.datid,
+    s.pid,
+    s.allocated_bytes,
+    s.aset_allocated_bytes,
+    s.dsm_allocated_bytes,
+    s.generation_allocated_bytes,
+    s.slab_allocated_bytes
+   FROM (pg_stat_get_memory_allocation(NULL::integer) s(datid, pid, allocated_bytes, aset_allocated_bytes, dsm_allocated_bytes, generation_allocated_bytes, slab_allocated_bytes)
+     LEFT JOIN pg_database d ON ((s.datid = d.oid)));
 pg_stat_progress_analyze| SELECT s.pid,
     s.datid,
     d.datname,
diff --git a/src/test/regress/expected/stats.out b/src/test/regress/expected/stats.out
index 6e08898b18..902d827998 100644
--- a/src/test/regress/expected/stats.out
+++ b/src/test/regress/expected/stats.out
@@ -1646,4 +1646,40 @@ SELECT COUNT(*) FROM brin_hot_3 WHERE a = 2;
 
 DROP TABLE brin_hot_3;
 SET enable_seqscan = on;
+-- ensure that allocated_bytes exist for backends
+SELECT
+    allocated_bytes > 0 AS result
+FROM
+    pg_stat_activity ps
+    JOIN pg_stat_memory_allocation pa ON (pa.pid = ps.pid)
+WHERE
+    backend_type IN ('checkpointer', 'background writer', 'walwriter', 'autovacuum launcher');
+ result 
+--------
+ t
+ t
+ t
+ t
+(4 rows)
+
+-- ensure that pg_stat_global_memory_allocation view exists
+SELECT
+    datid > 0, pg_size_bytes(shared_memory_size) >= 0, shared_memory_size_in_huge_pages >= -1, global_dsm_allocated_bytes >= 0
+FROM
+    pg_stat_global_memory_allocation;
+ ?column? | ?column? | ?column? | ?column? 
+----------+----------+----------+----------
+ t        | t        | t        | t
+(1 row)
+
+-- ensure that pg_stat_memory_allocation view exists
+SELECT
+    pid > 0, allocated_bytes >= 0, aset_allocated_bytes >= 0, dsm_allocated_bytes >= 0, generation_allocated_bytes >= 0, slab_allocated_bytes >= 0
+FROM
+    pg_stat_memory_allocation limit 1;
+ ?column? | ?column? | ?column? | ?column? | ?column? | ?column? 
+----------+----------+----------+----------+----------+----------
+ t        | t        | t        | t        | t        | t
+(1 row)
+
 -- End of Stats Test
diff --git a/src/test/regress/sql/stats.sql b/src/test/regress/sql/stats.sql
index d8ac0d06f4..40746c9258 100644
--- a/src/test/regress/sql/stats.sql
+++ b/src/test/regress/sql/stats.sql
@@ -849,4 +849,24 @@ DROP TABLE brin_hot_3;
 
 SET enable_seqscan = on;
 
+-- ensure that allocated_bytes exist for backends
+SELECT
+    allocated_bytes > 0 AS result
+FROM
+    pg_stat_activity ps
+    JOIN pg_stat_memory_allocation pa ON (pa.pid = ps.pid)
+WHERE
+    backend_type IN ('checkpointer', 'background writer', 'walwriter', 'autovacuum launcher');
+
+-- ensure that pg_stat_global_memory_allocation view exists
+SELECT
+    datid > 0, pg_size_bytes(shared_memory_size) >= 0, shared_memory_size_in_huge_pages >= -1, global_dsm_allocated_bytes >= 0
+FROM
+    pg_stat_global_memory_allocation;
+
+-- ensure that pg_stat_memory_allocation view exists
+SELECT
+    pid > 0, allocated_bytes >= 0, aset_allocated_bytes >= 0, dsm_allocated_bytes >= 0, generation_allocated_bytes >= 0, slab_allocated_bytes >= 0
+FROM
+    pg_stat_memory_allocation limit 1;
 -- End of Stats Test
-- 
2.43.2

v20140313-0002-fixup-pgstat_get_local_beentry_by_index.patchtext/x-patch; charset=UTF-8; name=v20140313-0002-fixup-pgstat_get_local_beentry_by_index.patchDownload
From 0934a92f51ccb19266a2faa2f0b9146e3f9a665c Mon Sep 17 00:00:00 2001
From: Tomas Vondra <tomas@2ndquadrant.com>
Date: Tue, 26 Dec 2023 18:05:02 +0100
Subject: [PATCH 2/3] fixup: pgstat_get_local_beentry_by_index

---
 src/backend/utils/adt/pgstatfuncs.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index fec7ae2d5f..9c82ec48cb 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -2057,7 +2057,7 @@ pg_stat_get_memory_allocation(PG_FUNCTION_ARGS)
 		PgBackendStatus *beentry;
 
 		/* Get the next one in the list */
-		local_beentry = pgstat_fetch_stat_local_beentry(curr_backend);
+		local_beentry = pgstat_get_local_beentry_by_index(curr_backend);
 		beentry = &local_beentry->backendStatus;
 
 		/* If looking for specific PID, ignore all the others */
-- 
2.43.2

v20140313-0003-Add-the-ability-to-limit-the-amount-of-memory-that-c.patchtext/x-patch; charset=UTF-8; name=v20140313-0003-Add-the-ability-to-limit-the-amount-of-memory-that-c.patchDownload
From 3e65eb6c298d3160db9e528ab3c2b857acd57937 Mon Sep 17 00:00:00 2001
From: Tomas Vondra <tomas@2ndquadrant.com>
Date: Tue, 26 Dec 2023 17:55:23 +0100
Subject: [PATCH 3/3] Add the ability to limit the amount of memory that can be
 allocated to backends.

This builds on the work that adds backend memory allocated tracking.

Add GUC variable max_total_backend_memory.

Specifies a limit to the amount of memory (in MB) that may be allocated to
backends in total (i.e. this is not a per user or per backend limit). If unset,
or set to 0 it is disabled. It is intended as a resource to help avoid the OOM
killer on LINUX and manage resources in general. A backend request that would
exhaust max_total_backend_memory memory will be denied with an out of memory
error causing that backend's current query/transaction to fail.  Further
requests will not be allocated until dropping below the limit. Keep this in
mind when setting this value. Due to the dynamic nature of memory allocations,
this limit is not exact. This limit does not affect auxiliary backend
processes. Backend memory allocations are displayed in the
pg_stat_memory_allocation and pg_stat_global_memory_allocation views.
---
 doc/src/sgml/config.sgml                      |  30 +++
 doc/src/sgml/monitoring.sgml                  |  38 +++-
 src/backend/catalog/system_views.sql          |   2 +
 src/backend/port/sysv_shmem.c                 |   9 +
 src/backend/postmaster/postmaster.c           |   5 +
 src/backend/storage/ipc/dsm_impl.c            |  18 ++
 src/backend/storage/lmgr/proc.c               |  45 +++++
 src/backend/utils/activity/backend_status.c   | 175 ++++++++++++++++++
 src/backend/utils/adt/pgstatfuncs.c           |  16 +-
 src/backend/utils/hash/dynahash.c             |   3 +-
 src/backend/utils/init/miscinit.c             |   8 +
 src/backend/utils/misc/guc_tables.c           |  11 ++
 src/backend/utils/misc/postgresql.conf.sample |   3 +
 src/backend/utils/mmgr/aset.c                 |  33 ++++
 src/backend/utils/mmgr/generation.c           |  16 ++
 src/backend/utils/mmgr/slab.c                 |  15 +-
 src/include/catalog/pg_proc.dat               |   6 +-
 src/include/storage/proc.h                    |   7 +
 src/include/utils/backend_status.h            | 103 ++++++++++-
 src/test/regress/expected/rules.out           |   4 +-
 20 files changed, 526 insertions(+), 21 deletions(-)

diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 65a6e6c408..4f26284ee1 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -2306,6 +2306,36 @@ include_dir 'conf.d'
       </listitem>
      </varlistentry>
 
+     <varlistentry id="guc-max-total-backend-memory" xreflabel="max_total_backend_memory">
+      <term><varname>max_total_backend_memory</varname> (<type>integer</type>)
+      <indexterm>
+       <primary><varname>max_total_backend_memory</varname> configuration parameter</primary>
+      </indexterm>
+      </term>
+      <listitem>
+       <para>
+        Specifies a limit to the amount of memory (MB) that may be allocated to
+        backends in total (i.e. this is not a per user or per backend limit).
+        If unset, or set to 0 it is disabled.  At databse startup
+        max_total_backend_memory is reduced by shared_memory_size_mb
+        (includes shared buffers and other memory required for initialization).
+        Each backend process is intialized with a 1MB local allowance which
+        also reduces total_bkend_mem_bytes_available. Keep this in mind when
+        setting this value. A backend request that would exhaust the limit will
+        be denied with an out of memory error causing that backend's current
+        query/transaction to fail. Further requests will not be allocated until
+        dropping below the limit.  This limit does not affect auxiliary backend
+        processes
+        <xref linkend="glossary-auxiliary-proc"/> or the postmaster process.
+        Backend memory allocations (<varname>allocated_bytes</varname>) are
+        displayed in the
+        <link linkend="monitoring-pg-stat-memory-allocation-view"><structname>pg_stat_memory_allocation</structname></link>
+        view.  Due to the dynamic nature of memory allocations, this limit is
+        not exact.
+       </para>
+      </listitem>
+     </varlistentry>
+
      </variablelist>
      </sect2>
 
diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 5f827fe0b0..dbe40b8810 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -4658,10 +4658,7 @@ description | Waiting for a newly initialized WAL file to reach durable storage
       </para>
      <para>
       Memory currently allocated to this backend in bytes. This is the balance
-      of bytes allocated and freed by this backend. Dynamic shared memory
-      allocations are included only in the value displayed for the backend that
-      created them, they are not included in the value for backends that are
-      attached to them to avoid double counting.
+      of bytes allocated and freed by this backend.
      </para></entry>
      </row>
 
@@ -4778,6 +4775,39 @@ description | Waiting for a newly initialized WAL file to reach durable storage
      </para></entry>
      </row>
 
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>max_total_backend_memory_bytes</structfield> <type>bigint</type>
+      </para>
+     <para>
+      Reports the user defined backend maximum allowed shared memory in bytes.
+      0 if disabled or not set. See
+      <xref linkend="guc-max-total-backend-memory"/>.
+     </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>total_bkend_mem_bytes_available</structfield> <type>bigint</type>
+      </para>
+     <para>
+      Tracks max_total_backend_memory (in bytes) available for allocation. At
+      database startup, total_bkend_mem_bytes_available is reduced by the
+      byte equivalent of shared_memory_size_mb. Each backend process is
+      intialized with a 1MB local allowance which also reduces
+      total_bkend_mem_bytes_available. A process's allocation requests reduce
+      it's local allowance. If a process's allocation request exceeds it's
+      remaining allowance, an attempt is made to refill the local allowance
+      from total_bkend_mem_bytes_available. If the refill request fails, then
+      the requesting process will fail with an out of memory error resulting
+      in the cancellation of that process's active query/transaction.  The
+      default refill allocation quantity is 1MB.  If a request is greater than
+      1MB, an attempt will be made to allocate the full amount. If
+      max_total_backend_memory is disabled, this will be -1.
+      <xref linkend="guc-max-total-backend-memory"/>.
+     </para></entry>
+     </row>
+
      <row>
       <entry role="catalog_table_entry"><para role="column_definition">
        <structfield>global_dsm_allocated_bytes</structfield> <type>bigint</type>
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 61ff4a59b6..c646b28f16 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -1402,6 +1402,8 @@ SELECT
         S.datid AS datid,
         current_setting('shared_memory_size', true) as shared_memory_size,
         (current_setting('shared_memory_size_in_huge_pages', true))::integer as shared_memory_size_in_huge_pages,
+        pg_size_bytes(current_setting('max_total_backend_memory', true)) as max_total_backend_memory_bytes,
+        S.total_bkend_mem_bytes_available,
         S.global_dsm_allocated_bytes,
         sums.total_aset_allocated_bytes,
         sums.total_dsm_allocated_bytes,
diff --git a/src/backend/port/sysv_shmem.c b/src/backend/port/sysv_shmem.c
index 1a6d8fa0fb..c0788732df 100644
--- a/src/backend/port/sysv_shmem.c
+++ b/src/backend/port/sysv_shmem.c
@@ -34,6 +34,7 @@
 #include "storage/fd.h"
 #include "storage/ipc.h"
 #include "storage/pg_shmem.h"
+#include "utils/backend_status.h"
 #include "utils/guc.h"
 #include "utils/guc_hooks.h"
 #include "utils/pidfile.h"
@@ -918,6 +919,14 @@ PGSharedMemoryReAttach(void)
 	dsm_set_control_handle(hdr->dsm_control);
 
 	UsedShmemSegAddr = hdr;		/* probably redundant */
+
+	/*
+	 * Init allocated bytes to avoid double counting parent allocation for
+	 * fork/exec processes. Forked processes perform this action in
+	 * InitPostmasterChild. For EXEC_BACKEND processes we have to wait for
+	 * shared memory to be reattached.
+	 */
+	pgstat_init_allocated_bytes();
 }
 
 /*
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 49fc6f979e..abb10ed7c8 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -556,6 +556,7 @@ typedef struct
 #endif
 	char		my_exec_path[MAXPGPATH];
 	char		pkglib_path[MAXPGPATH];
+	int			max_total_bkend_mem;
 } BackendParameters;
 
 static void read_backend_variables(char *id, ClientSocket **client_sock, BackgroundWorker **worker);
@@ -6152,6 +6153,8 @@ save_backend_variables(BackendParameters *param, ClientSocket *client_sock, Back
 
 	strlcpy(param->pkglib_path, pkglib_path, MAXPGPATH);
 
+	param->max_total_bkend_mem = max_total_bkend_mem;
+
 	return true;
 }
 
@@ -6391,6 +6394,8 @@ restore_backend_variables(BackendParameters *param, ClientSocket **client_sock,
 
 	strlcpy(pkglib_path, param->pkglib_path, MAXPGPATH);
 
+	max_total_bkend_mem = param->max_total_bkend_mem;
+
 	/*
 	 * We need to restore fd.c's counts of externally-opened FDs; to avoid
 	 * confusion, be sure to do this after restoring max_safe_fds.  (Note:
diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c
index af67e55bdf..b6dee75423 100644
--- a/src/backend/storage/ipc/dsm_impl.c
+++ b/src/backend/storage/ipc/dsm_impl.c
@@ -254,6 +254,16 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 		return true;
 	}
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+	{
+		ereport(elevel,
+				(errcode_for_dynamic_shared_memory(),
+				 errmsg("out of memory for segment \"%s\" - exceeds max_total_backend_memory: %m",
+						name)));
+		return false;
+	}
+
 	/*
 	 * Create new segment or open an existing one for attach.
 	 *
@@ -523,6 +533,10 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 		int			flags = IPCProtection;
 		size_t		segsize;
 
+		/* Do not exceed maximum allowed memory allocation */
+		if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+			return false;
+
 		/*
 		 * Allocate the memory BEFORE acquiring the resource, so that we don't
 		 * leak the resource if memory allocation fails.
@@ -717,6 +731,10 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 		return true;
 	}
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+		return false;
+
 	/* Create new segment or open an existing one for attach. */
 	if (op == DSM_OP_CREATE)
 	{
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index 1959b5f4e6..6dbe4373f8 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -50,6 +50,7 @@
 #include "storage/procsignal.h"
 #include "storage/spin.h"
 #include "storage/standby.h"
+#include "utils/guc.h"
 #include "utils/timeout.h"
 #include "utils/timestamp.h"
 
@@ -182,6 +183,50 @@ InitProcGlobal(void)
 	pg_atomic_init_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER);
 	pg_atomic_init_u64(&ProcGlobal->global_dsm_allocation, 0);
 
+	/* Setup backend memory limiting if configured */
+	if (max_total_bkend_mem > 0)
+	{
+		/*
+		 * Convert max_total_bkend_mem to bytes, account for
+		 * shared_memory_size, and initialize total_bkend_mem_bytes.
+		 */
+		int			result = 0;
+
+		/* Get integer value of shared_memory_size */
+		if (parse_int(GetConfigOption("shared_memory_size", true, false), &result, 0, NULL))
+		{
+			/*
+			 * Error on startup if backend memory limit is less than shared
+			 * memory size. Warn on startup if backend memory available is
+			 * less than arbitrarily picked value of 100MB.
+			 */
+
+			if (max_total_bkend_mem - result <= 0)
+			{
+				ereport(ERROR,
+						errmsg("configured max_total_backend_memory %dMB is <= shared_memory_size %dMB",
+							   max_total_bkend_mem, result),
+						errhint("Disable or increase the configuration parameter \"max_total_backend_memory\"."));
+			}
+			else if (max_total_bkend_mem - result <= 100)
+			{
+				ereport(WARNING,
+						errmsg("max_total_backend_memory %dMB - shared_memory_size %dMB is <= 100MB",
+							   max_total_bkend_mem, result),
+						errhint("Consider increasing the configuration parameter \"max_total_backend_memory\"."));
+			}
+
+			/*
+			 * Account for shared memory size and initialize
+			 * total_bkend_mem_bytes.
+			 */
+			pg_atomic_init_u64(&ProcGlobal->total_bkend_mem_bytes,
+							   (uint64) max_total_bkend_mem * 1024 * 1024 - (uint64) result * 1024 * 1024);
+		}
+		else
+			ereport(ERROR, errmsg("max_total_backend_memory initialization is unable to parse shared_memory_size"));
+	}
+
 	/*
 	 * Create and initialize all the PGPROC structures we'll need.  There are
 	 * five separate consumers: (1) normal backends, (2) autovacuum workers
diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c
index 25b545441b..c125dc3abb 100644
--- a/src/backend/utils/activity/backend_status.c
+++ b/src/backend/utils/activity/backend_status.c
@@ -44,6 +44,12 @@
 bool		pgstat_track_activities = false;
 int			pgstat_track_activity_query_size = 1024;
 
+/*
+ * Max backend memory allocation allowed (MB). 0 = disabled.
+ * Centralized bucket ProcGlobal->max_total_bkend_mem is initialized
+ * as a byte representation of this value in InitProcGlobal().
+ */
+int			max_total_bkend_mem = 0;
 
 /* exposed so that backend_progress.c can access it */
 PgBackendStatus *MyBEEntry = NULL;
@@ -67,6 +73,31 @@ uint64	   *my_generation_allocated_bytes = &local_my_generation_allocated_bytes;
 uint64		local_my_slab_allocated_bytes = 0;
 uint64	   *my_slab_allocated_bytes = &local_my_slab_allocated_bytes;
 
+/*
+ * Define initial allocation allowance for a backend.
+ *
+ * NOTE: initial_allocation_allowance && allocation_allowance_refill_qty
+ * may be candidates for future GUC variables. Arbitrary 1MB selected initially.
+ */
+uint64		initial_allocation_allowance = 1024 * 1024;
+uint64		allocation_allowance_refill_qty = 1024 * 1024;
+
+/*
+ * Local counter to manage shared memory allocations. At backend startup, set to
+ * initial_allocation_allowance via pgstat_init_allocated_bytes(). Decrease as
+ * memory is malloc'd. When exhausted, atomically refill if available from
+ * ProcGlobal->max_total_bkend_mem via exceeds_max_total_bkend_mem().
+ */
+uint64		allocation_allowance = 0;
+
+/*
+ * Local counter of free'd shared memory. Return to global
+ * max_total_bkend_mem when return threshold is met. Arbitrary 1MB bytes
+ * selected initially.
+ */
+uint64		allocation_return = 0;
+uint64		allocation_return_threshold = 1024 * 1024;
+
 static PgBackendStatus *BackendStatusArray = NULL;
 static char *BackendAppnameBuffer = NULL;
 static char *BackendClientHostnameBuffer = NULL;
@@ -1272,6 +1303,8 @@ pgstat_set_allocated_bytes_storage(uint64 *allocated_bytes,
 
 	my_slab_allocated_bytes = slab_allocated_bytes;
 	*slab_allocated_bytes = local_my_slab_allocated_bytes;
+
+	return;
 }
 
 /*
@@ -1295,6 +1328,23 @@ pgstat_reset_allocated_bytes_storage(void)
 								*my_dsm_allocated_bytes);
 	}
 
+	/*
+	 * When limiting maximum backend memory, return this backend's memory
+	 * allocations to global.
+	 */
+	if (max_total_bkend_mem)
+	{
+		volatile PROC_HDR *procglobal = ProcGlobal;
+
+		pg_atomic_add_fetch_u64(&procglobal->total_bkend_mem_bytes,
+								*my_allocated_bytes + allocation_allowance +
+								allocation_return);
+
+		/* Reset memory allocation variables */
+		allocation_allowance = 0;
+		allocation_return = 0;
+	}
+
 	/* Reset memory allocation variables */
 	*my_allocated_bytes = local_my_allocated_bytes = 0;
 	*my_aset_allocated_bytes = local_my_aset_allocated_bytes = 0;
@@ -1308,4 +1358,129 @@ pgstat_reset_allocated_bytes_storage(void)
 	my_dsm_allocated_bytes = &local_my_dsm_allocated_bytes;
 	my_generation_allocated_bytes = &local_my_generation_allocated_bytes;
 	my_slab_allocated_bytes = &local_my_slab_allocated_bytes;
+
+	return;
+}
+
+/*
+ * Determine if allocation request will exceed max backend memory allowed.
+ * Do not apply to auxiliary processes.
+ * Refill allocation request bucket when needed/possible.
+ */
+bool
+exceeds_max_total_bkend_mem(uint64 allocation_request)
+{
+	bool		result = false;
+
+	/*
+	 * When limiting maximum backend memory, attempt to refill allocation
+	 * request bucket if needed.
+	 */
+	if (max_total_bkend_mem && allocation_request > allocation_allowance &&
+		ProcGlobal != NULL)
+	{
+		volatile PROC_HDR *procglobal = ProcGlobal;
+		uint64		available_max_total_bkend_mem = 0;
+		bool		sts = false;
+
+		/*
+		 * If allocation request is larger than memory refill quantity then
+		 * attempt to increase allocation allowance with requested amount,
+		 * otherwise fall through. If this refill fails we do not have enough
+		 * memory to meet the request.
+		 */
+		if (allocation_request >= allocation_allowance_refill_qty)
+		{
+			while ((available_max_total_bkend_mem = pg_atomic_read_u64(&procglobal->total_bkend_mem_bytes)) >= allocation_request)
+			{
+				if ((result = pg_atomic_compare_exchange_u64(&procglobal->total_bkend_mem_bytes,
+															 &available_max_total_bkend_mem,
+															 available_max_total_bkend_mem - allocation_request)))
+				{
+					allocation_allowance = allocation_allowance + allocation_request;
+					break;
+				}
+			}
+
+			/*
+			 * Exclude auxiliary and Postmaster processes from the check.
+			 * Return false. While we want to exclude them from the check, we
+			 * do not want to exclude them from the above allocation handling.
+			 */
+			switch (MyBackendType)
+			{
+				case B_STARTUP:
+				case B_ARCHIVER:
+				case B_BG_WRITER:
+				case B_CHECKPOINTER:
+				case B_WAL_WRITER:
+				case B_WAL_RECEIVER:
+				case B_WAL_SUMMARIZER:
+					return false;
+				default:
+					break;
+			}
+
+			if (MyProcPid == PostmasterPid)
+				return false;
+
+			/*
+			 * If the atomic exchange fails (result == false), we do not have
+			 * enough reserve memory to meet the request. Negate result to
+			 * return the proper value.
+			 */
+
+			return !result;
+		}
+
+		/*
+		 * Attempt to increase allocation allowance by memory refill quantity.
+		 * If available memory is/becomes less than memory refill quantity,
+		 * fall through to attempt to allocate remaining available memory.
+		 */
+		while ((available_max_total_bkend_mem = pg_atomic_read_u64(&procglobal->total_bkend_mem_bytes)) >= allocation_allowance_refill_qty)
+		{
+			if ((sts = pg_atomic_compare_exchange_u64(&procglobal->total_bkend_mem_bytes,
+													  &available_max_total_bkend_mem,
+													  available_max_total_bkend_mem - allocation_allowance_refill_qty)))
+			{
+				allocation_allowance = allocation_allowance + allocation_allowance_refill_qty;
+				break;
+			}
+		}
+
+		/* Do not attempt to increase allocation if available memory is below
+		 * allocation_allowance_refill_qty .
+		 */
+
+		/*
+		 * If refill is not successful, we return true, memory limit exceeded
+		 */
+		if (!sts)
+			result = true;
+	}
+
+	/*
+	 * Exclude auxiliary and postmaster processes from the check. Return false.
+	 * While we want to exclude them from the check, we do not want to exclude
+	 * them from the above allocation handling.
+	 */
+	switch (MyBackendType)
+	{
+		case B_STARTUP:
+		case B_ARCHIVER:
+		case B_BG_WRITER:
+		case B_CHECKPOINTER:
+		case B_WAL_WRITER:
+		case B_WAL_RECEIVER:
+		case B_WAL_SUMMARIZER:
+			result = false;
+		default:
+			break;
+	}
+
+	if (MyProcPid == PostmasterPid)
+		result = false;
+
+	return result;
 }
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 9c82ec48cb..15d2800d5b 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -2093,7 +2093,7 @@ pg_stat_get_memory_allocation(PG_FUNCTION_ARGS)
 Datum
 pg_stat_get_global_memory_allocation(PG_FUNCTION_ARGS)
 {
-#define PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS	2
+#define PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS	3
 	TupleDesc	tupdesc;
 	Datum		values[PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS] = {0};
 	bool		nulls[PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS] = {0};
@@ -2103,15 +2103,23 @@ pg_stat_get_global_memory_allocation(PG_FUNCTION_ARGS)
 	tupdesc = CreateTemplateTupleDesc(PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 1, "datid",
 					   OIDOID, -1, 0);
-	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "global_dsm_allocated_bytes",
+	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "total_bkend_mem_bytes_available",
+					   INT8OID, -1, 0);
+	TupleDescInitEntry(tupdesc, (AttrNumber) 3, "global_dsm_allocated_bytes",
 					   INT8OID, -1, 0);
 	BlessTupleDesc(tupdesc);
 
 	/* datid */
 	values[0] = ObjectIdGetDatum(MyDatabaseId);
 
-	/* get global_dsm_allocated_bytes */
-	values[1] = Int64GetDatum(pg_atomic_read_u64(&procglobal->global_dsm_allocation));
+	/* Get total_bkend_mem_bytes - return -1 if disabled */
+	if (max_total_bkend_mem == 0)
+		values[1] = Int64GetDatum(-1);
+	else
+		values[1] = Int64GetDatum(pg_atomic_read_u64(&procglobal->total_bkend_mem_bytes));
+
+	/* Get global_dsm_allocated_bytes */
+	values[2] = Int64GetDatum(pg_atomic_read_u64(&procglobal->global_dsm_allocation));
 
 	/* Returns the record as Datum */
 	PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls)));
diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c
index a4152080b5..9450032a89 100644
--- a/src/backend/utils/hash/dynahash.c
+++ b/src/backend/utils/hash/dynahash.c
@@ -104,7 +104,6 @@
 #include "utils/dynahash.h"
 #include "utils/memutils.h"
 
-
 /*
  * Constants
  *
@@ -359,7 +358,6 @@ hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
 	Assert(flags & HASH_ELEM);
 	Assert(info->keysize > 0);
 	Assert(info->entrysize >= info->keysize);
-
 	/*
 	 * For shared hash tables, we have a local hash header (HTAB struct) that
 	 * we allocate in TopMemoryContext; all else is in shared memory.
@@ -377,6 +375,7 @@ hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
 	}
 	else
 	{
+		/* Set up to allocate the hash header */
 		/* Create the hash table's private memory context */
 		if (flags & HASH_CONTEXT)
 			CurrentDynaHashCxt = info->hcxt;
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index 9b47450813..d72ec3a0db 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -171,8 +171,16 @@ InitPostmasterChild(void)
 				 errmsg_internal("could not set postmaster death monitoring pipe to FD_CLOEXEC mode: %m")));
 #endif
 
+	/*
+	 * Init pgstat allocated bytes counters here for forked backends.
+	 * Fork/exec backends have not yet reattached to shared memory at this
+	 * point. They will init pgstat allocated bytes counters in
+	 * PGSharedMemoryReAttach.
+	 */
+#ifndef EXEC_BACKEND
 	/* Init allocated bytes to avoid double counting parent allocation */
 	pgstat_init_allocated_bytes();
+#endif
 }
 
 /*
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index d77214795d..56aca7d5bc 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -3626,6 +3626,17 @@ struct config_int ConfigureNamesInt[] =
 		NULL, NULL, NULL
 	},
 
+	{
+		{"max_total_backend_memory", PGC_SU_BACKEND, RESOURCES_MEM,
+			gettext_noop("Restrict total backend memory allocations to this max."),
+			gettext_noop("0 turns this feature off."),
+			GUC_UNIT_MB
+		},
+		&max_total_bkend_mem,
+		0, 0, INT_MAX,
+		NULL, NULL, NULL
+	},
+
 	/* End-of-list marker */
 	{
 		{NULL, 0, 0, NULL, NULL}, NULL, 0, 0, 0, NULL, NULL, NULL
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 2244ee52f7..50e2bb2bcf 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -169,6 +169,9 @@
 #vacuum_buffer_usage_limit = 256kB	# size of vacuum and analyze buffer access strategy ring;
 					# 0 to disable vacuum buffer access strategy;
 					# range 128kB to 16GB
+#max_total_backend_memory = 0MB		# Restrict total backend memory allocations
+									# to this max (in MB). 0 turns this feature
+									# off.
 
 # - Disk -
 
diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index a599a3a6e4..be56585853 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -438,6 +438,18 @@ AllocSetContextCreateInternal(MemoryContext parent,
 	else
 		firstBlockSize = Max(firstBlockSize, initBlockSize);
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (exceeds_max_total_bkend_mem(firstBlockSize))
+	{
+		if (TopMemoryContext)
+			MemoryContextStats(TopMemoryContext);
+		ereport(ERROR,
+				(errcode(ERRCODE_OUT_OF_MEMORY),
+				 errmsg("out of memory - exceeds max_total_backend_memory"),
+				 errdetail("Failed while creating memory context \"%s\".",
+						   name)));
+	}
+
 	/*
 	 * Allocate the initial block.  Unlike other aset.c blocks, it starts with
 	 * the context header and its block header follows that.
@@ -724,6 +736,11 @@ AllocSetAllocLarge(MemoryContext context, Size size, int flags)
 #endif
 
 	blksize = chunk_size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
+
+	/* Do not exceed maximum allowed memory allocation */
+	if (exceeds_max_total_bkend_mem(blksize))
+		return NULL;
+
 	block = (AllocBlock) malloc(blksize);
 	if (block == NULL)
 		return MemoryContextAllocationFailure(context, size, flags);
@@ -917,6 +934,10 @@ AllocSetAllocFromNewBlock(MemoryContext context, Size size, int flags,
 	while (blksize < required_size)
 		blksize <<= 1;
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (exceeds_max_total_bkend_mem(blksize))
+		return NULL;
+
 	/* Try to allocate it */
 	block = (AllocBlock) malloc(blksize);
 
@@ -1238,6 +1259,18 @@ AllocSetRealloc(void *pointer, Size size, int flags)
 		blksize = chksize + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
 		oldblksize = block->endptr - ((char *) block);
 
+		/*
+		 * Do not exceed maximum allowed memory allocation. NOTE: checking for
+		 * the full size here rather than just the amount of increased
+		 * allocation to prevent a potential underflow of *my_allocation
+		 * allowance in cases where blksize - oldblksize does not trigger a
+		 * refill but blksize is greater than *my_allocation_allowance.
+		 * Underflow would occur with the call below to
+		 * pgstat_report_allocated_bytes_increase()
+		 */
+		if (blksize > oldblksize && exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		block = (AllocBlock) realloc(block, blksize);
 		if (block == NULL)
 		{
diff --git a/src/backend/utils/mmgr/generation.c b/src/backend/utils/mmgr/generation.c
index d511b67b08..ea4dc2cb27 100644
--- a/src/backend/utils/mmgr/generation.c
+++ b/src/backend/utils/mmgr/generation.c
@@ -203,6 +203,16 @@ GenerationContextCreate(MemoryContext parent,
 	else
 		allocSize = Max(allocSize, initBlockSize);
 
+	if (exceeds_max_total_bkend_mem(allocSize))
+	{
+		MemoryContextStats(TopMemoryContext);
+		ereport(ERROR,
+				(errcode(ERRCODE_OUT_OF_MEMORY),
+				 errmsg("out of memory - exceeds max_total_backend_memory"),
+				 errdetail("Failed while creating memory context \"%s\".",
+						   name)));
+	}
+
 	/*
 	 * Allocate the initial block.  Unlike other generation.c blocks, it
 	 * starts with the context header and its block header follows that.
@@ -372,6 +382,9 @@ GenerationAllocLarge(MemoryContext context, Size size, int flags)
 	required_size = chunk_size + Generation_CHUNKHDRSZ;
 	blksize = required_size + Generation_BLOCKHDRSZ;
 
+	if (exceeds_max_total_bkend_mem(blksize))
+		return NULL;
+
 	block = (GenerationBlock *) malloc(blksize);
 	if (block == NULL)
 		return MemoryContextAllocationFailure(context, size, flags);
@@ -494,6 +507,9 @@ GenerationAllocFromNewBlock(MemoryContext context, Size size, int flags,
 	if (blksize < required_size)
 		blksize = pg_nextpower2_size_t(required_size);
 
+	if (exceeds_max_total_bkend_mem(blksize))
+		return NULL;
+
 	block = (GenerationBlock *) malloc(blksize);
 
 	if (block == NULL)
diff --git a/src/backend/utils/mmgr/slab.c b/src/backend/utils/mmgr/slab.c
index 98a8bbaf91..d0f80f10a2 100644
--- a/src/backend/utils/mmgr/slab.c
+++ b/src/backend/utils/mmgr/slab.c
@@ -360,7 +360,16 @@ SlabContextCreate(MemoryContext parent,
 		elog(ERROR, "block size %zu for slab is too small for %zu-byte chunks",
 			 blockSize, chunkSize);
 
-
+	/* Do not exceed maximum allowed memory allocation */
+	if (exceeds_max_total_bkend_mem(Slab_CONTEXT_HDRSZ(chunksPerBlock)))
+	{
+		MemoryContextStats(TopMemoryContext);
+		ereport(ERROR,
+				(errcode(ERRCODE_OUT_OF_MEMORY),
+				 errmsg("out of memory - exceeds max_total_backend_memory"),
+				 errdetail("Failed while creating memory context \"%s\".",
+						   name)));
+	}
 
 	slab = (SlabContext *) malloc(Slab_CONTEXT_HDRSZ(chunksPerBlock));
 	if (slab == NULL)
@@ -582,6 +591,10 @@ SlabAllocFromNewBlock(MemoryContext context, Size size, int flags)
 	}
 	else
 	{
+		/* Do not exceed maximum allowed memory allocation */
+		if (exceeds_max_total_bkend_mem(slab->blockSize))
+			return MemoryContextAllocationFailure(context, size, flags);
+
 		block = (SlabBlock *) malloc(slab->blockSize);
 
 		if (unlikely(block == NULL))
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 47903e755e..13f1c15b6d 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -5448,9 +5448,9 @@
   descr => 'statistics: global memory allocation information',
   proname => 'pg_stat_get_global_memory_allocation', proisstrict => 'f',
   provolatile => 's', proparallel => 'r', prorettype => 'record',
-  proargtypes => '', proallargtypes => '{oid,int8}',
-  proargmodes => '{o,o}',
-  proargnames => '{datid,global_dsm_allocated_bytes}',
+  proargtypes => '', proallargtypes => '{oid,int8,int8}',
+  proargmodes => '{o,o,o}',
+  proargnames => '{datid,total_bkend_mem_bytes_available,global_dsm_allocated_bytes}',
   prosrc =>'pg_stat_get_global_memory_allocation' },
 { oid => '2022',
   descr => 'statistics: information about currently active backends',
diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h
index a350f455cd..fa7c94c6c9 100644
--- a/src/include/storage/proc.h
+++ b/src/include/storage/proc.h
@@ -424,6 +424,13 @@ typedef struct PROC_HDR
 	int			startupBufferPinWaitBufId;
 	/* Global dsm allocations */
 	pg_atomic_uint64 global_dsm_allocation;
+
+	/*
+	 * Max backend memory allocation tracker. Used/Initialized when
+	 * max_total_bkend_mem > 0 as max_total_bkend_mem (MB) converted to bytes.
+	 * Decreases/increases with free/malloc of backend memory.
+	 */
+	pg_atomic_uint64 total_bkend_mem_bytes;
 } PROC_HDR;
 
 extern PGDLLIMPORT PROC_HDR *ProcGlobal;
diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h
index cbf801884d..a833941272 100644
--- a/src/include/utils/backend_status.h
+++ b/src/include/utils/backend_status.h
@@ -14,7 +14,7 @@
 #include "datatype/timestamp.h"
 #include "libpq/pqcomm.h"
 #include "miscadmin.h"			/* for BackendType */
-#include "storage/procnumber.h"
+#include "storage/proc.h"
 #include "utils/backend_progress.h"
 
 
@@ -303,6 +303,7 @@ typedef struct LocalPgBackendStatus
  */
 extern PGDLLIMPORT bool pgstat_track_activities;
 extern PGDLLIMPORT int pgstat_track_activity_query_size;
+extern PGDLLIMPORT int max_total_bkend_mem;
 
 
 /* ----------
@@ -315,6 +316,10 @@ extern PGDLLIMPORT uint64 *my_aset_allocated_bytes;
 extern PGDLLIMPORT uint64 *my_dsm_allocated_bytes;
 extern PGDLLIMPORT uint64 *my_generation_allocated_bytes;
 extern PGDLLIMPORT uint64 *my_slab_allocated_bytes;
+extern PGDLLIMPORT uint64 allocation_allowance;
+extern PGDLLIMPORT uint64 initial_allocation_allowance;
+extern PGDLLIMPORT uint64 allocation_return;
+extern PGDLLIMPORT uint64 allocation_return_threshold;
 
 
 /* ----------
@@ -363,6 +368,7 @@ extern PgBackendStatus *pgstat_get_beentry_by_proc_number(ProcNumber procNumber)
 extern LocalPgBackendStatus *pgstat_get_local_beentry_by_proc_number(ProcNumber procNumber);
 extern LocalPgBackendStatus *pgstat_get_local_beentry_by_index(int idx);
 extern char *pgstat_clip_activity(const char *raw_activity);
+extern bool exceeds_max_total_bkend_mem(uint64 allocation_request);
 
 /* ----------
  * pgstat_report_allocated_bytes_decrease() -
@@ -378,7 +384,7 @@ pgstat_report_allocated_bytes_decrease(int64 proc_allocated_bytes,
 {
 	uint64		temp;
 
-	/* Avoid allocated_bytes unsigned integer overflow on decrease */
+	/* Sanity check: my allocated bytes should never drop below zero */
 	if (pg_sub_u64_overflow(*my_allocated_bytes, proc_allocated_bytes, &temp))
 	{
 		/* On overflow, set allocated bytes and allocator type bytes to zero */
@@ -387,13 +393,35 @@ pgstat_report_allocated_bytes_decrease(int64 proc_allocated_bytes,
 		*my_dsm_allocated_bytes = 0;
 		*my_generation_allocated_bytes = 0;
 		*my_slab_allocated_bytes = 0;
+
+		/* Add freed memory to allocation return counter. */
+		allocation_return += proc_allocated_bytes;
+
+		/*
+		 * Return freed memory to the global counter if return threshold is
+		 * met.
+		 */
+		if (max_total_bkend_mem && allocation_return >= allocation_return_threshold)
+		{
+			if (ProcGlobal)
+			{
+				volatile PROC_HDR *procglobal = ProcGlobal;
+
+				/* Add to global tracker */
+				pg_atomic_add_fetch_u64(&procglobal->total_bkend_mem_bytes,
+										allocation_return);
+
+				/* Restart the count */
+				allocation_return = 0;
+			}
+		}
 	}
 	else
 	{
-		/* decrease allocation */
-		*my_allocated_bytes -= proc_allocated_bytes;
+		/* Add freed memory to allocation return counter */
+		allocation_return += proc_allocated_bytes;
 
-		/* Decrease allocator type allocated bytes. */
+		/* Decrease allocator type allocated bytes */
 		switch (pg_allocator_type)
 		{
 			case PG_ALLOC_ASET:
@@ -415,6 +443,30 @@ pgstat_report_allocated_bytes_decrease(int64 proc_allocated_bytes,
 				*my_slab_allocated_bytes -= proc_allocated_bytes;
 				break;
 		}
+
+		/* decrease allocation */
+		*my_allocated_bytes = *my_aset_allocated_bytes +
+			*my_dsm_allocated_bytes + *my_generation_allocated_bytes +
+			*my_slab_allocated_bytes;
+
+		/*
+		 * Return freed memory to the global counter if return threshold is
+		 * met.
+		 */
+		if (max_total_bkend_mem && allocation_return >= allocation_return_threshold)
+		{
+			if (ProcGlobal)
+			{
+				volatile PROC_HDR *procglobal = ProcGlobal;
+
+				/* Add to global tracker */
+				pg_atomic_add_fetch_u64(&procglobal->total_bkend_mem_bytes,
+										allocation_return);
+
+				/* Restart the count */
+				allocation_return = 0;
+			}
+		}
 	}
 
 	return;
@@ -432,7 +484,13 @@ static inline void
 pgstat_report_allocated_bytes_increase(int64 proc_allocated_bytes,
 									   int pg_allocator_type)
 {
-	*my_allocated_bytes += proc_allocated_bytes;
+	uint64		temp;
+
+	/* Sanity check: my allocated bytes should never drop below zero */
+	if (pg_sub_u64_overflow(allocation_allowance, proc_allocated_bytes, &temp))
+		allocation_allowance = 0;
+	else
+		allocation_allowance -= proc_allocated_bytes;
 
 	/* Increase allocator type allocated bytes */
 	switch (pg_allocator_type)
@@ -457,6 +515,9 @@ pgstat_report_allocated_bytes_increase(int64 proc_allocated_bytes,
 			break;
 	}
 
+	*my_allocated_bytes = *my_aset_allocated_bytes + *my_dsm_allocated_bytes +
+		*my_generation_allocated_bytes + *my_slab_allocated_bytes;
+
 	return;
 }
 
@@ -476,6 +537,36 @@ pgstat_init_allocated_bytes(void)
 	*my_generation_allocated_bytes = 0;
 	*my_slab_allocated_bytes = 0;
 
+	/* If we're limiting backend memory */
+	if (max_total_bkend_mem)
+	{
+		volatile PROC_HDR *procglobal = ProcGlobal;
+		uint64		available_max_total_bkend_mem = 0;
+
+		allocation_return = 0;
+		allocation_allowance = 0;
+
+		/* Account for the initial allocation allowance */
+		while ((available_max_total_bkend_mem = pg_atomic_read_u64(&procglobal->total_bkend_mem_bytes)) >= initial_allocation_allowance)
+		{
+			/*
+			 * On success populate allocation_allowance. Failure here will
+			 * result in the backend's first invocation of
+			 * exceeds_max_total_bkend_mem allocating requested, default, or
+			 * available memory or result in an out of memory error.
+			 */
+			if (pg_atomic_compare_exchange_u64(&procglobal->total_bkend_mem_bytes,
+											   &available_max_total_bkend_mem,
+											   available_max_total_bkend_mem -
+											   initial_allocation_allowance))
+			{
+				allocation_allowance = initial_allocation_allowance;
+
+				break;
+			}
+		}
+	}
+
 	return;
 }
 
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index 2f62f5e4ea..01dee8ddea 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1887,13 +1887,15 @@ pg_stat_global_memory_allocation| WITH sums AS (
  SELECT s.datid,
     current_setting('shared_memory_size'::text, true) AS shared_memory_size,
     (current_setting('shared_memory_size_in_huge_pages'::text, true))::integer AS shared_memory_size_in_huge_pages,
+    pg_size_bytes(current_setting('max_total_backend_memory'::text, true)) AS max_total_backend_memory_bytes,
+    s.total_bkend_mem_bytes_available,
     s.global_dsm_allocated_bytes,
     sums.total_aset_allocated_bytes,
     sums.total_dsm_allocated_bytes,
     sums.total_generation_allocated_bytes,
     sums.total_slab_allocated_bytes
    FROM sums,
-    (pg_stat_get_global_memory_allocation() s(datid, global_dsm_allocated_bytes)
+    (pg_stat_get_global_memory_allocation() s(datid, total_bkend_mem_bytes_available, global_dsm_allocated_bytes)
      LEFT JOIN pg_database d ON ((s.datid = d.oid)));
 pg_stat_gssapi| SELECT pid,
     gss_auth AS gss_authenticated,
-- 
2.43.2

#58Anton A. Melnikov
a.melnikov@postgrespro.ru
In reply to: Anton A. Melnikov (#57)
2 attachment(s)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On 13.03.2024 10:41, Anton A. Melnikov wrote:

Here is a version updated for the current master.

During patch updating i mistakenly added double counting of deallocatated blocks.
That's why the tests in the patch tester failed.
Fixed it and squashed fix 0002 with 0001.
Here is fixed version.

With the best wishes!

--
Anton A. Melnikov
Postgres Professional: http://www.postgrespro.com
The Russian Postgres Company

Attachments:

v20240314-0001-Add-tracking-of-backend-memory-allocated.patchtext/x-patch; charset=UTF-8; name=v20240314-0001-Add-tracking-of-backend-memory-allocated.patchDownload
From 7a0925a38acfb9a945087318a5d91fae4680db0e Mon Sep 17 00:00:00 2001
From: Tomas Vondra <tomas@2ndquadrant.com>
Date: Tue, 26 Dec 2023 17:54:40 +0100
Subject: [PATCH 1/2] Add tracking of backend memory allocated

Add tracking of backend memory allocated in total and by allocation
type (aset, dsm, generation, slab) by process.

allocated_bytes tracks the current bytes of memory allocated to the
backend process. aset_allocated_bytes, dsm_allocated_bytes,
generation_allocated_bytes and slab_allocated_bytes track the
allocation by type for the backend process. They are updated for the
process as memory is malloc'd/freed.  Memory allocated to items on
the freelist is included.  Dynamic shared memory allocations are
included only in the value displayed for the backend that created
them, they are not included in the value for backends that are
attached to them to avoid double counting. DSM allocations that are
not destroyed by the creating process prior to it's exit are
considered long lived and are tracked in a global counter
global_dsm_allocated_bytes. We limit the floor of allocation
counters to zero. Created views pg_stat_global_memory_allocation and
pg_stat_memory_allocation for access to these trackers.
---
 doc/src/sgml/monitoring.sgml                | 246 ++++++++++++++++++++
 src/backend/catalog/system_views.sql        |  34 +++
 src/backend/storage/ipc/dsm.c               |  11 +-
 src/backend/storage/ipc/dsm_impl.c          |  78 +++++++
 src/backend/storage/lmgr/proc.c             |   1 +
 src/backend/utils/activity/backend_status.c | 114 +++++++++
 src/backend/utils/adt/pgstatfuncs.c         |  84 +++++++
 src/backend/utils/init/miscinit.c           |   3 +
 src/backend/utils/mmgr/aset.c               |  17 ++
 src/backend/utils/mmgr/generation.c         |  13 ++
 src/backend/utils/mmgr/slab.c               |  22 ++
 src/include/catalog/pg_proc.dat             |  17 ++
 src/include/storage/proc.h                  |   2 +
 src/include/utils/backend_status.h          | 144 +++++++++++-
 src/test/regress/expected/rules.out         |  27 +++
 src/test/regress/expected/stats.out         |  36 +++
 src/test/regress/sql/stats.sql              |  20 ++
 17 files changed, 867 insertions(+), 2 deletions(-)

diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 8736eac284..41d788be45 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -4599,6 +4599,252 @@ description | Waiting for a newly initialized WAL file to reach durable storage
 
  </sect2>
 
+ <sect2 id="monitoring-pg-stat-memory-allocation-view">
+  <title><structname>pg_stat_memory_allocation</structname></title>
+
+  <indexterm>
+   <primary>pg_stat_memory_allocation</primary>
+  </indexterm>
+
+  <para>
+   The <structname>pg_stat_memory_allocation</structname> view will have one
+   row per server process, showing information related to the current memory
+   allocation of that process in total and by allocator type. Due to the
+   dynamic nature of memory allocations the allocated bytes values may not be
+   exact but should be sufficient for the intended purposes. Dynamic shared
+   memory allocations are included only in the value displayed for the backend
+   that created them, they are not included in the value for backends that are
+   attached to them to avoid double counting.  Use
+   <function>pg_size_pretty</function> described in
+   <xref linkend="functions-admin-dbsize"/> to make these values more easily
+   readable.
+  </para>
+
+  <table id="pg-stat-memory-allocation-view" xreflabel="pg_stat_memory_allocation">
+   <title><structname>pg_stat_memory_allocation</structname> View</title>
+   <tgroup cols="1">
+    <thead>
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       Column Type
+      </para>
+      <para>
+       Description
+      </para></entry>
+     </row>
+    </thead>
+
+    <tbody>
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>datid</structfield> <type>oid</type>
+      </para>
+      <para>
+       OID of the database this backend is connected to
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>pid</structfield> <type>integer</type>
+      </para>
+      <para>
+       Process ID of this backend
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>allocated_bytes</structfield> <type>bigint</type>
+      </para>
+     <para>
+      Memory currently allocated to this backend in bytes. This is the balance
+      of bytes allocated and freed by this backend. Dynamic shared memory
+      allocations are included only in the value displayed for the backend that
+      created them, they are not included in the value for backends that are
+      attached to them to avoid double counting.
+     </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>aset_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Memory currently allocated to this backend in bytes via the allocation
+       set allocator.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>dsm_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Memory currently allocated to this backend in bytes via the dynamic
+       shared memory allocator. Upon process exit, dsm allocations that have
+       not been freed are considered long lived and added to
+       <structfield>global_dsm_allocated_bytes</structfield> found in the
+       <link linkend="monitoring-pg-stat-global-memory-allocation-view">
+       <structname>pg_stat_global_memory_allocation</structname></link> view.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>generation_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Memory currently allocated to this backend in bytes via the generation
+       allocator.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>slab_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Memory currently allocated to this backend in bytes via the slab
+       allocator.
+      </para></entry>
+     </row>
+
+    </tbody>
+   </tgroup>
+  </table>
+
+ </sect2>
+
+ <sect2 id="monitoring-pg-stat-global-memory-allocation-view">
+  <title><structname>pg_stat_global_memory_allocation</structname></title>
+
+  <indexterm>
+   <primary>pg_stat_global-memory_allocation</primary>
+  </indexterm>
+
+  <para>
+   The <structname>pg_stat_global_memory_allocation</structname> view will
+   have one row showing information related to current shared memory
+   allocations. Due to the dynamic nature of memory allocations the allocated
+   bytes values may not be exact but should be sufficient for the intended
+   purposes. Use <function>pg_size_pretty</function> described in
+   <xref linkend="functions-admin-dbsize"/> to make the byte populated values
+   more easily readable.
+  </para>
+
+  <table id="pg-stat-global-memory-allocation-view" xreflabel="pg_stat_global_memory_allocation">
+   <title><structname>pg_stat_global_memory_allocation</structname> View</title>
+   <tgroup cols="1">
+    <thead>
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       Column Type
+      </para>
+      <para>
+       Description
+      </para></entry>
+     </row>
+    </thead>
+
+    <tbody>
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>datid</structfield> <type>oid</type>
+      </para>
+      <para>
+       OID of the database this backend is connected to
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>shared_memory_size_mb</structfield> <type>integer</type>
+      </para>
+      <para>
+       Reports the size of the main shared memory area, rounded up to the
+       nearest megabyte. See <xref linkend="guc-shared-memory-size"/>.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>shared_memory_size_in_huge_pages</structfield> <type>bigint</type>
+      </para>
+     <para>
+      Reports the number of huge pages that are needed for the main shared
+      memory area based on the specified huge_page_size. If huge pages are not
+      supported, this will be -1. See
+      <xref linkend="guc-shared-memory-size-in-huge-pages"/>.
+     </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>global_dsm_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Long lived dynamically allocated memory currently allocated to the
+       database. Upon process exit, dsm allocations that have not been freed
+       are considered long lived and added to
+       <structfield>global_dsm_allocated_bytes</structfield>.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>total_aset_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Sum total of <structfield>aset_allocated_bytes</structfield> for all
+       backend processes from
+       <link linkend="monitoring-pg-stat-memory-allocation-view">
+       <structname>pg_stat_memory_allocation</structname></link> view.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>total_dsm_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Sum total of <structfield>dsm_allocated_bytes</structfield> for all
+       backend processes from
+       <link linkend="monitoring-pg-stat-memory-allocation-view">
+       <structname>pg_stat_memory_allocation</structname></link> view.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>total_generation_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Sum total of <structfield>generation_allocated_bytes</structfield> for
+       all backend processes from
+       <link linkend="monitoring-pg-stat-memory-allocation-view">
+       <structname>pg_stat_memory_allocation</structname></link> view.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>total_slab_allocated_bytes</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Sum total of <structfield>slab_allocated_bytes</structfield> for all
+       backend processes from
+       <link linkend="monitoring-pg-stat-memory-allocation-view">
+       <structname>pg_stat_memory_allocation</structname></link> view.
+      </para></entry>
+     </row>
+
+    </tbody>
+   </tgroup>
+  </table>
+
+ </sect2>
+
  <sect2 id="monitoring-stats-functions">
   <title>Statistics Functions</title>
 
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 04227a72d1..61ff4a59b6 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -1375,3 +1375,37 @@ CREATE VIEW pg_stat_subscription_stats AS
 
 CREATE VIEW pg_wait_events AS
     SELECT * FROM pg_get_wait_events();
+
+CREATE VIEW pg_stat_memory_allocation AS
+    SELECT
+        S.datid AS datid,
+        S.pid,
+        S.allocated_bytes,
+        S.aset_allocated_bytes,
+        S.dsm_allocated_bytes,
+        S.generation_allocated_bytes,
+        S.slab_allocated_bytes
+    FROM pg_stat_get_memory_allocation(NULL) AS S
+        LEFT JOIN pg_database AS D ON (S.datid = D.oid);
+
+CREATE VIEW pg_stat_global_memory_allocation AS
+WITH sums AS (
+    SELECT
+        SUM(aset_allocated_bytes) AS total_aset_allocated_bytes,
+        SUM(dsm_allocated_bytes) AS total_dsm_allocated_bytes,
+        SUM(generation_allocated_bytes) AS total_generation_allocated_bytes,
+        SUM(slab_allocated_bytes) AS total_slab_allocated_bytes
+    FROM
+        pg_stat_memory_allocation
+)
+SELECT
+        S.datid AS datid,
+        current_setting('shared_memory_size', true) as shared_memory_size,
+        (current_setting('shared_memory_size_in_huge_pages', true))::integer as shared_memory_size_in_huge_pages,
+        S.global_dsm_allocated_bytes,
+        sums.total_aset_allocated_bytes,
+        sums.total_dsm_allocated_bytes,
+        sums.total_generation_allocated_bytes,
+        sums.total_slab_allocated_bytes
+    FROM sums, pg_stat_get_global_memory_allocation() AS S
+        LEFT JOIN pg_database AS D ON (S.datid = D.oid);
diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c
index c2e33a7e43..b950640643 100644
--- a/src/backend/storage/ipc/dsm.c
+++ b/src/backend/storage/ipc/dsm.c
@@ -802,6 +802,15 @@ dsm_detach_all(void)
 void
 dsm_detach(dsm_segment *seg)
 {
+	/*
+	 * Retain mapped_size to pass into destroy call in cases where the detach
+	 * is the last reference. mapped_size is zeroed as part of the detach
+	 * process, but is needed later in these cases for dsm_allocated_bytes
+	 * accounting.
+	 */
+	Size		local_seg_mapped_size = seg->mapped_size;
+	Size	   *ptr_local_seg_mapped_size = &local_seg_mapped_size;
+
 	/*
 	 * Invoke registered callbacks.  Just in case one of those callbacks
 	 * throws a further error that brings us back here, pop the callback
@@ -882,7 +891,7 @@ dsm_detach(dsm_segment *seg)
 			 */
 			if (is_main_region_dsm_handle(seg->handle) ||
 				dsm_impl_op(DSM_OP_DESTROY, seg->handle, 0, &seg->impl_private,
-							&seg->mapped_address, &seg->mapped_size, WARNING))
+							&seg->mapped_address, ptr_local_seg_mapped_size, WARNING))
 			{
 				LWLockAcquire(DynamicSharedMemoryControlLock, LW_EXCLUSIVE);
 				if (is_main_region_dsm_handle(seg->handle))
diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c
index 8dd669e0ce..af67e55bdf 100644
--- a/src/backend/storage/ipc/dsm_impl.c
+++ b/src/backend/storage/ipc/dsm_impl.c
@@ -66,6 +66,7 @@
 #include "postmaster/postmaster.h"
 #include "storage/dsm_impl.h"
 #include "storage/fd.h"
+#include "utils/backend_status.h"
 #include "utils/guc.h"
 #include "utils/memutils.h"
 
@@ -232,6 +233,14 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_allocated_bytes_decrease(*mapped_size, PG_ALLOC_DSM);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && shm_unlink(name) != 0)
@@ -332,6 +341,33 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+	{
+		/*
+		 * Posix creation calls dsm_impl_posix_resize implying that resizing
+		 * occurs or may be added in the future. As implemented
+		 * dsm_impl_posix_resize utilizes fallocate or truncate, passing the
+		 * whole new size as input, growing the allocation as needed (only
+		 * truncate supports shrinking). We update by replacing the old
+		 * allocation with the new.
+		 */
+#if defined(HAVE_POSIX_FALLOCATE) && defined(__linux__)
+		/*
+		 * posix_fallocate does not shrink allocations, adjust only on
+		 * allocation increase.
+		 */
+		if (request_size > *mapped_size)
+			pgstat_report_allocated_bytes_increase(request_size - *mapped_size, PG_ALLOC_DSM);
+#else
+		pgstat_report_allocated_bytes_decrease(*mapped_size, PG_ALLOC_DSM);
+		pgstat_report_allocated_bytes_increase(request_size, PG_ALLOC_DSM);
+#endif
+	}
 	*mapped_address = address;
 	*mapped_size = request_size;
 	close(fd);
@@ -538,6 +574,14 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_allocated_bytes_decrease(*mapped_size, PG_ALLOC_DSM);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && shmctl(ident, IPC_RMID, NULL) < 0)
@@ -585,6 +629,13 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_allocated_bytes_increase(request_size, PG_ALLOC_DSM);
 	*mapped_address = address;
 	*mapped_size = request_size;
 
@@ -653,6 +704,13 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 			return false;
 		}
 
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		if (op == DSM_OP_DESTROY)
+			pgstat_report_allocated_bytes_decrease(*mapped_size, PG_ALLOC_DSM);
 		*impl_private = NULL;
 		*mapped_address = NULL;
 		*mapped_size = 0;
@@ -769,6 +827,12 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 		return false;
 	}
 
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_allocated_bytes_increase(info.RegionSize, PG_ALLOC_DSM);
 	*mapped_address = address;
 	*mapped_size = info.RegionSize;
 	*impl_private = hmap;
@@ -813,6 +877,13 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size,
 							name)));
 			return false;
 		}
+
+		/*
+		 * Detach and destroy pass through here, only decrease the memory
+		 * shown allocated in pg_stat_activity when the creator destroys the
+		 * allocation.
+		 */
+		pgstat_report_allocated_bytes_decrease(*mapped_size, PG_ALLOC_DSM);
 		*mapped_address = NULL;
 		*mapped_size = 0;
 		if (op == DSM_OP_DESTROY && unlink(name) != 0)
@@ -934,6 +1005,13 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size,
 						name)));
 		return false;
 	}
+
+	/*
+	 * Attach and create pass through here, only update backend memory
+	 * allocated in pg_stat_activity for the creator process.
+	 */
+	if (op == DSM_OP_CREATE)
+		pgstat_report_allocated_bytes_increase(request_size, PG_ALLOC_DSM);
 	*mapped_address = address;
 	*mapped_size = request_size;
 
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index f3e20038f4..1959b5f4e6 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -180,6 +180,7 @@ InitProcGlobal(void)
 	ProcGlobal->checkpointerLatch = NULL;
 	pg_atomic_init_u32(&ProcGlobal->procArrayGroupFirst, INVALID_PROC_NUMBER);
 	pg_atomic_init_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER);
+	pg_atomic_init_u64(&ProcGlobal->global_dsm_allocation, 0);
 
 	/*
 	 * Create and initialize all the PGPROC structures we'll need.  There are
diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c
index 1ccf4c6d83..25b545441b 100644
--- a/src/backend/utils/activity/backend_status.c
+++ b/src/backend/utils/activity/backend_status.c
@@ -48,6 +48,24 @@ int			pgstat_track_activity_query_size = 1024;
 /* exposed so that backend_progress.c can access it */
 PgBackendStatus *MyBEEntry = NULL;
 
+/*
+ * Memory allocated to this backend prior to pgstats initialization. Migrated to
+ * shared memory on pgstats initialization.
+ */
+uint64		local_my_allocated_bytes = 0;
+uint64	   *my_allocated_bytes = &local_my_allocated_bytes;
+
+/* Memory allocated to this backend by type prior to pgstats initialization.
+ * Migrated to shared memory on pgstats initialization
+ */
+uint64		local_my_aset_allocated_bytes = 0;
+uint64	   *my_aset_allocated_bytes = &local_my_aset_allocated_bytes;
+uint64		local_my_dsm_allocated_bytes = 0;
+uint64	   *my_dsm_allocated_bytes = &local_my_dsm_allocated_bytes;
+uint64		local_my_generation_allocated_bytes = 0;
+uint64	   *my_generation_allocated_bytes = &local_my_generation_allocated_bytes;
+uint64		local_my_slab_allocated_bytes = 0;
+uint64	   *my_slab_allocated_bytes = &local_my_slab_allocated_bytes;
 
 static PgBackendStatus *BackendStatusArray = NULL;
 static char *BackendAppnameBuffer = NULL;
@@ -382,6 +400,32 @@ pgstat_bestart(void)
 	lbeentry.st_progress_command_target = InvalidOid;
 	lbeentry.st_query_id = UINT64CONST(0);
 
+	/* Alter allocation reporting from local storage to shared memory */
+	pgstat_set_allocated_bytes_storage(&MyBEEntry->allocated_bytes,
+									   &MyBEEntry->aset_allocated_bytes,
+									   &MyBEEntry->dsm_allocated_bytes,
+									   &MyBEEntry->generation_allocated_bytes,
+									   &MyBEEntry->slab_allocated_bytes);
+
+	/*
+	 * Populate sum of memory allocated prior to pgstats initialization to
+	 * pgstats and zero the local variable. This is a += assignment because
+	 * InitPostgres allocates memory after pgstat_beinit but prior to
+	 * pgstat_bestart so we have allocations to both local and shared memory
+	 * to combine.
+	 */
+	lbeentry.allocated_bytes += local_my_allocated_bytes;
+	local_my_allocated_bytes = 0;
+	lbeentry.aset_allocated_bytes += local_my_aset_allocated_bytes;
+	local_my_aset_allocated_bytes = 0;
+
+	lbeentry.dsm_allocated_bytes += local_my_dsm_allocated_bytes;
+	local_my_dsm_allocated_bytes = 0;
+	lbeentry.generation_allocated_bytes += local_my_generation_allocated_bytes;
+	local_my_generation_allocated_bytes = 0;
+	lbeentry.slab_allocated_bytes += local_my_slab_allocated_bytes;
+	local_my_slab_allocated_bytes = 0;
+
 	/*
 	 * we don't zero st_progress_param here to save cycles; nobody should
 	 * examine it until st_progress_command has been set to something other
@@ -441,6 +485,9 @@ pgstat_beshutdown_hook(int code, Datum arg)
 {
 	volatile PgBackendStatus *beentry = MyBEEntry;
 
+	/* Stop reporting memory allocation changes to shared memory */
+	pgstat_reset_allocated_bytes_storage();
+
 	/*
 	 * Clear my status entry, following the protocol of bumping st_changecount
 	 * before and after.  We use a volatile pointer here to ensure the
@@ -1195,3 +1242,70 @@ pgstat_clip_activity(const char *raw_activity)
 
 	return activity;
 }
+
+/*
+ * Configure bytes allocated reporting to report allocated bytes to
+ * shared memory.
+ *
+ * Expected to be called during backend startup (in pgstat_bestart), to point
+ * allocated bytes accounting into shared memory.
+ */
+void
+pgstat_set_allocated_bytes_storage(uint64 *allocated_bytes,
+								   uint64 *aset_allocated_bytes,
+								   uint64 *dsm_allocated_bytes,
+								   uint64 *generation_allocated_bytes,
+								   uint64 *slab_allocated_bytes)
+{
+	/* Map allocations to shared memory */
+	my_allocated_bytes = allocated_bytes;
+	*allocated_bytes = local_my_allocated_bytes;
+
+	my_aset_allocated_bytes = aset_allocated_bytes;
+	*aset_allocated_bytes = local_my_aset_allocated_bytes;
+
+	my_dsm_allocated_bytes = dsm_allocated_bytes;
+	*dsm_allocated_bytes = local_my_dsm_allocated_bytes;
+
+	my_generation_allocated_bytes = generation_allocated_bytes;
+	*generation_allocated_bytes = local_my_generation_allocated_bytes;
+
+	my_slab_allocated_bytes = slab_allocated_bytes;
+	*slab_allocated_bytes = local_my_slab_allocated_bytes;
+}
+
+/*
+ * Reset allocated bytes storage location.
+ *
+ * Expected to be called during backend shutdown, before the locations set up
+ * by pgstat_set_allocated_bytes_storage become invalid.
+ */
+void
+pgstat_reset_allocated_bytes_storage(void)
+{
+	if (ProcGlobal)
+	{
+		volatile PROC_HDR *procglobal = ProcGlobal;
+
+		/*
+		 * Add dsm allocations that have not been freed to global dsm
+		 * accounting
+		 */
+		pg_atomic_add_fetch_u64(&procglobal->global_dsm_allocation,
+								*my_dsm_allocated_bytes);
+	}
+
+	/* Reset memory allocation variables */
+	*my_allocated_bytes = local_my_allocated_bytes = 0;
+	*my_aset_allocated_bytes = local_my_aset_allocated_bytes = 0;
+	*my_dsm_allocated_bytes = local_my_dsm_allocated_bytes = 0;
+	*my_generation_allocated_bytes = local_my_generation_allocated_bytes = 0;
+	*my_slab_allocated_bytes = local_my_slab_allocated_bytes = 0;
+
+	/* Point my_{*_}allocated_bytes from shared memory back to local */
+	my_allocated_bytes = &local_my_allocated_bytes;
+	my_aset_allocated_bytes = &local_my_aset_allocated_bytes;
+	my_dsm_allocated_bytes = &local_my_dsm_allocated_bytes;
+	my_generation_allocated_bytes = &local_my_generation_allocated_bytes;
+	my_slab_allocated_bytes = &local_my_slab_allocated_bytes;
+}
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 3876339ee1..9c82ec48cb 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -2032,3 +2032,87 @@ pg_stat_have_stats(PG_FUNCTION_ARGS)
 
 	PG_RETURN_BOOL(pgstat_have_entry(kind, dboid, objoid));
 }
+
+/*
+ * Get the memory allocation of PG backends.
+ */
+Datum
+pg_stat_get_memory_allocation(PG_FUNCTION_ARGS)
+{
+#define PG_STAT_GET_MEMORY_ALLOCATION_COLS	7
+	int			num_backends = pgstat_fetch_stat_numbackends();
+	int			curr_backend;
+	int			pid = PG_ARGISNULL(0) ? -1 : PG_GETARG_INT32(0);
+	ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
+
+	InitMaterializedSRF(fcinfo, 0);
+
+	/* 1-based index */
+	for (curr_backend = 1; curr_backend <= num_backends; curr_backend++)
+	{
+		/* for each row */
+		Datum		values[PG_STAT_GET_MEMORY_ALLOCATION_COLS] = {0};
+		bool		nulls[PG_STAT_GET_MEMORY_ALLOCATION_COLS] = {0};
+		LocalPgBackendStatus *local_beentry;
+		PgBackendStatus *beentry;
+
+		/* Get the next one in the list */
+		local_beentry = pgstat_get_local_beentry_by_index(curr_backend);
+		beentry = &local_beentry->backendStatus;
+
+		/* If looking for specific PID, ignore all the others */
+		if (pid != -1 && beentry->st_procpid != pid)
+			continue;
+
+		/* Values available to all callers */
+		if (beentry->st_databaseid != InvalidOid)
+			values[0] = ObjectIdGetDatum(beentry->st_databaseid);
+		else
+			nulls[0] = true;
+
+		values[1] = Int32GetDatum(beentry->st_procpid);
+		values[2] = UInt64GetDatum(beentry->allocated_bytes);
+		values[3] = UInt64GetDatum(beentry->aset_allocated_bytes);
+		values[4] = UInt64GetDatum(beentry->dsm_allocated_bytes);
+		values[5] = UInt64GetDatum(beentry->generation_allocated_bytes);
+		values[6] = UInt64GetDatum(beentry->slab_allocated_bytes);
+
+		tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
+
+		/* If only a single backend was requested, and we found it, break. */
+		if (pid != -1)
+			break;
+	}
+
+	return (Datum) 0;
+}
+
+/*
+ * Get the global memory allocation statistics.
+ */
+Datum
+pg_stat_get_global_memory_allocation(PG_FUNCTION_ARGS)
+{
+#define PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS	2
+	TupleDesc	tupdesc;
+	Datum		values[PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS] = {0};
+	bool		nulls[PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS] = {0};
+	volatile PROC_HDR *procglobal = ProcGlobal;
+
+	/* Initialise attributes information in the tuple descriptor */
+	tupdesc = CreateTemplateTupleDesc(PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS);
+	TupleDescInitEntry(tupdesc, (AttrNumber) 1, "datid",
+					   OIDOID, -1, 0);
+	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "global_dsm_allocated_bytes",
+					   INT8OID, -1, 0);
+	BlessTupleDesc(tupdesc);
+
+	/* datid */
+	values[0] = ObjectIdGetDatum(MyDatabaseId);
+
+	/* get global_dsm_allocated_bytes */
+	values[1] = Int64GetDatum(pg_atomic_read_u64(&procglobal->global_dsm_allocation));
+
+	/* Returns the record as Datum */
+	PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls)));
+}
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index 537d92c0cf..9b47450813 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -170,6 +170,9 @@ InitPostmasterChild(void)
 				(errcode_for_socket_access(),
 				 errmsg_internal("could not set postmaster death monitoring pipe to FD_CLOEXEC mode: %m")));
 #endif
+
+	/* Init allocated bytes to avoid double counting parent allocation */
+	pgstat_init_allocated_bytes();
 }
 
 /*
diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index 751cc3408c..cd074add17 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -47,6 +47,7 @@
 #include "postgres.h"
 
 #include "port/pg_bitutils.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_internal.h"
@@ -517,6 +518,7 @@ AllocSetContextCreateInternal(MemoryContext parent,
 						name);
 
 	((MemoryContext) set)->mem_allocated = firstBlockSize;
+	pgstat_report_allocated_bytes_increase(firstBlockSize, PG_ALLOC_ASET);
 
 	return (MemoryContext) set;
 }
@@ -539,6 +541,7 @@ AllocSetReset(MemoryContext context)
 	AllocSet	set = (AllocSet) context;
 	AllocBlock	block;
 	Size		keepersize PG_USED_FOR_ASSERTS_ONLY;
+	uint64		deallocation = 0;
 
 	Assert(AllocSetIsValid(set));
 
@@ -581,6 +584,7 @@ AllocSetReset(MemoryContext context)
 		{
 			/* Normal case, release the block */
 			context->mem_allocated -= block->endptr - ((char *) block);
+			deallocation += block->endptr - ((char *) block);
 
 #ifdef CLOBBER_FREED_MEMORY
 			wipe_mem(block, block->freeptr - ((char *) block));
@@ -591,6 +595,7 @@ AllocSetReset(MemoryContext context)
 	}
 
 	Assert(context->mem_allocated == keepersize);
+	pgstat_report_allocated_bytes_decrease(deallocation, PG_ALLOC_ASET);
 
 	/* Reset block size allocation sequence, too */
 	set->nextBlockSize = set->initBlockSize;
@@ -609,6 +614,7 @@ AllocSetDelete(MemoryContext context)
 	AllocSet	set = (AllocSet) context;
 	AllocBlock	block = set->blocks;
 	Size		keepersize PG_USED_FOR_ASSERTS_ONLY;
+	uint64		deallocation = 0;
 
 	Assert(AllocSetIsValid(set));
 
@@ -647,11 +653,13 @@ AllocSetDelete(MemoryContext context)
 
 				freelist->first_free = (AllocSetContext *) oldset->header.nextchild;
 				freelist->num_free--;
+				deallocation += oldset->header.mem_allocated;
 
 				/* All that remains is to free the header/initial block */
 				free(oldset);
 			}
 			Assert(freelist->num_free == 0);
+			pgstat_report_allocated_bytes_decrease(deallocation, PG_ALLOC_ASET);
 		}
 
 		/* Now add the just-deleted context to the freelist. */
@@ -668,7 +676,10 @@ AllocSetDelete(MemoryContext context)
 		AllocBlock	next = block->next;
 
 		if (!IsKeeperBlock(set, block))
+		{
 			context->mem_allocated -= block->endptr - ((char *) block);
+			deallocation += block->endptr - ((char *) block);
+		}
 
 #ifdef CLOBBER_FREED_MEMORY
 		wipe_mem(block, block->freeptr - ((char *) block));
@@ -681,6 +692,7 @@ AllocSetDelete(MemoryContext context)
 	}
 
 	Assert(context->mem_allocated == keepersize);
+	pgstat_report_allocated_bytes_decrease(deallocation + context->mem_allocated, PG_ALLOC_ASET);
 
 	/* Finally, free the context header, including the keeper block */
 	free(set);
@@ -717,6 +729,7 @@ AllocSetAllocLarge(MemoryContext context, Size size, int flags)
 		return MemoryContextAllocationFailure(context, size, flags);
 
 	context->mem_allocated += blksize;
+	pgstat_report_allocated_bytes_increase(blksize, PG_ALLOC_ASET);
 
 	block->aset = set;
 	block->freeptr = block->endptr = ((char *) block) + blksize;
@@ -923,6 +936,7 @@ AllocSetAllocFromNewBlock(MemoryContext context, Size size, int flags,
 		return MemoryContextAllocationFailure(context, size, flags);
 
 	context->mem_allocated += blksize;
+	pgstat_report_allocated_bytes_increase(blksize, PG_ALLOC_ASET);
 
 	block->aset = set;
 	block->freeptr = ((char *) block) + ALLOC_BLOCKHDRSZ;
@@ -1100,6 +1114,7 @@ AllocSetFree(void *pointer)
 			block->next->prev = block->prev;
 
 		set->header.mem_allocated -= block->endptr - ((char *) block);
+		pgstat_report_allocated_bytes_decrease(block->endptr - ((char *) block), PG_ALLOC_ASET);
 
 #ifdef CLOBBER_FREED_MEMORY
 		wipe_mem(block, block->freeptr - ((char *) block));
@@ -1233,7 +1248,9 @@ AllocSetRealloc(void *pointer, Size size, int flags)
 
 		/* updated separately, not to underflow when (oldblksize > blksize) */
 		set->header.mem_allocated -= oldblksize;
+		pgstat_report_allocated_bytes_decrease(oldblksize, PG_ALLOC_ASET);
 		set->header.mem_allocated += blksize;
+		pgstat_report_allocated_bytes_increase(blksize, PG_ALLOC_ASET);
 
 		block->freeptr = block->endptr = ((char *) block) + blksize;
 
diff --git a/src/backend/utils/mmgr/generation.c b/src/backend/utils/mmgr/generation.c
index 5d81af1f94..dbea4f248e 100644
--- a/src/backend/utils/mmgr/generation.c
+++ b/src/backend/utils/mmgr/generation.c
@@ -37,6 +37,7 @@
 
 #include "lib/ilist.h"
 #include "port/pg_bitutils.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_internal.h"
@@ -266,6 +267,7 @@ GenerationContextCreate(MemoryContext parent,
 						name);
 
 	((MemoryContext) set)->mem_allocated = firstBlockSize;
+	pgstat_report_allocated_bytes_increase(firstBlockSize, PG_ALLOC_GENERATION);
 
 	return (MemoryContext) set;
 }
@@ -284,6 +286,7 @@ GenerationReset(MemoryContext context)
 {
 	GenerationContext *set = (GenerationContext *) context;
 	dlist_mutable_iter miter;
+	uint64		deallocation = 0;
 
 	Assert(GenerationIsValid(set));
 
@@ -306,9 +309,14 @@ GenerationReset(MemoryContext context)
 		if (IsKeeperBlock(set, block))
 			GenerationBlockMarkEmpty(block);
 		else
+		{
+			deallocation += block->blksize;
 			GenerationBlockFree(set, block);
+		}
 	}
 
+	pgstat_report_allocated_bytes_decrease(deallocation, PG_ALLOC_GENERATION);
+
 	/* set it so new allocations to make use of the keeper block */
 	set->block = KeeperBlock(set);
 
@@ -329,6 +337,9 @@ GenerationDelete(MemoryContext context)
 {
 	/* Reset to release all releasable GenerationBlocks */
 	GenerationReset(context);
+
+	pgstat_report_allocated_bytes_decrease(context->mem_allocated, PG_ALLOC_GENERATION);
+
 	/* And free the context header and keeper block */
 	free(context);
 }
@@ -366,6 +377,7 @@ GenerationAllocLarge(MemoryContext context, Size size, int flags)
 		return MemoryContextAllocationFailure(context, size, flags);
 
 	context->mem_allocated += blksize;
+	pgstat_report_allocated_bytes_increase(blksize, PG_ALLOC_GENERATION);
 
 	/* block with a single (used) chunk */
 	block->context = set;
@@ -488,6 +500,7 @@ GenerationAllocFromNewBlock(MemoryContext context, Size size, int flags,
 		return MemoryContextAllocationFailure(context, size, flags);
 
 	context->mem_allocated += blksize;
+	pgstat_report_allocated_bytes_increase(blksize, PG_ALLOC_GENERATION);
 
 	/* initialize the new block */
 	GenerationBlockInit(set, block, blksize);
diff --git a/src/backend/utils/mmgr/slab.c b/src/backend/utils/mmgr/slab.c
index 3e15d59683..850760f485 100644
--- a/src/backend/utils/mmgr/slab.c
+++ b/src/backend/utils/mmgr/slab.c
@@ -69,6 +69,7 @@
 #include "postgres.h"
 
 #include "lib/ilist.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_internal.h"
@@ -417,6 +418,13 @@ SlabContextCreate(MemoryContext parent,
 						parent,
 						name);
 
+	/*
+	 * If SlabContextCreate is updated to add context header size to
+	 * context->mem_allocated, then update here and SlabDelete appropriately
+	 */
+	pgstat_report_allocated_bytes_increase(Slab_CONTEXT_HDRSZ(slab->chunksPerBlock),
+										   PG_ALLOC_SLAB);
+
 	return (MemoryContext) slab;
 }
 
@@ -433,6 +441,7 @@ SlabReset(MemoryContext context)
 	SlabContext *slab = (SlabContext *) context;
 	dlist_mutable_iter miter;
 	int			i;
+	uint64		deallocation = 0;
 
 	Assert(SlabIsValid(slab));
 
@@ -453,6 +462,7 @@ SlabReset(MemoryContext context)
 #endif
 		free(block);
 		context->mem_allocated -= slab->blockSize;
+		deallocation += slab->blockSize;
 	}
 
 	/* walk over blocklist and free the blocks */
@@ -469,9 +479,11 @@ SlabReset(MemoryContext context)
 #endif
 			free(block);
 			context->mem_allocated -= slab->blockSize;
+			deallocation += slab->blockSize;
 		}
 	}
 
+	pgstat_report_allocated_bytes_decrease(deallocation, PG_ALLOC_SLAB);
 	slab->curBlocklistIndex = 0;
 
 	Assert(context->mem_allocated == 0);
@@ -486,6 +498,14 @@ SlabDelete(MemoryContext context)
 {
 	/* Reset to release all the SlabBlocks */
 	SlabReset(context);
+
+	/*
+	 * Until context header allocation is included in context->mem_allocated,
+	 * cast to slab and decrement the header allocation
+	 */
+	pgstat_report_allocated_bytes_decrease(Slab_CONTEXT_HDRSZ(((SlabContext *) context)->chunksPerBlock),
+										   PG_ALLOC_SLAB);
+
 	/* And free the context header */
 	free(context);
 }
@@ -569,6 +589,7 @@ SlabAllocFromNewBlock(MemoryContext context, Size size, int flags)
 
 		block->slab = slab;
 		context->mem_allocated += slab->blockSize;
+		pgstat_report_allocated_bytes_increase(slab->blockSize, PG_ALLOC_SLAB);
 
 		/* use the first chunk in the new block */
 		chunk = SlabBlockGetChunk(slab, block, 0);
@@ -797,6 +818,7 @@ SlabFree(void *pointer)
 #endif
 			free(block);
 			slab->header.mem_allocated -= slab->blockSize;
+			pgstat_report_allocated_bytes_decrease(slab->blockSize, PG_ALLOC_SLAB);
 		}
 
 		/*
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4af5c2e847..56ab1f9470 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -5435,6 +5435,23 @@
   proname => 'pg_stat_get_backend_idset', prorows => '100', proretset => 't',
   provolatile => 's', proparallel => 'r', prorettype => 'int4',
   proargtypes => '', prosrc => 'pg_stat_get_backend_idset' },
+{ oid => '9890',
+  descr => 'statistics: memory allocation information for backends',
+  proname => 'pg_stat_get_memory_allocation', prorows => '100', proisstrict => 'f',
+  proretset => 't', provolatile => 's', proparallel => 'r',
+  prorettype => 'record', proargtypes => 'int4',
+  proallargtypes => '{int4,oid,int4,int8,int8,int8,int8,int8}',
+  proargmodes => '{i,o,o,o,o,o,o,o}',
+  proargnames => '{pid,datid,pid,allocated_bytes,aset_allocated_bytes,dsm_allocated_bytes,generation_allocated_bytes,slab_allocated_bytes}',
+  prosrc => 'pg_stat_get_memory_allocation' },
+{ oid => '9891',
+  descr => 'statistics: global memory allocation information',
+  proname => 'pg_stat_get_global_memory_allocation', proisstrict => 'f',
+  provolatile => 's', proparallel => 'r', prorettype => 'record',
+  proargtypes => '', proallargtypes => '{oid,int8}',
+  proargmodes => '{o,o}',
+  proargnames => '{datid,global_dsm_allocated_bytes}',
+  prosrc =>'pg_stat_get_global_memory_allocation' },
 { oid => '2022',
   descr => 'statistics: information about currently active backends',
   proname => 'pg_stat_get_activity', prorows => '100', proisstrict => 'f',
diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h
index 1095aefddf..a350f455cd 100644
--- a/src/include/storage/proc.h
+++ b/src/include/storage/proc.h
@@ -422,6 +422,8 @@ typedef struct PROC_HDR
 	int			spins_per_delay;
 	/* Buffer id of the buffer that Startup process waits for pin on, or -1 */
 	int			startupBufferPinWaitBufId;
+	/* Global dsm allocations */
+	pg_atomic_uint64 global_dsm_allocation;
 } PROC_HDR;
 
 extern PGDLLIMPORT PROC_HDR *ProcGlobal;
diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h
index 7b7f6f59d0..cbf801884d 100644
--- a/src/include/utils/backend_status.h
+++ b/src/include/utils/backend_status.h
@@ -10,6 +10,7 @@
 #ifndef BACKEND_STATUS_H
 #define BACKEND_STATUS_H
 
+#include "common/int.h"
 #include "datatype/timestamp.h"
 #include "libpq/pqcomm.h"
 #include "miscadmin.h"			/* for BackendType */
@@ -32,6 +33,14 @@ typedef enum BackendState
 	STATE_DISABLED,
 } BackendState;
 
+/* Enum helper for reporting memory allocator type */
+enum pg_allocator_type
+{
+	PG_ALLOC_ASET = 1,
+	PG_ALLOC_DSM,
+	PG_ALLOC_GENERATION,
+	PG_ALLOC_SLAB
+};
 
 /* ----------
  * Shared-memory data structures
@@ -170,6 +179,15 @@ typedef struct PgBackendStatus
 
 	/* query identifier, optionally computed using post_parse_analyze_hook */
 	uint64		st_query_id;
+
+	/* Current memory allocated to this backend */
+	uint64		allocated_bytes;
+
+	/* Current memory allocated to this backend by type */
+	uint64		aset_allocated_bytes;
+	uint64		dsm_allocated_bytes;
+	uint64		generation_allocated_bytes;
+	uint64		slab_allocated_bytes;
 } PgBackendStatus;
 
 
@@ -292,6 +310,11 @@ extern PGDLLIMPORT int pgstat_track_activity_query_size;
  * ----------
  */
 extern PGDLLIMPORT PgBackendStatus *MyBEEntry;
+extern PGDLLIMPORT uint64 *my_allocated_bytes;
+extern PGDLLIMPORT uint64 *my_aset_allocated_bytes;
+extern PGDLLIMPORT uint64 *my_dsm_allocated_bytes;
+extern PGDLLIMPORT uint64 *my_generation_allocated_bytes;
+extern PGDLLIMPORT uint64 *my_slab_allocated_bytes;
 
 
 /* ----------
@@ -323,7 +346,12 @@ extern const char *pgstat_get_backend_current_activity(int pid, bool checkUser);
 extern const char *pgstat_get_crashed_backend_activity(int pid, char *buffer,
 													   int buflen);
 extern uint64 pgstat_get_my_query_id(void);
-
+extern void pgstat_set_allocated_bytes_storage(uint64 *allocated_bytes,
+											   uint64 *aset_allocated_bytes,
+											   uint64 *dsm_allocated_bytes,
+											   uint64 *generation_allocated_bytes,
+											   uint64 *slab_allocated_bytes);
+extern void pgstat_reset_allocated_bytes_storage(void);
 
 /* ----------
  * Support functions for the SQL-callable functions to
@@ -336,5 +364,119 @@ extern LocalPgBackendStatus *pgstat_get_local_beentry_by_proc_number(ProcNumber
 extern LocalPgBackendStatus *pgstat_get_local_beentry_by_index(int idx);
 extern char *pgstat_clip_activity(const char *raw_activity);
 
+/* ----------
+ * pgstat_report_allocated_bytes_decrease() -
+ *  Called to report decrease in memory allocated for this backend.
+ *
+ * my_{*_}allocated_bytes initially points to local memory, making it safe to
+ * call this before pgstats has been initialized.
+ * ----------
+ */
+static inline void
+pgstat_report_allocated_bytes_decrease(int64 proc_allocated_bytes,
+									   int pg_allocator_type)
+{
+	uint64		temp;
+
+	/* Avoid allocated_bytes unsigned integer overflow on decrease */
+	if (pg_sub_u64_overflow(*my_allocated_bytes, proc_allocated_bytes, &temp))
+	{
+		/* On overflow, set allocated bytes and allocator type bytes to zero */
+		*my_allocated_bytes = 0;
+		*my_aset_allocated_bytes = 0;
+		*my_dsm_allocated_bytes = 0;
+		*my_generation_allocated_bytes = 0;
+		*my_slab_allocated_bytes = 0;
+	}
+	else
+	{
+		/* decrease allocation */
+		*my_allocated_bytes -= proc_allocated_bytes;
+
+		/* Decrease allocator type allocated bytes. */
+		switch (pg_allocator_type)
+		{
+			case PG_ALLOC_ASET:
+				*my_aset_allocated_bytes -= proc_allocated_bytes;
+				break;
+			case PG_ALLOC_DSM:
+
+				/*
+				 * Some dsm allocations live beyond process exit. These are
+				 * accounted for in a global counter in
+				 * pgstat_reset_allocated_bytes_storage at process exit.
+				 */
+				*my_dsm_allocated_bytes -= proc_allocated_bytes;
+				break;
+			case PG_ALLOC_GENERATION:
+				*my_generation_allocated_bytes -= proc_allocated_bytes;
+				break;
+			case PG_ALLOC_SLAB:
+				*my_slab_allocated_bytes -= proc_allocated_bytes;
+				break;
+		}
+	}
+
+	return;
+}
+
+/* ----------
+ * pgstat_report_allocated_bytes_increase() -
+ *  Called to report increase in memory allocated for this backend.
+ *
+ * my_allocated_bytes initially points to local memory, making it safe to call
+ * this before pgstats has been initialized.
+ * ----------
+ */
+static inline void
+pgstat_report_allocated_bytes_increase(int64 proc_allocated_bytes,
+									   int pg_allocator_type)
+{
+	*my_allocated_bytes += proc_allocated_bytes;
+
+	/* Increase allocator type allocated bytes */
+	switch (pg_allocator_type)
+	{
+		case PG_ALLOC_ASET:
+			*my_aset_allocated_bytes += proc_allocated_bytes;
+			break;
+		case PG_ALLOC_DSM:
+
+			/*
+			 * Some dsm allocations live beyond process exit. These are
+			 * accounted for in a global counter in
+			 * pgstat_reset_allocated_bytes_storage at process exit.
+			 */
+			*my_dsm_allocated_bytes += proc_allocated_bytes;
+			break;
+		case PG_ALLOC_GENERATION:
+			*my_generation_allocated_bytes += proc_allocated_bytes;
+			break;
+		case PG_ALLOC_SLAB:
+			*my_slab_allocated_bytes += proc_allocated_bytes;
+			break;
+	}
+
+	return;
+}
+
+/* ---------
+ * pgstat_init_allocated_bytes() -
+ *
+ * Called to initialize allocated bytes variables after fork and to
+ * avoid double counting allocations.
+ * ---------
+ */
+static inline void
+pgstat_init_allocated_bytes(void)
+{
+	*my_allocated_bytes = 0;
+	*my_aset_allocated_bytes = 0;
+	*my_dsm_allocated_bytes = 0;
+	*my_generation_allocated_bytes = 0;
+	*my_slab_allocated_bytes = 0;
+
+	return;
+}
 
 #endif							/* BACKEND_STATUS_H */
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index 0cd2c64fca..2f62f5e4ea 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1877,6 +1877,24 @@ pg_stat_database_conflicts| SELECT oid AS datid,
     pg_stat_get_db_conflict_startup_deadlock(oid) AS confl_deadlock,
     pg_stat_get_db_conflict_logicalslot(oid) AS confl_active_logicalslot
    FROM pg_database d;
+pg_stat_global_memory_allocation| WITH sums AS (
+         SELECT sum(pg_stat_memory_allocation.aset_allocated_bytes) AS total_aset_allocated_bytes,
+            sum(pg_stat_memory_allocation.dsm_allocated_bytes) AS total_dsm_allocated_bytes,
+            sum(pg_stat_memory_allocation.generation_allocated_bytes) AS total_generation_allocated_bytes,
+            sum(pg_stat_memory_allocation.slab_allocated_bytes) AS total_slab_allocated_bytes
+           FROM pg_stat_memory_allocation
+        )
+ SELECT s.datid,
+    current_setting('shared_memory_size'::text, true) AS shared_memory_size,
+    (current_setting('shared_memory_size_in_huge_pages'::text, true))::integer AS shared_memory_size_in_huge_pages,
+    s.global_dsm_allocated_bytes,
+    sums.total_aset_allocated_bytes,
+    sums.total_dsm_allocated_bytes,
+    sums.total_generation_allocated_bytes,
+    sums.total_slab_allocated_bytes
+   FROM sums,
+    (pg_stat_get_global_memory_allocation() s(datid, global_dsm_allocated_bytes)
+     LEFT JOIN pg_database d ON ((s.datid = d.oid)));
 pg_stat_gssapi| SELECT pid,
     gss_auth AS gss_authenticated,
     gss_princ AS principal,
@@ -1903,6 +1921,15 @@ pg_stat_io| SELECT backend_type,
     fsync_time,
     stats_reset
    FROM pg_stat_get_io() b(backend_type, object, context, reads, read_time, writes, write_time, writebacks, writeback_time, extends, extend_time, op_bytes, hits, evictions, reuses, fsyncs, fsync_time, stats_reset);
+pg_stat_memory_allocation| SELECT s.datid,
+    s.pid,
+    s.allocated_bytes,
+    s.aset_allocated_bytes,
+    s.dsm_allocated_bytes,
+    s.generation_allocated_bytes,
+    s.slab_allocated_bytes
+   FROM (pg_stat_get_memory_allocation(NULL::integer) s(datid, pid, allocated_bytes, aset_allocated_bytes, dsm_allocated_bytes, generation_allocated_bytes, slab_allocated_bytes)
+     LEFT JOIN pg_database d ON ((s.datid = d.oid)));
 pg_stat_progress_analyze| SELECT s.pid,
     s.datid,
     d.datname,
diff --git a/src/test/regress/expected/stats.out b/src/test/regress/expected/stats.out
index 6e08898b18..902d827998 100644
--- a/src/test/regress/expected/stats.out
+++ b/src/test/regress/expected/stats.out
@@ -1646,4 +1646,40 @@ SELECT COUNT(*) FROM brin_hot_3 WHERE a = 2;
 
 DROP TABLE brin_hot_3;
 SET enable_seqscan = on;
+-- ensure that allocated_bytes exist for backends
+SELECT
+    allocated_bytes > 0 AS result
+FROM
+    pg_stat_activity ps
+    JOIN pg_stat_memory_allocation pa ON (pa.pid = ps.pid)
+WHERE
+    backend_type IN ('checkpointer', 'background writer', 'walwriter', 'autovacuum launcher');
+ result 
+--------
+ t
+ t
+ t
+ t
+(4 rows)
+
+-- ensure that pg_stat_global_memory_allocation view exists
+SELECT
+    datid > 0, pg_size_bytes(shared_memory_size) >= 0, shared_memory_size_in_huge_pages >= -1, global_dsm_allocated_bytes >= 0
+FROM
+    pg_stat_global_memory_allocation;
+ ?column? | ?column? | ?column? | ?column? 
+----------+----------+----------+----------
+ t        | t        | t        | t
+(1 row)
+
+-- ensure that pg_stat_memory_allocation view exists
+SELECT
+    pid > 0, allocated_bytes >= 0, aset_allocated_bytes >= 0, dsm_allocated_bytes >= 0, generation_allocated_bytes >= 0, slab_allocated_bytes >= 0
+FROM
+    pg_stat_memory_allocation limit 1;
+ ?column? | ?column? | ?column? | ?column? | ?column? | ?column? 
+----------+----------+----------+----------+----------+----------
+ t        | t        | t        | t        | t        | t
+(1 row)
+
 -- End of Stats Test
diff --git a/src/test/regress/sql/stats.sql b/src/test/regress/sql/stats.sql
index d8ac0d06f4..40746c9258 100644
--- a/src/test/regress/sql/stats.sql
+++ b/src/test/regress/sql/stats.sql
@@ -849,4 +849,24 @@ DROP TABLE brin_hot_3;
 
 SET enable_seqscan = on;
 
+-- ensure that allocated_bytes exist for backends
+SELECT
+    allocated_bytes > 0 AS result
+FROM
+    pg_stat_activity ps
+    JOIN pg_stat_memory_allocation pa ON (pa.pid = ps.pid)
+WHERE
+    backend_type IN ('checkpointer', 'background writer', 'walwriter', 'autovacuum launcher');
+
+-- ensure that pg_stat_global_memory_allocation view exists
+SELECT
+    datid > 0, pg_size_bytes(shared_memory_size) >= 0, shared_memory_size_in_huge_pages >= -1, global_dsm_allocated_bytes >= 0
+FROM
+    pg_stat_global_memory_allocation;
+
+-- ensure that pg_stat_memory_allocation view exists
+SELECT
+    pid > 0, allocated_bytes >= 0, aset_allocated_bytes >= 0, dsm_allocated_bytes >= 0, generation_allocated_bytes >= 0, slab_allocated_bytes >= 0
+FROM
+    pg_stat_memory_allocation limit 1;
 -- End of Stats Test
-- 
2.43.2

v20240314-0002-Add-the-ability-to-limit-the-amount-of-memory-that-c.patchtext/x-patch; charset=UTF-8; name=v20240314-0002-Add-the-ability-to-limit-the-amount-of-memory-that-c.patchDownload
From 72656bfa6819990be79bf925e5e888168aeb71a4 Mon Sep 17 00:00:00 2001
From: Tomas Vondra <tomas@2ndquadrant.com>
Date: Tue, 26 Dec 2023 17:55:23 +0100
Subject: [PATCH 2/2] Add the ability to limit the amount of memory that can be
 allocated to backends.

This builds on the work that adds backend memory allocated tracking.

Add GUC variable max_total_backend_memory.

Specifies a limit to the amount of memory (in MB) that may be allocated to
backends in total (i.e. this is not a per user or per backend limit). If unset,
or set to 0 it is disabled. It is intended as a resource to help avoid the OOM
killer on LINUX and manage resources in general. A backend request that would
exhaust max_total_backend_memory memory will be denied with an out of memory
error causing that backend's current query/transaction to fail.  Further
requests will not be allocated until dropping below the limit. Keep this in
mind when setting this value. Due to the dynamic nature of memory allocations,
this limit is not exact. This limit does not affect auxiliary backend
processes. Backend memory allocations are displayed in the
pg_stat_memory_allocation and pg_stat_global_memory_allocation views.
---
 doc/src/sgml/config.sgml                      |  30 +++
 doc/src/sgml/monitoring.sgml                  |  38 +++-
 src/backend/catalog/system_views.sql          |   2 +
 src/backend/port/sysv_shmem.c                 |   9 +
 src/backend/postmaster/postmaster.c           |   5 +
 src/backend/storage/ipc/dsm_impl.c            |  18 ++
 src/backend/storage/lmgr/proc.c               |  45 +++++
 src/backend/utils/activity/backend_status.c   | 175 ++++++++++++++++++
 src/backend/utils/adt/pgstatfuncs.c           |  16 +-
 src/backend/utils/hash/dynahash.c             |   3 +-
 src/backend/utils/init/miscinit.c             |   8 +
 src/backend/utils/misc/guc_tables.c           |  11 ++
 src/backend/utils/misc/postgresql.conf.sample |   3 +
 src/backend/utils/mmgr/aset.c                 |  33 ++++
 src/backend/utils/mmgr/generation.c           |  16 ++
 src/backend/utils/mmgr/slab.c                 |  15 +-
 src/include/catalog/pg_proc.dat               |   6 +-
 src/include/storage/proc.h                    |   7 +
 src/include/utils/backend_status.h            | 103 ++++++++++-
 src/test/regress/expected/rules.out           |   4 +-
 20 files changed, 526 insertions(+), 21 deletions(-)

diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 65a6e6c408..4f26284ee1 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -2306,6 +2306,36 @@ include_dir 'conf.d'
       </listitem>
      </varlistentry>
 
+     <varlistentry id="guc-max-total-backend-memory" xreflabel="max_total_backend_memory">
+      <term><varname>max_total_backend_memory</varname> (<type>integer</type>)
+      <indexterm>
+       <primary><varname>max_total_backend_memory</varname> configuration parameter</primary>
+      </indexterm>
+      </term>
+      <listitem>
+       <para>
+        Specifies a limit to the amount of memory (MB) that may be allocated to
+        backends in total (i.e. this is not a per user or per backend limit).
+        If unset, or set to 0 it is disabled.  At databse startup
+        max_total_backend_memory is reduced by shared_memory_size_mb
+        (includes shared buffers and other memory required for initialization).
+        Each backend process is intialized with a 1MB local allowance which
+        also reduces total_bkend_mem_bytes_available. Keep this in mind when
+        setting this value. A backend request that would exhaust the limit will
+        be denied with an out of memory error causing that backend's current
+        query/transaction to fail. Further requests will not be allocated until
+        dropping below the limit.  This limit does not affect auxiliary backend
+        processes
+        <xref linkend="glossary-auxiliary-proc"/> or the postmaster process.
+        Backend memory allocations (<varname>allocated_bytes</varname>) are
+        displayed in the
+        <link linkend="monitoring-pg-stat-memory-allocation-view"><structname>pg_stat_memory_allocation</structname></link>
+        view.  Due to the dynamic nature of memory allocations, this limit is
+        not exact.
+       </para>
+      </listitem>
+     </varlistentry>
+
      </variablelist>
      </sect2>
 
diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 41d788be45..3c3689c03b 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -4659,10 +4659,7 @@ description | Waiting for a newly initialized WAL file to reach durable storage
       </para>
      <para>
       Memory currently allocated to this backend in bytes. This is the balance
-      of bytes allocated and freed by this backend. Dynamic shared memory
-      allocations are included only in the value displayed for the backend that
-      created them, they are not included in the value for backends that are
-      attached to them to avoid double counting.
+      of bytes allocated and freed by this backend.
      </para></entry>
      </row>
 
@@ -4779,6 +4776,39 @@ description | Waiting for a newly initialized WAL file to reach durable storage
      </para></entry>
      </row>
 
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>max_total_backend_memory_bytes</structfield> <type>bigint</type>
+      </para>
+     <para>
+      Reports the user defined backend maximum allowed shared memory in bytes.
+      0 if disabled or not set. See
+      <xref linkend="guc-max-total-backend-memory"/>.
+     </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>total_bkend_mem_bytes_available</structfield> <type>bigint</type>
+      </para>
+     <para>
+      Tracks max_total_backend_memory (in bytes) available for allocation. At
+      database startup, total_bkend_mem_bytes_available is reduced by the
+      byte equivalent of shared_memory_size_mb. Each backend process is
+      intialized with a 1MB local allowance which also reduces
+      total_bkend_mem_bytes_available. A process's allocation requests reduce
+      it's local allowance. If a process's allocation request exceeds it's
+      remaining allowance, an attempt is made to refill the local allowance
+      from total_bkend_mem_bytes_available. If the refill request fails, then
+      the requesting process will fail with an out of memory error resulting
+      in the cancellation of that process's active query/transaction.  The
+      default refill allocation quantity is 1MB.  If a request is greater than
+      1MB, an attempt will be made to allocate the full amount. If
+      max_total_backend_memory is disabled, this will be -1.
+      <xref linkend="guc-max-total-backend-memory"/>.
+     </para></entry>
+     </row>
+
      <row>
       <entry role="catalog_table_entry"><para role="column_definition">
        <structfield>global_dsm_allocated_bytes</structfield> <type>bigint</type>
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 61ff4a59b6..c646b28f16 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -1402,6 +1402,8 @@ SELECT
         S.datid AS datid,
         current_setting('shared_memory_size', true) as shared_memory_size,
         (current_setting('shared_memory_size_in_huge_pages', true))::integer as shared_memory_size_in_huge_pages,
+        pg_size_bytes(current_setting('max_total_backend_memory', true)) as max_total_backend_memory_bytes,
+        S.total_bkend_mem_bytes_available,
         S.global_dsm_allocated_bytes,
         sums.total_aset_allocated_bytes,
         sums.total_dsm_allocated_bytes,
diff --git a/src/backend/port/sysv_shmem.c b/src/backend/port/sysv_shmem.c
index 1a6d8fa0fb..c0788732df 100644
--- a/src/backend/port/sysv_shmem.c
+++ b/src/backend/port/sysv_shmem.c
@@ -34,6 +34,7 @@
 #include "storage/fd.h"
 #include "storage/ipc.h"
 #include "storage/pg_shmem.h"
+#include "utils/backend_status.h"
 #include "utils/guc.h"
 #include "utils/guc_hooks.h"
 #include "utils/pidfile.h"
@@ -918,6 +919,14 @@ PGSharedMemoryReAttach(void)
 	dsm_set_control_handle(hdr->dsm_control);
 
 	UsedShmemSegAddr = hdr;		/* probably redundant */
+
+	/*
+	 * Init allocated bytes to avoid double counting parent allocation for
+	 * fork/exec processes. Forked processes perform this action in
+	 * InitPostmasterChild. For EXEC_BACKEND processes we have to wait for
+	 * shared memory to be reattached.
+	 */
+	pgstat_init_allocated_bytes();
 }
 
 /*
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 49fc6f979e..abb10ed7c8 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -556,6 +556,7 @@ typedef struct
 #endif
 	char		my_exec_path[MAXPGPATH];
 	char		pkglib_path[MAXPGPATH];
+	int			max_total_bkend_mem;
 } BackendParameters;
 
 static void read_backend_variables(char *id, ClientSocket **client_sock, BackgroundWorker **worker);
@@ -6152,6 +6153,8 @@ save_backend_variables(BackendParameters *param, ClientSocket *client_sock, Back
 
 	strlcpy(param->pkglib_path, pkglib_path, MAXPGPATH);
 
+	param->max_total_bkend_mem = max_total_bkend_mem;
+
 	return true;
 }
 
@@ -6391,6 +6394,8 @@ restore_backend_variables(BackendParameters *param, ClientSocket **client_sock,
 
 	strlcpy(pkglib_path, param->pkglib_path, MAXPGPATH);
 
+	max_total_bkend_mem = param->max_total_bkend_mem;
+
 	/*
 	 * We need to restore fd.c's counts of externally-opened FDs; to avoid
 	 * confusion, be sure to do this after restoring max_safe_fds.  (Note:
diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c
index af67e55bdf..b6dee75423 100644
--- a/src/backend/storage/ipc/dsm_impl.c
+++ b/src/backend/storage/ipc/dsm_impl.c
@@ -254,6 +254,16 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 		return true;
 	}
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+	{
+		ereport(elevel,
+				(errcode_for_dynamic_shared_memory(),
+				 errmsg("out of memory for segment \"%s\" - exceeds max_total_backend_memory: %m",
+						name)));
+		return false;
+	}
+
 	/*
 	 * Create new segment or open an existing one for attach.
 	 *
@@ -523,6 +533,10 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size,
 		int			flags = IPCProtection;
 		size_t		segsize;
 
+		/* Do not exceed maximum allowed memory allocation */
+		if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+			return false;
+
 		/*
 		 * Allocate the memory BEFORE acquiring the resource, so that we don't
 		 * leak the resource if memory allocation fails.
@@ -717,6 +731,10 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
 		return true;
 	}
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (op == DSM_OP_CREATE && exceeds_max_total_bkend_mem(request_size))
+		return false;
+
 	/* Create new segment or open an existing one for attach. */
 	if (op == DSM_OP_CREATE)
 	{
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index 1959b5f4e6..6dbe4373f8 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -50,6 +50,7 @@
 #include "storage/procsignal.h"
 #include "storage/spin.h"
 #include "storage/standby.h"
+#include "utils/guc.h"
 #include "utils/timeout.h"
 #include "utils/timestamp.h"
 
@@ -182,6 +183,50 @@ InitProcGlobal(void)
 	pg_atomic_init_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER);
 	pg_atomic_init_u64(&ProcGlobal->global_dsm_allocation, 0);
 
+	/* Setup backend memory limiting if configured */
+	if (max_total_bkend_mem > 0)
+	{
+		/*
+		 * Convert max_total_bkend_mem to bytes, account for
+		 * shared_memory_size, and initialize total_bkend_mem_bytes.
+		 */
+		int			result = 0;
+
+		/* Get integer value of shared_memory_size */
+		if (parse_int(GetConfigOption("shared_memory_size", true, false), &result, 0, NULL))
+		{
+			/*
+			 * Error on startup if backend memory limit is less than shared
+			 * memory size. Warn on startup if backend memory available is
+			 * less than arbitrarily picked value of 100MB.
+			 */
+
+			if (max_total_bkend_mem - result <= 0)
+			{
+				ereport(ERROR,
+						errmsg("configured max_total_backend_memory %dMB is <= shared_memory_size %dMB",
+							   max_total_bkend_mem, result),
+						errhint("Disable or increase the configuration parameter \"max_total_backend_memory\"."));
+			}
+			else if (max_total_bkend_mem - result <= 100)
+			{
+				ereport(WARNING,
+						errmsg("max_total_backend_memory %dMB - shared_memory_size %dMB is <= 100MB",
+							   max_total_bkend_mem, result),
+						errhint("Consider increasing the configuration parameter \"max_total_backend_memory\"."));
+			}
+
+			/*
+			 * Account for shared memory size and initialize
+			 * total_bkend_mem_bytes.
+			 */
+			pg_atomic_init_u64(&ProcGlobal->total_bkend_mem_bytes,
+							   (uint64) max_total_bkend_mem * 1024 * 1024 - (uint64) result * 1024 * 1024);
+		}
+		else
+			ereport(ERROR, errmsg("max_total_backend_memory initialization is unable to parse shared_memory_size"));
+	}
+
 	/*
 	 * Create and initialize all the PGPROC structures we'll need.  There are
 	 * five separate consumers: (1) normal backends, (2) autovacuum workers
diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c
index 25b545441b..c125dc3abb 100644
--- a/src/backend/utils/activity/backend_status.c
+++ b/src/backend/utils/activity/backend_status.c
@@ -44,6 +44,12 @@
 bool		pgstat_track_activities = false;
 int			pgstat_track_activity_query_size = 1024;
 
+/*
+ * Max backend memory allocation allowed (MB). 0 = disabled.
+ * Centralized bucket ProcGlobal->max_total_bkend_mem is initialized
+ * as a byte representation of this value in InitProcGlobal().
+ */
+int			max_total_bkend_mem = 0;
 
 /* exposed so that backend_progress.c can access it */
 PgBackendStatus *MyBEEntry = NULL;
@@ -67,6 +73,31 @@ uint64	   *my_generation_allocated_bytes = &local_my_generation_allocated_bytes;
 uint64		local_my_slab_allocated_bytes = 0;
 uint64	   *my_slab_allocated_bytes = &local_my_slab_allocated_bytes;
 
+/*
+ * Define initial allocation allowance for a backend.
+ *
+ * NOTE: initial_allocation_allowance && allocation_allowance_refill_qty
+ * may be candidates for future GUC variables. Arbitrary 1MB selected initially.
+ */
+uint64		initial_allocation_allowance = 1024 * 1024;
+uint64		allocation_allowance_refill_qty = 1024 * 1024;
+
+/*
+ * Local counter to manage shared memory allocations. At backend startup, set to
+ * initial_allocation_allowance via pgstat_init_allocated_bytes(). Decrease as
+ * memory is malloc'd. When exhausted, atomically refill if available from
+ * ProcGlobal->max_total_bkend_mem via exceeds_max_total_bkend_mem().
+ */
+uint64		allocation_allowance = 0;
+
+/*
+ * Local counter of free'd shared memory. Return to global
+ * max_total_bkend_mem when return threshold is met. Arbitrary 1MB bytes
+ * selected initially.
+ */
+uint64		allocation_return = 0;
+uint64		allocation_return_threshold = 1024 * 1024;
+
 static PgBackendStatus *BackendStatusArray = NULL;
 static char *BackendAppnameBuffer = NULL;
 static char *BackendClientHostnameBuffer = NULL;
@@ -1272,6 +1303,8 @@ pgstat_set_allocated_bytes_storage(uint64 *allocated_bytes,
 
 	my_slab_allocated_bytes = slab_allocated_bytes;
 	*slab_allocated_bytes = local_my_slab_allocated_bytes;
+
+	return;
 }
 
 /*
@@ -1295,6 +1328,23 @@ pgstat_reset_allocated_bytes_storage(void)
 								*my_dsm_allocated_bytes);
 	}
 
+	/*
+	 * When limiting maximum backend memory, return this backend's memory
+	 * allocations to global.
+	 */
+	if (max_total_bkend_mem)
+	{
+		volatile PROC_HDR *procglobal = ProcGlobal;
+
+		pg_atomic_add_fetch_u64(&procglobal->total_bkend_mem_bytes,
+								*my_allocated_bytes + allocation_allowance +
+								allocation_return);
+
+		/* Reset memory allocation variables */
+		allocation_allowance = 0;
+		allocation_return = 0;
+	}
+
 	/* Reset memory allocation variables */
 	*my_allocated_bytes = local_my_allocated_bytes = 0;
 	*my_aset_allocated_bytes = local_my_aset_allocated_bytes = 0;
@@ -1308,4 +1358,129 @@ pgstat_reset_allocated_bytes_storage(void)
 	my_dsm_allocated_bytes = &local_my_dsm_allocated_bytes;
 	my_generation_allocated_bytes = &local_my_generation_allocated_bytes;
 	my_slab_allocated_bytes = &local_my_slab_allocated_bytes;
+
+	return;
+}
+
+/*
+ * Determine if allocation request will exceed max backend memory allowed.
+ * Do not apply to auxiliary processes.
+ * Refill allocation request bucket when needed/possible.
+ */
+bool
+exceeds_max_total_bkend_mem(uint64 allocation_request)
+{
+	bool		result = false;
+
+	/*
+	 * When limiting maximum backend memory, attempt to refill allocation
+	 * request bucket if needed.
+	 */
+	if (max_total_bkend_mem && allocation_request > allocation_allowance &&
+		ProcGlobal != NULL)
+	{
+		volatile PROC_HDR *procglobal = ProcGlobal;
+		uint64		available_max_total_bkend_mem = 0;
+		bool		sts = false;
+
+		/*
+		 * If allocation request is larger than memory refill quantity then
+		 * attempt to increase allocation allowance with requested amount,
+		 * otherwise fall through. If this refill fails we do not have enough
+		 * memory to meet the request.
+		 */
+		if (allocation_request >= allocation_allowance_refill_qty)
+		{
+			while ((available_max_total_bkend_mem = pg_atomic_read_u64(&procglobal->total_bkend_mem_bytes)) >= allocation_request)
+			{
+				if ((result = pg_atomic_compare_exchange_u64(&procglobal->total_bkend_mem_bytes,
+															 &available_max_total_bkend_mem,
+															 available_max_total_bkend_mem - allocation_request)))
+				{
+					allocation_allowance = allocation_allowance + allocation_request;
+					break;
+				}
+			}
+
+			/*
+			 * Exclude auxiliary and Postmaster processes from the check.
+			 * Return false. While we want to exclude them from the check, we
+			 * do not want to exclude them from the above allocation handling.
+			 */
+			switch (MyBackendType)
+			{
+				case B_STARTUP:
+				case B_ARCHIVER:
+				case B_BG_WRITER:
+				case B_CHECKPOINTER:
+				case B_WAL_WRITER:
+				case B_WAL_RECEIVER:
+				case B_WAL_SUMMARIZER:
+					return false;
+				default:
+					break;
+			}
+
+			if (MyProcPid == PostmasterPid)
+				return false;
+
+			/*
+			 * If the atomic exchange fails (result == false), we do not have
+			 * enough reserve memory to meet the request. Negate result to
+			 * return the proper value.
+			 */
+
+			return !result;
+		}
+
+		/*
+		 * Attempt to increase allocation allowance by memory refill quantity.
+		 * If available memory is/becomes less than memory refill quantity,
+		 * fall through to attempt to allocate remaining available memory.
+		 */
+		while ((available_max_total_bkend_mem = pg_atomic_read_u64(&procglobal->total_bkend_mem_bytes)) >= allocation_allowance_refill_qty)
+		{
+			if ((sts = pg_atomic_compare_exchange_u64(&procglobal->total_bkend_mem_bytes,
+													  &available_max_total_bkend_mem,
+													  available_max_total_bkend_mem - allocation_allowance_refill_qty)))
+			{
+				allocation_allowance = allocation_allowance + allocation_allowance_refill_qty;
+				break;
+			}
+		}
+
+		/* Do not attempt to increase allocation if available memory is below
+		 * allocation_allowance_refill_qty .
+		 */
+
+		/*
+		 * If refill is not successful, we return true, memory limit exceeded
+		 */
+		if (!sts)
+			result = true;
+	}
+
+	/*
+	 * Exclude auxiliary and postmaster processes from the check. Return false.
+	 * While we want to exclude them from the check, we do not want to exclude
+	 * them from the above allocation handling.
+	 */
+	switch (MyBackendType)
+	{
+		case B_STARTUP:
+		case B_ARCHIVER:
+		case B_BG_WRITER:
+		case B_CHECKPOINTER:
+		case B_WAL_WRITER:
+		case B_WAL_RECEIVER:
+		case B_WAL_SUMMARIZER:
+			result = false;
+		default:
+			break;
+	}
+
+	if (MyProcPid == PostmasterPid)
+		result = false;
+
+	return result;
 }
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 9c82ec48cb..15d2800d5b 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -2093,7 +2093,7 @@ pg_stat_get_memory_allocation(PG_FUNCTION_ARGS)
 Datum
 pg_stat_get_global_memory_allocation(PG_FUNCTION_ARGS)
 {
-#define PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS	2
+#define PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS	3
 	TupleDesc	tupdesc;
 	Datum		values[PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS] = {0};
 	bool		nulls[PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS] = {0};
@@ -2103,15 +2103,23 @@ pg_stat_get_global_memory_allocation(PG_FUNCTION_ARGS)
 	tupdesc = CreateTemplateTupleDesc(PG_STAT_GET_GLOBAL_MEMORY_ALLOCATION_COLS);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 1, "datid",
 					   OIDOID, -1, 0);
-	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "global_dsm_allocated_bytes",
+	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "total_bkend_mem_bytes_available",
+					   INT8OID, -1, 0);
+	TupleDescInitEntry(tupdesc, (AttrNumber) 3, "global_dsm_allocated_bytes",
 					   INT8OID, -1, 0);
 	BlessTupleDesc(tupdesc);
 
 	/* datid */
 	values[0] = ObjectIdGetDatum(MyDatabaseId);
 
-	/* get global_dsm_allocated_bytes */
-	values[1] = Int64GetDatum(pg_atomic_read_u64(&procglobal->global_dsm_allocation));
+	/* Get total_bkend_mem_bytes - return -1 if disabled */
+	if (max_total_bkend_mem == 0)
+		values[1] = Int64GetDatum(-1);
+	else
+		values[1] = Int64GetDatum(pg_atomic_read_u64(&procglobal->total_bkend_mem_bytes));
+
+	/* Get global_dsm_allocated_bytes */
+	values[2] = Int64GetDatum(pg_atomic_read_u64(&procglobal->global_dsm_allocation));
 
 	/* Returns the record as Datum */
 	PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls)));
diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c
index a4152080b5..9450032a89 100644
--- a/src/backend/utils/hash/dynahash.c
+++ b/src/backend/utils/hash/dynahash.c
@@ -104,7 +104,6 @@
 #include "utils/dynahash.h"
 #include "utils/memutils.h"
 
-
 /*
  * Constants
  *
@@ -359,7 +358,6 @@ hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
 	Assert(flags & HASH_ELEM);
 	Assert(info->keysize > 0);
 	Assert(info->entrysize >= info->keysize);
-
 	/*
 	 * For shared hash tables, we have a local hash header (HTAB struct) that
 	 * we allocate in TopMemoryContext; all else is in shared memory.
@@ -377,6 +375,7 @@ hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
 	}
 	else
 	{
+		/* Set up to allocate the hash header */
 		/* Create the hash table's private memory context */
 		if (flags & HASH_CONTEXT)
 			CurrentDynaHashCxt = info->hcxt;
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index 9b47450813..d72ec3a0db 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -171,8 +171,16 @@ InitPostmasterChild(void)
 				 errmsg_internal("could not set postmaster death monitoring pipe to FD_CLOEXEC mode: %m")));
 #endif
 
+	/*
+	 * Init pgstat allocated bytes counters here for forked backends.
+	 * Fork/exec backends have not yet reattached to shared memory at this
+	 * point. They will init pgstat allocated bytes counters in
+	 * PGSharedMemoryReAttach.
+	 */
+#ifndef EXEC_BACKEND
 	/* Init allocated bytes to avoid double counting parent allocation */
 	pgstat_init_allocated_bytes();
+#endif
 }
 
 /*
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index 57d9de4dd9..65f0b69319 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -3626,6 +3626,17 @@ struct config_int ConfigureNamesInt[] =
 		NULL, NULL, NULL
 	},
 
+	{
+		{"max_total_backend_memory", PGC_SU_BACKEND, RESOURCES_MEM,
+			gettext_noop("Restrict total backend memory allocations to this max."),
+			gettext_noop("0 turns this feature off."),
+			GUC_UNIT_MB
+		},
+		&max_total_bkend_mem,
+		0, 0, INT_MAX,
+		NULL, NULL, NULL
+	},
+
 	/* End-of-list marker */
 	{
 		{NULL, 0, 0, NULL, NULL}, NULL, 0, 0, 0, NULL, NULL, NULL
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 2244ee52f7..50e2bb2bcf 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -169,6 +169,9 @@
 #vacuum_buffer_usage_limit = 256kB	# size of vacuum and analyze buffer access strategy ring;
 					# 0 to disable vacuum buffer access strategy;
 					# range 128kB to 16GB
+#max_total_backend_memory = 0MB		# Restrict total backend memory allocations
+									# to this max (in MB). 0 turns this feature
+									# off.
 
 # - Disk -
 
diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index cd074add17..f0ee6a9390 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -438,6 +438,18 @@ AllocSetContextCreateInternal(MemoryContext parent,
 	else
 		firstBlockSize = Max(firstBlockSize, initBlockSize);
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (exceeds_max_total_bkend_mem(firstBlockSize))
+	{
+		if (TopMemoryContext)
+			MemoryContextStats(TopMemoryContext);
+		ereport(ERROR,
+				(errcode(ERRCODE_OUT_OF_MEMORY),
+				 errmsg("out of memory - exceeds max_total_backend_memory"),
+				 errdetail("Failed while creating memory context \"%s\".",
+						   name)));
+	}
+
 	/*
 	 * Allocate the initial block.  Unlike other aset.c blocks, it starts with
 	 * the context header and its block header follows that.
@@ -724,6 +736,11 @@ AllocSetAllocLarge(MemoryContext context, Size size, int flags)
 #endif
 
 	blksize = chunk_size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
+
+	/* Do not exceed maximum allowed memory allocation */
+	if (exceeds_max_total_bkend_mem(blksize))
+		return NULL;
+
 	block = (AllocBlock) malloc(blksize);
 	if (block == NULL)
 		return MemoryContextAllocationFailure(context, size, flags);
@@ -917,6 +934,10 @@ AllocSetAllocFromNewBlock(MemoryContext context, Size size, int flags,
 	while (blksize < required_size)
 		blksize <<= 1;
 
+	/* Do not exceed maximum allowed memory allocation */
+	if (exceeds_max_total_bkend_mem(blksize))
+		return NULL;
+
 	/* Try to allocate it */
 	block = (AllocBlock) malloc(blksize);
 
@@ -1238,6 +1259,18 @@ AllocSetRealloc(void *pointer, Size size, int flags)
 		blksize = chksize + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
 		oldblksize = block->endptr - ((char *) block);
 
+		/*
+		 * Do not exceed maximum allowed memory allocation. NOTE: checking for
+		 * the full size here rather than just the amount of increased
+		 * allocation to prevent a potential underflow of *my_allocation
+		 * allowance in cases where blksize - oldblksize does not trigger a
+		 * refill but blksize is greater than *my_allocation_allowance.
+		 * Underflow would occur with the call below to
+		 * pgstat_report_allocated_bytes_increase()
+		 */
+		if (blksize > oldblksize && exceeds_max_total_bkend_mem(blksize))
+			return NULL;
+
 		block = (AllocBlock) realloc(block, blksize);
 		if (block == NULL)
 		{
diff --git a/src/backend/utils/mmgr/generation.c b/src/backend/utils/mmgr/generation.c
index dbea4f248e..3a6e3abeb8 100644
--- a/src/backend/utils/mmgr/generation.c
+++ b/src/backend/utils/mmgr/generation.c
@@ -203,6 +203,16 @@ GenerationContextCreate(MemoryContext parent,
 	else
 		allocSize = Max(allocSize, initBlockSize);
 
+	if (exceeds_max_total_bkend_mem(allocSize))
+	{
+		MemoryContextStats(TopMemoryContext);
+		ereport(ERROR,
+				(errcode(ERRCODE_OUT_OF_MEMORY),
+				 errmsg("out of memory - exceeds max_total_backend_memory"),
+				 errdetail("Failed while creating memory context \"%s\".",
+						   name)));
+	}
+
 	/*
 	 * Allocate the initial block.  Unlike other generation.c blocks, it
 	 * starts with the context header and its block header follows that.
@@ -372,6 +382,9 @@ GenerationAllocLarge(MemoryContext context, Size size, int flags)
 	required_size = chunk_size + Generation_CHUNKHDRSZ;
 	blksize = required_size + Generation_BLOCKHDRSZ;
 
+	if (exceeds_max_total_bkend_mem(blksize))
+		return NULL;
+
 	block = (GenerationBlock *) malloc(blksize);
 	if (block == NULL)
 		return MemoryContextAllocationFailure(context, size, flags);
@@ -494,6 +507,9 @@ GenerationAllocFromNewBlock(MemoryContext context, Size size, int flags,
 	if (blksize < required_size)
 		blksize = pg_nextpower2_size_t(required_size);
 
+	if (exceeds_max_total_bkend_mem(blksize))
+		return NULL;
+
 	block = (GenerationBlock *) malloc(blksize);
 
 	if (block == NULL)
diff --git a/src/backend/utils/mmgr/slab.c b/src/backend/utils/mmgr/slab.c
index 850760f485..36b3f14279 100644
--- a/src/backend/utils/mmgr/slab.c
+++ b/src/backend/utils/mmgr/slab.c
@@ -360,7 +360,16 @@ SlabContextCreate(MemoryContext parent,
 		elog(ERROR, "block size %zu for slab is too small for %zu-byte chunks",
 			 blockSize, chunkSize);
 
-
+	/* Do not exceed maximum allowed memory allocation */
+	if (exceeds_max_total_bkend_mem(Slab_CONTEXT_HDRSZ(chunksPerBlock)))
+	{
+		MemoryContextStats(TopMemoryContext);
+		ereport(ERROR,
+				(errcode(ERRCODE_OUT_OF_MEMORY),
+				 errmsg("out of memory - exceeds max_total_backend_memory"),
+				 errdetail("Failed while creating memory context \"%s\".",
+						   name)));
+	}
 
 	slab = (SlabContext *) malloc(Slab_CONTEXT_HDRSZ(chunksPerBlock));
 	if (slab == NULL)
@@ -582,6 +591,10 @@ SlabAllocFromNewBlock(MemoryContext context, Size size, int flags)
 	}
 	else
 	{
+		/* Do not exceed maximum allowed memory allocation */
+		if (exceeds_max_total_bkend_mem(slab->blockSize))
+			return MemoryContextAllocationFailure(context, size, flags);
+
 		block = (SlabBlock *) malloc(slab->blockSize);
 
 		if (unlikely(block == NULL))
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 56ab1f9470..79869d1c41 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -5448,9 +5448,9 @@
   descr => 'statistics: global memory allocation information',
   proname => 'pg_stat_get_global_memory_allocation', proisstrict => 'f',
   provolatile => 's', proparallel => 'r', prorettype => 'record',
-  proargtypes => '', proallargtypes => '{oid,int8}',
-  proargmodes => '{o,o}',
-  proargnames => '{datid,global_dsm_allocated_bytes}',
+  proargtypes => '', proallargtypes => '{oid,int8,int8}',
+  proargmodes => '{o,o,o}',
+  proargnames => '{datid,total_bkend_mem_bytes_available,global_dsm_allocated_bytes}',
   prosrc =>'pg_stat_get_global_memory_allocation' },
 { oid => '2022',
   descr => 'statistics: information about currently active backends',
diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h
index a350f455cd..fa7c94c6c9 100644
--- a/src/include/storage/proc.h
+++ b/src/include/storage/proc.h
@@ -424,6 +424,13 @@ typedef struct PROC_HDR
 	int			startupBufferPinWaitBufId;
 	/* Global dsm allocations */
 	pg_atomic_uint64 global_dsm_allocation;
+
+	/*
+	 * Max backend memory allocation tracker. Used/Initialized when
+	 * max_total_bkend_mem > 0 as max_total_bkend_mem (MB) converted to bytes.
+	 * Decreases/increases with free/malloc of backend memory.
+	 */
+	pg_atomic_uint64 total_bkend_mem_bytes;
 } PROC_HDR;
 
 extern PGDLLIMPORT PROC_HDR *ProcGlobal;
diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h
index cbf801884d..a833941272 100644
--- a/src/include/utils/backend_status.h
+++ b/src/include/utils/backend_status.h
@@ -14,7 +14,7 @@
 #include "datatype/timestamp.h"
 #include "libpq/pqcomm.h"
 #include "miscadmin.h"			/* for BackendType */
-#include "storage/procnumber.h"
+#include "storage/proc.h"
 #include "utils/backend_progress.h"
 
 
@@ -303,6 +303,7 @@ typedef struct LocalPgBackendStatus
  */
 extern PGDLLIMPORT bool pgstat_track_activities;
 extern PGDLLIMPORT int pgstat_track_activity_query_size;
+extern PGDLLIMPORT int max_total_bkend_mem;
 
 
 /* ----------
@@ -315,6 +316,10 @@ extern PGDLLIMPORT uint64 *my_aset_allocated_bytes;
 extern PGDLLIMPORT uint64 *my_dsm_allocated_bytes;
 extern PGDLLIMPORT uint64 *my_generation_allocated_bytes;
 extern PGDLLIMPORT uint64 *my_slab_allocated_bytes;
+extern PGDLLIMPORT uint64 allocation_allowance;
+extern PGDLLIMPORT uint64 initial_allocation_allowance;
+extern PGDLLIMPORT uint64 allocation_return;
+extern PGDLLIMPORT uint64 allocation_return_threshold;
 
 
 /* ----------
@@ -363,6 +368,7 @@ extern PgBackendStatus *pgstat_get_beentry_by_proc_number(ProcNumber procNumber)
 extern LocalPgBackendStatus *pgstat_get_local_beentry_by_proc_number(ProcNumber procNumber);
 extern LocalPgBackendStatus *pgstat_get_local_beentry_by_index(int idx);
 extern char *pgstat_clip_activity(const char *raw_activity);
+extern bool exceeds_max_total_bkend_mem(uint64 allocation_request);
 
 /* ----------
  * pgstat_report_allocated_bytes_decrease() -
@@ -378,7 +384,7 @@ pgstat_report_allocated_bytes_decrease(int64 proc_allocated_bytes,
 {
 	uint64		temp;
 
-	/* Avoid allocated_bytes unsigned integer overflow on decrease */
+	/* Sanity check: my allocated bytes should never drop below zero */
 	if (pg_sub_u64_overflow(*my_allocated_bytes, proc_allocated_bytes, &temp))
 	{
 		/* On overflow, set allocated bytes and allocator type bytes to zero */
@@ -387,13 +393,35 @@ pgstat_report_allocated_bytes_decrease(int64 proc_allocated_bytes,
 		*my_dsm_allocated_bytes = 0;
 		*my_generation_allocated_bytes = 0;
 		*my_slab_allocated_bytes = 0;
+
+		/* Add freed memory to allocation return counter. */
+		allocation_return += proc_allocated_bytes;
+
+		/*
+		 * Return freed memory to the global counter if return threshold is
+		 * met.
+		 */
+		if (max_total_bkend_mem && allocation_return >= allocation_return_threshold)
+		{
+			if (ProcGlobal)
+			{
+				volatile PROC_HDR *procglobal = ProcGlobal;
+
+				/* Add to global tracker */
+				pg_atomic_add_fetch_u64(&procglobal->total_bkend_mem_bytes,
+										allocation_return);
+
+				/* Restart the count */
+				allocation_return = 0;
+			}
+		}
 	}
 	else
 	{
-		/* decrease allocation */
-		*my_allocated_bytes -= proc_allocated_bytes;
+		/* Add freed memory to allocation return counter */
+		allocation_return += proc_allocated_bytes;
 
-		/* Decrease allocator type allocated bytes. */
+		/* Decrease allocator type allocated bytes */
 		switch (pg_allocator_type)
 		{
 			case PG_ALLOC_ASET:
@@ -415,6 +443,30 @@ pgstat_report_allocated_bytes_decrease(int64 proc_allocated_bytes,
 				*my_slab_allocated_bytes -= proc_allocated_bytes;
 				break;
 		}
+
+		/* decrease allocation */
+		*my_allocated_bytes = *my_aset_allocated_bytes +
+			*my_dsm_allocated_bytes + *my_generation_allocated_bytes +
+			*my_slab_allocated_bytes;
+
+		/*
+		 * Return freed memory to the global counter if return threshold is
+		 * met.
+		 */
+		if (max_total_bkend_mem && allocation_return >= allocation_return_threshold)
+		{
+			if (ProcGlobal)
+			{
+				volatile PROC_HDR *procglobal = ProcGlobal;
+
+				/* Add to global tracker */
+				pg_atomic_add_fetch_u64(&procglobal->total_bkend_mem_bytes,
+										allocation_return);
+
+				/* Restart the count */
+				allocation_return = 0;
+			}
+		}
 	}
 
 	return;
@@ -432,7 +484,13 @@ static inline void
 pgstat_report_allocated_bytes_increase(int64 proc_allocated_bytes,
 									   int pg_allocator_type)
 {
-	*my_allocated_bytes += proc_allocated_bytes;
+	uint64		temp;
+
+	/* Sanity check: my allocated bytes should never drop below zero */
+	if (pg_sub_u64_overflow(allocation_allowance, proc_allocated_bytes, &temp))
+		allocation_allowance = 0;
+	else
+		allocation_allowance -= proc_allocated_bytes;
 
 	/* Increase allocator type allocated bytes */
 	switch (pg_allocator_type)
@@ -457,6 +515,9 @@ pgstat_report_allocated_bytes_increase(int64 proc_allocated_bytes,
 			break;
 	}
 
+	*my_allocated_bytes = *my_aset_allocated_bytes + *my_dsm_allocated_bytes +
+		*my_generation_allocated_bytes + *my_slab_allocated_bytes;
+
 	return;
 }
 
@@ -476,6 +537,36 @@ pgstat_init_allocated_bytes(void)
 	*my_generation_allocated_bytes = 0;
 	*my_slab_allocated_bytes = 0;
 
+	/* If we're limiting backend memory */
+	if (max_total_bkend_mem)
+	{
+		volatile PROC_HDR *procglobal = ProcGlobal;
+		uint64		available_max_total_bkend_mem = 0;
+
+		allocation_return = 0;
+		allocation_allowance = 0;
+
+		/* Account for the initial allocation allowance */
+		while ((available_max_total_bkend_mem = pg_atomic_read_u64(&procglobal->total_bkend_mem_bytes)) >= initial_allocation_allowance)
+		{
+			/*
+			 * On success populate allocation_allowance. Failure here will
+			 * result in the backend's first invocation of
+			 * exceeds_max_total_bkend_mem allocating requested, default, or
+			 * available memory or result in an out of memory error.
+			 */
+			if (pg_atomic_compare_exchange_u64(&procglobal->total_bkend_mem_bytes,
+											   &available_max_total_bkend_mem,
+											   available_max_total_bkend_mem -
+											   initial_allocation_allowance))
+			{
+				allocation_allowance = initial_allocation_allowance;
+
+				break;
+			}
+		}
+	}
+
 	return;
 }
 
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index 2f62f5e4ea..01dee8ddea 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1887,13 +1887,15 @@ pg_stat_global_memory_allocation| WITH sums AS (
  SELECT s.datid,
     current_setting('shared_memory_size'::text, true) AS shared_memory_size,
     (current_setting('shared_memory_size_in_huge_pages'::text, true))::integer AS shared_memory_size_in_huge_pages,
+    pg_size_bytes(current_setting('max_total_backend_memory'::text, true)) AS max_total_backend_memory_bytes,
+    s.total_bkend_mem_bytes_available,
     s.global_dsm_allocated_bytes,
     sums.total_aset_allocated_bytes,
     sums.total_dsm_allocated_bytes,
     sums.total_generation_allocated_bytes,
     sums.total_slab_allocated_bytes
    FROM sums,
-    (pg_stat_get_global_memory_allocation() s(datid, global_dsm_allocated_bytes)
+    (pg_stat_get_global_memory_allocation() s(datid, total_bkend_mem_bytes_available, global_dsm_allocated_bytes)
      LEFT JOIN pg_database d ON ((s.datid = d.oid)));
 pg_stat_gssapi| SELECT pid,
     gss_auth AS gss_authenticated,
-- 
2.43.2

#59Alexander Lakhin
exclusion@gmail.com
In reply to: Anton A. Melnikov (#58)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

Hello Anton,

14.03.2024 23:36, Anton A. Melnikov wrote:

On 13.03.2024 10:41, Anton A. Melnikov wrote:

Here is a version updated for the current master.

During patch updating i mistakenly added double counting of deallocatated blocks.
That's why the tests in the patch tester failed.
Fixed it and squashed fix 0002 with 0001.
Here is fixed version.

Please try the following with the patches applied:
echo "shared_buffers = '1MB'
max_total_backend_memory = '10MB'" > /tmp/extra.config

CPPFLAGS="-Og" ./configure --enable-tap-tests --enable-debug --enable-cassert ...
TEMP_CONFIG=/tmp/extra.config make check

It fails for me as follows:
...
# postmaster did not respond within 60 seconds, examine ".../src/test/regress/log/postmaster.log" for the reason
...
src/test/regress/log/postmaster.log contains:
...
TRAP: failed Assert("ret != NULL"), File: "mcxt.c", Line: 1327, PID: 4109270
TRAP: failed Assert("ret != NULL"), File: "mcxt.c", Line: 1327, PID: 4109271
postgres: autovacuum launcher (ExceptionalCondition+0x69)[0x55ce441fcc6e]
postgres: autovacuum launcher (palloc0+0x0)[0x55ce4422eb67]
postgres: logical replication launcher (ExceptionalCondition+0x69)[0x55ce441fcc6e]
postgres: autovacuum launcher (InitDeadLockChecking+0xa6)[0x55ce4408a6f0]
postgres: logical replication launcher (palloc0+0x0)[0x55ce4422eb67]
postgres: logical replication launcher (InitDeadLockChecking+0x45)[0x55ce4408a68f]
postgres: autovacuum launcher (InitProcess+0x600)[0x55ce4409c6f2]
postgres: logical replication launcher (InitProcess+0x600)[0x55ce4409c6f2]
postgres: autovacuum launcher (+0x44b4e2)[0x55ce43ff24e2]
...
grep TRAP src/test/regress/log/postmaster.log | wc -l
445

Best regards,
Alexander

#60James Hunter
james.hunter.pg@gmail.com
In reply to: Tomas Vondra (#55)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

Reviving this thread, because I am thinking about something related --
please ignore the "On Fri, Dec 27, 2024" date, this seems to be an
artifact of me re-sending the message, from the list archive. The
original message was from January 28, 2024.

On Fri, Dec 27, 2024 at 11:02 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

Firstly, I agree with the goal of having a way to account for memory
used by the backends, and also ability to enforce some sort of limit.
It's difficult to track the memory at the OS level (interpreting RSS
values is not trivial), and work_mem is not sufficient to enforce a
backend-level limit, not even talking about a global limit.

But as I said earlier, it seems quite strange to start by introducing
some sort of global limit, combining memory for all backends. I do
understand that the intent is to have such global limit in order to
prevent issues with the OOM killer and/or not to interfere with other
stuff running on the same machine. And while I'm not saying we should
not have such limit, every time I wished to have a memory limit it was a
backend-level one. Ideally a workmem-like limit that would "adjust" the
work_mem values used by the optimizer (but that's not what this patch
aims to do), or at least a backstop in case something goes wrong (say, a
memory leak, OLTP application issuing complex queries, etc.).

I think what Tomas suggests is the right strategy. I am thinking of
something like:

1. Say we have a backend_work_mem limit. Then the total amount of
memory available on the entire system, for all queries, as work_mem,
would be backend_work_mem * max_connections.

2. We use this backend_work_mem to "adjust" work_mem values used by
the executor. (I don't care about the optimizer right now -- optimizer
just does its best to predict what will happen at runtime.)

At runtime, every node that uses work_mem currently checks its memory
usage against the session work_mem (and possibly hash_mem_multiplier)
GUC(s). Instead, now, every node would check against its node-specific
"adjusted" work_mem. If it exceeds this limit, it spills, using
existing logic.

In other words -- existing logic spills based on comparison to global
work_mem GUC. Let's make it spill, instead, based on comparison to an
operator-local "PlanState.work_mem" field.

And then let's set that "PlanState.work_mem" field based on a new
"backend_work_mem" GUC. Then no queries will run OOM (at least, not
due to work_mem -- we'll address other memory usages separately), so
they won't need to be canceled. Instead, they'll spill.

This strategy solves the ongoing problem of how to set work_mem, if
some queries have lots of operators and others don't -- now we just
set backend_work_mem, as a limit on the entire query's total work_mem.
And a bit of integration with the optimizer will allow us to
distribute the total backend_work_mem to individual execution nodes,
with the goal of minimizing spilling, without exceeding the
backend_work_mem limit.

Anyway, I revived this thread to see if there's interest in this sort
of strategy --

Thanks,
James

#61Tomas Vondra
tomas@vondra.me
In reply to: James Hunter (#60)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On 12/27/24 20:14, James Hunter wrote:

Reviving this thread, because I am thinking about something related --
please ignore the "On Fri, Dec 27, 2024" date, this seems to be an
artifact of me re-sending the message, from the list archive. The
original message was from January 28, 2024.

On Fri, Dec 27, 2024 at 11:02 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

Firstly, I agree with the goal of having a way to account for memory
used by the backends, and also ability to enforce some sort of limit.
It's difficult to track the memory at the OS level (interpreting RSS
values is not trivial), and work_mem is not sufficient to enforce a
backend-level limit, not even talking about a global limit.

But as I said earlier, it seems quite strange to start by introducing
some sort of global limit, combining memory for all backends. I do
understand that the intent is to have such global limit in order to
prevent issues with the OOM killer and/or not to interfere with other
stuff running on the same machine. And while I'm not saying we should
not have such limit, every time I wished to have a memory limit it was a
backend-level one. Ideally a workmem-like limit that would "adjust" the
work_mem values used by the optimizer (but that's not what this patch
aims to do), or at least a backstop in case something goes wrong (say, a
memory leak, OLTP application issuing complex queries, etc.).

I think what Tomas suggests is the right strategy. I am thinking of
something like:

1. Say we have a backend_work_mem limit. Then the total amount of
memory available on the entire system, for all queries, as work_mem,
would be backend_work_mem * max_connections.

2. We use this backend_work_mem to "adjust" work_mem values used by
the executor. (I don't care about the optimizer right now -- optimizer
just does its best to predict what will happen at runtime.)

At runtime, every node that uses work_mem currently checks its memory
usage against the session work_mem (and possibly hash_mem_multiplier)
GUC(s). Instead, now, every node would check against its node-specific
"adjusted" work_mem. If it exceeds this limit, it spills, using
existing logic.

In other words -- existing logic spills based on comparison to global
work_mem GUC. Let's make it spill, instead, based on comparison to an
operator-local "PlanState.work_mem" field.

And then let's set that "PlanState.work_mem" field based on a new
"backend_work_mem" GUC. Then no queries will run OOM (at least, not
due to work_mem -- we'll address other memory usages separately), so
they won't need to be canceled. Instead, they'll spill.

This strategy solves the ongoing problem of how to set work_mem, if
some queries have lots of operators and others don't -- now we just
set backend_work_mem, as a limit on the entire query's total work_mem.
And a bit of integration with the optimizer will allow us to
distribute the total backend_work_mem to individual execution nodes,
with the goal of minimizing spilling, without exceeding the
backend_work_mem limit.

Anyway, I revived this thread to see if there's interest in this sort
of strategy --

I think there's still interest in having a memory limit of this kind,
but it's not very clear to me what you mean by "adjusted work_mem". Can
you explain how would that actually work in practice?

Whenever I've been thinking about this in the past, it wasn't clear to
me how would we know when to start adjusting work_mem, because we don't
know which nodes will actually use work_mem concurrently.

We certainly don't know that during planning - e.g. because we don't
actually know what nodes will be "above" the operation we're planning.
And AFIAK we don't have any concept which parts of the plan may be
active at the same time ...

Let's say we have limits work_mem=4MB and query_mem=8MB (to keep it
simple). And we have a query plan with 3 separate hash joins, each
needing 4MB. I believe these things can happen:

1) The hash joins are in distant parts of the query plan, and will not
actually run concurrently - we'll run each hashjoin till completion
before starting the next one. So, no problem with query_mem.

2) The hash joins are active at the same time, initialized one by one.
But we don't know what, so we'll init HJ #1, it'll get 4MB of memory.
Then we'll init HJ #2, it'll also get 4MB of memory. And now we want to
init HJ #3, but we've already exhausted query_mem, but the memory is
already used and we can't reclaim it.

How would the work_mem get adjusted in these cases? Ideally, we'd not
adjust work_mem in (1), because it'd force hash joins to spill data to
disk, affecting performance when there's enough memory to just run the
query plan (but maybe that's a reasonable price for the memory limit?).
While in (2) we'd need to start adjusting the memory from the beginning,
but I don't think we know that so early.

Can you explain / walk me through the proposal for these cases?

regards

--
Tomas Vondra

#62Anton A. Melnikov
a.melnikov@postgrespro.ru
In reply to: Tomas Vondra (#61)
1 attachment(s)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

Hi!

On 28.12.2024 04:48, Tomas Vondra wrote:

On 12/27/24 20:14, James Hunter wrote:

Reviving this thread, because I am thinking about something related --
please ignore the "On Fri, Dec 27, 2024" date, this seems to be an
artifact of me re-sending the message, from the list archive. The
original message was from January 28, 2024.

On Fri, Dec 27, 2024 at 11:02 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

Firstly, I agree with the goal of having a way to account for memory
used by the backends, and also ability to enforce some sort of limit.
It's difficult to track the memory at the OS level (interpreting RSS
values is not trivial), and work_mem is not sufficient to enforce a
backend-level limit, not even talking about a global limit.

But as I said earlier, it seems quite strange to start by introducing
some sort of global limit, combining memory for all backends. I do
understand that the intent is to have such global limit in order to
prevent issues with the OOM killer and/or not to interfere with other
stuff running on the same machine. And while I'm not saying we should
not have such limit, every time I wished to have a memory limit it was a
backend-level one. Ideally a workmem-like limit that would "adjust" the
work_mem values used by the optimizer (but that's not what this patch
aims to do), or at least a backstop in case something goes wrong (say, a
memory leak, OLTP application issuing complex queries, etc.).

I think what Tomas suggests is the right strategy.

I'm also interested in this topic. And agreed that it's best to move from the limit
for a separate backend to the global one. In more details let me suggest
the following steps or parts:
1) realize memory limitation for a separate backend independent from the work_mem GUC;
2) add workmem-like limit that would "adjust" the work_mem values used by
the optimize as Thomas suggested;
3) add global limit for all backends.

As for p.1 there is a patch that was originally suggested by my colleague
Maxim Orlov <orlovmg@gmail.com> and which i modified for the current master.
This patch introduces the only max_backend_memory GUC that specifies
the maximum amount of memory that can be allocated to a backend.
Zero value means no limit.
If the allocated memory size is exceeded, a standard "out of memory" error will be issued.
Also the patch introduces the pg_get_backend_memory_contexts_total_bytes() function,
which allows to know how many bytes have already been allocated
to the process in contexts. And in the build with asserts it adds
the pg_get_backend_memory_allocation_stats() function that allows
to get additional information about memory allocations for debug purposes.

This strategy solves the ongoing problem of how to set work_mem, if
some queries have lots of operators and others don't -- now we just
set backend_work_mem, as a limit on the entire query's total work_mem.
And a bit of integration with the optimizer will allow us to
distribute the total backend_work_mem to individual execution nodes,
with the goal of minimizing spilling, without exceeding the
backend_work_mem limit.

As for p.2 maybe one can set a maximum number of parallel sort or
hash table operations before writing to disk instead of absolute
value in the work_mem GUC? E.g. introduce а max_query_operations GUC
or a variable in such a way that old work_mem will be equal
to max_backend_memory divided by max_query_operations.

What do you think about such approach?

With the best wishes,

--
Anton A. Melnikov
Postgres Professional: http://www.postgrespro.com
The Russian Postgres Company

Attachments:

0001-v1-limit-backend-heap-memory-allocation.patchtext/x-patch; charset=UTF-8; name=0001-v1-limit-backend-heap-memory-allocation.patchDownload
From 8ec3548604bf6a1f5f4c290495843e7080d09660 Mon Sep 17 00:00:00 2001
From: "Anton A. Melnikov" <a.melnikov@postgrespro.ru>
Date: Sat, 28 Dec 2024 12:47:24 +0300
Subject: [PATCH]     Limit backend heap memory allocation

    This per-backend GUC can limit the amount of heap allocated
    memory.  Upon reaching this limit "out of memory" error will
    be triggered.

    GUC is diabled by default.

    Authors: Maxim Orlov <orlovmg@gmail.com>, Anton A. Melnikov <a.melnikov@postgrespro.ru>
---
 doc/src/sgml/config.sgml                      |  17 +
 src/backend/utils/activity/backend_status.c   | 335 ++++++++++++++++++
 src/backend/utils/misc/guc_tables.c           |  10 +
 src/backend/utils/misc/postgresql.conf.sample |   1 +
 src/backend/utils/mmgr/aset.c                 |  36 +-
 src/backend/utils/mmgr/generation.c           |  18 +-
 src/backend/utils/mmgr/slab.c                 |  17 +-
 src/include/catalog/pg_proc.dat               |  14 +
 src/include/utils/backend_status.h            |  10 +
 src/test/modules/Makefile                     |   4 +
 .../modules/test_backend_memory/.gitignore    |   4 +
 src/test/modules/test_backend_memory/Makefile |  14 +
 src/test/modules/test_backend_memory/README   |   1 +
 .../t/001_max_backend_memory.pl               |  85 +++++
 14 files changed, 540 insertions(+), 26 deletions(-)
 create mode 100644 src/test/modules/test_backend_memory/.gitignore
 create mode 100644 src/test/modules/test_backend_memory/Makefile
 create mode 100644 src/test/modules/test_backend_memory/README
 create mode 100644 src/test/modules/test_backend_memory/t/001_max_backend_memory.pl

diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index fbdd6ce574..4099d6e1a8 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -2337,6 +2337,23 @@ include_dir 'conf.d'
       </listitem>
      </varlistentry>
 
+    <varlistentry id="guc-max-backend-memory" xreflabel="max_backend_memory">
+      <term><varname>max_backend_memory</varname> (<type>integer</type>)
+      <indexterm>
+       <primary><varname>max_backend_memory</varname> configuration parameter</primary>
+      </indexterm>
+      </term>
+      <listitem>
+       <para>
+        Specifies the maximum amount of memory that can be allocated to a backend.
+        Zero means no limit.
+       </para>
+       <para>
+        Default: 0
+       </para>
+      </listitem>
+     </varlistentry>
+
      </variablelist>
      </sect2>
 
diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c
index bf33e33a4e..a41f004cf7 100644
--- a/src/backend/utils/activity/backend_status.c
+++ b/src/backend/utils/activity/backend_status.c
@@ -12,6 +12,7 @@
 #include "postgres.h"
 
 #include "access/xact.h"
+#include "funcapi.h"
 #include "libpq/libpq-be.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
@@ -20,6 +21,7 @@
 #include "storage/proc.h"		/* for MyProc */
 #include "storage/procarray.h"
 #include "utils/ascii.h"
+#include "utils/builtins.h"
 #include "utils/guc.h"			/* for application_name */
 #include "utils/memutils.h"
 
@@ -73,6 +75,17 @@ static void pgstat_beshutdown_hook(int code, Datum arg);
 static void pgstat_read_current_status(void);
 static void pgstat_setup_backend_status_context(void);
 
+/*
+ * Total memory size allocated by backend.
+ */
+static Size my_allocated_bytes = 0;
+
+/*
+ * GUC variable
+ *
+ * Max backend memory allocation allowed (MB). 0 = disabled
+ */
+int max_backend_memory_size_mb = 0;
 
 /*
  * Report shared-memory space needed by BackendStatusShmemInit.
@@ -1222,3 +1235,325 @@ pgstat_clip_activity(const char *raw_activity)
 
 	return activity;
 }
+
+#ifdef USE_ASSERT_CHECKING
+/*
+ * Single memory allocation.
+ */
+typedef struct
+{
+	void   *addr;
+	Size	size;
+	bool	deleted;
+} HeapBlock;
+
+/*
+ * Dynamic array of all allocated memory.
+ */
+typedef struct
+{
+	HeapBlock	   *blocks;
+	Size			size;
+	Size			capacity;
+	Size			ndeleted;
+} HeapBlockStat;
+
+static HeapBlockStat heapstat =
+{
+	.blocks = NULL,
+	.size = 0,
+	.capacity = 0,
+	.ndeleted = 0
+};
+
+/*
+ * Extend heapstat allocation stat array.
+ */
+static inline void
+HeapBlockStatExtend(void)
+{
+	if (heapstat.capacity == 0)
+	{
+#define INIT_MEMORY_CAPACITY 1024
+		heapstat.capacity = INIT_MEMORY_CAPACITY;
+		heapstat.blocks = (HeapBlock *) malloc(heapstat.capacity *
+											sizeof(heapstat.blocks[0]));
+	}
+	else if (heapstat.capacity == heapstat.size)
+	{
+		heapstat.capacity *= 2;
+		heapstat.blocks = (HeapBlock *) realloc(heapstat.blocks,
+											 heapstat.capacity *
+											 sizeof(heapstat.blocks[0]));
+	}
+}
+
+/*
+ * Compare HeapBlocks. Put not deleted in the beginning of an array.
+ */
+static int
+HeapBlockCmp(const void *p, const void *q)
+{
+	const HeapBlock    *a = (const HeapBlock *) p,
+					   *b = (const HeapBlock *) q;
+	int					arg1 = a->deleted,
+						arg2 = b->deleted;
+
+	if (arg1 < arg2)
+		return -1;
+	if (arg1 > arg2)
+		return 1;
+	return 0;
+}
+
+/*
+ * Put all not deleted items in the beginning.
+ */
+static void
+HeapBlockStatCompactify(void)
+{
+	if (heapstat.ndeleted < heapstat.size / 2)
+		return;
+
+	qsort(heapstat.blocks, heapstat.size, sizeof(heapstat.blocks[0]), HeapBlockCmp);
+	heapstat.size -= heapstat.ndeleted;
+	heapstat.ndeleted = 0;
+}
+
+/*
+ * Push new memory allocation.
+ */
+static void
+HeapBlockStatPush(void *ptr, Size size)
+{
+	Size	i;
+
+	HeapBlockStatExtend();
+	HeapBlockStatCompactify();
+
+	for (i = 0; i < heapstat.size; ++i)
+		Assert(heapstat.blocks[i].deleted || heapstat.blocks[i].addr != ptr);
+
+	Assert(heapstat.ndeleted <= heapstat.size);
+
+	/* Try to find deleted item to reuse it... */
+	for (i = 0; i < heapstat.size; ++i)
+	{
+		if (heapstat.blocks[i].deleted == true)
+		{
+			heapstat.blocks[i].addr = ptr;
+			heapstat.blocks[i].size = size;
+			heapstat.blocks[i].deleted = false;
+			--heapstat.ndeleted;
+			Assert(heapstat.ndeleted <= heapstat.size);
+			return;
+		}
+	}
+
+	/* ... no empty places, append! */
+	heapstat.blocks[i].addr = ptr;
+	heapstat.blocks[i].size = size;
+	heapstat.blocks[i].deleted = false;
+
+	++heapstat.size;
+}
+
+/*
+ * Pop memory allocation.
+ */
+static Size
+HeapBlockStatPop(void *ptr)
+{
+	Size	i;
+
+	for (i = 0; i < heapstat.size; ++i)
+	{
+		if (heapstat.blocks[i].addr == ptr)
+		{
+			Assert(heapstat.blocks[i].deleted == false);
+			heapstat.blocks[i].deleted = true;
+			++heapstat.ndeleted;
+			Assert(heapstat.ndeleted <= heapstat.size);
+			return heapstat.blocks[i].size;
+		}
+	}
+
+	/* should not get here... */
+	Assert(i != heapstat.size);
+	return 0;
+}
+#endif /* USE_ASSERT_CHECKING */
+
+/*
+ * Count backend allocated memory.
+ * If limit is set (max_backend_memory_size_mb) and check=true, then need to
+ * check my_allocated_bytes for going beyond the limit.
+ */
+static bool
+pgstat_alloc(Size size, bool check)
+{
+	/* Exclude auxiliary processes from the check */
+	switch (MyBackendType)
+	{
+		case B_STARTUP:
+		case B_ARCHIVER:
+		case B_BG_WRITER:
+		case B_CHECKPOINTER:
+		case B_WAL_WRITER:
+		case B_WAL_RECEIVER:
+		case B_WAL_SUMMARIZER:
+			return true;
+		default:
+			break;
+	}
+
+	my_allocated_bytes += size;
+
+	if (max_backend_memory_size_mb == 0 || !check)
+		return true;
+
+	/* Check for going beyond the limit */
+#define TO_BYTES(mb)	((Size)(mb) * 1024 * 1024)
+	if (my_allocated_bytes > TO_BYTES(max_backend_memory_size_mb))
+	{
+		my_allocated_bytes -= size;
+		return false;
+	}
+
+	return true;
+}
+
+/*
+ * Count deallocated backend memory.
+ */
+static void
+pgstat_free(Size size)
+{
+	/* Exclude auxiliary processes from the check */
+	switch (MyBackendType)
+	{
+		case B_STARTUP:
+		case B_ARCHIVER:
+		case B_BG_WRITER:
+		case B_CHECKPOINTER:
+		case B_WAL_WRITER:
+		case B_WAL_RECEIVER:
+		case B_WAL_SUMMARIZER:
+			return;
+		default:
+			break;
+	}
+
+	Assert(my_allocated_bytes >= size);
+	my_allocated_bytes -= size;
+}
+
+/*
+ * malloc() with bytes counter
+ */
+void *
+malloc_and_count(Size size)
+{
+	void   *ptr;
+
+	if (!pgstat_alloc(size, true))
+		return NULL;
+
+	ptr = malloc(size);
+	if (ptr == NULL)
+		pgstat_free(size);
+#ifdef USE_ASSERT_CHECKING
+	else
+		HeapBlockStatPush(ptr, size);
+#endif
+
+	return ptr;
+}
+
+/*
+ * realloc() with bytes counter
+ */
+void *
+realloc_and_count(void *ptr, Size new_size, Size old_size)
+{
+	Assert(old_size == HeapBlockStatPop(ptr));
+
+	pgstat_free(old_size);
+
+	if (!pgstat_alloc(new_size, true))
+	{
+		/* New buffer can not be alloced, so need to restore old one */
+		pgstat_alloc(old_size, false);
+#ifdef USE_ASSERT_CHECKING
+		HeapBlockStatPush(ptr, old_size);
+#endif
+		return NULL;
+	}
+
+	ptr = realloc(ptr, new_size);
+	if (ptr == NULL)
+		pgstat_free(new_size);
+#ifdef USE_ASSERT_CHECKING
+	else
+		HeapBlockStatPush(ptr, new_size);
+#endif
+
+	return ptr;
+}
+
+/*
+ * free() with bytes counter
+ */
+void
+free_and_count(void *ptr, Size size)
+{
+#ifdef USE_ASSERT_CHECKING
+	Assert(size == HeapBlockStatPop(ptr));
+#endif
+
+	pgstat_free(size);
+	free(ptr);
+}
+
+/*
+ * pg_get_backend_memory_contexts_total_bytes
+ *		Total amount of bytes in all allocated contexts.
+ */
+Datum
+pg_get_backend_memory_contexts_total_bytes(PG_FUNCTION_ARGS)
+{
+	PG_RETURN_INT64(my_allocated_bytes);
+}
+
+/*
+ * pg_get_backend_memory_allocation_stats
+ *		SQL SRF showing backend allocated memory.
+ */
+Datum
+pg_get_backend_memory_allocation_stats(PG_FUNCTION_ARGS)
+{
+#ifdef USE_ASSERT_CHECKING
+#define MEMORY_ALLOCATION_COLS 3
+	ReturnSetInfo  *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
+	Datum			values[MEMORY_ALLOCATION_COLS];
+	bool			nulls[MEMORY_ALLOCATION_COLS];
+	Size			i;
+	char			text[16];
+
+	InitMaterializedSRF(fcinfo, 0);
+
+	memset(nulls, 0, sizeof(nulls));
+	for (i = 0; i < heapstat.size; ++i)
+	{
+		pg_snprintf(text, sizeof(text), "%p", heapstat.blocks[i].addr);
+		values[0] = CStringGetTextDatum(text);
+		values[1] = Int64GetDatum(heapstat.blocks[i].size);
+		values[2] = BoolGetDatum(heapstat.blocks[i].deleted);
+		tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
+	}
+#else
+	elog(ERROR, "this only works for builds with asserts enabled");
+#endif
+
+	return (Datum) 0;
+}
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index 8cf1afbad2..f888d417de 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -3732,6 +3732,16 @@ struct config_int ConfigureNamesInt[] =
 		SCRAM_SHA_256_DEFAULT_ITERATIONS, 1, INT_MAX,
 		NULL, NULL, NULL
 	},
+	{
+		{"max_backend_memory", PGC_SU_BACKEND, RESOURCES_MEM,
+			gettext_noop("Restrict total backend memory allocations to this max (rounded up to the nearest MB)."),
+			NULL,
+			GUC_UNIT_MB
+		},
+		&max_backend_memory_size_mb,
+		0, 0, INT_MAX,
+		NULL, NULL, NULL
+	},
 
 	/* End-of-list marker */
 	{
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index a2ac7575ca..1854601ca9 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -171,6 +171,7 @@
 #serializable_buffers = 32		# memory for pg_serial
 #subtransaction_buffers = 0		# memory for pg_subtrans (0 = auto)
 #transaction_buffers = 0		# memory for pg_xact (0 = auto)
+#max_backend_memory = 0			# limit amount of per-backend allocated memory in megabytes
 
 # - Disk -
 
diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index dede30dd86..e304da7c3c 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -47,6 +47,7 @@
 #include "postgres.h"
 
 #include "port/pg_bitutils.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_internal.h"
@@ -441,7 +442,7 @@ AllocSetContextCreateInternal(MemoryContext parent,
 	 * Allocate the initial block.  Unlike other aset.c blocks, it starts with
 	 * the context header and its block header follows that.
 	 */
-	set = (AllocSet) malloc(firstBlockSize);
+	set = (AllocSet) malloc_and_count(firstBlockSize);
 	if (set == NULL)
 	{
 		if (TopMemoryContext)
@@ -579,13 +580,16 @@ AllocSetReset(MemoryContext context)
 		}
 		else
 		{
+			Size	deallocation_size;
+
 			/* Normal case, release the block */
-			context->mem_allocated -= block->endptr - ((char *) block);
+			deallocation_size = block->endptr - ((char *) block);
+			context->mem_allocated -= deallocation_size;
 
 #ifdef CLOBBER_FREED_MEMORY
 			wipe_mem(block, block->freeptr - ((char *) block));
 #endif
-			free(block);
+			free_and_count(block, deallocation_size);
 		}
 		block = next;
 	}
@@ -649,7 +653,7 @@ AllocSetDelete(MemoryContext context)
 				freelist->num_free--;
 
 				/* All that remains is to free the header/initial block */
-				free(oldset);
+				free_and_count(oldset, oldset->header.mem_allocated);
 			}
 			Assert(freelist->num_free == 0);
 		}
@@ -666,16 +670,20 @@ AllocSetDelete(MemoryContext context)
 	while (block != NULL)
 	{
 		AllocBlock	next = block->next;
+		Size		deallocation_size = 0;
 
 		if (!IsKeeperBlock(set, block))
-			context->mem_allocated -= block->endptr - ((char *) block);
+		{
+			deallocation_size = block->endptr - ((char *) block);
+			context->mem_allocated -= deallocation_size;
+		}
 
 #ifdef CLOBBER_FREED_MEMORY
 		wipe_mem(block, block->freeptr - ((char *) block));
 #endif
 
 		if (!IsKeeperBlock(set, block))
-			free(block);
+			free_and_count(block, deallocation_size);
 
 		block = next;
 	}
@@ -683,7 +691,7 @@ AllocSetDelete(MemoryContext context)
 	Assert(context->mem_allocated == keepersize);
 
 	/* Finally, free the context header, including the keeper block */
-	free(set);
+	free_and_count(set, keepersize);
 }
 
 /*
@@ -712,7 +720,7 @@ AllocSetAllocLarge(MemoryContext context, Size size, int flags)
 #endif
 
 	blksize = chunk_size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
-	block = (AllocBlock) malloc(blksize);
+	block = (AllocBlock) malloc_and_count(blksize);
 	if (block == NULL)
 		return MemoryContextAllocationFailure(context, size, flags);
 
@@ -905,7 +913,7 @@ AllocSetAllocFromNewBlock(MemoryContext context, Size size, int flags,
 		blksize <<= 1;
 
 	/* Try to allocate it */
-	block = (AllocBlock) malloc(blksize);
+	block = (AllocBlock) malloc_and_count(blksize);
 
 	/*
 	 * We could be asking for pretty big blocks here, so cope if malloc fails.
@@ -916,7 +924,7 @@ AllocSetAllocFromNewBlock(MemoryContext context, Size size, int flags,
 		blksize >>= 1;
 		if (blksize < required_size)
 			break;
-		block = (AllocBlock) malloc(blksize);
+		block = (AllocBlock) malloc_and_count(blksize);
 	}
 
 	if (block == NULL)
@@ -1071,6 +1079,7 @@ AllocSetFree(void *pointer)
 	{
 		/* Release single-chunk block. */
 		AllocBlock	block = ExternalChunkGetBlock(chunk);
+		Size		deallocation_size;
 
 		/*
 		 * Try to verify that we have a sane block pointer: the block header
@@ -1099,12 +1108,13 @@ AllocSetFree(void *pointer)
 		if (block->next)
 			block->next->prev = block->prev;
 
-		set->header.mem_allocated -= block->endptr - ((char *) block);
+		deallocation_size = block->endptr - ((char *) block);
+		set->header.mem_allocated -= deallocation_size;
 
 #ifdef CLOBBER_FREED_MEMORY
 		wipe_mem(block, block->freeptr - ((char *) block));
 #endif
-		free(block);
+		free_and_count(block, deallocation_size);
 	}
 	else
 	{
@@ -1223,7 +1233,7 @@ AllocSetRealloc(void *pointer, Size size, int flags)
 		blksize = chksize + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
 		oldblksize = block->endptr - ((char *) block);
 
-		block = (AllocBlock) realloc(block, blksize);
+		block = (AllocBlock) realloc_and_count(block, blksize, oldblksize);
 		if (block == NULL)
 		{
 			/* Disallow access to the chunk header. */
diff --git a/src/backend/utils/mmgr/generation.c b/src/backend/utils/mmgr/generation.c
index 0238c111d2..c7ec138110 100644
--- a/src/backend/utils/mmgr/generation.c
+++ b/src/backend/utils/mmgr/generation.c
@@ -37,6 +37,7 @@
 
 #include "lib/ilist.h"
 #include "port/pg_bitutils.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_internal.h"
@@ -206,7 +207,7 @@ GenerationContextCreate(MemoryContext parent,
 	 * Allocate the initial block.  Unlike other generation.c blocks, it
 	 * starts with the context header and its block header follows that.
 	 */
-	set = (GenerationContext *) malloc(allocSize);
+	set = (GenerationContext *) malloc_and_count(allocSize);
 	if (set == NULL)
 	{
 		MemoryContextStats(TopMemoryContext);
@@ -330,7 +331,7 @@ GenerationDelete(MemoryContext context)
 	/* Reset to release all releasable GenerationBlocks */
 	GenerationReset(context);
 	/* And free the context header and keeper block */
-	free(context);
+	free_and_count(context, context->mem_allocated + MAXALIGN(sizeof(GenerationContext)));
 }
 
 /*
@@ -361,7 +362,7 @@ GenerationAllocLarge(MemoryContext context, Size size, int flags)
 	required_size = chunk_size + Generation_CHUNKHDRSZ;
 	blksize = required_size + Generation_BLOCKHDRSZ;
 
-	block = (GenerationBlock *) malloc(blksize);
+	block = (GenerationBlock *) malloc_and_count(blksize);
 	if (block == NULL)
 		return MemoryContextAllocationFailure(context, size, flags);
 
@@ -482,7 +483,7 @@ GenerationAllocFromNewBlock(MemoryContext context, Size size, int flags,
 	if (blksize < required_size)
 		blksize = pg_nextpower2_size_t(required_size);
 
-	block = (GenerationBlock *) malloc(blksize);
+	block = (GenerationBlock *) malloc_and_count(blksize);
 
 	if (block == NULL)
 		return MemoryContextAllocationFailure(context, size, flags);
@@ -663,6 +664,9 @@ GenerationBlockFreeBytes(GenerationBlock *block)
 static inline void
 GenerationBlockFree(GenerationContext *set, GenerationBlock *block)
 {
+	/* Have to store the value locally, block will be wiped. */
+	Size	blksize = block->blksize;
+
 	/* Make sure nobody tries to free the keeper block */
 	Assert(!IsKeeperBlock(set, block));
 	/* We shouldn't be freeing the freeblock either */
@@ -671,13 +675,13 @@ GenerationBlockFree(GenerationContext *set, GenerationBlock *block)
 	/* release the block from the list of blocks */
 	dlist_delete(&block->node);
 
-	((MemoryContext) set)->mem_allocated -= block->blksize;
+	((MemoryContext) set)->mem_allocated -= blksize;
 
 #ifdef CLOBBER_FREED_MEMORY
-	wipe_mem(block, block->blksize);
+	wipe_mem(block, blksize);
 #endif
 
-	free(block);
+	free_and_count(block, blksize);
 }
 
 /*
diff --git a/src/backend/utils/mmgr/slab.c b/src/backend/utils/mmgr/slab.c
index 3e15d59683..b8baea6c98 100644
--- a/src/backend/utils/mmgr/slab.c
+++ b/src/backend/utils/mmgr/slab.c
@@ -69,6 +69,7 @@
 #include "postgres.h"
 
 #include "lib/ilist.h"
+#include "utils/backend_status.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_internal.h"
@@ -361,7 +362,7 @@ SlabContextCreate(MemoryContext parent,
 
 
 
-	slab = (SlabContext *) malloc(Slab_CONTEXT_HDRSZ(chunksPerBlock));
+	slab = (SlabContext *) malloc_and_count(Slab_CONTEXT_HDRSZ(chunksPerBlock));
 	if (slab == NULL)
 	{
 		MemoryContextStats(TopMemoryContext);
@@ -451,7 +452,7 @@ SlabReset(MemoryContext context)
 #ifdef CLOBBER_FREED_MEMORY
 		wipe_mem(block, slab->blockSize);
 #endif
-		free(block);
+		free_and_count(block, slab->blockSize);
 		context->mem_allocated -= slab->blockSize;
 	}
 
@@ -467,7 +468,7 @@ SlabReset(MemoryContext context)
 #ifdef CLOBBER_FREED_MEMORY
 			wipe_mem(block, slab->blockSize);
 #endif
-			free(block);
+			free_and_count(block, slab->blockSize);
 			context->mem_allocated -= slab->blockSize;
 		}
 	}
@@ -484,10 +485,14 @@ SlabReset(MemoryContext context)
 void
 SlabDelete(MemoryContext context)
 {
+#ifdef MEMORY_CONTEXT_CHECKING
+	SlabContext *slab = (SlabContext *) context;
+#endif
+
 	/* Reset to release all the SlabBlocks */
 	SlabReset(context);
 	/* And free the context header */
-	free(context);
+	free_and_count(context, Slab_CONTEXT_HDRSZ(slab->chunksPerBlock));
 }
 
 /*
@@ -562,7 +567,7 @@ SlabAllocFromNewBlock(MemoryContext context, Size size, int flags)
 	}
 	else
 	{
-		block = (SlabBlock *) malloc(slab->blockSize);
+		block = (SlabBlock *) malloc_and_count(slab->blockSize);
 
 		if (unlikely(block == NULL))
 			return MemoryContextAllocationFailure(context, size, flags);
@@ -795,7 +800,7 @@ SlabFree(void *pointer)
 #ifdef CLOBBER_FREED_MEMORY
 			wipe_mem(block, slab->blockSize);
 #endif
-			free(block);
+			free_and_count(block, slab->blockSize);
 			slab->header.mem_allocated -= slab->blockSize;
 		}
 
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 2dcc2d42da..16dd4a0d97 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8442,6 +8442,20 @@
   proargmodes => '{o,o,o,o,o,o,o,o,o,o}',
   proargnames => '{name, ident, type, level, path, total_bytes, total_nblocks, free_bytes, free_chunks, used_bytes}',
   prosrc => 'pg_get_backend_memory_contexts' },
+{ oid => '8085',
+  descr => 'get the allocated memory in all memory contexts of local backend',
+  proname => 'pg_get_backend_memory_contexts_total_bytes', provolatile => 'v',
+  proparallel => 'r', prorettype => 'int8', proargtypes => '',
+  prosrc => 'pg_get_backend_memory_contexts_total_bytes' },
+{ oid => '8005',
+  descr => 'information about memory allocation of local backend',
+  proname => 'pg_get_backend_memory_allocation_stats', prorows => '1024',
+  proretset => 't', provolatile => 'v', proparallel => 'r',
+  prorettype => 'record', proargtypes => '',
+  proallargtypes => '{text,int8,bool}',
+  proargmodes => '{o,o,o}',
+  proargnames => '{pointer, size, deleted}',
+  prosrc => 'pg_get_backend_memory_allocation_stats' },
 
 # logging memory contexts of the specified backend
 { oid => '4543', descr => 'log memory contexts of the specified backend',
diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h
index 4e8b39a66d..26b9338b2f 100644
--- a/src/include/utils/backend_status.h
+++ b/src/include/utils/backend_status.h
@@ -11,6 +11,7 @@
 #define BACKEND_STATUS_H
 
 #include "datatype/timestamp.h"
+#include "fmgr.h"
 #include "libpq/pqcomm.h"
 #include "miscadmin.h"			/* for BackendType */
 #include "storage/procnumber.h"
@@ -285,6 +286,7 @@ typedef struct LocalPgBackendStatus
  */
 extern PGDLLIMPORT bool pgstat_track_activities;
 extern PGDLLIMPORT int pgstat_track_activity_query_size;
+extern PGDLLIMPORT int max_backend_memory_size_mb;
 
 
 /* ----------
@@ -337,5 +339,13 @@ extern LocalPgBackendStatus *pgstat_get_local_beentry_by_proc_number(ProcNumber
 extern LocalPgBackendStatus *pgstat_get_local_beentry_by_index(int idx);
 extern char *pgstat_clip_activity(const char *raw_activity);
 
+/*
+ * Fuctions to count memory
+ */
+extern void *malloc_and_count(Size size);
+extern void *realloc_and_count(void *ptr, Size new_size, Size old_size);
+extern void free_and_count(void *ptr, Size size);
+extern Datum pg_get_backend_memory_contexts_total_bytes(PG_FUNCTION_ARGS);
+extern Datum pg_get_backend_memory_allocation_stats(PG_FUNCTION_ARGS);
 
 #endif							/* BACKEND_STATUS_H */
diff --git a/src/test/modules/Makefile b/src/test/modules/Makefile
index c0d3cf0e14..f011f29b27 100644
--- a/src/test/modules/Makefile
+++ b/src/test/modules/Makefile
@@ -54,6 +54,10 @@ else
 ALWAYS_SUBDIRS += ssl_passphrase_callback
 endif
 
+ifneq (test_backend_memory,$(filter test_backend_memory,$(PG_TEST_SKIP)))
+SUBDIRS += test_backend_memory
+endif
+
 # Test runs an LDAP server, so only run if ldap is in PG_TEST_EXTRA
 ifeq ($(with_ldap),yes)
 ifneq (,$(filter ldap,$(PG_TEST_EXTRA)))
diff --git a/src/test/modules/test_backend_memory/.gitignore b/src/test/modules/test_backend_memory/.gitignore
new file mode 100644
index 0000000000..5dcb3ff972
--- /dev/null
+++ b/src/test/modules/test_backend_memory/.gitignore
@@ -0,0 +1,4 @@
+# Generated subdirectories
+/log/
+/results/
+/tmp_check/
diff --git a/src/test/modules/test_backend_memory/Makefile b/src/test/modules/test_backend_memory/Makefile
new file mode 100644
index 0000000000..c6afaedd0a
--- /dev/null
+++ b/src/test/modules/test_backend_memory/Makefile
@@ -0,0 +1,14 @@
+# src/test/modules/test_backend_memory/Makefile
+
+TAP_TESTS = 1
+
+ifdef USE_PGXS
+PG_CONFIG = pg_config
+PGXS := $(shell $(PG_CONFIG) --pgxs)
+include $(PGXS)
+else
+subdir = src/test/modules/test_backend_memory
+top_builddir = ../../../..
+include $(top_builddir)/src/Makefile.global
+include $(top_srcdir)/contrib/contrib-global.mk
+endif
diff --git a/src/test/modules/test_backend_memory/README b/src/test/modules/test_backend_memory/README
new file mode 100644
index 0000000000..95ffe2c438
--- /dev/null
+++ b/src/test/modules/test_backend_memory/README
@@ -0,0 +1 @@
+This directory contain tests for max_backend_memory GUC
diff --git a/src/test/modules/test_backend_memory/t/001_max_backend_memory.pl b/src/test/modules/test_backend_memory/t/001_max_backend_memory.pl
new file mode 100644
index 0000000000..c479f6ec4f
--- /dev/null
+++ b/src/test/modules/test_backend_memory/t/001_max_backend_memory.pl
@@ -0,0 +1,85 @@
+# Tests to check backend memory limit (max_backend_memory GUC)
+
+use strict;
+use warnings;
+use PostgreSQL::Test::Cluster;
+use PostgreSQL::Test::Utils;
+use Test::More;
+
+my $node = PostgreSQL::Test::Cluster->new('main');
+$node->init;
+$node->start;
+
+# Initialize backend memory limit
+$node->safe_psql('postgres', qq{
+	ALTER SYSTEM SET max_backend_memory = 15;
+	SELECT pg_reload_conf();
+});
+
+# Check backend memory limit after SET.
+my $psql_stdout;
+$psql_stdout = $node->safe_psql('postgres',
+								"SELECT current_setting('max_backend_memory');");
+is($psql_stdout, '15MB', "max_backend_memory is SET correctly");
+
+# Create test table and function.
+$node->safe_psql('postgres', q{
+	CREATE TABLE test(t text);
+	INSERT INTO test VALUES (repeat('1234567890', 400000));
+
+	-- Recursive function that should cause overflow
+	CREATE FUNCTION test_func() RETURNS void LANGUAGE plpgsql AS $$
+	DECLARE
+		bt text;
+	BEGIN
+		SELECT t || 'x' FROM test INTO bt;
+		PERFORM test_func();
+	END;
+$$;
+});
+
+# Call function "test_func" several times for memory leak check.
+my $psql_stdout_first;
+for (my $i = 0; $i < 4; $i++)
+{
+	# Call function and check that it finishes with 'out of memory' error.
+	my ($ret, $stdout, $stderr) = $node->psql('postgres',
+											  "SELECT test_func();");
+	is($ret, 3, 'recursive function call causes overflow');
+	like($stderr, qr/out of memory/, 'expected out of memory error');
+
+	$psql_stdout = $node->safe_psql('postgres',
+									"SELECT pg_get_backend_memory_contexts_total_bytes();");
+	if ($i eq 0)
+	{
+		# Store first value of backend_memory_contexts_total_bytes.
+		$psql_stdout_first = $psql_stdout;
+		is($psql_stdout_first > 0, 1,
+		   "backend has allocated $psql_stdout_first (greater than 0) bytes");
+		next;
+	}
+	# Check other values of backend_memory_contexts_total_bytes.
+	# They should be the same as first value.
+	is($psql_stdout, $psql_stdout_first, "memory does not leak");
+}
+
+# Drop test table and function.
+$node->safe_psql('postgres', q{
+	DROP FUNCTION test_func();
+	DROP TABLE test;
+});
+
+# Deinitialize backend memory limit.
+$node->safe_psql('postgres', q{
+	ALTER SYSTEM RESET max_backend_memory;
+	SELECT pg_reload_conf();
+});
+
+# Check backend memory limit after RESET.
+$psql_stdout = $node->safe_psql('postgres',
+								"SELECT current_setting('max_backend_memory');");
+is($psql_stdout, '0', "max_backend_memory is RESET correctly");
+
+$node->stop;
+
+done_testing();
-- 
2.47.1

#63Tomas Vondra
tomas@vondra.me
In reply to: Anton A. Melnikov (#62)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On 12/28/24 13:36, Anton A. Melnikov wrote:

Hi!

On 28.12.2024 04:48, Tomas Vondra wrote:

On 12/27/24 20:14, James Hunter wrote:

Reviving this thread, because I am thinking about something related --
please ignore the "On Fri, Dec 27, 2024" date, this seems to be an
artifact of me re-sending the message, from the list archive. The
original message was from January 28, 2024.

On Fri, Dec 27, 2024 at 11:02 AM Tomas Vondra
<tomas.vondra@enterprisedb.com> wrote:

Firstly, I agree with the goal of having a way to account for memory
used by the backends, and also ability to enforce some sort of limit.
It's difficult to track the memory at the OS level (interpreting RSS
values is not trivial), and work_mem is not sufficient to enforce a
backend-level limit, not even talking about a global limit.

But as I said earlier, it seems quite strange to start by introducing
some sort of global limit, combining memory for all backends. I do
understand that the intent is to have such global limit in order to
prevent issues with the OOM killer and/or not to interfere with other
stuff running on the same machine. And while I'm not saying we should
not have such limit, every time I wished to have a memory limit it
was a
backend-level one. Ideally a workmem-like limit that would "adjust" the
work_mem values used by the optimizer (but that's not what this patch
aims to do), or at least a backstop in case something goes wrong
(say, a
memory leak, OLTP application issuing complex queries, etc.).

I think what Tomas suggests is the right strategy.

I'm also interested in this topic. And agreed that it's best to move
from the limit
for a separate backend to the global one. In more details let me suggest
the following steps or parts:
1) realize memory limitation for a separate backend independent from the
work_mem GUC;
2) add workmem-like limit that would "adjust" the work_mem values used by
the optimize as Thomas suggested;
3) add global limit for all backends.

As for p.1 there is a patch that was originally suggested by my colleague
Maxim Orlov <orlovmg@gmail.com> and which i modified for the current
master.
This patch introduces the only max_backend_memory GUC that specifies
the maximum amount of memory that can be allocated to a backend.
Zero value means no limit.
If the allocated memory size is exceeded, a standard "out of memory"
error will be issued.
Also the patch introduces the
pg_get_backend_memory_contexts_total_bytes() function,
which allows to know how many bytes have already been allocated
to the process in contexts. And in the build with asserts it adds
the pg_get_backend_memory_allocation_stats() function that allows
to get additional information about memory allocations for debug purposes.

Not sure a simple memory limit like in the patch (which just adds memory
accounting + OOM after hitting the limit) can work as anything but a the
last safety measure. It seems to me the limit would have to be set to a
value that's much higher than any backend would realistically need.

The first challenge I envision is that without any feedback (either to
the planner or executor), it may break queries quite easily. It just
takes the planner to add one more sort / hash join / materialize (which
it can do arbitrarily, as it has no concept of the memory limit), and
now the query can't run.

And secondly, there are allocations that we don't restrict by work_mem,
but this memory limit would include them, ofc. The main example that I
can think of is hash join, where we (currently) don't account for the
BufFile arrays, and that can already lead to annoying OOM issues, see
e.g. [1]/messages/by-id/20190504003414.bulcbnge3rhwhcsh@development [2]/messages/by-id/20230228190643.1e368315@karst and [3]/messages/by-id/bc138e9f-c89e-9147-5395-61d51a757b3b@gusw.net (I'm sure there are more threads about the issue).

It's wrong we don't account for the BufFile arrays, so it's not included
in work_mem (or considered is some other way). And maybe we should
finally improve that (not the fault of this patch, ofc). But it's hard,
because as the amount of data grows, we have to add more batches - and
at some point that starts adding more memory than we save. Ultimately,
we end up breaking work_mem one way or the other - either we add more
batches, or allow the hash table to exceed work_mem.

That's a preexisting issue, of course. But wouldn't this simple limit
make the situation worse? The query would likely complete OK (otherwise
we'd get many more reports about OOM), but with the new limit it would
probably fail with OOM. Maybe that's correct, and the response to that
is "Don't set the limit with such queries," although it's hard to say in
advance and it can happen randomly? Not sure.

What bothers me a bit is that users would likely try to reduce work_mem,
but that's the wrong thing to do in this case - it just increases the
number of batches, and thus makes the situation worse.

[1]: /messages/by-id/20190504003414.bulcbnge3rhwhcsh@development
/messages/by-id/20190504003414.bulcbnge3rhwhcsh@development

[2]: /messages/by-id/20230228190643.1e368315@karst

[3]: /messages/by-id/bc138e9f-c89e-9147-5395-61d51a757b3b@gusw.net
/messages/by-id/bc138e9f-c89e-9147-5395-61d51a757b3b@gusw.net

This strategy solves the ongoing problem of how to set work_mem, if
some queries have lots of operators and others don't -- now we just
set backend_work_mem, as a limit on the entire query's total work_mem.
And a bit of integration with the optimizer will allow us to
distribute the total backend_work_mem to individual execution nodes,
with the goal of minimizing spilling, without exceeding the
backend_work_mem limit.

As for p.2 maybe one can set a maximum number of parallel sort or
hash table operations before writing to disk instead of absolute
value in the work_mem GUC? E.g. introduce а max_query_operations GUC
or a variable in such a way that old work_mem will be equal
to max_backend_memory divided by max_query_operations.

What do you think about such approach?

It's not clear to me how you want to calculate the number of parallel
operations that might use work_mem. Can you elaborate?

regards

--
Tomas Vondra

#64Jeremy Schneider
schneider@ardentperf.com
In reply to: Tomas Vondra (#63)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On Sat, 28 Dec 2024 15:57:44 +0100
Tomas Vondra <tomas@vondra.me> wrote:

Not sure a simple memory limit like in the patch (which just adds
memory accounting + OOM after hitting the limit) can work as anything
but a the last safety measure. It seems to me the limit would have to
be set to a value that's much higher than any backend would
realistically need.

The first challenge I envision is that without any feedback (either to
the planner or executor), it may break queries quite easily. It just
takes the planner to add one more sort / hash join / materialize
(which it can do arbitrarily, as it has no concept of the memory
limit), and now the query can't run.

And secondly, there are allocations that we don't restrict by
work_mem, but this memory limit would include them, ofc. The main
example that I can think of is hash join, where we (currently) don't
account for the BufFile arrays, and that can already lead to annoying
OOM issues, see e.g. [1] [2] and [3] (I'm sure there are more threads
about the issue).

Hi James!

While I don't have a detailed design in mind, I'd like to add a strong
+1 on the general idea that work_mem is hard to effectively use because
queries can vary so widely in how many nodes might need work memory.

I'd almost like to have two limits:

First, a hard per-connection limit which could be set very high - we
can track total memory usage across contexts inside of palloc and pfree
(and maybe this could also be exposed in pg_stat_activity for easy
visibility into a snapshot of memory use across all backends). If
palloc detects that an allocation would take the total over the hard
limit, then you just fail the palloc with an OOM. This protects
postgres from a memory leak in a single backend OOM'ing the whole
system and restarting the whole database; failing a single connection
is better than failing all of them.

Second, a soft per-connection "total_connection_work_mem_target" which
could be set lower. The planner can just look at the total number of
nodes that it expects to allocate work memory, divide the target by
this and then set the work_mem for that query. There should be a
reasonable floor (minimum) for work_mem - maybe the value of work_mem
itself becomes this and the new target doesn't do anything besides
increasing runtime work_mem.

Maybe even could do a "total_instance_work_mem_target" where it's
divided by the number of average active connections or something.

In practice this target idea doesn't guarantee anything about total work
memory used, but it's the tool I'd most like as an admin. And the
per-connection hard limit is the tool I'd like to have for protecting
myself against memory leaks or individual connections going bonkers and
killing all my connections for an instance restart.

-Jeremy

#65Jim Nasby
jnasby@upgrade.com
In reply to: Jeremy Schneider (#64)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On Dec 28, 2024, at 12:26 PM, Jeremy Schneider <schneider@ardentperf.com> wrote:

While I don't have a detailed design in mind, I'd like to add a strong
+1 on the general idea that work_mem is hard to effectively use because
queries can vary so widely in how many nodes might need work memory.

I'd almost like to have two limits:

First, a hard per-connection limit which could be set very high - we
can track total memory usage across contexts inside of palloc and pfree
(and maybe this could also be exposed in pg_stat_activity for easy
visibility into a snapshot of memory use across all backends). If
palloc detects that an allocation would take the total over the hard
limit, then you just fail the palloc with an OOM. This protects
postgres from a memory leak in a single backend OOM'ing the whole
system and restarting the whole database; failing a single connection
is better than failing all of them.

Second, a soft per-connection "total_connection_work_mem_target" which
could be set lower. The planner can just look at the total number of
nodes that it expects to allocate work memory, divide the target by
this and then set the work_mem for that query. There should be a
reasonable floor (minimum) for work_mem - maybe the value of work_mem
itself becomes this and the new target doesn't do anything besides
increasing runtime work_mem.

Maybe even could do a "total_instance_work_mem_target" where it's
divided by the number of average active connections or something.

IMHO none of this will be very sane until we actually have cluster-level limits. One sudden burst in active connections and you still OOM the instance. And while we could have such a mechanism do something clever like dynamically lowering every sessions query_mem/work_mem/whatever, ultimately I think it would also need the ability to deny or delay sessions from starting new transactions.

#66James Hunter
james.hunter.pg@gmail.com
In reply to: Tomas Vondra (#61)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On Fri, Dec 27, 2024 at 5:48 PM Tomas Vondra <tomas@vondra.me> wrote:

Whenever I've been thinking about this in the past, it wasn't clear to
me how would we know when to start adjusting work_mem, because we don't
know which nodes will actually use work_mem concurrently.

You certainly know the PostgreSQL source code better than I do, but
just looking over nodeHash[join].c, for example, it looks like we
don't call ExecHashTableDestroy() until ExecEndHashJoin() or
ExecReScanHashJoin(). I am assuming this means that we don't destroy
the hash table (and therefore don't free the work_mem) until we either
(a) end the executor for the entire query plan, or (b) rescan the hash
join.

Does PostgreSQL currently rescan Hash Joins when they are "no longer
needed," to free work_mem early? If so, then I would try to reuse this
existing logic to decide which nodes need work_mem concurrently.

If not, then all nodes that use work_mem actually use it
"concurrently," because we don't free that work_mem until we call
ExecutorEnd().

Or, is the problem that one query might generate and execute a second
query, recursively? (And the second might generate and execute a third
query, etc.?) For example, the first query might call a function that
starts a new portal and executes a second query, and so on. Is this
what you're thinking about? If so, I would model this pattern as each
level of recursion taking up, logically, a "new connection."

Thanks,
James

#67David Rowley
dgrowleyml@gmail.com
In reply to: James Hunter (#66)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On Tue, 31 Dec 2024 at 10:11, James Hunter <james.hunter.pg@gmail.com> wrote:

Does PostgreSQL currently rescan Hash Joins when they are "no longer
needed," to free work_mem early? If so, then I would try to reuse this
existing logic to decide which nodes need work_mem concurrently.

If not, then all nodes that use work_mem actually use it
"concurrently," because we don't free that work_mem until we call
ExecutorEnd().

The problem with that statement is that Hash Join isn't the only node
type that uses work_mem. Plenty of other node types do. Have a look
at MultiExecBitmapOr(). You can see logic there that does tbm_free()
after the tbm_union() call. Going by that, it seems there is at least
one place where we might free some work_mem memory before allocating
another lot.

David

#68David Rowley
dgrowleyml@gmail.com
In reply to: James Hunter (#60)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On Sat, 28 Dec 2024 at 08:14, James Hunter <james.hunter.pg@gmail.com> wrote:

2. We use this backend_work_mem to "adjust" work_mem values used by
the executor. (I don't care about the optimizer right now -- optimizer
just does its best to predict what will happen at runtime.)

While I do want to see improvements in this area, I think "don't care
about the optimizer" is going to cause performance issues. The
problem is that the optimizer takes into account what work_mem is set
to when calculating the costs of work_mem-consuming node types. See
costsize.c for usages of "work_mem". If you go and reduce the amount
of memory a given node can consume after the costs have been applied
then we may end up in a situation where some other plan would have
suited much better.

There's also the problem with what to do when you chop work_mem down
so far that the remaining size is just a pitiful chunk. For now,
work_mem can't go below 64 kilobytes. You might think that's a very
unlikely situation that it'd be chopped down so far, but with
partition-wise join and partition-wise aggregate, we could end up
using a work_mem per partition and if you have thousands of partitions
then you might end up reducing work_mem by quite a large amount.

I think the best solution to this is the memory grant stuff I talked
about in [1]/messages/by-id/CAApHDvrzacGEA1ZRea2aio_LAi2fQcgoK74bZGfBddg4ymW-Ow@mail.gmail.com. That does require figuring out which nodes will consume
the work_mem concurrently so that infrastructure you talked about to
do that would be a good step forward towards that, but that's probably
not the most difficult part of that idea.

I definitely encourage work in this area, but I think what you're
proposing might be swapping one problem for another problem.

David

[1]: /messages/by-id/CAApHDvrzacGEA1ZRea2aio_LAi2fQcgoK74bZGfBddg4ymW-Ow@mail.gmail.com

#69James Hunter
james.hunter.pg@gmail.com
In reply to: David Rowley (#67)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On Mon, Dec 30, 2024 at 2:56 PM David Rowley <dgrowleyml@gmail.com> wrote:

On Tue, 31 Dec 2024 at 10:11, James Hunter <james.hunter.pg@gmail.com> wrote:

Does PostgreSQL currently rescan Hash Joins when they are "no longer
needed," to free work_mem early? If so, then I would try to reuse this
existing logic to decide which nodes need work_mem concurrently.

If not, then all nodes that use work_mem actually use it
"concurrently," because we don't free that work_mem until we call
ExecutorEnd().

The problem with that statement is that Hash Join isn't the only node
type that uses work_mem. Plenty of other node types do. Have a look
at MultiExecBitmapOr(). You can see logic there that does tbm_free()
after the tbm_union() call. Going by that, it seems there is at least
one place where we might free some work_mem memory before allocating
another lot.

OK, then as a first approximation, we can assume that all nodes that
use work_mem, use it concurrently. This assumption seems to hold for
Hash Join and [Hash] Agg. PostgreSQL already considers the hash
operations "more important," in some sense, than other operators that
use work_mem -- this is why they get to multiply by
hash_mem_multiplier (defaulted to 2.0).

I think the above approximation answers Tomas's first concern. For
now, we can assume that the amount of work memory used by a query is
the sum of the individual work memories used by all of its operators.
(In the future, we can be more precise, for operators that free their
work memory as soon as they have no more rows to produce.)

Dividing backend_work_mem up and distributing it to the query's
operators would, I think, work something like the following, using a
two-phase algorithm:

1. Planner records the nbytes it estimated, for a given Path, on that
Path. However, it would continue to make its costing (and
partitioning, for parallel Hash Join) decisions, same as before, using
"work_mem [* hash_mem_multiplier]". (So "work_mem" behaves sort of
like a hint to the optimizer.)

2. At runtime, executor checks backend_work_mem. It sums up all the
nbytes fields from all the query's Paths, and compares to
backend_work_mem. And then it sets each node's work_mem field to some
fraction of the total backend_work_mem, based on nbytes and work_mem.

3. Each node then runs exactly as it does now, except instead of
checking the global work_mem [* hash_mem_multiplier] GUCs, it checks
its own work_mem field.

The "proportion" chosen in (2) should probably take into account
nbytes, work_mem, hash_mem_multiplier, etc. I think we'd want it to
overprovision work memory for nodes/paths with small nbytes, to
mitigate error in planner estimates.

James

#70James Hunter
james.hunter.pg@gmail.com
In reply to: Tomas Vondra (#63)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On Sat, Dec 28, 2024 at 6:57 AM Tomas Vondra <tomas@vondra.me> wrote:

On 12/28/24 13:36, Anton A. Melnikov wrote:

... In more details let me suggest
the following steps or parts:
1) realize memory limitation for a separate backend independent from the
work_mem GUC;
2) add workmem-like limit that would "adjust" the work_mem values used by
the optimize as Thomas suggested;
3) add global limit for all backends.

As for p.1 there is a patch that was originally suggested by my colleague
Maxim Orlov <orlovmg@gmail.com> and which i modified for the current
master.
This patch introduces the only max_backend_memory GUC that specifies
the maximum amount of memory that can be allocated to a backend.
...
If the allocated memory size is exceeded, a standard "out of memory"
error will be issued.

Yes this seems like a reasonable plan. I would add that (2) might be
good enough to solve (1), without needing to emit an "out of memory"
error.

Not sure a simple memory limit like in the patch (which just adds memory
accounting + OOM after hitting the limit) can work as anything but a the
last safety measure.

I agree -- since PG already has the ability to spill operators, I
think we can avoid using too much "working memory" without too much
coding effort.

Now, PG uses memory for things other than what's captured in "working
memory," so there is probably still some value in a (1) that kills the
query or backend.

The first challenge I envision is that without any feedback (either to
the planner or executor), it may break queries quite easily. It just
takes the planner to add one more sort / hash join / materialize (which
it can do arbitrarily, as it has no concept of the memory limit), and
now the query can't run.

Yes -- the planner figures it can allocate another work_mem [*
hash_mem_multiplier] for any new sort / hash join / materialize. It
doesn't know about per-backend memory limits.

That's why (2) is so nice, because it tells the executor (but, to keep
things simple, not the planner) how much working memory it *actually*
has available. And then the executor will (try to) spill rather than
exceed that actual limit.

And secondly, there are allocations that we don't restrict by work_mem,
but this memory limit would include them, ofc.

I'm neutral on this subject. The example you gave, of BufFile arrays,
should be included in the working-memory calculation, but there will
always be other sources of memory unaccounted for... I'm neutral on
how to deal with these cases...

That's a preexisting issue, of course. But wouldn't this simple limit
make the situation worse? The query would likely complete OK (otherwise
we'd get many more reports about OOM), but with the new limit it would
probably fail with OOM.

If I understand your point, you're saying that killing a query due to
OOM is OK if the "OOM" is based on the amount of available *global*
memory going to 0, but you're not comfortable doing this when
*per-backend* memory goes to 0.

I think you're right. A per-backend limit is nice because it can be
distributed to individual operators as per-operator working memory,
because operators will just spill. But killing a query based on an
approximation of how much memory we have seems like an overreaction.

Thanks,
James

#71James Hunter
james.hunter.pg@gmail.com
In reply to: Jeremy Schneider (#64)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On Sat, Dec 28, 2024 at 10:26 AM Jeremy Schneider
<schneider@ardentperf.com> wrote:

Thanks for the feedback, Jeremy!

While I don't have a detailed design in mind, I'd like to add a strong
+1 on the general idea that work_mem is hard to effectively use because
queries can vary so widely in how many nodes might need work memory.

That's my main concern with work_mem. Even if I am running a single
query at a time, on a single connection, I still run into the
limitations of the work_mem GUC if I try to run:

(a) a query with a single large Hash Join; vs.
(b) a query with, say, 10 Hash Joins, some of which are small and
others of which are large.

In (a), I want to set work_mem to the total amount of memory available
on the system. In (b), I *don't* want to set it to "(a) / 10", because
I want some Hash Joins to get more memory than others.

It's just really hard to distribute working memory intelligently,
using this GUC!

I'd almost like to have two limits:

First, a hard per-connection limit which could be set very high

... If
palloc detects that an allocation would take the total over the hard
limit, then you just fail the palloc with an OOM. This protects
postgres from a memory leak in a single backend OOM'ing the whole
system and restarting the whole database; failing a single connection
is better than failing all of them.

Yes, this seems fine to me. Per Tomas's comments in [1]/messages/by-id/4806d917-c019-49c7-9182-1203129cd295@vondra.me ,the "OOM"
limit would probably have to be global.

Second, a soft per-connection "total_connection_work_mem_target" which
could be set lower. The planner can just look at the total number of
nodes that it expects to allocate work memory, divide the target by
this and then set the work_mem for that query.

I wouldn't even bother to inform the planner of the "actual" working
memory, because that adds complexity to the query compilation process.

Just: planner assumes it will have "work_mem" per node, but records
how much memory it estimates it will use ("nbytes") [2]/messages/by-id/CAJVSvF6i_1Em6VPZ9po5wyTubGwifvfNFLrOYrdgT-e1GmR5Fw@mail.gmail.com. The executor
then sets the "actual" work_mem, for each node, based on nbytes and
the global "work_mem" GUC.

(It's hard for the planner to decide how much memory each path / node
should get, while building and costing plans. E.g., is it better to
take X MB of working memory from join 1 and hand it to join 2, which
would cause join 1 to spill Y% more data, but join 2 to spill Z%
less?)

Maybe even could do a "total_instance_work_mem_target" where it's
divided by the number of average active connections or something.

This seems fine to me, but I prefer "backend_work_mem_target", because
I find multiplying easier than dividing. (E.g., if I add 2 more
backends, I would use up to "backend_work_mem_target" * 2 more memory.
Vs., each query now gets "total_instance_work_mem_target / (N+2)"
memory...)

[1]: /messages/by-id/4806d917-c019-49c7-9182-1203129cd295@vondra.me
[2]: /messages/by-id/CAJVSvF6i_1Em6VPZ9po5wyTubGwifvfNFLrOYrdgT-e1GmR5Fw@mail.gmail.com

Thanks,
James

#72James Hunter
james.hunter.pg@gmail.com
In reply to: Jim Nasby (#65)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On Sat, Dec 28, 2024 at 11:24 PM Jim Nasby <jnasby@upgrade.com> wrote:

IMHO none of this will be very sane until we actually have cluster-level limits. One sudden burst in active connections and you still OOM the instance.

Fwiw, PG does support "max_connections" GUC, so a backend/connection -
level limit, times "max_connections", yields a cluster-level limit.

Now, which is easier for customers to understand -- that's up for debate!

James

#73James Hunter
james.hunter.pg@gmail.com
In reply to: David Rowley (#68)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On Mon, Dec 30, 2024 at 3:12 PM David Rowley <dgrowleyml@gmail.com> wrote:

On Sat, 28 Dec 2024 at 08:14, James Hunter <james.hunter.pg@gmail.com> wrote:

2. We use this backend_work_mem to "adjust" work_mem values used by
the executor. (I don't care about the optimizer right now -- optimizer
just does its best to predict what will happen at runtime.)

While I do want to see improvements in this area, I think "don't care
about the optimizer" is going to cause performance issues. The
problem is that the optimizer takes into account what work_mem is set
to when calculating the costs of work_mem-consuming node types. See
costsize.c for usages of "work_mem". If you go and reduce the amount
of memory a given node can consume after the costs have been applied
then we may end up in a situation where some other plan would have
suited much better.

Yes, but this sort of thing is unavoidable in SQL compilers. We can
always generate and cost more paths, but that increases compile time,
which eats away at runtime.

I agree that it's good to mitigate these sorts of cases, but I see
that as a refinement on the original idea.

There's also the problem with what to do when you chop work_mem down
so far that the remaining size is just a pitiful chunk. For now,
work_mem can't go below 64 kilobytes. You might think that's a very
unlikely situation that it'd be chopped down so far, but with
partition-wise join and partition-wise aggregate, we could end up
using a work_mem per partition and if you have thousands of partitions
then you might end up reducing work_mem by quite a large amount.

I look at this from the opposite direction: if I am doing a
partition-wise join or aggregate, and that join or aggregate requires
more memory than I feel comfortable letting it use, then the current
PG behavior doesn't solve this problem, so much as throw up its hands
and hope for the best. Because if I don't have 64 KB * (# joins) * (#
join partitions), today, then either my query is going to run OOM --
or I am lying, and I really have more memory than I claim. :)

I think the best solution to this is the memory grant stuff I talked
about in [1].

I am absolutely in favor of memory grants. Long-term, I think memory
grants, like what you described in [1], are absolutely necessary.
However, per-backend limits are:
(a) easier;
(b) a good intermediate step; and
(c) still necessary in a world in which we have memory grants, to
prevent deadlocks.

In [1], you suggested using PG's deadlock detector, but this has the
side effect of killing queries, which I would like to avoid.

Even with memory grants, if you give each backend a minimal amount of
reserved working-memory, you can avoid deadlock, by making the
"offending" spill and run slowly, rather than getting canceled.

That does require figuring out which nodes will consume
the work_mem concurrently so that infrastructure you talked about to
do that would be a good step forward towards that, but that's probably
not the most difficult part of that idea.

Yeah - for example, specifying work_mem per node, on the PlanState,
gives the executor some options, if it can't checkout as much memory
as it would like.

I definitely encourage work in this area, but I think what you're
proposing might be swapping one problem for another problem.

David

[1] /messages/by-id/CAApHDvrzacGEA1ZRea2aio_LAi2fQcgoK74bZGfBddg4ymW-Ow@mail.gmail.com

Thanks for the feedback!
James

#74Jim Nasby
jnasby@upgrade.com
In reply to: James Hunter (#72)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On Dec 30, 2024, at 7:05 PM, James Hunter <james.hunter.pg@gmail.com> wrote:

On Sat, Dec 28, 2024 at 11:24 PM Jim Nasby <jnasby@upgrade.com> wrote:

IMHO none of this will be very sane until we actually have cluster-level limits. One sudden burst in active connections and you still OOM the instance.

Fwiw, PG does support "max_connections" GUC, so a backend/connection -
level limit, times "max_connections", yields a cluster-level limit.

max_connections is useless here, for two reasons:

1. Changing it requires a restart. That’s at *best* a real PITA in production. [1]
2. It still doesn’t solve the actual problem. Unless your workload *and* your data are extremely homogeneous you can’t simply limit the number of connections and call it a day. A slight change in incoming queries, OR in the data that the queries are looking at and you go from running fine to meltdown. You don’t even need a plan flip for this to happen, just the same plan run at the same rate but now accessing more data than before.

Most of what I’ve seen on this thread is discussing ways to *optimize* how much memory the set of running backends can consume. Adjusting how you slice the memory pie across backends, or even within a single backend, is optimization. While that’s a great goal that I do support, it will never fully fix the problem. At some point you need to either throw your hands in the air and start tossing memory errors, because you don’t have control over how much work is being thrown at the engine. The only way that the engine can exert control over that would be to hold new transactions from starting when the system is under duress (ie, workload management). While workload managers can be quite sophisticated (aka, complex), the nice thing about limiting this scope to work_mem, and only as a means to prevent complete overload, is that the problem becomes a lot simpler since you’re only looking at one metric and not trying to support any kind of priority system. The only fanciness I think an MVP would need is a GUC to control how long a transaction can sit waiting before it throws an error. Frankly, that sounds a lot less complex and much easier for DBAs to adjust than trying to teach the planner how to apportion out per-node work_mem limits.

As I said, I’m not opposed to optimizations, I just think they’re very much cart-before-the-horse.

1: While it’d be a lot of work to make max_connections dynamic one thing we could do fairly easily would be to introduce another GUC (max_backends?) that actually controls the total number of allowed backends for everything. The sum of max_backends + autovac workers + background workers + whatever else I’m forgetting would have to be less than that. The idea here is that you’d normally run with max_connections set significantly lower than max_backends. That means that if you need to adjust any of these GUCs (other than max_backends) you don’t need to restart - the new limits would just apply to new connection requests.

#75Tomas Vondra
tomas@vondra.me
In reply to: Jim Nasby (#74)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On 12/31/24 21:46, Jim Nasby wrote:

On Dec 30, 2024, at 7:05 PM, James Hunter <james.hunter.pg@gmail.com> wrote:

On Sat, Dec 28, 2024 at 11:24 PM Jim Nasby <jnasby@upgrade.com> wrote:

IMHO none of this will be very sane until we actually have cluster-level limits. One sudden burst in active connections and you still OOM the instance.

Fwiw, PG does support "max_connections" GUC, so a backend/connection -
level limit, times "max_connections", yields a cluster-level limit.

max_connections is useless here, for two reasons:

1. Changing it requires a restart. That’s at *best* a real PITA in production. [1]
2. It still doesn’t solve the actual problem. Unless your workload *and* your data are extremely homogeneous you can’t simply limit the number of connections and call it a day. A slight change in incoming queries, OR in the data that the queries are looking at and you go from running fine to meltdown. You don’t even need a plan flip for this to happen, just the same plan run at the same rate but now accessing more data than before.

I really don't follow your argument ...

Yes, changing max_connections requires a restart - so what? AFAIK the
point James was making is that if you multiply max_connections by the
per-backend limit, you get a cluster-wide limit. And presumably the
per-backend limit would be a GUC not requiring a restart.

Yes, high values of max_connections are problematic. I don't see how a
global limit would fundamentally change that. In fact, it could
introduce yet more weird failures because some unrelated backend did
something weird.

FWIW I'm not opposed to having some global memory limit, but as I
explained earlier, I don't see a way to do that sensibly without having
a per-backend limit first. Because if you have a global limit, a single
backend consuming memory could cause all kinds of weird failures in
random other backends.

Most of what I’ve seen on this thread is discussing ways to *optimize* how much memory the set of running backends can consume. Adjusting how you slice the memory pie across backends, or even within a single backend, is optimization. While that’s a great goal that I do support, it will never fully fix the problem. At some point you need to either throw your hands in the air and start tossing memory errors, because you don’t have control over how much work is being thrown at the engine. The only way that the engine can exert control over that would be to hold new transactions from starting when the system is under duress (ie, workload management). While workload managers can be quite sophisticated (aka, complex), the nice thing about limiting this scope to work_mem, and only as a means to prevent complete overload, is that the problem becomes a lot simpler since you’re only looking at one metric and not trying to support any kind of priority system. The only fanciness I think an MVP would need is a GUC to control how long a transaction can sit waiting before it throws an error. Frankly, that sounds a lot less complex and much easier for DBAs to adjust than trying to teach the planner how to apportion out per-node work_mem limits.

As I said, I’m not opposed to optimizations, I just think they’re very much cart-before-the-horse.

What optimization? I didn't notice anything like that. I don't see how
"adjusting how you slice the memory pie across backends" counts as an
optimization. I mean, that's exactly what a memory limit is meant to do.

Similarly, there was a proposal to do planning with work_mem, and then
go back and adjust the per-node limits to impose a global limit. That
does not seem like an optimization either ... (more an opposite of it).

1: While it’d be a lot of work to make max_connections dynamic one thing we could do fairly easily would be to introduce another GUC (max_backends?) that actually controls the total number of allowed backends for everything. The sum of max_backends + autovac workers + background workers + whatever else I’m forgetting would have to be less than that. The idea here is that you’d normally run with max_connections set significantly lower than max_backends. That means that if you need to adjust any of these GUCs (other than max_backends) you don’t need to restart - the new limits would just apply to new connection requests.

I don't quite understad how max_backends helps with anything except
allowing to change the limit of connections without a restart, or why
would it be needed for introducing a memory limit. To me those seem very
much like two separate features.

regards

--
Tomas Vondra

#76Jim Nasby
jnasby@upgrade.com
In reply to: Tomas Vondra (#75)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On Dec 31, 2024, at 5:41 PM, Tomas Vondra <tomas@vondra.me> wrote:

On 12/31/24 21:46, Jim Nasby wrote:

On Dec 30, 2024, at 7:05 PM, James Hunter <james.hunter.pg@gmail.com> wrote:

On Sat, Dec 28, 2024 at 11:24 PM Jim Nasby <jnasby@upgrade.com> wrote:

IMHO none of this will be very sane until we actually have cluster-level limits. One sudden burst in active connections and you still OOM the instance.

Fwiw, PG does support "max_connections" GUC, so a backend/connection -
level limit, times "max_connections", yields a cluster-level limit.

max_connections is useless here, for two reasons:

1. Changing it requires a restart. That’s at *best* a real PITA in production. [1]
2. It still doesn’t solve the actual problem. Unless your workload *and* your data are extremely homogeneous you can’t simply limit the number of connections and call it a day. A slight change in incoming queries, OR in the data that the queries are looking at and you go from running fine to meltdown. You don’t even need a plan flip for this to happen, just the same plan run at the same rate but now accessing more data than before.

I really don't follow your argument ...

Yes, changing max_connections requires a restart - so what? AFAIK the
point James was making is that if you multiply max_connections by the
per-backend limit, you get a cluster-wide limit. And presumably the
per-backend limit would be a GUC not requiring a restart.

Yes, high values of max_connections are problematic. I don't see how a
global limit would fundamentally change that. In fact, it could
introduce yet more weird failures because some unrelated backend did
something weird.

That’s basically my argument for having workload management. If a system becomes loaded enough for the global limit to start kicking in it’s likely that query response time is increasing, which means you will soon have more and more active backends trying to run queries. That’s just going to make the situation even worse. You’d either have to start trying to “take memory away” from already running backends or backends that are just starting would have such a low limit as to cause them to spill very quickly, creating further load on the system.

FWIW I'm not opposed to having some global memory limit, but as I
explained earlier, I don't see a way to do that sensibly without having
a per-backend limit first. Because if you have a global limit, a single
backend consuming memory could cause all kinds of weird failures in
random other backends.

I agree, but I’m also not sure how much a per-backend limit would actually help on its own, especially in OLTP environments.

Most of what I’ve seen on this thread is discussing ways to *optimize* how much memory the set of running backends can consume. Adjusting how you slice the memory pie across backends, or even within a single backend, is optimization. While that’s a great goal that I do support, it will never fully fix the problem. At some point you need to either throw your hands in the air and start tossing memory errors, because you don’t have control over how much work is being thrown at the engine. The only way that the engine can exert control over that would be to hold new transactions from starting when the system is under duress (ie, workload management). While workload managers can be quite sophisticated (aka, complex), the nice thing about limiting this scope to work_mem, and only as a means to prevent complete overload, is that the problem becomes a lot simpler since you’re only looking at one metric and not trying to support any kind of priority system. The only fanciness I think an MVP would need is a GUC to control how long a transaction can sit waiting before it throws an error. Frankly, that sounds a lot less complex and much easier for DBAs to adjust than trying to teach the planner how to apportion out per-node work_mem limits.

As I said, I’m not opposed to optimizations, I just think they’re very much cart-before-the-horse.

What optimization? I didn't notice anything like that. I don't see how
"adjusting how you slice the memory pie across backends" counts as an
optimization. I mean, that's exactly what a memory limit is meant to do.

Similarly, there was a proposal to do planning with work_mem, and then
go back and adjust the per-node limits to impose a global limit. That
does not seem like an optimization either ... (more an opposite of it).

It’s optimization in that you’re trying to increase how many active backends you can have before getting memory errors. It’s an alternative to throwing more memory at the problem or limiting the rate of incoming workload.

1: While it’d be a lot of work to make max_connections dynamic one thing we could do fairly easily would be to introduce another GUC (max_backends?) that actually controls the total number of allowed backends for everything. The sum of max_backends + autovac workers + background workers + whatever else I’m forgetting would have to be less than that. The idea here is that you’d normally run with max_connections set significantly lower than max_backends. That means that if you need to adjust any of these GUCs (other than max_backends) you don’t need to restart - the new limits would just apply to new connection requests.

I don't quite understad how max_backends helps with anything except
allowing to change the limit of connections without a restart, or why
would it be needed for introducing a memory limit. To me those seem very
much like two separate features.

It’s related to this because the number of active backends is directly related to memory consumption. Yet because max_connections requires a restart it’s very hard to actually manage how many active backends you have. Your only option is a single-point connection pool, but that introduces its own problems.

That said, I do think a workload manager would be more effective than trying to limit total connections.

#77Tomas Vondra
tomas@vondra.me
In reply to: Jim Nasby (#76)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On 1/2/25 22:09, Jim Nasby wrote:

On Dec 31, 2024, at 5:41 PM, Tomas Vondra <tomas@vondra.me> wrote:

On 12/31/24 21:46, Jim Nasby wrote:

On Dec 30, 2024, at 7:05 PM, James Hunter <james.hunter.pg@gmail.com>
wrote:

On Sat, Dec 28, 2024 at 11:24 PM Jim Nasby <jnasby@upgrade.com> wrote:

IMHO none of this will be very sane until we actually have cluster-
level limits. One sudden burst in active connections and you still
OOM the instance.

Fwiw, PG does support "max_connections" GUC, so a backend/connection -
level limit, times "max_connections", yields a cluster-level limit.

max_connections is useless here, for two reasons:

1. Changing it requires a restart. That’s at *best* a real PITA in
production. [1]
2. It still doesn’t solve the actual problem. Unless your workload
*and* your data are extremely homogeneous you can’t simply limit the
number of connections and call it a day. A slight change in incoming
queries, OR in the data that the queries are looking at and you go
from running fine to meltdown. You don’t even need a plan flip for
this to happen, just the same plan run at the same rate but now
accessing more data than before.

I really don't follow your argument ...

Yes, changing max_connections requires a restart - so what? AFAIK the
point James was making is that if you multiply max_connections by the
per-backend limit, you get a cluster-wide limit. And presumably the
per-backend limit would be a GUC not requiring a restart.

Yes, high values of max_connections are problematic. I don't see how a
global limit would fundamentally change that. In fact, it could
introduce yet more weird failures because some unrelated backend did
something weird.

That’s basically my argument for having workload management. If a system
becomes loaded enough for the global limit to start kicking in it’s
likely that query response time is increasing, which means you will soon
have more and more active backends trying to run queries. That’s just
going to make the situation even worse. You’d either have to start
trying to “take memory away” from already running backends or backends
that are just starting would have such a low limit as to cause them to
spill very quickly, creating further load on the system.

I'm not opposed to having a some sort of "workload management" (similar
to what's available in some databases), but my guess is that's (at
least) an order of magnitude more complex than introducing the memory
limit discussed here. I can only guess, because no one really explained
what would it include, how would it be implemented. Which makes it easy
to dream about a solution that would fix the problem ...

What I'm afraid will happen everyone mostly agrees a comprehensive
workload management system would be better than a memory limit (be it
per-backend or a global one). But without a workable proposal how to
implement it no one ends up working on it. And no one gets to work on a
memory limit because the imagined workload management would be better.
So we get nothing ...

FWIW I have a hard time imagining a workload management system without
some sort of a memory limit.

FWIW I'm not opposed to having some global memory limit, but as I
explained earlier, I don't see a way to do that sensibly without having
a per-backend limit first. Because if you have a global limit, a single
backend consuming memory could cause all kinds of weird failures in
random other backends.

I agree, but I’m also not sure how much a per-backend limit would
actually help on its own, especially in OLTP environments.

So what if it doesn't help in every possible case? It'd be valuable even
for OLAP/mixed workloads with sensible max_connection values, because
it'd allow setting the work_mem more aggressively.

Most of what I’ve seen on this thread is discussing ways to
*optimize* how much memory the set of running backends can consume.
Adjusting how you slice the memory pie across backends, or even
within a single backend, is optimization. While that’s a great goal
that I do support, it will never fully fix the problem. At some point
you need to either throw your hands in the air and start tossing
memory errors, because you don’t have control over how much work is
being thrown at the engine. The only way that the engine can exert
control over that would be to hold new transactions from starting
when the system is under duress (ie, workload management). While
workload managers can be quite sophisticated (aka, complex), the nice
thing about limiting this scope to work_mem, and only as a means to
prevent complete overload, is that the problem becomes a lot simpler
since you’re only looking at one metric and not trying to support any
kind of priority system. The only fanciness I think an MVP would need
is a GUC to control how long a transaction can sit waiting before it
throws an error. Frankly, that sounds a lot less complex and much
easier for DBAs to adjust than trying to teach the planner how to
apportion out per-node work_mem limits.

As I said, I’m not opposed to optimizations, I just think they’re
very much cart-before-the-horse.

What optimization? I didn't notice anything like that. I don't see how
"adjusting how you slice the memory pie across backends" counts as an
optimization. I mean, that's exactly what a memory limit is meant to do.

Similarly, there was a proposal to do planning with work_mem, and then
go back and adjust the per-node limits to impose a global limit. That
does not seem like an optimization either ... (more an opposite of it).

It’s optimization in that you’re trying to increase how many active
backends you can have before getting memory errors. It’s an alternative
to throwing more memory at the problem or limiting the rate of incoming
workload.

I don't see it that way. I see it as a "safety measure" for queries that
happen to be more complex than expected, or something. Yes, it may allow
you to use a higher max_connections, or higher work_mem. But it's still
just a safety measure.

1: While it’d be a lot of work to make max_connections dynamic one
thing we could do fairly easily would be to introduce another GUC
(max_backends?) that actually controls the total number of allowed
backends for everything. The sum of max_backends + autovac workers +
background workers + whatever else I’m forgetting would have to be
less than that. The idea here is that you’d normally run with
max_connections set significantly lower than max_backends. That means
that if you need to adjust any of these GUCs (other than
max_backends) you don’t need to restart - the new limits would just
apply to new connection requests.

I don't quite understad how max_backends helps with anything except
allowing to change the limit of connections without a restart, or why
would it be needed for introducing a memory limit. To me those seem very
much like two separate features.

It’s related to this because the number of active backends is directly
related to memory consumption. Yet because max_connections requires a
restart it’s very hard to actually manage how many active backends you
have. Your only option is a single-point connection pool, but that
introduces its own problems.

I think you need to choose. Either problems with many active backends,
or problems with connection pools ...

That said, I do think a workload manager would be more effective than
trying to limit total connections.

The "workload management" concept is so abstract I find it very
difficult to discuss without much more detail about how would it
actually work / be implemented.

I believe implementing some rudimentary "global" memory accounting would
not be *that* hard (possibly along the lines of the patches early in
this thread), and adding some sort of dynamic connection limit would not
be much harder I think. But then comes the hard part of actually doing
the "workload management" part, which seems pretty comparable to what a
QoS / scheduler needs to do. With all the weird corner cases.

regards

--
Tomas Vondra

#78James Hunter
james.hunter.pg@gmail.com
In reply to: Jim Nasby (#76)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

I think this discussion is getting away from a manageable scope of work...

On Thu, Jan 2, 2025 at 1:09 PM Jim Nasby <jnasby@upgrade.com> wrote:

That’s basically my argument for having workload management. If a system becomes loaded enough for the global limit to start kicking in it’s likely that query response time is increasing, which means you will soon have more and more active backends trying to run queries. That’s just going to make the situation even worse. You’d either have to start trying to “take memory away” from already running backends or backends that are just starting would have such a low limit as to cause them to spill very quickly, creating further load on the system.

I think this is backward. There's a fixed number of backends, limited
by "max_connections." A given backend becoming slow to respond doesn't
increase this limit. The load on the system is limited by
"max_connections." This makes the system stable.

If, instead, the system starts cancelling queries, then a naive client
will typically just retry the query. If the reason the query was
cancelled is that the system is overloaded, then the query is likely
to be cancelled again, leading to a retry storm, even though the
number of backends is limited by "max_connections," since a given
backend will be repeatedly cancelled.

Long-term, the solution to, "I don't have enough resources to run my
workload efficiency," is either:

* Buy more resources; or
* Reduce your workload.

We can't help with either of those solutions!

However, the (short-term) problem I'd like to solve is: how do we
expose efficient use of resources, in those cases where we *do* have
enough resources to run a workload efficiently, but the existing
"work_mem" and "hash_mem_multiplier" GUCs are insufficient?

Thanks,
James

#79James Hunter
james.hunter.pg@gmail.com
In reply to: Tomas Vondra (#77)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On Thu, Jan 2, 2025 at 7:21 PM Tomas Vondra <tomas@vondra.me> wrote:

I'm not opposed to having a some sort of "workload management" (similar
to what's available in some databases), but my guess is that's (at
least) an order of magnitude more complex than introducing the memory
limit discussed here. I can only guess, because no one really explained
what would it include, how would it be implemented. Which makes it easy
to dream about a solution that would fix the problem ...

I agree -- anyway, I will try to start a new thread sometime next
week, with a more concrete proposal. (I wanted to get general feedback
first, and I got a lot of it -- thanks!)

What I'm afraid will happen everyone mostly agrees a comprehensive
workload management system would be better than a memory limit (be it
per-backend or a global one). But without a workable proposal how to
implement it no one ends up working on it. And no one gets to work on a
memory limit because the imagined workload management would be better.
So we get nothing ...

That seems to be where this thread is heading...

FWIW I have a hard time imagining a workload management system without
some sort of a memory limit.

Yes, and more strongly; you can't create a system to manage resources,
unless you first have some way of managing those resources. Today, I
can't say: query X gets 50 MB of RAM, while query Y gets 200 MB of
RAM, even if I wanted to -- at least, not in any useful way that
doesn't involve waiting for the query to exceed its (hidden!) memory
limit, and then killing it.

Before we can discuss how much memory queries X and Y should get, and
whether X can steal memory for Y, etc. -- we need a way to force X and
Y to respect the memory limits we impose! Otherwise, we always end up
back at: I have a secret memory limit for X, and if X exceeds that
memory limit, I'll kill X. I think there's been some rationalization
that "just kill X" is a reasonable response, but I think it really
isn't. Any workload management system whose only available tool is
killing queries is going to be incredibly sensitive / unstable.

It would be better if, when someone -- either workload management, or
a GUC -- decides that query X gets 50 MB of memory, we informed query
X of this limit, and let the query do its best to stay within it. (Yes
it makes sense to have the option to "kill -9", but there's a reason
we have other signals as well...)

The good news is, PostgreSQL operators already try to stay within
work_mem [* hash_mem_multiplier], so the problem of how to get query X
to stay within 50 MB of RAM breaks down into splitting that 50 MB into
per-operator "work_mem" limits, which is (as you point out!) at least
an order of magnitude easier than a general workload management
solution. Once we have per-operator "work_mem" limits, existing
PostgreSQL logic takes care of the rest.

Thanks,
James

#80Jim Nasby
jnasby@upgrade.com
In reply to: Tomas Vondra (#77)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On Jan 2, 2025, at 9:21 PM, Tomas Vondra <tomas@vondra.me> wrote:

That said, I do think a workload manager would be more effective than
trying to limit total connections.

The "workload management" concept is so abstract I find it very
difficult to discuss without much more detail about how would it
actually work / be implemented.

I believe implementing some rudimentary "global" memory accounting would
not be *that* hard (possibly along the lines of the patches early in
this thread), and adding some sort of dynamic connection limit would not
be much harder I think. But then comes the hard part of actually doing
the "workload management" part, which seems pretty comparable to what a
QoS / scheduler needs to do. With all the weird corner cases.

I’ve been saying “workload management” for lack of a better term, but my initial suggestion upthread was to simply stop allowing new transactions to start if global work_mem consumption exceeded some threshold. That’s simplistic enough that I wouldn’t really consider it “workload management”. Maybe “deferred execution” would be a better name. The only other thing it’d need is a timeout on how long a new transaction could sit in limbo.

I agree that no matter what everything being proposed would rely on having metrics on actual work_mem consumption. That would definitely be a good feature on its own. I’m thinking adding “work_mem_bytes” and “work_mem_operations” to pg_stat_activity (where “work_mem_operations” would tell you how many different things were using work_mem in the backend.

Incidentally, something related to this that I’ve seen is backend memory consumption slowly growing over time. Unbounded growth of relcache and friends was presumably the biggest contributor. There’s an argument to be made for a view dedicated to tracking per-backend memory stats, with additional info about things contributing to idle memory consumption.

#81Tomas Vondra
tomas@vondra.me
In reply to: Jim Nasby (#80)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On 1/6/25 22:07, Jim Nasby wrote:

On Jan 2, 2025, at 9:21 PM, Tomas Vondra <tomas@vondra.me> wrote:

That said, I do think a workload manager would be more effective than
trying to limit total connections.

The "workload management" concept is so abstract I find it very
difficult to discuss without much more detail about how would it
actually work / be implemented.

I believe implementing some rudimentary "global" memory accounting would
not be *that* hard (possibly along the lines of the patches early in
this thread), and adding some sort of dynamic connection limit would not
be much harder I think. But then comes the hard part of actually doing
the "workload management" part, which seems pretty comparable to what a
QoS / scheduler needs to do. With all the weird corner cases.

I’ve been saying “workload management” for lack of a better term, but my
initial suggestion upthread was to simply stop allowing new transactions
to start if global work_mem consumption exceeded some threshold. That’s
simplistic enough that I wouldn’t really consider it “workload
management”. Maybe “deferred execution” would be a better name. The only
other thing it’d need is a timeout on how long a new transaction could
sit in limbo.

How would that not be a huge DoS vector? If a low-priority task can
allocate a chunk of memory, and block/delay execution of everything
else, that seems potentially disastrous.

I believe there is a reason why workload management systems tend to be
fairly complex systems, both to implement and manage, requiring stuff
like resource pools, workload classes, etc.

I agree that no matter what everything being proposed would rely on
having metrics on actual work_mem consumption. That would definitely be
a good feature on its own. I’m thinking adding “work_mem_bytes” and
“work_mem_operations” to pg_stat_activity (where “work_mem_operations”
would tell you how many different things were using work_mem in the backend.

Incidentally, something related to this that I’ve seen is backend memory
consumption slowly growing over time. Unbounded growth of relcache and
friends was presumably the biggest contributor. There’s an argument to
be made for a view dedicated to tracking per-backend memory stats, with
additional info about things contributing to idle memory consumption.

True, but I don't quite see how would a global memory limit help with
any of that. In fact, relcache seems exactly like the thing to limit at
the backend level.

regards

--
Tomas Vondra

#82James Hunter
james.hunter.pg@gmail.com
In reply to: Jim Nasby (#80)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

On Mon, Jan 6, 2025 at 1:07 PM Jim Nasby <jnasby@upgrade.com> wrote:

I’ve been saying “workload management” for lack of a better term, but my initial suggestion upthread was to simply stop allowing new transactions to start if global work_mem consumption exceeded some threshold. That’s simplistic enough that I wouldn’t really consider it “workload management”. Maybe “deferred execution” would be a better name. The only other thing it’d need is a timeout on how long a new transaction could sit in limbo.

Yes, this seems like a good thing to do, but we need to handle
"work_mem" , by itself, first.

The problem is that it's just too easy for a query to blow up work_mem
consumption, almost instantaneously. By the time we notice that we're
low on working memory, pausing new transactions may not be sufficient.
We could already be in the middle of a giant Hash Join, for example,
and the hash table is just going to continue to grow...

Before we can solve the problem you describe, we need to be able to
limit the work_mem consumption by an in-progress query.

James

#83Tomas Vondra
tomas@vondra.me
In reply to: James Hunter (#82)
Re: Add the ability to limit the amount of memory that can be allocated to backends.

Hi,

Let me bump this dormant thread after about a year. I don't have any
patch to share or anything like that, but I happened to read two quite
interesting papers relevant to the topic of setting a per-query memory
limit, and distributing the memory between operators in a query plan:

1) Exploiting pipeline interruptions for efficient memory allocation
Authors: Josep Aguilar-Saborit, Mohammad Jalali, Dave Sharpe, Victor
Muntés MuleroAuthors Info & Claims
Published: 2008
PDF: https://dl.acm.org/doi/epdf/10.1145/1458082.1458169

2) Saving Private Hash Join
Authors: Laurens Kuiper, Paul Groß, Peter Boncz, Hannes Mühleisen
Published: 2024-2025
PDF: https://www.vldb.org/pvldb/vol18/p2748-kuiper.pdf

I read the (2) paper first, expecting to learn some new stuff about hash
joins, but to my surprise it's focusing on how to distribute memory
between multiple hash joins in a single query. The hash joins serve
mostly as an example of an actual/common operator in a query.

The (1) paper establishes the theoretical framework and algorithms, and
(2) presents a more precise/complete model for hash joins.

I think both papers are worth reading, and the framework seems quite
helpful. Even if there some parts may need tweaks, as Postgres does
certain things differently for whatever reason.

I'm not going to explain all the details (the papers are not that long
anyway), but the proposed approach combines a couple basic parts:

1) leverage "pipeline interruption" operations

Some operators materialize the intermediate results. This splits the
plan into parts that don't need memory at the same time. It's enough to
enforce the limit for these parts, not for the whole plan. Which means
the optimization problems are smaller, and the operators can get more
memory than when assuming the whole query runs at the same time.

Of course, the reality is more complicated. Some operators are only
partial pipeline interruptions (e.g. hashjoin breaks for the inner
subplan, not the outer).

And Postgres currently delays the Hash build until the first outer
tuple, unlike DuckDB used in the (2) paper.

2) cost model for memory distribution

The memory is distributed between operators based on a simple cost
model, instead of using a simple scheme where operators get 1/N of
memory. The (2) paper presents a hash join cost model combining
"materialization cost" and "throughput".

But it's a pretty generic approach, and should not be too difficult to
do for other operators. Most operators don't even need to allocate that
much memory, so the cost model can ignore those, I think. Only nodes
that "break the pipeline" would matter.

The important part is that this is a second optimization phase. The
optimizer picks a query plan (assuming some default memory sizes), and
then the cost model determines how to distribute memory within that
particular plan.

The paper does that repeatedly during execution, but I suspect these
adjustments are easier in DuckDB. In Postgres we'd probably do that only
once right after planning? Or maybe not, not sure.

The (1) paper does things a bit differently, so that it works on DB2 (so
less dynamic), but it also focuses on plans with hash joins etc. The
general framework seems to be mostly the same.

Anyway, that's all I have. I don't expect to work on this anytime soon,
but I found those papers interesting.

regards

--
Tomas Vondra