[racket] Performance. How to disable contract checks?

380 views
Skip to first unread message

Roman Klochkov

unread,
Jun 2, 2014, 3:43:39 PM6/2/14
to Racket Users List
Is there a way to disable all contract checks?

Suppose, I debugged my program and sure that it is reliable. I disable debugging, but as I understand, contracts are still checked in every function.
But I want to maximize the performance of my program. Is there a way to do that or I have to manually hack racket/contract/base to do that?


--
Roman Klochkov

Matthias Felleisen

unread,
Jun 2, 2014, 3:50:32 PM6/2/14
to Roman Klochkov, Racket Users List
No.

;; ---

Programmers who disable assertion checking as they are deploying software are like people who wear life vests on land when they learn about the theory of sailing and take them off as soon as they board the boat for practical exercises on the water. -- somebody famous

;; ---

You will need to define a version of provide and/or contract-out that throws away contracts based on a switch.

Or you check out option contracts and use those.

-- Matthias


____________________
Racket Users list:
http://lists.racket-lang.org/users

Roman Klochkov

unread,
Jun 2, 2014, 4:22:09 PM6/2/14
to Matthias Felleisen, Racket Users List
The problem is that, when debbugging, contract should be precise. For example, insert-in-sorted-queue may check that queue is orted before and after the function.
But inserting the element is O(log n) and testing will be O(n).

option contracts -- 1) unstable 2) should be turned off and on individually.

For quick hack, I'll simply redefine contract-out and recompile all. But I propose something like two contracts: for debug and production modes. 


Mon, 2 Jun 2014 15:49:05 -0400 от Matthias Felleisen <matt...@ccs.neu.edu>:
--
Roman Klochkov

Matthias Felleisen

unread,
Jun 2, 2014, 4:26:27 PM6/2/14
to Roman Klochkov, Racket Users List

Yes, option contracts should move into the mainstream library.

The point of option contracts is that you can program which parts you want to run, how often, and which parts you want turned off. I urge you to build your abstraction on top of option contracts. If you do, please report back on your experience.

-- Matthias

Robby Findler

unread,
Jun 2, 2014, 4:35:55 PM6/2/14
to Matthias Felleisen, Racket Users List
+1

Robby

Daniel Prager

unread,
Jun 3, 2014, 12:40:11 AM6/3/14
to Roman Klochkov, Racket Users List, Matthias Felleisen
> I propose something like two contracts: for debug and production modes.

Eiffel compilers implement a sliding scale of contract-checking, something like:
  1. Check nothing [naive]
  2. Check pre-conditions only [good for production - quick]
  3. Check pre- and post-conditions only [can be slow]
  4. Check pre- and post-conditions and invariants [van be very slow]
[Loop and ad hoc assertions would have been in there too.]

Post-conditions and invariants can be *very* expensive to check, but are great when debugging.

Pre-condition checking is typically cheap, and quickly tells you when trusted code is being called with bad arguments.

Recommeneded development practice was to start with all contracts checked, and as one's code iterated towards trustworthiness turn down the checking-level (but leave pre-conduitions on) and enjoy the huge speed boost.

There's value in being able to control checking on a per module basis, essentially doing deep checks on newer / less-tested / less-trusted parts of the system.

How does the picture change with higher-order contracts and checking at module boundaries?

Dan



____________________
  Racket Users list:
  http://lists.racket-lang.org/users




--
Daniel Prager
Agile/Lean Coaching, Software Development and Leadership
Twitter: @agilejitsu 

Matthias Felleisen

unread,
Jun 3, 2014, 7:50:27 AM6/3/14
to Daniel Prager, Racket Users List, Christos Dimoulas

You can program these scenarios with option contracts; see comparison in paper. Perhaps it's time to write this up as a chapter for the Guide. 

Roman Klochkov

unread,
Jun 3, 2014, 12:26:35 PM6/3/14
to Matthias Felleisen, Racket Users List, Christos Dimoulas
There should be _standard_ check-modes. With global variable (or better compile-mode).

Because, I can in my own libraries make this 4 or even more modes. But I use 3d-party or standard library. And I cannot rewrite them all to my 4 modes.
Even if another developer will use the same idea, he or she will have own modes and own variable to set them.


Tue, 3 Jun 2014 07:47:37 -0400 от Matthias Felleisen <matt...@ccs.neu.edu>:
--
Roman Klochkov

Matthias Felleisen

unread,
Jun 3, 2014, 12:49:30 PM6/3/14
to Roman Klochkov, Racket Users List, Christos Dimoulas

Your mail calls for a philosophical answer. If this were Eiffel, you would be correct.

But Racket is not Eiffel:
-- we are not a tools company that sells a language
-- we spent our own time on a maintenance effort that goes above and beyond our jobs
-- and we don't provide a standard language (meant to make developers happy and its creators famous and wealthy).

Racket is a programming language programming language [not a typo]. We wish to go beyond conventional features. When it comes to contracts, this means we wish to provide (1) higher-order contracts so that we cover the full spectrum of linguistic features and (2) a programmable toolbox so that programmers can create their own favorite idioms -- above and beyond the stuff available in standard languages.

We fully understand that expanding the horizons of the language puts some burden on programmers. Every programmer may have to develop his own techniques and tools and idioms for our new features. We balance this burden with a catalog-driven on-line library, where programmers can register little more than a github URL to share such libraries.

With apologies for the extra burden and the non-technical answer -- Matthias

Roman Klochkov

unread,
Jun 3, 2014, 1:18:13 PM6/3/14
to Matthias Felleisen, Racket Users List, Christos Dimoulas
Will you accept patch for this, if I'll write it?

(contract-out ...) will have (id debug-contract-expr production-contract-expr) instead of (id contract-expr) in syntax
There will be global phase-1 variable
contract-mode : (or/c 'nothing 'production 'pre 'pre-and-past 'all) = 'all

nothing -- no checks
production -- use production contract if present, otherwise check only pre-condiction
pre -- check only pre-condiction
pre-and-post -- check pre and post conditions
all -- current behavior




Tue, 3 Jun 2014 12:47:18 -0400 от Matthias Felleisen <matt...@ccs.neu.edu>:
--
Roman Klochkov

Jay McCarthy

unread,
Jun 3, 2014, 2:01:04 PM6/3/14
to Roman Klochkov, Racket Users List, Christos Dimoulas, Matthias Felleisen
Roman,

This approach is unlikely to work out due to separate compilation. Module A can't really affect how module B gets compiled. Your contract-mode appears to be trying to do such a thing.

So it is not clear where the decision on compile mode is made. If it is inside a module, then why not turn them off to remove contracts that enforce things like security?

Something like this seems to be "outside" of the language. I have thought that the right place would be inside the compiler or something like the demodularizer. Further, I imagine a general mechanism that turns

(if p e (error ...))

into just

e

Instead of baked-in cooperation with and knowledge of contracts.

Jay

Sent from my iPhone

Roman Klochkov

unread,
Jun 3, 2014, 3:18:42 PM6/3/14
to Jay McCarthy, Racket Users List, Christos Dimoulas, Matthias Felleisen
Now we have t least errortrace (http://docs.racket-lang.org/errortrace/index.html) with the same approach.

One should require (or set variable) at top level, then remove *.zo and recompile the module.

I even may make it as a simple phase-0 variable and replace arrow-val-first.rkt/check-post-condition with

(define (check-post-condition blame neg-party val thunk)
  (unless (or (skip-post-check? contract-mode) (thunk))
    (raise-blame-error
     blame #:missing-party neg-party val
     "#:post condition failure")))

Then it will be still checked, but the post check will be almost no-op. Then no recompilation needed. And one may even inside module control contract usage with particular call.

Main problem is: this should be mainstream behaviour. Like using contract-out now. I cannot simply make my own drop-in replacement for racket/contract -- nobody will use it.

Tue, 3 Jun 2014 13:58:59 -0400 от Jay McCarthy <jay.mc...@gmail.com>:
--
Roman Klochkov

Jay McCarthy

unread,
Jun 3, 2014, 3:27:22 PM6/3/14
to Roman Klochkov, Racket Users List, Christos Dimoulas, Matthias Felleisen
I think the phase-0 approach would leave in the cost of constructing the wrappers and blame information in addition to inhibiting inlining. 


Jay

Sent from my iPhone

Roman Klochkov

unread,
Jun 3, 2014, 3:29:57 PM6/3/14
to Jay McCarthy, Racket Users List, Christos Dimoulas, Matthias Felleisen
On the other side of the question:
one may simply make something like

(module lib/unsafe racket/base
   (provide foo bar baz)
   ...)

(module lib racket/base
  (require lib/unsafe)
  (provide/contract
     (foo (-> integer? any))
     (bar (-> list? list?)))

(module lib/debug racket/base
  (require lib/unsafe lib/checks)
  (provide/contract
     (foo (->i [x integer?] [result (complicated-check? result]))
     (bar (-> sorted-integer-list? sorted-integer-list?)))

To debug simply use */debug, and for max speed */unsafe... I need to think about it.




Tue, 3 Jun 2014 13:58:59 -0400 от Jay McCarthy <jay.mc...@gmail.com>:
Roman,


--
Roman Klochkov

Matthew Butterick

unread,
Jun 3, 2014, 8:21:38 PM6/3/14
to Racket list
You can use `module+` to automatically create a submodule that invokes your contracts, while the main module ignores them.

Then if you want speed, you can import your module as 

(require module-name) 

or if you want safety, you can import as

(require (submod module-name safe))

Here's how I did it:

Matthias Felleisen

unread,
Jun 3, 2014, 8:41:11 PM6/3/14
to Roman Klochkov, Jay McCarthy, Racket Users List, Christos Dimoulas

Yes, I have a suite of half-finished macros that do something like this. I don't have the time to extract these macros from a project and create an independent library. Sorry. 

Yes, I proposed something like this on 'dev' for types. You can have one submodule that exports typed versions and another one that exports untyped versions to avoid the types->contract compiler and the associated boundary overhead. 

-- Matthias

Saša Janiška

unread,
Nov 18, 2019, 7:15:05 AM11/18/19
to racket...@googlegroups.com
On Tue, 3 Jun 2014 12:47:18 -0400
Matthias Felleisen <matt...@ccs.neu.edu>
wrote:

Hello Matthias,

> Your mail calls for a philosophical answer. If this were Eiffel, you
> would be correct.

Recently I stumbled upon some application discovering it is written in Eiffel
and I had become curious to investigate a bit about the language
seeing DbC as interesting concept...

>
> But Racket is not Eiffel:
> -- we are not a tools company that sells a language
> -- we spent our own time on a maintenance effort that goes above and
> beyond our jobs -- and we don't provide a standard language (meant to
> make developers happy and its creators famous and wealthy).
>
> Racket is a programming language programming language [not a typo].
> We wish to go beyond conventional features. When it comes to
> contracts, this means we wish to provide (1) higher-order contracts
> so that we cover the full spectrum of linguistic features and (2) a
> programmable toolbox so that programmers can create their own
> favorite idioms -- above and beyond the stuff available in standard
> languages.

...but your (philosophical) anwer does answer all the possible
doubts which language to use for the project. ;)

Thanks a lot for your input!!


Sincerely,
Saša

--
As a blazing fire turns firewood to ashes, O Arjuna, so does the
fire of knowledge burn to ashes all reactions to material activities.


Reply all
Reply to author
Forward
0 new messages