Recent Blogs

Understanding IOPS, Latency and storage performance

posted Jun 21, 2018, 2:23 AM by Karthik Karuppasamy   [ updated Jun 21, 2018, 2:45 AM ]

How much throughput can this drive deliver? You might have come across this question often, if you are in the storage field. Let’s unravel the most common terms like Throughput, IOPS & Latency in this blog. Normally throughput is represented in Megabytes/Seconds i.e. MB/s. Higher throughput ensures better performance and getting maximum value is depend lot of factors.
Before swim into the deeper part, let’s start with simple stuffs. 

Below diagram provides the 2D representation of the single disk plate in the Hard Drive. Disk plate have been divided in to tracks and each track is segregated to sectors. Data to be read/written i.e. IO will be stored in this sectors in binary format.
One sector can have Maximum “512 Bytes” of data. Hence IOPS [Input Output Per Second] means amount of read or write can be performed in one second on the sectors.
In real time, the application or service will not request IO from only one sector but will request for certain amount of IO from the disk [E.g. 4KB,8KB]. This IO size will differ based on the application and operating system as well. Hence IO Size means a certain amount of data to be read/written at the same time in disk.
So Throughput can be changed based on IOPS and Size of IO too. Throughput in MB/s = IOPS * Average IO Size.
What is Latency then?? Average Latency means average time taken to complete the each IO request. It has to be considered from application point of view]. 

Let us understand this term using real time example. Assume you are going to hospital for the health check up and the doctor takes approximately 15 minutes to complete the check up for one patient. Hence for an hour, we can assume that doctor (disk) can complete the check up for four patients (IOs) in average of 15 minute per person (Avg. Latency). It is clear that although the doctor can complete the check up for four persons in an hour, he can't handle them in same time rather. But if the second patient comes in 10 th minute, then his overall check up time will become 20 minutes which includes 5 minutes of waiting time. Hence "average latency" is always considered for representation. 

Normally latency is denoted in milliseconds (ms). We can easily understand from above example that the average latency should be minimal for better performance. In real world, this latency can be affected by several factors, especially traditional hard disk physical limits due to its mechanical construction. SAS Hard disk is having 10K or 15K RPM and SATA is having 5400 or 7200 RPM.
What is RPM? RPM is Revolutions per Minute or Rotational Per Minute. i.e. How many times the disk plate rotates in a minute. If the RPM value is high, the disk will provide high performance.
Lets take SAS drive which has 10000 RPM. Hence the plate will rotate 167 times for one second. To make it in different terms, plate will take 6 milliseconds to complete one full rotation. This is so called “Rotational Delay”

In the diagram, red dotted path represents the disk plate rotational movement [Anti Clock Wise] and blue dot represents the “disk arm and head” movement [to and fro]. Data can be read/written at any sector of any track and Disk head has to wait until the disk rotates to particular sector. In the diagram, in order to read the blue sector, disk has to rotate and disk arm & head also have to move outer part of the disk. 

The time it takes to move the disk arm & head is called “Seek Time”. If the average seek time is minimal for the disk then the disk arm & head movement is fast enough. 

If the IO size is 512 bytes, then reading of that one sector is enough [ one sector = 512 bytes]. But in real time, the IO size could be 4KB, 8KB and eventually we need to read more sectors. If the upcoming sector is also having our required data, then the disk plate movement is very very less and there is no movement for disk arm & head. But the fact is, the required data could present at any sectors of any track. Hence disk plate and head have to move continuously until the IO size is completed.
The amount of time taken to read/write the requested IO Size is called Transfer Delay. This transfer delay will be less if IO type is sequential. For Random IOs, requested data will be scattered all over the disk and hence transfer delay will be high.
So far we have checked some physical factors which decide the disk performance. To summarize everything, Throughput (MB/S) is based on the IOSize * IOPS. For the throughput of 150 MB/s with IO size of 4KB, we can achieve IOPS count of 36650. But for the same throughput 150 MB/s with the IO size of 32KB, we can only get IOPS count of 4580. One vital point we didn’t mention here. Guessed what? Yes, it is IO Type and these numbers for sequential IO. If it is Random IO then IOPS count will drastically reduce due to the physical factors what we discussed earlier.
So the thumb rule is: Only IOPS numbers are meaningless unless until other factors latency, IOSize , IOtype & Read/Write % are mentioned along with that.
Finally, to get better performance, go for the disks with High RPM and less average seek time. Also to improve the performance with Random IOs, we can go for RAID Management which could serve multiple IOs in parallel. 

Please do comment and share your thoughts if I have missed something.

Difference between Abstract class and Interface - C#

posted Oct 14, 2009, 11:16 PM by Karthik Karuppasamy   [ updated Jun 21, 2018, 3:10 AM ]

Every C# developer would have faced this question at least once in their development career. If you are a fresher, hopefully following real time example could be helpful for you to understand them. Please note that this example is only for understanding the concept and could suit approximately and not appropriately.

Assume you have to purchase shirts for your brother and cousin for upcoming traditional function. You have only Rs.10000 in your hand and hence you are fixing Rs.5000 per head for the shirt. Now the problem is, you don't know anything about their liking and disliking. So you have decided to give the amount to choose of their own. 

Points to Consider: 
  1. As it is traditional function, you want them to buy formal shirt only and not T-Shirt. 
  2. You have to make sure that they will use the whole amount for the shirt and should not use for other stuffs
  3. Also you want them to decide their own brand and colour of the shirt. 
Eventually you decided to provide Generic Gift Voucher from Bank or ShowRoom to buy the shirt.The Generic Gift voucher is so called "Interface" which makes sure that the shirts "[of their own choices]" are bought within the money range.

Below code represents the IGiftVoucher5000 interface and Shirt class. The "Shirt" return type for GetShirt() function in Interface, makes sure that shirt has only been bought. 

//Interface which is similar to GiftVoucher
interface IGiftVoucher5000
{//Return type "Shirt" class make sure that they buy shirt only
Shirt GetShirt();
public class Shirt
public Shirt(string brandName, string color)
this.Brand = brandName;
this.Color = color;
public string Brand { get; set; }
public string Color { get; set; }

Now your brother and cousin can use that gift voucher and can buy shirt with his own choice of "brand". Similarly "Brother" class can inherit the interface "IGiftVoucher5000" and implement "GetShirt()" of his own. Also "Cousin" can inherit and implement "GetShirt()" of his own.
Note: GetShirt() function does not have any implementation in interface. Inheriting class has to implement it. If it is not implemented then it will throw an error.
public class Cousin : IGiftVoucher5000
{// Cousin can implement his own choice of brand and color
public Shirt GetShirt()
   return new Shirt("Peter England", "Black");
public class Brother : IGiftVoucher5000
{// Brother also can mention his own choice
public Shirt GetShirt()
return new Shirt("Raymond", "White");
class Program
static void Main(string[] args)
Cousin Ram = new Cousin();
Console.WriteLine("Your cousin bought {0} : {1} shirt of his own choice !!!", Ram.GetShirt().Brand, Ram.GetShirt().Color);
Brother Sri = new Brother();
Console.WriteLine("Your brother bought {0} : {1} shirt of his own choice !!!", Sri.GetShirt().Brand, Sri.GetShirt().Color);

Now create an object for Brother, Cousin classes and call the GetShirt(). The output will be
Your cousin bought Peter England : Black shirt of his own choice !!! Your brother bought Raymond : White shirt of his own choice !!!
Bit simple, isn't it?? Now it's the time to move on for "Abstract". In our above example, you let your brother and cousin to make their own choice while buying the shirt. But now you want to present the shirt from your favorite and best brand as default option. So you have decided to opt for "The Raymond Shop - Gift card" instead of Generic gift voucher which will have additional Check. In the below abstract class, we can show alert message if some other brand is passed.
This "The Raymond Shop - Gift card" is so called Abstract class which has default check for GetShirt() using it's default implementation and still forces the subclasses to follow certain protocol.
public abstract class GiftVoucher5000
//Constant for Raymond
private const string BrandName = "Raymond";
//Condition to check "Raymond" brand
public  GiftVoucher5000()
if (this.GetShirt().Brand != BrandName)
Console.WriteLine("Alert !!!");
Console.WriteLine("Success !!!");
//Abstract method which should be implemented by sub class method.
//Else it will throw an error.
public abstract Shirt GetShirt();
public class Cousin_Abs : GiftVoucher5000
//Overriding the abstract method. It will throw an error if it is not overrided.
public override Shirt GetShirt()
//Passing other brand should display "Alert" message
return new Shirt("Raymond", "Black");
public class Brother_Abs : GiftVoucher5000
//Overriding the abstract method
public override Shirt GetShirt()
//Passing Raymond brand should display "Success" message
return new Shirt("Tommy Hilfiger", "Blue");
static void Main(string[] args)
Cousin_Abs Ram = new Cousin_Abs();
Console.WriteLine("Your cousin bought {0} : {1} shirt !!!", Ram.GetShirt().Brand, Ram.GetShirt().Color);
Brother_Abs Sri = new Brother_Abs();
Console.WriteLine("Your brother bought {0} : {1} shirt !!!", Sri.GetShirt().Brand, Sri.GetShirt().Color);

Your cousin accepts to have Raymond brand but your brother wants only Tommy Hilfiger. In this case, Abstract class constructor will show "Alert" message based on the selected brand. The output will be
Success !!! Your cousin bought Raymond : Black shirt !!! Alert !!! Your brother bought Tommy Hilfiger : Blue shirt !!!
So to summarize everything,


  • Interface is not a class and defined with a word "Interface". It provides only blue print and will not have any implementation for any method.
  • All the methods in Interface should be implemented in subclass.
  • Any class can inherit multiple interfaces.
  • Only "Public" access modifier is allowed

Abstract Class

  • Abstract class provides certain standards or hierarchy and forces the subclasses to follow them. If needed, Abstract classes provides default implementation for certain methods and subclasses can use as it is.
  • No need to implement all the methods in abstract classes. Only abstract methods should be implemented.
  • Abstract class cannot be instantiated. That means you cannot create object for it and only can be inherited. Any class can inherit only one Abstract class.
  • Different access modifiers are allowed.

Fixing a “FailedAndSuspended” content index for an Exchange

posted Oct 14, 2009, 11:11 PM by Karthik Karuppasamy   [ updated Jun 8, 2018, 4:39 AM ]

This post provides the solution for "FailedAndSuspended" status of Exchange Database after rebooting Server if the administrator has single copy of the DB alone. Below are steps to reproduce the issue with Exchange Server 2013 (SP1).
1. Setup Exchange Server "TESTEXCHANGE" and create New Database named "testdb". Note: Exchange server will have default database also. In our case that db name is "Mailbox Database 203053209"
[PS] C:\Windows\system32>get-mailboxdatabasecopystatus
 Name Status CopyQueue ReplayQueue LastInspectedLogTime ContentIndex Length Length State ---- ------ --------- ----------- -------------------- ------------ Mailbox Database 2030532095\TESTEXCHANGE Mounted 0 0 Healthy testdb\TESTEXCHANGE Mounted 0 0 Healthy
2. Restart the server and check the status for DB using following command.
[PS] C:\Windows\system32>get-mailboxdatabasecopystatus | fl name, ContentIndexState Name : Mailbox Database 2030532095\TESTEXCHANGE ContentIndexState : Healthy Name : testdb\TESTEXCHANGE ContentIndexState : FailedAndSuspended
3. Since “ContentIndexState “ was “FailedAndSuspended”, we couldn’t use that DB to recover mail.

Solution to recover Mailbox DB from Failed state:

1. Stop the following exchange services
[PS] C:\Windows\system32>stop-Service MSExchangeFastSearch
WARNING: Waiting for service 'Microsoft Exchange Search (MSExchangeFastSearch)' to stop... WARNING: Waiting for service 'Microsoft Exchange Search (MSExchangeFastSearch)' to stop... 
[PS] C:\Windows\system32>Stop-Service HostControllerService 
WARNING: Waiting for service 'Microsoft Exchange Search Host Controller (HostControllerService)' to stop... [PS] C:\Windows\system32>
2. Delete Index folders for both Mailbox Database 2030532095\TESTEXCHANGE, testdb\TESTEXCHANGE
Default DB index folder path: C:\Program Files\Microsoft\Exchange Server\V15\Mailbox\ In that path check for the folder having very long name and having three sub folders. This is folder where the index is stored. Delete this folder along with sub folders. Make sure you deleted the index folder for default DB and the DB created by yourself.
3. start the following exchange services and check status again
[PS] C:\Windows\system32>Start-Service HostControllerService
[PS] C:\Windows\system32>start-Service MSExchangeFastSearch 
[PS] C:\Windows\system32>get-mailboxdatabasecopystatus | fl name, ContentIndexState Name : Mailbox Database 2030532095\TESTEXCHANGE ContentIndexState : Healthy Name : testdb\TESTEXCHANGE ContentIndexState : Healthy
NOTE: Index folder creation may take some time based on the size. In my setup, it is created within ~4 minutes. Based on the size of the DB it will take some time to become healthy Status.

1-3 of 3