nim-lang / Nim

Nim is a statically typed compiled systems programming language. It combines successful concepts from mature languages like Python, Ada and Modula. Its design focuses on efficiency, expressiveness, and elegance (in that order of priority).
https://nim-lang.org
Other
16.44k stars 1.47k forks source link

Very slow compiling when computing big constant arrays #19075

Closed tsoj closed 1 year ago

tsoj commented 2 years ago

The following example takes almost 4 minutes to compile on an i5-8250U.

Example

const size = 50_000

const stuff = block:
    var a: array[size, int]
    a

const zeugs = block:
    var zeugs: array[size, int]
    for i in 0..<size:
        zeugs[i] = stuff[i]
    zeugs

echo zeugs[0]

Current Output

$ time nim c --run main.nim
Hint: used config file '/home/tsoj/.choosenim/toolchains/nim-#devel/config/nim.cfg' [Conf]
Hint: used config file '/home/tsoj/.choosenim/toolchains/nim-#devel/config/config.nims' [Conf]
.........................................................
CC: stdlib_digitsutils.nim
CC: stdlib_assertions.nim
CC: stdlib_dollars.nim
CC: stdlib_io.nim
CC: stdlib_system.nim
CC: main.nim
Hint:  [Link]
Hint: gc: refc; opt: none (DEBUG BUILD, `-d:release` generates faster code)
26631 lines; 237.035s; 145.992MiB peakmem; proj: /home/tsoj/Dokumente/Projects/nim-slow-compile-test/main.nim; out: /home/tsoj/Dokumente/Projects/nim-slow-compile-test/main [SuccessX]
Hint: /home/tsoj/Dokumente/Projects/nim-slow-compile-test/main  [Exec]
0

________________________________________________________
Executed in  237.21 secs    fish           external
   usr time  236.79 secs    1.02 millis  236.79 secs
   sys time    0.23 secs    0.59 millis    0.23 secs

Expected Output

I would expect the compilation to take less time. The following example compiles in less than one second, despite having equally big constant arrays:

import random

const size = 50_000

const stuff = block:
    var a: array[size, int]
    a

const zeugs = block:
    var zeugs: array[size, int]
    for i in 0..<size:
        zeugs[i] = i
    zeugs

echo stuff[rand(0..<size)]
echo zeugs[rand(0..<size)]

Additional information

$ nim -v
Nim Compiler Version 1.7.1 [Linux: amd64]
Compiled at 2021-10-31
Copyright (c) 2006-2021 by Andreas Rumpf

git hash: 2bda4a30a6b12dd0840dc347e454e54fe26721e7
active boot switches: -d:release
jackhftang commented 2 years ago

Not a solution, but to mitigate the problem, move the const stuff outside for loop.

const size = 50_000

const stuff = block:
    var a: array[size, int]
    a

const zeugs = block:
    let inline = stuff
    var zeugs: array[size, int]
    for i in 0..<size:
        zeugs[i] = inline[i]
    zeugs

echo zeugs[1]