Skip to content

Commit 8f388bb

Browse files
committed
feat: record pod target prebuilt hmap
1 parent a40c1d0 commit 8f388bb

File tree

6 files changed

+44
-70
lines changed

6 files changed

+44
-70
lines changed

README.md

Lines changed: 16 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,20 @@
11
# cocoapods-project-hmap
22

3-
此插件思路来源于[《一款可以让大型iOS工程编译速度提升50%的工具》](https://tech.meituan.com/2021/02/25/cocoapods-hmap-prebuilt.html)通过使用hmap代替文件路径搜索优化预处理阶段中头文件搜索的性能实现编译速度提升
3+
此插件思路来源于[《一款可以让大型iOS工程编译速度提升50%的工具》](https://tech.meituan.com/2021/02/25/cocoapods-hmap-prebuilt.html)通过使用 header map (以下简称 hmap ) 代替文件路径搜索优化预处理阶段中头文件搜索的性能实现编译速度提升
44

55
[English](./README_en.md)
66

7-
## 效果测试
8-
9-
我在另一个项目 [hmap-benchmark](https://github.com/chenxGen/hmap-benchmark/) 写了几个测试用例,统计并输出增加M个源文件,N个第三方库在使用和不使用插件的情况下的编译时间.
10-
11-
最新一次跑 `run_benchmark.rb` 脚本的时间统计为:
12-
13-
- Mac mini (Intel i7/16g) :
14-
15-
```
16-
+--------------------------------------+--------------------+------------------------------------------------------------------------------------------------------------------------+
17-
| Case | Average(s) | Detail(s) |
18-
+--------------------------------------+--------------------+------------------------------------------------------------------------------------------------------------------------+
19-
| 100 source files & 125 pods (origin) | 192.43606980641684 | [218.57447242736816, 178.7542200088501, 179.97951698303223] |
20-
| 100 source files & 125 pods (plugin) | 165.76690363883972 | [166.8555600643158, 165.40182876586914, 165.04332208633423] |
21-
| > optimization (speed) | 16.09% | |
22-
| > optimization (time cost) | 13.86% | |
23-
| 1 source files & 125 pods (origin) | 170.00553512573242 | [175.31463813781738, 173.79285717010498, 160.9091100692749] |
24-
| 1 source files & 125 pods (plugin) | 124.49473492304485 | [123.54309391975403, 124.4949209690094, 125.4461898803711] |
25-
| > optimization (speed) | 36.56% | |
26-
| > optimization (time cost) | 26.77% | |
27-
| Total (origin) | 181.22080246607462 | [218.57447242736816, 178.7542200088501, 179.97951698303223, 175.31463813781738, 173.79285717010498, 160.9091100692749] |
28-
| Total (plugin) | 145.1308192809423 | [166.8555600643158, 165.40182876586914, 165.04332208633423, 123.54309391975403, 124.4949209690094, 125.4461898803711] |
29-
| > optimization (speed) | 24.87% | |
30-
| > optimization (time cost) | 19.91% | |
31-
+--------------------------------------+--------------------+------------------------------------------------------------------------------------------------------------------------+
32-
```
33-
- Mac air (Apple M1/16g) :
34-
35-
```
36-
+--------------------------------------+-------------------+--------------------------------------------------------------------------------------------------------------------+
37-
| Case | Average(s) | Detail(s) |
38-
+--------------------------------------+-------------------+--------------------------------------------------------------------------------------------------------------------+
39-
| 100 source files & 125 pods (origin) | 95.07198365529378 | [91.36949586868286, 96.10968923568726, 97.73676586151123] |
40-
| 100 source files & 125 pods (plugin) | 91.2074584166289 | [90.87663986448735, 90.77357686752014, 91.97326111793518] |
41-
| > optimization (speed) | 4.24% | |
42-
| > optimization (time cost) | 4.06% | |
43-
| 1 source files & 125 pods (origin) | 81.564133644104 | [80.95829105377197, 82.07278513988386, 81.66132473945618] |
44-
| 1 source files & 125 pods (plugin) | 79.28314812668217 | [78.21958923339844, 80.21097787748413, 79.17887886892395] |
45-
| > optimization (speed) | 2.98% | |
46-
| > optimization (time cost) | 2.89% | |
47-
| Total (origin) | 88.3180586496989 | [91.36949586868286, 96.10968923568726, 97.73676586151123, 80.95829105377197, 82.07278513988386, 81.66132473945618] |
48-
| Total (plugin) | 85.2053037/161153 | [90.87663986448735, 90.77357686752014, 91.97326111793518, 78.21958923339844, 80.21097787748413, 79.17887886892395] |
49-
| > optimization (speed) | 3.65% | |
50-
| > optimization (time cost) | 3.52% | |
51-
+--------------------------------------+-------------------+--------------------------------------------------------------------------------------------------------------------+
52-
```
53-
54-
从上面的输出日志可以看出,插件可以带来3%-36%的编译速度提升,在使用Intel芯片的机器上优化效果还是挺好的,但是在使用Apple M1芯片的机器上效果就约等于没有了,只能说是M1的性能实在牛批。**如果你用的是M1,这里建议直接 `return`**
7+
## 首先,什么样的项目适合使用这个插件?
8+
9+
1. **仅适合使用 objective-c 作为主要开发语言项目**,因为 swift 没有头文件的概念,从其编译原理上看并没有什么帮助;
10+
2. **不适合 Podfile 中 开启了 `use_frameworks!` or `use_modular_headers!` 的项目使用**,由于为了兼容 clang module 特性,采取的策略是不对开启了 DEFINES_MODULE 的项目生成 hmap;
11+
3. **不适用于 CPU 为 M1 以及后续 M 系列芯片的 Mac**,因为使用之后提升也很小;
12+
13+
综上,比较适合 old school 的项目使用此插件,如果你的项目满足以上条件推荐使用此插件,不然可能收效甚微,不建议继续往下看了。
14+
15+
## 插件名的由来
16+
17+
最初版本的插件仅仅为了给 Pod Project 和 Host Project 提供一个可行的跨项目 hmap 方案,填补 Xcode 自带的仅支持 Project 内部的 hmap 的空白,由此得名:cocoapods-project-hmap.
5518

5619
## 环境要求
5720

@@ -92,6 +55,10 @@ target 'app' do
9255
end
9356
```
9457

58+
## 联系方式
59+
60+
QQ: 930565063
61+
9562
## License
9663

9764
cocoapods-project-hmap is released under the MIT license. See LICENSE for details.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
module CocoapodsProjectHmap
2-
VERSION = "0.0.4"
2+
VERSION = "0.0.5"
33
end

lib/cocoapods-project-hmap/pod_target.rb

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
module Pod
99
class Target
10+
attr_accessor :prebuilt_hmap_target_names
1011
def save_hmap(hmap)
1112
if hmap.empty? == false
1213
target_hmap_name="#{name}.hmap"
@@ -21,15 +22,22 @@ def save_hmap(hmap)
2122
end
2223
end
2324
end
25+
def add_prebuilt_hmap_target(name)
26+
@prebuilt_hmap_target_names = Array.new if @prebuilt_hmap_target_names == nil
27+
@prebuilt_hmap_target_names << name
28+
end
29+
def concat_prebuilt_hmap_targets(names)
30+
@prebuilt_hmap_target_names = Array.new if @prebuilt_hmap_target_names == nil
31+
@prebuilt_hmap_target_names.concat(names) if names
32+
end
2433
end
2534

2635
class PodTarget
27-
attr_accessor :unused_targets
2836
def reset_header_search_with_relative_hmap_path(hmap_path)
2937
if build_settings.instance_of?(Hash)
3038
build_settings.each do |config_name, setting|
3139
config_file = setting.xcconfig
32-
config_file.reset_header_search_with_relative_hmap_path(hmap_path, @unused_targets.uniq)
40+
config_file.reset_header_search_with_relative_hmap_path(hmap_path, @prebuilt_hmap_target_names.uniq)
3341
# https://github.com/CocoaPods/CocoaPods/issues/1216
3442
# just turn off private xcconfig's USE_HEADERMAP flag
3543
config_file.set_use_hmap(false)
@@ -38,45 +46,44 @@ def reset_header_search_with_relative_hmap_path(hmap_path)
3846
end
3947
elsif build_settings.instance_of?(BuildSettings::PodTargetSettings)
4048
config_file = build_settings.xcconfig
41-
config_file.reset_header_search_with_relative_hmap_path(hmap_path, @unused_targets.uniq)
49+
config_file.reset_header_search_with_relative_hmap_path(hmap_path, @prebuilt_hmap_target_names.uniq)
4250
# https://github.com/CocoaPods/CocoaPods/issues/1216
4351
# just turn off private xcconfig's USE_HEADERMAP flag
4452
config_file.set_use_hmap(false)
4553
config_path = xcconfig_path
4654
config_file.save_as(config_path)
4755
else
48-
puts 'Unknown build settings'.red
56+
Pod::UI.notice 'Unknown build settings'
4957
end
5058
end
5159
def recursively_add_dependent_headers_to_hmap(hmap, generate_type)
5260
dependent_targets.each do |depend_target|
5361
# set public header for dependent target
5462
depend_target.generate_hmap(hmap, generate_type, true, true) if depend_target.respond_to?(:generate_hmap)
55-
@unused_targets.concat(depend_target.unused_targets) unless depend_target.unused_targets.empty?
63+
concat_prebuilt_hmap_targets(depend_target.prebuilt_hmap_target_names) if depend_target.prebuilt_hmap_target_names
5664
end
5765
end
5866

5967
def generate_hmap(hmap, generate_type, only_public_headers=true, add_dependency=false)
60-
@unused_targets = Array.new if @unused_targets == nil
6168
# There is no need to add headers of target defines module to hmap.
6269
unless defines_module?
6370
unless $hmap_black_pod_list.include?(name)
64-
Pod::UI.message "- hanlding headers of target :#{name}"
71+
add_prebuilt_hmap_target(name)
6572
# Create hmap for current target if not in black list.
6673
hmap.add_hmap_with_header_mapping(only_public_headers ? public_header_mappings_by_file_accessor : header_mappings_by_file_accessor, generate_type, name, product_module_name)
6774
# Recursively add dependent targets if needed.
6875
recursively_add_dependent_headers_to_hmap(hmap, generate_type) if add_dependency
76+
else
77+
Pod::UI.message "- skip target in black list :#{name}"
6978
end
70-
else
71-
@unused_targets << name
7279
end
7380
end
7481
end
7582
class AggregateTarget
7683
def reset_header_search_with_relative_hmap_path(hmap_path)
7784
# override xcconfig
7885
xcconfigs.each do |config_name, config_file|
79-
config_file.reset_header_search_with_relative_hmap_path(hmap_path)
86+
config_file.reset_header_search_with_relative_hmap_path(hmap_path, @prebuilt_hmap_target_names.uniq)
8087
config_path = xcconfig_path(config_name)
8188
config_file.save_as(config_path)
8289
end

lib/cocoapods-project-hmap/podfile_dsl.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# built-in black list pods (long import path not supported
33
# you can use hmap_black_pod_list to add other pods
44
$hmap_black_pod_list = [
5-
'GoogleUtilities',
5+
# 'GoogleUtilities',
66
'MeshPipe',
77
'GoogleDataTransport',
88
'FirebaseCoreDiagnostics',

lib/cocoapods-project-hmap/xcconfig.rb

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,19 @@ def remove_attr_with_key(key)
77
@attributes.delete(key)
88
end
99
end
10-
def remove_header_search_path(white_list=nil)
10+
def remove_header_search_path(prebuilt_hmap_target_names=nil)
1111
header_search_paths = @attributes['HEADER_SEARCH_PATHS']
1212
if header_search_paths
1313
new_paths = Array.new
1414
header_search_paths.split(' ').each do |p|
15-
if p.include?('${PODS_ROOT}/Headers') == false
15+
if p.include?('${PODS_ROOT}/Headers') == false or p.end_with?('/Private"') or p.end_with?('/Public"')
1616
# retain path not in normal `pod headers` path
17+
# and "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public"
1718
new_paths << p
18-
elsif white_list != nil && white_list.empty? == false
19-
white_list.each do |white_target_name|
20-
if p.include?(white_target_name)
21-
new_paths << p
22-
break
23-
end
19+
elsif prebuilt_hmap_target_names != nil && prebuilt_hmap_target_names.empty? == false
20+
# add path not prebuilt hmap
21+
if prebuilt_hmap_target_names.select { |name| p.include?(name) }.empty?
22+
new_paths << p
2423
end
2524
end
2625
end

lib/cocoapods_plugin.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,13 @@ module ProjectHeaderMap
88
generate_type = $strict_mode ? HmapGenerator::ANGLE_BRACKET : HmapGenerator::BOTH
99
post_context.aggregate_targets.each do |one|
1010
pods_hmap = HmapGenerator.new
11-
Pod::UI.message "- hanlde headers of aggregate target :#{one.name}"
11+
Pod::UI.message "- hanlding headers of aggregate target :#{one.name}"
1212
one.pod_targets.each do |target|
1313
target.generate_hmap(pods_hmap, generate_type, true, false)
1414
target_hmap = HmapGenerator.new
1515
target.generate_hmap(target_hmap, HmapGenerator::BOTH, false, true)
1616
target.save_hmap(target_hmap)
17+
one.concat_prebuilt_hmap_targets(target.prebuilt_hmap_target_names)
1718
end
1819
one.save_hmap(pods_hmap)
1920
end

0 commit comments

Comments
 (0)