Just to point out a couple of things before heading out for a wild goose chase:
.NET / CLR is used by SQL Server for a variety of things, even if you never added any custom SQLCLR code. There are built-in functions such as
FORMAT(), there are features such as the CLR datatypes (
HierarchyID), Change Tracking, etc. Even if you have disabled the server configuration option of "CLR enabled", you could very well still be using CLR in one or more areas. Meaning, this is not guaranteed to be coming from your code (even if custom code is the best first place to check).
Memory pressure is a function of the system running out of physical memory, which may or may not be related to actual usage of custom CLR Assemblies. Getting that message in the log file about an App Domain being marked for unload due to memory pressure does not imply anything about what was being done in that App Domain outside of merely existing and hence being a candidate for unloading.
You can try paying attention to the
survived_memory_kb field from the following DMV:
SELECT * FROM sys.dm_clr_appdomains;
as that should be the amount of memory that is not being released. Of course, if all 60 SQLCLR stored procedures are in the same App Domain, then that might not help, except to possible prove / disprove the idea that a large amount of memory is being held by the App Domain.
Also, how busy is your system? Sometimes garbage collection doesn't run if the system is busy. In which case you can force it by creating a simple CLR function that does garbage collection (it's a single command) which doesn't get rid of everything, and shouldn't be called often, but it definitely clears out some stuff.
Finally, it need not be
UNSAFE code locking up resources. If you have
EXTERNAL_ACCESS code that interacts with the network or file system, etc, then you need to make sure that those resources are being properly disposed of, either explicitly via a call to
.Dispose() or by the instantiation of the object being wrapped in a
using() construct. If not properly disposing external resources, it is theoretically possible to use up all available handles, especially if the code is called at high volumes.