SlideShare a Scribd company logo
Optimizing Spark UDFs
Shivangi Srivastava
Senior Engineering Manager
Presenter Introduction
▪ Shivangi Srivastava
▪ Senior Engineering Leader at Informatica
▪ 10 + years of experience with Distributed computing, database systems
▪ Linkedin - https://www.linkedin.com/in/shivangi-srivastava1
Informatica
• Leading provider of Data Engineering solutions
• Informatica offerings –
Agenda
▪ Introduction to UDF
▪ Example and benefits of UDF
▪ Performance considerations
▪ Suggested Alternatives
▪ Performance results
▪ Questions/Feedback
Introduction to UDFs
▪ User-Defined Functions (aka UDF) is a feature of Spark SQL to define
new Column-based functions that extend the vocabulary of Spark
SQL’s DSL for transforming Datasets.
▪ UDFs are key features of most SQL environment and extend the system’s in-built functionality.
▪ Custom functions can be defined and registered as UDFs in Spark SQL with an associated alias that is made available to SQL
queries.
Typical Example
▪ Define a UDF in scala
val plusOne = udf((x: Int) => x + 1)
▪ Register the UDF
spark.udf.register("plusOne", plusOne)
▪ Usage
spark.sql("SELECT plusOne(5)").show()
// +------+
// |UDF(5)|
// +------+
// | 6|
// +------+
Benefits of UDFs
▪ Extends the in-built capabilities of Spark SQL.
▪ Simple and straightforward to implement.
▪ Plug and play architecture.
▪ Define once and use across multiple dataframes.
▪ Backward compatible. Stable API not impacted by version upgrades.
Performance concerns with UDFs
▪ UDFs are black-box to Spark optimizations.
▪ UDFs block many spark optimizations like
▪ WholeStageCodegen
▪ Null Optimizations
▪ Predicate Pushdown
▪ More optimizations from Catalyst Optimizer
▪ String Handling within UDFs
▪ UTF-8 to UTF-16 conversion. Spark maintains string in UTF-8 encoding versus Java runtime encodes in UTF-16.
▪ Any String input to UDF requires UTF-8 to UTF-16 conversion.
▪ Conversely, a String output requires a UTF-16 to UTF-8 conversion.
age codegen
Analyzing physical plan
X+1 versus PlusOne
Analyzing physical plan
X+1 versus plusOne
Analyzing physical plan – Predicate Pushdown
X+1 versus plusOne
Analyzing physical plan – Predicate Pushdown
X+1 versus plusOne
Redesign UDF implementation
▪ Implement UDFs as Spark native functions.
▪ Design Goals for reimplementing.
▪ Extend Spark’s capabilities with minimal changes to the existing Spark code.
▪ Ability to upgrade to later Spark versions without significant engineering effort
Reimplementing Spark UDFs as Spark native
▪ Create a new project structure like spark.
Reimplementing Spark UDFs as Spark native
▪ Extend from Spark’s Expression class
▪ UnaryExpression – Single argument expressions
▪ TernaryExpression – Multi argument expressions
▪ Satisfy expression contract
Reimplementing Spark UDFs as Spark native
▪ Examples for existing Spark functions can be found at –
▪ sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/
Reimplementing Spark UDFs
▪ Define the function
implementation
Reimplementing Spark UDFs as Spark native
functions
▪ Add new function definition file to package org.apache.spark.sql
▪ Compile and add the jar to spark/jars folder.
Reimplementing - Usage
▪ Select as a normal function available within spark library.
Reimplementing - SQL
▪ Functions require editing of FunctionsRegistry.scala if sql support is
needed.
▪ sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/FunctionRegistry.scala
▪ Register your function
▪ expression[PlusOneNative]("plusonenative“)
▪ Recompile spark code to generate spark-catalyst_*.jar
▪ Edit the pom to add dependency to your previously created jar.
▪ Replace under spark/jars location
Reimplementing - Usage
▪ Exercise using spark-sql
Analyzing physical plan – Predicate Pushdown
plusOneNative
More Tips and Tricks
▪ Make conscious effort to avoid temporary object allocation.
▪ Use Scala’s while construct over for.
▪ For causes creation of temporary object creation.
▪ Consider imperative style over functional style.
▪ Consider using thread static variable to allocate temporary buffer
▪ Sometimes UTF-8 to UTF-16 conversion is required, consider lazy
conversion based on presence of UTF-16 characters.
▪ Inspect the string for presence of UTF-16 characters
Performance Comparison – String function
▪ Performance
improvement of about
20% to 200%
▪ Overhead of UTF-8 to
UTF-16 conversion
avoided. SF1 SF10 SF50
optimization disabled 0:02:57 0:04:13 0:18:29
optimization enabled 0:02:38 0:03:26 0:06:21
0:00:00
0:02:53
0:05:46
0:08:38
0:11:31
0:14:24
0:17:17
0:20:10
Time(hh:mm:ss)
Scale Factor
String Function
optimization disabled optimization enabled
Performance Comparison – Date function
▪ Performance
improvement of about
20% to 100%
▪ Avoided creating
temporary objects
▪ Used imperative style programming
▪ Used while instead of for
SF1 SF10 SF50
optimization disabled 0:03:10 0:04:28 0:10:09
optimization enabled 0:02:38 0:02:41 0:05:39
0:00:00
0:01:26
0:02:53
0:04:19
0:05:46
0:07:12
0:08:38
0:10:05
0:11:31
Time(hh:mm:ss)
Scale Factor
Date Function
optimization disabled optimization enabled
Performance Comparison – Numeric function
▪ Performance
improvement of about
15% to 50%
SF1 SF10 SF50
optimization disabled 0:04:15 0:06:07 0:10:41
optimization enabled 0:03:36 0:04:04 0:09:15
0:00:00
0:01:26
0:02:53
0:04:19
0:05:46
0:07:12
0:08:38
0:10:05
0:11:31
Time(hh:mm:ss)
Scale Factor
Numeric Function
optimization disabled optimization enabled
Performance comparison - Summary
▪ 200% faster for certain String functions with large datasets (50GB).
▪ 50%-100% faster for date and numeric functions.
▪ Performance difference becomes noticeable with larger datasets.
▪ Conversion and optimization cost goes up.
▪ Garbage collection overhead becomes a significant contributor to the overall execution time.
Feedback
Your feedback is important to us.
Don’t forget to rate
and review the sessions.

More Related Content

PDF
Fine Tuning and Enhancing Performance of Apache Spark Jobs
PDF
Deep Dive into Spark SQL with Advanced Performance Tuning with Xiao Li & Wenc...
PPTX
A Deep Dive into Spark SQL's Catalyst Optimizer with Yin Huai
PDF
Designing Structured Streaming Pipelines—How to Architect Things Right
PDF
Deep Dive: Memory Management in Apache Spark
PDF
Apache Spark Core – Practical Optimization
PDF
Building a SIMD Supported Vectorized Native Engine for Spark SQL
PPTX
Optimizing Apache Spark SQL Joins
Fine Tuning and Enhancing Performance of Apache Spark Jobs
Deep Dive into Spark SQL with Advanced Performance Tuning with Xiao Li & Wenc...
A Deep Dive into Spark SQL's Catalyst Optimizer with Yin Huai
Designing Structured Streaming Pipelines—How to Architect Things Right
Deep Dive: Memory Management in Apache Spark
Apache Spark Core – Practical Optimization
Building a SIMD Supported Vectorized Native Engine for Spark SQL
Optimizing Apache Spark SQL Joins

What's hot (20)

PDF
InfluxDB IOx Tech Talks: Query Engine Design and the Rust-Based DataFusion in...
PPTX
Tuning and Debugging in Apache Spark
PDF
Apache Spark Core—Deep Dive—Proper Optimization
PDF
Understanding Query Plans and Spark UIs
PDF
Spark SQL
PDF
Improving SparkSQL Performance by 30%: How We Optimize Parquet Pushdown and P...
PDF
Understanding Memory Management In Spark For Fun And Profit
PDF
Spark and S3 with Ryan Blue
PDF
Top 5 Mistakes to Avoid When Writing Apache Spark Applications
PDF
Tuning Apache Spark for Large-Scale Workloads Gaoxiang Liu and Sital Kedia
PDF
Materialized Column: An Efficient Way to Optimize Queries on Nested Columns
PDF
Apache Spark At Scale in the Cloud
PDF
Simplify CDC Pipeline with Spark Streaming SQL and Delta Lake
PDF
How Adobe Does 2 Million Records Per Second Using Apache Spark!
PDF
Dynamic Partition Pruning in Apache Spark
PDF
Parquet performance tuning: the missing guide
PDF
Spark shuffle introduction
PDF
From Query Plan to Query Performance: Supercharging your Apache Spark Queries...
PDF
Apache Spark in Depth: Core Concepts, Architecture & Internals
PDF
Running Apache Spark on Kubernetes: Best Practices and Pitfalls
InfluxDB IOx Tech Talks: Query Engine Design and the Rust-Based DataFusion in...
Tuning and Debugging in Apache Spark
Apache Spark Core—Deep Dive—Proper Optimization
Understanding Query Plans and Spark UIs
Spark SQL
Improving SparkSQL Performance by 30%: How We Optimize Parquet Pushdown and P...
Understanding Memory Management In Spark For Fun And Profit
Spark and S3 with Ryan Blue
Top 5 Mistakes to Avoid When Writing Apache Spark Applications
Tuning Apache Spark for Large-Scale Workloads Gaoxiang Liu and Sital Kedia
Materialized Column: An Efficient Way to Optimize Queries on Nested Columns
Apache Spark At Scale in the Cloud
Simplify CDC Pipeline with Spark Streaming SQL and Delta Lake
How Adobe Does 2 Million Records Per Second Using Apache Spark!
Dynamic Partition Pruning in Apache Spark
Parquet performance tuning: the missing guide
Spark shuffle introduction
From Query Plan to Query Performance: Supercharging your Apache Spark Queries...
Apache Spark in Depth: Core Concepts, Architecture & Internals
Running Apache Spark on Kubernetes: Best Practices and Pitfalls
Ad

Similar to Optimizing Apache Spark UDFs (20)

PDF
Migrating ETL Workflow to Apache Spark at Scale in Pinterest
PPTX
Stream, stream, stream: Different streaming methods with Spark and Kafka
PDF
Big Data Beyond the JVM - Strata San Jose 2018
PDF
Adi Polak - Light up the Spark in Catalyst by avoiding UDFs - Codemotion Berl...
PDF
Creating Reusable Geospatial Pipelines
PDF
Fast federated SQL with Apache Calcite
PPTX
Spark - The Ultimate Scala Collections by Martin Odersky
PPTX
Adi Polak - Light up the Spark in Catalyst by avoiding UDFs - Codemotion Berl...
PPTX
Profiling & Testing with Spark
PPTX
Adi Polak - Light up the Spark in Catalyst by avoiding UDFs - Codemotion Mila...
PPTX
Spark UDFs are EviL, Catalyst to the rEsCue!
PDF
Writing an Interactive Interface for SQL on Flink
PDF
Migrating to spark 2.0
PDF
Portable UDFs: Write Once, Run Anywhere
PDF
Scala & Spark(1.6) in Performance Aspect for Scala Taiwan
PPTX
Spark Advanced Analytics NJ Data Science Meetup - Princeton University
PPTX
AWS Big Data Demystified #3 | Zeppelin + spark sql, jdbc + thrift, ganglia, r...
PDF
PySpark on Kubernetes @ Python Barcelona March Meetup
PDF
Productionalizing a spark application
PDF
Hadoop made fast - Why Virtual Reality Needed Stream Processing to Survive
Migrating ETL Workflow to Apache Spark at Scale in Pinterest
Stream, stream, stream: Different streaming methods with Spark and Kafka
Big Data Beyond the JVM - Strata San Jose 2018
Adi Polak - Light up the Spark in Catalyst by avoiding UDFs - Codemotion Berl...
Creating Reusable Geospatial Pipelines
Fast federated SQL with Apache Calcite
Spark - The Ultimate Scala Collections by Martin Odersky
Adi Polak - Light up the Spark in Catalyst by avoiding UDFs - Codemotion Berl...
Profiling & Testing with Spark
Adi Polak - Light up the Spark in Catalyst by avoiding UDFs - Codemotion Mila...
Spark UDFs are EviL, Catalyst to the rEsCue!
Writing an Interactive Interface for SQL on Flink
Migrating to spark 2.0
Portable UDFs: Write Once, Run Anywhere
Scala & Spark(1.6) in Performance Aspect for Scala Taiwan
Spark Advanced Analytics NJ Data Science Meetup - Princeton University
AWS Big Data Demystified #3 | Zeppelin + spark sql, jdbc + thrift, ganglia, r...
PySpark on Kubernetes @ Python Barcelona March Meetup
Productionalizing a spark application
Hadoop made fast - Why Virtual Reality Needed Stream Processing to Survive
Ad

More from Databricks (20)

PPTX
DW Migration Webinar-March 2022.pptx
PPTX
Data Lakehouse Symposium | Day 1 | Part 1
PPT
Data Lakehouse Symposium | Day 1 | Part 2
PPTX
Data Lakehouse Symposium | Day 2
PPTX
Data Lakehouse Symposium | Day 4
PDF
5 Critical Steps to Clean Your Data Swamp When Migrating Off of Hadoop
PDF
Democratizing Data Quality Through a Centralized Platform
PDF
Learn to Use Databricks for Data Science
PDF
Why APM Is Not the Same As ML Monitoring
PDF
The Function, the Context, and the Data—Enabling ML Ops at Stitch Fix
PDF
Stage Level Scheduling Improving Big Data and AI Integration
PDF
Simplify Data Conversion from Spark to TensorFlow and PyTorch
PDF
Scaling your Data Pipelines with Apache Spark on Kubernetes
PDF
Scaling and Unifying SciKit Learn and Apache Spark Pipelines
PDF
Sawtooth Windows for Feature Aggregations
PDF
Redis + Apache Spark = Swiss Army Knife Meets Kitchen Sink
PDF
Re-imagine Data Monitoring with whylogs and Spark
PDF
Raven: End-to-end Optimization of ML Prediction Queries
PDF
Processing Large Datasets for ADAS Applications using Apache Spark
PDF
Massive Data Processing in Adobe Using Delta Lake
DW Migration Webinar-March 2022.pptx
Data Lakehouse Symposium | Day 1 | Part 1
Data Lakehouse Symposium | Day 1 | Part 2
Data Lakehouse Symposium | Day 2
Data Lakehouse Symposium | Day 4
5 Critical Steps to Clean Your Data Swamp When Migrating Off of Hadoop
Democratizing Data Quality Through a Centralized Platform
Learn to Use Databricks for Data Science
Why APM Is Not the Same As ML Monitoring
The Function, the Context, and the Data—Enabling ML Ops at Stitch Fix
Stage Level Scheduling Improving Big Data and AI Integration
Simplify Data Conversion from Spark to TensorFlow and PyTorch
Scaling your Data Pipelines with Apache Spark on Kubernetes
Scaling and Unifying SciKit Learn and Apache Spark Pipelines
Sawtooth Windows for Feature Aggregations
Redis + Apache Spark = Swiss Army Knife Meets Kitchen Sink
Re-imagine Data Monitoring with whylogs and Spark
Raven: End-to-end Optimization of ML Prediction Queries
Processing Large Datasets for ADAS Applications using Apache Spark
Massive Data Processing in Adobe Using Delta Lake

Recently uploaded (20)

PPTX
Introduction to Firewall Analytics - Interfirewall and Transfirewall.pptx
PDF
Clinical guidelines as a resource for EBP(1).pdf
PPTX
Computer network topology notes for revision
PPTX
Supervised vs unsupervised machine learning algorithms
PPTX
iec ppt-1 pptx icmr ppt on rehabilitation.pptx
PPTX
MODULE 8 - DISASTER risk PREPAREDNESS.pptx
PPT
Quality review (1)_presentation of this 21
PPTX
DISORDERS OF THE LIVER, GALLBLADDER AND PANCREASE (1).pptx
PPTX
advance b rammar.pptxfdgdfgdfsgdfgsdgfdfgdfgsdfgdfgdfg
PPTX
Introduction to Knowledge Engineering Part 1
PDF
Lecture1 pattern recognition............
PDF
TRAFFIC-MANAGEMENT-AND-ACCIDENT-INVESTIGATION-WITH-DRIVING-PDF-FILE.pdf
PPTX
The THESIS FINAL-DEFENSE-PRESENTATION.pptx
PDF
168300704-gasification-ppt.pdfhghhhsjsjhsuxush
PPTX
Business Ppt On Nestle.pptx huunnnhhgfvu
PPT
Miokarditis (Inflamasi pada Otot Jantung)
PDF
“Getting Started with Data Analytics Using R – Concepts, Tools & Case Studies”
PPTX
IBA_Chapter_11_Slides_Final_Accessible.pptx
PPTX
mbdjdhjjodule 5-1 rhfhhfjtjjhafbrhfnfbbfnb
Introduction to Firewall Analytics - Interfirewall and Transfirewall.pptx
Clinical guidelines as a resource for EBP(1).pdf
Computer network topology notes for revision
Supervised vs unsupervised machine learning algorithms
iec ppt-1 pptx icmr ppt on rehabilitation.pptx
MODULE 8 - DISASTER risk PREPAREDNESS.pptx
Quality review (1)_presentation of this 21
DISORDERS OF THE LIVER, GALLBLADDER AND PANCREASE (1).pptx
advance b rammar.pptxfdgdfgdfsgdfgsdgfdfgdfgsdfgdfgdfg
Introduction to Knowledge Engineering Part 1
Lecture1 pattern recognition............
TRAFFIC-MANAGEMENT-AND-ACCIDENT-INVESTIGATION-WITH-DRIVING-PDF-FILE.pdf
The THESIS FINAL-DEFENSE-PRESENTATION.pptx
168300704-gasification-ppt.pdfhghhhsjsjhsuxush
Business Ppt On Nestle.pptx huunnnhhgfvu
Miokarditis (Inflamasi pada Otot Jantung)
“Getting Started with Data Analytics Using R – Concepts, Tools & Case Studies”
IBA_Chapter_11_Slides_Final_Accessible.pptx
mbdjdhjjodule 5-1 rhfhhfjtjjhafbrhfnfbbfnb

Optimizing Apache Spark UDFs

  • 1. Optimizing Spark UDFs Shivangi Srivastava Senior Engineering Manager
  • 2. Presenter Introduction ▪ Shivangi Srivastava ▪ Senior Engineering Leader at Informatica ▪ 10 + years of experience with Distributed computing, database systems ▪ Linkedin - https://www.linkedin.com/in/shivangi-srivastava1
  • 3. Informatica • Leading provider of Data Engineering solutions • Informatica offerings –
  • 4. Agenda ▪ Introduction to UDF ▪ Example and benefits of UDF ▪ Performance considerations ▪ Suggested Alternatives ▪ Performance results ▪ Questions/Feedback
  • 5. Introduction to UDFs ▪ User-Defined Functions (aka UDF) is a feature of Spark SQL to define new Column-based functions that extend the vocabulary of Spark SQL’s DSL for transforming Datasets. ▪ UDFs are key features of most SQL environment and extend the system’s in-built functionality. ▪ Custom functions can be defined and registered as UDFs in Spark SQL with an associated alias that is made available to SQL queries.
  • 6. Typical Example ▪ Define a UDF in scala val plusOne = udf((x: Int) => x + 1) ▪ Register the UDF spark.udf.register("plusOne", plusOne) ▪ Usage spark.sql("SELECT plusOne(5)").show() // +------+ // |UDF(5)| // +------+ // | 6| // +------+
  • 7. Benefits of UDFs ▪ Extends the in-built capabilities of Spark SQL. ▪ Simple and straightforward to implement. ▪ Plug and play architecture. ▪ Define once and use across multiple dataframes. ▪ Backward compatible. Stable API not impacted by version upgrades.
  • 8. Performance concerns with UDFs ▪ UDFs are black-box to Spark optimizations. ▪ UDFs block many spark optimizations like ▪ WholeStageCodegen ▪ Null Optimizations ▪ Predicate Pushdown ▪ More optimizations from Catalyst Optimizer ▪ String Handling within UDFs ▪ UTF-8 to UTF-16 conversion. Spark maintains string in UTF-8 encoding versus Java runtime encodes in UTF-16. ▪ Any String input to UDF requires UTF-8 to UTF-16 conversion. ▪ Conversely, a String output requires a UTF-16 to UTF-8 conversion. age codegen
  • 10. Analyzing physical plan X+1 versus plusOne
  • 11. Analyzing physical plan – Predicate Pushdown X+1 versus plusOne
  • 12. Analyzing physical plan – Predicate Pushdown X+1 versus plusOne
  • 13. Redesign UDF implementation ▪ Implement UDFs as Spark native functions. ▪ Design Goals for reimplementing. ▪ Extend Spark’s capabilities with minimal changes to the existing Spark code. ▪ Ability to upgrade to later Spark versions without significant engineering effort
  • 14. Reimplementing Spark UDFs as Spark native ▪ Create a new project structure like spark.
  • 15. Reimplementing Spark UDFs as Spark native ▪ Extend from Spark’s Expression class ▪ UnaryExpression – Single argument expressions ▪ TernaryExpression – Multi argument expressions ▪ Satisfy expression contract
  • 16. Reimplementing Spark UDFs as Spark native ▪ Examples for existing Spark functions can be found at – ▪ sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/
  • 17. Reimplementing Spark UDFs ▪ Define the function implementation
  • 18. Reimplementing Spark UDFs as Spark native functions ▪ Add new function definition file to package org.apache.spark.sql ▪ Compile and add the jar to spark/jars folder.
  • 19. Reimplementing - Usage ▪ Select as a normal function available within spark library.
  • 20. Reimplementing - SQL ▪ Functions require editing of FunctionsRegistry.scala if sql support is needed. ▪ sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/FunctionRegistry.scala ▪ Register your function ▪ expression[PlusOneNative]("plusonenative“) ▪ Recompile spark code to generate spark-catalyst_*.jar ▪ Edit the pom to add dependency to your previously created jar. ▪ Replace under spark/jars location
  • 21. Reimplementing - Usage ▪ Exercise using spark-sql
  • 22. Analyzing physical plan – Predicate Pushdown plusOneNative
  • 23. More Tips and Tricks ▪ Make conscious effort to avoid temporary object allocation. ▪ Use Scala’s while construct over for. ▪ For causes creation of temporary object creation. ▪ Consider imperative style over functional style. ▪ Consider using thread static variable to allocate temporary buffer ▪ Sometimes UTF-8 to UTF-16 conversion is required, consider lazy conversion based on presence of UTF-16 characters. ▪ Inspect the string for presence of UTF-16 characters
  • 24. Performance Comparison – String function ▪ Performance improvement of about 20% to 200% ▪ Overhead of UTF-8 to UTF-16 conversion avoided. SF1 SF10 SF50 optimization disabled 0:02:57 0:04:13 0:18:29 optimization enabled 0:02:38 0:03:26 0:06:21 0:00:00 0:02:53 0:05:46 0:08:38 0:11:31 0:14:24 0:17:17 0:20:10 Time(hh:mm:ss) Scale Factor String Function optimization disabled optimization enabled
  • 25. Performance Comparison – Date function ▪ Performance improvement of about 20% to 100% ▪ Avoided creating temporary objects ▪ Used imperative style programming ▪ Used while instead of for SF1 SF10 SF50 optimization disabled 0:03:10 0:04:28 0:10:09 optimization enabled 0:02:38 0:02:41 0:05:39 0:00:00 0:01:26 0:02:53 0:04:19 0:05:46 0:07:12 0:08:38 0:10:05 0:11:31 Time(hh:mm:ss) Scale Factor Date Function optimization disabled optimization enabled
  • 26. Performance Comparison – Numeric function ▪ Performance improvement of about 15% to 50% SF1 SF10 SF50 optimization disabled 0:04:15 0:06:07 0:10:41 optimization enabled 0:03:36 0:04:04 0:09:15 0:00:00 0:01:26 0:02:53 0:04:19 0:05:46 0:07:12 0:08:38 0:10:05 0:11:31 Time(hh:mm:ss) Scale Factor Numeric Function optimization disabled optimization enabled
  • 27. Performance comparison - Summary ▪ 200% faster for certain String functions with large datasets (50GB). ▪ 50%-100% faster for date and numeric functions. ▪ Performance difference becomes noticeable with larger datasets. ▪ Conversion and optimization cost goes up. ▪ Garbage collection overhead becomes a significant contributor to the overall execution time.
  • 28. Feedback Your feedback is important to us. Don’t forget to rate and review the sessions.