Optimization in Software: Beyond Functionality to Performance
- Vimala Koduru
- January 12, 2024
Software has transcended its role from a mere tool and has evolved into a cornerstone of business success. As a result, it has become imperative for developers to develop a deeper understanding of business requirements and effectively translate gathered insights not only into software capable of delivering functionality but also non-functional aspects, including performance expectations.
The professional path of an AI developer in a product development team typically centers around addressing key challenges in software optimization and throughput. This often leads to the creation of valuable resources aimed at helping developers manage the complexities of software development in an ever-changing technological landscape. The intent behind this blog is to provide useful and informative content for those in the field.
Optimization: A Practical Guide for Business Growth
Optimization involves finding the most effective solution while working with specific constraints and limited resources. The main aim is to enhance efficiency, performance, and quality, among other aspects, to ultimately cut costs or boost a business’s profitability. Here are some practical, real-world scenarios:
- Optimizing Patient Flow Through Effective Time Management: Imagine a scenario where an oncologist strives to maximize efficiency by attending to as many patients as possible by breaking away from the conventional one-room, sequential consultation method and innovating by using multiple consultation rooms. This strategy ensures patients are ready with their previous prescriptions and vital information and enables the doctor to efficiently transition between rooms.
The result? A reduction in the time patients spend moving in and out, and settling in. Essentially, balances the use of extra space (i.e., additional rooms) against the significant benefit of time efficiency.
- Optimizing Function and Space with Multipurpose Furniture: Multipurpose furniture is becoming increasingly popular in households as it helps to save space. For instance, a sofa that can be easily expanded to become a bed, or vice versa, is a great way to optimize space in the house for other purposes. These types of furniture are designed to cater to most use cases while being expandable for other minor use cases.
Similarly, software programs use suitable data structures to optimize space for most use cases. Every software must make trade-offs between runtime and memory based on constraints and requirements.
Let’s now explore a few techniques that can be used to improve software performance.
Approaches to Computer System Optimization
Typically, optimization refers to improving a computer program or system’s speed and efficiency by identifying and eliminating bottlenecks, improving algorithms and data structures, and reducing resource usage. It is usually categorized into memory optimization and runtime optimization.
- Architecture/Design Level Optimization: The pursuit of software optimization begins with thoroughly examining the high-level design or architecture. It’s vital to devise a design that utilizes available resources efficiently, targeting specific goals while adhering to practical and business constraints.
If a design presents inherent drawbacks, the next step involves assessing alternative designs and methodically refining them to achieve the intended results. This often becomes an iterative process, necessitating ongoing evaluation and enhancements to ensure the optimal solution.
- Source Code Level Optimization:
Some of the basic checks for source code optimization are:
- Identify the program/script goal
- List and prioritize the functionalities
- Check the timings of each functionality
- Identify and optimize time-consuming steps
- Understand and visualize the trends
- Eliminate redundant calculations
- Identify built-in packages or libraries with potentially optimized implementations
The Impact of Code Review on Software Quality and Efficiency
Code review is a crucial step in enhancing the speed and reliability of software programs. It involves a systematic examination where another developer scrutinizes the code to pinpoint and rectify performance bottlenecks and issues. This process, carried out by an experienced code reviewer, identifies common areas that hinder performance. Through their expert feedback, code review not only elevates the quality of the software but also ensures its robustness and efficiency in operation.
The Importance of Coding Standards in Software Excellence
Adhering to coding standards and meticulously organizing code into functions, classes, and modules is imperative for achieving excellence in software development.
By segmenting code into logical units, each dedicated to a distinct task, developers can enhance code reuse, improve readability, and ensure maintainability. This structured approach facilitates easier identification and resolution of performance bottlenecks and elevates the overall quality and efficiency of the development process.
The Role of Reusable Components in Sustainable Software Development
In software development, it’s essential to identify and leverage reusable components. This strategy not only streamlines the development process by reducing code duplication but also contributes to creating software that is more efficient, maintainable, and of higher quality.
Integrating reusable components often results in leaner codebases, leading to improved performance and quicker execution times. This approach is critical in enhancing software programs’ overall effectiveness and sustainability.
Improving Performance by Addressing I/O Operation Challenges
Addressing the inherent slowness of I/O operations is pivotal to enhancing performance. An effective strategy in this regard is the optimization of disk reading operations (e.g., using a faster disk) or fine tuning database queries. By refining these database queries, the time required to retrieve data from a database can be substantially reduced, improving system efficiency. This optimization is vital in streamlining processes and ensuring faster, more reliable outcomes.
Evaluating Python code with code profilers
1. Routine performance testing by the datetime module
2. Performance testing by profilers
Some of the libraries included to perform this are:
- timeit
- line_profiler
- memory_profiler
- cProfile library
- Pyinstrument
- Snakeviz
- Heapy
This will execute 1000 times and report an average execution time
- OS/Hardware level optimization: Sometimes, a change in OS also brings in a lot of optimizations. It is possible that there are OS-level features over which you might have better control for optimizing software. Also, low-level languages like C/C++ offer more control over memory and speed instead of high-level languages. Based on the problem, you can enhance hardware resources such as GPU, TPU (mainly ML/AI/CV), and RAM.
If you are dealing with Windows OS, consider the following before executing:
- Run the Disc Cleanup tool
- Remove Temp Internet Files and Thumbnails
- Check for any remote sync operations, such as One Drive, and pause them
- Unselect all the non-essential startup applications
- If necessary, run fragmentation and CHKDSK
- Optimization with Parallel Processing:
Parallel Processing cuts across various aspects. As such, one can introduce parallelization at the source code, design, or hardware level, depending on the requirement.Parallel processing is usually the preferred choice for handling large datasets and complex operations that don’t require serial execution, time-sensitive tasks with real-time data, or when scaling an application to meet future demands.
- At the design level, one achieves parallel processing by dividing the problem into smaller, simultaneously executable tasks. This division involves identifying independent or loosely coupled tasks or employing strategies like task decomposition and pipelining.
- At the hardware level, various techniques enable parallel processing. These include using multi-core processors or computing clusters.
- At the source code level, one can implement parallel processing through techniques like multi-threading and multi-processing. It is essential to categorize software as CPU-bound or I/O bound and choose the appropriate package for implementation. Additionally, understanding the limitations of the selected packages and programming languages is essential.
Multiprocessing is best used for CPU-heavy tasks. Multithreading is best used for IO (Input/Output) based tasks like querying a database or loading a web page.
For Python specifically, the GIL or Global Interpreter Lock, is a mutex that protects access to Python objects, preventing multiple threads from executing Python bytecodes simultaneously. Although the GIL is a necessary evil in Python, it also acts as a performance bottleneck. This is because only one thread can execute Python bytecodes at a time, even on a multi-core system.
A few ways to mitigate the impact of GIL are by using asynchronous programming, which allows Python programs to run multiple tasks concurrently without being blocked by the GIL, and also by using C extensions, which enables the task to run without being affected by GIL. It is, however, essential to note that the GIL is specific to CPython and does not apply to all Python implementations.
The upcoming Python releases(3.13) will see a significant shift with the introduction of the Per-Interpreter Global Interpreter Lock (GIL). This change is poised to bring about notable transformations in the Python multithreading environment.
Consider the below as an example for multiprocessing using shared memory:
Summary:
Three significant factors predominantly influence the approach and time invested in optimization at a high level : business needs, cost implications, and technical constraints. Business needs involve determining if reducing an application’s runtime aligns with strategic objectives or if it constitutes over–engineering.
Cost considerations revolve around the evolving economics of resources like disk space, which may justify favoring runtime efficiency over storage concerns. Technical constraints include factors such as the choice of programming language, software architecture, and operating system. Moreover, adopting a holistic perspective on optimization is vital. This means examining the entire architecture to identify and prioritize areas where maximum benefits can be achieved with a reasonable balance of effort and cost.