dotplan

troubleshooting & performance analysis

Hardware design for high density storage pod

Tags: , , , , ,

These guys at ‘backblaze’ claim to be able to provide 67TB for $7,867 based on 45 SATA drives, RAID6 (Linux) and JFS. The hardware design which is presented in the blog as a how-to uses vertically stacked drives and looks very much like the Sun ‘Thumper’ (X4500) device which I first saw when I was still at Sun around 2006. No performance numbers are given, and whilst the capacity is much cheaper than ‘real’ storage, I doubt that write performance is much to write home about.

  • 45 SATA Drives
  • JFS
  • RAID6 (Linux mdadm)
  • Served via HTTPS (not NFS,iSCSI)
  • Map MAC to NIC vendor.

    Tags:

    Not sure how well known this trick is, but it is possible to figure out the vendor of a particular NIC by looking at the first few digits of the MAC address. We used to use this when I worked at Sun to figure out if the customers were using pukka Sun NICs and what might be at the other end. In the modern world there is a web tool that will do the lookup for you. Mac Find

    • Author: gary
    • Published: Sep 2nd, 2009
    • Category: unix
    • Comments: None

    List binary objects by size.

    Tags: , , , , ,

    Sometimes you will want to know what a binary file contains (functions, arrays, objects) etc. The ‘nm’ command will do that for you, and the following 1-liner will sort the output by size. I use this to determine why some source compiled on Solaris is larger than when compiled in linux.

    e.g.

     nm  | sort -n -t \| +2
    

    Here is a small binary I happen to have.

    $ nm write_random | sort -n -t \| +2 
    
    write_random:
    
    [Index]   Value      Size    Type  Bind  Other Shndx   Name
    ..
    
    ..
    [72]    | 134520544|      60|OBJT |GLOB |0    |23     |tstr
    [85]    |         0|      60|FUNC |GLOB |0    |UNDEF  |lseek@@GLIBC_2.0
    [58]    | 134515432|      66|FUNC |GLOB |0    |12     |__libc_csu_fini
    [66]    |         0|      67|FUNC |GLOB |0    |UNDEF  |getopt@@GLIBC_2.0
    [74]    | 134515348|      82|FUNC |GLOB |0    |12     |__libc_csu_init
    [51]    |         0|     113|FUNC |GLOB |0    |UNDEF  |close@@GLIBC_2.0
    [76]    |         0|     113|FUNC |GLOB |0    |UNDEF  |fsync@@GLIBC_2.0
    [50]    |         0|     124|FUNC |GLOB |0    |UNDEF  |write@@GLIBC_2.0
    [88]    |         0|     124|FUNC |GLOB |0    |UNDEF  |open@@GLIBC_2.0
    [55]    | 134514968|     163|FUNC |GLOB |0    |12     |getSizeInBlocks
    [68]    | 134515131|     214|FUNC |GLOB |0    |12     |do_writes
    [89]    |         0|     217|FUNC |GLOB |0    |UNDEF  |exit@@GLIBC_2.0
    [79]    |         0|     221|FUNC |GLOB |0    |UNDEF  |__libc_start_main@@GLIBC_2.0
    [67]    |         0|     344|FUNC |GLOB |0    |UNDEF  |__fxstat@@GLIBC_2.0
    [53]    |         0|     523|FUNC |GLOB |0    |UNDEF  |perror@@GLIBC_2.0
    [62]    |         0|     539|FUNC |GLOB |0    |UNDEF  |malloc@@GLIBC_2.0
    [77]    | 134514424|     544|FUNC |GLOB |0    |12     |main
    

    Here’s the source code for the same binary, notice in the output of nm the size of the object tstr is 60 bytes, and in the code it’s specified as char[60].

    $ cat write_random.c
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    #define ARRAYSIZE 16*1024
    #define NUMTOWRITE 10
    
    int getSizeInBlocks(int,int, char *);
    void do_writes(int,int, int);
    int     loopsToDo=1;
    int     limitLoops=0;   /*Default to doing loops forever*/
    int     msPause=0;
    int     iostart,iostop,iotimeMS,ioThresh;
    struct tm *tm_ptr;
    time_t  tm;
    char    tstr[60];
    int     IOoverThresh=1,TotalIOs=1,dofsync=0,forcesize=0;
    double  badpct;
    
    int main(argc, argv)
    int     argc;
    char    *argv[];
    {
    
            int     i,n,count=0,SizeInBlocks;
            int     appBlockSize=8192,key;  /*Default IO size is 8k*/
            int     mode=O_RDWR;
            int     dsync=0;
            char    *array,c,filename[255];
            int fd;
    
            if (argc == 1) {
                    fprintf(stderr,"Usage: [-d  -f | -b  |-s | -l  | -o st_size; */
      FileSize=lseek(fd,0,SEEK_END);
      if (forcesize)
        FileSize=forcesize*1024*1024;
      appBlocks = (int) FileSize/appBlockSize;
      printf("file %s is %d bytes %d application blocks blocksize = %d\n",filename,FileSize,appBlocks,appBlockSize);
      return appBlocks;
    }
    
    void do_writes(int fd,int appBlockSize, int appBlocks)
    {
     char *array;
     array=malloc(appBlockSize);
    
     while  (loopsToDo >0 ){
      /*generate a random number 0-appBlocks*/
      int seek_val=rand()%appBlocks;
      lseek(fd,appBlockSize * seek_val, SEEK_SET);
      write(fd,array, appBlockSize);
      if (dofsync)
        fsync(fd);
      TotalIOs++;
    
      if (limitLoops)
            loopsToDo--;
      if (msPause)
            usleep(msPause*1000);
      }
      return;
    }
    

    © 2009 dotplan. All Rights Reserved.

    This blog is powered by Wordpress and Magatheme by Bryan Helmig.