Mar 31

VFRHelper 1.2.4[2010.3.31更新][连接修复]

3.31:这次更新是@lititude的feature request,意见感谢!

 TFMOVR

      
VFRHelper - MKV章节制作工具(不要问我为什么叫这个名字。。。
更新日志:
1.2.4
(*)FFMS更新到2.13
(*)点击视频进度条可直接跳转到指定位置
(+)TFMOverrideEditor可使用AVS脚本作为视频
(*)其它改动略
1.2.3
(*)修复部分MKV章节文件无法加载的问题
(*)Bug修复
1.2.2
(*)FFMpegSource更新到2.0 beta 4
1.2.1
(*)Bug修复及易用性改动
1.2.0
(+)新增插件框架,章节编辑器改为插件形式
(+)新增插件:TFM OVR文件编辑器
(*)一些小改动
1.1.1
(+)新增功能:按时间跳转
1.1.0
(*)视频代码重写,速度提高
(+)FFMpegSource更新到2.0 beta 3,现在打开非avs文件不需要AviSynth了
(+)使用FFMpegSource打开文件时,在标题栏显示索引进度
(+)新增支持读取VFR MP4的Timecode
(*)一些小改动及bug修复
1.0.2
(+)新增1个快捷键
(+)FFMpegSource更新到1.19
(-)使用按钮能够正常打开非AVI文件了
1.0.1
(+)新增2个快捷键
(+)快捷键现在可以自定义
(*)退出程序时会询问是否保留临时文件(如果有的话)
1.0.0
初始版本
功能:
*可视化制作MKV章节文件
*支持打开TXT及XML格式的章节
*支持VFR(只支持V2的Timecode,如果是V1的话请预先转换好
*查看V2 Timecode各帧的时间(附带功能
*编辑TFM的OVR文件
支持的视频格式:
AVI
AVS
MKV
MP4
FLV
MKV、MP4及FLV需要FFMS2.dll支持。
快捷键说明:
方向键左/右					跳转至上一个/下一个关键帧
Shift+方向键左/右			跳转至上一帧/下一帧(注意:跳转的时候会忽略空帧)
方向键上/下					上一个/下一个章节
空格								设置当前选中章节的时间
F12									解码速度测试(可以无视
快捷键可以自定义,使用记事本之类的工具编辑keymappings.xml即可。按键名称可查看KeyNames.htm获得。
一些注意事项:
*章节文件的格式无法被改变(即只能保存为打开时候的格式)
*新建章节只支持TXT格式

 

下载:

完整包(内附源代码)

系统需求:

.Net Framework 2.0

Windows(废话

AviSynth(可选

源代码编译需求VS2008

Mar 24

gcc编译基本要点

弄了一上午终于开始make gcc了。。。于是记录一下要点。。。

0、在/etc/profile加上以下设置可减少很多麻烦事:

export CFLAGS='-I/usr/local/include'

export CPPFLAGS='-I/usr/local/include'

export LDFLAGS='-L/usr/local/lib'

1、必须库及编译顺序:gmp –> mpfr –> polylib –> ppl –> cloog-ppl

2、必须库configure的时候全部用–enable-shared –disable-static

特例:

ppl:需要加上LDFLAGS=’-no-undefined -L/usr/local/lib’,否则编译出来的还是静态库,后面编译cloog-ppl的时候会出现一大堆undefined reference。这个错误折磨了我很久。。。

cloog-ppl:需加上–with-ppl=/usr/local/,这个是编译gcc的要求

3、必须在gcc源代码目录树的外面新建一个文件夹,并在里面configure及make(请允许我吐槽。。。这是什么鬼规定。。。

3-26更新:

(前面的写完之后又折腾了一整天,编译gcc果然非常ep。。。

4、mingw目录必须在分区根部(如D:\MingW),不然会出现很奇怪的问题。。。

5、gcc在configure的时候要显式指定1里面4个库的位置,否则stage2会出错

6、cloog-ppl也要加上ppl的ldflags,不加的话编译出来的还是静态库

7、编译libgomp的时候有可能会出现ar.exe的错误,把其它目录的libtool复制到libgomp里面覆盖掉继续make就可以。这个操作可能要重复5次以上。。。

大概就是这样了。。。另外感谢squallatf同学的大力协助,很多问题都是他解答的,让我少走很多弯路。。。

Mar 12

Entity Framework CompiledQuery某bug及workaround

最近的项目里面用到了EF,某个功能需要做大量查询,性能很糟糕。

于是尝试把查询改成CompiledQuery,结果发现使用后性能反而下降了。祭出Profiler,结果发现:

image

有1/3的查询都调用了System.Data.Metadata.Edm.ObjectItemCollection.LoadAllReferencedAssemblies这个方法,时间基本全部耗在上面了。

看名字猜测,这方法似乎是用来加载查询引用的程序集的,但是理论上程序集只需要加载一次而已,感觉是EF内部的缓存机制出了问题。

Reflector反编译之,发现以下代码段:

   1: ' System.Data.Objects.CompiledQuery

   2: Private Function Invoke(Of TArg0 As ObjectContext, TArg1, TArg2, TArg3, TResult)(ByVal arg0 As TArg0, ByVal arg1 As TArg1, ByVal arg2 As TArg2, ByVal arg3 As TArg3) As TResult

   3:     EntityUtil.CheckArgumentNull(Of TArg0)(arg0, "arg0")

   4:     arg0.MetadataWorkspace.LoadAssemblyForType(GetType(TResult), Assembly.GetCallingAssembly)

   5:     Return Me.ExecuteQuery(Of TResult)(arg0, New Object() { arg1, arg2, arg3 })

   6: End Function

   7:  

   8: ' System.Data.Metadata.Edm.MetadataWorkspace

   9: Friend Sub LoadAssemblyForType(ByVal type As Type, ByVal callingAssembly As Assembly)

  10:     Dim items As ItemCollection

  11:     If Me.TryGetItemCollection(DataSpace.OSpace, items) Then

  12:         Dim items2 As ObjectItemCollection = DirectCast(items, ObjectItemCollection)

  13:         If (Not items2.LoadAssemblyForType(type) AndAlso (Not callingAssembly Is Nothing)) Then

  14:             items2.LoadAllReferencedAssemblies(callingAssembly)

  15:         End If

  16:     End If

  17: End Sub

  18:  

  19: ' System.Data.Metadata.Edm.ObjectItemCollection

  20: Friend Function LoadAssemblyForType(ByVal type As Type) As Boolean

  21:     Dim flag As Boolean = ObjectItemCollection.LoadAssemblyFromCache(Me, type.Assembly, False)

  22:     If type.IsGenericType Then

  23:         Dim type2 As Type

  24:         For Each type2 In type.GetGenericArguments

  25:             flag = (flag Or Me.LoadAssemblyForType(type2))

  26:         Next

  27:     End If

  28:     Return flag

  29: End Function

  30:  

  31:  

  32:  

  33: Private Shared Function LoadAssemblyFromCache(ByVal objectItemCollection As ObjectItemCollection, ByVal [assembly] As Assembly, ByVal loadReferencedAssemblies As Boolean) As Boolean

  34:     Dim flag As Boolean

  35:     If ObjectItemCollection.ShouldFilterAssembly([assembly].FullName) Then

  36:         Return False

  37:     End If

  38:     

  39:     ' skipped

  40: End Function

  41:  

  42: Friend Shared Function ShouldFilterAssembly(ByVal fullName As String) As Boolean

  43:     Return fullName.EndsWith("PublicKeyToken=b77a5c561934e089", StringComparison.OrdinalIgnoreCase)

  44: End Function

 

b77a5c561934e089是M$程序集的PublicKeyToken,看到这里基本就明白了。CompiledQuery执行的时候会加载调用方程序集引用的所有程序集,以TResult及其泛型参数作为键来缓存(具体的流程没有深入研究,可能不太准确)。在取缓存的时候如果键类型是M$程序集里面的话就会直接跳过。

但是取缓存的代码有个bug,如果TResult和它的泛型参数全部是M$程序集里面的类型的话,LoadAssemblyForType就会返回False,导致每次查询都会调用LoadAllReferencedAssemblies,大幅拖慢速度。

项目里面的符合条件的查询有2个,刚好是1/3,分别是返回IQueryable(Of Integer)和IQueryable(Of Decimal)。知道原因之后解决方法就很简单了。新建一个容器类如PrimitiveHolder(Of T),然后把CompiledQuery里面的TResult改成容器类就可以了,如IQueryable(Of PrimitiveHolder(Of Integer))和IQueryable(Of PrimitiveHolder(Of Decimal))。

(话说这几天弄项目一直在捣鼓EF,发现问题真的很多。。。果然M$的东西第一个版本都是这样么。。。希望.Net 4.0的EF会有改进。。。

Mar 04

小技巧:在VB中使用Module模拟C#的静态类

VB中建立助手类一般有两种方法,一是使用Module,另一个是用Class然后把成员全部声明为Shared。

不过这两种方法都有缺点,第一种方法由于VB的特性会污染命名空间;第二个需要显式声明Shared,如果以后要把代码转换到实例方法会很麻烦。(还有个问题是我经常忘记加,在调用成员失败的时候才想起来。。。)

最近发现了一个很简单的方法,能把两者的优点结合起来,范例:

   1:  

   2: Namespace Utils

   3:     <HideModuleName()> _

   4:     Module Utils

   5:         Public Sub XXX()

   6:             ' ...

   7:         End Sub

   8:     End Module

   9: End Module

  10:  

  11: ' 使用方法时Import ExcelUtils的上层命名空间即可

  12: Utils.XXX()

HideModuleName属性使VS的Intellisense在显示Utils命名空间的时候不显示类名,这样这个命名空间里面就只有Utils类的成员了,间接实现了静态类的效果。