Since a lot of people get kind of stuck in their IO ways and for whatever 
reasons seem to not just trust my word for it and since @Scotpip seems new to 
Nim and might want some hand holding, here is some **_code to get him/others 
started_** : 
    
    
    import times, os, memfiles, strutils # This is barIO.nim
    type
      Bar* = object {.packed.}
        t*: int64 # ns since 1970-01-01 gives +-292 year range!
        o*, h*, l*, c*, v*: float # open,hi,lo,close,vlm
      Bars* = UncheckedArray[Bar]
      BarFile* = object
        barf: MemFile
        bars: ptr Bars
        nBar: int #XXX should define `[]` bounds checking this
    
    proc bopen*(path: string): BarFile =
      result.barf = memfiles.open path
      result.bars = cast[ptr Bars](result.barf.mem)
      result.nBar = result.barf.size div Bar.sizeof
    proc close*(bf: var BarFile) = bf.barf.close
    
    when isMainModule:
      if paramCount() != 3:
        stderr.write "Use: bario make|vlmTot path.bars num|idx\n"
        quit(1)
      let path = paramStr(2)
      let num  = parseInt paramStr(3)
      let t0   = epochTime()
      case paramStr(1)
      of "make":
        let f = system.open(path, fmWrite)
        var bar: Bar        # real data have more than `.v` ;)
        for i in 1..num:
          bar.v = float(i)  #XXX handle disk full below
          discard f.writeBuffer(bar.addr, bar.sizeof)
      of "vlmTot":
        var bf = bopen(path)
        var total = 0.0
        for i in bf.nBar - num ..< bf.nBar:
          total += bf.bars[i].v #XXX bf[i].v once `[]` exists
        echo "volume total of last ", num, " records is ", total
      echo epochTime() - t0, " seconds"
    
    
    Run

That's it - define, create, read, benchmark all in under 40 lines. Now for some 
**_benchmark numbers that might inspire you to care_**. Below are times for a 
Unix RAM test; 72 MB likely VERY cachable and data like this is typically 
write-once read-many. So, round-trip is much less relevant than teased apart 
write/read measurement. 
    
    
    $ ./barIO make /dev/shm/test.bars 1_500_000
      0.039844 seconds
    $ ./barIO vlmTot /dev/shm/test.bars 1_500_000
      volume total of last 1500000 records is 1125000750000.0
      0.005187 seconds
    $ ./barIO vlmTot /dev/shm/test.bars 100_000
      volume total of last 100000 records is 145000050000.0
      0.000386 seconds   # 337X faster than 260ms/2 (for RT)
    
    # Demo some NIO stuff while we're at it:
    $ ln -s /dev/shm/test.bars /dev/shm/tohlcv.Nlddddd
    $ nio print /dev/shm/tohlcv.Nlddddd | tail -n100000 |
        awk '{print sum += $6}' | tail -n1
    145000050000 # Checks out; Just 2.65s=7000X slower.. ;)
    # Ok, ok..
    $ nio cut -d :5 /dev/shm/tohlcv.Nlddddd |
        nio tails -t 100000 .Nd | nio pr .Nd |
        awk '{print sum+=\$1}' | tail -n1
    145000050000 # Also verifies; 122 millisec; 360X slower. ;)
    
    
    Run

Now, 72 MB/.005187s =~ 13.9 GB/s. **_Not terrible, but also not great_**. That 
machine can do like 45 GB/s, but getting 3 cores hot sucking data out of DIMMs 
is out of scope. You are on your own for the last factor of 3..12X. :-D { That 
will also obviously depend upon your exact calculations anyway, but VWAP or 
EWMA or other things should be pretty similar to volume totals. And 5 ms may be 
fast enough and who knows what your mem bw situation is anyway. }

Reply via email to