cad.net 插件式架构/四叉树
本帖最后由 你有种再说一遍 于 2025-4-12 16:57 编辑温故而知新:
指针都是弱的,引用才分强弱.
所以指针/弱引用要if,强引用不需要.
弱引用的目标对象被强引用持有,其他地方被弱引用指向了.
这样强引用被回收之后,就剩下弱引用指向,就会自动回收.
避免全部都是强引用.
这么说来WeakReference
其实只是一个:标记+扫描机制,
如果扫到的对象是弱引用指向,而没有强引用持有,就会发生回收.
它没有一个全局map储存,而是通过根可达性进行扫描.
JAVA对象头MarkWord不持有,而是JVM持有的.
C#同理,只不过C#剩下弱引用,
通过其他机制把其他两个都干掉了.
ReferenceProcessor {
DiscoveredList _discoveredSoftRefs;// 软引用列表
DiscoveredList _discoveredWeakRefs; // 弱引用列表
DiscoveredList _discoveredPhantomRefs; // 虚引用列表
}
弱引用表用来做什么的呢?
是取值用的:
weakObj.TryGetTarget(out var obj)
这个时候会获取弱引用指向对象.
其实这个时候是立即增加一个强引用计数,
否则不就可能出现get了立即释放嘛.
C++的weak_ptr上面看原理可以看见,
强引用计数阻止对象回收,
弱引用计数不阻止对象回收,但会阻止控制块回收.
那它底层是啥?
struct ControlBlock {
T* ptr; // 指向被管理的对象
std::atomic<size_t> strong_count; // 强引用计数
std::atomic<size_t> weak_count; // 弱引用计数
Deleter deleter; // 自定义删除器(如释放内存的函数)
Allocator allocator; // 内存分配器(可选)
};
修改了四叉树代码
1,根节点多了一个_entMap,移除ent所在节点时候是O(1)了.
我原本怎么没想到呢,多一个缓存不就好了.
而且缓存值是节点,节点要改为弱引用,
这样发生直接Clrear(node)才可以无关联移除.
我原本还以为要递归进去四叉树...写了一堆代码...
然后难点来了,_entMap的key如何释放呢?
理论上应该写一个定时器定期扫一下,
后来AI建议直接计数+概率性释放,
发现这就是惰性释放.
2,调整了节点结构,用数组储存,一是方便遍历,二是方便剔除.
3,剔除了大量的废案.
4,debug模式画图可以更方便找问题,
把某些字段直接改为只读提供,
原来readonly关键字是为了这样存在的.
release模式会更快,因为把属性访问器都剔除了.
四叉树:
https://www.cnblogs.com/JJBox/p/15512317.html
插件式架构:
发现退出CAD进程会弹一个跨GCHandle无解.
https://www.cnblogs.com/JJBox/p/18800009 Thanks for Sharing 优化了几个部位,越来越简单的表达四叉树,
惰性回收上面既然好用就应该用嘛. 发现点容器设计还是挺麻烦的,直接改为List作为demo算了.
还发现我原本remove居然忘记移除点了. 原来redis之所以用跳表,还有一个问题是有序性扫描,
尤其是key可以上百亿的,
无序哈希表一个ToArray()直接给你卡死了.
但是C#没有提供跳表,需要自己做,懒
页:
[1]