你可能不知道的 AS 小技巧之「Extract Resource」

介绍了一个Android Studio的小技巧,能够快速将代码或布局文件中的字符串转换为XML资源文件中的条目,极大提升了重构效率。

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

阅读本文大概需要 1 分钟。

最近,想对项目做点小重构,不经意间发现一个 Android Studio 小技巧,实话说,以前并不知道,有点小惊喜,于是迫不及待分享出来。

我们知道 Android 开发中,是不建议在布局文件或者代码中直接出现字符串的,而应该把字符串统一放在 String 的 xml 资源文件中,具体原因就不多解释了。

但是因为之前的老项目不太规范,或者有些开发的时候比较紧急,就直接裸写的字符串,现在有时间了,需要处理的时候还挺麻烦的,需要把字符串拷贝到 strings.xml 中,然后取一个 id,再之后把之前的字符串替换成 id。

是不是稍显麻烦?但是 AS 有个神秘的技巧可以一键帮你搞定。废话不多说,直接看演示动图:

0?

是不是很方便酷炫?

其实不止在布局文件中,同样适用于代码中,直接鼠标定位在字符串位置,然后 Alt + Enter -> Extract string/dimension resource 就 ok 了,简直不要太方便。


PS:通过后台读者的留言,我发现现在竟然还有用 Eclipse 来开发 Android 的,我只能说太落伍了吧,我在 14 年的时候,就在博客出了一套 Android Studio 的教程,号召国内 Android 开发尽早使用 AS,如今 Google 自己都抛弃了 Eclipse,不得不说,我还是蛮有远见的,你到现在还没使用 AS 真有点说不过去了。

再再 PS:最近我司有一大波职位有编制了,过几天我可能会发个招聘贴哦,准备找工作的不妨关注下,提前准备下简历,真的是一大波职位,好好把握机会。



其实,我在扯淡!

0

不止技术与职场,还有生活与远方

长按关注,听我扯淡

——

微博: @googdev

个人博客: http://stormzhang.com

0?

赞助商:

优秀人才不缺工作机会,只缺适合自己的好机会。但是他们往往没有精力从海量机会中找到最适合的那个。

100offer 会对平台上的人才和企业进行严格筛选,让「最好的人才」和「最好的公司」相遇。

扫描下方二维码,注册 100offer,谈谈你对下一份工作的期待。一周内,收到 5-10 个满足你要求的好机会!

640?

def extract_dataset(): df = pd.read_csv(file_path + processed_data_filename) dummies_df = pd.get_dummies(df, columns=["model", "vendor"], sparse=True) # 删除列并保留时间序列结构 dummies_df = dummies_df.drop(columns=['datetime', 'ptype']) window_size = 7 * 24 # 7天(每小时一条记录) future_window = 3 * 24 # 未来3天 # 直接提取窗口数据(非聚合计算) def extract_raw_windows(group): windows = [] for i in range(len(group) - window_size + 1): # 提取连续7天原始数据(168小时) window_data = group.iloc[i:i+window_size].drop(columns='is_fault') windows.append(window_data.values.flatten()) # 展平为特征向量 return windows # 并行提取原始窗口 raw_features = Parallel(n_jobs=-1)( delayed(extract_raw_windows)(group) for _, group in dummies_df.groupby('sn') ) # 标签生成(未来3天故障标志) def generate_labels(group): labels = [] for i in range(len(group) - window_size - future_window + 1): label = group['is_fault'].iloc[ i+window_size : i+window_size+future_window ].max() labels.append(label) return labels labels = Parallel(n_jobs=-1)( delayed(generate_labels)(group) for _, group in dummies_df.groupby('sn') ) # 合并结果 X = np.vstack([item for sublist in raw_features for item in sublist]) y = np.hstack([item for sublist in labels for item in sublist]) # 仅使用一种缩放(推荐标准化) scaler = StandardScaler() X_scaled = scaler.fit_transform(X) # 输出结构优化 samples_df = pd.DataFrame(X_scaled) samples_df['label'] = y print(samples_df.head(10)) 这个代码有哪些可以优化和修改?要对进程数和使用内存量做限制
最新发布
07-15
<think>我们面对的问题是如何优化基于pandas和Parallel的时序数据预处理代码,包括限制进程数和内存使用。 首先,用户使用了Parallel(可能是来自joblib库)来并行处理,但需要控制进程数和内存使用,以避免资源耗尽。 分析: 1. 限制进程数:在Parallel中可以通过n_jobs参数设置。 2. 限制内存使用:这通常需要从两个方面考虑: a. 每个子进程的内存使用:我们可以通过减少每个子进程处理的数据量,或者优化每个子进程中的代码来减少内存占用。 b. 整体内存管理:避免同时运行过多的子进程,因为每个子进程都会复制一部分数据(进程隔离),所以总内存使用量可能会很大。 针对Parallel,我们可以通过以下方式优化: - 设置n_jobs参数为合适的值,要超过CPU核心数(或者略多,但注意内存限制)。 - 使用pre_dispatch参数来控制同时被派发的任务数量,从而控制同时运行的进程数,进而控制内存峰值。 - 使用batch_size(在delayed函数内部)将大任务分成小块,这样可以让每个子进程一次处理一小部分数据,减少内存占用,同时也可以利用缓存。 另外,对于pandas操作,我们可以考虑: - 使用更高效的数据类型(例如,将category类型用于分类变量,使用整数类型代替浮点类型等)。 - 避免在并行函数中加载大文件,而是将数据作为参数传递(注意:在Windows上,由于使用spawn创建进程,需要确保数据可序列化且会太大;在Linux上使用fork则会复制数据,但修改数据会触发写时复制,也可能导致内存增加)。 - 使用chunksize分块处理,然后在每个子任务中处理一个块。 然而,用户提到的是时序数据预处理,可能涉及到时间序列特有的操作(如重采样、滑动窗口等),这些操作可能很耗内存。 建议的优化步骤: 1. 调整并行度:设置n_jobs为合适的值(例如,n_jobs=4),避免设置n_jobs=-1(使用所有核心),因为这样可能导致内存足。 2. 使用pre_dispatch:设置pre_dispatch='2*n_jobs'(默认值)或更小,以控制同时准备的任务数量,防止任务堆积占用内存。 3. 在并行函数中,尽量使用局部变量,并删除再需要的大变量,以帮助垃圾回收。 4. 使用分块处理:如果单个文件很大,可以在每个子任务中再分块处理(使用pandas的chunksize),但要注意这样可能会增加计算时间。 5. 考虑使用其他并行后端:joblib的默认后端是multiprocessing,它会产生多个进程,每个进程都有独立的内存空间。另一种选择是使用threading后端(如果任务是CPU密集型,而是I/O密集型),因为线程共享内存,但要注意GIL(全局解释器锁)对CPU密集型任务的限制。对于pandas,很多操作是受GIL限制的,所以多进程通常更好。但如果我们能减少内存复制,多线程也是可以考虑的(例如,当任务主要是I/O操作时)。 6. 监控内存:使用memory_profiler等工具监控内存使用情况。 代码示例: 假设原始代码可能是这样的: from joblib import Parallel, delayed import pandas as pd def process_file(file): df = pd.read_csv(file) # 进行一些预处理 return df files = [f'file_{i}.csv' for i in range(100)] results = Parallel(n_jobs=-1)(delayed(process_file)(file) for file in files) 优化版本: # 设置n_jobs为固定值,例如4 n_jobs = 4 # 根据可用内存和核心数调整 # 为了减少每个子进程的内存占用,我们可以在读取文件时使用更高效的数据类型 # 同时,我们可以考虑分块读取(如果单个文件很大,但这里每个文件可能大,所以需要) # 定义处理函数,注意优化内部操作 def process_file(file): # 指定数据类型,减少内存 dtypes = {'col1': 'int32', 'col2': 'float32', 'col3': 'category'} df = pd.read_csv(file, dtype=dtypes) # 处理... # 删除中间变量,及时释放内存 # ... return processed_df # 使用Parallel,并设置pre_dispatch results = Parallel(n_jobs=n_jobs, pre_dispatch='2*n_jobs')(delayed(process_file)(file) for file in files) 7. 如果内存仍然紧张,我们可以考虑分批处理文件。即,将文件列表分成若干批,每次只处理一批,等一批处理完再处理下一批。 batch_size = 20 # 每批20个文件 all_results = [] for i in range(0, len(files), batch_size): batch = files[i:i+batch_size] batch_results = Parallel(n_jobs=n_jobs)(delayed(process_file)(file) for file in batch) all_results.extend(batch_results) 8. 另外,如果数据量极大,可能需要考虑使用Dask或Spark等分布式计算框架,这些框架可以更好地处理内存限制。 9. 关于内存限制的硬性控制:在Python中,我们可以使用resource模块(Unix系统)来设置子进程的内存限制,但Windows支持。因此,跨平台方案可能较难。如果是在Linux上,可以尝试: import resource def set_memory_limit(): # 设置进程的最大虚拟内存为2GB soft, hard = resource.getrlimit(resource.RLIMIT_AS) resource.setrlimit(resource.RLIMIT_AS, (2 * 1024 * 1024 * 1024, hard)) # 然后在子进程中调用这个函数 def process_file(file): set_memory_limit() # ... 处理文件 # 注意:在Parallel中,每个子进程在启动后可以设置自己的资源限制。 但是,需要注意的是,如果子进程超出内存限制,它会被操作系统终止,这可能导致整个并行任务失败。因此,最好还是通过控制数据量和优化代码来避免。 总结:优化方向主要是控制并行进程数、分批次处理、优化每个进程的内存使用(包括数据类型和分块读取)、设置进程内存限制(仅Unix)等。 根据引用[2]中提到的单线程导入耗时8.65秒,我们可以推测每个文件处理的时间长,因此并行处理时主要关注内存控制。 相关问题: 1. 如何监控Python程序的内存使用情况? 2. 在并行处理中,如何避免内存泄漏? 3. 除了joblib,还有哪些适用于pandas的并行处理库? 4. 如何选择合适的分块大小(chunk size)来平衡内存和效率? 5. 在时间序列预处理中,有哪些常见的高效操作技巧?</think>### 优化Pandas和Parallel时序数据预处理的方案 针对时序数据预处理场景,以下是优化代码性能和资源占用的关键方案: #### 1. 控制并行进程数 ```python from joblib import Parallel, delayed # 显式设置进程数(建议为CPU核心数的50-75%) n_jobs = max(1, os.cpu_count() // 2) # 例:8核机器设为4进程 results = Parallel(n_jobs=n_jobs)(delayed(process_func)(chunk) for chunk in data_chunks) ``` - **原理**:避免`n_jobs=-1`(默认使用所有核心),减少进程竞争和内存开销[^1] - **建议**:通过`os.cpu_count()`动态获取核心数 #### 2. 内存优化策略 **a. 分块处理数据** ```python chunk_size = 10_000 # 根据内存调整 for chunk in pd.read_csv('data.csv', chunksize=chunk_size): process_chunk(chunk) ``` - **优势**:避免全量数据加载,减少峰值内存占用 **b. 优化数据类型** ```python dtype_dict = { 'temp': 'float32', # 比float64省50%内存 'device_id': 'category', # 分类数据专用类型 'timestamp': 'datetime64[s]' } df = df.astype(dtype_dict) ``` - **效果**:可减少内存占用60-70%[^1] **c. 主动释放内存** ```python del large_object # 显式删除大对象 gc.collect() # 强制垃圾回收 ``` #### 3. Parallel高级配置 ```python Parallel( n_jobs=4, backend='loky', # 比multiprocessing更稳定 mmap_mode='c', # 共享内存减少拷贝 max_nbytes='1M', # 限制子进程数据大小 batch_size=50, # 分批提交任务 pre_dispatch='n_jobs*2' # 控制预加载任务量 ) ``` #### 4. 时序处理专用优化 ```python # 使用resample代替循环计算 resampled = df.set_index('timestamp').resample('5T').mean() # 向量化操作替代apply df['moving_avg'] = df['value'].rolling(30).mean() # 比apply快100倍 ``` #### 5. 资源监控(可选) ```python # 实时监控内存 import psutil def memory_limit(perc=0.8): if psutil.virtual_memory().percent > perc * 100: os.kill(os.getpid(), signal.SIGTERM) ``` > **关键取舍**:当内存<32GB时,建议`n_jobs ≤ 4`;处理>1GB数据时,分块大小建议设为10000-50000行[^2]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值