    library("lme4")

# lme4 Performance Tips

- use control = `[g]lmerControl(calc.derivs = FALSE)` to turn off the time consuming derivative calculation that is performed after the optmization is finished, e.g.

    lmer(y ~ service * dept + (1|s) + (1|d), InstEval,
         control = lmerControl(calc.derivs = FALSE))

Note that this will disable some of the convergence tests, as well as (for `glmer` only) making `lme4` use a less accurate approximation to compute the standard errors of the fixed effects.

- models that only contain random effects of the form `(1|f)` use better starting values for the optimization which in tests have cut run time in certain examples by up to 50% relative to the previous default starting values. The `InstEval` fit shown above is one such example.

- `lmer` uses the `bobyqa` optimizer from the `minqa` package by default; `glmer` uses a combination of Nelder-Mead and `bobyqa`. If you are specifying the `optimx` package optimizer, note that by default `optimx` performs certain time-consuming processing at the beginning and end which can be turned off as follows (here we have specified the `"nlminb"` method but this applies to any `optimx` method):

    library("optimx")
    lmer(y ~ service * dept + (1|s) + (1|d), InstEval,
         control = lmerControl(optimizer = "optimx", calc.derivs = FALSE,
         optCtrl = list(method = "nlminb", starttests = FALSE, kkt = FALSE)))

- the `nloptr` package supports a variety of algorithms and importantly supports additional stopping criteria which can stop the optimization earlier if it believes it has reached the optimum. For many problems using these stopping criteria will result in the same solution or nearly the same solution as the default optimizer but in less time (up to 50 percent savings have been observed); however, in some cases it may stop prematurely giving suboptimal results. (In the example below omit `print_level` if output tracing is not desired and increase `maxeval` if the optimization requires more than 1000 iterations and you wish to allow it to proceed.)

    nlopt <- function(par, fn, lower, upper, control) {
        .nloptr <<- res <- nloptr(par, fn, lb = lower, ub = upper,
            opts = list(algorithm = "NLOPT_LN_BOBYQA", print_level = 1,
            maxeval = 1000, xtol_abs = 1e-6, ftol_abs = 1e-6))
        list(par = res$solution,
             fval = res$objective,
             conv = if (res$status > 0) 0 else res$status,
             message = res$message
        )
    }
    lmer(y ~ service * dept + (1|s) + (1|d), InstEval,
        control = lmerControl(optimizer = "nloptwrap", calc.derivs = FALSE))