GlobalLogic Java Community Webinar #18 “How to Improve Web Application Performance_”.pdf

GlobalLogicUkraine 145 views 69 slides Jun 18, 2024
Slide 1
Slide 1 of 69
Slide 1
1
Slide 2
2
Slide 3
3
Slide 4
4
Slide 5
5
Slide 6
6
Slide 7
7
Slide 8
8
Slide 9
9
Slide 10
10
Slide 11
11
Slide 12
12
Slide 13
13
Slide 14
14
Slide 15
15
Slide 16
16
Slide 17
17
Slide 18
18
Slide 19
19
Slide 20
20
Slide 21
21
Slide 22
22
Slide 23
23
Slide 24
24
Slide 25
25
Slide 26
26
Slide 27
27
Slide 28
28
Slide 29
29
Slide 30
30
Slide 31
31
Slide 32
32
Slide 33
33
Slide 34
34
Slide 35
35
Slide 36
36
Slide 37
37
Slide 38
38
Slide 39
39
Slide 40
40
Slide 41
41
Slide 42
42
Slide 43
43
Slide 44
44
Slide 45
45
Slide 46
46
Slide 47
47
Slide 48
48
Slide 49
49
Slide 50
50
Slide 51
51
Slide 52
52
Slide 53
53
Slide 54
54
Slide 55
55
Slide 56
56
Slide 57
57
Slide 58
58
Slide 59
59
Slide 60
60
Slide 61
61
Slide 62
62
Slide 63
63
Slide 64
64
Slide 65
65
Slide 66
66
Slide 67
67
Slide 68
68
Slide 69
69

About This Presentation

Під час доповіді відповімо на питання, навіщо потрібно підвищувати продуктивність аплікації і які є найефективніші способи для цього. А також поговоримо про те, що...


Slide Content

1
Confidential
How to improve web-application performance
June 12, 2024

2
Confidential
Content
•What is performance?
•Why do we have to improve it?
•Microservices – vs – Monolithic in terms of performance
•Analysis of the bottlenecks
•Levels of performance improving
•Container level (Load Balancer, CQRS, Circuit Breaker)
•Database level (Indexes, Sharding)
•Code level (Async, Caching, Clean code, Best
practices)
•Links
•QA

3
Confidential

Optimal use of resources such as CPU, memory, and
network bandwidth to handle client requests and process
data, minimizing waste and maximizing output with the
least amount of input.
Speed
Efficiency
What is performance?
Rapid processing and delivery of responses to client
requests, ensuring minimal latency and quick recovery.
Performance
The efficiency and speed at which the application handles client requests, processes data, and
delivers responses, ensuring minimal latency and high throughput.

4
Confidential
What is performance?
Time complexity
Constant Time (O(1)): The execution time does not depend on the size of the input data. Example: accessing an element in
an array by index.

Logarithmic Time (O(log n)): The execution time grows logarithmically with the size of the input data. Example: binary search
in a sorted array.

Linear Time (O(n)): The execution time grows linearly with the size of the input data. Example: traversing through an array to
find a specific element.

Linearithmic Time (O(n log n)): The execution time grows in proportion to the size of the input data multiplied by the
logarithm of the input data size. Example: sorting algorithms like merge sort and heap sort.

Quadratic Time (O(n^2)): The execution time grows quadratically with the size of the input data. Example: nested loops
where each loop iterates over the size of the input data.

5
Confidential
Why do we have to do this?

6
Confidential
Why do we have to do this?
For the client
1.Increases the profit: providing
faster response times that
lead to a smoother and more
enjoyable interaction with the
application.
2.More efficient applications
are generally more reliable,
with fewer crashes and
downtime.
3.Offering a seamless
experience even during peak
usage times.

7
Confidential
Why do we have to do this?
For the client
1.Increases the profit: providing
faster response times that
lead to a smoother and more
enjoyable interaction with the
application.
2.More efficient applications
are generally more reliable,
with fewer crashes and
downtime.
3.Offering a seamless
experience even during peak
usage times.
For ourselves
●Easier Maintenance: optimized
code and architecture make
the application easier to
maintain and extend.
●Reduced Resource
Consumption: allows
developers to work within
more manageable resource
constraints.
●Enhanced Debugging and
Monitoring: making it easier to
identify and fix issues

8
Confidential
Why do we have to do this?
For the client
1.Increases the profit: providing
faster response times that
lead to a smoother and more
enjoyable interaction with the
application.
2.More efficient applications
are generally more reliable,
with fewer crashes and
downtime.
3.Offering a seamless
experience even during peak
usage times.
For ourselves
●Easier Maintenance: optimized
code and architecture make
the application easier to
maintain and extend.
●Reduced Resource
Consumption: allows
developers to work within
more manageable resource
constraints.
●Enhanced Debugging and
Monitoring: making it easier to
identify and fix issues
For the team
●More Effective UI
Development / Testing: UI /
tests can run faster,
allowing for quicker
iterations and it’s easier to
simulate real-world load
conditions and identify
performance bottlenecks.
●Testers can cover more
scenarios and edge cases
in the same amount of
time.

9
Confidential
Why do we have to do this?
GOOD PERFORMANCE

10
Confidential
Why do we have to do this?
GOOD PERFORMANCE
=

11
Confidential
Why do we have to do this?
GOOD PERFORMANCE
=
GOOD LIFE

12
Confidential
Why do we have to do this?
GOOD PERFORMANCE
=
GOOD LIFE
=

13
Confidential
Why do we have to do this?
GOOD PERFORMANCE
=
GOOD LIFE
=
GOOD SLEEP

14
Confidential
Here's a focused comparison of Microservices vs. Monolithic architectures in terms of performance:
Response Time
Potentially higher due to network latency
between services
Generally lower as calls are within the same
process
More efficient, as resources are allocated
per service need
Resource Utilization
Higher, due to inter-service communication
Network latency

Lower, as communication is within the
same process
Microservices –vs– Monolithic in terms of performance
Microservices Monolithic
Less efficient, as overprovisioning may be
needed
Service-specific caching can reduce load
and improve speed
Cache

Centralized caching, but can be simpler to
implement

15
Confidential
Summary:

•Microservices: Offer superior scalability and resource utilization, as well as faster
deployment and fault isolation, but potentially suffer from higher response times and network
latency due to the distributed nature of services.

•Monolithic: Generally provide lower response times and network latency due to in-process
communication, but scaling, resource utilization, deployment, and fault isolation are less
efficient compared to microservices.
Microservices –vs– Monolithic in terms of performance

16
Confidential
Analysis of the bottlenecks
•Using Java code (Prometheus with @Timed annotations
or our own @Timed annotations)
•Using external tools (for example Jprofiler and others)
•Using DB language syntax (for example EXPLAIN
command)

17
Confidential
Analysis of the bottlenecks
Using Java

We can set up @Timed annotations from “io.micrometer” dependency. Spring Boot
Actuator integrates with Micrometer to expose metrics. By default, metrics are available at
/actuator/prometheus.
INFO DemoApplication - Total time of exampleMethod(): 200.13 ms

18
Confidential
Analysis of the bottlenecks
Using Java
Besides @Timed annotation we can use other utility annotations that can be helpful for us to
track down the method that is taking our application’s performance down:

•@Counted - is used to count the number of times a method is invoked
•@Gauge - is used to expose a ‘gauge’ metric, which represents a single numerical value
that can go up or down. For example: queue size or number of active threads.

19
Confidential
Analysis of the bottlenecks
Using Java (Graphana UI)

20
Confidential
Analysis of the bottlenecks
Using external tools: JProfiler
• Features:
•CPU profiling
•Memory profiling
•Thread profiling
•Database profiling
•Extensive IDE integration
• Usage:
•Available as a standalone application and as plugins for various IDEs.
•Requires a license, though a trial version is available.

21
Confidential
Analysis of the bottlenecks
Using external tools: JProfiler

22
Confidential
Analysis of the bottlenecks
Using external tools: JProfiler

23
Confidential
Analysis of the bottlenecks
Using DB language syntax (SQL EXPLAIN)
Using EXPLAIN helps you understand the execution plan of your SQL queries, identify performance
bottlenecks, optimize query performance, and ensure efficient use of database resources.

By regularly analyzing and tuning your queries with EXPLAIN, you can significantly improve the
performance and responsiveness of your database applications.

By the way you can achieve the same results by using explain() in NoSQL solutions.

24
Confidential
Analysis of the bottlenecks
Using DB language syntax (EXPLAIN)

MySQL: EXPLAIN SELECT * FROM employees WHERE department = 'Sales’;

PostgreSQL: EXPLAIN SELECT * FROM employees WHERE department = 'Sales’;

Oracle: EXPLAIN PLAN FOR SELECT * FROM employees WHERE department = 'Sales'; SELECT * FROM
TABLE(DBMS_XPLAN.DISPLAY);

25
Confidential
Analysis of the bottlenecks
Using DB language syntax (EXPLAIN)
Initial Query: SELECT * FROM employees WHERE department = 'Sales';
Running EXPLAIN in MySQL: EXPLAIN SELECT * FROM employees WHERE department = 'Sales’;
Output:





Analysis:
• Table Scan: The type column shows ALL, indicating a full table scan. This can be slow if the table is
large.
• No Index: The possible_keys and key columns are NULL, indicating no index is being used for the
department column.


id select_type table type possible_keys key key_len ref rows extra
1 SIMPLE employees ALL NULL NULLNULL NULL 1000 Using
where

26
Confidential
Analysis of the bottlenecks
Using DB language syntax (EXPLAIN)
Optimization:
•Create an index on the department column to speed up the query:
CREATE INDEX idx_department ON employees(department);

•Re-running EXPLAIN:





Analysis:
• Index Scan: The type column now shows ref, indicating an index scan instead of a full table scan.
• Using Index: The key column shows idx_department, confirming the index is used.


id select_typetable typepossible_keyskey key_len ref rows extra
1 SIMPLE employees ref idx_departmentidx_department 1024 const1000
Using index

27
Confidential
Container level of performance improving
Load Balancer
A load balancer is a device or software that distributes network or application traffic across multiple servers.
The primary goal of a load balancer is to optimize resource use, maximize throughput, minimize response
time, and avoid overload on any single server.
Distributes Traffic Evenly
1.Prevents performance bottlenecks
and maximizes the utilization of
your server resources.
2.Redirects traffic to servers that
have more available capacity, thus
maintaining optimal performance
and reducing response.
Enhances Scalability
1.Makes it easier to scale your
application horizontally by adding
or removing servers based on
demand.
2.In combination with auto-scaling
tools, a load balancer can
automatically add more servers
when the load increases and
remove them when the load
decreases, ensuring cost efficiency
and high performance.
Improves Availability
1.Provides redundancy by routing
traffic to healthy servers if one
or more servers fail. This
minimizes the impact of
hardware or software failures,
enhancing the reliability and
availability of your application.

28
Confidential
Container level of performance improving
Load Balancer
Round Robin
Benefits:
1.Simplicity: Easy to implement and
understand.
2.Fair Distribution: Ensures that all
servers get an equal amount of
traffic over time.
Usage:
1.Best for: Environments where
servers have similar capabilities
and the load is evenly distributed.
2.Example: Web servers behind a
load balancer.
Least Connections
Benefits:
1.Dynamic Load Balancing: Adjusts
to real-time server load.
2.Improved Performance: Helps
prevent overloading a single
server.
Usage:
1.Best for: Applications where
request processing times vary
significantly.
2.Example: Database servers
handling queries of varying
complexity.
IP Hash
Benefits:
1.Session Persistence: Ensures the
same client is routed to the same
server, which is useful for
maintaining session data.
2.Distributes load based on client IP
Usage:
1.Best for: Scenarios requiring
session persistence, such as
online shopping carts.
2.Example: E-commerce platforms
or any application needing session
affinity.

29
Confidential
Container level of performance improving
Load Balancer
Nginx
1.Load Balancer
2.Reverse Proxy (sits between client
devices and web servers)
3.HTTP Cache (storing copies of
HTTP responses in a cache)
Amazon Elastic Load
Balancing (ELB)
1.Load Balancer
2.Integration with AWS services

HAProxy
1.Load Balancer
2.Free
3.Proxy
4.Health Checks

30
Confidential
Container level of performance improving
Load Balancer
Summary

Load Balancer enhances the performance of your application by distributing traffic evenly across multiple
servers, facilitating scalability, and improving reliability and availability through redundancy and health
monitoring.

Use cases

•Your application experiences high traffic volumes or unpredictable traffic spikes.
•You need to ensure your application remains available even if some servers fail.
•Your users are distributed across different geographic regions, and you want to reduce latency (in
conjunction with CDN).

31
Confidential
Container level of performance improving
CQRS
CQRS stands for Command Query Responsibility Segregation. It is a design pattern that separates the
read and write operations of a data store.

Instead of using the same model for querying and updating data, CQRS divides the system into two distinct
parts: command (handles all the write operations) and query (handles all read operations).

32
Confidential
Container level of performance improving
CQRS
Twitter:

Write operations (commands): posting tweets, retweets, and user
interactions.
Read operations (queries): fetching timelines, searching tweets,
and analytics.

Netflix:

Write operations (commands): uploading and processing new
videos, metadata updates, user interactions, recommendation
generation.
Read operations (queries): content discovery, user profiles, content
playback, search and filtering.

33
Confidential
Container level of performance improving
CQRS
Optimized Data Models for Read and Write Operations

Separates the read and write models, allowing each to be optimized independently.

Performance Benefits:
1.Read Model Optimization: The read model can be denormalized, indexed, or cached in ways that are specific to read
operations, resulting in faster query performance and reduced latency.
2.Write Model Optimization: The write model can focus on transactional integrity without the overhead of
read-optimization, leading to more efficient writes.

34
Confidential
Container level of performance improving
CQRS
Independent Scaling of Read and Write Operations

Different applications often experience different loads for read and write operations. For example, an e-commerce application
may have far more reads (viewing product details) than writes (placing orders).

CQRS allows you to scale read and write operations independently. This means you can add more read replicas to handle
increased query load without affecting the write database.

Performance Benefits:
1.Read Scalability: By deploying multiple read replicas or using specialized read databases, you can handle a high volume
of read requests efficiently.
2.Write Scalability: The write model can be scaled separately, ensuring that heavy write loads do not impact read
performance. This can be particularly beneficial in systems with high transaction volumes.

35
Confidential
Container level of performance improving
CQRS
When something update in write database, it
will publish an update event with
using message broker (event bus) systems
and this will consume by the read database
and sync data according to latest changes.

36
Confidential
Container level of performance improving
CQRS
Summary

Implementing CQRS can significantly improve the performance of an application by:
1.Optimizing data models separately for read and write operations, ensuring each is as efficient as possible.
2.Allowing independent scaling of read and write components, ensuring the system can handle varying loads more
effectively.
3.Reducing contention and improving concurrency, leading to higher throughput and more efficient resource utilization.

These improvements result in faster query performance, more efficient transaction processing, and a system that can handle
higher loads and more concurrent users.

Use case

•Your application has a significant difference between read and write operations (e.g., more reads than writes).

37
Confidential
Container level of performance improving
Circuit Breaker
A Circuit Breaker is a design pattern used in software
development to improve the stability and resilience of
distributed systems.

It is similar to the electrical circuit breaker in a house, which
automatically shuts off power to a circuit when it detects a
fault, preventing damage to electrical appliances.

38
Confidential
Container level of performance improving
Circuit Breaker
Netflix Hystrix
1.Configurable thresholds for
latency, failure rate, and
concurrency.
2.Provides metrics and monitoring
capabilities to track circuit status
and health.
3.Integrates with Netflix Ribbon for
client-side load balancing and
service discovery
Resilience4j
1.Offers a fluent and functional API
for configuring resilience strategies.
2.Supports decorators for Circuit
Breaker, Retry, Rate Limiter, and
Bulkhead patterns.
3.Integrates with Java functional
interfaces for composing and
chaining resilience behaviors.
Sentinel
1.Supports adaptive flow control
based on various metrics
including QPS (queries per
second) and concurrency.
2.Provides circuit breaking,
system isolation, and real-time
monitoring capabilities.
3.Integrates with Spring Cloud,
Dubbo, gRPC, and other
frameworks.

39
Confidential
Container level of performance improving
Circuit Breaker
Rapid Response to Failures and Reduced Downtime

•Circuit Breakers detect failures quickly and respond immediately by tripping and providing fallback
responses.
•Instead of waiting indefinitely for a response from an unhealthy service, users receive timely fallback
responses, such as cached data or default messages.
•This reduces downtime and ensures that your application remains operational, even in the face of service
failures.

Performance Benefits:
1.By reducing downtime and providing fast fallback responses, Circuit Breakers enhance the user
experience.
2.Users experience fewer disruptions and delays, leading to higher satisfaction and retention rates.

40
Confidential
Container level of performance improving
Circuit Breaker
Summary

Circuit Breakers play a crucial role in maintaining the stability,
reliability, and performance of distributed systems by
detecting failures, preventing cascading failures, and ensuring
efficient resource utilization.

Use cases

•Your application depends on external services or APIs
(e.g., microservices, databases, third-party APIs).
•A failure in one part of your application leads to a cascade
of failures across other components or services.
•Your application is built using microservices architecture,
where failures in one service can affect other services.

41
Confidential
DB level of performance improving
Indexing
Indexing is a technique used to efficiently retrieve
data from tables based on the values of certain
columns.

An index is a data structure that stores a sorted list
of values along with pointers to the corresponding
rows in the table.

Indexes can significantly improve the performance
of SQL queries by allowing the database
management system (DBMS) to locate and retrieve
the desired rows more quickly.

42
Confidential
DB level of performance improving
Indexing
B-Tree Index: log(n)
Are widely used in relational databases.
They organize data in a hierarchical
structure, allowing for efficient retrieval
based on keys.
1.MySQL
2.PostgreSQL
3.Oracle Database
4.Microsoft SQL Server
Hash Index: O(1)
Hash indexes store keys and
corresponding pointers to data using a
hash function. They provide
constant-time (O(1)) access for exact
match queries
1.MongoDB
2.PostgreSQL
3.Apache Cassandra
Full-Text Index: O(n) to
O(m * log(n))
Full-text indexes are used for
searching text data efficiently. They
enable features like keyword
search, phrase search, and
proximity search.
1.MySQL (via FULLTEXT index).
2.PostgreSQL (via full-text
search).
3.MongoDB (text indexes)

43
Confidential
DB level of performance improving
How Indexing Improves Query Performance
1.Faster Data Retrieval: without indexes, the DBMS would need to scan the entire table sequentially to
find rows that match the query conditions. With indexes, the DBMS can quickly locate the relevant rows
based on the indexed columns, reducing the number of rows that need to be examined.
2.Reduced Disk I/O: indexes store data in a sorted order, which allows the DBMS to perform binary
searches to locate rows efficiently. This reduces the amount of disk I/O required to retrieve data, as the
DBMS can access the required rows directly without scanning unnecessary portions of the table.
3.Support for Sorting and Grouping: indexes can also improve the performance of queries that involve
sorting or grouping by the indexed columns. The DBMS can use the index to retrieve the data in the
desired order or to quickly identify groups of rows with identical values.
4.Faster Joins: indexes can accelerate join operations by allowing the DBMS to quickly locate matching
rows in the joined tables. If both tables have indexes on the join columns, the DBMS can perform index
nested loop joins, which are typically faster than other join algorithms.

44
Confidential
DB level of performance improving
Sharding
Sharding is a database partitioning technique where large datasets are divided into smaller, more
manageable parts called shards, and each shard is stored on a separate database server or shard server.

The goal of sharding is to distribute the workload and data storage across multiple servers, improving
scalability, performance, and availability.

Vertical sharding involves dividing the database vertically, meaning different columns or attributes of a table
are stored on separate shards. Each shard contains a subset of columns from the original table.

Horizontal sharding involves dividing the database horizontally, meaning rows of a table are distributed
across multiple shards based on a shard key or partitioning criteria. Each shard contains a subset of rows
from the original table.

45
Confidential
DB level of performance improving
Vertical –vs- Horizontal Sharding
Vertical Sharding:

1.Data Isolation: Vertical sharding is useful when different sets of columns have different access patterns
or are accessed by different parts of the application. For example, frequently accessed columns can be
stored on separate shards to improve query performance.

2.Scaling Individual Components: Vertical sharding allows you to scale individual components of the
database independently. For instance, if certain columns experience high write throughput, you can
shard those columns separately to distribute the load.

In an e-commerce application, customer information such as names, email addresses, and shipping
addresses may be stored on one shard, while order history and payment details are stored on another
shard.

46
Confidential
DB level of performance improving
Vertical –vs- Horizontal Sharding
Horizontal Sharding:

1.Scalability: Horizontal sharding is useful when you need to scale out your database to handle
increasing data volumes or transaction loads. By distributing data across multiple shards, you can
achieve linear scalability.

2.Load Balancing: Horizontal sharding helps distribute the workload evenly across multiple servers,
preventing any single server from becoming a bottleneck. It is suitable for applications with unpredictable
or fluctuating workloads.

In a social media platform, user data could be horizontally sharded based on user IDs. Each shard may
contain user profiles and related data for a range of user IDs (e.g., users with IDs from 1 to 1000 on one
shard, users with IDs from 1001 to 2000 on another shard, and so on).

47
Confidential
DB level of performance improving
How Sharding Improves Performance
1.Horizontal Scalability: Sharding enables horizontal scalability by distributing data across multiple
servers. As the dataset grows, new shards can be added to accommodate the increased load, allowing
the system to scale out by adding more servers rather than scaling up by upgrading hardware.
With horizontal scalability, the overall capacity and performance of the system can be increased linearly
by adding more shard servers.
2.Reduced Query Response Time: By distributing the data across multiple servers, sharding reduces the
amount of data that needs to be processed for each query. Queries can be targeted to specific shards
based on the data being queried, allowing for faster query response times compared to querying a single
monolithic database.

48
Confidential
DB level of performance improving
Example

49
Confidential
Code level of performance improving
Async
Asynchronous execution refers to a programming model where tasks are executed independently of the
main program flow, allowing other tasks to proceed concurrently.
Benefits for performance:

1.Minimized Idle Time: Asynchronous operations execute concurrently, reducing idle time and maximizing
resource utilization.
2.Enhanced Responsiveness: Non-blocking calls in asynchronous operations ensure the application
remains interactive and responsive to user input.
3.Efficient I/O Handling: Asynchronous programming efficiently manages I/O-bound operations, such as
network requests or file I/O, leading to faster execution times.
4.Concurrency Management: Event-driven or reactive programming models offer robust concurrency
management, enhancing performance in complex, concurrent applications.

50
Confidential
Code level of performance improving
Async
CompletableFuture

•Library: Standard Java API (no
additional library required).

•Description: CompletableFuture is a
class introduced in Java 8 that
represents a future result of an
asynchronous computation

•Example: Performing asynchronous
HTTP requests
Java NIO (New I/O)
•Library: Standard Java API (no
additional library required).
•Description: Java NIO (New I/O) is
a set of APIs introduced in Java 1.4
for non-blocking I/O operations.
•Example: Creating a non-blocking
TCP server
Message Brokers
•Library: External solutions like
RabbitMQ or ActiveMQ.
•Description: By integrating with
messaging brokers like
RabbitMQ or ActiveMQ, you can
implement asynchronous
communication patterns such as
publish-subscribe, message
queues, and event-driven
architectures.
•Example: Handling order
delivery or social media
activities

51
Confidential
Code level of performance improving
Caching
1.Using plain Map:

52
Confidential
Code level of performance improving
Caching
2. Using EhCache:

53
Confidential
Code level of performance improving
Caching
2. Using EhCache:

54
Confidential
Code level of performance improving
Caching
2. Using EhCache:

55
Confidential
Code level of performance improving
Caching
3. Using Redis:
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>4.0.1</version>
</dependency>

56
Confidential
Code level of performance improving
Caching
3. Using Redis:

57
Confidential
Code level of performance improving
Caching
3. Using Redis:

58
Confidential
Code level of performance improving
Caching
3. Using Redis:

59
Confidential
Code level of performance improving
Clean code
How not to do

60
Confidential
Code level of performance improving
Clean code
How not to do
How should we do

61
Confidential
Code level of performance improving
Clean code
How not to do

62
Confidential
Code level of performance improving
Clean code
How not to do
How should we do

63
Confidential
Code level of performance improving
Clean code
How not to do

64
Confidential
Code level of performance improving
Clean code
How should we do

65
Confidential
Code level of performance improving
Clean code
How not to do

66
Confidential
Code level of performance improving
Clean code
How should we do

67
Confidential
Links
1.Time Complexity cheat sheet for Java
2.Nice articles about Load Balancer, CQRS and Circuit Breaker.
3.Indexing, Partitioning and Sharding
4.Caching in Java

68
Confidential
How to improve web-application performance?
QA

69
Confidential
How to improve web-application performance?
Thank You