GCP 数据流上 Python 与 Java 运行 之间的 Apache Beam 性能
Apache Beam Performance Between Python Vs Java Running on GCP Dataflow
我们在使用 Python 和 Java 编写的 GCP 数据流上有 Beam 数据管道 运行。一开始,我们有一些简单直接的 python beam 作业,效果很好。所以最近我们决定 运行sform 更多 java beam to python beam 工作。当我们有更复杂的工作时,尤其是需要在光束中开窗的工作,我们注意到 python 工作比 java 工作明显慢,最终使用更多 cpu 和内存而且花费更多。
一些示例 python 代码如下所示:
step1 = (
read_from_pub_sub
| "MapKey" >> beam.Map(lambda elem: (elem.data[key], elem))
| "WindowResults"
>> beam.WindowInto(
beam.window.SlidingWindows(360,90),
allowed_lateness=args.allowed_lateness,
)
| "GroupById" >> beam.GroupByKey()
而 Java 代码如下:
PCollection<DataStructure> step1 =
message
.apply(
"MapKey",
MapElements.into(
TypeDescriptors.kvs(
TypeDescriptors.strings(), TypeDescriptor.of(DataStructure.class)))
.via(event -> KV.of(event.key, event)))
.apply(
"WindowResults",
Window.<KV<String, CustomInterval>>into(
SlidingWindows.of(Duration.standardSeconds(360))
.every(Duration.standardSeconds(90)))
.withAllowedLateness(Duration.standardSeconds(this.allowedLateness))
.discardingFiredPanes())
.apply("GroupById", GroupByKey.<String, DataStructure>create())
我们注意到 Python 总是比 Java 需要多使用 3 次 CPU 和内存。我们做了一些实验测试,只是 运行 JSON 输入和 JSON 输出,结果相同。我们不确定这只是因为 Python 通常比 java 慢,或者 GCP 数据流执行 Beam Python 和 Java 的方式不同。任何类似的经验,测试和原因表示赞赏。
是的,这是 Python 和 Java 之间非常正常的性能因素。事实上,对于许多程序来说,该系数可能是 10 倍或更多。
程序的细节可以从根本上改变相对性能。以下是一些需要考虑的事项:
- Profiling the Dataflow job (official docs)
- Profiling a Dataflow pipeline (medium blog)
- Profiling Apache Beam Python pipelines (another medium blog)
- Profiling Python (general Cloud Profiler docs)
- How can I profile a Python Dataflow job?(上一个关于分析 Python 作业的 Whosebug 问题)
如果您更喜欢 Python 的简洁语法或库生态系统,实现速度的方法是使用优化的 C 库或 Cython 进行核心处理,例如使用 pandas/numpy/etc。如果您使用 Beam's new Pandas-compatible dataframe API,您将自动获得此福利。
我们在使用 Python 和 Java 编写的 GCP 数据流上有 Beam 数据管道 运行。一开始,我们有一些简单直接的 python beam 作业,效果很好。所以最近我们决定 运行sform 更多 java beam to python beam 工作。当我们有更复杂的工作时,尤其是需要在光束中开窗的工作,我们注意到 python 工作比 java 工作明显慢,最终使用更多 cpu 和内存而且花费更多。
一些示例 python 代码如下所示:
step1 = (
read_from_pub_sub
| "MapKey" >> beam.Map(lambda elem: (elem.data[key], elem))
| "WindowResults"
>> beam.WindowInto(
beam.window.SlidingWindows(360,90),
allowed_lateness=args.allowed_lateness,
)
| "GroupById" >> beam.GroupByKey()
而 Java 代码如下:
PCollection<DataStructure> step1 =
message
.apply(
"MapKey",
MapElements.into(
TypeDescriptors.kvs(
TypeDescriptors.strings(), TypeDescriptor.of(DataStructure.class)))
.via(event -> KV.of(event.key, event)))
.apply(
"WindowResults",
Window.<KV<String, CustomInterval>>into(
SlidingWindows.of(Duration.standardSeconds(360))
.every(Duration.standardSeconds(90)))
.withAllowedLateness(Duration.standardSeconds(this.allowedLateness))
.discardingFiredPanes())
.apply("GroupById", GroupByKey.<String, DataStructure>create())
我们注意到 Python 总是比 Java 需要多使用 3 次 CPU 和内存。我们做了一些实验测试,只是 运行 JSON 输入和 JSON 输出,结果相同。我们不确定这只是因为 Python 通常比 java 慢,或者 GCP 数据流执行 Beam Python 和 Java 的方式不同。任何类似的经验,测试和原因表示赞赏。
是的,这是 Python 和 Java 之间非常正常的性能因素。事实上,对于许多程序来说,该系数可能是 10 倍或更多。
程序的细节可以从根本上改变相对性能。以下是一些需要考虑的事项:
- Profiling the Dataflow job (official docs)
- Profiling a Dataflow pipeline (medium blog)
- Profiling Apache Beam Python pipelines (another medium blog)
- Profiling Python (general Cloud Profiler docs)
- How can I profile a Python Dataflow job?(上一个关于分析 Python 作业的 Whosebug 问题)
如果您更喜欢 Python 的简洁语法或库生态系统,实现速度的方法是使用优化的 C 库或 Cython 进行核心处理,例如使用 pandas/numpy/etc。如果您使用 Beam's new Pandas-compatible dataframe API,您将自动获得此福利。