Oh, and if you did want to use a zero copy IO interface like `memfiles` on 
this, you can and indeed it is over 3X faster, but you have to write your own 
integer parser because `parseUint` and all its analogues take a Nim `string` 
not `MemSlice`. You can use the dollar operator `$` to convert, but that is no 
faster than just using `lines` in the first place. Parsing an integer in ASCII 
is actually pretty easy, though. E.g., 
    
    
    import tables, os, memfiles
    
    proc parseUInt(data: cstring, size: int): uint {.inline.} =
      let zero = ord('0')
      let nine = ord('9')
      for i in 0 ..< size:
        let code = ord(data[i])
        if code >= zero and code <= nine:
          result *= 10
          result += uint(code - zero)
        else:
          return 0  #non-digit; parse error
    
    proc ytz(path: string): uint =
        var
          table = initTable[uint, uint]()
          mf = memfiles.open(path)
        if mf.mem == nil:
            quit("Cannot open " & path)
        for s in memSlices(mf):
            let n = parseUInt(cast[cstring](s.data), s.size)
            if n == 0:
                quit("Parse error: " & $s)
            table.mgetOrPut(n, 0) += n
        for key, val in table:
            result = max(result, val)
        mf.close
    
    proc main() =
        echo ytz(paramStr(1))
    
    main()
    
    
    Run

Not a big deal here, but if the file were really large that factor of 3 might 
be more appreciated.

Reply via email to