dans.blog


The miscellaneous ramblings and thoughts of Dan G. Switzer, II

Fixing Subclipse/SVNKit in Eclipse from constantly asking for credentials

I've been working on migrating to Eclipse v3.6.1 x64, but was having a ton of issues getting Subversion/SVN support working in Eclipse. I prefer using Subclipse, so it was my goal to get that up and running because I'm used to the interface.

I originally tried using SVNKit, because I wanted to use native libraries. However, when I tried to use the SVNKit connector, every single time an SVN operation would occur it would prompt me over and over for my credentials—like it was saving them (although it was updating the .keystore.) After getting frustrate with this, I decided to just use the JavaHL libraries.

If you're using Eclipse 32-bit, then everything you need is included with the distributed versions of Subclipse. Since I'm using the 64-bit version of Eclipse, I needed to download Slik's Subversion v1.6.16 (x64). So, I closed down Eclipse and install the 64-bit client. I verified that everything was working correctly by running the javahltests.jar.

However, after restarting and configuring Subclipse to use JavaHL, I started experiencing issues with Eclipse hanging up. I'd constantly get messages like "Building workspace"—which would stay at 0% and never progress. Switching back to SVNKit was working, but the constant credential checking was driving me crazy. So, after lots of researching, I finally found a thread on authentication issues on the SVNKit mailing list. Turns out I am using NTML  and Basic authentication on our server and that was causing an issue with SVNKit.

The fix is to edit your eclipse.ini file and add this line somewhere after the "-vmargs" line:

-Dsvnkit.http.methods=Digest,Basic,Negotiate,NTLM

Depending on your configuration, you may need to tweak the order of the methods, but as soon as I restarted Eclipse with this line in my eclipse.ini everything started working like I expected.


Duplex scanning in Adobe Acrobat using a Brother MFC

I was trying to scan in a bunch of pages that had printing on both sides. Adobe Acrobat supports duplex scanning, even for scanners that don't have native support for duplex scanning. The problem is I couldn't get it to work with my Brother MFC-8820D printer/scanner. The problem appears to be using the "TW-Brother MFC-8820D USB". As soon as I switched to using the "WIA-Brother MFC-8820D" scanner driver everything starting working well.

So, if you need to perform a duplex scan on an automatic feeder that doesn't support it, here's how you do it in Adobe Acrobat 9:

  1. Go to File > Create PDF > From Scanner > Custom Scan…
  2. In the "Scanner" box, select "WIA-Brother MFC-8820D."

    image
    NOTE: You can safely ignore this message.
  3. In the "Sides" box, select "Both Sides"
  4. Configure the rest of the options as meet your needs
  5. Click "Scan"
  6. When the "Scan using Brother MFC-8820D" dialog appears, select "Document Feeder" as the "Paper source"
  7. Select the appropriate scanning options (recommend using at least 300dpi in the "Custom Settings")
  8. Make sure to choose the "Page size" that matches your paper size

    image
  9. Click "Scan"
  10. Once the scanning has finished, take the stack of paper that just went through the document feeder and put it face up in the exact order it just came out in (you feed in the last sheet first.)
  11. Acrobat will have already prompted with you the dialog to scan the other sides. From this dialog, choose the "Scan reverse sides" option:

    image
  12. Click "Ok"
  13. Repeat the steps in 6-9 to finish scanning the back side pages

That's all there is to it!


Performance issues with <cfqueryparam /> on first execution when using Microsoft SQL Server

The last couple of weeks have been interesting for me. I spent a bulk of the time tuning queries to optimize for performance and a learned a number of interesting things about Microsoft SQL Server and where some of the bottlenecks in our application actually lie.

One interesting situations I ran into was that I wasn't able to replicate some of the performance issues I was seeing in our application when I'd run the same query from Query Analyzer. Now there's a number of reasons why this could happen, but in my case I thought I was running the query in manner that mimicked what was being executed on the server—but it turns out I was missing a key step in the process and I'll get to that in a minute.

So, what was the problem? Let me explain.

Let's say we have the following query in ColdFusion. We'll call this "Method 1":

select
  Name, Email, Phone
from
  Employee
where
  DepartmentId = <cfqueryparam cfsqltype="cf_sql_integer" value="1" />

When you use the <cfqueryparam /> tag, ColdFusion translates the code into a bound parameter. This has the benefit of helping prevent SQL injections, but it often helps with performance because it allows the backend database (like Microsoft SQL Server) to cache the execution plan—which can help speed up performance. So roughly speaking, when the following query is executed on the server, it's translated to (which we'll call "Method 2":)

declare @p1 int
set @p1 = 1

select
  Name, Email, Phone
from
  Employee
where
  DepartmentId = @p1

You'll see this if you turn on ColdFusion debugging, and you can verify that even the name @p1 is used if you try manually adding a declare @p1 statement to your ColdFusion query.

However, when I'd run the bound version of my query in Microsoft SQL Server Management Studio, I was seeing dramatically different results. With a cleared cache, the "Method 1" query was running 7 times slower than "Method 2" when I'd run it in a query analyzer window. In the process of trying to troubleshoot the problem, I tried running the following in my ColdFusion query (which we'll call "Method 3":)

declare @p1 int
set @p1 = <cfqueryparam cfsqltype="cf_sql_integer" value="1" />

select
  Name, Email, Phone
from
  Employee
where
  DepartmentId = @p1

What's interesting about "Method 3" is I was now seeing the exact same performance as I was seeing when I run "Method 2" from my desktop locally. This had my confused and I knew I had to be missing something. I was obviously missing a key execution step that was missing between "Method 1" and "Method 2". What's even more confusing is that I had already been running SQL Profiler on the database server to catch the TSQL statements being executed—it's how I originally captured the query I was using in "Method  2" to run locally. The problem was I was missing a key event that I should have been logging—the RPC:Starting and RPC:Completed events.

Once I enabled the RPC:Starting event, I saw where the bottleneck was coming through.

When you use <cfqueryparam /> in SQL Server, the query isn't just translated directly into a bound statement, but instead it's first passed into the sp_prepexec system stored procedure.  So, instead of actually executing "Method 2" immediately, something like the following executed first:

declare @p1 int
set @p1=68
exec sp_prepexec @p1 output,N'@P1 int',N'select
  Name, Email, Phone
from
  Employee
where
  DepartmentId = @p1',190
select @p1

It was the call to the sp_prepexec stored procedure that was causing the huge difference in performance between "Method 1" and "Method 2". It turns out it was taking this stored procedure a lot of time to figure out the best execution plan to use before it could cache it.

To fix the problem, I just spent some time with my query (which actually ended up involving modifying some core system views) so that sp_prepexec could analyze my query and returned the cached plan faster.

So, if you're having performance issues—especially on first run execution—you might want to monitor your server and see if the bottleneck isn't with the sp_prepexec trying to figure out the best plan to cache.