Re: Memory usage skyrocketed with nim 0.18.0 (in my async tcp service test)

2018-04-07 Thread aguspiza2
Ok, i have found why:

In that commit there is a new templated implementation for newSelector() 
(0.17.2) to newSelector[T]() (0.17.3+) in linux specifically it is using epoll.


proc newSelector*[T](): Selector[T] =
  # Retrieve the maximum fd count (for current OS) via getrlimit()
  var a = RLimit()
  if getrlimit(RLIMIT_NOFILE, a) != 0:
raiseOsError(osLastError())
  var maxFD = int(a.rlim_max)
  doAssert(maxFD > 0)
  
  var epollFD = epoll_create(MAX_EPOLL_EVENTS)
  if epollFD < 0:
raiseOsError(osLastError())
  
  when hasThreadSupport:
result = cast[Selector[T]](allocShared0(sizeof(SelectorImpl[T])))
result.epollFD = epollFD
result.maxFD = maxFD
result.fds = allocSharedArray[SelectorKey[T]](maxFD)
  else:
result = Selector[T]()
result.epollFD = epollFD
result.maxFD = maxFD
result.fds = newSeq[SelectorKey[T]](maxFD)


As you see, it is allocating newSeq[SelectorKey[T]](maxFD)

in my system (docker alpine) maxFD is set to 1M and SelectorKey is defined as:


SelectorKey[T] = object
  ident: int
  events: set[Event]
  param: int
  data: T


sizeof SelectorKey[AsyncData] is 40 so a simple math 40*1M = 40M

A simple workaround that uses 10x less memory:


proc newSelector*[T](): Selector[T] =
  # Retrieve the maximum fd count (for current OS) via getrlimit()
  var a = RLimit()
  if getrlimit(RLIMIT_NOFILE, a) != 0:
raiseOsError(osLastError())
  var maxFD = int(a.rlim_max)
  doAssert(maxFD > 0)
  
  var epollFD = epoll_create(MAX_EPOLL_EVENTS)
  if epollFD < 0:
raiseOsError(osLastError())
  
  when defined(maxFileDescriptors):
const maxFileDescriptors {.intdefine.}: int = 132072
if maxFD > maxFileDescriptors:
  maxFD = maxFileDescriptors
  
  when hasThreadSupport:
result = cast[Selector[T]](allocShared0(sizeof(SelectorImpl[T])))
result.epollFD = epollFD
result.maxFD = maxFD
result.fds = allocSharedArray[SelectorKey[T]](maxFD)
  else:
result = Selector[T]()
result.epollFD = epollFD
result.maxFD = maxFD
result.fds = newSeq[SelectorKey[T]](maxFD)


For a proper solution we should dinamically increase fds if we are requesting 
more than 132072 file descriptors 


Memory usage skyrocketed with nim 0.18.0 (in my async tcp service test)

2018-04-01 Thread aguspiza2
I have done a little test to find out if I could run some microservices with 
async code in memory constrained devices. Here is the test code:

[https://gist.github.com/aguspiza/80e34b5cf65aa3bbfd19c7339ee9b695](https://gist.github.com/aguspiza/80e34b5cf65aa3bbfd19c7339ee9b695)

That test uses 5x more memory with 0.18.0 than with 0.17.2 (or any previous 
version at least with boehm gc)

Here you have some numbers:


Linux x64 0.17.2 boehm 24MB used (release 14MB)
Linux x64 0.18.0 boehm 94MB used (release 84MB)

other gc's have similar increases +40MB:
0.17.2 default gc 70MB (release 30-36MB)
0.18.0 default gc 146MB (release 110MB)
similar result with gc:v2 146MB (release 110MB)


I am getting those numbers from RSS column on "ps"


$ ps aux
USER   PID %CPU %MEMVSZ   RSS TTY  STAT START   TIME COMMAND
root 13946 38.9  0.0  18024 15136 pts/0Sl+  11:55   0:22 ./httpasync


Is this a known issue?

Is this expected from latest gc optimization (TLSF algorithm) in 0.18.0?

Why is there so much difference between gc's?

Should I use boehm, markandsweep, v2 or default gc?

Boehm is giving the best results but Araq told me (at IRC) that it is not using 
Nim's memory allocator ?!?!


Re: Memory usage skyrocketed with nim 0.18.0 (in my async tcp service test)

2018-04-03 Thread aguspiza2
Thanks Araq, right now I am using "clients" to avoid deallocating memory, so 
that I can get peak memory use. In the future, it will be used to dispatch 
messages to specific connected clients. This service should also remove clients 
from that sequence when they disconnect. Sorry, I will try to clean up the code 
so that the test makes more "sense", this may help me to find out which part is 
allocating those extra 70MB (Sorry for the long post): 


sudo pmap 26153
26153:   httpasync/src/httpasync018
556fff75a000124K r-x-- httpasync018
556fff978000  4K r httpasync018
556fff979000  4K rw--- httpasync018
556fff97a000 32K rw---   [ anon ]
557000ed2000124K rw---   [ anon ]
7f2806a93000  84164K rw---   [ anon ]
7f280bcc4000   2172K r-x-- libgc.so.1.0.3
7f280bee3000  4K r libgc.so.1.0.3
7f280bee4000  4K rw--- libgc.so.1.0.3
7f280bee5000264K rw---   [ anon ]
7f280bf2c000548K r-x-- ld-musl-x86_64.so.1
7f280bfbc000   1472K rw---   [ anon ]
7f280c12c000  4K r--s- localtime
7f280c12f000  8K -   [ anon ]
7f280c131000 84K rw---   [ anon ]
7f280c146000  8K -   [ anon ]
7f280c148000 84K rw---   [ anon ]
7f280c15d000  8K -   [ anon ]
7f280c15f000340K rw---   [ anon ]
7f280c1b4000  4K r ld-musl-x86_64.so.1
7f280c1b5000  4K rw--- ld-musl-x86_64.so.1
7f280c1b6000 12K rw---   [ anon ]
7ffdf4ad5000132K rw---   [ pila ]
7ffdf4b9c000  8K r   [ anon ]
7ffdf4b9e000  8K r-x--   [ anon ]
ff60  4K r-x--   [ anon ]
 total89624K


versus 0.17.2 


sudo pmap 26094
26094:   httpasync/src/httpasync
55b617f37000104K r-x-- httpasync
55b61815  4K r httpasync
55b618151000  4K rw--- httpasync
55b618152000 28K rw---   [ anon ]
55b6194e120K rw---   [ anon ]
7fe5853e4000  11648K rw---   [ anon ]
7fe585f44000   2172K r-x-- libgc.so.1.0.3
7fe586163000  4K r libgc.so.1.0.3
7fe586164000  4K rw--- libgc.so.1.0.3
7fe586165000264K rw---   [ anon ]
7fe5861ac000548K r-x-- ld-musl-x86_64.so.1
7fe586235000   1512K rw---   [ anon ]
7fe5863af000  8K -   [ anon ]
7fe5863b1000 84K rw---   [ anon ]
7fe5863c6000  8K -   [ anon ]
7fe5863c8000 84K rw---   [ anon ]
7fe5863dd000  8K -   [ anon ]
7fe5863df000340K rw---   [ anon ]
7fe586434000  4K r ld-musl-x86_64.so.1
7fe586435000  4K rw--- ld-musl-x86_64.so.1
7fe586436000 12K rw---   [ anon ]
7ffebaff6000132K rw---   [ pila ]
7ffebb124000  8K r   [ anon ]
7ffebb126000  8K r-x--   [ anon ]
ff60  4K r-x--   [ anon ]
 total17116K


Anyway, I understand that it should work (leak) in a similar way regardless of 
the gc or nim version used. There is a fixed number of clients that are 
connecting, so that sequence will grow to 1000 and stop there. I am measuring 
memory use after all clients (1000) have sent and received 1000 messages, so it 
should not depend on the speed they are added.

jcosborn, I have been doing all tests with "official" docker images 
(nimlang/nim:0.xx.y-alpine), and nimlang/nim:devel reports version 0.15.3. I 
have been looking for the original Dockerfile of those images to build an 
updated devel branch but it seems it is actually generated with nim code in a 
very smart way  I'll put some time on this and report back.


Re: Memory usage skyrocketed with nim 0.18.0 (in my async tcp service test)

2018-04-06 Thread aguspiza2
I am thinking about bisecting it now that I have a simple test. Also now I have 
a Dockerfile to bootstrap any commit 


FROM alpine
RUN apk add --no-cache g++ curl tar git
RUN git clone https://github.com/nim-lang/Nim.git;
RUN cd Nim; \
git clone --depth 1 https://github.com/nim-lang/csources.git;
ARG GITCOMMIT
RUN cd /Nim; \
git checkout -b testMemory; \
echo $GITCOMMIT; \
git reset --hard $GITCOMMIT
RUN cd /Nim/csources; \
sh build.sh; \
cd ../; \
bin/nim c koch; \
./koch boot -d:release; \
./koch tools;



Re: Memory usage skyrocketed with nim 0.18.0 (in my async tcp service test)

2018-04-03 Thread aguspiza2
indeed no changes:


sudo pmap 28234
28234:   ./httpasync0181
561967f7a000124K r-x-- httpasync0181
561968198000  4K r httpasync0181
561968199000  4K rw--- httpasync0181
56196819a000 32K rw---   [ anon ]
561968b41000124K rw---   [ anon ]
7fde9f0e3000  84164K rw---   [ anon ]
7fdea4314000   2172K r-x-- libgc.so.1.0.3
7fdea4533000  4K r libgc.so.1.0.3
7fdea4534000  4K rw--- libgc.so.1.0.3
7fdea4535000264K rw---   [ anon ]
7fdea457c000548K r-x-- ld-musl-x86_64.so.1
7fdea460c000   1472K rw---   [ anon ]
7fdea477c000  4K r--s- localtime
7fdea477f000  8K -   [ anon ]
7fdea4781000 84K rw---   [ anon ]
7fdea4796000  8K -   [ anon ]
7fdea4798000 84K rw---   [ anon ]
7fdea47ad000  8K -   [ anon ]
7fdea47af000340K rw---   [ anon ]
7fdea4804000  4K r ld-musl-x86_64.so.1
7fdea4805000  4K rw--- ld-musl-x86_64.so.1
7fdea4806000 12K rw---   [ anon ]
7fffec4e9000132K rw---   [ pila ]
7fffec5ec000  8K r   [ anon ]
7fffec5ee000  8K r-x--   [ anon ]
ff60  4K r-x--   [ anon ]
 total89624K



Re: Memory usage skyrocketed with nim 0.18.0 (in my async tcp service test)

2018-04-04 Thread aguspiza2
For anyone interested I found that: 


import asyncdispatch, asyncnet, os

var server = newAsyncSocket() #or newAsyncNativeSocket()
let x = readFile("/proc/self/status")
echo x


Uses 44MB with 0.18.x

Uses 4MB with 0.17.2


Re: Memory usage skyrocketed with nim 0.18.0 (in my async tcp service test)

2018-04-07 Thread aguspiza2
Found, big commit, but i will check it



d3394be5559c324da1c6b576d0ae9bfa966698d9 is the first bad commit
commit d3394be5559c324da1c6b576d0ae9bfa966698d9
Author: Dominik Picheta 
Date:   Wed Nov 22 14:43:10 2017 +

Async upcoming (#6585)

* Merge upcoming async with current.
* Various improvements to selectors (mostly docs).

Two changes to highlight:

* Renamed setEvent to trigger
* Reused setBlocking from nativesockets.
* Various changes/fixes to asyncdispatch after upcoming merge.
* Make some attempts to be compatible with older selectors.
* Reuse epoll module in ioselectors_epoll.

:04 04 16b975f4a522742edfd7a5c97ad650dd4811b994 
251521440149c2bba6c176f3e3d2ccba931b1efa M  lib
:04 04 46c44c82e288c889cecdb39d2fc565124e8c7590 
34039d8cb5aee971cbf87ea77ddff885afb9 M  tests




/Nim # git bisect log
git bisect start
# bad: [e695f9d94e752fbf18012f9ee164af1ba0649fa1] make Nim compile with 
older nim versions
git bisect bad e695f9d94e752fbf18012f9ee164af1ba0649fa1
# good: [811fbdafd958443ddac98ad58c77245860b38620] Revert usage of 
non-standard uname -o command in build.sh (#6342)
git bisect good 811fbdafd958443ddac98ad58c77245860b38620
# good: [157d48bc3208720af98ac5ed60a08494ddc5e328] make 'nim doc2 
system.nim' work again
git bisect good 157d48bc3208720af98ac5ed60a08494ddc5e328
# bad: [2bb2e6975e397bef1b320cd5dbafb6b3338fdaf0] Fix infinite recursion 
when using json.to on ref with cycle.
git bisect bad 2bb2e6975e397bef1b320cd5dbafb6b3338fdaf0
# good: [aac94e0ab58e9bdc896a59422d4ab9dcb87bb9e3] Don't run "kde-open" and 
"gnome-open" under Unix (#6426)
git bisect good aac94e0ab58e9bdc896a59422d4ab9dcb87bb9e3
# bad: [a372363190488d7267e545ce9ec6c81ccb79ed8c] Don't catch-all in 
asynchttpserver. It hides bugs.
git bisect bad a372363190488d7267e545ce9ec6c81ccb79ed8c
# bad: [a6226d9452194cc3b8d35a0d38d9f8c89ddf04f5] fixes #6682
git bisect bad a6226d9452194cc3b8d35a0d38d9f8c89ddf04f5
# good: [844e123061631d4cc5bc4300301d1865eda5a337] updated changelog to 
mention the removal of 'generic' and 'atomic'
git bisect good 844e123061631d4cc5bc4300301d1865eda5a337
# good: [85b00aff56c98f4da8f70b120dc889c18791fab9] fixes #6445 (concepts 
for the JS target)
git bisect good 85b00aff56c98f4da8f70b120dc889c18791fab9
# bad: [89fa4388574872c3e56e9e5030cdfe4d758d106c] use more make conventions 
(#6789)
git bisect bad 89fa4388574872c3e56e9e5030cdfe4d758d106c
# bad: [d3394be5559c324da1c6b576d0ae9bfa966698d9] Async upcoming (#6585)
git bisect bad d3394be5559c324da1c6b576d0ae9bfa966698d9
# good: [2c584cdb3d71f0cd811e3774c49db34735040032] use make default linker 
naming convention (#6787)
git bisect good 2c584cdb3d71f0cd811e3774c49db34735040032
# first bad commit: [d3394be5559c324da1c6b576d0ae9bfa966698d9] Async 
upcoming (#6585)



Re: Memory usage skyrocketed with nim 0.18.0 (in my async tcp service test)

2018-04-10 Thread aguspiza2
If performance is the reason to avoid allocations, my suggestion is to allocate 
some initial amount which will be good for 99% of use cases and if that initial 
amount is reached and maxFD is bigger, reallocate one more time the full maxFD 
and copy from initial seq. This allocation will only affect to whoever really 
needs maxFD descriptors.


Re: Begginer's question - pointers and refs

2019-03-20 Thread aguspiza2
Use var sdl_rect : Rect If you ate going to process a lot of them sequentially.

Use var sdl_rect : ref Rect If you only handle those instances individually or 
if you use OOP or if there is a lot of fields (data) in the object


Re: Begginer's question - pointers and refs

2019-03-21 Thread aguspiza2
Yes you are right. I was thinking about type definiton while the question was 
about variable definition. Thanks.


Re: 1.0.0 is here

2019-09-24 Thread aguspiza2
It happened!!! Congrats!!! Long life to this wonderful language.


Re: Nim in business

2020-06-05 Thread aguspiza2
I have been using nim for at least 2 years, doing some simple tools (console 
and ui with libui) for the company I work for. Also I enjoy programming some 
PoCs here and there in github.

I am really happy coding with nim, that is the best nim feature, developer 
happiness.

Nim and its core libraries are mature, but on the other hand some third party 
libs still require some love.


Re: Faster and Safer Raytracing in Nim

2020-06-05 Thread aguspiza2
> i wanted to use Option[T] which were removed anyway because it made the code 
> 5x slower

Doing exactly the same thing (but taking a rust port as a reference), I also 
had the same problem with Option[T] as return type being 3.5x slower than 
(bool, T) tuple on some cases but not others. :(

Also my threaded version was quite ugly and I was unable to use "parallel for". 
I will definitelly give "weave" a ride. Thank you!

> [https://github.com/aguspiza/raytracing-nim](https://github.com/aguspiza/raytracing-nim)


Re: Simple gui app with threadpool

2020-06-14 Thread aguspiza2
If you do ^t just after spawn, you are effectively not using the worker thread 
as the UI thread is blocked waiting the worker thread to finish.

What you should do is to spawn a thread and inside the worker thread notify the 
UI thread that "t" is ready, so UI thread can then update "textArea".

This is easier said than done depending on UI library though. Most UI libraries 
have a queue where other threads can push closures to be executed by the 
main/UI thread.

Another possibility is to avoid the creation of the worker thread. If the 
library provides a way to mix async-eventlopp and UI mainloop, you can try to 
use async/await to avoid locking the main thread too.

I have not used nigui but libui (ui in nimble) provides both ways with 
functions:

  * rawui.queueMain
  * pollingMainLoop