重学OC第六篇:类结构之cache

本文深入探讨了Objective-C中的cache_t结构,分析了在模拟器和arm64真机环境下的差异,特别是关于_mask、_occupied的变化及bucket_t的数据丢失和乱序现象。通过cache::insert和cache_t::reallocate方法解析了cache的工作原理,同时介绍了散列表冲突解决的开放定址法和链表法。最后总结了cache关键属性的作用和扩容策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、cache_t分析

#if defined(__arm64__) && __LP64__
#define CACHE_MASK_STORAGE CACHE_MASK_STORAGE_HIGH_16
#elif defined(__arm64__) && !__LP64__
#define CACHE_MASK_STORAGE CACHE_MASK_STORAGE_LOW_4
#else
#define CACHE_MASK_STORAGE CACHE_MASK_STORAGE_OUTLINED
#endif

struct bucket_t {
   
    // IMP-first is better for arm64e ptrauth and no worse for arm64.
    // SEL-first is better for armv7* and i386 and x86_64.
#if __arm64__
    explicit_atomic<uintptr_t> _imp;
    explicit_atomic<SEL> _sel;
#else
    explicit_atomic<SEL> _sel;
    explicit_atomic<uintptr_t> _imp;
#endif
}

struct cache_t {
   
#if CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_OUTLINED  
    explicit_atomic<struct bucket_t *> _buckets;
    explicit_atomic<mask_t> _mask;
#elif CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_HIGH_16
    explicit_atomic<uintptr_t> _maskAndBuckets;
    mask_t _mask_unused;
    ......
#else
#error Unknown cache mask storage type.
#endif
    
#if __LP64__
    uint16_t _flags;
#endif
    uint16_t _occupied;

1 模拟器环境(i386、x86_64、armv7)

简化一下上面的代码,explicit_atomic的作用就是显式原子操作。

struct bucket_t {
   
	SEL _sel;
    uintptr_t _imp;
}
struct cache_t {
   
	struct bucket_t * _buckets;   //缓存的方法的SEL和IMP
   	mask_t _mask;                 //哈希掩码,开辟capacity - 1
    uint16_t _flags;			//缓存标识
    uint16_t _occupied;			//已占用的缓存空间
}

以前都是使用lldb进行内存偏移访问,今天通过打印直接访问

typedef uint32_t mask_t;  // x86_64 & arm64 asm are less efficient with 16-bits
struct gc_bucket_t {
   
    SEL _sel;
    IMP _imp;
};
struct gc_cache_t {
   
    struct gc_bucket_t *_buckets;
    mask_t _mask;
    uint16_t _flags;
    uint16_t _occupied;
};
struct gc_class_data_bits_t {
   
    uintptr_t bits;
};
struct gc_objc_class {
   
    Class ISA;
    Class superclass;
    struct gc_cache_t cache;             // formerly cache pointer and vtable
    struct gc_class_data_bits_t bits;    // class_rw_t * plus custom rr/alloc flags
};

@interface TestA : NSObject

- (void)test1;
- (void)test2;
- (void)test3;
- (void)test4;
- (void)test5;
- (void)test6;

@end

@implementation TestA

- (void)test1 {
   
    NSLog(@"TestA method name : %s", __func__);
}
- (void)test2 {
   
    NSLog(@"TestA method name : %s", __func__);
}
- (void)test3 {
   
    NSLog(@"TestA method name : %s", __func__);
}
- (void)test4 {
   
    NSLog(@"TestA method name : %s", __func__);
}
- (void)test5 {
   
    NSLog(@"TestA method name : %s", __func__);
}
- (void)test6 {
   
    NSLog(@"TestA method name : %s", __func__);
}
@end

void log_cache_t(struct gc_cache_t cache) {
   
    for (mask_t i = 0 ; i < cache._mask; i++) {
   
        // 打印获取的 bucket
        struct gc_bucket_t bucket = cache._buckets[i];
        NSLog(@"bucket._sel=%@ - bucket._imp=%p",NSStringFromSelector(bucket._sel),bucket._imp);
    }
    NSLog(@"_mask=%u, _flags=%hu, _occupied=%hu", cache._mask, cache._flags, cache._occupied);
}

int main(int argc, const char * argv[]) {
   
    @autoreleasepool {
   
        TestA *testA = [[TestA alloc] init];
        struct gc_objc_class *cls = (__bridge struct gc_objc_class *)[TestA class];
    
        log_cache_t<
<think>好的,我现在要处理用户关于数据库笛卡尔积的问题。首先,我需要明确用户的需求。用户想了解笛卡尔积的概念、产生原因以及避免方法。根据用户提供的引用内容,我需要整合这些信息,确保回答准确且结构清晰。 首先,回忆笛卡尔积的定义。根据引用[5],笛卡尔积是多个域的集合中所有可能的有序组合,但在数据库中,只有子集有意义。接着,用户提到的引用[4]指出笛卡尔积产生的两种情况:缺少连接条件优化器判断使用笛卡尔积更快。这可能涉及到SQL编写错误数据库优化器的问题。 接下来,我需要分析原因。引用[1]提到笛卡尔积容易导致数据库假死,因此必须避免。引用[4]中的两种情况需要详细解释,比如开发人员遗漏关联条件或表数据量小导致优化器误判。然后,避免方法方面,引用[3][4]建议检查关联条件、使用统计信息更新,以及分步处理数据。 然后,整合这些内容,确保每个部分都有对应的引用支持。例如,在解释原因时,引用[4][1]可以作为依据。避免方法部分需要提到检查JOIN条件、使用INNER JOIN代替CROSS JOIN,以及优化器相关的统计信息更新,这些在引用[4][3]中都有涉及。 另外,用户要求使用中文回答,行内公式用$...$,独立公式用$$...$$。虽然这个问题主要涉及数据库,可能数学公式较少,但如果有相关例子,比如笛卡尔积的数量计算,可以用公式表示,比如$D1 × D2 × … × Dn$。 最后,生成相关问题时要参考用户提供的示例,确保问题相关且有深度。例如,优化笛卡尔积的方法、实际应用场景,或者与性能分析相关的问题。 需要检查是否有遗漏的引用内容,比如引用[2]提到笛卡尔积在数据分析中的应用价值,但用户的问题主要围绕原因避免方法,可能这部分内容可以简要提及,但重点还是放在原因解决方法上。 总结回答结构:先定义笛卡尔积,然后详细说明原因,接着列出避免方法,最后附上相关问题。确保每个部分都有对应的引用标注,例如在原因部分末尾添加[^4][^1]等。</think>### 数据库笛卡尔积的原因及避免方法 #### 1. 笛卡尔积的定义 笛卡尔积(Cartesian Product)是数据库中两个表(或关系)的所有行组合的集合。例如,若表$A$有$m$行,表$B$有$n$行,则它们的笛卡尔积会生成$m \times n$行结果[^5]。数学上可表示为: $$ A \times B = \{(a,b) \mid a \in A, b \in B\} $$ #### 2. 产生原因 - **缺少关联条件**:在表连接(如`JOIN`)时未指定`ON`或`WHERE`条件,导致数据库直接生成所有可能的组合[^4]。 示例错误SQL: ```sql SELECT * FROM table1, table2; -- 隐式笛卡尔积 ``` - **优化器误判**:当表中数据量极小时,数据库可能自动选择笛卡尔积作为“更优”执行计划,尤其当统计信息过期或采样不准确时。 #### 3. 避免方法 - **显式指定关联条件**:使用`INNER JOIN`或`LEFT JOIN`并明确`ON`子句。 正确示例: ```sql SELECT * FROM table1 JOIN table2 ON table1.id = table2.id; ``` - **避免`CROSS JOIN`**:除非明确需要所有组合,否则不使用`CROSS JOIN`。 - **更新统计信息**:定期执行`ANALYZE TABLE`或类似操作,确保优化器准确估算数据量。 - **分步处理数据**:对大数据集先筛选再关联,减少中间结果集大小[^3]。 #### 4. 性能影响 笛卡尔积的时间复杂度为$O(n^2)$,当表数据量较大时会导致: - 内存溢出或临时表空间不足; - 查询响应时间急剧增加,甚至触发数据库假死[^4]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值