标题:C写档速度问题
只看楼主
yz1025
Rank: 8Rank: 8
等 级:蝙蝠侠
威 望:6
帖 子:473
专家分:915
注 册:2012-10-26
结帖率:97.67%
已结贴  问题点数:20 回复次数:6 
C写档速度问题
我有一支VB6程序连续调用VC6编译的DLL档,再由VB6的介面计算每次写二进制档的执行速度,
发现不知道为什么,每次写档前约30次,花费时间几乎为之后写档速度的 2倍,
无论档案是新开的或是Append的。想不出是什么原因而决定这个结果?

VB6 :
程序代码:
Option Explicit

Private Declare Function Write1 Lib "Write1.dll" (ByVal FN As String, ByVal iCount As Long, ByVal A As Long) As Long

Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Declare Function GetSystemDirectory Lib "kernel32" Alias "GetSystemDirectoryA" (ByVal lpbuffer As String, ByVal nSize As Long) As Long
Private Declare Function SetCurrentDirectory Lib "kernel32" Alias "SetCurrentDirectoryA" (ByVal lpPathName As String) As Long
Private Declare Function QueryPerformanceCounter Lib "kernel32" (X As Currency) As Boolean
Private Declare Function QueryPerformanceFrequency Lib "kernel32" (X As Currency) As Boolean

Dim S1 As Currency, S2 As Currency, f As Currency, t1 As Currency   
Dim iSize(25600) As Long, Myindex As Integer, iTime(25600) As Currency, iCount As Integer

Private Sub Form_Activate()
Dim i As Integer

    List1.Clear
    List2.Clear
    
    For i = 0 To 25600
        List1.AddItem i & " : " & iSize(i), i
        List2.AddItem i & " : " & iTime(i), i
    Next i
    
End Sub

Private Sub Form_Load()
Dim i As Integer, A() As Byte, j As Integer, k As Long
    
    For i = 0 To 25600
    
        ReDim A(256)
        For j = 0 To 256
            A(j) = i Mod 256
        Next j
        
        Call QueryPerformanceFrequency(f)      
        Call QueryPerformanceCounter(S1)       
        
        Call WaitEXE(Write1("C:\AAA.std", 256, VarPtr(A(0))), iCount)
        
        Call QueryPerformanceCounter(S2)       
        
        iTime(iCount) = (S2 - S1) / f
        iCount = iCount + 1
    Next i
    
End Sub

Private Sub WaitEXE(k As Long, m As Integer)
    Do
        If k = 1 Then
            iSize(m) = k
            Exit Do
        End If
        MyDoEvents 100
    Loop
End Sub

Private Function MyDoEvents(Optional ByVal dwMilliseconds As Long = 1)

   MyDoEvents = DoEvents()
   Sleep dwMilliseconds
   
End Function


VC6 :
程序代码:
// Write1.cpp : Defines the entry point for the DLL application.
//

#include "stdafx.h"
#include <stdio.h>

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
                     )
{
    return TRUE;
}

int _stdcall Write1(char *FN, int Count, int *A)
{
    int i=0,nwDataSize=0;
    long size=0;

    FILE *stream = fopen( FN, "ab+" );

    if( stream != NULL )
    {
        fseek(stream,0,SEEK_END);
        size=ftell(stream);
        nwDataSize =fwrite(&A[0],sizeof (char), Count, stream);
    }
    else
        return 0;

    fclose(stream);

    return 1;
}


0.0059秒 <.....> 0.0021秒

[此贴子已经被作者于2020-4-29 14:03编辑过]

搜索更多相关主题的帖子: Long Sub ByVal Function Private 
2020-04-29 13:39
yz1025
Rank: 8Rank: 8
等 级:蝙蝠侠
威 望:6
帖 子:473
专家分:915
注 册:2012-10-26
得分:0 
还有另一个问题 :

当VB将内存起始地址传给VC后,若VB立即释放该阵列空间,
那该空间控制权是否当下已转交在VC手上?

或是VC必须另开一个阵列空间做一次memcpy(),
将原本VB的阵列资料被另存到VC开的阵列空间后,
原本VB阵列资料才会在VC的新空间被系统保护?

系统上是如何看待,
不同程式间的资料转移过程中的内存空间所有权的?

不要投我
2020-04-30 12:16
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:432
帖 子:10064
专家分:41463
注 册:2014-5-20
得分:0 
int _stdcall Write1(char *FN, int Count, int *A)
{
......
    nwDataSize =fwrite(&A[0],sizeof (char), Count, stream);
问问,从这两句看 A是int,为何用sizeof(char)作计量单位
2020-04-30 16:17
wmf2014
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:216
帖 子:2039
专家分:11273
注 册:2014-12-6
得分:20 
回复 3楼 吹水佬
指针参数就是个接收地址的作用,指针类型没实际意义。他vb里定义的是byte类型,长度就只有256字节。
关于楼主的问题,我的理解是:
1,关于写入速度问题。在数据量没变化、代码执行没其他分支的情况下,前后写入有速度变化,应该是系统自动优化的作用,看他写入的数据是重复写入0-255,应该是数据写入缓存发挥作用了,看上去写完了,实际上文件写入只是移交了控制权,硬盘自己在后台自动写入造成的错觉。
2,关于vb提交后释放内存的问题,实际上是在数据写入函数返回之前vb是无法释放内存的(楼主定义的是变长byte类型数组,并没有这类释放机制,除非是new的对象),即使使用了线程共享某一存储空间,也不能够轻易被释放,系统会检测所有线程不再用这个空间才彻底释放。

能编个毛线衣吗?
2020-04-30 16:45
yz1025
Rank: 8Rank: 8
等 级:蝙蝠侠
威 望:6
帖 子:473
专家分:915
注 册:2012-10-26
得分:0 
以下是引用吹水佬在2020-4-30 16:17:45的发言:

int _stdcall Write1(char *FN, int Count, int *A)
{
......
    nwDataSize =fwrite(&A[0],sizeof (char), Count, stream);
问问,从这两句看 A是int,为何用sizeof(char)作计量单位


因为VB6传过来的byte阵列起始地址(Long),而C是接收该指针(int),
而VB6也传了该byte阵列大小,所以C才能知道该内存中原本VB6所定义的阵列全部资料。

只是不确定VB6传指针的动作,是否也代表内存阵列资料控制权移交,若VB6传完后立即ReDim,
该内存资料是否仍受C程式的保护,所以保险一点又再加一段。

unsigned char *TitleTemp = new unsigned char[Count];
memcpy(&TitleTemp[0],&A[0],Count);

如果能确定有控制权移交,C就不用再开阵列浪费内存空间。

不要投我
2020-05-05 16:38
yz1025
Rank: 8Rank: 8
等 级:蝙蝠侠
威 望:6
帖 子:473
专家分:915
注 册:2012-10-26
得分:0 
话说发现ab+的作用跟fseek(stream,0,SEEK_END);重复,好像可以省掉这一段代码。

只是现在需求是C会不断的被VB6呼叫写入同一档案,但是该档案可能会被其他未知程式锁定,
导致无法被写入,所以要做暂时写入到新开的第二备分档,等原档解锁后,
再一次全部合并所有资料,而资料有顺序性。

但是考虑到若第二备分档也被锁,又得再加第三备份档,依此类推,
最后还要倒着合并回来成一个档案,实在不知道该怎么写。

而程式需求者在VB6内无法解决档案被锁定后无法写入问题,
想透过第三方程式DLL去处理,要我写个递回去解决。


VB6好像也是有档案在锁定状态时,仍能写入的代码,两边同时实验。
Open "FN" For Output Lock Write as #1

不要投我
2020-05-05 17:06
yz1025
Rank: 8Rank: 8
等 级:蝙蝠侠
威 望:6
帖 子:473
专家分:915
注 册:2012-10-26
得分:0 
以下是引用wmf2014在2020-4-30 16:45:03的发言:

指针参数就是个接收地址的作用,指针类型没实际意义。他vb里定义的是byte类型,长度就只有256字节。
关于楼主的问题,我的理解是:
1,关于写入速度问题。在数据量没变化、代码执行没其他分支的情况下,前后写入有速度变化,应该是系统自动优化的作用,看他写入的数据是重复写入0-255,应该是数据写入缓存发挥作用了,看上去写完了,实际上文件写入只是移交了控制权,硬盘自己在后台自动写入造成的错觉。
2,关于vb提交后释放内存的问题,实际上是在数据写入函数返回之前vb是无法释放内存的(楼主定义的是变长byte类型数组,并没有这类释放机制,除非是new的对象),即使使用了线程共享某一存储空间,也不能够轻易被释放,系统会检测所有线程不再用这个空间才彻底释放。


我的VB6程式是实验性质代码,真实的情况,VB6也可以Call DLL后就跑,不等回传值,
然后马上做ReDim或 Erase,如果这样C还能保有原本VB6给的内存空间吗?

不要投我
2020-05-05 17:13



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-501329-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.111912 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved