{verbose};
return "total=$current_total user=$times[0] sys=$times[1] " .
"cuser=$times[2] csys=$times[3]";
}
return;
}
EOR
Then at the beginning of the code to check, call
[benchmark start=1]
to start the measurement. At the end
[benchmark]
will display the time used. Bear in mind that it is not precise, and
that there may be variation due to system conditions. Also, the longer
the times and the bigger the list, the better the comparison.
To see the system/user breakdown, do:
[benchmark verbose=1]
In general, "user" time measures Interchange processing time and and
the rest are indicative of the database access overhead, which can
vary widely from database to database.
Optimizations
=over 4
=item *
[PREFIX-tag] is faster than [parsed-tag]
[loop prefix=foo search="ra=yes"]
=back
[foo-data products image]
is slightly faster than
[foo-field image]
which is MUCH faster than
[data products image [foo-code]]
which is faster than
[data table=products column=image key="[foo-code]"]
[/loop]
The loop tags are interpreted by means of fast regular expression
scans of the loop container text, and fetch an entire row of data in
one query. The [data ...] ITL tag interpretation is delayed until
after the loop is finished, whereby the ITL tag parser must find the
tag, build a parameter list, then fetch the data with a separate
query. If there are repeated references to the same field in the loop,
the speedup can be 10x or more.
=over 4
=item *
Pre-fetch data with rf=field1,field2,field3 and access with
[PREFIX-param field1].
=back
mv_return_fields (otherwise known as "rf" in one-click terminology)
sets the fields that are returned from a search. Once they are
returned, they can be accessed with [PREFIX-param field]. They can
also be referenced with [PREFIX-pos N], where N is a digit
representing the ordinal position (i.e. starting with 0) in the list
of fields.
The following are equivalent:
Benchmark loop-field list: [benchmark start=1]
TIME: [benchmark]
Benchmark loop-param list: [benchmark start=1]
TIME: [benchmark]
but the second is much, much faster.
=over 4
=item *
[PREFIX-alternate N] is available for row counting and display.
=back
A common need when building tables is to conditionally close the table
row or data containers. I see a lot of:
[loop search="ra=yes"]
[calc] return '' if [loop-increment] == 1; return[/calc]
[calc] return '' if [loop-increment] % 3; return '
' [/calc]
[/loop]
Much faster, by a few orders of magnitude, is:
[loop search="ra=yes"]
[loop-change 1][condition]1[/condition][/loop-change 1]
[loop-alternate 3]
[/loop-alternate]
[/loop]
If you think you need to close the final row by checking the
final count, look at this:
[loop search="ra=yes"]
[on-match]
[/on-match]
[list]
[loop-code] |
[loop-alternate 3]
[/loop-alternate]
[/list]
[on-match]
[/on-match]
[no-match]
No match, sorry.
[/no-match]
[/loop]
This is a hundred times faster than anything you can build with
multiple [calc] tags.
=over 4
=item *
Use simple go/nogo comparisons in [if ...]
=back
Consider these two snippets:
[if scratch|value|cgi key] THEN [/if]
and:
[if scratch|value|cgi key == '1'] THEN [/if]
The first one doesn't require Perl evaluation. It simply checks to see
if the value is blank or 0, and returns true if it is anything but. Of
course this requires setting your test values to blank or 0 instead of
"No" or " " or somesuch, but it is anywhere from 20-35% faster.
Try it on the foundation demo:
---- begin test ---
Overhead:
[benchmark start=1]
[benchmark]
if scratch compare:
[benchmark start=1]
[benchmark]
if scratch compare eq 1:
[benchmark start=1]
[benchmark]
[page @@MV_PAGE@@]Again
---- end test ---
=over 4
=item *
Use [PREFIX-calc] instead of [calc] or [perl]
=back
You can execute the same code as [calc] with [PREFIX-calc], which has
two benefits:
=over 4
=item 11.
It doesn't require ITL parsing.
=item 12.
It is executed during the loop instead of after it.
=back
The [PREFIX-calc] object has complete access to all normal embedded
Perl objects like $Values, $Carts, $Tag, and such. If you want to make
a data table (i.e. "products" or "pricing") available for access
inside of it, just do:
[perl tables="products pricing"] [/perl]
prior to list start. Now you can do something like:
[loop search="ra=yes"]
[loop-calc]
$desc = $Tag->data('products', 'description', '[loop-code]');
$link = $Tag->page('[loop-code]');
return "$link $desc ";
[/loop-calc]
[/loop]
=over 4
=item *
ADVANCED: Precompile and execute with [PREFIX-sub] and [PREFIX-exec]
=back
For repetitive routines, you can achieve a considerable savings in CPU
by pre-compiling your embedded Perl code.
In the "Construct Something" demo, the bar_link() routine in
catalog_before.cfg is an example of compiling the subroutine once at
catalog configuration time.
You can also compile routines at the time of the list execution with
[item-sub routine] CODE [/item-sub]. This means only one Safe
evaluation is done -- every time the [loop-exec routine] is called, it
is done fast as a call to the routine. This can be 10 times or more
faster than separate [calc] calls, or 5 times faster than separate
[PREFIX-calc] calls.
=over 4
=item
Example:
[benchmark start=1]
=back
loop-calc:
[benchmark]
[benchmark start=1]
loop-sub and loop-exec:
[benchmark]
=over 4
=item *
ADVANCED: Execute and save with [query ...], then use an embedded Perl
routine.
=back
You can run [query arrayref=myref sql="query"], which saves the
results of the search/query in a Perl reference. It is then available
in $Tmp->{myref}. (Of course, "myref" can be any arbitrary name.)
This is the fastest possible method to display a list.
=over 4
=item
Observe:
--- begin test code ---
=back
[set waiting_for]os28004[/set]
[benchmark start=1] Embedded Perl
[/query]
[perl]
# Get the query results, has multiple fields
my $ary = $Tmp->{myref};
my $out = '';
foreach $line (@$ary) {
my ($sku, $price, $desc) = @$line;
if($sku eq $Scratch->{waiting_for}) {
$out .= "We were waiting for this one!!!!\n";
}
$out .= "sku: $sku price: $price description: $desc\n";
}
return $out;
[/perl]
-->
TIME: [benchmark]
[benchmark start=1] All loop
TIME: [benchmark]
--- end test code ---
=over 4
=item *
Other things that help:
=over 8
=item *
Avoid interpolate=1 when possible. A separate tag parser must be
spawned every time you do this. Many times people use this without
needing it.
=item *
Avoid saving large values to Scratch, as these have to be written to
the users session. If you need them only for the current page, clear
at the end by using [tmp scratch_var] contents [/tmp], which is the
same as [seti scratch_var] contents [/seti] except clears the value
before the session is written. You can also use [scratchd scratch_var]
to return the contents and delete them from the session at the same
time.
=item *
Use the [more-list] facility to break up your large searches. You can
use them in [query ....] and [loop ...] searches as well -- see the
docs.
=back
=back
=head1 Using Interchange with Oracle
Question: should we be using the DBI ChopBlanks setting for Oracle or
is Interchange trimming trailing space from CHAR fields itself?
IC daemon user should have environment variables ORACLE_HOME and
possibly NLS_LANG set.
Mark Johnson (mark@endpoint.com) wrote this trigger on TABLE_NAME to
update the MOD_TIME column on insert or update. The user must have
been granted the RESOURCE role to create triggers. Here it is:
CREATE TRIGGER tr_modtime_for_TABLE_NAME BEFORE INSERT OR UPDATE ON
TABLE_NAME FOR EACH ROW BEGIN
new.MOD_TIME := SYSDATE; END; /
=head1 Using Interchange with PostgreSQL
Make sure you have DBD::Pg installed and tested. Make sure
POSTGRES_INCLUDE and POSTGRES_LIB environment variables are set.
=head1 Using Interchange with MySQL
Permissions. test_ databases usually special.
=head1 Using Interchange with Apache
Slightly modified article posted to the old minivend-users mail list.
Minivend-users is now interchange-users.
Date: Thu, 7 Sep 2000 12:08:37 -0700
From: Bill Randle
To: minivend-users@minivend.com
Subject: Re: [mv] no /cgi-bin/storename/
On Sep 6, 5:13am, Victor Nolton wrote:
} Subject: [mv] no /cgi-bin/storename/
} ****** message to minivend-users from Victor Nolton ******
}
} I've noticed some of the catalogs I've done are not indexed well with
} the search engine, though most pages have meta tags, there is a
} robot.txt file and so on and so forth.I assume it's due to the
} cgi-bin in the url (not sure).
}
} I'd like to start having stores be like
}
} http://www.yourdomain.com/index.html
} http://www.yourdomain.com/ord/basket.html
} instead of
} http://www.yourdomain.com/cgi-bin/yourstore/index.html
} http://www.yourdomain.com/cgi-bin/yourstore/ord/basket.html
}
} how do you accomplish this? I assume it can be done somehow.
In addition to using mod_minivend, previosuly suggested, you can do this
with Apache rewrite rules in the VirtualHost directive for yourdomain.com:
ServerAdmin support@mainhost.com
DocumentRoot /home/httpd/html/yourstore
ServerName www.yourdomain.com
ErrorLog logs/yourdomain-error_log
CustomLog logs/yourdomain-access_log common
ScriptAlias /cgi-bin/ "/home/httpd/cgi-bin/"
RewriteEngine On
RewriteRule ^$ /cgi-bin/yourstore/index.html [PT,L]
RewriteRule ^/$ /cgi-bin/yourstore/index.html [PT,L]
RewriteRule ^/index\.html$ /cgi-bin/yourstore/index.html [PT,L]
RewriteRule ^/cgi-bin/yourstore/.* - [PT,L]
RewriteRule ^/.*images/.* - [PT,L]
RewriteRule ^/(.*) /cgi-bin/yourstore/$1 [PT,L]
I just did this for a client and it works quite well (as long as you're
using a fairly recent version of Apache as your webserver).
-Bill
=head1 Perl/Interchange FAQ
=head2 Cameron Prince's local Perl installation how-to
=over 4
=item 13.
Login as user. In this example, we'll call the user bob. Bob's home
directory is /home/bob.
=item 14.
Get the perl tarball and extract it in /home/bob. (tar -xzvf
perl-5.6.0.tar.gz)
=item 15.
Create a directory for the local perl. (mkdir /home/bob/local-perl)
=item 16.
Compile perl.
=over 8
=item 17.
cd perl-5.6.0
=item 18.
sh Configure
=item 19.
Choose all the defaults until you get to: "Directories to use for
library searches?" Here you want to enter the new local perl path, as
well as the defaults. So you should enter something like:
/home/bob/local-perl/lib /usr/local/lib /lib /usr/lib
=item 20.
Continue choosing defaults till you get to: "Any additional ld flags
(NOT including libraries)?" This should be: -L/home/bob/local-perl/lib
=item 21.
Continue choosing defaults till you get to: "Installation prefix to
use? (~name ok)" This should be: /home/bob/local-perl
=item 22.
Choose all defaults till you get to: "Directory
/home/bob/local-perl/bin doesn't exist. Use that name anyway?" Enter
y.
=item 23.
Continue choosing defaults till you get to: "Do you want to install
perl as /usr/bin/perl?" Enter n.
=item 24.
Continue choosing defaults till you get to: "Directory
/home/bob/local-perl/bin doesn't exist. Use that name anyway?" Enter
y.
=item 25.
Directory /home/bob/local-perl/bin doesn't exist. Use that name
anyway? Enter y.
=item 26.
Continue taking defaults till you return to a prompt.
=item 27.
make
=item 28.
make test
=item 29.
make install
=back
=item 30.
/home/bob/local-perl/bin/perl -v
You should see: This is perl, v5.6.0
=item 31.
edit /home/bob/.bash_rc
Change: PATH=$PATH:$HOME/bin
To: PATH=/home/bob/local-perl/bin:$PATH:$HOME/bin
=item 32.
Logout and log back in.
=item 33.
which perl
You should see: ~/local-perl/bin/perl or /home/bob/local-perl/bin/perl
=item 34.
perl -MCPAN -e 'install Bundle::Interchange'
Keep running this until you see:
MD5 is up to date.
=back
MIME::Base64 is up to date.
URI is up to date.
Net::FTP is up to date.
MIME::Base64 is up to date.
Digest::MD5 is up to date.
HTML::Tagset is up to date.
HTML::Parser is up to date.
HTML::HeadParser is up to date.
LWP is up to date.
Term::ReadKey is up to date.
Term::ReadLine::Perl is up to date.
Business::UPS is up to date.
SQL::Statement is up to date.
Storable is up to date.
DBI is up to date.
Safe::Hole is up to date.
You may need to get the modules via ftp and install them by hand. For
instance, during the test used to create this document, I had to get
URI and LWP and install by hand before everything reported that it was
up to date. To do this, follow these steps:
=over 4
=over 8
=item 35.
ftp ftp.cpan.org
=item 36.
cd /CPAN/modules/by-module/URI
=item 37.
bin
=item 38.
get URI-1.10.tar.gz
=item 39.
quit
=item 40.
tar -xzvf URI-1.10.tar.gz
=item 41.
cd URI-1.10
=item 42.
perl Makefile.pl
=item 43.
make
=item 44.
make test
=item 45.
make install
=back
=back
Use the same basic steps for any module not properly installed by
using perl -MCPAN -e 'install Bundle::Interchange'
Now, install Interchange as normal.
=head1 Other / Miscellaneous Questions
=head2 What does the "mv_pc" variable added to every URL mean?
It can be used to prevent the users' browser from caching dynamic
content, or, combined with the session 'id', it can make every link
unique so that the users behind a proxy (e.g. AOL) will not have
dynamic content cached.
=head2 Where is process.html?
(Answered by Ed LaFrance & Kevin Walsh)
It is in the guts of Interchange. The [process] form action tells
interchange to process the posted form vars according to the action
set with mv_todo. The processing is not associated with any specific
target page (though a page to display when processing is complete can
be specified with mv_nextpage), so Interchange just builds a target
URL that ends in an 'imaginary' page called 'process.html'.
There are other ways to handle a form post. For more information, see
the Form Actions section Interchange Templates manual.
Basically, when you submit a