SlideShare une entreprise Scribd logo
1  sur  36
Ruby/Rails
Performance and Profiling
And the results are in...
● Benchmark Basics
● Memory/GC Profiling
● CPU Profiling
● Web App Performance
● Ruby Performance Patterns
● Rails Performance Patterns
Basics of Benchmarking
● Benchmark module
● benchmark-ips gem
● Beware GC!
Benchmark module
The Benchmark module provides methods
to measure and report the time used to
execute Ruby code.
Benchmark.realtime - Returns the elapsed real time used to execute the given
block.
Benchmark.bmbm - Attempts to reduce noise in benchmarks by running benchmarks
twice: once to warm up the runtime environment and once for real.
require “benchmark”
Benchmark.realtime && Benchmark.bmbm
benchmark-ips gem
● IPS == Iterations Per Second
● Similar to Benchmark.bmbm, but executes
the given block as many times as possible
per second
● Also includes warm-up period
● More configurable
● Includes margin of errorgem “benchmark-ips”
require “benchmark/ips”
Benchmark.ips
Beware GC!
A Thorough Benchmark...
Memory and GC Profiling
● GC module
● memory_profiler gem
GC Module
GC#stat - Returns a Hash of information
about the GC.
GC::Profiler - Provides access to
information on GC runs including time, length
and object space size.
GC.stat
GC::Profiler
memory_profiler gem
● Memory profiling routines for Ruby Head
gem “memory_profiler”
require “memory_profiler”
CPU Profiling
● ruby-prof gem
ruby-prof gem
A fast code profiler for Ruby
● Fast - C extension so, many times faster than the
standard Ruby profiler.
● Modes - Can measure a number of different parameters,
including call times, memory usage and object
allocations.
● Reports - can generate many types of reports.
gem “ruby-prof”
require “ruby-prof”
ruby-prof gem
Modes:
● wall time (RubyProf::WALL_TIME)
● process time (RubyProf::PROCESS_TIME)
● cpu time (RubyProf::CPU_TIME)*
● object allocations (RubyProf::ALLOCATIONS)
● memory usage (RubyProf::MEMORY) **
● garbage collection time (RubyProf::GC_TIME) **
● garbage collections runs (RubyProf::GC_RUNS) **
* Linux only
** Requires patched Ruby
gem “ruby-prof”
require “ruby-prof”
A simple example...
RubyProf Reports: Flat Report
Shows the total amount of time spent in each method
RubyProf Reports: Flat Report
Shows the total amount of time spent in each method
%self - The percentage of time spent in this method, derived from self_time/total_time
total - The time spent in this method and its children.
self - The time spent in this method.
wait - The time the thread spent waiting on other threads.
children - The time spent in this method's children.
calls - The number of times this method was called.
self/call - The average time spent per call in this method.
total/call - The average time spent per call in this method and its children.
name - The name of the method.
RubyProf Reports: Graph Report
Shows the total amount of time spent in each method
%total - The percentage of time spent in this method and its children
%self - The percentage of time spent in this method
total - The time spent in this method and its children.
self - The time spent in this method.
wait - The time the thread spent waiting on other threads.
child - The time spent in this method's children.
calls - The number of times this method was called.
name - The name of the method.
RubyProf Reports: Call Stack Report
Creates an HTML representation of the Ruby call stack
RubyProf Reports: Visualizing with KCachegrind
RubyProf Reports: Visualizing with KCachegrind
3 Rules of Rails Profiling
1.Disable GC
2.Always profile in production
mode
3.Profile at least twice, ignore
first result
Web App Performance
● New Relic
● rack-mini-profiler gem
New Relic
rack-mini-profiler gem
gem “rack-mini-profiler”
require “rack-mini-profiler”
Middleware that displays speed badge and flame-graph for every HTML page.
● Can be useful in development
● Useful for examining a particular page
● Tends to be less useful in environments that use New
Relic.
rack-mini-profiler gem
Ruby Performance Patterns
● Modify objects in place
● Avoid iterators that allocate additional
objects
● Beware String allocations
● Write less Ruby
Modify objects in place
Beware of iterators that make extra allocations
Beware of iterators that make extra allocations
Rails Performance Patterns
● ActiveRecord
o Take only what you need using #select
and #pluck
o Eager loading using #includes
o Let the database do the work
● ActionView
o Avoid rendering partials in a loop
● Use caching where it makes sense
Other tools
stackprof - A fast sampling profiler for ruby
code, with cpu, wallclock and object allocation
samplers.
allocation_tracer - Similar to memory_profiler
but focused on "age" of objects. Written by
Koichi Sasada.
Additional Resources
● Module: Benchmark - RubyDoc.org: http://ruby-doc.org/stdlib-
2.0.0/libdoc/benchmark/rdoc/Benchmark.html
● Module: GC - RubyDoc.org: http://ruby-doc.org/core-2.0.0/GC.html
● Performance Testing Rails Applications - Rails Guide:
http://guides.rubyonrails.org/v3.2.13/performance_testing.html
● Rails Performance - What You Need To Know: https://www.airpair.com/ruby-
on-rails/performance
● Ruby Performance Optimization: Why Ruby Is Slow, and How to Fix It by
Alexander Dymo: https://pragprog.com/book/adrpo/ruby-performance-
optimization
● GORUCO 2015 - How to Performance by Eileen Uchitelle:
https://www.youtube.com/watch?v=oT74HLvDo_A

Contenu connexe

Tendances

How to test code with mruby
How to test code with mrubyHow to test code with mruby
How to test code with mrubyHiroshi SHIBATA
 
The details of CI/CD environment for Ruby
The details of CI/CD environment for RubyThe details of CI/CD environment for Ruby
The details of CI/CD environment for RubyHiroshi SHIBATA
 
Leave end-to-end testing to Capybara
Leave end-to-end testing to CapybaraLeave end-to-end testing to Capybara
Leave end-to-end testing to CapybaraHiroshi SHIBATA
 
Large-scaled Deploy Over 100 Servers in 3 Minutes
Large-scaled Deploy Over 100 Servers in 3 MinutesLarge-scaled Deploy Over 100 Servers in 3 Minutes
Large-scaled Deploy Over 100 Servers in 3 MinutesHiroshi SHIBATA
 
Middleware as Code with mruby
Middleware as Code with mrubyMiddleware as Code with mruby
Middleware as Code with mrubyHiroshi SHIBATA
 
The OMR GC talk - Ruby Kaigi 2015
The OMR GC talk - Ruby Kaigi 2015The OMR GC talk - Ruby Kaigi 2015
The OMR GC talk - Ruby Kaigi 2015craig lehmann
 
Find bottleneck and tuning in Java Application
Find bottleneck and tuning in Java ApplicationFind bottleneck and tuning in Java Application
Find bottleneck and tuning in Java Applicationguest1f2740
 
Gate of Agile Web Development
Gate of Agile Web DevelopmentGate of Agile Web Development
Gate of Agile Web DevelopmentKoichi ITO
 
Python Load Testing - Pygotham 2012
Python Load Testing - Pygotham 2012Python Load Testing - Pygotham 2012
Python Load Testing - Pygotham 2012Dan Kuebrich
 
Tale of Kafka Consumer for Spark Streaming
Tale of Kafka Consumer for Spark StreamingTale of Kafka Consumer for Spark Streaming
Tale of Kafka Consumer for Spark StreamingSigmoid
 
How to Begin to Develop Ruby Core
How to Begin to Develop Ruby CoreHow to Begin to Develop Ruby Core
How to Begin to Develop Ruby CoreHiroshi SHIBATA
 
Mасштабирование микросервисов на Go, Matt Heath (Hailo)
Mасштабирование микросервисов на Go, Matt Heath (Hailo)Mасштабирование микросервисов на Go, Matt Heath (Hailo)
Mасштабирование микросервисов на Go, Matt Heath (Hailo)Ontico
 
Javascript TDD with Jasmine, Karma, and Gulp
Javascript TDD with Jasmine, Karma, and GulpJavascript TDD with Jasmine, Karma, and Gulp
Javascript TDD with Jasmine, Karma, and GulpAll Things Open
 
30 Minutes To CPAN
30 Minutes To CPAN30 Minutes To CPAN
30 Minutes To CPANdaoswald
 
DSLing your System For Scalability Testing Using Gatling - Dublin Scala User ...
DSLing your System For Scalability Testing Using Gatling - Dublin Scala User ...DSLing your System For Scalability Testing Using Gatling - Dublin Scala User ...
DSLing your System For Scalability Testing Using Gatling - Dublin Scala User ...Aman Kohli
 
Toolbox of a Ruby Team
Toolbox of a Ruby TeamToolbox of a Ruby Team
Toolbox of a Ruby TeamArto Artnik
 
Middleware as Code with mruby
Middleware as Code with mrubyMiddleware as Code with mruby
Middleware as Code with mrubyHiroshi SHIBATA
 

Tendances (20)

How to test code with mruby
How to test code with mrubyHow to test code with mruby
How to test code with mruby
 
The details of CI/CD environment for Ruby
The details of CI/CD environment for RubyThe details of CI/CD environment for Ruby
The details of CI/CD environment for Ruby
 
Leave end-to-end testing to Capybara
Leave end-to-end testing to CapybaraLeave end-to-end testing to Capybara
Leave end-to-end testing to Capybara
 
Large-scaled Deploy Over 100 Servers in 3 Minutes
Large-scaled Deploy Over 100 Servers in 3 MinutesLarge-scaled Deploy Over 100 Servers in 3 Minutes
Large-scaled Deploy Over 100 Servers in 3 Minutes
 
Middleware as Code with mruby
Middleware as Code with mrubyMiddleware as Code with mruby
Middleware as Code with mruby
 
Run Node Run
Run Node RunRun Node Run
Run Node Run
 
The OMR GC talk - Ruby Kaigi 2015
The OMR GC talk - Ruby Kaigi 2015The OMR GC talk - Ruby Kaigi 2015
The OMR GC talk - Ruby Kaigi 2015
 
Find bottleneck and tuning in Java Application
Find bottleneck and tuning in Java ApplicationFind bottleneck and tuning in Java Application
Find bottleneck and tuning in Java Application
 
Tuning Solr for Logs
Tuning Solr for LogsTuning Solr for Logs
Tuning Solr for Logs
 
Gate of Agile Web Development
Gate of Agile Web DevelopmentGate of Agile Web Development
Gate of Agile Web Development
 
Python Load Testing - Pygotham 2012
Python Load Testing - Pygotham 2012Python Load Testing - Pygotham 2012
Python Load Testing - Pygotham 2012
 
Tale of Kafka Consumer for Spark Streaming
Tale of Kafka Consumer for Spark StreamingTale of Kafka Consumer for Spark Streaming
Tale of Kafka Consumer for Spark Streaming
 
How to Begin to Develop Ruby Core
How to Begin to Develop Ruby CoreHow to Begin to Develop Ruby Core
How to Begin to Develop Ruby Core
 
Mасштабирование микросервисов на Go, Matt Heath (Hailo)
Mасштабирование микросервисов на Go, Matt Heath (Hailo)Mасштабирование микросервисов на Go, Matt Heath (Hailo)
Mасштабирование микросервисов на Go, Matt Heath (Hailo)
 
Usenix lisa 2011
Usenix lisa 2011Usenix lisa 2011
Usenix lisa 2011
 
Javascript TDD with Jasmine, Karma, and Gulp
Javascript TDD with Jasmine, Karma, and GulpJavascript TDD with Jasmine, Karma, and Gulp
Javascript TDD with Jasmine, Karma, and Gulp
 
30 Minutes To CPAN
30 Minutes To CPAN30 Minutes To CPAN
30 Minutes To CPAN
 
DSLing your System For Scalability Testing Using Gatling - Dublin Scala User ...
DSLing your System For Scalability Testing Using Gatling - Dublin Scala User ...DSLing your System For Scalability Testing Using Gatling - Dublin Scala User ...
DSLing your System For Scalability Testing Using Gatling - Dublin Scala User ...
 
Toolbox of a Ruby Team
Toolbox of a Ruby TeamToolbox of a Ruby Team
Toolbox of a Ruby Team
 
Middleware as Code with mruby
Middleware as Code with mrubyMiddleware as Code with mruby
Middleware as Code with mruby
 

Similaire à Ruby/rails performance and profiling

Debugging Rails 3 Applications
Debugging Rails 3 ApplicationsDebugging Rails 3 Applications
Debugging Rails 3 ApplicationsNathan Broadbent
 
Ruby confhighlights
Ruby confhighlightsRuby confhighlights
Ruby confhighlightsClaire Tran
 
DevoxxUK: Optimizating Application Performance on Kubernetes
DevoxxUK: Optimizating Application Performance on KubernetesDevoxxUK: Optimizating Application Performance on Kubernetes
DevoxxUK: Optimizating Application Performance on KubernetesDinakar Guniguntala
 
Ruby performance - The low hanging fruit
Ruby performance - The low hanging fruitRuby performance - The low hanging fruit
Ruby performance - The low hanging fruitBruce Werdschinski
 
Ruby Performance - The Last Mile - RubyConf India 2016
Ruby Performance - The Last Mile - RubyConf India 2016Ruby Performance - The Last Mile - RubyConf India 2016
Ruby Performance - The Last Mile - RubyConf India 2016Charles Nutter
 
Kopf @ Python Pizza Berlin, 2019-08-23
Kopf @ Python Pizza Berlin, 2019-08-23Kopf @ Python Pizza Berlin, 2019-08-23
Kopf @ Python Pizza Berlin, 2019-08-23Sergey Vasilyev
 
Ruby C extensions at the Ruby drink-up of Sophia, April 2012
Ruby C extensions at the Ruby drink-up of Sophia, April 2012Ruby C extensions at the Ruby drink-up of Sophia, April 2012
Ruby C extensions at the Ruby drink-up of Sophia, April 2012rivierarb
 
Performance profiling and testing of symfony application 2
Performance profiling and testing of symfony application 2Performance profiling and testing of symfony application 2
Performance profiling and testing of symfony application 2Andrew Yatsenko
 
Ninad cucumber rails
Ninad cucumber railsNinad cucumber rails
Ninad cucumber railsninad23p
 
Fyber - airflow best practices in production
Fyber - airflow best practices in productionFyber - airflow best practices in production
Fyber - airflow best practices in productionItai Yaffe
 
Behavioural Testing Ruby/Rails Apps @ Scale - Rspec & Cucumber
       Behavioural Testing Ruby/Rails Apps @ Scale - Rspec & Cucumber       Behavioural Testing Ruby/Rails Apps @ Scale - Rspec & Cucumber
Behavioural Testing Ruby/Rails Apps @ Scale - Rspec & CucumberUdaya Kiran
 
JRuby, Ruby, Rails and You on the Cloud
JRuby, Ruby, Rails and You on the CloudJRuby, Ruby, Rails and You on the Cloud
JRuby, Ruby, Rails and You on the CloudHiro Asari
 
How to develop the Standard Libraries of Ruby?
How to develop the Standard Libraries of Ruby?How to develop the Standard Libraries of Ruby?
How to develop the Standard Libraries of Ruby?Hiroshi SHIBATA
 
20180503 kube con eu kubernetes metrics deep dive
20180503 kube con eu   kubernetes metrics deep dive20180503 kube con eu   kubernetes metrics deep dive
20180503 kube con eu kubernetes metrics deep diveBob Cotton
 
Jruby synergy-of-ruby-and-java
Jruby synergy-of-ruby-and-javaJruby synergy-of-ruby-and-java
Jruby synergy-of-ruby-and-javaKeith Bennett
 
JS Fest 2018. Алексей Волков. Полезные инструменты для JS разработки
JS Fest 2018. Алексей Волков. Полезные инструменты для JS разработкиJS Fest 2018. Алексей Волков. Полезные инструменты для JS разработки
JS Fest 2018. Алексей Волков. Полезные инструменты для JS разработкиJSFestUA
 
TorqueBox - Ruby Hoedown 2011
TorqueBox - Ruby Hoedown 2011TorqueBox - Ruby Hoedown 2011
TorqueBox - Ruby Hoedown 2011Lance Ball
 

Similaire à Ruby/rails performance and profiling (20)

Debugging Rails 3 Applications
Debugging Rails 3 ApplicationsDebugging Rails 3 Applications
Debugging Rails 3 Applications
 
Ruby confhighlights
Ruby confhighlightsRuby confhighlights
Ruby confhighlights
 
DevoxxUK: Optimizating Application Performance on Kubernetes
DevoxxUK: Optimizating Application Performance on KubernetesDevoxxUK: Optimizating Application Performance on Kubernetes
DevoxxUK: Optimizating Application Performance on Kubernetes
 
Concurrency in ruby
Concurrency in rubyConcurrency in ruby
Concurrency in ruby
 
Ruby performance - The low hanging fruit
Ruby performance - The low hanging fruitRuby performance - The low hanging fruit
Ruby performance - The low hanging fruit
 
Ruby Performance - The Last Mile - RubyConf India 2016
Ruby Performance - The Last Mile - RubyConf India 2016Ruby Performance - The Last Mile - RubyConf India 2016
Ruby Performance - The Last Mile - RubyConf India 2016
 
RubyGems 3 & 4
RubyGems 3 & 4RubyGems 3 & 4
RubyGems 3 & 4
 
Kopf @ Python Pizza Berlin, 2019-08-23
Kopf @ Python Pizza Berlin, 2019-08-23Kopf @ Python Pizza Berlin, 2019-08-23
Kopf @ Python Pizza Berlin, 2019-08-23
 
Ruby C extensions at the Ruby drink-up of Sophia, April 2012
Ruby C extensions at the Ruby drink-up of Sophia, April 2012Ruby C extensions at the Ruby drink-up of Sophia, April 2012
Ruby C extensions at the Ruby drink-up of Sophia, April 2012
 
RubyGems 3 & 4
RubyGems 3 & 4RubyGems 3 & 4
RubyGems 3 & 4
 
Performance profiling and testing of symfony application 2
Performance profiling and testing of symfony application 2Performance profiling and testing of symfony application 2
Performance profiling and testing of symfony application 2
 
Ninad cucumber rails
Ninad cucumber railsNinad cucumber rails
Ninad cucumber rails
 
Fyber - airflow best practices in production
Fyber - airflow best practices in productionFyber - airflow best practices in production
Fyber - airflow best practices in production
 
Behavioural Testing Ruby/Rails Apps @ Scale - Rspec & Cucumber
       Behavioural Testing Ruby/Rails Apps @ Scale - Rspec & Cucumber       Behavioural Testing Ruby/Rails Apps @ Scale - Rspec & Cucumber
Behavioural Testing Ruby/Rails Apps @ Scale - Rspec & Cucumber
 
JRuby, Ruby, Rails and You on the Cloud
JRuby, Ruby, Rails and You on the CloudJRuby, Ruby, Rails and You on the Cloud
JRuby, Ruby, Rails and You on the Cloud
 
How to develop the Standard Libraries of Ruby?
How to develop the Standard Libraries of Ruby?How to develop the Standard Libraries of Ruby?
How to develop the Standard Libraries of Ruby?
 
20180503 kube con eu kubernetes metrics deep dive
20180503 kube con eu   kubernetes metrics deep dive20180503 kube con eu   kubernetes metrics deep dive
20180503 kube con eu kubernetes metrics deep dive
 
Jruby synergy-of-ruby-and-java
Jruby synergy-of-ruby-and-javaJruby synergy-of-ruby-and-java
Jruby synergy-of-ruby-and-java
 
JS Fest 2018. Алексей Волков. Полезные инструменты для JS разработки
JS Fest 2018. Алексей Волков. Полезные инструменты для JS разработкиJS Fest 2018. Алексей Волков. Полезные инструменты для JS разработки
JS Fest 2018. Алексей Волков. Полезные инструменты для JS разработки
 
TorqueBox - Ruby Hoedown 2011
TorqueBox - Ruby Hoedown 2011TorqueBox - Ruby Hoedown 2011
TorqueBox - Ruby Hoedown 2011
 

Ruby/rails performance and profiling

  • 2. And the results are in... ● Benchmark Basics ● Memory/GC Profiling ● CPU Profiling ● Web App Performance ● Ruby Performance Patterns ● Rails Performance Patterns
  • 3. Basics of Benchmarking ● Benchmark module ● benchmark-ips gem ● Beware GC!
  • 4. Benchmark module The Benchmark module provides methods to measure and report the time used to execute Ruby code. Benchmark.realtime - Returns the elapsed real time used to execute the given block. Benchmark.bmbm - Attempts to reduce noise in benchmarks by running benchmarks twice: once to warm up the runtime environment and once for real. require “benchmark”
  • 6. benchmark-ips gem ● IPS == Iterations Per Second ● Similar to Benchmark.bmbm, but executes the given block as many times as possible per second ● Also includes warm-up period ● More configurable ● Includes margin of errorgem “benchmark-ips” require “benchmark/ips”
  • 10. Memory and GC Profiling ● GC module ● memory_profiler gem
  • 11. GC Module GC#stat - Returns a Hash of information about the GC. GC::Profiler - Provides access to information on GC runs including time, length and object space size.
  • 14. memory_profiler gem ● Memory profiling routines for Ruby Head gem “memory_profiler” require “memory_profiler”
  • 16. ruby-prof gem A fast code profiler for Ruby ● Fast - C extension so, many times faster than the standard Ruby profiler. ● Modes - Can measure a number of different parameters, including call times, memory usage and object allocations. ● Reports - can generate many types of reports. gem “ruby-prof” require “ruby-prof”
  • 17. ruby-prof gem Modes: ● wall time (RubyProf::WALL_TIME) ● process time (RubyProf::PROCESS_TIME) ● cpu time (RubyProf::CPU_TIME)* ● object allocations (RubyProf::ALLOCATIONS) ● memory usage (RubyProf::MEMORY) ** ● garbage collection time (RubyProf::GC_TIME) ** ● garbage collections runs (RubyProf::GC_RUNS) ** * Linux only ** Requires patched Ruby gem “ruby-prof” require “ruby-prof”
  • 19. RubyProf Reports: Flat Report Shows the total amount of time spent in each method
  • 20. RubyProf Reports: Flat Report Shows the total amount of time spent in each method %self - The percentage of time spent in this method, derived from self_time/total_time total - The time spent in this method and its children. self - The time spent in this method. wait - The time the thread spent waiting on other threads. children - The time spent in this method's children. calls - The number of times this method was called. self/call - The average time spent per call in this method. total/call - The average time spent per call in this method and its children. name - The name of the method.
  • 21. RubyProf Reports: Graph Report Shows the total amount of time spent in each method %total - The percentage of time spent in this method and its children %self - The percentage of time spent in this method total - The time spent in this method and its children. self - The time spent in this method. wait - The time the thread spent waiting on other threads. child - The time spent in this method's children. calls - The number of times this method was called. name - The name of the method.
  • 22. RubyProf Reports: Call Stack Report Creates an HTML representation of the Ruby call stack
  • 23. RubyProf Reports: Visualizing with KCachegrind
  • 24. RubyProf Reports: Visualizing with KCachegrind
  • 25. 3 Rules of Rails Profiling 1.Disable GC 2.Always profile in production mode 3.Profile at least twice, ignore first result
  • 26. Web App Performance ● New Relic ● rack-mini-profiler gem
  • 28. rack-mini-profiler gem gem “rack-mini-profiler” require “rack-mini-profiler” Middleware that displays speed badge and flame-graph for every HTML page. ● Can be useful in development ● Useful for examining a particular page ● Tends to be less useful in environments that use New Relic.
  • 30. Ruby Performance Patterns ● Modify objects in place ● Avoid iterators that allocate additional objects ● Beware String allocations ● Write less Ruby
  • 32. Beware of iterators that make extra allocations
  • 33. Beware of iterators that make extra allocations
  • 34. Rails Performance Patterns ● ActiveRecord o Take only what you need using #select and #pluck o Eager loading using #includes o Let the database do the work ● ActionView o Avoid rendering partials in a loop ● Use caching where it makes sense
  • 35. Other tools stackprof - A fast sampling profiler for ruby code, with cpu, wallclock and object allocation samplers. allocation_tracer - Similar to memory_profiler but focused on "age" of objects. Written by Koichi Sasada.
  • 36. Additional Resources ● Module: Benchmark - RubyDoc.org: http://ruby-doc.org/stdlib- 2.0.0/libdoc/benchmark/rdoc/Benchmark.html ● Module: GC - RubyDoc.org: http://ruby-doc.org/core-2.0.0/GC.html ● Performance Testing Rails Applications - Rails Guide: http://guides.rubyonrails.org/v3.2.13/performance_testing.html ● Rails Performance - What You Need To Know: https://www.airpair.com/ruby- on-rails/performance ● Ruby Performance Optimization: Why Ruby Is Slow, and How to Fix It by Alexander Dymo: https://pragprog.com/book/adrpo/ruby-performance- optimization ● GORUCO 2015 - How to Performance by Eileen Uchitelle: https://www.youtube.com/watch?v=oT74HLvDo_A