Wednesday, March 13, 2024

Heavy Memory Usage of the Regression Test in XCTest

While recently wrestling with a regression test for my Swift project using the XCTest framework, I ventured into the tumultuous world of a heavily multithreaded application. Ensuring the absence of timing issues was like defusing a bomb – one wrong wire, and boom! So, what's a developer to do? Run the code tens of thousands of times, of course (or even more for the marathon runners of applications), and keep your fingers crossed for any anomalies.

My trusty XCTest framework was the stage, and my test code, which cheerfully returned results asynchronously, demanded I master the classic XCTest dance of expectation(...) and waitForExpectations(...) moves. All seemed well as the test passed with flying colors for a few thousand iterations. However, as I ambitiously cranked up the numbers, strange gremlins began to pop up. The memory usage skyrocketed, adding a whopping 90 MB per 10,000 iterations – definitely not a feature I had intended to implement!

I dove into the depths of Instruments, yet no memory leaks waved back at me. Puzzling! Yet, I noticed waitForExpectations was having a bit too much fun allocating objects like NSString left and right. My online detective work on Google and StackOverflow turned up zilch – it seemed I was charting uncharted waters.

Refusing to be defeated, me and my digital buddy ChatGPT kept on going into the uncharted territory with me as novis to Swift while ChatGPT blind beyond 20 ft. I scrutinized the allocation patterns revealed by Instruments with a detective's eye. This careful observation led to a pivotal "Eureka!" moment. It dawned on me to employ an autoreleasepool within the scope of each iteration. This strategic move, akin to a well-crafted chess play, was not just a stroke of luck but a calculated decision based on the insights gleaned. And, like a charm, this adept adjustment worked wonders, effectively dispelling the memory bloat gremlins back into the abyss from whence they came.


Here is a sample test code anyone can run in our XCTest project, to reproduce the issue and verify the solution.

  1.     func testAsyncOperationInLoop() {
  2.         let iterationCount = 50000  // Number of iterations in the loop
  3.         
  4.         for i in 1...iterationCount {
  5.             autoreleasepool {
  6.                 
  7.                 // Create a new expectation for each iteration of the loop
  8.                 let expectation = self.expectation(description: "Async operation \(i)")
  9.                 
  10.                 if i > 0 && i % (10000) == 0 {
  11.                     print("breaking for a breath")
  12.                 }
  13.                 
  14.                 // Simulate an asynchronous operation
  15.                 DispatchQueue.global().asyncAfter(deadline: .now() + 1.0/100000) {
  16.                     expectation.fulfill()  // Fulfill the expectation once the operation is completed
  17.                 }
  18.                 
  19.                 // Wait for the expectation to be fulfilled, with a timeout
  20.                 waitForExpectations(timeout: 2) { error in
  21.                     if let error = error {
  22.                         XCTFail("waitForExpectations errored: \(error)")
  23.                     }
  24.                 }
  25.             }
  26.         }
  27.         
  28.         print("All iterations completed")
  29.     }

Wednesday, February 07, 2024

Decoding the Mystery: How Food Label Decoder Simplifies Your Grocery Shopping

This blog is about a custom ChatGPT model that you can use if you have ChatGPT 4 account. Follow this link to use the custom model: https://chat.openai.com/g/g-c2AWb78Mr-food-label-decoder 


In today’s fast-paced world, our dependence on packaged foods has become more a necessity than a choice. Amidst the rush of daily life, who has the time to decode the complex list of ingredients on the back of every package? Yet, understanding these labels is crucial, as it's about more than just counting calories—it's about knowing what we're truly feeding ourselves and our loved ones.

The Hidden Truth Behind Packaged Foods

Packaged food items are a marvel of modern convenience, but this convenience often comes with a hidden cost. To stay competitive, ensure a long shelf life, and appeal to consumer tastes, companies often resort to using a range of additives, preservatives, and sugars. These ingredients can be cleverly disguised under scientific names, making them nearly impossible for the average shopper to recognize.

Moreover, with the ever-evolving "health trends," many products are marketed as "healthy" options, leveraging buzzwords like "natural," "organic," or "low-fat." However, a closer inspection of their ingredient lists often reveals a different story. How many times have you picked up a product, enticed by its health claims, only to find it packed with unpronounceable chemicals or excessive sugars?

Enter the Food Label Decoder

This is where the Food Label Decoder comes into play—a tool designed to bridge the gap between confusing labels and informed dietary choices. Powered by ChatGPT's Artificial Intelligence, it offers a simple yet revolutionary approach: just take a picture of the food label, share any specific dietary preferences or health concerns, and let the AI do the rest.
The Decoder breaks down the jargon into simple, understandable terms. It evaluates the major ingredients, sugars, preservatives, artificial components, potential allergens, and more. It even gives a health snapshot using emojis, making it easier to grasp the nutritional value at a glance.

Why Trust Food Label Decoder?

You might wonder, why trust an AI with something as personal as your dietary choices? The answer is simple: because it was created to solve real, everyday dilemmas—ones that I faced in my own life. Choosing between Product A and Product B, both claiming to be the healthier option, was a constant struggle due to the coded language of ingredients lists.

Food Label Decoder was born out of a need for transparency and simplicity. It cuts through the marketing noise, offering clear, unbiased information. It doesn't just tell you what's in your food; it helps you understand what that means for you, based on your unique health goals or dietary restrictions.

Making Informed Choices Has Never Been Easier

The beauty of the Food Label Decoder lies in its simplicity and accessibility. It empowers you to make informed decisions, turning the daunting task of reading labels into a quick, straightforward process. Whether you're navigating dietary restrictions, managing health conditions, or simply striving for a healthier lifestyle, the Decoder is your personal guide in the complex world of food shopping.

Act on Your Health

So, the next time you find yourself standing in the grocery aisle, perplexed by the list of ingredients on a product, remember that help is just a click away. The Food Label Decoder is more than just a tool; it's a movement towards a healthier, more informed society. It's time to take control of what we eat, one product at a time.

Why not start today? Take the first step towards becoming a more informed consumer and see the difference it makes in your shopping habits. After all, the best dietary choices are those made with confidence and clarity. Let's embark on this journey together, towards a healthier, happier you.

Wednesday, September 07, 2022

Useful Perforce Commands

 Perfoce Commands are especially useful when you are working on multiple branches and you don't want to download all branches but want to get some information. 

Before you proceed make sure you understand how wild cards work in perforce command: https://www.perforce.com/manuals/cmdref/Content/CmdRef/filespecs.html 

Search Text in All Readme.txt at any subfolder level of //depot/xxx/yyy/abc/

p4 grep -i -e "mytext" //depot/xxx/yyy/abc/.../Readme.txt

or (to cover .md and .txt files)

p4 grep -s -e -i "punta" //depot/iView/GTM_Branches/Release/.../Readme.*


Search Directory by name

p4 dirs -i "//depot/xxx/yyy/abc/*/def/dir_to_search"

also,

p4 dirs -i "//depot/xxx/yyy/abc/*/def/*dir_to_search*"

for searching file, use "files" command instead of "dirs command.

Use @@1 instead of * for single level search

Get Last Check-in info for a directory

p4 changes -m 1 "//depot/xxx/yyy/abc/*/def/…"


Diff between two files

p4 diff "//depot/xxx/def.txt" "//depot/yyy/def.txt"

File Sizes by name

p4 sizes -h "//depot/.../def.txt" 




Thursday, October 07, 2021

Break the sleep and leave the scope immediately immediately!

I wanted to write a quick and dirty code... but I didn't want to make it lousy in execution. Had simple requirement: Run a piece of code in a separate thread every 6 seconds but have ability to terminate (almost) immediately. Like any other lousy programmer, I didn't want to implement a timer (which is lengthy process in  C++). So I stumbled upon a solution which uses std::future to terminate the sleep immediately and doesn't execute anything once the future times out. Even if I was using while loop instead of do..while, it would have come out of the scope immediately. I am publishing it here as my example is more clear and that "Bad bad code." is present in that solution. Happy programming!


to compile: > g++ -pthread test.cpp


#include <thread>
#include <iostream>
#include <assert.h>
#include <chrono>
#include <future>
using namespace std;
void threadFunction(std::future<void> future){
   std::cout << "Starting the thread" << std::endl;
   do {
      std::cout << "Executing the thread....." << std::endl;
      //std::this_thread::sleep_for(std::chrono::milliseconds(6000)); //bad bad code
   } while (future.wait_for(std::chrono::milliseconds(6000)) == std::future_status::timeout);
   std::cout << "Thread Terminated" << std::endl;
}
main(){
   std::promise<void> signal_exit; //create promise object
   std::future<void> future = signal_exit.get_future();//create future objects
   std::thread my_thread(&threadFunction, std::move(future)); //start thread, and move future
   std::this_thread::sleep_for(std::chrono::seconds(7)); //wait for 7 seconds
   std::cout << "Threads will be stopped soon...." << std::endl;
   signal_exit.set_value(); //set value into promise
   my_thread.join(); //join the thread with the main thread
   std::cout << "Doing task in main function" << std::endl;
}

Tuesday, September 22, 2020

Simple GroupBy Function in for Python

After a lot of research I found that Python has no good groupby function that you can use in a single line (like Linq GroupBy of C#). For that, I've made a sample reusable groupby function that works with one or more keys, I wouldn't say it has great performance (actually far from it). But, it works and it is easier to use :) 

You may want to make changes based on your input:

import copy
import itertools

def yogee_groupby(collkeys):

    copied_collection = copy.deepcopy(coll)
    master_key = ""

    if len(keys) > 1:
        copied_collection = copy.deepcopy(coll)
        for key in keys:
            master_key = master_key + key
        
        for an_element in copied_collection:
            element_key = ""
            for key in keys:
                element_key = element_key + an_element[key]
            an_element[master_key] = element_key
    else:
        master_key = keys[0]

    grouped = {}
    sorted_collection = sorted(copied_collection, key = lambda item: item[master_key])
    for k, g in itertools.groupby(sorted_collection,  lambda item: item[master_key]):
        group = list(g)
        if len(keys) > 1:
            for an_element in group:
                an_element.pop(master_key, None)
        
        grouped[k] = group
    return grouped


def test_groupby_2():
    test_data = [
        {
            "E1""V1",
            "E2""V2",
            "E3": ["V31","V32","V33","V34"],
            "E3": {"E31":"V31","E32""V32","E33""V33","E34":"V34"}
        },
        {
            "E1""W1",
            "E2""W2",
            "E3": ["W31","W32","W33","W34"],
            "E3": {"E31":"W31","E32""W32","E33""W33","E34":"W34"}
        },
        {
            "E1""V1",
            "E2""V2",
            "E3": ["VV31","VV32","VV33","VV34"],
            "E3": {"E31":"VV31","E32""VV32","E33""VV33","E34":"VV34"}
        },
        {
            "E1""V1",
            "E2""V22",
            "E3": ["X31","X32","X33","X34"],
            "E3": {"E31":"X31","E32""X32","E33""X33","E34":"X34"}
        },
    ]
    grouped = yogee_groupby(test_data, ["E1""E2"])
    print(grouped)
    grouped = yogee_groupby(test_data, ["E1"])
    print(grouped)

test_groupby_2()



Tuesday, January 26, 2016

Anonymous method with Parameters 'i' -> Thread -> Iteration with 'i' -> Mess!

Problem:
You see IndexOutOfRangeException with message  "Index was outside the bounds of the array." when you thread out an anonymous method with iterator value as parameter.


Cause:
Surprised? How is it possible to see value i >= 4 (it was 4) in the 'for' loop there?
Well, it's 'possible' if your have written code as above.

Secret is that the anonymous method doesn't get called unless the Thread created doesn't becomes live. Once thread becomes live, it searches for it's anonymous method which is: MethodToCompute(NumberOfIterationPerThread[i])
Here, value of 'i' might have changed as 'for' loop to create thread runs in a different thread!

Solution:
solution is NOT to pass any value to threaded anonymous method which the parent thread may modify. In above case, I would create an extra variable to store value to pass to anonymous method which will be threaded out.

    for (int i = 0; i < NumberOfThreads; i++)
    {
        int iterationToRun = NumberOfIterationPerThread[i]; //magic line!
        threads[i] = new Thread(new ThreadStart(() => MethodToCompute(iterationToRun)));
        threads[i].IsBackground = true;
        threads[i].Start();
    }

Wednesday, June 10, 2015

NDK Directory Location on Windows 7

I am not big fan of Android on Windows 7 but that's what I've at present and now I've to install NDK for some reason. So, I downloaded Android NDK from https://developer.android.com/ndk/downloads/index.html According to the documentation, I've to double click the NDK download and it will automatically extract file. I ran and now I don't know where it has extracted the files are. I have to mention installed NDK path (ndk.dir) in "local.properties" (btw, I am using Android Studio). After searching whole C: suing below DOS command (I saw my nkd folder was "android-ndk-r10e"),


    dir /b /s /ad | findstr "android-ndk-r10e"

Found the directory. As I've downloaded 64 bit NDK, it's

    "C:\Windows\SysWOW64\android-ndk-r10e"

on my 64bit Windows 7 machine.

Hope this helps and you don't have to search C: like me.