范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

我用Rust改写了自己的C项目这两个语言都很折磨人!

  作者 | Strager
  译者 | 马可薇
  策划 | 褚杏娟
  C++漫长的构建时间可谓臭名昭著,编程圈的"我的代码在编译"只是个段子,但 C++让这个段子长盛不衰。
  谷歌 Chromium 规模的项目在新硬件上的构建时间长达一小时,而在老硬件上的构建时间更是达到了六个小时。虽然也有海量的调整方案能加速构建速度,还有不少削减构建内容但极易出错的捷径供人选择,再加上数千美元的云计算能力,Chromium 的构建时间仍是接近十分钟。这点我完全无法接受,人们每天都是怎么干活的啊?
  有人说 Rust 也是一样,构建时间同样令人头疼。但事实就是如此,还是这仅仅是一种反 Rust 的宣传手段?在构建时间方面 Rust 和 C++究竟谁能更胜一筹呢?
  构建速度和运行时性能对我来说非常重要。构建测试的周期越短,我编程就越高效、越快乐。我会不遗余力地让我的软件速度更快,让我的客户也越快乐。因此,我决定亲自试试 Rust 的构建速度到底怎么样,计划如下:
  找一个 C++项目 把项目中的一部分单独拿出来 逐行将 C++代码重写为 Rust 优化 C++和 Rust 项目的构建 对比两个项目的构建测试时间
  我的猜想如下(有理有据的猜测,但不是结论):
  Rust 的代码行数比 C++少。C++中多数函数和方法都需要声明两次:一次在 header 里,一次在实现文件里。但 Rust 不需要,因此代码行数会更少 C++的完整构建时间比 Rust 长(Rust 更胜一筹)。在每个.cpp 文件里,都需要重新编译一次 C++的 #include   功能和模板,虽然都是并行运行,但并行不等于完美。 Rust 的增量构建时间比 C++长(C++更胜一筹)。Rust 一个 crate(独立可编译单元)一编译,但 C++是按文件编译。因此代码每次变动,Rust 要读取的比 C++多。·
  对此,大家怎么看呢?我在推特上的投票结果如下:
  42%的人认为 C++会赢,35%同意"看情况",另外 17%的则觉得 Rust 会让我们大吃一惊。
  那么结果到底如何呢?下面让我们进入正题。
  编写 C++和 Rust 的测试对象找个项目
  考虑到我未来一个月都要花在重写代码上,什么样的代码最合适?我认为得满足以下几点:
  很少或不用第三方依赖(标准库可以使用); 能在 Linux 和 macOS 上运行(我不怎么管 Windows 上的构建时间); 大量测试套组(不然我没法确定 Rust 代码的正确性); FFI(外部函数接口)、指针、标准或自定义容器、功能类和函数、I/O、并发、泛型、宏、SIMD(单指令多数据流)、继承等等,多少都有使用。
  其实答案也很简单,直接找我前几年一直在做的项目就行。我用的是一个 JavaScript 词法分析器,quick-lint-js项目。
  quick-lint-js 的吉祥物 Dusty
  截取 C++代码
  quick-lint-js 项目中 C++部分的代码行数超过 10 万,要把这些全改成 Rust 得花上我半年时间,不如只关注 JavaScript 词法分析部分,其中涉及项目中的:
  诊断系统 翻译系统(用于诊断) 各种内存分配器和容器(如 bump 分配器、适用于 SIMD 的字符串) 各种功能类函数(如 UTF-8 解码器、SIMD 内在包装器) 测试的辅助代码(如自定义断言宏) C 的 API
  可惜这部分代码里不涉及并发或 I/O,我测试不了 Rust 里 async  / await  的编译时间开销,但这只是 quick-lint-js 项目里的一小部分,所以我还不用太担心。
  我首先把所有的 C++代码都复制到新项目里,然后删掉已知与词法分析无关的部分,比如分析器和 LSP 服务器。我甚至一不小心删多了代码,最后不得不重新把这些代码添了回去。在我不断截代码的过程中,C++的测试一直保持了通过状态。
  在彻底将 quick-lint-js 项目中涉及词法分析的部分全截出来之后,项目中 C++的代码大约有 1.7 万行。
  C++代码行数
  源码
  9.3k
  测试
  7.3k
  总计
  16.6k
  dep: Google Test
  69.7k
  重写代码
  至于要怎么重写这上千行的 C++代码,我选择按部就班:
  找一个适合转换的模块; 复制黏贴代码、测试、搜索替换并修改部分语法、继续运行 cargo(Rust 的构建系统和包管理器)测试直到构建测测试都通过; 如果这个模块依赖另一个模块,那就找到被依赖的模块,继续进行第二步,然后再回到现在这个模块; 如果还有模块没转换,再回到第一步。
  主要影响 Rust 和 C++构建时间的问题在于,C++的诊断系统是通过大量代码生成、宏、constexpr(常量表达式)实现的,而我在重写 Rust 版时,则用了代码生成、proc 宏、普通宏以及一点点 const 实现。传闻 proc 宏速度很慢,也有说是因为代码质量太差导致的 proc 宏速度慢。希望我写的 proc 宏还可以(祈祷~)。
  我写完才发现,原来 Rust 项目比 C++项目还要大,Rust 代码 17.1k 行,而 C++只有 16.6k 行。
  C++代码行数
  Rust代码行数
  行数差
  源码
  9.3k
  9.5k
  +0.2k (+1.6%)
  测试
  7.3k
  7.6k
  +0.3k (+4.3%)
  总数
  16.6k
  17.1k
  +0.4k (+2.7%)
  dep: Google Test
  69.7k
  dep: autocfg
  0.6k
  dep: lazy_static
  0.4k
  dep: libc
  88.6k
  dep: memoffset
  0.6k
  优化 Rust 构建
  构建时间很重要,因为我在截取 C++代码之前就已经做好了 C++项目构建时间的优化,所以我现在只需要对 Rust 项目的构建时间做同样的优化即可。以下是我觉得可能会优化 Rust 构建时间的条目:
  更快的链接器 Cranelift 后端 编译器和链接器标志 工作区与测试布局区分 最小化依赖功能 cargo-nextest 使用 PGO 自定义工具链
  更快的链接器
  我第一步要做的是分析构建,我用的是-Zself-profile rustc标志。在这个标志所生成的两个文件里,其中一个文件中的 run_linker 阶段颇为突出:
  条目
  本身时间
  全部时间占比
  run_linker
  129.20ms
  60.326
  LLVM_module_­codegen_emit_obj
  23.58ms
  11.009
  LLVM_passes
  13.63ms
  6.365
  第一轮-Zself-profile 结果
  之前我通过向Mold链接器的转换成功优化了 C++的构建时间,那这套对 Rust 能否行得通?
  Linux:链接器性能几乎一致。 (数据越小越好)
  可惜,Linux 上虽然确实有提升,但效果不明显。那 macOS 上的优化又表现如何?在 macOS 上默认链接器的替代品有两种,lld 和 zld,效果如下:
  macOS:链接器性能几乎不变。 (数据越小越好)
  可以看出,macOS 上替换默认链接器的效果同样不明显,我怀疑这可能是因为 Linux 和 macOS 上的默认链接器对我的小项目而言已经做到了最好,这些优化后的链接器(Mold、lld、zld)在大型项目上效果非常好。
  Cranelift 后端
  让我们再回到-Zself-profile的另一篇报告上,LLVM_module_­codegen_emit_obj 和 LLVM_passes 阶段颇为突出:
  条目
  自身时间
  全部时间占比
  LLVM_module_­codegen_emit_obj
  171.83ms
  24.274
  typeck
  57.50ms
  8.123
  eval_to_allocation_raw
  54.56ms
  7.708
  LLVM_passes
  50.03ms
  7.068
  codegen_module
  40.58ms
  5.733
  mir_borrowck
  36.94ms
  5.218
  -Zself-profile 的第二轮结果
  传闻可以把 rustc 的后端从 LLVM 换成 Cranelift,于是我又用rustc Cranelift后端重新构建了一遍,-Zself-profile 结果看起来不错:
  条目
  自身时间
  全部时间占比
  define function
  69.21ms
  12.307
  typeck
  57.94ms
  10.303
  eval_to_allocation_raw
  55.77ms
  9.917
  mir_borrowck
  33.44ms
  6.657
  使用 Cranelife 的-Zself-profile 第二轮结果
  可惜,在实际的构建中 Cranelife 比 LLVM 慢。
  Rust 后端:默认 LLVM 比 Cranelift 强。 (测试于 Linux,数据越小越好)
  2023 年 1 月 7 日更新:rustc 的 Cranelift 后端维护者 bjorn3 帮我看了下为什么 Cranelift 在我的项目上效果不佳:可能是 rustup 的开销导致的。如果绕过这部分 Cranelife 效果可能会有提升,上图中的结果没有采用任何措施。
  编译器和链接器标志
  编译器里有一堆可以加快(或减缓)构建速度的选项,让我们一一试过:
  -Zshare-generics=y (rustc) (Nightly only) -Clink-args=-Wl,-s (rustc) debug = false (Cargo) debug-assertions = false (Cargo) incremental = true 且 incremental = false (Cargo) overflow-checks = false (Cargo) panic = "abort" (Cargo) lib.doctest = false (Cargo) lib.test = false (Cargo)
  rustc 标志:快速构建优于调试构建。 (测试于 Linux,数据越小越好)
  注:图中的"quick, -Zshare-generics=y"与"quick, incremental=true"且启用"-Zshare-generics=y"标志相等同,其余柱状图没有标识"-Zshare-generics=y"是因为没有启用该标志,后者意味着需要 nightly rust 编译器。
  上图中使用的多数选项都有文档可查,但我还没找到有人写过加-s 的链接。子命令-s 将包括 Rust 标准库静态链接在内的所有调试信息全部剥离,让链接器做更少的工作,从而减少链接时间。
  工作区与测试布局
  在文件的物理位置问题上,Rust 和 Cargo 都提供了部分灵活性。对我的项目而言,以下是三种合理布局:
  理论上来说,如果我们把代码拆成多个 crate,cargo 就可以并行化 rustc 的调用。鉴于我的 Linux 机器上有一个 32 线程的 CPU,macOS 机器上有一个 10 线程的 CPU,并行化应该可以降低构建时间。
  对一个 crate 而言,Rust 项目中的测试有很多可运行的地方:
  由于依赖周期的存在,我没办法做"源码文件内的测试"这个布局的基准,但其他布局组合里我都做了基准:
  Rust 完整构建:工作区布局最快。 (测试于 Linux,数据越小越好)
  Rust 增量构建:最佳布局不明。 (测试于 Linux,数据越小越好)
  工作区设置中,无论是分成多个可执行测试(many test exes),还是合并成一个可执行测试,似乎都能斩获头筹。所以后续我们还是按照"工作区+多个可执行文件"的配置吧。 最小化依赖功能
  多个 crate 的拆分支持可选功能,而部分可选功能都是默认启用的,具体功能可以通过 cargo tree 命令查看:
  让我们把 crate 之一,libc 中的 std 功能关掉,测试后再看看构建时间有没有变化。
  Cargo.toml  [dependencies] +libc = { version = "0.2.138", default-features = false } -libc = { version = "0.2.138" }
  关掉 libc 功能后没有任何变化。 (测试于 Linux,数据越小越好)
  构建时间没有任何变化,有可能 std 功能实际没什么大影响。不管怎么说,让我们进入下一个环节。
  cargo-nextest
  作为一款据说"比 cargo 测试快 60%"的工具,cargo-nextest对于我这个代码中 44%都是测试的项目来说非常合适。让我们来对比下构建和测试时间:
  Linux:cargo-nextest 减慢了测试速度。 (数据越小越好)
  在我的 Linux 机器上,cargo-nextest 帮了倒忙,虽然输出不错,不过……
  示例 cargo-nextest 测试输出: PASS [   0.002s]        cpp_vs_rust::test_locale no_match PASS [   0.002s]     cpp_vs_rust::test_offset_of fields_have_different_offsets PASS [   0.002s]     cpp_vs_rust::test_offset_of matches_memoffset_for_primitive_fields PASS [   0.002s] cpp_vs_rust::test_padded_string as_slice_excludes_padding_bytes PASS [   0.002s]     cpp_vs_rust::test_offset_of matches_memoffset_for_reference_fields PASS [   0.004s] cpp_vs_rust::test_linked_vector push_seven
  那 macOS 上怎么说?
  macOS:cargo-nextest 加快了构建测试。 (数据越小越好)
  在我的 MacBook pro 上,cargo-nextest 确实提高了构建测试的速度。但为什么 Linux 上没有呢?难道是和硬件有关?
  在下面测试中,我会在 macOS 上使用 cargo-nextest,但 Linux 上的测试不用。
  使用 PGO 自定义工具链
  我发现 C++编译器的构建如果用配置文件引导的优化(PGO,也称作 FDO),会有明显的性能提升。因此,让我们试试用 PGO 优化 Rust 工具链的同时,也用 LLVM BOLT 加上-Ctarget-cpu=native 进一步优化 rustc。
  Rust 工具链:自定义工具链是最快的。 (测试于 Linux,数据越小越好)
  如果你好奇的话,可以看看这段工具链构建脚本。可能不适用于你的机器,但只要我能运行就行:https://github.com/quick-lint/cpp-vs-rust/blob/953429a4d92923ec030301e5b00face1c13bb92b/tools/build-toolchains.sh
  与 C++编译器相比,通过 rustup 发布的 Rust 工具链似乎已经是优化完成的结果。PGO 加上 BOLT 的组合只带来了不到 10%的性能提升。但有提升就是好的,所以在后续与 C++的竞争中我们会继续使用这个速度最快的工具链。
  我第一次搭建的 Rust 自定义工具链比 Nightly 还要慢 2%,我在 Rust config.toml 的各种选项中反复调整,不断交叉检查 Rust 的 CI 构建脚本以及我自己的脚本,最终在好几天的挣扎后才让这二者性能持平。在我最终润色这篇文章时,我进行了 rustup 更新,拉取 git 项目,并重头又建了一遍工具链。结果这次我的自定义工具链速度更快了!有可能是我在 Rust 仓库里提交错了代码……
  优化 C++构建
  在最初的 C++项目 quick-lint-js 中,我已经用常见的手段优化了编译时间,比如用 PCH、禁用异常和 RTTI、调整编译标志、删除非必要 #include、将代码从头中移出、外置模板实例等方法。但此外还有一些 C++编译器和链接器我没试过,在我们进入 C++和 Rust 的对比之前,先从这些里面挑出最适合我们的。
  Linux:自定义 Clang 是最快的工具链。 (数据越小越好)
  很明显,Linux 上的 GCC 是个特例,而 Clang 的表现则要好上很多。我自定义构建的 Clang(和 Rust 工具链一样,也是用 PGO 和 BOLT 构建的)相较于 Ubuntu 的 Clang,显著优化了构建时间,而 libstdc++的构建略快于平均 libc++的速度。
  那我的自定义 Clang 加上 libstdc++在 C++和 Rust 的对比中表现如何呢?
  macOS:Xcode 是最快的工具链。 (数据越小越好)
  在 macOS 上,搭配 Xcode 的 Clang 工具链似乎要比 LLVM 网站上的 Clang 工具链优化得更好。
  C++20 模块
  我的 C++代码用的是 #include,但如果用 C++20 中新增加的 import 又会怎么样呢?C++20 的模块是不是理论上来说应该会让编译速度超级快?
  我在项目了尝试过 C++20 模块,但直到 2023 年的 1 月 3 日,Linux 上的 CMake 模块支持过于实验性质了,我甚至连"hello world"都没跑起来。
  或许 2023 年中 C++20 模块会大放异彩,对于我这种超级在意构建时间的人来说,真是这样就太好了。但目前为止,我还是继续用经典 C++的 #include 和 Rust 做对比吧。
  对比 C++和 Rust 的构建时间
  通过把 C++项目改写成 Rust,并尽可能地优化 Rust 的构建时间后,问题来了:C++和 Rust 究竟谁更快呢?
  很可惜,答案是"看情况"!
  Linux:Rust 部分情况下构建速度超越 C++ 。(数据越小越好)
  在我的 Linux 机器上,部分情况下 Rust 的构建速度确实优于 C++,但也有速度持平或逊于 C++的情况。在增量 lex 的基准上,我们修改了大量源码,Clang 比 rustc 速度快,但在其他增量基准上,rustc 又会反超 Clang。
  macOS:C++构建速度通常快于 Rust。 (数据越小越好)
  但我的 macOS 机器上情况却截然不同。C++的构建速度常常快上 Rust 许多。在增量测试 utf-8 的基准,我们修改中等数量测试文件,rustc 编译速度会略微超过 Clang,但在包括全量构建等其他基准上,Clang 很明显效果要更好。
  超过 17k 行代码
  我基准测试的项目只有 17k 行代码,算是小型项目,那么对超过 10 万行代码的大型项目来说,又是什么情况呢?
  我把最大的模块,也就是词法分析器的代码复制粘贴了 8、16 以及 24 遍,分别用来测试。因为我的基准里也包括了运行测试的时间,我觉得构建时间即使是对于那些能瞬间构建完的项目,也应该会线性增长。
  C++代码行数
  Rust代码行数
  1x
  16.6k
  17.7k
  8x
  52.3k (+215%)
  43.7k (+156%)
  16x
  93.1k (+460%)
  74.0k (+334%)
  24x
  133.8k (+705%)
  104.4k (+512%)
  倍数扩大后 C++完整构建优于 Rust。 (测试于 Linux,数据越小越好)
  倍数扩大后 C++增量构建优于 Rust。 (测试于 Linux,数据越小越好)
  Rust 和 Clang 确实都是线性扩大,这点很好。
  正如预期中一样,修改 C++的头文件,也就是增量 diag-type 会大幅影响构建时间。而由于 Mold 链接器的存在,其他增量基准中构建时间的扩展系数很低。
  Rust 构建的扩展性让我很失望,即使只是增量 utf-8 测试的基准,无关文件的加入也不应该让它的构建时间如此受影响。测试所用的 crate 布局时"工作区且多个可执行测试",因此 utf-8 测试应该能独立编译可执行文件。 结论
  编译时间对 Rust 而言算是问题吗?答案是肯定的。虽然也有一些可以加快编译速度的提示和技巧,但却没有效果非常显著的数量级改进,这让我在开发 Rust 时非常高兴。
  Rust 的编译时间和 C++相比呢?确实也很糟。至少对我的编码风格来说,Rust 在大型项目上开发的编译时间甚至更加远比 C++还要糟糕。
  再回过头看看我当初的假设,几乎全军覆没:
  Rust 改写版代码行数比 C++多; 在全量构建上,C++相比 Rust 在 1.7 万行代码上构建时间相似,在 10 万行代码上构建时间要少; 在增量构建上,Rust 相比 C++在部分情况构建时间要短,在 1.7 万行上构建时间要长,在 10 万行代码上构建时间甚至更长。
  我不爽吗?确实。在改写过程中,我不断学习着 Rust 相关的知识,比如 proc marco 能替代三个不同代码生成器,简化构建流水线,让新开发者们日子更好过。但我完全不想念头文件,以及 Rust 的工具类真的很好用,特别是 Cargo、rustup 以及 miri。
  但我决定不把 quick-lint-js 项目中剩下的代码也改成 Rust,但如果 Rust 的构建时间能有明显优化,或许我会改变主意。当然,前提是我还没被Zig迷走心神。
  附注源码
  删减后的 C++项目源码、移植版 Rust(包括不同的项目布局)、代码生成脚本和基准测试脚本、GPL-3.0 及以上。
  Linux 机器
  名称:strapurp
  CPU:AMD Ryzen 9 5950X (PBO; stock clocks) (32 threads) (x86_64)
  RAM:G.SKILL F4-4000C19-16GTZR 2x16 GiB (overclocked to 3800 MT/s)
  操作系统:Linux Mint 21.1
  内核:Linux strapurp 5.15.0-56-generic #62-Ubuntu SMP Tue Nov 22 19:54:14 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
  Linux 性能治理器:schedutil
  CMake:版本 3.19.1
  Ninja:版本 1.10.2
  GCC:版本 12.1.0-2ubuntu1~22.04
  Clang(Ubuntu):版本 14.0.0-1ubuntu1
  Clang (自定义):版本 15.0.6(Rust fork; 代码提交3dfd4d93fa013e1c0578­d3ceac5c8f4ebba4b6ec)
  libstdc++ for Clang:版本 11.3.0-1ubuntu1~22.04
  Rust 稳定版:1.66.0 (69f9c33d7 2022-12-12)
  Rust Nightly:版本 1.68.0-nightly (c7572670a 2023-01-03)
  Rust(自定义):版本 1.68.0-dev (c7572670a 2023-01-03)
  Mold:版本 0.9.3 (ec3319b37f653dccfa4d­1a859a5c687565ab722d)
  binutils:版本 2.38
  macOS 机器
  名称:strammer
  CPU:Apple M1 Max (10 threads) (AArch64)
  RAM:Apple 64 GiB
  操作系统:macOS Monterey 12.6
  CMake:版本 3.19.1
  Ninja:版本 1.10.2
  Xcode Clang:Apple clang 版本 14.0.0 (clang-1400.0.29.202) (Xcode 14.2)
  Clang 15:版本 15.0.6 (LLVM.org website)
  Rust 稳定版:1.66.0 (69f9c33d7 2022-12-12)
  Rust Nightly:版本 1.68.0-nightly (c7572670a 2023-01-03)
  Rust(自定义):版本 1.68.0-dev (c7572670a 2023-01-03)
  lld:版本 15.0.6
  zld:代码提交 d50a975a5fe6576ba0fd­2863897c6d016eaeac41
  基准
  用 deps 的构建和测试
  C++: cmake -S build -B . -G Ninja && ninja -C build quick-lint-js-test && build/test/quick-lint-js-test   计时
  Rust: cargo fetch   未计时,再用  cargo test   计时
  不用 deps 的构建和测试
  C++: cmake -S build -B . -G Ninja && ninja -C build gmock gmock_main gtest   未计时, 再用 ninja -C build quick-lint-js-test && build/test/quick-lint-js-test   计时
  Rust: cargo build --package lazy_static --package libc --package memoffset"   未计时, 再用 cargo test   计时
  增量 diag-types
  C++:构建和测试未计时,随后修改 diagnostic-types.h  ,再用 ninja -C build quick-lint-js-test && build/test/quick-lint-js-test
  Rust:构建和测试未计时,修改 diagnostic_types.rs  后, cargo test
  增量 lex
  同增量 diag-types,但使用 lex.cpp/lex.rs
  增量 utf-8 测试
  同增量,但使用 test-utf-8.cpp/test_utf_8.rs
  每个可执行基准均采用 12 个样本,弃置前两个,基准仅显示最后十个样本的平均性能。误差区间展示最小与最大样本间区别。
  原文链接:
  https://quick-lint-js.com/blog/cpp-vs-rust-build-times/

詹姆斯家人就是我的首发五虎妻子是真正的MVP直播吧2月10日讯湖人迎战雄鹿,球队在赛前为詹姆斯举行加冕得分王庆祝仪式。詹姆斯牵着心爱的女儿Zhuri入场湖人名宿詹姆斯沃西现场致辞祝贺詹姆斯詹姆斯在家人和球迷面前发表了长篇讲话市场的脊梁骨市场信息传递的基础设施,我们称之为脊梁骨。在实体世界中依靠的是美联储主导的全球商业银行网络,是一个租脊柱的社会(租金是利息)。这是一个单向度的框架,资本的基础设施通过向上制造稀缺欲新疆吐鲁番市167个重大项目集中开复工开工复工仪式现场。杨文浩摄中新网乌鲁木齐2月10日电(杜虎)开春即开工,复产即满弦。2月10日上午,新疆吐鲁番市2023年第一季度重大项目集中复工开工仪式在鄯善工业园区鄯善硅基新材听过直播带岗吗?将春风吹到企业和求职者身边文维辰听说过直播带货,你听过直播带岗吗?春节还没过去,多地保障企业用工需求的抢人大战已悄然打响。一些用工大省不仅在节前就开始布局跨省招工包机包车接务工人员返岗复工,各地人社部门主办数读中汽协1月乘用车产销同比均下降33市场需要政策持续提振文懂车帝原创李德喆懂车帝原创行业2月10日,中国汽车工业协会公布了2023年1月汽车工业运行情况。受春节假期及部分消费需求提前透支影响,叠加传统燃油车购置税优惠和新能源汽车补贴政策再有国内企业研发光刻机,挡不住中国芯片了,美国和ASML后悔不迭光刻机已成为中国芯片发展的最大障碍,美国恰恰是看到这一点,近段时间拉拢ASML和尼康等限制对中国出售光刻机,试图阻止中国芯片前进的脚步,然而日前又一家中国企业表示已成功研发出光刻机痘痘不断?这4种食物正在加剧你的烦恼!长痘这事除了身体原因,其实还有一个重要的原因就是跟我们吃的东西有关系,今天我要和大家分享三种食物,这三种食物是越吃痘痘越多。首先,脂肪和糖类食物对皮肤长痘有很大影响。摄入过多的脂肪U20国足抵克后首场热身赛下半场连追2球,22逼平拉脱维亚国青当地时间2月2日抵达克罗地亚之后,经过一个星期的调整,中国U20国足在当地时间2月9日晚,与拉脱维亚U19国家队进行了一场热身赛,上半场02落后的情况下,下半场中国队由阿卜杜拉希尔佩林卡欢迎新援相信他们能帮助球队以强劲的势头结束这个赛季直播吧2月10日讯今日湖人官方宣布球队交易得到德安吉洛拉塞尔马利克比斯利和范德比尔特。佩林卡在一份声明中表示我们很高兴拉塞尔马利克和贾里德能够加入我们的球队,我们相信他们的才能将提一些著名的诡异事件太平洋孤岛事件太平洋孤岛事件是指1937年12月5日,一架名为明尼苏达号的美国客机在飞往澳大利亚的途中失踪,飞机上的人员共20人,包括乘客和机组人员,他们在飞行中消失了,没有任何一听,火箭兵的心里话马启蕾向战教战育尖兵视频加载中本期发言人马启蕾,火箭军士官学校基础部军事共同课目教研室教员,火箭军第一届军人代表大会代表。先后被评为某部优秀基层干部标兵践行高原火箭兵精神模范,学校四有优秀军官优秀共产
被日本老人街拍惊艳了白发不染,穿衣不扮嫩不显老,优雅不做作每次一提到时尚潮流,相信大多数的人都会很自然的想到年轻人,可实际上,这些不仅仅是年轻人的专利,对于老年女性来说,只要懂得打扮自己时尚感照样很强。在大多数的日本奶奶身上,就总是有着我小香风这一次又赢了!春天穿它,时髦优雅女人从来不会输女人要变美,往往需要内外兼具,热爱服饰穿搭,可要是缺乏内涵和素养,就会让气质这一块没法很好地体现出来。同理,若本身具有见识和修为,但不具备美学常识和扮美的方法,内在美也一样会被掩藏天鹅群空降北京平谷金海湖上演水上芭蕾中新网北京2月27日电(马平川)初春的北京市平谷区金海湖,冰消湖开。2月27日,30多只大天鹅飞临金海湖。它们在春日暖阳下的湖水中悠然漫舞,山水大幕陪伴婀娜精灵,仿佛奏响了天鹅湖优美食课堂甲流高发期,饮食建议3吃2不吃!近期,甲流肆虐让很多人都中招了,这甲流到底是咋回事?普通人从饮食上要如何应对呢?甲流的传播能力特别强,尤其是冬春交替这个季节,天气乍暖还寒,本就容易感冒发热,所以这个时候,除了要注宋高宗为何会将皇位传给宋太祖后人建炎元年六月十三(1127年7月23日),宋高宗的妃子潘氏在南京(今河南商丘)生下一子,取名为赵旉,是为宋高宗第一子,一出生是备受宠爱,宋高宗对其可谓是寄予厚望,后来立其为皇太子。大明风云人物10朱文正此篇为大家介绍朱元璋的宗族大将,以老朱亲侄的特殊身份展现军事才华,逐渐成为洪武时期军中巨擘。后却因欲望难填,死于亲叔叔鞭打之下的大都督朱文正。朱重四比弟弟朱重八(元璋)年长二十岁,南京鼓楼开展安全生产培训2月10日,鼓楼区水务局邀请江苏中安科技服务有限公司共同开展安全生产培训学习,各水务项目建设单位施工单位负责人和安全生产管理人员等参加。该公司安全专家围绕落实六个一要求,从安全生产西藏英雄城江孜风光江孜是西藏历史文化名城,地处西藏南部,面积3800平方公里,人口6。8万。1904年,英国侵略西藏,江孜人民不畏强暴,浴血卫国,英勇悲壮,英雄城因此闻名中外。宗山位于县城中心,是江临沂费县坚持四化之路肉鸡产业蓬勃发展有力助推乡村振兴来源人民网山东频道近年来,临沂费县始终坚持绿色发展理念,通过强化科技支撑和监管服务双轮驱动,持续推进肉鸡产业转型升级,肉鸡产业发展迅猛,为全县乡村振兴注入了源头活水。坚持走规模化产家居行业专题报告迎来拐点,看好家居复苏与高质量发展(报告出品方作者东莞证券,魏红梅谭欣欣)1。家居行业复苏,2023年或是关键拐点1。1家居行业概况家居产业链覆盖范围广。从上游供应来看,家居行业上游包括多种原材料供应商,提供如实木山海经传说军团系统详细概述山海经传说是一款大型多人角色扮演游戏,由同名热播电视剧改编而成,整个游戏贯穿电视剧的故事剧情让玩家在游戏领略不同的风采,为玩家带来一个全新的游戏世界。山海经传说军团系统详细概述ht